mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 07:34:20 +00:00
Bug 278560, fix RDF/XML serialize - parse cycle wrt namespace mappings, regression from bug 192139, r=mscott, sr=peterv
This commit is contained in:
parent
f3c9ef6e37
commit
14d0d7849a
@ -229,19 +229,23 @@ protected:
|
||||
PRInt32 mTextLength;
|
||||
PRInt32 mTextSize;
|
||||
|
||||
/**
|
||||
* From the set of given attributes, this method extracts the
|
||||
* namespace definitions and feeds them to the datasource.
|
||||
* These can then be suggested to the serializer to be used again.
|
||||
* Hopefully, this will keep namespace definitions intact in a
|
||||
* parse - serialize cycle.
|
||||
*/
|
||||
void RegisterNamespaces(const PRUnichar **aAttributes);
|
||||
|
||||
/**
|
||||
* Extracts the localname from aExpatName, the name that the Expat parser
|
||||
* passes us. aValue should contain a namespace URI if we need to register
|
||||
* a new prefix-to-namespace-URI mapping when aExpatName declares a
|
||||
* namespace (namespace URI in aExpatName being
|
||||
* http://www.w3.org/2000/xmlns/). aValue is typically the value of an
|
||||
* xmlns attribute.
|
||||
* aLocalName will contain the localname in aExpatName and the returned
|
||||
* value will be the namespace URI.
|
||||
* passes us.
|
||||
* aLocalName will contain the localname in aExpatName.
|
||||
* The return value is a dependent string containing just the namespace.
|
||||
*/
|
||||
const nsDependentSubstring SplitExpatName(const PRUnichar *aExpatName,
|
||||
nsIAtom **aLocalName,
|
||||
const PRUnichar* aValue = nsnull);
|
||||
nsIAtom **aLocalName);
|
||||
|
||||
enum eContainerType { eBag, eSeq, eAlt };
|
||||
nsresult InitContainer(nsIRDFResource* aContainerType, nsIRDFResource* aContainer);
|
||||
@ -448,6 +452,8 @@ RDFContentSinkImpl::HandleStartElement(const PRUnichar *aName,
|
||||
|
||||
nsresult rv = NS_ERROR_UNEXPECTED; // XXX
|
||||
|
||||
RegisterNamespaces(aAtts);
|
||||
|
||||
switch (mState) {
|
||||
case eRDFContentSinkState_InProlog:
|
||||
rv = OpenRDF(aName);
|
||||
@ -835,8 +841,7 @@ RDFContentSinkImpl::GetIdAboutAttribute(const PRUnichar** aAttributes,
|
||||
nsCOMPtr<nsIAtom> localName;
|
||||
for (; *aAttributes; aAttributes += 2) {
|
||||
const nsDependentSubstring& nameSpaceURI =
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName),
|
||||
aAttributes[1]);
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName));
|
||||
|
||||
// We'll accept either `ID' or `rdf:ID' (ibid with `about' or
|
||||
// `rdf:about') in the spirit of being liberal towards the
|
||||
@ -904,8 +909,7 @@ RDFContentSinkImpl::GetResourceAttribute(const PRUnichar** aAttributes,
|
||||
nsCOMPtr<nsIAtom> localName;
|
||||
for (; *aAttributes; aAttributes += 2) {
|
||||
const nsDependentSubstring& nameSpaceURI =
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName),
|
||||
aAttributes[1]);
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName));
|
||||
|
||||
// We'll accept `resource' or `rdf:resource', under the spirit
|
||||
// that we should be liberal towards the input that we
|
||||
@ -946,8 +950,7 @@ RDFContentSinkImpl::AddProperties(const PRUnichar** aAttributes,
|
||||
nsCOMPtr<nsIAtom> localName;
|
||||
for (; *aAttributes; aAttributes += 2) {
|
||||
const nsDependentSubstring& nameSpaceURI =
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName),
|
||||
aAttributes[1]);
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName));
|
||||
|
||||
// skip 'xmlns' directives, these are "meta" information
|
||||
if (nameSpaceURI.EqualsLiteral("http://www.w3.org/2000/xmlns/")) {
|
||||
@ -1001,8 +1004,7 @@ RDFContentSinkImpl::SetParseMode(const PRUnichar **aAttributes)
|
||||
nsCOMPtr<nsIAtom> localName;
|
||||
for (; *aAttributes; aAttributes += 2) {
|
||||
const nsDependentSubstring& nameSpaceURI =
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName),
|
||||
aAttributes[1]);
|
||||
SplitExpatName(aAttributes[0], getter_AddRefs(localName));
|
||||
|
||||
if (localName == kParseTypeAtom) {
|
||||
nsAutoString v(aAttributes[1]);
|
||||
@ -1270,13 +1272,48 @@ RDFContentSinkImpl::OpenValue(const PRUnichar* aName, const PRUnichar** aAttribu
|
||||
return OpenObject(aName,aAttributes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// namespace resolution
|
||||
void
|
||||
RDFContentSinkImpl::RegisterNamespaces(const PRUnichar **aAttributes)
|
||||
{
|
||||
nsCOMPtr<nsIRDFXMLSink> sink = do_QueryInterface(mDataSource);
|
||||
if (!sink) {
|
||||
return;
|
||||
}
|
||||
NS_NAMED_LITERAL_STRING(xmlns, "http://www.w3.org/2000/xmlns/");
|
||||
for (; *aAttributes; aAttributes += 2) {
|
||||
// check the namespace
|
||||
const PRUnichar* attr = aAttributes[0];
|
||||
const PRUnichar* xmlnsP = xmlns.BeginReading();
|
||||
while (*attr == *xmlnsP) {
|
||||
++attr;
|
||||
++xmlnsP;
|
||||
}
|
||||
if (*attr != 0xFFFF ||
|
||||
xmlnsP != xmlns.EndReading()) {
|
||||
continue;
|
||||
}
|
||||
// get the localname (or "xmlns" for the default namespace)
|
||||
const PRUnichar* endLocal = ++attr;
|
||||
while (*endLocal && *endLocal != 0xFFFF) {
|
||||
++endLocal;
|
||||
}
|
||||
nsDependentSubstring lname(attr, endLocal);
|
||||
nsCOMPtr<nsIAtom> preferred = do_GetAtom(lname);
|
||||
if (preferred == kXMLNSAtom) {
|
||||
preferred = nsnull;
|
||||
}
|
||||
sink->AddNameSpace(preferred, nsDependentString(aAttributes[1]));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Qualified name resolution
|
||||
|
||||
const nsDependentSubstring
|
||||
RDFContentSinkImpl::SplitExpatName(const PRUnichar *aExpatName,
|
||||
nsIAtom **aLocalName,
|
||||
const PRUnichar *aValue)
|
||||
nsIAtom **aLocalName)
|
||||
{
|
||||
/**
|
||||
* Expat can send the following:
|
||||
@ -1305,17 +1342,6 @@ RDFContentSinkImpl::SplitExpatName(const PRUnichar *aExpatName,
|
||||
const nsDependentSubstring& nameSpaceURI = Substring(aExpatName, uriEnd);
|
||||
*aLocalName = NS_NewAtom(NS_ConvertUTF16toUTF8(nameStart,
|
||||
pos - nameStart));
|
||||
|
||||
if (uriEnd != aExpatName && aValue &&
|
||||
nameSpaceURI.EqualsLiteral("http://www.w3.org/2000/xmlns/")) {
|
||||
nsCOMPtr<nsIAtom> prefix =
|
||||
*aLocalName == kXMLNSAtom ? nsnull : *aLocalName;
|
||||
nsCOMPtr<nsIRDFXMLSink> sink = do_QueryInterface(mDataSource);
|
||||
if (sink) {
|
||||
sink->AddNameSpace(prefix, nsDependentString(aValue));
|
||||
}
|
||||
}
|
||||
|
||||
return nameSpaceURI;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user