aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net
diff options
context:
space:
mode:
authorJiri Vanek <[email protected]>2013-06-21 12:15:03 +0200
committerJiri Vanek <[email protected]>2013-06-21 12:15:03 +0200
commitda8ec0b9cba22448fbb5b599bff3e1f5fb8c0bf7 (patch)
treee3cd2c82fd0eff3b9d9c95b4f67fac27d7d519bc /netx/net
parent70371886c351800a6fad9bad17777179af2d8584 (diff)
Added tagsup (optional dependence) as sanitizer for (possibly) invalid xml files
Diffstat (limited to 'netx/net')
-rw-r--r--netx/net/sourceforge/jnlp/JNLPCreator.java4
-rw-r--r--netx/net/sourceforge/jnlp/JNLPFile.java72
-rw-r--r--netx/net/sourceforge/jnlp/Launcher.java10
-rw-r--r--netx/net/sourceforge/jnlp/MalformedXMLParser.java123
-rw-r--r--netx/net/sourceforge/jnlp/Parser.java155
-rw-r--r--netx/net/sourceforge/jnlp/ParserSettings.java27
-rw-r--r--netx/net/sourceforge/jnlp/PluginBridge.java5
-rw-r--r--netx/net/sourceforge/jnlp/XmlParser.java183
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages.properties1
-rw-r--r--netx/net/sourceforge/jnlp/runtime/Boot.java14
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java7
11 files changed, 427 insertions, 174 deletions
diff --git a/netx/net/sourceforge/jnlp/JNLPCreator.java b/netx/net/sourceforge/jnlp/JNLPCreator.java
index ca1b94b..4ece458 100644
--- a/netx/net/sourceforge/jnlp/JNLPCreator.java
+++ b/netx/net/sourceforge/jnlp/JNLPCreator.java
@@ -28,8 +28,8 @@ import java.net.URL;
import net.sourceforge.jnlp.cache.UpdatePolicy;
public class JNLPCreator {
- public JNLPFile create(URL location, Version version, boolean strict,
+ public JNLPFile create(URL location, Version version, ParserSettings settings,
UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException {
- return new JNLPFile(location, version, strict, policy, forceCodebase);
+ return new JNLPFile(location, version, settings, policy, forceCodebase);
}
}
diff --git a/netx/net/sourceforge/jnlp/JNLPFile.java b/netx/net/sourceforge/jnlp/JNLPFile.java
index 26bc806..f8c953e 100644
--- a/netx/net/sourceforge/jnlp/JNLPFile.java
+++ b/netx/net/sourceforge/jnlp/JNLPFile.java
@@ -67,6 +67,9 @@ public class JNLPFile {
/** the network location of this JNLP file */
protected URL fileLocation;
+ /** the ParserSettings which were used to parse this file */
+ protected ParserSettings parserSettings = null;
+
/** A key that uniquely identifies connected instances (main jnlp+ext) */
protected String uniqueKey = null;
@@ -145,7 +148,7 @@ public class JNLPFile {
* @throws ParseException if the JNLP file was invalid
*/
public JNLPFile(URL location) throws IOException, ParseException {
- this(location, false); // not strict
+ this(location, new ParserSettings());
}
/**
@@ -153,12 +156,12 @@ public class JNLPFile {
* default policy.
*
* @param location the location of the JNLP file
- * @param strict whether to enforce the spec when
+ * @param settings the parser settings to use while parsing the file
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(URL location, boolean strict) throws IOException, ParseException {
- this(location, (Version) null, strict);
+ public JNLPFile(URL location, ParserSettings settings) throws IOException, ParseException {
+ this(location, (Version) null, settings);
}
/**
@@ -167,12 +170,12 @@ public class JNLPFile {
*
* @param location the location of the JNLP file
* @param version the version of the JNLP file
- * @param strict whether to enforce the spec when
+ * @param settings the parser settings to use while parsing the file
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(URL location, Version version, boolean strict) throws IOException, ParseException {
- this(location, version, strict, JNLPRuntime.getDefaultUpdatePolicy());
+ public JNLPFile(URL location, Version version, ParserSettings settings) throws IOException, ParseException {
+ this(location, version, settings, JNLPRuntime.getDefaultUpdatePolicy());
}
/**
@@ -186,8 +189,8 @@ public class JNLPFile {
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {
- this(location, version, strict, policy, null);
+ public JNLPFile(URL location, Version version, ParserSettings settings, UpdatePolicy policy) throws IOException, ParseException {
+ this(location, version, settings, policy, null);
}
/**
@@ -196,15 +199,16 @@ public class JNLPFile {
*
* @param location the location of the JNLP file
* @param version the version of the JNLP file
- * @param strict whether to enforce the spec when
+ * @param settings the parser settings to use while parsing the file
* @param policy the update policy
* @param forceCodebase codebase to use if not specified in JNLP file.
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- protected JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException {
- Node root = Parser.getRootNode(openURL(location, version, policy));
- parse(root, strict, location, forceCodebase);
+ protected JNLPFile(URL location, Version version, ParserSettings settings, UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException {
+ InputStream input = openURL(location, version, policy);
+ this.parserSettings = settings;
+ parse(input, location, forceCodebase);
//Downloads the original jnlp file into the cache if possible
//(i.e. If the jnlp file being launched exist locally, but it
@@ -231,13 +235,13 @@ public class JNLPFile {
* @param location the location of the JNLP file
* @param uniqueKey A string that uniquely identifies connected instances
* @param version the version of the JNLP file
- * @param strict whether to enforce the spec when
+ * @param settings the parser settings to use while parsing the file
* @param policy the update policy
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(URL location, String uniqueKey, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {
- this(location, version, strict, policy);
+ public JNLPFile(URL location, String uniqueKey, Version version, ParserSettings settings, UpdatePolicy policy) throws IOException, ParseException {
+ this(location, version, settings, policy);
this.uniqueKey = uniqueKey;
if (JNLPRuntime.isDebug())
@@ -250,8 +254,9 @@ public class JNLPFile {
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(InputStream input, boolean strict) throws ParseException {
- this(input, null, strict);
+ public JNLPFile(InputStream input, ParserSettings settings) throws ParseException {
+ this.parserSettings = settings;
+ parse(input, null, null);
}
/**
@@ -263,22 +268,11 @@ public class JNLPFile {
* @throws IOException if an IO exception occurred
* @throws ParseException if the JNLP file was invalid
*/
- public JNLPFile(InputStream input, URL codebase, boolean strict) throws ParseException {
- parse(Parser.getRootNode(input), strict, null, codebase);
+ public JNLPFile(InputStream input, URL codebase, ParserSettings settings) throws ParseException {
+ this.parserSettings = settings;
+ parse(input, null, codebase);
}
- /**
- * Create a JNLPFile from a character stream.
- *
- * @param input the stream
- * @param strict whether to enforce the spec when
- * @throws IOException if an IO exception occurred
- * @throws ParseException if the JNLP file was invalid
- */
- private JNLPFile(Reader input, boolean strict) throws ParseException {
- // todo: now that we are using NanoXML we can use a Reader
- //parse(Parser.getRootNode(input), strict, null);
- }
/**
* Open the jnlp file URL from the cache if there, otherwise
@@ -338,6 +332,13 @@ public class JNLPFile {
}
/**
+ * Returns the ParserSettings that was used to parse this file
+ */
+ public ParserSettings getParserSettings() {
+ return parserSettings;
+ }
+
+ /**
* Returns the JNLP file's version.
*/
public Version getFileVersion() {
@@ -685,15 +686,16 @@ public class JNLPFile {
* from the constructor.
*
* @param root the root node
- * @param strict whether to enforce the spec when
+ * @param settings the parser settings to use while parsing the file
* @param location the file location or null
*/
- private void parse(Node root, boolean strict, URL location, URL forceCodebase) throws ParseException {
+ private void parse(InputStream input, URL location, URL forceCodebase) throws ParseException {
try {
//if (location != null)
// location = new URL(location, "."); // remove filename
- Parser parser = new Parser(this, location, root, strict, true, forceCodebase); // true == allow extensions
+ Node root = Parser.getRootNode(input, parserSettings);
+ Parser parser = new Parser(this, location, root, parserSettings, forceCodebase); // true == allow extensions
// JNLP tag information
specVersion = parser.getSpecVersion();
diff --git a/netx/net/sourceforge/jnlp/Launcher.java b/netx/net/sourceforge/jnlp/Launcher.java
index 11ca09f..efb1915 100644
--- a/netx/net/sourceforge/jnlp/Launcher.java
+++ b/netx/net/sourceforge/jnlp/Launcher.java
@@ -477,12 +477,12 @@ public class Launcher {
try {
JNLPFile file = null;
- file = new JNLPFile(location, parserSettings.isStrict());
+ file = new JNLPFile(location, parserSettings);
if (fromSource) {
// Launches the jnlp file where this file originated.
if (file.getSourceLocation() != null) {
- file = new JNLPFile(file.getSourceLocation(), parserSettings.isStrict());
+ file = new JNLPFile(file.getSourceLocation(), parserSettings);
}
}
return file;
@@ -504,9 +504,11 @@ public class Launcher {
JNLPFile file = null;
try {
- file = new JNLPFile(location, (Version) null, true, updatePolicy); // strict
+ ParserSettings settings = new ParserSettings(true, true, false);
+ file = new JNLPFile(location, (Version) null, settings, updatePolicy); // strict
} catch (ParseException ex) {
- file = new JNLPFile(location, (Version) null, false, updatePolicy);
+ ParserSettings settings = new ParserSettings(false, true, true);
+ file = new JNLPFile(location, (Version) null, settings, updatePolicy);
// only here if strict failed but lax did not fail
LaunchException lex =
diff --git a/netx/net/sourceforge/jnlp/MalformedXMLParser.java b/netx/net/sourceforge/jnlp/MalformedXMLParser.java
new file mode 100644
index 0000000..04cfe19
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/MalformedXMLParser.java
@@ -0,0 +1,123 @@
+/*
+ Copyright (C) 2013 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+import org.ccil.cowan.tagsoup.HTMLSchema;
+import org.ccil.cowan.tagsoup.Parser;
+import org.ccil.cowan.tagsoup.XMLWriter;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * An specialized {@link XMLParser} that uses TagSoup[1] to parse
+ * malformed XML
+ *
+ * Used by net.sourceforge.jnlp.Parser
+ *
+ * [1] http://home.ccil.org/~cowan/XML/tagsoup/
+ */
+public class MalformedXMLParser extends XMLParser {
+
+ /**
+ * Parses the data from an {@link InputStream} to create a XML tree.
+ * Returns a {@link Node} representing the root of the tree.
+ *
+ * @param input the {@link InputStream} to read data from
+ * @throws ParseException if an exception occurs while parsing the input
+ */
+ @Override
+ public Node getRootNode(InputStream input) throws ParseException {
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Using MalformedXMLParser");
+ }
+ InputStream xmlInput = xmlizeInputStream(input);
+ return super.getRootNode(xmlInput);
+ }
+
+ /**
+ * Reads malformed XML from the InputStream original and returns a new
+ * InputStream which can be used to read a well-formed version of the input
+ *
+ * @param original
+ * @return an {@link InputStream} which can be used to read a well-formed
+ * version of the input XML
+ * @throws ParseException
+ */
+ private InputStream xmlizeInputStream(InputStream original) throws ParseException {
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ HTMLSchema schema = new HTMLSchema();
+ XMLReader reader = new Parser();
+
+ //TODO walk through the javadoc and tune more settings
+ //see tagsoup javadoc for details
+ reader.setProperty(Parser.schemaProperty, schema);
+ reader.setFeature(Parser.bogonsEmptyFeature, false);
+ reader.setFeature(Parser.ignorableWhitespaceFeature, true);
+ reader.setFeature(Parser.ignoreBogonsFeature, false);
+
+ Writer writeger = new OutputStreamWriter(out);
+ XMLWriter x = new XMLWriter(writeger);
+
+ reader.setContentHandler(x);
+
+ InputSource s = new InputSource(original);
+
+ reader.parse(s);
+ return new ByteArrayInputStream(out.toByteArray());
+ } catch (SAXException e) {
+ throw new ParseException(R("PBadXML"), e);
+ } catch (IOException e) {
+ throw new ParseException(R("PBadXML"), e);
+ }
+
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/Parser.java b/netx/net/sourceforge/jnlp/Parser.java
index a825a5b..efa6bcd 100644
--- a/netx/net/sourceforge/jnlp/Parser.java
+++ b/netx/net/sourceforge/jnlp/Parser.java
@@ -1,5 +1,5 @@
// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
-// Copyright (C) 2012 Red Hat, Inc.
+// Copyright (C) 2009-2013 Red Hat, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -20,16 +20,14 @@ package net.sourceforge.jnlp;
import static net.sourceforge.jnlp.runtime.Translator.R;
import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.*;
import java.util.*;
-//import javax.xml.parsers.*; // commented to use right Node
-//import org.w3c.dom.*; // class for using Tiny XML | NanoXML
-//import org.xml.sax.*;
-//import gd.xml.tiny.*;
+
import net.sourceforge.jnlp.UpdateDesc.Check;
import net.sourceforge.jnlp.UpdateDesc.Policy;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
-import net.sourceforge.nanoxml.*;
/**
* Contains methods to parse an XML document into a JNLPFile.
@@ -106,12 +104,11 @@ class Parser {
* @param file the (uninitialized) file reference
* @param base if codebase is not specified, a default base for relative URLs
* @param root the root node
- * @param strict whether to enforce strict compliance with the JNLP spec
- * @param allowExtensions whether to allow extensions to the JNLP spec
+ * @param settings the parser settings to use when parsing the JNLP file
* @throws ParseException if the JNLP file is invalid
*/
- public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions) throws ParseException {
- this(file, base, root, strict, allowExtensions, null);
+ public Parser(JNLPFile file, URL base, Node root, ParserSettings settings) throws ParseException {
+ this(file, base, root, settings, null);
}
/**
@@ -126,16 +123,15 @@ class Parser {
* @param file the (uninitialized) file reference
* @param base if codebase is not specified, a default base for relative URLs
* @param root the root node
- * @param strict whether to enforce strict compliance with the JNLP spec
- * @param allowExtensions whether to allow extensions to the JNLP spec
+ * @param settings the parser settings to use when parsing the JNLP file
* @param codebase codebase to use if we did not parse one from JNLP file.
* @throws ParseException if the JNLP file is invalid
*/
- public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions, URL codebase) throws ParseException {
+ public Parser(JNLPFile file, URL base, Node root, ParserSettings settings, URL codebase) throws ParseException {
this.file = file;
this.root = root;
- this.strict = strict;
- this.allowExtensions = allowExtensions;
+ this.strict = settings.isStrict();
+ this.allowExtensions = settings.isExtensionAllowed();
// ensure it's a JNLP node
if (root == null || !root.getNodeName().equals("jnlp"))
@@ -1265,116 +1261,33 @@ class Parser {
*
* @throws ParseException if the JNLP file is invalid
*/
- public static Node getRootNode(InputStream input) throws ParseException {
- try {
- /* SAX
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setValidating(false);
- factory.setNamespaceAware(true);
- DocumentBuilder builder = factory.newDocumentBuilder();
- builder.setErrorHandler(errorHandler);
-
- Document doc = builder.parse(input);
- return doc.getDocumentElement();
- */
-
- /* TINY
- Node document = new Node(TinyParser.parseXML(input));
- Node jnlpNode = getChildNode(document, "jnlp"); // skip comments
- */
-
- //A BufferedInputStream is used to allow marking and reseting
- //of a stream.
- BufferedInputStream bs = new BufferedInputStream(input);
-
- /* NANO */
- final XMLElement xml = new XMLElement();
- final PipedInputStream pin = new PipedInputStream();
- final PipedOutputStream pout = new PipedOutputStream(pin);
- final InputStreamReader isr = new InputStreamReader(bs, getEncoding(bs));
- // Clean the jnlp xml file of all comments before passing
- // it to the parser.
- new Thread(
- new Runnable() {
- public void run() {
- (new XMLElement()).sanitizeInput(isr, pout);
- try {
- pout.close();
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- }
- }).start();
- xml.parseFromReader(new InputStreamReader(pin));
- Node jnlpNode = new Node(xml);
- return jnlpNode;
- } catch (Exception ex) {
- throw new ParseException(R("PBadXML"), ex);
+ public static Node getRootNode(InputStream input, ParserSettings settings) throws ParseException {
+ String className = null;
+ if (settings.isMalformedXmlAllowed()) {
+ className = "net.sourceforge.jnlp.MalformedXMLParser";
+ } else {
+ className = "net.sourceforge.jnlp.XMLParser";
}
- }
- /**
- * Returns the name of the encoding used in this InputStream.
- *
- * @param input the InputStream
- * @return a String representation of encoding
- */
- private static String getEncoding(InputStream input) throws IOException {
- //Fixme: This only recognizes UTF-8, UTF-16, and
- //UTF-32, which is enough to parse the prolog portion of xml to
- //find out the exact encoding (if it exists). The reason being
- //there could be other encodings, such as ISO 8859 which is 8-bits
- //but it supports latin characters.
- //So what needs to be done is to parse the prolog and retrieve
- //the exact encoding from it.
-
- int[] s = new int[4];
- String encoding = "UTF-8";
-
- //Determine what the first four bytes are and store
- //them into an int array.
- input.mark(4);
- for (int i = 0; i < 4; i++) {
- s[i] = input.read();
- }
- input.reset();
-
- //Set the encoding base on what the first four bytes of the
- //inputstream turn out to be (following the information from
- //www.w3.org/TR/REC-xml/#sec-guessing).
- if (s[0] == 255) {
- if (s[1] == 254) {
- if (s[2] != 0 || s[3] != 0) {
- encoding = "UnicodeLittle";
- } else {
- encoding = "X-UTF-32LE-BOM";
- }
+ try {
+ Class<?> klass = null;
+ try {
+ klass = Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ klass = Class.forName("net.sourceforge.jnlp.XMLParser");
}
- } else if (s[0] == 254 && s[1] == 255 && (s[2] != 0 ||
- s[3] != 0)) {
- encoding = "UTF-16";
-
- } else if (s[0] == 0 && s[1] == 0 && s[2] == 254 &&
- s[3] == 255) {
- encoding = "X-UTF-32BE-BOM";
-
- } else if (s[0] == 0 && s[1] == 0 && s[2] == 0 &&
- s[3] == 60) {
- encoding = "UTF-32BE";
-
- } else if (s[0] == 60 && s[1] == 0 && s[2] == 0 &&
- s[3] == 0) {
- encoding = "UTF-32LE";
-
- } else if (s[0] == 0 && s[1] == 60 && s[2] == 0 &&
- s[3] == 63) {
- encoding = "UTF-16BE";
- } else if (s[0] == 60 && s[1] == 0 && s[2] == 63 &&
- s[3] == 0) {
- encoding = "UTF-16LE";
- }
+ Object instance = klass.newInstance();
+ Method m = klass.getMethod("getRootNode", InputStream.class);
- return encoding;
+ return (Node) m.invoke(instance, input);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof ParseException) {
+ throw (ParseException)(e.getCause());
+ }
+ throw new ParseException(R("PBadXML"), e);
+ } catch (Exception e) {
+ throw new ParseException(R("PBadXML"), e);
+ }
}
}
diff --git a/netx/net/sourceforge/jnlp/ParserSettings.java b/netx/net/sourceforge/jnlp/ParserSettings.java
index b0a69e3..de781d9 100644
--- a/netx/net/sourceforge/jnlp/ParserSettings.java
+++ b/netx/net/sourceforge/jnlp/ParserSettings.java
@@ -35,7 +35,6 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
*/
-
package net.sourceforge.jnlp;
/**
@@ -46,16 +45,34 @@ package net.sourceforge.jnlp;
public class ParserSettings {
private final boolean isStrict;
+ private final boolean extensionAllowed;
+ private final boolean malformedXmlAllowed;
+ /** Create a new ParserSettings with the defautl parser settings */
public ParserSettings() {
- isStrict = false;
+ this(false, true, true);
+ }
+
+ /** Create a new ParserSettings object */
+ public ParserSettings(boolean strict, boolean extensionAllowed, boolean malformedXmlAllowed) {
+ this.isStrict = strict;
+ this.extensionAllowed = extensionAllowed;
+ this.malformedXmlAllowed = malformedXmlAllowed;
}
- public ParserSettings(boolean strict) {
- isStrict = strict;
+ /** @return true if extensions to the spec are allowed */
+ public boolean isExtensionAllowed() {
+ return extensionAllowed;
}
+ /** @return true if parsing malformed xml is allowed */
+ public boolean isMalformedXmlAllowed() {
+ return malformedXmlAllowed;
+ }
+
+ /** @return true if strict parsing mode is to be used */
public boolean isStrict() {
return isStrict;
}
-}
+
+} \ No newline at end of file
diff --git a/netx/net/sourceforge/jnlp/PluginBridge.java b/netx/net/sourceforge/jnlp/PluginBridge.java
index d069479..9163404 100644
--- a/netx/net/sourceforge/jnlp/PluginBridge.java
+++ b/netx/net/sourceforge/jnlp/PluginBridge.java
@@ -96,14 +96,15 @@ public class PluginBridge extends JNLPFile {
try {
// Use codeBase as the context for the URL. If jnlp_href's
// value is a complete URL, it will replace codeBase's context.
+ ParserSettings defaultSettings = new ParserSettings();
URL jnlp = new URL(codeBase, params.getJNLPHref());
JNLPFile jnlpFile = null;
if (params.getJNLPEmbedded() != null) {
InputStream jnlpInputStream = new ByteArrayInputStream(decodeBase64String(params.getJNLPEmbedded()));
- jnlpFile = new JNLPFile(jnlpInputStream, codeBase, false);
+ jnlpFile = new JNLPFile(jnlpInputStream, codeBase, defaultSettings);
} else {
- jnlpFile = jnlpCreator.create(jnlp, null, false, JNLPRuntime.getDefaultUpdatePolicy(), codeBase);
+ jnlpFile = jnlpCreator.create(jnlp, null, defaultSettings, JNLPRuntime.getDefaultUpdatePolicy(), codeBase);
}
if (jnlpFile.isApplet())
diff --git a/netx/net/sourceforge/jnlp/XmlParser.java b/netx/net/sourceforge/jnlp/XmlParser.java
new file mode 100644
index 0000000..05080ea
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/XmlParser.java
@@ -0,0 +1,183 @@
+/*
+ Copyright (C) 2013 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import net.sourceforge.nanoxml.XMLElement;
+
+//import javax.xml.parsers.*; // commented to use right Node
+//import org.w3c.dom.*; // class for using Tiny XML | NanoXML
+//import org.xml.sax.*;
+//import gd.xml.tiny.*;
+
+/**
+ * A gateway to the actual implementation of the parsers.
+ *
+ * Used by net.sourceforge.jnlp.Parser
+ */
+class XMLParser {
+
+ /**
+ * Parses input from an InputStream and returns a Node representing the
+ * root of the parse tree.
+ *
+ * @param input the {@link InputStream} containing the XML
+ * @return a {@link Node} representing the root of the parsed XML
+ * @throws ParseException
+ */
+ public Node getRootNode(InputStream input) throws ParseException {
+
+ try {
+ /* SAX
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ builder.setErrorHandler(errorHandler);
+
+ Document doc = builder.parse(input);
+ return doc.getDocumentElement();
+ */
+
+ /* TINY
+ Node document = new Node(TinyParser.parseXML(input));
+ Node jnlpNode = getChildNode(document, "jnlp"); // skip comments
+ */
+
+ //A BufferedInputStream is used to allow marking and reseting
+ //of a stream.
+ BufferedInputStream bs = new BufferedInputStream(input);
+
+ /* NANO */
+ final XMLElement xml = new XMLElement();
+ final PipedInputStream pin = new PipedInputStream();
+ final PipedOutputStream pout = new PipedOutputStream(pin);
+ final InputStreamReader isr = new InputStreamReader(bs, getEncoding(bs));
+ // Clean the jnlp xml file of all comments before passing
+ // it to the parser.
+ new Thread(
+ new Runnable() {
+ public void run() {
+ (new XMLElement()).sanitizeInput(isr, pout);
+ try {
+ pout.close();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ }).start();
+ xml.parseFromReader(new InputStreamReader(pin));
+ Node jnlpNode = new Node(xml);
+ return jnlpNode;
+ } catch (Exception ex) {
+ throw new ParseException(R("PBadXML"), ex);
+ }
+ }
+
+ /**
+ * Returns the name of the encoding used in this InputStream.
+ *
+ * @param input the InputStream
+ * @return a String representation of encoding
+ */
+ private static String getEncoding(InputStream input) throws IOException {
+ //Fixme: This only recognizes UTF-8, UTF-16, and
+ //UTF-32, which is enough to parse the prolog portion of xml to
+ //find out the exact encoding (if it exists). The reason being
+ //there could be other encodings, such as ISO 8859 which is 8-bits
+ //but it supports latin characters.
+ //So what needs to be done is to parse the prolog and retrieve
+ //the exact encoding from it.
+
+ int[] s = new int[4];
+ String encoding = "UTF-8";
+
+ //Determine what the first four bytes are and store
+ //them into an int array.
+ input.mark(4);
+ for (int i = 0; i < 4; i++) {
+ s[i] = input.read();
+ }
+ input.reset();
+
+ //Set the encoding base on what the first four bytes of the
+ //inputstream turn out to be (following the information from
+ //www.w3.org/TR/REC-xml/#sec-guessing).
+ if (s[0] == 255) {
+ if (s[1] == 254) {
+ if (s[2] != 0 || s[3] != 0) {
+ encoding = "UnicodeLittle";
+ } else {
+ encoding = "X-UTF-32LE-BOM";
+ }
+ }
+ } else if (s[0] == 254 && s[1] == 255 && (s[2] != 0 ||
+ s[3] != 0)) {
+ encoding = "UTF-16";
+
+ } else if (s[0] == 0 && s[1] == 0 && s[2] == 254 &&
+ s[3] == 255) {
+ encoding = "X-UTF-32BE-BOM";
+
+ } else if (s[0] == 0 && s[1] == 0 && s[2] == 0 &&
+ s[3] == 60) {
+ encoding = "UTF-32BE";
+
+ } else if (s[0] == 60 && s[1] == 0 && s[2] == 0 &&
+ s[3] == 0) {
+ encoding = "UTF-32LE";
+
+ } else if (s[0] == 0 && s[1] == 60 && s[2] == 0 &&
+ s[3] == 63) {
+ encoding = "UTF-16BE";
+ } else if (s[0] == 60 && s[1] == 0 && s[2] == 63 &&
+ s[3] == 0) {
+ encoding = "UTF-16LE";
+ }
+
+ return encoding;
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties
index 2691005..d0de783 100644
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties
@@ -189,6 +189,7 @@ BONoupdate = Disables checking for updates.
BOHeadless = Disables download window, other UIs.
BOStrict = Enables strict checking of JNLP file format.
BOViewer = Shows the trusted certificate viewer.
+BOXml = Uses a strict XML parser to parse the JNLP file.
BXnofork = Do not create another JVM.
BXclearcache= Clean the JNLP application cache.
BXignoreheaders= Skip jar header verification.
diff --git a/netx/net/sourceforge/jnlp/runtime/Boot.java b/netx/net/sourceforge/jnlp/runtime/Boot.java
index 9b69660..4af893a 100644
--- a/netx/net/sourceforge/jnlp/runtime/Boot.java
+++ b/netx/net/sourceforge/jnlp/runtime/Boot.java
@@ -102,6 +102,7 @@ public final class Boot implements PrivilegedAction<Void> {
+ " -noupdate " + R("BONoupdate") + "\n"
+ " -headless " + R("BOHeadless") + "\n"
+ " -strict " + R("BOStrict") + "\n"
+ + " -xml " + R("BOXml") + "\n"
+ " -Xnofork " + R("BXnofork") + "\n"
+ " -Xclearcache " + R("BXclearcache") + "\n"
+ " -Xignoreheaders " + R("BXignoreheaders") + "\n"
@@ -197,9 +198,18 @@ public final class Boot implements PrivilegedAction<Void> {
extra.put("arguments", getOptions("-arg"));
extra.put("parameters", getOptions("-param"));
extra.put("properties", getOptions("-property"));
+ boolean strict = false;
+ boolean malformedXmlAllowed = true;
- boolean strict = (null != getOption("-strict"));
- ParserSettings settings = new ParserSettings(strict);
+ if (null != getOption("-strict")) {
+ strict = true;
+ }
+
+ if (null != getOption("-xml")) {
+ malformedXmlAllowed = false;
+ }
+
+ ParserSettings settings = new ParserSettings(strict, true, malformedXmlAllowed);
try {
Launcher launcher = new Launcher(false);
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
index 46212d7..a74f541 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
@@ -76,6 +76,7 @@ import net.sourceforge.jnlp.LaunchDesc;
import net.sourceforge.jnlp.LaunchException;
import net.sourceforge.jnlp.NullJnlpFileException;
import net.sourceforge.jnlp.ParseException;
+import net.sourceforge.jnlp.ParserSettings;
import net.sourceforge.jnlp.PluginBridge;
import net.sourceforge.jnlp.ResourcesDesc;
import net.sourceforge.jnlp.SecurityDesc;
@@ -460,7 +461,7 @@ public class JNLPClassLoader extends URLClassLoader {
* @param policy the update policy to use when downloading resources
* @param mainName Overrides the main class name of the application
*/
- public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy, String mainName)
+ public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version,ParserSettings settings, UpdatePolicy policy, String mainName)
throws IOException, ParseException, LaunchException {
JNLPClassLoader loader;
@@ -469,7 +470,7 @@ public class JNLPClassLoader extends URLClassLoader {
loader = uniqueKeyToLoader.get(uniqueKey);
if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) {
- JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, false, policy);
+ JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, settings, policy);
loader = getInstance(jnlpFile, policy, mainName);
}
@@ -504,7 +505,7 @@ public class JNLPClassLoader extends URLClassLoader {
for (int i = 0; i < ext.length; i++) {
try {
String uniqueKey = this.getJNLPFile().getUniqueKey();
- JNLPClassLoader loader = getInstance(ext[i].getLocation(), uniqueKey, ext[i].getVersion(), updatePolicy, mainClass);
+ JNLPClassLoader loader = getInstance(ext[i].getLocation(), uniqueKey, ext[i].getVersion(), file.getParserSettings(), updatePolicy, mainClass);
loaderList.add(loader);
} catch (Exception ex) {
ex.printStackTrace();