Bug 1222624: Make xpath document() function use nsIPrincipals and nsIURIs rather than strings. r=peterv

This commit is contained in:
Jonas Sicking 2015-12-04 21:06:47 -08:00
parent 860b42573b
commit 0a991fdd2a
19 changed files with 180 additions and 137 deletions

View File

@ -17,30 +17,6 @@ using mozilla::LoadInfo;
* A set of utilities for handling URIs
**/
/**
* Resolves the given href argument, using the given documentBase
* if necessary.
* The new resolved href will be appended to the given dest String
**/
void URIUtils::resolveHref(const nsAString& href, const nsAString& base,
nsAString& dest) {
if (base.IsEmpty()) {
dest.Append(href);
return;
}
if (href.IsEmpty()) {
dest.Append(base);
return;
}
nsCOMPtr<nsIURI> pURL;
nsAutoString resultHref;
nsresult result = NS_NewURI(getter_AddRefs(pURL), base);
if (NS_SUCCEEDED(result)) {
NS_MakeAbsoluteURI(resultHref, href, pURL);
dest.Append(resultHref);
}
} //-- resolveHref
// static
void
URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode)

View File

@ -23,14 +23,6 @@ public:
* Reset the given document with the document of the source node
*/
static void ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode);
/**
* Resolves the given href argument, using the given documentBase
* if necessary.
* The new resolved href will be appended to the given dest String
**/
static void resolveHref(const nsAString& href, const nsAString& base,
nsAString& dest);
}; //-- URIUtils
/* */

View File

@ -0,0 +1,4 @@
<?xml-stylesheet type="text/xsl" href="file_bug1222624.xsl"?>
<root>
<load>file_bug1222624_data2.xml</load>
</root>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="file_bug1222624_sub.xsl"/>
<xsl:template match="/root">
<result>
<xsl:call-template name="external"/>
<xsl:value-of select="document('file_bug1222624_data1.xml')"/>
<xsl:text>!</xsl:text>
<xsl:value-of select="document(load)"/>
</result>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1 @@
<data>doc1</data>

View File

@ -0,0 +1 @@
<data>doc2</data>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="file_bug1222624_sub_sub.xsl"/>
</xsl:stylesheet>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="external">
<external/>
</xsl:template>
</xsl:stylesheet>

View File

@ -16,5 +16,7 @@
[test_bug667315.html]
[test_bug1135764.html]
support-files = file_bug1135764.xml file_bug1135764.xsl
[test_bug1222624.html]
support-files = file_bug1222624.xml file_bug1222624.xsl file_bug1222624_sub.xsl file_bug1222624_sub_sub.xsl file_bug1222624_data1.xml file_bug1222624_data2.xml
[test_exslt_regex.html]
[test_parameter.html]

View File

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1222624
-->
<head>
<title>Test for Bug 1222624</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1222624">Mozilla Bug 1222624</a>
<p id="display"></p>
<iframe id="frame"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 1222624 **/
const transformRes = '<?xml version="1.0" encoding="UTF-8"?>\n<result><external/>doc1!doc2</result>';
xhr = new XMLHttpRequest();
xhr.open("GET", "file_bug1222624.xml", false);
xhr.send();
var xmlDoc = xhr.responseXML;
xhr.open("GET", "file_bug1222624.xsl", false);
xhr.send();
var xslDoc = xhr.responseXML;
var processor = new XSLTProcessor;
processor.importStylesheet(xslDoc);
var apiRes = new XMLSerializer().serializeToString(processor.transformToDocument(xmlDoc));
is(apiRes, transformRes, "API transformation correct");
SimpleTest.waitForExplicitFinish();
var frame = $("frame");
frame.src = "file_bug1222624.xml";
frame.onload = function () {
var piRes = new XMLSerializer().serializeToString(frame.contentDocument);
is(piRes, transformRes, "processing-instruction transformation correct");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

View File

@ -15,20 +15,14 @@
#include "nsIPrincipal.h"
nsresult
txParseDocumentFromURI(const nsAString& aHref,
const txXPathNode& aLoader,
txParseDocumentFromURI(nsIURI* aUri,
nsIDocument* aLoadingDocument,
nsAString& aErrMsg,
txXPathNode** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nullptr;
nsCOMPtr<nsIURI> documentURI;
nsresult rv = NS_NewURI(getter_AddRefs(documentURI), aHref);
NS_ENSURE_SUCCESS(rv, rv);
nsIDocument* loaderDocument = txXPathNativeNode::getDocument(aLoader);
nsCOMPtr<nsILoadGroup> loadGroup = loaderDocument->GetDocumentLoadGroup();
nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
// For the system principal loaderUri will be null here, which is good
// since that means that chrome documents can load any uri.
@ -36,20 +30,24 @@ txParseDocumentFromURI(const nsAString& aHref,
// Raw pointer, we want the resulting txXPathNode to hold a reference to
// the document.
nsIDOMDocument* theDocument = nullptr;
nsAutoSyncOperation sync(loaderDocument);
rv = nsSyncLoadService::LoadDocument(documentURI,
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
loaderDocument->NodePrincipal(),
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
loadGroup, true,
loaderDocument->GetReferrerPolicy(),
&theDocument);
nsAutoSyncOperation sync(aLoadingDocument);
nsresult rv =
nsSyncLoadService::LoadDocument(aUri,
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
aLoadingDocument->NodePrincipal(),
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
loadGroup,
true,
aLoadingDocument->GetReferrerPolicy(),
&theDocument);
if (NS_FAILED(rv)) {
aErrMsg.AppendLiteral("Document load of ");
aErrMsg.Append(aHref);
nsAutoCString spec;
aUri->GetSpec(spec);
aErrMsg.Append(NS_ConvertUTF8toUTF16(spec));
aErrMsg.AppendLiteral(" failed.");
return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
return rv;
}
*aResult = txXPathNativeNode::createXPathNode(theDocument);

View File

@ -9,6 +9,8 @@
#include "txCore.h"
class txXPathNode;
class nsIURI;
class nsIDocument;
/**
* API to load XML files into DOM datastructures.
@ -20,7 +22,9 @@ class txXPathNode;
* of the document aLoader.
*/
extern "C" nsresult
txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
nsAString& aErrMsg, txXPathNode** aResult);
txParseDocumentFromURI(nsIURI* aUri,
nsIDocument* aLoadingDocument,
nsAString& aErrMsg,
txXPathNode** aResult);
#endif

View File

@ -563,9 +563,9 @@ txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
/* static */
void
txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsIURI** aUri)
{
aNode.mNode->GetBaseURI(aURI);
*aUri = aNode.mNode->GetBaseURI().take();
}
/* static */

View File

@ -93,7 +93,7 @@ public:
static nsresult getXSLTId(const txXPathNode& aNode,
const txXPathNode& aBase, nsAString& aResult);
static void release(txXPathNode* aNode);
static void getBaseURI(const txXPathNode& aNode, nsAString& aURI);
static void getBaseURI(const txXPathNode& aNode, nsIURI** aURI);
static int comparePosition(const txXPathNode& aNode,
const txXPathNode& aOtherNode);
static bool localNameEquals(const txXPathNode& aNode,

View File

@ -14,48 +14,32 @@
#include "txExecutionState.h"
#include "txURIUtils.h"
#include "nsIURI.h"
/*
* Creates a new DocumentFunctionCall.
*/
DocumentFunctionCall::DocumentFunctionCall(nsIURI* aBaseURI)
{
nsCString spec;
aBaseURI->GetSpec(spec);
mBaseURI = NS_ConvertUTF8toUTF16(spec);
}
#include "nsNetUtil.h"
static void
retrieveNode(txExecutionState* aExecutionState, const nsAString& aUri,
const nsAString& aBaseUri, txNodeSet* aNodeSet)
retrieveNode(txExecutionState* aExecutionState,
const nsAString& aUri,
nsIURI* aBaseUri,
txNodeSet* aNodeSet)
{
nsAutoString absUrl;
URIUtils::resolveHref(aUri, aBaseUri, absUrl);
int32_t hash = absUrl.RFindChar(char16_t('#'));
uint32_t urlEnd, fragStart, fragEnd;
if (hash == kNotFound) {
urlEnd = absUrl.Length();
fragStart = 0;
fragEnd = 0;
}
else {
urlEnd = hash;
fragStart = hash + 1;
fragEnd = absUrl.Length();
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUri, nullptr, aBaseUri);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsDependentSubstring docUrl(absUrl, 0, urlEnd);
nsDependentSubstring frag(absUrl, fragStart, fragEnd);
nsAutoCString frag;
uri->GetRef(frag);
uri->SetRef(EmptyCString());
const txXPathNode* loadNode = aExecutionState->retrieveDocument(docUrl);
const txXPathNode* loadNode = aExecutionState->retrieveDocument(uri);
if (loadNode) {
if (frag.IsEmpty()) {
aNodeSet->add(*loadNode);
}
else {
txXPathTreeWalker walker(*loadNode);
if (walker.moveToElementById(frag)) {
if (walker.moveToElementById(NS_ConvertUTF8toUTF16(frag))) {
aNodeSet->add(walker.getCurrentPosition());
}
}
@ -90,7 +74,7 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext,
rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult1));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString baseURI;
nsCOMPtr<nsIURI> baseURI;
bool baseURISet = false;
if (mParams.Length() == 2) {
@ -107,7 +91,8 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext,
baseURISet = true;
if (!nodeSet2->isEmpty()) {
txXPathNodeUtils::getBaseURI(nodeSet2->get(0), baseURI);
txXPathNodeUtils::getBaseURI(nodeSet2->get(0),
getter_AddRefs(baseURI));
}
}
@ -124,7 +109,7 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext,
if (!baseURISet) {
// if the second argument wasn't specified, use
// the baseUri of node itself
txXPathNodeUtils::getBaseURI(node, baseURI);
txXPathNodeUtils::getBaseURI(node, getter_AddRefs(baseURI));
}
retrieveNode(es, uriStr, baseURI, nodeSet);
}
@ -137,8 +122,8 @@ DocumentFunctionCall::evaluate(txIEvalContext* aContext,
// The first argument is not a NodeSet
nsAutoString uriStr;
exprResult1->stringValue(uriStr);
const nsAString* base = baseURISet ? &baseURI : &mBaseURI;
retrieveNode(es, uriStr, *base, nodeSet);
nsIURI* base = baseURISet ? baseURI.get() : mBaseURI.get();
retrieveNode(es, uriStr, base, nodeSet);
NS_ADDREF(*aResult = nodeSet);

View File

@ -21,27 +21,28 @@ txLoadedDocumentsHash::init(txXPathNode* aSourceDocument)
{
mSourceDocument = aSourceDocument;
nsAutoString baseURI;
txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI);
nsCOMPtr<nsIURI> baseURI;
txXPathNodeUtils::getBaseURI(*mSourceDocument, getter_AddRefs(baseURI));
PutEntry(baseURI)->mDocument = mSourceDocument;
LookupOrAdd(baseURI)->mDocument = mSourceDocument;
}
txLoadedDocumentsHash::~txLoadedDocumentsHash()
{
if (mSourceDocument) {
nsAutoString baseURI;
txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI);
nsCOMPtr<nsIURI> baseURI;
txXPathNodeUtils::getBaseURI(*mSourceDocument, getter_AddRefs(baseURI));
txLoadedDocumentEntry* entry = GetEntry(baseURI);
if (entry) {
delete entry->mDocument.forget();
txLoadedDocumentInfo* info = Get(baseURI);
if (info) {
delete info->mDocument.forget();
}
}
}
txExecutionState::txExecutionState(txStylesheet* aStylesheet,
bool aDisableLoads)
bool aDisableLoads,
nsIDocument* aLoadingDocument)
: mOutputHandler(nullptr),
mResultHandler(nullptr),
mStylesheet(aStylesheet),
@ -51,6 +52,7 @@ txExecutionState::txExecutionState(txStylesheet* aStylesheet,
mEvalContext(nullptr),
mInitialEvalContext(nullptr),
mGlobalParams(nullptr),
mLoadingDocument(aLoadingDocument),
mKeyHash(aStylesheet->getKeyMap()),
mDisableLoads(aDisableLoads)
{
@ -372,41 +374,48 @@ txExecutionState::getEvalContext()
}
const txXPathNode*
txExecutionState::retrieveDocument(const nsAString& aUri)
txExecutionState::retrieveDocument(nsIURI* aUri)
{
NS_ASSERTION(!aUri.Contains(char16_t('#')),
"Remove the fragment.");
#ifdef DEBUG
{
bool hasFrag;
aUri->GetHasRef(&hasFrag);
MOZ_ASSERT(!hasFrag, "Remove the fragment");
}
#endif
if (mDisableLoads) {
if (mDisableLoads || !mLoadingDocument) {
return nullptr;
}
MOZ_LOG(txLog::xslt, LogLevel::Debug,
("Retrieve Document %s", NS_LossyConvertUTF16toASCII(aUri).get()));
if (MOZ_LOG_TEST(txLog::xslt, LogLevel::Debug)) {
nsAutoCString spec;
aUri->GetSpec(spec);
MOZ_LOG(txLog::xslt, LogLevel::Debug,
("Retrieve Document %s", spec.get()));
}
// try to get already loaded document
txLoadedDocumentEntry *entry = mLoadedDocuments.PutEntry(aUri);
if (!entry) {
return nullptr;
}
txLoadedDocumentInfo* info = mLoadedDocuments.LookupOrAdd(aUri);
if (!entry->mDocument && !entry->LoadingFailed()) {
if (!info->mDocument && !info->LoadingFailed()) {
// open URI
nsAutoString errMsg;
// XXX we should get the loader from the actual node
// triggering the load, but this will do for the time being
entry->mLoadResult =
txParseDocumentFromURI(aUri, *mLoadedDocuments.mSourceDocument,
errMsg, getter_Transfers(entry->mDocument));
info->mLoadResult =
txParseDocumentFromURI(aUri, mLoadingDocument,
errMsg, getter_Transfers(info->mDocument));
if (entry->LoadingFailed()) {
if (info->LoadingFailed()) {
nsAutoCString spec;
aUri->GetSpec(spec);
receiveError(NS_LITERAL_STRING("Couldn't load document '") +
aUri + NS_LITERAL_STRING("': ") + errMsg,
entry->mLoadResult);
NS_ConvertUTF8toUTF16(spec) +
NS_LITERAL_STRING("': ") + errMsg,
info->mLoadResult);
}
}
return entry->mDocument;
return info->mDocument;
}
nsresult

View File

@ -17,24 +17,19 @@
#include "txStylesheet.h"
#include "txXPathTreeWalker.h"
#include "nsTArray.h"
#include "nsURIHashKey.h"
class txAOutputHandlerFactory;
class txAXMLEventHandler;
class txInstruction;
class txLoadedDocumentEntry : public nsStringHashKey
class txLoadedDocumentInfo
{
public:
explicit txLoadedDocumentEntry(KeyTypePointer aStr) : nsStringHashKey(aStr),
mLoadResult(NS_OK)
explicit txLoadedDocumentInfo() : mLoadResult(NS_OK)
{
}
txLoadedDocumentEntry(const txLoadedDocumentEntry& aToCopy)
: nsStringHashKey(aToCopy)
{
NS_ERROR("We're horked.");
}
~txLoadedDocumentEntry()
~txLoadedDocumentInfo()
{
if (mDocument) {
txXPathNodeUtils::release(mDocument);
@ -52,11 +47,11 @@ public:
nsresult mLoadResult;
};
class txLoadedDocumentsHash : public nsTHashtable<txLoadedDocumentEntry>
class txLoadedDocumentsHash : public nsClassHashtable<nsURIHashKey, txLoadedDocumentInfo>
{
public:
txLoadedDocumentsHash()
: nsTHashtable<txLoadedDocumentEntry>(4),
: nsClassHashtable<nsURIHashKey, txLoadedDocumentInfo>(4),
mSourceDocument(nullptr)
{
}
@ -72,7 +67,8 @@ private:
class txExecutionState : public txIMatchContext
{
public:
txExecutionState(txStylesheet* aStylesheet, bool aDisableLoads);
txExecutionState(txStylesheet* aStylesheet, bool aDisableLoads,
nsIDocument* aLoaderDocument);
~txExecutionState();
nsresult init(const txXPathNode& aNode,
txOwningExpandedNameMap<txIGlobalParameter>* aGlobalParams);
@ -107,7 +103,7 @@ public:
// state-getting functions
txIEvalContext* getEvalContext();
const txXPathNode* retrieveDocument(const nsAString& aUri);
const txXPathNode* retrieveDocument(nsIURI* aUri);
nsresult getKeyNodes(const txExpandedName& aKeyName,
const txXPathNode& aRoot,
const nsAString& aKeyValue, bool aIndexIfNotFound,
@ -161,6 +157,7 @@ private:
//Document* mRTFDocument;
txOwningExpandedNameMap<txIGlobalParameter>* mGlobalParams;
nsCOMPtr<nsIDocument> mLoadingDocument;
txLoadedDocumentsHash mLoadedDocuments;
txKeyHash mKeyHash;
RefPtr<txResultRecycler> mRecycler;

View File

@ -673,7 +673,7 @@ txMozillaXSLTProcessor::TransformToDoc(nsIDOMDocument **aResult,
sourceDOMDocument = do_QueryInterface(mSource);
}
txExecutionState es(mStylesheet, IsLoadDisabled());
txExecutionState es(mStylesheet, IsLoadDisabled(), getLoaderDoc());
// XXX Need to add error observers
@ -741,7 +741,7 @@ txMozillaXSLTProcessor::TransformToFragment(nsIDOMNode *aSource,
return NS_ERROR_OUT_OF_MEMORY;
}
txExecutionState es(mStylesheet, IsLoadDisabled());
txExecutionState es(mStylesheet, IsLoadDisabled(), getLoaderDoc());
// XXX Need to add error observers

View File

@ -23,12 +23,14 @@ public:
/**
* Creates a new document() function call
**/
explicit DocumentFunctionCall(nsIURI* aBaseURI);
explicit DocumentFunctionCall(nsIURI* aBaseURI)
: mBaseURI(aBaseURI)
{}
TX_DECL_FUNCTION
private:
nsString mBaseURI;
nsCOMPtr<nsIURI> mBaseURI;
};
/*