@@ -18,6 +18,7 @@ interface
18
18
19
19
uses
20
20
// VCL
21
+ XMLIntf,
21
22
Generics.Collections,
22
23
// Project
23
24
SWAG.UCommon,
@@ -47,8 +48,8 @@ TSWAGXMLProcessor = class(TObject)
47
48
cCategoryNode = ' category' ;
48
49
cCategoryIDAttr = ' id' ;
49
50
cCategoryTitleNode = ' title' ;
50
- cPacketsNode = ' snippets ' ;
51
- cPacketNode = ' snippet ' ;
51
+ cPacketsNode = ' packets ' ;
52
+ cPacketNode = ' packet ' ;
52
53
cPacketIDAttr = ' id' ;
53
54
cPacketCatIdNode = ' category-id' ;
54
55
cPacketFileNameNode = ' file-name' ;
@@ -91,6 +92,18 @@ TSWAGXMLProcessor = class(TObject)
91
92
// / <exception>ESWAGXMLProcessor raised if packet source code can't be
92
93
// / loaded.</exception>
93
94
procedure GetPacketSourceCode (var Packet: TSWAGPacket);
95
+ // / <summary>Read and validate a positive integer value from a node
96
+ // / attribute</summary>
97
+ // / <param name="Node">IXMLNode [in] Node whose attribute is to be read.
98
+ // / </param>
99
+ // / <param name="Attr">string [in] Name of attribute.</param>
100
+ // / <param name="ErrMsg">string [in] Exception error messsage to be used on
101
+ // / error.</param>
102
+ // / <returns>Required postive integer value.</returns>
103
+ // / <exception>ESWAGXMLProcessor raised if attribute value is missing or
104
+ // / is not a positive integer.</exception>
105
+ function GetPositiveIntAttribute (Node: IXMLNode; const Attr: string;
106
+ const ErrMsg: string): Cardinal;
94
107
public
95
108
// / <summary>Constructor that sets up object ready to to process XML.
96
109
// / </summary>
@@ -110,13 +123,13 @@ TSWAGXMLProcessor = class(TObject)
110
123
procedure GetCategories (CatList: TList<TSWAGCategory>);
111
124
// / <summary>Gets partial information about all packets belonging to a
112
125
// / category from the SWAG XML file.</summary>
113
- // / <param name="CatID">string [in] ID of category for which packets are
126
+ // / <param name="CatID">Cardinal [in] ID of category for which packets are
114
127
// / required.</param>
115
128
// / <param name="PacketList">TList<TSWAGPacket> [in] Receives list
116
129
// / of packets read.</param>
117
130
// / <exception>ESWAGXMLProcessor raised if partial packets can't be read
118
131
// / or are invalid.</exception>
119
- procedure GetPartialPackets (const CatID: string ;
132
+ procedure GetPartialPackets (const CatID: Cardinal ;
120
133
PacketList: TList<TSWAGPacket>);
121
134
// / <summary>Gets a single packet from the SWAG XML file.</summary>
122
135
// / <param name="PacketID">Cardinal [in] Unique ID of the required packet.
@@ -142,7 +155,6 @@ implementation
142
155
Classes,
143
156
IOUtils,
144
157
ActiveX,
145
- XMLIntf,
146
158
Math,
147
159
DateUtils,
148
160
// Project
@@ -179,6 +191,7 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
179
191
sMissingNode = ' Invalid SWAG XML file: no categories information found' ;
180
192
sMissingID = ' Invalid SWAG XML file: missing category ID' ;
181
193
sMissingTitle = ' Invalid SWAG XML file: missing title for category "%s"' ;
194
+ sBadSourceID = ' Invalid SWAG XML file: invalid or missing category ID' ;
182
195
begin
183
196
CategoriesNode := fXMLDoc.FindNode(
184
197
NodePath([cSWAGRootNode, cCategoriesNode])
@@ -188,9 +201,9 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
188
201
CategoryNodes := fXMLDoc.FindChildNodes(CategoriesNode, cCategoryNode);
189
202
for CategoryNode in CategoryNodes do
190
203
begin
191
- Category.ID := CategoryNode.Attributes[cCategoryIDAttr];
192
- if StrIsEmpty(Category.ID, True) then
193
- raise ESWAGXMLProcessor.Create(sMissingID );
204
+ Category.ID := GetPositiveIntAttribute(
205
+ CategoryNode, cCategoryIDAttr, sBadSourceID
206
+ );
194
207
Category.Title := TXMLDocHelper.GetSubTagText(
195
208
fXMLDoc, CategoryNode, cCategoryTitleNode
196
209
);
@@ -205,9 +218,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
205
218
AllPacketsNode: IXMLNode;
206
219
PacketNode: IXMLNode;
207
220
DateStr: string;
221
+ PacketCatID: Cardinal;
208
222
resourcestring
209
223
sPacketsNodeMissing = ' Invalid SWAG XML file: no packet information found' ;
210
224
sPacketNotFound = ' Invalid SWAG XML file: packet with ID %d not found' ;
225
+ sBadPacketCategory = ' Invalid SWAG XML file: packet has invalid or missing '
226
+ + ' category ID' ;
211
227
begin
212
228
// Find required Packet node
213
229
AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
@@ -220,9 +236,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
220
236
raise ESWAGXMLProcessor.CreateFmt(sPacketNotFound, [PacketID]);
221
237
// Get Packet info from Packet node
222
238
Result.ID := PacketID;
223
- Result.Category := TXMLDocHelper.GetSubTagText(
224
- fXMLDoc, PacketNode, cPacketCatIdNode
225
- );
239
+ if not TryStrToCardinal(
240
+ TXMLDocHelper.GetSubTagText(fXMLDoc, PacketNode, cPacketCatIdNode),
241
+ PacketCatID
242
+ ) then
243
+ raise ESWAGXMLProcessor.Create(sBadPacketCategory);
244
+ Result.Category := PacketCatID;
226
245
Result.FileName := TXMLDocHelper.GetSubTagText(
227
246
fXMLDoc, PacketNode, cPacketFileNameNode
228
247
);
@@ -255,12 +274,10 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
255
274
begin
256
275
Assert(Packet.ID > 0 , ClassName + ' .GetPacketSourceCode: '
257
276
+ ' Packet.ID not set' );
258
- Assert(not StrIsEmpty(Packet.Category),
259
- ClassName + ' .GetPacketSourceCode: Packet.Category not set' );
260
277
Assert(not StrIsEmpty(Packet.FileName),
261
278
ClassName + ' .GetPacketSourceCode: Packet.FileName not set' );
262
279
FilePath := StrJoin(
263
- [fSWAGRootDir, Packet.Category, Packet. FileName], PathDelim
280
+ [fSWAGRootDir, Packet.FileName], PathDelim
264
281
);
265
282
if not TFile.Exists(FilePath, False) then
266
283
raise ESWAGXMLProcessor.CreateFmt(sSourceCodeNotFound, [Packet.ID]);
@@ -271,17 +288,17 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
271
288
Packet.SourceCode := Code;
272
289
end ;
273
290
274
- procedure TSWAGXMLProcessor.GetPartialPackets (const CatID: string ;
291
+ procedure TSWAGXMLProcessor.GetPartialPackets (const CatID: Cardinal ;
275
292
PacketList: TList<TSWAGPacket>);
276
293
var
277
294
AllPacketsNode: IXMLNode;
278
295
PacketNodes: IXMLSimpleNodeList;
279
296
PacketNode: IXMLNode;
280
297
Packet: TSWAGPacket;
281
- PacketID: Integer ;
298
+ CatIDFromNode: Cardinal ;
282
299
resourcestring
283
300
sPacketsNodeMissing = ' Invalid SWAG XML file: no packet information found' ;
284
- sBadSourceID = ' Invalid SWAG XML file: invalid packet ID encountered ' ;
301
+ sBadSourceID = ' Invalid SWAG XML file: missing or invalid packet ID' ;
285
302
begin
286
303
AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
287
304
if not Assigned(AllPacketsNode) then
@@ -291,14 +308,14 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
291
308
Exit;
292
309
for PacketNode in PacketNodes do
293
310
begin
294
- if StrSameText (
311
+ if TryStrToCardinal (
295
312
TXMLDocHelper.GetSubTagText(fXMLDoc, PacketNode, cPacketCatIdNode),
296
- CatID
297
- ) then
313
+ CatIDFromNode
314
+ ) and (CatIDFromNode > 0 ) and (CatIDFromNode = CatID) then
298
315
begin
299
- if not TryStrToInt(PacketNode.Attributes[cPacketIDAttr], PacketID) then
300
- raise ESWAGXMLProcessor.Create( sBadSourceID);
301
- Packet.ID := PacketID ;
316
+ Packet.ID := GetPositiveIntAttribute(
317
+ PacketNode, cPacketIDAttr, sBadSourceID
318
+ ) ;
302
319
Packet.Title := TXMLDocHelper.GetSubTagText(
303
320
fXMLDoc, PacketNode, cPacketTitleNode
304
321
);
@@ -308,6 +325,13 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
308
325
end ;
309
326
end ;
310
327
328
+ function TSWAGXMLProcessor.GetPositiveIntAttribute (Node: IXMLNode; const Attr,
329
+ ErrMsg: string): Cardinal;
330
+ begin
331
+ if not TryStrToCardinal(Node.Attributes[Attr], Result) or (Result = 0 ) then
332
+ raise ESWAGXMLProcessor.Create(ErrMsg);
333
+ end ;
334
+
311
335
procedure TSWAGXMLProcessor.Initialise (const SWAGDirName: string);
312
336
resourcestring
313
337
sFileReadError = ' Can'' t read SWAG database file "%0:s"' + EOL2
@@ -352,14 +376,14 @@ class function TSWAGXMLProcessor.NodePath(const Tags: array of string): string;
352
376
353
377
procedure TSWAGXMLProcessor.ValidatePacket (const Packet: TSWAGPacket);
354
378
resourcestring
355
- sBadCatID = ' Invalid SWAG XML file: packet %d has no category' ;
379
+ sBadCatID = ' Invalid SWAG XML file: packet %d has invalid category' ;
356
380
sBadFileName = ' Invalid SWAG XML file: packet %d has no file name' ;
357
381
sBadDateStamp = ' Invalid SWAG XML file: packet %d has no date stamp' ;
358
382
sBadAuthor = ' Invalid SWAG XML file: packet %d has no author' ;
359
383
sBadSourceCode = ' Invalid SWAG XML file: packet %d has no source code' ;
360
384
begin
361
385
ValidatePartialPacket(Packet);
362
- if StrIsEmpty( Packet.Category, True) then
386
+ if Packet.Category = 0 then
363
387
raise ESWAGXMLProcessor.CreateFmt(sBadCatID, [Packet.ID]);
364
388
if StrIsEmpty(Packet.FileName, True) then
365
389
raise ESWAGXMLProcessor.CreateFmt(sBadFileName, [Packet.ID]);
0 commit comments