Bug 335366 - Add support for xsd:include. r=aaronr,peterv

This commit is contained in:
doronr%us.ibm.com 2006-06-06 16:00:58 +00:00
parent 2377896430
commit d9ec80d2c8
2 changed files with 187 additions and 40 deletions

View File

@ -42,6 +42,7 @@
// content includes
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOM3Node.h"
@ -660,47 +661,17 @@ nsSchemaLoader::GetResolvedURI(const nsAString& aSchemaURI,
/* nsISchema load (in AString schemaURI); */
NS_IMETHODIMP
nsSchemaLoader::Load(const nsAString& schemaURI,
nsSchemaLoader::Load(const nsAString& schemaURI,
nsISchema **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
nsCOMPtr<nsIURI> resolvedURI;
nsresult rv = GetResolvedURI(schemaURI, "load", getter_AddRefs(resolvedURI));
if (NS_FAILED(rv)) {
return rv;
}
nsCAutoString spec;
resolvedURI->GetSpec(spec);
nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
if (!request) {
return rv;
}
const nsAString& empty = EmptyString();
rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_FALSE, empty,
empty);
if (NS_FAILED(rv)) {
return rv;
}
// Force the mimetype of the returned stream to be xml.
rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
if (NS_FAILED(rv)) {
return rv;
}
rv = request->Send(nsnull);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIDOMDocument> document;
rv = request->GetResponseXML(getter_AddRefs(document));
if (NS_FAILED(rv)) {
return rv;
}
nsresult rv = GetDocumentFromURI(schemaURI, getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
if (!document)
return NS_ERROR_SCHEMA_LOADING_ERROR;
nsCOMPtr<nsIDOMElement> element;
document->GetDocumentElement(getter_AddRefs(element));
@ -711,7 +682,7 @@ nsSchemaLoader::Load(const nsAString& schemaURI,
else {
rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
}
return rv;
}
@ -783,7 +754,7 @@ static const char* kSchemaNamespaces[] = {NS_SCHEMA_1999_NAMESPACE,
static PRUint32 kSchemaNamespacesLength = sizeof(kSchemaNamespaces) / sizeof(const char*);
/* nsISchema processSchemaElement (in nsIDOMElement element, in nsIWebServiceErrorHandler aErrorHandler); */
NS_IMETHODIMP
NS_IMETHODIMP
nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
nsIWebServiceErrorHandler* aErrorHandler,
nsISchema **aResult)
@ -815,7 +786,6 @@ nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
// For now, ignore the following
// annotations
// include
// import
// redefine
// notation
@ -871,8 +841,142 @@ nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
if (NS_SUCCEEDED(rv)) {
rv = schemaInst->AddModelGroup(modelGroup);
}
}
else if (tagName == nsSchemaAtoms::sInclude_atom) {
/* http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-include
If we include a schema, it must either
(a) have the same targetNamespace as the including schema document or
(b) no targetNamespace at all
If the uri to load doesn't resolve, it isn't a error. It is if it's an
invalid XML document or not a schema file
*/
NS_NAMED_LITERAL_STRING(schemaLocationStr, "schemaLocation");
nsAutoString schemalocation;
childElement->GetAttribute(schemaLocationStr, schemalocation);
// if empty, skip it
if (schemalocation.IsEmpty())
continue;
nsCOMPtr<nsIIOService> ios = do_GetIOService();
NS_ENSURE_STATE(ios);
nsCOMPtr<nsIDOMDocument> document;
aElement->GetOwnerDocument(getter_AddRefs(document));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri),
NS_ConvertUTF16toUTF8(schemalocation),
doc->GetDocumentCharacterSet().get(),
doc->GetDocumentURI());
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(uri);
// since we could be going cross-domain, make sure we can load it by doing
// a principal same origin check.
// get the base document's principal
nsIPrincipal *basePrincipal = doc->NodePrincipal();
NS_ENSURE_STATE(basePrincipal);
// check the security manager and do a same original check on the principal
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
NS_ENSURE_STATE(secMan);
// get a principal for the uri we are testing
nsCOMPtr<nsIPrincipal> testPrincipal;
rv = secMan->GetCodebasePrincipal(uri, getter_AddRefs(testPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
rv = secMan->CheckSameOriginPrincipal(basePrincipal, testPrincipal);
// if not allowed, continue onwards
if (NS_FAILED(rv))
continue;
// get the url
nsCAutoString spec;
uri->GetSpec(spec);
nsCOMPtr<nsIDOMDocument> includedDocument;
rv = GetDocumentFromURI(NS_ConvertUTF8toUTF16(spec),
getter_AddRefs(includedDocument));
NS_ENSURE_SUCCESS(rv, rv);
// if no document, it is an error
NS_ENSURE_STATE(includedDocument);
// get the document element - it should be a xsd:schema
nsCOMPtr<nsIDOMElement> element;
includedDocument->GetDocumentElement(getter_AddRefs(element));
nsAutoString localName, nsUri;
element->GetLocalName(localName);
element->GetNamespaceURI(nsUri);
PRBool correctNamespace = PR_FALSE;
PRUint32 i;
for (i = 0; i < kSchemaNamespacesLength; i++) {
if (nsUri.Equals(NS_ConvertASCIItoUTF16(kSchemaNamespaces[i]))) {
correctNamespace = PR_TRUE;
break;
}
}
if (!correctNamespace || !localName.EqualsLiteral("schema")) {
// not a valid schema file
return NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
}
// XXX: check the target namespace requirements
// import/append all elements in the included file to our schema element
nsCOMPtr<nsIDOMDocument> ownerDoc;
rv = childElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(ownerDoc);
nsCOMPtr<nsIDOMNode> tmpNode, importedNode, dummy;
element->GetFirstChild(getter_AddRefs(tmpNode));
// get the child element's next sibling so we have something to insert
// before while we are appending to the current schema document
unsigned short nodeType;
nsCOMPtr<nsIDOMNode> nextSibling;
childElement->GetNextSibling(getter_AddRefs(nextSibling));
while (tmpNode) {
tmpNode->GetNodeType(&nodeType);
if (nodeType == nsIDOMNode::ELEMENT_NODE) {
rv = ownerDoc->ImportNode(tmpNode, PR_TRUE,
getter_AddRefs(importedNode));
NS_ENSURE_SUCCESS(rv, rv);
// InsertBefore can deal with a null nextSibling (will append)
rv = aElement->InsertBefore(importedNode, nextSibling,
getter_AddRefs(dummy));
NS_ENSURE_SUCCESS(rv, rv);
}
tmpNode->GetNextSibling(getter_AddRefs(dummy));
tmpNode = dummy;
}
// we twidle the iterator (reset), making sure to point it at the right
// place. We do this because the iterator takes a snapshot the DOMList,
// so we tell it to reinit itself and then reset it to the original index.
PRUint32 index = iterator.GetCurrentIndex();
iterator.SetElement(aElement);
iterator.Reset(index);
} else if (tagName != nsSchemaAtoms::sAnnotation_atom &&
tagName != nsSchemaAtoms::sInclude_atom &&
tagName != nsSchemaAtoms::sImport_atom &&
tagName != nsSchemaAtoms::sRedefine_atom &&
tagName != nsSchemaAtoms::sNotation_atom) {
@ -3248,3 +3352,43 @@ nsSchemaLoader::ParseNameAndNS(const nsAString& aName, nsIDOMElement* aElement,
return rv;
}
nsresult
nsSchemaLoader::GetDocumentFromURI(const nsAString& aUri,
nsIDOMDocument** aDocument)
{
*aDocument = nsnull;
nsCOMPtr<nsIURI> resolvedURI;
nsresult rv = GetResolvedURI(aUri, "load", getter_AddRefs(resolvedURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXMLHttpRequest> request =
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString spec;
resolvedURI->GetSpec(spec);
const nsAString& empty = EmptyString();
rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_FALSE, empty,
empty);
NS_ENSURE_SUCCESS(rv, rv);
// Force the mimetype of the returned stream to be xml.
rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
NS_ENSURE_SUCCESS(rv, rv);
rv = request->Send(nsnull);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMDocument> document;
rv = request->GetResponseXML(getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
if (document) {
document.swap(*aDocument);
}
return NS_OK;
}

View File

@ -224,6 +224,9 @@ protected:
nsresult ParseNameAndNS(const nsAString& aName, nsIDOMElement* aElement,
nsAString& aTypeName, nsAString& aTypeNS);
nsresult GetDocumentFromURI(const nsAString& aUri,
nsIDOMDocument** aDocument);
protected:
nsInterfaceHashtable<nsStringHashKey, nsISchema> mSchemas;
nsCOMPtr<nsISchemaCollection> mBuiltinCollection;