diff options
author | Chris Burdess <dog@bluezoo.org> | 2006-01-16 16:23:20 +0000 |
---|---|---|
committer | Chris Burdess <dog@bluezoo.org> | 2006-01-16 16:23:20 +0000 |
commit | 62ae4fb5ad2e0e8ef50b5eec08f076b8fb9b365a (patch) | |
tree | b3e7575dfd0730b9c8af853958167c41850dd0fd /gnu/xml/stream | |
parent | fb562e9a115a7077188a691fe2f53f47bee8d449 (diff) | |
download | classpath-62ae4fb5ad2e0e8ef50b5eec08f076b8fb9b365a.tar.gz |
2006-01-16 Chris Burdess <dog@gnu.org>
* gnu/xml/stream/XMLParser.java,
gnu/xml/stream/XMLStreamWriterImpl.java: Thoroughly check
XMLStreamWriter arguments for conformance to the XML specifications.
* gnu/xml/transform/Stylesheet.java,
gnu/xml/transform/Template.java,
gnu/xml/transform/TransformerImpl.java,
gnu/xml/xpath/LangFunction.java,
gnu/xml/xpath/Selector.java: better handling of template priorities;
fix indents when pretty-printing; recursive tests for xml:lang.
* gnu/xml/util/XHTMLWriter.java,
gnu/xml/util/XMLWriter.java: Deprecate old serializer classes.
Diffstat (limited to 'gnu/xml/stream')
-rw-r--r-- | gnu/xml/stream/XMLParser.java | 28 | ||||
-rw-r--r-- | gnu/xml/stream/XMLStreamWriterImpl.java | 331 |
2 files changed, 295 insertions, 64 deletions
diff --git a/gnu/xml/stream/XMLParser.java b/gnu/xml/stream/XMLParser.java index 6f10b9303..3545ff32d 100644 --- a/gnu/xml/stream/XMLParser.java +++ b/gnu/xml/stream/XMLParser.java @@ -2419,11 +2419,11 @@ public class XMLParser } else { - if (!isNameStartCharacter(cp[0])) + if (!isNameStartCharacter(cp[0], input.xml11)) error("malformed reference in entity value", value); for (int i = 1; i < cp.length; i++) { - if (!isNameCharacter(cp[i])) + if (!isNameCharacter(cp[i], input.xml11)) error("malformed reference in entity value", value); } } @@ -3469,13 +3469,13 @@ public class XMLParser int c = readCh(); if (isName) { - if (!isNameStartCharacter(c)) + if (!isNameStartCharacter(c, input.xml11)) error("not a name start character", "U+" + Integer.toHexString(c)); } else { - if (!isNameCharacter(c)) + if (!isNameCharacter(c, input.xml11)) error("not a name character", "U+" + Integer.toHexString(c)); } @@ -3510,7 +3510,7 @@ public class XMLParser reset(); return intern(buf.toString()); default: - if (!isNameCharacter(c)) + if (!isNameCharacter(c, input.xml11)) error("not a name character", "U+" + Integer.toHexString(c)); else @@ -3523,7 +3523,7 @@ public class XMLParser /** * Indicates whether the specified Unicode character is an XML 1.1 Char. */ - private boolean isXML11Char(int c) + public static boolean isXML11Char(int c) { return ((c >= 0x0001 && c <= 0xD7FF) || (c >= 0xE000 && c < 0xFFFD) || // NB exclude 0xfffd @@ -3534,7 +3534,7 @@ public class XMLParser * Indicates whether the specified Unicode character is an XML 1.1 * RestrictedChar. */ - private boolean isXML11RestrictedChar(int c) + public static boolean isXML11RestrictedChar(int c) { return ((c >= 0x0001 && c <= 0x0008) || (c >= 0x000B && c <= 0x000C) || @@ -3556,17 +3556,17 @@ public class XMLParser return false; if (isName) { - if (!isNameStartCharacter(cp[0])) + if (!isNameStartCharacter(cp[0], input.xml11)) return false; } else { - if (!isNameCharacter(cp[0])) + if (!isNameCharacter(cp[0], input.xml11)) return false; } for (int i = 1; i < cp.length; i++) { - if (!isNameCharacter(cp[i])) + if (!isNameCharacter(cp[i], input.xml11)) return false; } return true; @@ -3581,9 +3581,9 @@ public class XMLParser * Indicates whether the specified Unicode character is a Name start * character. */ - private boolean isNameStartCharacter(int c) + public static boolean isNameStartCharacter(int c, boolean xml11) { - if (input.xml11) + if (xml11) return ((c >= 0x0041 && c <= 0x005a) || (c >= 0x0061 && c <= 0x007a) || c == 0x3a | @@ -3608,9 +3608,9 @@ public class XMLParser * Indicates whether the specified Unicode character is a Name non-initial * character. */ - private boolean isNameCharacter(int c) + public static boolean isNameCharacter(int c, boolean xml11) { - if (input.xml11) + if (xml11) return ((c >= 0x0041 && c <= 0x005a) || (c >= 0x0061 && c <= 0x007a) || (c >= 0x0030 && c <= 0x0039) || diff --git a/gnu/xml/stream/XMLStreamWriterImpl.java b/gnu/xml/stream/XMLStreamWriterImpl.java index 6157296c6..291016e67 100644 --- a/gnu/xml/stream/XMLStreamWriterImpl.java +++ b/gnu/xml/stream/XMLStreamWriterImpl.java @@ -104,6 +104,9 @@ public class XMLStreamWriterImpl private NamespaceSupport namespaces; private int count = 0; + private boolean xml11; + private boolean hasXML11RestrictedChars; + /** * Constructor. * @see #writer @@ -145,6 +148,9 @@ public class XMLStreamWriterImpl { try { + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + endStartElement(); namespaces.pushContext(); @@ -167,6 +173,11 @@ public class XMLStreamWriterImpl { try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + endStartElement(); namespaces.pushContext(); @@ -190,7 +201,7 @@ public class XMLStreamWriterImpl inStartElement = true; if (!isDeclared) { - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } elements.addLast(new String[] { prefix, localName }); @@ -229,6 +240,13 @@ public class XMLStreamWriterImpl { try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (prefix != null && !isNCName(prefix)) + throw new IllegalArgumentException("illegal NCName: " + prefix); + if (!isNCName(localName)) + throw new IllegalArgumentException("illegal NCName: " + localName); + endStartElement(); namespaces.pushContext(); @@ -243,7 +261,7 @@ public class XMLStreamWriterImpl writer.write(localName); if (prefixDefaulting && !isCurrent) { - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } elements.addLast(new String[] { prefix, localName }); @@ -343,11 +361,19 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + if (!isChars(value)) + throw new IllegalArgumentException("illegal character: " + value); + writer.write(' '); writer.write(localName); writer.write('='); writer.write('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -366,11 +392,20 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (prefix != null && !isNCName(prefix)) + throw new IllegalArgumentException("illegal NCName: " + prefix); + if (!isNCName(localName)) + throw new IllegalArgumentException("illegal NCName: " + localName); + if (!isChars(value)) + throw new IllegalArgumentException("illegal character: " + value); + String currentPrefix = getPrefix(namespaceURI); if (currentPrefix == null) { if (prefixDefaulting) - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); else throw new XMLStreamException("namespace " + namespaceURI + " is not bound"); @@ -388,7 +423,10 @@ public class XMLStreamWriterImpl writer.write(localName); writer.write('='); writer.write('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -407,13 +445,20 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + if (!isChars(value)) + throw new IllegalArgumentException("illegal character: " + value); + String prefix = getPrefix(namespaceURI); if (prefix == null) { if (prefixDefaulting) { prefix = XMLConstants.DEFAULT_NS_PREFIX; - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } else throw new XMLStreamException("namespace " + namespaceURI + @@ -428,7 +473,10 @@ public class XMLStreamWriterImpl writer.write(localName); writer.write('='); writer.write('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -446,6 +494,25 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (!isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (!isNCName(prefix)) + throw new IllegalArgumentException("illegal NCName: " + prefix); + } + catch (IOException e) + { + XMLStreamException e2 = new XMLStreamException(e); + e2.initCause(e); + throw e2; + } + writeNamespaceImpl(prefix, namespaceURI); + } + + private void writeNamespaceImpl(String prefix, String namespaceURI) + throws XMLStreamException + { + try + { if (prefix == null) prefix = XMLConstants.DEFAULT_NS_PREFIX; @@ -474,21 +541,41 @@ public class XMLStreamWriterImpl public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException { - writeNamespace(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI); + if (!inStartElement) + throw new IllegalStateException(); + if (!isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + writeNamespaceImpl(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI); } public void writeComment(String data) throws XMLStreamException { + if (data == null) + return; try { + if (!isChars(data)) + throw new IllegalArgumentException("illegal XML character: " + data); + if (data.indexOf("--") != -1) + throw new IllegalArgumentException("illegal comment: " + data); + endStartElement(); - if (data != null && data.indexOf("--") != -1) - throw new IllegalArgumentException(data); - writer.write("<!--"); - if (data != null) + if (hasXML11RestrictedChars) + { + int[] seq = UnicodeReader.toCodePointArray(data); + for (int i = 0; i < seq.length; i++) + { + int c = seq[i]; + if (XMLParser.isXML11RestrictedChar(c)) + writer.write("&#x" + Integer.toHexString(c) + ";"); + else + writer.write(Character.toChars(i)); + } + } + else writer.write(data); writer.write("-->"); } @@ -511,6 +598,11 @@ public class XMLStreamWriterImpl { try { + if (!isName(target) || "xml".equalsIgnoreCase(target)) + throw new IllegalArgumentException("illegal PITarget: " + target); + if (data != null && !isChars(data)) + throw new IllegalArgumentException("illegal XML character: " + data); + endStartElement(); writer.write('<'); @@ -519,7 +611,20 @@ public class XMLStreamWriterImpl if (data != null) { writer.write(' '); - writer.write(data); + if (hasXML11RestrictedChars) + { + int[] seq = UnicodeReader.toCodePointArray(data); + for (int i = 0; i < seq.length; i++) + { + int c = seq[i]; + if (XMLParser.isXML11RestrictedChar(c)) + writer.write("&#x" + Integer.toHexString(c) + ";"); + else + writer.write(Character.toChars(i)); + } + } + else + writer.write(data); } writer.write('?'); writer.write('>'); @@ -537,10 +642,12 @@ public class XMLStreamWriterImpl { try { - endStartElement(); - + if (!isChars(data) || hasXML11RestrictedChars) + throw new IllegalArgumentException("illegal XML character: " + data); if (data.indexOf("]]") != -1) - throw new IllegalArgumentException(data); + throw new IllegalArgumentException("illegal CDATA section: " + data); + + endStartElement(); writer.write("<![CDATA["); writer.write(data); @@ -557,8 +664,12 @@ public class XMLStreamWriterImpl public void writeDTD(String dtd) throws XMLStreamException { + // Really thoroughly pointless method... try { + if (!isName(dtd)) + throw new IllegalArgumentException("illegal Name: " + dtd); + writer.write("<!DOCTYPE "); writer.write(dtd); writer.write('>'); @@ -576,6 +687,9 @@ public class XMLStreamWriterImpl { try { + if (!isName(name)) + throw new IllegalArgumentException("illegal Name: " + name); + endStartElement(); writer.write('&'); @@ -607,6 +721,8 @@ public class XMLStreamWriterImpl { if (version == null) version = "1.0"; + else if ("1.1".equals(version)) + xml11 = true; encoding = this.encoding; // YES: the parameter must be ignored if (encoding == null) encoding = "UTF-8"; @@ -632,11 +748,18 @@ public class XMLStreamWriterImpl public void writeCharacters(String text) throws XMLStreamException { + if (text == null) + return; try { + if (!isChars(text)) + throw new IllegalArgumentException("illegal XML character: " + text); + endStartElement(); - if (text != null) + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(text, false); + else writeEncoded(text, false); } catch (IOException e) @@ -650,39 +773,7 @@ public class XMLStreamWriterImpl public void writeCharacters(char[] text, int start, int len) throws XMLStreamException { - try - { - endStartElement(); - - int end = start + len; - len = 0; - for (int i = start; i < end; i++) - { - char c = text[i]; - if (c == '<' || c == '>' || c == '&') - { - writer.write(text, start, len); - if (c == '<') - writer.write("<"); - else if (c == '>') - writer.write(">"); - else - writer.write("&"); - start = i + 1; - len = 0; - } - else - len++; - } - if (len > 0) - writer.write(text, start, len); - } - catch (IOException e) - { - XMLStreamException e2 = new XMLStreamException(e); - e2.initCause(e); - throw e2; - } + writeCharacters(new String(text, start, len)); } public String getPrefix(String uri) @@ -697,6 +788,19 @@ public class XMLStreamWriterImpl public void setPrefix(String prefix, String uri) throws XMLStreamException { + try + { + if (!isURI(uri)) + throw new IllegalArgumentException("illegal URI: " + uri); + if (!isNCName(prefix)) + throw new IllegalArgumentException("illegal NCName: " + prefix); + } + catch (IOException e) + { + XMLStreamException e2 = new XMLStreamException(e); + e2.initCause(e); + throw e2; + } if (!namespaces.declarePrefix(prefix, uri)) throw new XMLStreamException("illegal prefix " + prefix); } @@ -704,6 +808,8 @@ public class XMLStreamWriterImpl public void setDefaultNamespace(String uri) throws XMLStreamException { + if (!isURI(uri)) + throw new IllegalArgumentException("illegal URI: " + uri); if (!namespaces.declarePrefix(XMLConstants.DEFAULT_NS_PREFIX, uri)) throw new XMLStreamException("illegal default namespace prefix"); } @@ -769,6 +875,131 @@ public class XMLStreamWriterImpl if (len > 0) writer.write(chars, start, len); } + + /** + * Writes the specified text, in the knowledge that some of the + * characters are XML 1.1 restricted characters. + */ + private void writeEncodedWithRestrictedChars(String text, boolean inAttr) + throws IOException + { + int[] seq = UnicodeReader.toCodePointArray(text); + for (int i = 0; i < seq.length; i++) + { + int c = seq[i]; + switch (c) + { + case 0x3c: // '<' + writer.write("<"); + break; + case 0x3e: // '>' + writer.write(">"); + break; + case 0x26: // '&' + writer.write("&"); + break; + case 0x22: // '"' + if (inAttr) + writer.write("""); + else + writer.write(c); + break; + case 0x27: // '\'' + if (inAttr) + writer.write("'"); + else + writer.write(c); + break; + default: + if (XMLParser.isXML11RestrictedChar(c)) + writer.write("&#x" + Integer.toHexString(c) + ";"); + else + { + char[] chars = Character.toChars(c); + writer.write(chars, 0, chars.length); + } + } + } + } + + private boolean isName(String text) + throws IOException + { + if (text == null) + return false; + int[] seq = UnicodeReader.toCodePointArray(text); + if (seq.length < 1) + return false; + if (!XMLParser.isNameStartCharacter(seq[0], xml11)) + return false; + for (int i = 1; i < seq.length; i++) + { + if (!XMLParser.isNameCharacter(seq[i], xml11)) + return false; + } + return true; + } + + private boolean isNCName(String text) + throws IOException + { + if (text == null) + return false; + int[] seq = UnicodeReader.toCodePointArray(text); + if (seq.length < 1) + return false; + if (!XMLParser.isNameStartCharacter(seq[0], xml11) || seq[0] == 0x3a) + return false; + for (int i = 1; i < seq.length; i++) + { + if (!XMLParser.isNameCharacter(seq[i], xml11) || seq[i] == 0x3a) + return false; + } + return true; + } + + private boolean isChars(String text) + throws IOException + { + if (text == null) + return false; + int[] seq = UnicodeReader.toCodePointArray(text); + hasXML11RestrictedChars = false; + if (xml11) + { + for (int i = 0; i < seq.length; i++) + { + if (!XMLParser.isXML11Char(seq[i])) + return false; + if (XMLParser.isXML11RestrictedChar(seq[i])) + hasXML11RestrictedChars = true; + } + } + else + { + for (int i = 0; i < seq.length; i++) + { + if (!XMLParser.isChar(seq[i])) + return false; + } + } + return true; + } + + private boolean isURI(String text) + { + if (text == null) + return false; + char[] chars = text.toCharArray(); + if (chars.length < 1) + return false; + for (int i = 0; i < chars.length; i++) + { + if (chars[i] < 0x20 || chars[i] >= 0x7f) + return false; + } + return true; + } } |