LCOV - app.info - parser/htmlparser/src/nsExpatDriver.cpp

LCOV - code coverage report
| Current view: | directory - parser/htmlparser/src - nsExpatDriver.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 577 | 456 | 79.0 %
| Date: | 2012-06-02 | Functions: | 73 | 54 | 74.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Henri Sivonen <hsivonen@iki.fi>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "nsExpatDriver.h"
          40                 : #include "nsCOMPtr.h"
          41                 : #include "nsParserCIID.h"
          42                 : #include "CParserContext.h"
          43                 : #include "nsIExpatSink.h"
          44                 : #include "nsIExtendedExpatSink.h"
          45                 : #include "nsIContentSink.h"
          46                 : #include "nsParserMsgUtils.h"
          47                 : #include "nsIURL.h"
          48                 : #include "nsIUnicharInputStream.h"
          49                 : #include "nsISimpleUnicharStreamFactory.h"
          50                 : #include "nsNetUtil.h"
          51                 : #include "prprf.h"
          52                 : #include "prmem.h"
          53                 : #include "nsTextFormatter.h"
          54                 : #include "nsDirectoryServiceDefs.h"
          55                 : #include "nsCRT.h"
          56                 : #include "nsIConsoleService.h"
          57                 : #include "nsIScriptError.h"
          58                 : #include "nsIContentPolicy.h"
          59                 : #include "nsContentPolicyUtils.h"
          60                 : #include "nsContentErrors.h"
          61                 : #include "nsXPCOMCIDInternal.h"
          62                 : #include "nsUnicharInputStream.h"
          63                 :
          64                 : #define kExpatSeparatorChar 0xFFFF
          65                 :
          66                 : static const PRUnichar kUTF16[] = { 'U', 'T', 'F', '-', '1', '6', '\0' };
          67                 :
          68                 : #ifdef PR_LOGGING
          69            1464 : static PRLogModuleInfo *gExpatDriverLog = PR_NewLogModule("expatdriver");
          70                 : #endif
          71                 :
          72                 : /***************************** EXPAT CALL BACKS ******************************/
          73                 : // The callback handlers that get called from the expat parser.
          74                 :
          75                 : static void
          76            3095 : Driver_HandleXMLDeclaration(void *aUserData,
          77                 :                             const XML_Char *aVersion,
          78                 :                             const XML_Char *aEncoding,
          79                 :                             int aStandalone)
          80                 : {
          81            3095 :   NS_ASSERTION(aUserData, "expat driver should exist");
          82            3095 :   if (aUserData) {
          83            3095 :     nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
          84            3095 :     driver->HandleXMLDeclaration(aVersion, aEncoding, aStandalone);
          85                 :   }
          86            3095 : }
          87                 :
          88                 : static void
          89           82980 : Driver_HandleStartElement(void *aUserData,
          90                 :                           const XML_Char *aName,
          91                 :                           const XML_Char **aAtts)
          92                 : {
          93           82980 :   NS_ASSERTION(aUserData, "expat driver should exist");
          94           82980 :   if (aUserData) {
          95                 :     static_cast<nsExpatDriver*>(aUserData)->HandleStartElement(aName,
          96           82980 :                                                                   aAtts);
          97                 :   }
          98           82980 : }
          99                 :
         100                 : static void
         101           82966 : Driver_HandleEndElement(void *aUserData,
         102                 :                         const XML_Char *aName)
         103                 : {
         104           82966 :   NS_ASSERTION(aUserData, "expat driver should exist");
         105           82966 :   if (aUserData) {
         106           82966 :     static_cast<nsExpatDriver*>(aUserData)->HandleEndElement(aName);
         107                 :   }
         108           82966 : }
         109                 :
         110                 : static void
         111          282071 : Driver_HandleCharacterData(void *aUserData,
         112                 :                            const XML_Char *aData,
         113                 :                            int aLength)
         114                 : {
         115          282071 :   NS_ASSERTION(aUserData, "expat driver should exist");
         116          282071 :   if (aUserData) {
         117          282071 :     nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
         118          282071 :     driver->HandleCharacterData(aData, PRUint32(aLength));
         119                 :   }
         120          282071 : }
         121                 :
         122                 : static void
         123            3875 : Driver_HandleComment(void *aUserData,
         124                 :                      const XML_Char *aName)
         125                 : {
         126            3875 :   NS_ASSERTION(aUserData, "expat driver should exist");
         127            3875 :   if(aUserData) {
         128            3875 :     static_cast<nsExpatDriver*>(aUserData)->HandleComment(aName);
         129                 :   }
         130            3875 : }
         131                 :
         132                 : static void
         133              53 : Driver_HandleProcessingInstruction(void *aUserData,
         134                 :                                    const XML_Char *aTarget,
         135                 :                                    const XML_Char *aData)
         136                 : {
         137              53 :   NS_ASSERTION(aUserData, "expat driver should exist");
         138              53 :   if (aUserData) {
         139              53 :     nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
         140              53 :     driver->HandleProcessingInstruction(aTarget, aData);
         141                 :   }
         142              53 : }
         143                 :
         144                 : static void
         145            8117 : Driver_HandleDefault(void *aUserData,
         146                 :                      const XML_Char *aData,
         147                 :                      int aLength)
         148                 : {
         149            8117 :   NS_ASSERTION(aUserData, "expat driver should exist");
         150            8117 :   if (aUserData) {
         151            8117 :     nsExpatDriver* driver = static_cast<nsExpatDriver*>(aUserData);
         152            8117 :     driver->HandleDefault(aData, PRUint32(aLength));
         153                 :   }
         154            8117 : }
         155                 :
         156                 : static void
         157              68 : Driver_HandleStartCdataSection(void *aUserData)
         158                 : {
         159              68 :   NS_ASSERTION(aUserData, "expat driver should exist");
         160              68 :   if (aUserData) {
         161              68 :     static_cast<nsExpatDriver*>(aUserData)->HandleStartCdataSection();
         162                 :   }
         163              68 : }
         164                 :
         165                 : static void
         166              67 : Driver_HandleEndCdataSection(void *aUserData)
         167                 : {
         168              67 :   NS_ASSERTION(aUserData, "expat driver should exist");
         169              67 :   if (aUserData) {
         170              67 :     static_cast<nsExpatDriver*>(aUserData)->HandleEndCdataSection();
         171                 :   }
         172              67 : }
         173                 :
         174                 : static void
         175              49 : Driver_HandleStartDoctypeDecl(void *aUserData,
         176                 :                               const XML_Char *aDoctypeName,
         177                 :                               const XML_Char *aSysid,
         178                 :                               const XML_Char *aPubid,
         179                 :                               int aHasInternalSubset)
         180                 : {
         181              49 :   NS_ASSERTION(aUserData, "expat driver should exist");
         182              49 :   if (aUserData) {
         183                 :     static_cast<nsExpatDriver*>(aUserData)->
         184              49 :       HandleStartDoctypeDecl(aDoctypeName, aSysid, aPubid, !!aHasInternalSubset);
         185                 :   }
         186              49 : }
         187                 :
         188                 : static void
         189              49 : Driver_HandleEndDoctypeDecl(void *aUserData)
         190                 : {
         191              49 :   NS_ASSERTION(aUserData, "expat driver should exist");
         192              49 :   if (aUserData) {
         193              49 :     static_cast<nsExpatDriver*>(aUserData)->HandleEndDoctypeDecl();
         194                 :   }
         195              49 : }
         196                 :
         197                 : static int
         198              10 : Driver_HandleExternalEntityRef(void *aExternalEntityRefHandler,
         199                 :                                const XML_Char *aOpenEntityNames,
         200                 :                                const XML_Char *aBase,
         201                 :                                const XML_Char *aSystemId,
         202                 :                                const XML_Char *aPublicId)
         203                 : {
         204              10 :   NS_ASSERTION(aExternalEntityRefHandler, "expat driver should exist");
         205              10 :   if (!aExternalEntityRefHandler) {
         206               0 :     return 1;
         207                 :   }
         208                 :
         209                 :   nsExpatDriver* driver = static_cast<nsExpatDriver*>
         210              10 :                                      (aExternalEntityRefHandler);
         211                 :
         212                 :   return driver->HandleExternalEntityRef(aOpenEntityNames, aBase, aSystemId,
         213              10 :                                          aPublicId);
         214                 : }
         215                 :
         216                 : static void
         217             320 : Driver_HandleStartNamespaceDecl(void *aUserData,
         218                 :                                 const XML_Char *aPrefix,
         219                 :                                 const XML_Char *aUri)
         220                 : {
         221             320 :   NS_ASSERTION(aUserData, "expat driver should exist");
         222             320 :   if (aUserData) {
         223                 :     static_cast<nsExpatDriver*>(aUserData)->
         224             320 :       HandleStartNamespaceDecl(aPrefix, aUri);
         225                 :   }
         226             320 : }
         227                 :
         228                 : static void
         229             314 : Driver_HandleEndNamespaceDecl(void *aUserData,
         230                 :                               const XML_Char *aPrefix)
         231                 : {
         232             314 :   NS_ASSERTION(aUserData, "expat driver should exist");
         233             314 :   if (aUserData) {
         234                 :     static_cast<nsExpatDriver*>(aUserData)->
         235             314 :       HandleEndNamespaceDecl(aPrefix);
         236                 :   }
         237             314 : }
         238                 :
         239                 : static void
         240               0 : Driver_HandleNotationDecl(void *aUserData,
         241                 :                           const XML_Char *aNotationName,
         242                 :                           const XML_Char *aBase,
         243                 :                           const XML_Char *aSysid,
         244                 :                           const XML_Char *aPubid)
         245                 : {
         246               0 :   NS_ASSERTION(aUserData, "expat driver should exist");
         247               0 :   if (aUserData) {
         248                 :     static_cast<nsExpatDriver*>(aUserData)->
         249               0 :       HandleNotationDecl(aNotationName, aBase, aSysid, aPubid);
         250                 :   }
         251               0 : }
         252                 :
         253                 : static void
         254               0 : Driver_HandleUnparsedEntityDecl(void *aUserData,
         255                 :                                 const XML_Char *aEntityName,
         256                 :                                 const XML_Char *aBase,
         257                 :                                 const XML_Char *aSysid,
         258                 :                                 const XML_Char *aPubid,
         259                 :                                 const XML_Char *aNotationName)
         260                 : {
         261               0 :   NS_ASSERTION(aUserData, "expat driver should exist");
         262               0 :   if (aUserData) {
         263                 :     static_cast<nsExpatDriver*>(aUserData)->
         264                 :       HandleUnparsedEntityDecl(aEntityName, aBase, aSysid, aPubid,
         265               0 :                                aNotationName);
         266                 :   }
         267               0 : }
         268                 :
         269                 :
         270                 : /***************************** END CALL BACKS ********************************/
         271                 :
         272                 : /***************************** CATALOG UTILS *********************************/
         273                 :
         274                 : // Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus
         275                 : // MathML 2.0" DTD to the the lightweight customized version that Mozilla uses.
         276                 : // Since Mozilla is not validating, no need to fetch a *huge* file at each
         277                 : // click.
         278                 : // XXX The cleanest solution here would be to fix Bug 98413: Implement XML
         279                 : // Catalogs.
         280                 : struct nsCatalogData {
         281                 :   const char* mPublicID;
         282                 :   const char* mLocalDTD;
         283                 :   const char* mAgentSheet;
         284                 : };
         285                 :
         286                 : // The order of this table is guestimated to be in the optimum order
         287                 : static const nsCatalogData kCatalogTable[] = {
         288                 :   { "-//W3C//DTD XHTML 1.0 Transitional//EN",    "htmlmathml-f.ent", nsnull },
         289                 :   { "-//W3C//DTD XHTML 1.1//EN",                 "htmlmathml-f.ent", nsnull },
         290                 :   { "-//W3C//DTD XHTML 1.0 Strict//EN",          "htmlmathml-f.ent", nsnull },
         291                 :   { "-//W3C//DTD XHTML 1.0 Frameset//EN",        "htmlmathml-f.ent", nsnull },
         292                 :   { "-//W3C//DTD XHTML Basic 1.0//EN",           "htmlmathml-f.ent", nsnull },
         293                 :   { "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "htmlmathml-f.ent", "resource://gre-resources/mathml.css" },
         294                 :   { "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN", "htmlmathml-f.ent", "resource://gre-resources/mathml.css" },
         295                 :   { "-//W3C//DTD MathML 2.0//EN",                "htmlmathml-f.ent", "resource://gre-resources/mathml.css" },
         296                 :   { "-//WAPFORUM//DTD XHTML Mobile 1.0//EN",     "htmlmathml-f.ent", nsnull },
         297                 :   { nsnull, nsnull, nsnull }
         298                 : };
         299                 :
         300                 : static const nsCatalogData*
         301               8 : LookupCatalogData(const PRUnichar* aPublicID)
         302                 : {
         303              16 :   nsDependentString publicID(aPublicID);
         304                 :
         305                 :   // linear search for now since the number of entries is going to
         306                 :   // be negligible, and the fix for bug 98413 would get rid of this
         307                 :   // code anyway
         308               8 :   const nsCatalogData* data = kCatalogTable;
         309              88 :   while (data->mPublicID) {
         310              72 :     if (publicID.EqualsASCII(data->mPublicID)) {
         311               0 :       return data;
         312                 :     }
         313              72 :     ++data;
         314                 :   }
         315                 :
         316               8 :   return nsnull;
         317                 : }
         318                 :
         319                 : // This function provides a resource URI to a local DTD
         320                 : // in resource://gre/res/dtd/ which may or may not exist.
         321                 : // If aCatalogData is provided, it is used to remap the
         322                 : // DTD instead of taking the filename from the URI.
         323                 : static void
         324              10 : GetLocalDTDURI(const nsCatalogData* aCatalogData, nsIURI* aDTD,
         325                 :               nsIURI** aResult)
         326                 : {
         327              10 :   NS_ASSERTION(aDTD, "Null parameter.");
         328                 :
         329              20 :   nsCAutoString fileName;
         330              10 :   if (aCatalogData) {
         331                 :     // remap the DTD to a known local DTD
         332               0 :     fileName.Assign(aCatalogData->mLocalDTD);
         333                 :   }
         334                 :
         335              10 :   if (fileName.IsEmpty()) {
         336                 :     // Try to see if the user has installed the DTD file -- we extract the
         337                 :     // filename.ext of the DTD here. Hence, for any DTD for which we have
         338                 :     // no predefined mapping, users just have to copy the DTD file to our
         339                 :     // special DTD directory and it will be picked.
         340              20 :     nsCOMPtr<nsIURL> dtdURL = do_QueryInterface(aDTD);
         341              10 :     if (!dtdURL) {
         342                 :       return;
         343                 :     }
         344                 :
         345              10 :     dtdURL->GetFileName(fileName);
         346              10 :     if (fileName.IsEmpty()) {
         347                 :       return;
         348                 :     }
         349                 :   }
         350                 :
         351              20 :   nsCAutoString respath("resource://gre/res/dtd/");
         352              10 :   respath += fileName;
         353              10 :   NS_NewURI(aResult, respath);
         354                 : }
         355                 :
         356                 : /***************************** END CATALOG UTILS *****************************/
         357                 :
         358           13765 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsExpatDriver)
         359            6628 :   NS_INTERFACE_MAP_ENTRY(nsITokenizer)
         360            3314 :   NS_INTERFACE_MAP_ENTRY(nsIDTD)
         361               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDTD)
         362               0 : NS_INTERFACE_MAP_END
         363                 :
         364            9942 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsExpatDriver)
         365            9942 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsExpatDriver)
         366                 :
         367            1529 : NS_IMPL_CYCLE_COLLECTION_2(nsExpatDriver, mSink, mExtendedSink)
         368                 :
         369            3314 : nsExpatDriver::nsExpatDriver()
         370                 :   : mExpatParser(nsnull),
         371                 :     mInCData(false),
         372                 :     mInInternalSubset(false),
         373                 :     mInExternalDTD(false),
         374                 :     mMadeFinalCallToExpat(false),
         375                 :     mIsFinalChunk(false),
         376                 :     mInternalState(NS_OK),
         377                 :     mExpatBuffered(0),
         378                 :     mCatalogData(nsnull),
         379            3314 :     mInnerWindowID(0)
         380                 : {
         381            3314 : }
         382                 :
         383            9942 : nsExpatDriver::~nsExpatDriver()
         384                 : {
         385            3314 :   if (mExpatParser) {
         386            3314 :     XML_ParserFree(mExpatParser);
         387                 :   }
         388           13256 : }
         389                 :
         390                 : nsresult
         391           82980 : nsExpatDriver::HandleStartElement(const PRUnichar *aValue,
         392                 :                                   const PRUnichar **aAtts)
         393                 : {
         394           82980 :   NS_ASSERTION(mSink, "content sink not found!");
         395                 :
         396                 :   // Calculate the total number of elements in aAtts.
         397                 :   // XML_GetSpecifiedAttributeCount will only give us the number of specified
         398                 :   // attrs (twice that number, actually), so we have to check for default attrs
         399                 :   // ourselves.
         400                 :   PRUint32 attrArrayLength;
         401          165960 :   for (attrArrayLength = XML_GetSpecifiedAttributeCount(mExpatParser);
         402           82980 :        aAtts[attrArrayLength];
         403                 :        attrArrayLength += 2) {
         404                 :     // Just looping till we find out what the length is
         405                 :   }
         406                 :
         407           82980 :   if (mSink) {
         408           82980 :     nsresult rv = mSink->
         409                 :       HandleStartElement(aValue, aAtts, attrArrayLength,
         410                 :                          XML_GetIdAttributeIndex(mExpatParser),
         411           82980 :                          XML_GetCurrentLineNumber(mExpatParser));
         412           82980 :     MaybeStopParser(rv);
         413                 :   }
         414                 :
         415           82980 :   return NS_OK;
         416                 : }
         417                 :
         418                 : nsresult
         419           82966 : nsExpatDriver::HandleEndElement(const PRUnichar *aValue)
         420                 : {
         421           82966 :   NS_ASSERTION(mSink, "content sink not found!");
         422           82966 :   NS_ASSERTION(mInternalState != NS_ERROR_HTMLPARSER_BLOCK,
         423                 :                "Shouldn't block from HandleStartElement.");
         424                 :
         425           82966 :   if (mSink && mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
         426           82966 :     nsresult rv = mSink->HandleEndElement(aValue);
         427           82966 :     MaybeStopParser(rv);
         428                 :   }
         429                 :
         430           82966 :   return NS_OK;
         431                 : }
         432                 :
         433                 : nsresult
         434          282071 : nsExpatDriver::HandleCharacterData(const PRUnichar *aValue,
         435                 :                                    const PRUint32 aLength)
         436                 : {
         437          282071 :   NS_ASSERTION(mSink, "content sink not found!");
         438                 :
         439          282071 :   if (mInCData) {
         440             366 :     mCDataText.Append(aValue, aLength);
         441                 :   }
         442          281705 :   else if (mSink) {
         443          281705 :     nsresult rv = mSink->HandleCharacterData(aValue, aLength);
         444          281705 :     MaybeStopParser(rv);
         445                 :   }
         446                 :
         447          282071 :   return NS_OK;
         448                 : }
         449                 :
         450                 : nsresult
         451            3875 : nsExpatDriver::HandleComment(const PRUnichar *aValue)
         452                 : {
         453            3875 :   NS_ASSERTION(mSink, "content sink not found!");
         454                 :
         455            3875 :   if (mInExternalDTD) {
         456                 :     // Ignore comments from external DTDs
         457               0 :     return NS_OK;
         458                 :   }
         459                 :
         460            3875 :   if (mInInternalSubset) {
         461               0 :     mInternalSubset.AppendLiteral("<!--");
         462               0 :     mInternalSubset.Append(aValue);
         463               0 :     mInternalSubset.AppendLiteral("-->");
         464                 :   }
         465            3875 :   else if (mSink) {
         466            3875 :     nsresult rv = mSink->HandleComment(aValue);
         467            3875 :     MaybeStopParser(rv);
         468                 :   }
         469                 :
         470            3875 :   return NS_OK;
         471                 : }
         472                 :
         473                 : nsresult
         474              53 : nsExpatDriver::HandleProcessingInstruction(const PRUnichar *aTarget,
         475                 :                                            const PRUnichar *aData)
         476                 : {
         477              53 :   NS_ASSERTION(mSink, "content sink not found!");
         478                 :
         479              53 :   if (mInExternalDTD) {
         480                 :     // Ignore PIs in external DTDs for now.  Eventually we want to
         481                 :     // pass them to the sink in a way that doesn't put them in the DOM
         482               0 :     return NS_OK;
         483                 :   }
         484                 :
         485              53 :   if (mInInternalSubset) {
         486               0 :     mInternalSubset.AppendLiteral("<?");
         487               0 :     mInternalSubset.Append(aTarget);
         488               0 :     mInternalSubset.Append(' ');
         489               0 :     mInternalSubset.Append(aData);
         490               0 :     mInternalSubset.AppendLiteral("?>");
         491                 :   }
         492              53 :   else if (mSink) {
         493              53 :     nsresult rv = mSink->HandleProcessingInstruction(aTarget, aData);
         494              53 :     MaybeStopParser(rv);
         495                 :   }
         496                 :
         497              53 :   return NS_OK;
         498                 : }
         499                 :
         500                 : nsresult
         501            3095 : nsExpatDriver::HandleXMLDeclaration(const PRUnichar *aVersion,
         502                 :                                     const PRUnichar *aEncoding,
         503                 :                                     PRInt32 aStandalone)
         504                 : {
         505            3095 :   if (mSink) {
         506            3095 :     nsresult rv = mSink->HandleXMLDeclaration(aVersion, aEncoding, aStandalone);
         507            3095 :     MaybeStopParser(rv);
         508                 :   }
         509                 :
         510            3095 :   return NS_OK;
         511                 : }
         512                 :
         513                 : nsresult
         514            8117 : nsExpatDriver::HandleDefault(const PRUnichar *aValue,
         515                 :                              const PRUint32 aLength)
         516                 : {
         517            8117 :   NS_ASSERTION(mSink, "content sink not found!");
         518                 :
         519            8117 :   if (mInExternalDTD) {
         520                 :     // Ignore newlines in external DTDs
         521               0 :     return NS_OK;
         522                 :   }
         523                 :
         524            8117 :   if (mInInternalSubset) {
         525            1852 :     mInternalSubset.Append(aValue, aLength);
         526                 :   }
         527            6265 :   else if (mSink) {
         528                 :     PRUint32 i;
         529            6265 :     nsresult rv = mInternalState;
         530           14321 :     for (i = 0; i < aLength && NS_SUCCEEDED(rv); ++i) {
         531            8056 :       if (aValue[i] == '\n' || aValue[i] == '\r') {
         532            8051 :         rv = mSink->HandleCharacterData(&aValue[i], 1);
         533                 :       }
         534                 :     }
         535            6265 :     MaybeStopParser(rv);
         536                 :   }
         537                 :
         538            8117 :   return NS_OK;
         539                 : }
         540                 :
         541                 : nsresult
         542              68 : nsExpatDriver::HandleStartCdataSection()
         543                 : {
         544              68 :   mInCData = true;
         545                 :
         546              68 :   return NS_OK;
         547                 : }
         548                 :
         549                 : nsresult
         550              67 : nsExpatDriver::HandleEndCdataSection()
         551                 : {
         552              67 :   NS_ASSERTION(mSink, "content sink not found!");
         553                 :
         554              67 :   mInCData = false;
         555              67 :   if (mSink) {
         556              67 :     nsresult rv = mSink->HandleCDataSection(mCDataText.get(),
         557              67 :                                             mCDataText.Length());
         558              67 :     MaybeStopParser(rv);
         559                 :   }
         560              67 :   mCDataText.Truncate();
         561                 :
         562              67 :   return NS_OK;
         563                 : }
         564                 :
         565                 : nsresult
         566             320 : nsExpatDriver::HandleStartNamespaceDecl(const PRUnichar* aPrefix,
         567                 :                                         const PRUnichar* aUri)
         568                 : {
         569             320 :   if (mExtendedSink) {
         570             320 :     nsresult rv = mExtendedSink->HandleStartNamespaceDecl(aPrefix, aUri);
         571             320 :     MaybeStopParser(rv);
         572                 :   }
         573             320 :   return NS_OK;
         574                 : }
         575                 :
         576                 : nsresult
         577             314 : nsExpatDriver::HandleEndNamespaceDecl(const PRUnichar* aPrefix)
         578                 : {
         579             314 :   if (mExtendedSink && mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
         580             314 :     nsresult rv = mExtendedSink->HandleEndNamespaceDecl(aPrefix);
         581             314 :     MaybeStopParser(rv);
         582                 :   }
         583             314 :   return NS_OK;
         584                 : }
         585                 :
         586                 : nsresult
         587               0 : nsExpatDriver::HandleNotationDecl(const PRUnichar* aNotationName,
         588                 :                                   const PRUnichar* aBase,
         589                 :                                   const PRUnichar* aSysid,
         590                 :                                   const PRUnichar* aPubid)
         591                 : {
         592               0 :   if (mExtendedSink) {
         593               0 :     nsresult rv = mExtendedSink->HandleNotationDecl(aNotationName, aSysid,
         594               0 :                                                     aPubid);
         595               0 :     MaybeStopParser(rv);
         596                 :   }
         597               0 :   return NS_OK;
         598                 : }
         599                 :
         600                 : nsresult
         601               0 : nsExpatDriver::HandleUnparsedEntityDecl(const PRUnichar* aEntityName,
         602                 :                                         const PRUnichar* aBase,
         603                 :                                         const PRUnichar* aSysid,
         604                 :                                         const PRUnichar* aPubid,
         605                 :                                         const PRUnichar* aNotationName)
         606                 : {
         607               0 :   if (mExtendedSink) {
         608               0 :     nsresult rv = mExtendedSink->HandleUnparsedEntityDecl(aEntityName,
         609                 :                                                           aSysid,
         610                 :                                                           aPubid,
         611               0 :                                                           aNotationName);
         612               0 :     MaybeStopParser(rv);
         613                 :   }
         614               0 :   return NS_OK;
         615                 : }
         616                 :
         617                 : nsresult
         618              49 : nsExpatDriver::HandleStartDoctypeDecl(const PRUnichar* aDoctypeName,
         619                 :                                       const PRUnichar* aSysid,
         620                 :                                       const PRUnichar* aPubid,
         621                 :                                       bool aHasInternalSubset)
         622                 : {
         623              49 :   mDoctypeName = aDoctypeName;
         624              49 :   mSystemID = aSysid;
         625              49 :   mPublicID = aPubid;
         626                 :
         627              49 :   if (mExtendedSink) {
         628               4 :     nsresult rv = mExtendedSink->HandleStartDTD(aDoctypeName, aSysid, aPubid);
         629               4 :     MaybeStopParser(rv);
         630                 :   }
         631                 :
         632              49 :   if (aHasInternalSubset) {
         633                 :     // Consuming a huge internal subset translates to numerous
         634                 :     // allocations. In an effort to avoid too many allocations
         635                 :     // setting mInternalSubset's capacity to be 1K ( just a guesstimate! ).
         636              37 :     mInInternalSubset = true;
         637              37 :     mInternalSubset.SetCapacity(1024);
         638                 :   } else {
         639                 :     // Distinguish missing internal subset from an empty one
         640              12 :     mInternalSubset.SetIsVoid(true);
         641                 :   }
         642                 :
         643              49 :   return NS_OK;
         644                 : }
         645                 :
         646                 : nsresult
         647              49 : nsExpatDriver::HandleEndDoctypeDecl()
         648                 : {
         649              49 :   NS_ASSERTION(mSink, "content sink not found!");
         650                 :
         651              49 :   mInInternalSubset = false;
         652                 :
         653              49 :   if (mSink) {
         654                 :     // let the sink know any additional knowledge that we have about the
         655                 :     // document (currently, from bug 124570, we only expect to pass additional
         656                 :     // agent sheets needed to layout the XML vocabulary of the document)
         657              98 :     nsCOMPtr<nsIURI> data;
         658              49 :     if (mCatalogData && mCatalogData->mAgentSheet) {
         659               0 :       NS_NewURI(getter_AddRefs(data), mCatalogData->mAgentSheet);
         660                 :     }
         661                 :
         662                 :     // Note: mInternalSubset already doesn't include the [] around it.
         663              49 :     nsresult rv = mSink->HandleDoctypeDecl(mInternalSubset, mDoctypeName,
         664              49 :                                            mSystemID, mPublicID, data);
         665              49 :     MaybeStopParser(rv);
         666                 :   }
         667                 :
         668              49 :   mInternalSubset.SetCapacity(0);
         669                 :
         670              49 :   return NS_OK;
         671                 : }
         672                 :
         673                 : static NS_METHOD
         674               0 : ExternalDTDStreamReaderFunc(nsIUnicharInputStream* aIn,
         675                 :                             void* aClosure,
         676                 :                             const PRUnichar* aFromSegment,
         677                 :                             PRUint32 aToOffset,
         678                 :                             PRUint32 aCount,
         679                 :                             PRUint32 *aWriteCount)
         680                 : {
         681                 :   // Pass the buffer to expat for parsing.
         682               0 :   if (XML_Parse((XML_Parser)aClosure, (const char *)aFromSegment,
         683               0 :                 aCount * sizeof(PRUnichar), 0) == XML_STATUS_OK) {
         684               0 :     *aWriteCount = aCount;
         685                 :
         686               0 :     return NS_OK;
         687                 :   }
         688                 :
         689               0 :   *aWriteCount = 0;
         690                 :
         691               0 :   return NS_ERROR_FAILURE;
         692                 : }
         693                 :
         694                 : int
         695              10 : nsExpatDriver::HandleExternalEntityRef(const PRUnichar *openEntityNames,
         696                 :                                        const PRUnichar *base,
         697                 :                                        const PRUnichar *systemId,
         698                 :                                        const PRUnichar *publicId)
         699                 : {
         700              10 :   if (mInInternalSubset && !mInExternalDTD && openEntityNames) {
         701               0 :     mInternalSubset.Append(PRUnichar('%'));
         702               0 :     mInternalSubset.Append(nsDependentString(openEntityNames));
         703               0 :     mInternalSubset.Append(PRUnichar(';'));
         704                 :   }
         705                 :
         706                 :   // Load the external entity into a buffer.
         707              20 :   nsCOMPtr<nsIInputStream> in;
         708              20 :   nsAutoString absURL;
         709                 :   nsresult rv = OpenInputStreamFromExternalDTD(publicId, systemId, base,
         710              10 :                                                getter_AddRefs(in), absURL);
         711              10 :   NS_ENSURE_SUCCESS(rv, 1);
         712                 :
         713               0 :   nsCOMPtr<nsIUnicharInputStream> uniIn;
         714               0 :   rv = nsSimpleUnicharStreamFactory::GetInstance()->
         715               0 :     CreateInstanceFromUTF8Stream(in, getter_AddRefs(uniIn));
         716               0 :   NS_ENSURE_SUCCESS(rv, 1);
         717                 :
         718               0 :   int result = 1;
         719               0 :   if (uniIn) {
         720                 :     XML_Parser entParser = XML_ExternalEntityParserCreate(mExpatParser, 0,
         721               0 :                                                           kUTF16);
         722               0 :     if (entParser) {
         723               0 :       XML_SetBase(entParser, absURL.get());
         724                 :
         725               0 :       mInExternalDTD = true;
         726                 :
         727                 :       PRUint32 totalRead;
         728               0 :       do {
         729               0 :         rv = uniIn->ReadSegments(ExternalDTDStreamReaderFunc, entParser,
         730               0 :                                  PRUint32(-1), &totalRead);
         731               0 :       } while (NS_SUCCEEDED(rv) && totalRead > 0);
         732                 :
         733               0 :       result = XML_Parse(entParser, nsnull, 0, 1);
         734                 :
         735               0 :       mInExternalDTD = false;
         736                 :
         737               0 :       XML_ParserFree(entParser);
         738                 :     }
         739                 :   }
         740                 :
         741               0 :   return result;
         742                 : }
         743                 :
         744                 : nsresult
         745              10 : nsExpatDriver::OpenInputStreamFromExternalDTD(const PRUnichar* aFPIStr,
         746                 :                                               const PRUnichar* aURLStr,
         747                 :                                               const PRUnichar* aBaseURL,
         748                 :                                               nsIInputStream** aStream,
         749                 :                                               nsAString& aAbsURL)
         750                 : {
         751              20 :   nsCOMPtr<nsIURI> baseURI;
         752              10 :   nsresult rv = NS_NewURI(getter_AddRefs(baseURI),
         753              20 :                           NS_ConvertUTF16toUTF8(aBaseURL));
         754              10 :   NS_ENSURE_SUCCESS(rv, rv);
         755                 :
         756              20 :   nsCOMPtr<nsIURI> uri;
         757              10 :   rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURLStr), nsnull,
         758              10 :                  baseURI);
         759              10 :   NS_ENSURE_SUCCESS(rv, rv);
         760                 :
         761                 :   // check if it is alright to load this uri
         762              10 :   bool isChrome = false;
         763              10 :   uri->SchemeIs("chrome", &isChrome);
         764              10 :   if (!isChrome) {
         765                 :     // since the url is not a chrome url, check to see if we can map the DTD
         766                 :     // to a known local DTD, or if a DTD file of the same name exists in the
         767                 :     // special DTD directory
         768              10 :     if (aFPIStr) {
         769                 :       // see if the Formal Public Identifier (FPI) maps to a catalog entry
         770               8 :       mCatalogData = LookupCatalogData(aFPIStr);
         771                 :     }
         772                 :
         773              20 :     nsCOMPtr<nsIURI> localURI;
         774              10 :     GetLocalDTDURI(mCatalogData, uri, getter_AddRefs(localURI));
         775              10 :     if (!localURI) {
         776               0 :       return NS_ERROR_NOT_IMPLEMENTED;
         777                 :     }
         778                 :
         779              20 :     localURI.swap(uri);
         780                 :   }
         781                 :
         782              20 :   nsCOMPtr<nsIDocument> doc;
         783              10 :   NS_ASSERTION(mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)),
         784                 :                "In nsExpatDriver::OpenInputStreamFromExternalDTD: "
         785                 :                "mOriginalSink not the same object as mSink?");
         786              10 :   if (mOriginalSink)
         787              10 :     doc = do_QueryInterface(mOriginalSink->GetTarget());
         788              10 :   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
         789                 :   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_DTD,
         790                 :                                 uri,
         791              18 :                                 (doc ? doc->NodePrincipal() : nsnull),
         792                 :                                 doc,
         793              10 :                                 EmptyCString(), //mime guess
         794                 :                                 nsnull,         //extra
         795              28 :                                 &shouldLoad);
         796              10 :   if (NS_FAILED(rv)) return rv;
         797              10 :   if (NS_CP_REJECTED(shouldLoad)) {
         798                 :     // Disallowed by content policy
         799               0 :     return NS_ERROR_CONTENT_BLOCKED;
         800                 :   }
         801                 :
         802              20 :   nsCAutoString absURL;
         803              10 :   uri->GetSpec(absURL);
         804                 :
         805              10 :   CopyUTF8toUTF16(absURL, aAbsURL);
         806                 :
         807              20 :   nsCOMPtr<nsIChannel> channel;
         808              10 :   rv = NS_NewChannel(getter_AddRefs(channel), uri);
         809              10 :   NS_ENSURE_SUCCESS(rv, rv);
         810                 :
         811              10 :   channel->SetContentType(NS_LITERAL_CSTRING("application/xml"));
         812              10 :   return channel->Open(aStream);
         813                 : }
         814                 :
         815                 : static nsresult
         816              65 : CreateErrorText(const PRUnichar* aDescription,
         817                 :                 const PRUnichar* aSourceURL,
         818                 :                 const PRUint32 aLineNumber,
         819                 :                 const PRUint32 aColNumber,
         820                 :                 nsString& aErrorString)
         821                 : {
         822              65 :   aErrorString.Truncate();
         823                 :
         824             130 :   nsAutoString msg;
         825                 :   nsresult rv =
         826                 :     nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,
         827              65 :                                                "XMLParsingError", msg);
         828              65 :   NS_ENSURE_SUCCESS(rv, rv);
         829                 :
         830                 :   // XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$u, Column %4$u:
         831                 :   PRUnichar *message = nsTextFormatter::smprintf(msg.get(), aDescription,
         832                 :                                                  aSourceURL, aLineNumber,
         833              65 :                                                  aColNumber);
         834              65 :   if (!message) {
         835               0 :     return NS_ERROR_OUT_OF_MEMORY;
         836                 :   }
         837                 :
         838              65 :   aErrorString.Assign(message);
         839              65 :   nsTextFormatter::smprintf_free(message);
         840                 :
         841              65 :   return NS_OK;
         842                 : }
         843                 :
         844                 : static nsresult
         845              65 : AppendErrorPointer(const PRInt32 aColNumber,
         846                 :                    const PRUnichar *aSourceLine,
         847                 :                    nsString& aSourceString)
         848                 : {
         849              65 :   aSourceString.Append(PRUnichar('\n'));
         850                 :
         851                 :   // Last character will be '^'.
         852              65 :   PRInt32 last = aColNumber - 1;
         853                 :   PRInt32 i;
         854              65 :   PRUint32 minuses = 0;
         855             135 :   for (i = 0; i < last; ++i) {
         856              70 :     if (aSourceLine[i] == '\t') {
         857                 :       // Since this uses |white-space: pre;| a tab stop equals 8 spaces.
         858               0 :       PRUint32 add = 8 - (minuses % 8);
         859               0 :       aSourceString.AppendASCII("--------", add);
         860               0 :       minuses += add;
         861                 :     }
         862                 :     else {
         863              70 :       aSourceString.Append(PRUnichar('-'));
         864              70 :       ++minuses;
         865                 :     }
         866                 :   }
         867              65 :   aSourceString.Append(PRUnichar('^'));
         868                 :
         869              65 :   return NS_OK;
         870                 : }
         871                 :
         872                 : nsresult
         873              65 : nsExpatDriver::HandleError()
         874                 : {
         875              65 :   PRInt32 code = XML_GetErrorCode(mExpatParser);
         876              65 :   NS_ASSERTION(code > XML_ERROR_NONE, "unexpected XML error code");
         877                 :
         878                 :   // Map Expat error code to an error string
         879                 :   // XXX Deal with error returns.
         880             130 :   nsAutoString description;
         881                 :   nsParserMsgUtils::GetLocalizedStringByID(XMLPARSER_PROPERTIES, code,
         882              65 :                                            description);
         883                 :
         884              65 :   if (code == XML_ERROR_TAG_MISMATCH) {
         885                 :     /**
         886                 :      *  Expat can send the following:
         887                 :      *    localName
         888                 :      *    namespaceURI<separator>localName
         889                 :      *    namespaceURI<separator>localName<separator>prefix
         890                 :      *
         891                 :      *  and we use 0xFFFF for the <separator>.
         892                 :      *
         893                 :      */
         894              10 :     const PRUnichar *mismatch = MOZ_XML_GetMismatchedTag(mExpatParser);
         895              10 :     const PRUnichar *uriEnd = nsnull;
         896              10 :     const PRUnichar *nameEnd = nsnull;
         897                 :     const PRUnichar *pos;
         898             140 :     for (pos = mismatch; *pos; ++pos) {
         899             130 :       if (*pos == kExpatSeparatorChar) {
         900               0 :         if (uriEnd) {
         901               0 :           nameEnd = pos;
         902                 :         }
         903                 :         else {
         904               0 :           uriEnd = pos;
         905                 :         }
         906                 :       }
         907                 :     }
         908                 :
         909              20 :     nsAutoString tagName;
         910              10 :     if (uriEnd && nameEnd) {
         911                 :       // We have a prefix.
         912               0 :       tagName.Append(nameEnd + 1, pos - nameEnd - 1);
         913               0 :       tagName.Append(PRUnichar(':'));
         914                 :     }
         915              10 :     const PRUnichar *nameStart = uriEnd ? uriEnd + 1 : mismatch;
         916              10 :     tagName.Append(nameStart, (nameEnd ? nameEnd : pos) - nameStart);
         917                 :
         918              20 :     nsAutoString msg;
         919                 :     nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,
         920              10 :                                                "Expected", msg);
         921                 :
         922                 :     // . Expected: </%S>.
         923              10 :     PRUnichar *message = nsTextFormatter::smprintf(msg.get(), tagName.get());
         924              10 :     if (!message) {
         925               0 :       return NS_ERROR_OUT_OF_MEMORY;
         926                 :     }
         927                 :
         928              10 :     description.Append(message);
         929                 :
         930              20 :     nsTextFormatter::smprintf_free(message);
         931                 :   }
         932                 :
         933                 :   // Adjust the column number so that it is one based rather than zero based.
         934              65 :   PRUint32 colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
         935              65 :   PRUint32 lineNumber = XML_GetCurrentLineNumber(mExpatParser);
         936                 :
         937             130 :   nsAutoString errorText;
         938                 :   CreateErrorText(description.get(), XML_GetBase(mExpatParser), lineNumber,
         939              65 :                   colNumber, errorText);
         940                 :
         941              65 :   NS_ASSERTION(mSink, "no sink?");
         942                 :
         943             130 :   nsAutoString sourceText(mLastLine);
         944              65 :   AppendErrorPointer(colNumber, mLastLine.get(), sourceText);
         945                 :
         946                 :   // Try to create and initialize the script error.
         947             130 :   nsCOMPtr<nsIScriptError> serr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
         948              65 :   nsresult rv = NS_ERROR_FAILURE;
         949              65 :   if (serr) {
         950              65 :     rv = serr->InitWithWindowID(description.get(),
         951                 :                                 mURISpec.get(),
         952                 :                                 mLastLine.get(),
         953                 :                                 lineNumber, colNumber,
         954                 :                                 nsIScriptError::errorFlag, "malformed-xml",
         955              65 :                                 mInnerWindowID);
         956                 :   }
         957                 :
         958                 :   // If it didn't initialize, we can't do any logging.
         959              65 :   bool shouldReportError = NS_SUCCEEDED(rv);
         960                 :
         961              65 :   if (mSink && shouldReportError) {
         962              65 :     rv = mSink->ReportError(errorText.get(),
         963                 :                             sourceText.get(),
         964                 :                             serr,
         965              65 :                             &shouldReportError);
         966              65 :     if (NS_FAILED(rv)) {
         967               0 :       shouldReportError = true;
         968                 :     }
         969                 :   }
         970                 :
         971              65 :   if (shouldReportError) {
         972                 :     nsCOMPtr<nsIConsoleService> cs
         973             126 :       (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
         974              63 :     if (cs) {
         975              63 :       cs->LogMessage(serr);
         976                 :     }
         977                 :   }
         978                 :
         979              65 :   return NS_ERROR_HTMLPARSER_STOPPARSING;
         980                 : }
         981                 :
         982                 : void
         983            6754 : nsExpatDriver::ParseBuffer(const PRUnichar *aBuffer,
         984                 :                            PRUint32 aLength,
         985                 :                            bool aIsFinal,
         986                 :                            PRUint32 *aConsumed)
         987                 : {
         988            6754 :   NS_ASSERTION((aBuffer && aLength != 0) || (!aBuffer && aLength == 0), "?");
         989            6754 :   NS_ASSERTION(mInternalState != NS_OK || aIsFinal || aBuffer,
         990                 :                "Useless call, we won't call Expat");
         991            6754 :   NS_PRECONDITION(!BlockedOrInterrupted() || !aBuffer,
         992                 :                   "Non-null buffer when resuming");
         993            6754 :   NS_PRECONDITION(XML_GetCurrentByteIndex(mExpatParser) % sizeof(PRUnichar) == 0,
         994                 :                   "Consumed part of a PRUnichar?");
         995                 :
         996            6754 :   if (mExpatParser && (mInternalState == NS_OK || BlockedOrInterrupted())) {
         997            6754 :     PRInt32 parserBytesBefore = XML_GetCurrentByteIndex(mExpatParser);
         998            6754 :     NS_ASSERTION(parserBytesBefore >= 0, "Unexpected value");
         999                 :
        1000                 :     XML_Status status;
        1001            6754 :     if (BlockedOrInterrupted()) {
        1002               0 :       mInternalState = NS_OK; // Resume in case we're blocked.
        1003               0 :       status = XML_ResumeParser(mExpatParser);
        1004                 :     }
        1005                 :     else {
        1006                 :       status = XML_Parse(mExpatParser,
        1007                 :                          reinterpret_cast<const char*>(aBuffer),
        1008            6754 :                          aLength * sizeof(PRUnichar), aIsFinal);
        1009                 :     }
        1010                 :
        1011            6754 :     PRInt32 parserBytesConsumed = XML_GetCurrentByteIndex(mExpatParser);
        1012                 :
        1013            6754 :     NS_ASSERTION(parserBytesConsumed >= 0, "Unexpected value");
        1014            6754 :     NS_ASSERTION(parserBytesConsumed >= parserBytesBefore,
        1015                 :                  "How'd this happen?");
        1016            6754 :     NS_ASSERTION(parserBytesConsumed % sizeof(PRUnichar) == 0,
        1017                 :                  "Consumed part of a PRUnichar?");
        1018                 :
        1019                 :     // Consumed something.
        1020            6754 :     *aConsumed = (parserBytesConsumed - parserBytesBefore) / sizeof(PRUnichar);
        1021            6754 :     NS_ASSERTION(*aConsumed <= aLength + mExpatBuffered,
        1022                 :                  "Too many bytes consumed?");
        1023                 :
        1024            6754 :     NS_ASSERTION(status != XML_STATUS_SUSPENDED || BlockedOrInterrupted(),
        1025                 :                  "Inconsistent expat suspension state.");
        1026                 :
        1027            6754 :     if (status == XML_STATUS_ERROR) {
        1028              65 :       mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
        1029                 :     }
        1030                 :   }
        1031                 :   else {
        1032               0 :     *aConsumed = 0;
        1033                 :   }
        1034            6754 : }
        1035                 :
        1036                 : NS_IMETHODIMP
        1037            6704 : nsExpatDriver::ConsumeToken(nsScanner& aScanner, bool& aFlushTokens)
        1038                 : {
        1039                 :   // We keep the scanner pointing to the position where Expat will start
        1040                 :   // parsing.
        1041            6704 :   nsScannerIterator currentExpatPosition;
        1042            6704 :   aScanner.CurrentPosition(currentExpatPosition);
        1043                 :
        1044                 :   // This is the start of the first buffer that we need to pass to Expat.
        1045            6704 :   nsScannerIterator start = currentExpatPosition;
        1046            6704 :   start.advance(mExpatBuffered);
        1047                 :
        1048                 :   // This is the end of the last buffer (at this point, more data could come in
        1049                 :   // later).
        1050            6704 :   nsScannerIterator end;
        1051            6704 :   aScanner.EndReading(end);
        1052                 :
        1053            6704 :   PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1054                 :          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
        1055                 :           mExpatBuffered, Distance(start, end)));
        1056                 :
        1057                 :   // We want to call Expat if we have more buffers, or if we know there won't
        1058                 :   // be more buffers (and so we want to flush the remaining data), or if we're
        1059                 :   // currently blocked and there's data in Expat's buffer.
        1060           26736 :   while (start != end || (mIsFinalChunk && !mMadeFinalCallToExpat) ||
        1061            6639 :          (BlockedOrInterrupted() && mExpatBuffered > 0)) {
        1062            6754 :     bool noMoreBuffers = start == end && mIsFinalChunk;
        1063            6754 :     bool blocked = BlockedOrInterrupted();
        1064                 :
        1065                 :     const PRUnichar *buffer;
        1066                 :     PRUint32 length;
        1067            6754 :     if (blocked || noMoreBuffers) {
        1068                 :       // If we're blocked we just resume Expat so we don't need a buffer, if
        1069                 :       // there aren't any more buffers we pass a null buffer to Expat.
        1070            3302 :       buffer = nsnull;
        1071            3302 :       length = 0;
        1072                 :
        1073                 : #if defined(PR_LOGGING) || defined (DEBUG)
        1074            6604 :       if (blocked) {
        1075               0 :         PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1076                 :                ("Resuming Expat, will parse data remaining in Expat's "
        1077                 :                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
        1078                 :                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
        1079                 :                                       mExpatBuffered).get()));
        1080                 :       }
        1081                 :       else {
        1082            3302 :         NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end),
        1083                 :                      "Didn't pass all the data to Expat?");
        1084            3302 :         PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1085                 :                ("Last call to Expat, will parse data remaining in Expat's "
        1086                 :                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
        1087                 :                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
        1088                 :                                       mExpatBuffered).get()));
        1089                 :       }
        1090                 : #endif
        1091                 :     }
        1092                 :     else {
        1093            3452 :       buffer = start.get();
        1094            3452 :       length = PRUint32(start.size_forward());
        1095                 :
        1096            3452 :       PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1097                 :              ("Calling Expat, will parse data remaining in Expat's buffer and "
        1098                 :               "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew "
        1099                 :               "data:\n-----\n%s\n-----\n",
        1100                 :               NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
        1101                 :                                     mExpatBuffered).get(),
        1102                 :               NS_ConvertUTF16toUTF8(start.get(), length).get()));
        1103                 :     }
        1104                 :
        1105                 :     PRUint32 consumed;
        1106            6754 :     ParseBuffer(buffer, length, noMoreBuffers, &consumed);
        1107            6754 :     if (consumed > 0) {
        1108            3451 :       nsScannerIterator oldExpatPosition = currentExpatPosition;
        1109            3451 :       currentExpatPosition.advance(consumed);
        1110                 :
        1111                 :       // We consumed some data, we want to store the last line of data that
        1112                 :       // was consumed in case we run into an error (to show the line in which
        1113                 :       // the error occurred).
        1114                 :
        1115                 :       // The length of the last line that Expat has parsed.
        1116            3451 :       XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
        1117                 :
        1118            3451 :       if (lastLineLength <= consumed) {
        1119                 :         // The length of the last line was less than what expat consumed, so
        1120                 :         // there was at least one line break in the consumed data. Store the
        1121                 :         // last line until the point where we stopped parsing.
        1122            3449 :         nsScannerIterator startLastLine = currentExpatPosition;
        1123            3449 :         startLastLine.advance(-((ptrdiff_t)lastLineLength));
        1124            3449 :         CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine);
        1125                 :       }
        1126                 :       else {
        1127                 :         // There was no line break in the consumed data, append the consumed
        1128                 :         // data.
        1129               2 :         AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
        1130                 :       }
        1131                 :     }
        1132                 :
        1133            6754 :     mExpatBuffered += length - consumed;
        1134                 :
        1135            6754 :     if (BlockedOrInterrupted()) {
        1136               0 :       PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1137                 :              ("Blocked or interrupted parser (probably for loading linked "
        1138                 :               "stylesheets or scripts)."));
        1139                 :
        1140               0 :       aScanner.SetPosition(currentExpatPosition, true);
        1141               0 :       aScanner.Mark();
        1142                 :
        1143               0 :       return mInternalState;
        1144                 :     }
        1145                 :
        1146            6754 :     if (noMoreBuffers && mExpatBuffered == 0) {
        1147            3300 :       mMadeFinalCallToExpat = true;
        1148                 :     }
        1149                 :
        1150            6754 :     if (NS_FAILED(mInternalState)) {
        1151              65 :       if (XML_GetErrorCode(mExpatParser) != XML_ERROR_NONE) {
        1152              65 :         NS_ASSERTION(mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING,
        1153                 :                      "Unexpected error");
        1154                 :
        1155                 :         // Look for the next newline after the last one we consumed
        1156              65 :         nsScannerIterator lastLine = currentExpatPosition;
        1157             131 :         while (lastLine != end) {
        1158              13 :           length = PRUint32(lastLine.size_forward());
        1159              13 :           PRUint32 endOffset = 0;
        1160              13 :           const PRUnichar *buffer = lastLine.get();
        1161             278 :           while (endOffset < length && buffer[endOffset] != '\n' &&
        1162             126 :                  buffer[endOffset] != '\r') {
        1163             126 :             ++endOffset;
        1164                 :           }
        1165              13 :           mLastLine.Append(Substring(buffer, buffer + endOffset));
        1166              13 :           if (endOffset < length) {
        1167                 :             // We found a newline.
        1168              12 :             break;
        1169                 :           }
        1170                 :
        1171               1 :           lastLine.advance(length);
        1172                 :         }
        1173                 :
        1174              65 :         HandleError();
        1175                 :       }
        1176                 :
        1177              65 :       return mInternalState;
        1178                 :     }
        1179                 :
        1180                 :     // Either we have more buffers, or we were blocked (and we'll flush in the
        1181                 :     // next iteration), or we should have emptied Expat's buffer.
        1182            6689 :     NS_ASSERTION(!noMoreBuffers || blocked ||
        1183                 :                  (mExpatBuffered == 0 && currentExpatPosition == end),
        1184                 :                  "Unreachable data left in Expat's buffer");
        1185                 :
        1186            6689 :     start.advance(length);
        1187                 :
        1188                 :     // It's possible for start to have passed end if we received more data
        1189                 :     // (e.g. if we spun the event loop in an inline script). Reload end now
        1190                 :     // to compensate.
        1191            6689 :     aScanner.EndReading(end);
        1192                 :   }
        1193                 :
        1194            6639 :   aScanner.SetPosition(currentExpatPosition, true);
        1195            6639 :   aScanner.Mark();
        1196                 :
        1197            6639 :   PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
        1198                 :          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
        1199                 :           mExpatBuffered, Distance(currentExpatPosition, end)));
        1200                 :
        1201            6639 :   return NS_SUCCEEDED(mInternalState) ? kEOF : NS_OK;
        1202                 : }
        1203                 :
        1204                 : NS_IMETHODIMP
        1205            3314 : nsExpatDriver::WillBuildModel(const CParserContext& aParserContext,
        1206                 :                               nsITokenizer* aTokenizer,
        1207                 :                               nsIContentSink* aSink)
        1208                 : {
        1209            3314 :   mSink = do_QueryInterface(aSink);
        1210            3314 :   if (!mSink) {
        1211               0 :     NS_ERROR("nsExpatDriver didn't get an nsIExpatSink");
        1212                 :     // Make sure future calls to us bail out as needed
        1213               0 :     mInternalState = NS_ERROR_UNEXPECTED;
        1214               0 :     return mInternalState;
        1215                 :   }
        1216                 :
        1217            3314 :   mOriginalSink = aSink;
        1218                 :
        1219                 :   static const XML_Memory_Handling_Suite memsuite =
        1220                 :     {
        1221                 :       (void *(*)(size_t))PR_Malloc,
        1222                 :       (void *(*)(void *, size_t))PR_Realloc,
        1223                 :       PR_Free
        1224                 :     };
        1225                 :
        1226                 :   static const PRUnichar kExpatSeparator[] = { kExpatSeparatorChar, '\0' };
        1227                 :
        1228            3314 :   mExpatParser = XML_ParserCreate_MM(kUTF16, &memsuite, kExpatSeparator);
        1229            3314 :   NS_ENSURE_TRUE(mExpatParser, NS_ERROR_FAILURE);
        1230                 :
        1231            3314 :   XML_SetReturnNSTriplet(mExpatParser, XML_TRUE);
        1232                 :
        1233                 : #ifdef XML_DTD
        1234            3314 :   XML_SetParamEntityParsing(mExpatParser, XML_PARAM_ENTITY_PARSING_ALWAYS);
        1235                 : #endif
        1236                 :
        1237            3314 :   mURISpec = aParserContext.mScanner->GetFilename();
        1238                 :
        1239            3314 :   XML_SetBase(mExpatParser, mURISpec.get());
        1240                 :
        1241            6628 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(mOriginalSink->GetTarget());
        1242            3314 :   if (doc) {
        1243            2078 :     nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
        1244            1039 :     if (!win) {
        1245                 :       bool aHasHadScriptHandlingObject;
        1246                 :       nsIScriptGlobalObject *global =
        1247            1039 :         doc->GetScriptHandlingObject(aHasHadScriptHandlingObject);
        1248            1039 :       if (global) {
        1249               0 :         win = do_QueryInterface(global);
        1250                 :       }
        1251                 :     }
        1252            1039 :     if (win && !win->IsInnerWindow()) {
        1253               0 :       win = win->GetCurrentInnerWindow();
        1254                 :     }
        1255            1039 :     if (win) {
        1256               0 :       mInnerWindowID = win->WindowID();
        1257                 :     }
        1258                 :   }
        1259                 :
        1260                 :   // Set up the callbacks
        1261            3314 :   XML_SetXmlDeclHandler(mExpatParser, Driver_HandleXMLDeclaration);
        1262                 :   XML_SetElementHandler(mExpatParser, Driver_HandleStartElement,
        1263            3314 :                         Driver_HandleEndElement);
        1264            3314 :   XML_SetCharacterDataHandler(mExpatParser, Driver_HandleCharacterData);
        1265                 :   XML_SetProcessingInstructionHandler(mExpatParser,
        1266            3314 :                                       Driver_HandleProcessingInstruction);
        1267            3314 :   XML_SetDefaultHandlerExpand(mExpatParser, Driver_HandleDefault);
        1268                 :   XML_SetExternalEntityRefHandler(mExpatParser,
        1269                 :                                   (XML_ExternalEntityRefHandler)
        1270            3314 :                                           Driver_HandleExternalEntityRef);
        1271            3314 :   XML_SetExternalEntityRefHandlerArg(mExpatParser, this);
        1272            3314 :   XML_SetCommentHandler(mExpatParser, Driver_HandleComment);
        1273                 :   XML_SetCdataSectionHandler(mExpatParser, Driver_HandleStartCdataSection,
        1274            3314 :                              Driver_HandleEndCdataSection);
        1275                 :
        1276                 :   XML_SetParamEntityParsing(mExpatParser,
        1277            3314 :                             XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
        1278                 :   XML_SetDoctypeDeclHandler(mExpatParser, Driver_HandleStartDoctypeDecl,
        1279            3314 :                             Driver_HandleEndDoctypeDecl);
        1280                 :
        1281                 :   // If the sink is an nsIExtendedExpatSink,
        1282                 :   // register some addtional handlers.
        1283            3314 :   mExtendedSink = do_QueryInterface(mSink);
        1284            3314 :   if (mExtendedSink) {
        1285                 :     XML_SetNamespaceDeclHandler(mExpatParser,
        1286                 :                                 Driver_HandleStartNamespaceDecl,
        1287             205 :                                 Driver_HandleEndNamespaceDecl);
        1288                 :     XML_SetUnparsedEntityDeclHandler(mExpatParser,
        1289             205 :                                      Driver_HandleUnparsedEntityDecl);
        1290                 :     XML_SetNotationDeclHandler(mExpatParser,
        1291             205 :                                Driver_HandleNotationDecl);
        1292                 :   }
        1293                 :
        1294                 :   // Set up the user data.
        1295            3314 :   XML_SetUserData(mExpatParser, this);
        1296                 :
        1297                 :   // XML must detect invalid character convertion
        1298            3314 :   aParserContext.mScanner->OverrideReplacementCharacter(0xffff);
        1299                 :
        1300            3314 :   return mInternalState;
        1301                 : }
        1302                 :
        1303                 : NS_IMETHODIMP
        1304            6704 : nsExpatDriver::BuildModel(nsITokenizer* aTokenizer,
        1305                 :                           bool,// aCountLines,
        1306                 :                           const nsCString*)// aCharsetPtr)
        1307                 : {
        1308            6704 :   return mInternalState;
        1309                 : }
        1310                 :
        1311                 : NS_IMETHODIMP
        1312            3314 : nsExpatDriver::DidBuildModel(nsresult anErrorCode)
        1313                 : {
        1314            3314 :   mOriginalSink = nsnull;
        1315            3314 :   mSink = nsnull;
        1316            3314 :   mExtendedSink = nsnull;
        1317            3314 :   return NS_OK;
        1318                 : }
        1319                 :
        1320                 : NS_IMETHODIMP
        1321            6704 : nsExpatDriver::WillTokenize(bool aIsFinalChunk,
        1322                 :                             nsTokenAllocator* aTokenAllocator)
        1323                 : {
        1324            6704 :   mIsFinalChunk = aIsFinalChunk;
        1325            6704 :   return NS_OK;
        1326                 : }
        1327                 :
        1328                 : NS_IMETHODIMP
        1329            6704 : nsExpatDriver::DidTokenize(bool aIsFinalChunk)
        1330                 : {
        1331            6704 :   return NS_OK;
        1332                 : }
        1333                 :
        1334                 : NS_IMETHODIMP_(void)
        1335              65 : nsExpatDriver::Terminate()
        1336                 : {
        1337                 :   // XXX - not sure what happens to the unparsed data.
        1338              65 :   if (mExpatParser) {
        1339              65 :     XML_StopParser(mExpatParser, XML_FALSE);
        1340                 :   }
        1341              65 :   mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
        1342              65 : }
        1343                 :
        1344                 : NS_IMETHODIMP_(PRInt32)
        1345           30130 : nsExpatDriver::GetType()
        1346                 : {
        1347           30130 :   return NS_IPARSER_FLAG_XML;
        1348                 : }
        1349                 :
        1350                 : NS_IMETHODIMP_(nsDTDMode)
        1351            3314 : nsExpatDriver::GetMode() const
        1352                 : {
        1353            3314 :   return eDTDMode_full_standards;
        1354                 : }
        1355                 :
        1356                 : /*************************** Unused methods **********************************/
        1357                 :
        1358                 : NS_IMETHODIMP_(CToken*)
        1359               0 : nsExpatDriver::PushTokenFront(CToken* aToken)
        1360                 : {
        1361               0 :   return 0;
        1362                 : }
        1363                 :
        1364                 : NS_IMETHODIMP_(CToken*)
        1365               0 : nsExpatDriver::PushToken(CToken* aToken)
        1366                 : {
        1367               0 :   return 0;
        1368                 : }
        1369                 :
        1370                 : NS_IMETHODIMP_(CToken*)
        1371               0 : nsExpatDriver::PopToken(void)
        1372                 : {
        1373               0 :   return 0;
        1374                 : }
        1375                 :
        1376                 : NS_IMETHODIMP_(CToken*)
        1377               0 : nsExpatDriver::PeekToken(void)
        1378                 : {
        1379               0 :   return 0;
        1380                 : }
        1381                 :
        1382                 : NS_IMETHODIMP_(CToken*)
        1383               0 : nsExpatDriver::GetTokenAt(PRInt32 anIndex)
        1384                 : {
        1385               0 :   return 0;
        1386                 : }
        1387                 :
        1388                 : NS_IMETHODIMP_(PRInt32)
        1389               0 : nsExpatDriver::GetCount(void)
        1390                 : {
        1391               0 :   return 0;
        1392                 : }
        1393                 :
        1394                 : NS_IMETHODIMP_(nsTokenAllocator*)
        1395               0 : nsExpatDriver::GetTokenAllocator(void)
        1396                 : {
        1397               0 :   return 0;
        1398                 : }
        1399                 :
        1400                 : NS_IMETHODIMP_(void)
        1401               0 : nsExpatDriver::PrependTokens(nsDeque& aDeque)
        1402                 : {
        1403               0 : }
        1404                 :
        1405                 : NS_IMETHODIMP
        1406               0 : nsExpatDriver::CopyState(nsITokenizer* aTokenizer)
        1407                 : {
        1408               0 :   return NS_OK;
        1409                 : }
        1410                 :
        1411                 : nsresult
        1412               0 : nsExpatDriver::HandleToken(CToken* aToken)
        1413                 : {
        1414               0 :   return NS_OK;
        1415                 : }
        1416                 :
        1417                 : NS_IMETHODIMP_(bool)
        1418               0 : nsExpatDriver::IsContainer(PRInt32 aTag) const
        1419                 : {
        1420               0 :   return true;
        1421                 : }
        1422                 :
        1423                 : NS_IMETHODIMP_(bool)
        1424               0 : nsExpatDriver::CanContain(PRInt32 aParent,PRInt32 aChild) const
        1425                 : {
        1426               0 :   return true;
        1427                 : }
        1428                 :
        1429                 : void
        1430          461693 : nsExpatDriver::MaybeStopParser(nsresult aState)
        1431                 : {
        1432          461693 :   if (NS_FAILED(aState)) {
        1433                 :     // If we had a failure we want to override NS_ERROR_HTMLPARSER_INTERRUPTED
        1434                 :     // and we want to override NS_ERROR_HTMLPARSER_BLOCK but not with
        1435                 :     // NS_ERROR_HTMLPARSER_INTERRUPTED.
        1436               0 :     if (NS_SUCCEEDED(mInternalState) ||
        1437                 :         mInternalState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
        1438                 :         (mInternalState == NS_ERROR_HTMLPARSER_BLOCK &&
        1439                 :          aState != NS_ERROR_HTMLPARSER_INTERRUPTED)) {
        1440                 :       mInternalState = (aState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
        1441                 :                         aState == NS_ERROR_HTMLPARSER_BLOCK) ?
        1442                 :                        aState :
        1443               0 :                        NS_ERROR_HTMLPARSER_STOPPARSING;
        1444                 :     }
        1445                 :
        1446                 :     // If we get an error then we need to stop Expat (by calling XML_StopParser
        1447                 :     // with false as the last argument). If the parser should be blocked or
        1448                 :     // interrupted we need to pause Expat (by calling XML_StopParser with
        1449                 :     // true as the last argument).
        1450               0 :     XML_StopParser(mExpatParser, BlockedOrInterrupted());
        1451                 :   }
        1452          461693 :   else if (NS_SUCCEEDED(mInternalState)) {
        1453                 :     // Only clobber mInternalState with the success code if we didn't block or
        1454                 :     // interrupt before.
        1455          461693 :     mInternalState = aState;
        1456                 :   }
        1457          466085 : }

Generated by: LCOV version 1.7