@@ -18,6 +18,7 @@ interface
1818
1919uses
2020 // VCL
21+ XMLIntf,
2122 Generics.Collections,
2223 // Project
2324 SWAG.UCommon,
@@ -47,8 +48,8 @@ TSWAGXMLProcessor = class(TObject)
4748 cCategoryNode = ' category' ;
4849 cCategoryIDAttr = ' id' ;
4950 cCategoryTitleNode = ' title' ;
50- cPacketsNode = ' snippets ' ;
51- cPacketNode = ' snippet ' ;
51+ cPacketsNode = ' packets ' ;
52+ cPacketNode = ' packet ' ;
5253 cPacketIDAttr = ' id' ;
5354 cPacketCatIdNode = ' category-id' ;
5455 cPacketFileNameNode = ' file-name' ;
@@ -91,6 +92,18 @@ TSWAGXMLProcessor = class(TObject)
9192 // / <exception>ESWAGXMLProcessor raised if packet source code can't be
9293 // / loaded.</exception>
9394 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;
94107 public
95108 // / <summary>Constructor that sets up object ready to to process XML.
96109 // / </summary>
@@ -110,13 +123,13 @@ TSWAGXMLProcessor = class(TObject)
110123 procedure GetCategories (CatList: TList<TSWAGCategory>);
111124 // / <summary>Gets partial information about all packets belonging to a
112125 // / 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
114127 // / required.</param>
115128 // / <param name="PacketList">TList<TSWAGPacket> [in] Receives list
116129 // / of packets read.</param>
117130 // / <exception>ESWAGXMLProcessor raised if partial packets can't be read
118131 // / or are invalid.</exception>
119- procedure GetPartialPackets (const CatID: string ;
132+ procedure GetPartialPackets (const CatID: Cardinal ;
120133 PacketList: TList<TSWAGPacket>);
121134 // / <summary>Gets a single packet from the SWAG XML file.</summary>
122135 // / <param name="PacketID">Cardinal [in] Unique ID of the required packet.
@@ -142,7 +155,6 @@ implementation
142155 Classes,
143156 IOUtils,
144157 ActiveX,
145- XMLIntf,
146158 Math,
147159 DateUtils,
148160 // Project
@@ -179,6 +191,7 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
179191 sMissingNode = ' Invalid SWAG XML file: no categories information found' ;
180192 sMissingID = ' Invalid SWAG XML file: missing category ID' ;
181193 sMissingTitle = ' Invalid SWAG XML file: missing title for category "%s"' ;
194+ sBadSourceID = ' Invalid SWAG XML file: invalid or missing category ID' ;
182195begin
183196 CategoriesNode := fXMLDoc.FindNode(
184197 NodePath([cSWAGRootNode, cCategoriesNode])
@@ -188,9 +201,9 @@ procedure TSWAGXMLProcessor.GetCategories(CatList: TList<TSWAGCategory>);
188201 CategoryNodes := fXMLDoc.FindChildNodes(CategoriesNode, cCategoryNode);
189202 for CategoryNode in CategoryNodes do
190203 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+ );
194207 Category.Title := TXMLDocHelper.GetSubTagText(
195208 fXMLDoc, CategoryNode, cCategoryTitleNode
196209 );
@@ -205,9 +218,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
205218 AllPacketsNode: IXMLNode;
206219 PacketNode: IXMLNode;
207220 DateStr: string;
221+ PacketCatID: Cardinal;
208222resourcestring
209223 sPacketsNodeMissing = ' Invalid SWAG XML file: no packet information found' ;
210224 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' ;
211227begin
212228 // Find required Packet node
213229 AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
@@ -220,9 +236,12 @@ function TSWAGXMLProcessor.GetPacket(const PacketID: Cardinal): TSWAGPacket;
220236 raise ESWAGXMLProcessor.CreateFmt(sPacketNotFound, [PacketID]);
221237 // Get Packet info from Packet node
222238 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;
226245 Result.FileName := TXMLDocHelper.GetSubTagText(
227246 fXMLDoc, PacketNode, cPacketFileNameNode
228247 );
@@ -255,12 +274,10 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
255274begin
256275 Assert(Packet.ID > 0 , ClassName + ' .GetPacketSourceCode: '
257276 + ' Packet.ID not set' );
258- Assert(not StrIsEmpty(Packet.Category),
259- ClassName + ' .GetPacketSourceCode: Packet.Category not set' );
260277 Assert(not StrIsEmpty(Packet.FileName),
261278 ClassName + ' .GetPacketSourceCode: Packet.FileName not set' );
262279 FilePath := StrJoin(
263- [fSWAGRootDir, Packet.Category, Packet. FileName], PathDelim
280+ [fSWAGRootDir, Packet.FileName], PathDelim
264281 );
265282 if not TFile.Exists(FilePath, False) then
266283 raise ESWAGXMLProcessor.CreateFmt(sSourceCodeNotFound, [Packet.ID]);
@@ -271,17 +288,17 @@ procedure TSWAGXMLProcessor.GetPacketSourceCode(var Packet: TSWAGPacket);
271288 Packet.SourceCode := Code;
272289end ;
273290
274- procedure TSWAGXMLProcessor.GetPartialPackets (const CatID: string ;
291+ procedure TSWAGXMLProcessor.GetPartialPackets (const CatID: Cardinal ;
275292 PacketList: TList<TSWAGPacket>);
276293var
277294 AllPacketsNode: IXMLNode;
278295 PacketNodes: IXMLSimpleNodeList;
279296 PacketNode: IXMLNode;
280297 Packet: TSWAGPacket;
281- PacketID: Integer ;
298+ CatIDFromNode: Cardinal ;
282299resourcestring
283300 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' ;
285302begin
286303 AllPacketsNode := fXMLDoc.FindNode(NodePath([cSWAGRootNode, cPacketsNode]));
287304 if not Assigned(AllPacketsNode) then
@@ -291,14 +308,14 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
291308 Exit;
292309 for PacketNode in PacketNodes do
293310 begin
294- if StrSameText (
311+ if TryStrToCardinal (
295312 TXMLDocHelper.GetSubTagText(fXMLDoc, PacketNode, cPacketCatIdNode),
296- CatID
297- ) then
313+ CatIDFromNode
314+ ) and (CatIDFromNode > 0 ) and (CatIDFromNode = CatID) then
298315 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+ ) ;
302319 Packet.Title := TXMLDocHelper.GetSubTagText(
303320 fXMLDoc, PacketNode, cPacketTitleNode
304321 );
@@ -308,6 +325,13 @@ procedure TSWAGXMLProcessor.GetPartialPackets(const CatID: string;
308325 end ;
309326end ;
310327
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+
311335procedure TSWAGXMLProcessor.Initialise (const SWAGDirName: string);
312336resourcestring
313337 sFileReadError = ' Can'' t read SWAG database file "%0:s"' + EOL2
@@ -352,14 +376,14 @@ class function TSWAGXMLProcessor.NodePath(const Tags: array of string): string;
352376
353377procedure TSWAGXMLProcessor.ValidatePacket (const Packet: TSWAGPacket);
354378resourcestring
355- sBadCatID = ' Invalid SWAG XML file: packet %d has no category' ;
379+ sBadCatID = ' Invalid SWAG XML file: packet %d has invalid category' ;
356380 sBadFileName = ' Invalid SWAG XML file: packet %d has no file name' ;
357381 sBadDateStamp = ' Invalid SWAG XML file: packet %d has no date stamp' ;
358382 sBadAuthor = ' Invalid SWAG XML file: packet %d has no author' ;
359383 sBadSourceCode = ' Invalid SWAG XML file: packet %d has no source code' ;
360384begin
361385 ValidatePartialPacket(Packet);
362- if StrIsEmpty( Packet.Category, True) then
386+ if Packet.Category = 0 then
363387 raise ESWAGXMLProcessor.CreateFmt(sBadCatID, [Packet.ID]);
364388 if StrIsEmpty(Packet.FileName, True) then
365389 raise ESWAGXMLProcessor.CreateFmt(sBadFileName, [Packet.ID]);
0 commit comments