diff --git a/mozilla/htmlparser/src/nsExpatDriver.cpp b/mozilla/htmlparser/src/nsExpatDriver.cpp index dc92e871660..cd38716a98a 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/htmlparser/src/nsExpatDriver.cpp @@ -173,14 +173,12 @@ Driver_HandleExternalEntityRef(XML_Parser parser, const XML_Char *publicId) { int result = PR_TRUE; - -#ifdef XML_DTD // Load the external entity into a buffer nsCOMPtr in; nsAutoString absURL; - nsresult rv = nsExpatDriver::OpenInputStream(systemId, base, getter_AddRefs(in), absURL); + nsresult rv = nsExpatDriver::OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); if (NS_FAILED(rv)) { return result; @@ -215,10 +213,6 @@ Driver_HandleExternalEntityRef(XML_Parser parser, XML_ParserFree(entParser); } } - -#else // ! XML_DTD - NS_NOTYETIMPLEMENTED("Error: Driver_HandleExternalEntityRef() not yet implemented."); -#endif // XML_DTD return result; } @@ -407,13 +401,48 @@ nsExpatDriver::HandleEndDoctypeDecl() return NS_OK; } +// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus +// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. +// Since Mozilla is not validating, no need to fetch a *huge* file at each click. +// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs +struct nsCatalogEntry { + const char* mPublicID; + const char* mLocalDTD; +}; + +static const nsCatalogEntry kCatalogTable[] = { + {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd"}, + {"-//W3C//DTD SVG 20001102//EN", "svg.dtd"}, + {nsnull, nsnull} +}; + +static void +RemapDTD(const XML_Char* aPublicID, nsAWritableCString& aLocalDTD) +{ + nsCAutoString publicID; + publicID.AssignWithConversion((const PRUnichar*)aPublicID); + + // linear search for now since the number of entries is going to + // be negligible, and the fix for bug 98413 would get rid of this + // code anyway + aLocalDTD.Truncate(); + const nsCatalogEntry* data = kCatalogTable; + while (data->mPublicID) { + if (publicID.Equals(data->mPublicID)) { + aLocalDTD = data->mLocalDTD; + return; + } + ++data; + } +} + // aDTD is an in/out parameter. Returns true if the aDTD is a chrome url or if the // filename contained within the url exists in the special DTD directory ("dtd" // relative to the current process directory). For the latter case, aDTD is set // to the file: url that points to the DTD file found in the local DTD directory // AND the old URI is relased. static PRBool -IsLoadableDTD(nsCOMPtr* aDTD) +IsLoadableDTD(const XML_Char* aFPIStr, nsCOMPtr* aDTD) { PRBool isLoadable = PR_FALSE; nsresult res = NS_OK; @@ -428,35 +457,46 @@ IsLoadableDTD(nsCOMPtr* aDTD) // If the url is not a chrome url, check to see if a DTD file of the same name // exists in the special DTD directory - if (!isLoadable) { - nsCOMPtr dtdURL; - dtdURL = do_QueryInterface(*aDTD, &res); - if (NS_SUCCEEDED(res)) { - nsXPIDLCString fileName; + if (!isLoadable) { + // try to see if we can map the public ID to a known local DTD + nsXPIDLCString fileName; + RemapDTD(aFPIStr, fileName); + if (fileName.IsEmpty()) { + // try to see if the user has installed the DTD file -- we extract the + // filename.ext of the DTD here. Hence, for any DTD for which we have + // no predefined mapping, users just have to copy the DTD file to our + // special DTD directory and it will be picked + nsCOMPtr dtdURL; + dtdURL = do_QueryInterface(*aDTD, &res); + if (NS_FAILED(res)) { + return PR_FALSE; + } res = dtdURL->GetFileName(getter_Copies(fileName)); - if (NS_SUCCEEDED(res) && fileName) { - nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); - dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); - if (dtdPath.Exists()) { - // The DTD was found in the local DTD directory. - // Set aDTD to a file: url pointing to the local DTD - nsFileURL dtdFile(dtdPath); - nsCOMPtr dtdURI; - res = NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); - if (NS_SUCCEEDED(res) && dtdURI) { - *aDTD = dtdURI; - isLoadable = PR_TRUE; - } - } + if (NS_FAILED(res) || fileName.IsEmpty()) { + return PR_FALSE; } } - } + nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); + if (dtdPath.Exists()) { + // The DTD was found in the local DTD directory. + // Set aDTD to a file: url pointing to the local DTD + nsFileURL dtdFile(dtdPath); + nsCOMPtr dtdURI; + NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); + if (dtdURI) { + *aDTD = dtdURI; + isLoadable = PR_TRUE; + } + } + } return isLoadable; } nsresult -nsExpatDriver::OpenInputStream(const XML_Char* aURLStr, +nsExpatDriver::OpenInputStream(const XML_Char* aFPIStr, + const XML_Char* aURLStr, const XML_Char* aBaseURL, nsIInputStream** in, nsAString& aAbsURL) @@ -468,7 +508,7 @@ nsExpatDriver::OpenInputStream(const XML_Char* aURLStr, nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8((const PRUnichar*)aURLStr).get(), baseURI); if (NS_SUCCEEDED(rv) && uri) { - if (IsLoadableDTD(address_of(uri))) { + if (IsLoadableDTD(aFPIStr, address_of(uri))) { rv = NS_OpenURI(in, uri); nsXPIDLCString absURL; uri->GetSpec(getter_Copies(absURL)); diff --git a/mozilla/htmlparser/src/nsExpatDriver.h b/mozilla/htmlparser/src/nsExpatDriver.h index 1195658f0bd..753b9b32d8c 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.h +++ b/mozilla/htmlparser/src/nsExpatDriver.h @@ -59,7 +59,8 @@ public: virtual ~nsExpatDriver(); // Load up an external stream to get external entity information - static nsresult OpenInputStream(const XML_Char* aURLStr, + static nsresult OpenInputStream(const XML_Char* aFPIStr, + const XML_Char* aURLStr, const XML_Char* aBaseURL, nsIInputStream** in, nsAString& aAbsURL); diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp index dc92e871660..cd38716a98a 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp @@ -173,14 +173,12 @@ Driver_HandleExternalEntityRef(XML_Parser parser, const XML_Char *publicId) { int result = PR_TRUE; - -#ifdef XML_DTD // Load the external entity into a buffer nsCOMPtr in; nsAutoString absURL; - nsresult rv = nsExpatDriver::OpenInputStream(systemId, base, getter_AddRefs(in), absURL); + nsresult rv = nsExpatDriver::OpenInputStream(publicId, systemId, base, getter_AddRefs(in), absURL); if (NS_FAILED(rv)) { return result; @@ -215,10 +213,6 @@ Driver_HandleExternalEntityRef(XML_Parser parser, XML_ParserFree(entParser); } } - -#else // ! XML_DTD - NS_NOTYETIMPLEMENTED("Error: Driver_HandleExternalEntityRef() not yet implemented."); -#endif // XML_DTD return result; } @@ -407,13 +401,48 @@ nsExpatDriver::HandleEndDoctypeDecl() return NS_OK; } +// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus +// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses. +// Since Mozilla is not validating, no need to fetch a *huge* file at each click. +// XXX The cleanest solution here would be to fix Bug 98413: Implement XML Catalogs +struct nsCatalogEntry { + const char* mPublicID; + const char* mLocalDTD; +}; + +static const nsCatalogEntry kCatalogTable[] = { + {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "mathml.dtd"}, + {"-//W3C//DTD SVG 20001102//EN", "svg.dtd"}, + {nsnull, nsnull} +}; + +static void +RemapDTD(const XML_Char* aPublicID, nsAWritableCString& aLocalDTD) +{ + nsCAutoString publicID; + publicID.AssignWithConversion((const PRUnichar*)aPublicID); + + // linear search for now since the number of entries is going to + // be negligible, and the fix for bug 98413 would get rid of this + // code anyway + aLocalDTD.Truncate(); + const nsCatalogEntry* data = kCatalogTable; + while (data->mPublicID) { + if (publicID.Equals(data->mPublicID)) { + aLocalDTD = data->mLocalDTD; + return; + } + ++data; + } +} + // aDTD is an in/out parameter. Returns true if the aDTD is a chrome url or if the // filename contained within the url exists in the special DTD directory ("dtd" // relative to the current process directory). For the latter case, aDTD is set // to the file: url that points to the DTD file found in the local DTD directory // AND the old URI is relased. static PRBool -IsLoadableDTD(nsCOMPtr* aDTD) +IsLoadableDTD(const XML_Char* aFPIStr, nsCOMPtr* aDTD) { PRBool isLoadable = PR_FALSE; nsresult res = NS_OK; @@ -428,35 +457,46 @@ IsLoadableDTD(nsCOMPtr* aDTD) // If the url is not a chrome url, check to see if a DTD file of the same name // exists in the special DTD directory - if (!isLoadable) { - nsCOMPtr dtdURL; - dtdURL = do_QueryInterface(*aDTD, &res); - if (NS_SUCCEEDED(res)) { - nsXPIDLCString fileName; + if (!isLoadable) { + // try to see if we can map the public ID to a known local DTD + nsXPIDLCString fileName; + RemapDTD(aFPIStr, fileName); + if (fileName.IsEmpty()) { + // try to see if the user has installed the DTD file -- we extract the + // filename.ext of the DTD here. Hence, for any DTD for which we have + // no predefined mapping, users just have to copy the DTD file to our + // special DTD directory and it will be picked + nsCOMPtr dtdURL; + dtdURL = do_QueryInterface(*aDTD, &res); + if (NS_FAILED(res)) { + return PR_FALSE; + } res = dtdURL->GetFileName(getter_Copies(fileName)); - if (NS_SUCCEEDED(res) && fileName) { - nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); - dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); - if (dtdPath.Exists()) { - // The DTD was found in the local DTD directory. - // Set aDTD to a file: url pointing to the local DTD - nsFileURL dtdFile(dtdPath); - nsCOMPtr dtdURI; - res = NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); - if (NS_SUCCEEDED(res) && dtdURI) { - *aDTD = dtdURI; - isLoadable = PR_TRUE; - } - } + if (NS_FAILED(res) || fileName.IsEmpty()) { + return PR_FALSE; } } - } + nsSpecialSystemDirectory dtdPath(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + dtdPath += PromiseFlatCString(nsDependentCString(kDTDDirectory) + fileName).get(); + if (dtdPath.Exists()) { + // The DTD was found in the local DTD directory. + // Set aDTD to a file: url pointing to the local DTD + nsFileURL dtdFile(dtdPath); + nsCOMPtr dtdURI; + NS_NewURI(getter_AddRefs(dtdURI), dtdFile.GetURLString()); + if (dtdURI) { + *aDTD = dtdURI; + isLoadable = PR_TRUE; + } + } + } return isLoadable; } nsresult -nsExpatDriver::OpenInputStream(const XML_Char* aURLStr, +nsExpatDriver::OpenInputStream(const XML_Char* aFPIStr, + const XML_Char* aURLStr, const XML_Char* aBaseURL, nsIInputStream** in, nsAString& aAbsURL) @@ -468,7 +508,7 @@ nsExpatDriver::OpenInputStream(const XML_Char* aURLStr, nsCOMPtr uri; rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUCS2toUTF8((const PRUnichar*)aURLStr).get(), baseURI); if (NS_SUCCEEDED(rv) && uri) { - if (IsLoadableDTD(address_of(uri))) { + if (IsLoadableDTD(aFPIStr, address_of(uri))) { rv = NS_OpenURI(in, uri); nsXPIDLCString absURL; uri->GetSpec(getter_Copies(absURL)); diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.h b/mozilla/parser/htmlparser/src/nsExpatDriver.h index 1195658f0bd..753b9b32d8c 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.h +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.h @@ -59,7 +59,8 @@ public: virtual ~nsExpatDriver(); // Load up an external stream to get external entity information - static nsresult OpenInputStream(const XML_Char* aURLStr, + static nsresult OpenInputStream(const XML_Char* aFPIStr, + const XML_Char* aURLStr, const XML_Char* aBaseURL, nsIInputStream** in, nsAString& aAbsURL);