Преглед изворни кода

* xmlread.pp: move all entity recursion checks into one place (in ContextPush).

git-svn-id: trunk@14290 -
sergei пре 15 година
родитељ
комит
e45469b377
1 измењених фајлова са 30 додато и 34 уклоњено
  1. 30 34
      packages/fcl-xml/src/xmlread.pp

+ 30 - 34
packages/fcl-xml/src/xmlread.pp

@@ -170,6 +170,7 @@ type
     FResolved: Boolean;
     FOnStack: Boolean;
     FBetweenDecls: Boolean;
+    FIsPE: Boolean;
     FReplacementText: DOMString;
     FURI: DOMString;
     FStartLocation: TLocation;
@@ -419,7 +420,6 @@ type
     function  EntityCheck(NoExternals: Boolean = False): TDOMEntityEx;
     procedure AppendReference(AEntity: TDOMEntityEx);
     procedure PrefetchEntity(AEntity: TDOMEntityEx);    
-    procedure StartGE(AEntity: TDOMEntityEx);
     procedure StartPE;
     function  ParseRef(var ToFill: TWideCharBuf): Boolean;              // [67]
     function  ParseExternalID(out SysID, PubID: WideString;             // [75]
@@ -1735,7 +1735,7 @@ begin
         AppendReference(ent);
       end
       else
-        StartGE(ent);
+        ContextPush(ent);
     end
     else if wc <> #0 then
     begin
@@ -1754,10 +1754,16 @@ begin
   FValue.Length := 0;
 end;
 
+const
+  PrefixChar: array[Boolean] of string = ('', '%');
+
 function TXMLReader.ContextPush(AEntity: TDOMEntityEx): Boolean;
 var
   Src: TXMLCharSource;
 begin
+  if AEntity.FOnStack then
+    FatalError('Entity ''%s%s'' recursively references itself', [PrefixChar[AEntity.FIsPE], AEntity.FName]);
+
   if (AEntity.SystemID <> '') and not AEntity.FPrefetched then
   begin
     Result := ResolveEntity(AEntity.SystemID, AEntity.PublicID, AEntity.FURI, Src);
@@ -1845,9 +1851,6 @@ begin
 
   if not Result.FResolved then
   begin
-    if Result.FOnStack then
-      FatalError('Entity ''%s'' recursively references itself', [RefName]);
-
     // To build children of the entity itself, we must parse it "out of context"
     SaveCursor := FCursor;
     SaveElDef := FValidator[FNesting].FElementDef;
@@ -1881,13 +1884,6 @@ begin
   CheckMaxChars;
 end;
 
-procedure TXMLReader.StartGE(AEntity: TDOMEntityEx);
-begin
-  if AEntity.FOnStack then
-    FatalError('Entity ''%s'' recursively references itself', [AEntity.FName]);
-  ContextPush(AEntity);
-end;
-
 procedure TXMLReader.StartPE;
 var
   PEName: WideString;
@@ -1903,9 +1899,6 @@ begin
     Exit;
   end;
 
-  if PEnt.FOnStack then
-    FatalError('Entity ''%%%s'' recursively references itself', [PEnt.FName]);
-
   { cache an external PE so it's only fetched once }
   if (PEnt.SystemID <> '') and not PEnt.FPrefetched then
     PrefetchEntity(PEnt);
@@ -2023,7 +2016,7 @@ begin
         ent := EntityCheck(True);
         if ent = nil then
           Continue;
-        StartGE(ent);
+        ContextPush(ent);
       end;
     end
     else if wc = '<' then
@@ -2643,18 +2636,18 @@ end;
 
 procedure TXMLReader.ParseEntityDecl;        // [70]
 var
-  NDataAllowed: Boolean;
+  IsPE: Boolean;
   Entity: TDOMEntityEx;
   Map: TDOMNamedNodeMap;
 begin
   if not SkipWhitespace(True) then
     FatalError('Expected whitespace');
-  NDataAllowed := True;
+  IsPE := False;
   Map := FDocType.Entities;
   if CheckForChar('%') then                  // [72]
   begin
     ExpectWhitespace;
-    NDataAllowed := False;
+    IsPE := True;
     if FPEMap = nil then
       FPEMap := TDOMNamedNodeMap.Create(FDocType, ENTITY_NODE);
     Map := FPEMap;
@@ -2664,6 +2657,7 @@ begin
   Entity.SetReadOnly(True);
   try
     Entity.FExternallyDeclared := FSource.DTDSubsetType <> dsInternal;
+    Entity.FIsPE := IsPE;
     Entity.FName := ExpectName;
     CheckNCName;
     ExpectWhitespace;
@@ -2679,22 +2673,24 @@ begin
       SetString(Entity.FReplacementText, FEntityValue.Buffer, FEntityValue.Length);
       Entity.FCharCount := FEntityValue.Length;
       Entity.FStartLocation := FTokenStart;
-      NDataAllowed := False;
     end
-    else if not ParseExternalID(Entity.FSystemID, Entity.FPublicID, False) then
-      FatalError('Expected entity value or external ID');
-
-    if NDataAllowed then                // [76]
+    else
     begin
-      if FSource.FBuf^ <> '>' then
-        ExpectWhitespace;
-      if FSource.Matches('NDATA') then
+      if not ParseExternalID(Entity.FSystemID, Entity.FPublicID, False) then
+        FatalError('Expected entity value or external ID');
+
+      if not IsPE then                // [76]
       begin
-        ExpectWhitespace;
-        StoreLocation(FTokenStart);
-        Entity.FNotationName := ExpectName;
-        AddForwardRef(FNotationRefs, FName.Buffer, FName.Length);
-        // SAX: DTDHandler.UnparsedEntityDecl(...);
+        if FSource.FBuf^ <> '>' then
+          ExpectWhitespace;
+        if FSource.Matches('NDATA') then
+        begin
+          ExpectWhitespace;
+          StoreLocation(FTokenStart);
+          Entity.FNotationName := ExpectName;
+          AddForwardRef(FNotationRefs, FName.Buffer, FName.Length);
+          // SAX: DTDHandler.UnparsedEntityDecl(...);
+        end;
       end;
     end;
   except
@@ -2703,7 +2699,7 @@ begin
   end;
 
   // Repeated declarations of same entity are legal but must be ignored
-  if Map.GetNamedItem(Entity.NodeName) = nil then
+  if Map.GetNamedItem(Entity.FName) = nil then
     Map.SetNamedItem(Entity)
   else
     Entity.Free;
@@ -3011,7 +3007,7 @@ begin
         end
         else
         begin
-          StartGE(ent);
+          ContextPush(ent);
           Continue;
         end;
       end;