| diff --git a/build/build.py b/build/build.py |
| index 1a03b4c..7a99cf4 100755 |
| --- a/build/build.py |
| +++ b/build/build.py |
| @@ -168,6 +168,7 @@ runDependencyJars = [ |
| "jetty-util-ajax-9.2.9.v20150224.jar", |
| "log4j-1.2.17.jar", |
| "rhino-1.7R5.jar", |
| + "iri.jar" |
| ] |
| |
| buildOnlyDependencyJars = [ |
| @@ -641,6 +642,7 @@ def buildEmitters(): |
| '-d "%s"' % classDir, |
| '-encoding UTF-8', |
| ] |
| + return |
| if javaVersion != "": |
| args.append('-target ' + javaVersion) |
| args.append('-source ' + javaVersion) |
| diff --git a/htmlparser b/htmlparser |
| deleted file mode 160000 |
| index 543cc3e..0000000 |
| --- a/htmlparser |
| +++ /dev/null |
| @@ -1 +0,0 @@ |
| -Subproject commit 543cc3e7d442874c10ed40e114317115bcff1ca5 |
| diff --git a/jing-trang b/jing-trang |
| deleted file mode 160000 |
| index 35eb11b..0000000 |
| --- a/jing-trang |
| +++ /dev/null |
| @@ -1 +0,0 @@ |
| -Subproject commit 35eb11b84a230ee4d7168f12f98a28bf40e940aa |
| diff --git a/src/nu/validator/client/TestRunner.java b/src/nu/validator/client/TestRunner.java |
| deleted file mode 100644 |
| index 551df39..0000000 |
| --- a/src/nu/validator/client/TestRunner.java |
| +++ /dev/null |
| @@ -1,611 +0,0 @@ |
| -/* |
| - * Copyright (c) 2013-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.client; |
| - |
| -import java.io.BufferedWriter; |
| -import java.io.File; |
| -import java.io.FileInputStream; |
| -import java.io.FileOutputStream; |
| -import java.io.InputStreamReader; |
| -import java.io.IOException; |
| -import java.io.OutputStreamWriter; |
| -import java.io.PrintWriter; |
| -import java.net.MalformedURLException; |
| -import java.util.ArrayList; |
| -import java.util.HashMap; |
| -import java.util.LinkedHashMap; |
| -import java.util.List; |
| -import java.util.Map; |
| -import java.util.regex.Pattern; |
| - |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXParseException; |
| - |
| -import org.eclipse.jetty.util.ajax.JSON; |
| - |
| -import org.relaxng.datatype.DatatypeException; |
| -import com.thaiopensource.relaxng.exceptions.BadAttributeValueException; |
| - |
| -import nu.validator.datatype.Html5DatatypeException; |
| - |
| -import nu.validator.validation.SimpleDocumentValidator; |
| - |
| -public class TestRunner implements ErrorHandler { |
| - |
| - private boolean inError = false; |
| - |
| - private boolean emitMessages = false; |
| - |
| - private boolean exceptionIsWarning = false; |
| - |
| - private boolean expectingError = false; |
| - |
| - private Exception exception = null; |
| - |
| - private SimpleDocumentValidator validator; |
| - |
| - private PrintWriter err; |
| - |
| - private PrintWriter out; |
| - |
| - private String schema = "http://s.validator.nu/html5-all.rnc"; |
| - |
| - private boolean failed = false; |
| - |
| - private static File messagesFile; |
| - |
| - private static String[] ignoreList = null; |
| - |
| - private static boolean writeMessages; |
| - |
| - private static boolean verbose; |
| - |
| - private String baseDir = null; |
| - |
| - private Map<String, String> expectedMessages; |
| - |
| - private Map<String, String> reportedMessages; |
| - |
| - public TestRunner() throws IOException { |
| - reportedMessages = new LinkedHashMap<String, String>(); |
| - validator = new SimpleDocumentValidator(); |
| - try { |
| - this.err = new PrintWriter(new OutputStreamWriter(System.err, |
| - "UTF-8")); |
| - this.out = new PrintWriter(new OutputStreamWriter(System.out, |
| - "UTF-8")); |
| - } catch (Exception e) { |
| - // If this happens, the JDK is too broken anyway |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - |
| - private void checkHtmlFile(File file) throws IOException, SAXException { |
| - if (!file.exists()) { |
| - if (verbose) { |
| - out.println(String.format("\"%s\": warning: File not found.", |
| - file.toURI().toURL().toString())); |
| - out.flush(); |
| - } |
| - return; |
| - } |
| - if (verbose) { |
| - out.println(file); |
| - out.flush(); |
| - } |
| - if (isHtml(file)) { |
| - validator.checkHtmlFile(file, true); |
| - } else if (isXhtml(file)) { |
| - validator.checkXmlFile(file); |
| - } else { |
| - if (verbose) { |
| - out.println(String.format( |
| - "\"%s\": warning: File was not checked." |
| - + " Files must have a .html, .xhtml, .htm," |
| - + " or .xht extension.", |
| - file.toURI().toURL().toString())); |
| - out.flush(); |
| - } |
| - } |
| - } |
| - |
| - private boolean isXhtml(File file) { |
| - String name = file.getName(); |
| - return name.endsWith(".xhtml") || name.endsWith(".xht"); |
| - } |
| - |
| - private boolean isHtml(File file) { |
| - String name = file.getName(); |
| - return name.endsWith(".html") || name.endsWith(".htm"); |
| - } |
| - |
| - private boolean isCheckableFile(File file) { |
| - return file.isFile() && (isHtml(file) || isXhtml(file)); |
| - } |
| - |
| - private void recurseDirectory(File directory) throws SAXException, |
| - IOException { |
| - File[] files = directory.listFiles(); |
| - for (int i = 0; i < files.length; i++) { |
| - File file = files[i]; |
| - if (file.isDirectory()) { |
| - recurseDirectory(file); |
| - } else { |
| - checkHtmlFile(file); |
| - } |
| - } |
| - } |
| - |
| - private boolean isIgnorable(File file) throws IOException { |
| - String testPathname = file.getAbsolutePath().substring( |
| - baseDir.length() + 1); |
| - if (ignoreList != null) { |
| - for (String substring : ignoreList) { |
| - if (testPathname.contains(substring)) { |
| - if (verbose) { |
| - out.println(String.format( |
| - "\"%s\": warning: File ignored.", |
| - file.toURI().toURL().toString())); |
| - out.flush(); |
| - } |
| - return true; |
| - } |
| - } |
| - } |
| - return false; |
| - } |
| - |
| - private void checkFiles(List<File> files) throws IOException { |
| - for (File file : files) { |
| - if (isIgnorable(file)) { |
| - continue; |
| - } |
| - reset(); |
| - emitMessages = true; |
| - try { |
| - if (file.isDirectory()) { |
| - recurseDirectory(file); |
| - } else { |
| - checkHtmlFile(file); |
| - } |
| - } catch (IOException e) { |
| - } catch (SAXException e) { |
| - } |
| - if (inError) { |
| - failed = true; |
| - } |
| - } |
| - } |
| - |
| - private boolean messageMatches(String testFilename) { |
| - // p{C} = Other = Control+Format+Private_Use+Surrogate+Unassigned |
| - // http://www.regular-expressions.info/unicode.html#category |
| - // http://www.unicode.org/reports/tr18/#General_Category_Property |
| - String messageReported = exception.getMessage().replaceAll("\\p{C}", |
| - "?"); |
| - String messageExpected = expectedMessages.get(testFilename).replaceAll( |
| - "\\p{C}", "?"); |
| - // FIXME: The string replacements below are a hack to "normalize" |
| - // error messages reported for bad values of the ins/del datetime |
| - // attribute, to work around the fact that in Java 8, parts of |
| - // those error messages don't always get emitted in the same order |
| - // that they do in Java 7 and earlier. |
| - Pattern p; |
| - p = Pattern.compile("(Bad datetime with timezone: .+) (Bad date: .+)"); |
| - messageExpected = p.matcher(messageExpected).replaceAll("$2 $1"); |
| - messageReported = p.matcher(messageReported).replaceAll("$2 $1"); |
| - return messageReported.equals(messageExpected); |
| - } |
| - |
| - private void checkInvalidFiles(List<File> files) throws IOException { |
| - String testFilename; |
| - expectingError = true; |
| - for (File file : files) { |
| - if (isIgnorable(file)) { |
| - continue; |
| - } |
| - reset(); |
| - try { |
| - if (file.isDirectory()) { |
| - recurseDirectory(file); |
| - } else { |
| - checkHtmlFile(file); |
| - } |
| - } catch (IOException e) { |
| - } catch (SAXException e) { |
| - } |
| - if (exception != null) { |
| - testFilename = file.getAbsolutePath().substring( |
| - baseDir.length() + 1); |
| - if (writeMessages) { |
| - reportedMessages.put(testFilename, exception.getMessage()); |
| - } else if (expectedMessages != null |
| - && expectedMessages.get(testFilename) == null) { |
| - try { |
| - err.println(String.format( |
| - "\"%s\": warning: No expected message in" |
| - + " messages file.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } else if (expectedMessages != null |
| - && !messageMatches(testFilename)) { |
| - failed = true; |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected \"%s\"" |
| - + " but instead encountered \"%s\".", |
| - file.toURI().toURL().toString(), |
| - expectedMessages.get(testFilename), |
| - exception.getMessage())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - } |
| - if (!inError) { |
| - failed = true; |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected an error but did not" |
| - + " encounter any.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - } |
| - } |
| - |
| - private void checkHasWarningFiles(List<File> files) throws IOException { |
| - String testFilename; |
| - expectingError = false; |
| - for (File file : files) { |
| - if (isIgnorable(file)) { |
| - continue; |
| - } |
| - reset(); |
| - try { |
| - if (file.isDirectory()) { |
| - recurseDirectory(file); |
| - } else { |
| - checkHtmlFile(file); |
| - } |
| - } catch (IOException e) { |
| - } catch (SAXException e) { |
| - } |
| - if (exception != null) { |
| - testFilename = file.getAbsolutePath().substring( |
| - baseDir.length() + 1); |
| - if (writeMessages) { |
| - reportedMessages.put(testFilename, exception.getMessage()); |
| - } else if (expectedMessages != null |
| - && expectedMessages.get(testFilename) == null) { |
| - try { |
| - err.println(String.format( |
| - "\"%s\": warning: No expected message in" |
| - + " messages file.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } else if (expectedMessages != null |
| - && !messageMatches(testFilename)) { |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected \"%s\"" |
| - + " but instead encountered \"%s\".", |
| - file.toURI().toURL().toString(), |
| - expectedMessages.get(testFilename), |
| - exception.getMessage())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - } |
| - if (inError) { |
| - failed = true; |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected a warning but encountered" |
| - + " an error first.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } else if (!exceptionIsWarning) { |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected a warning but did not" |
| - + " encounter any.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - if (inError) { |
| - failed = true; |
| - try { |
| - err.println(String.format( |
| - "\"%s\": error: Expected a warning only but" |
| - + " encountered at least one error.", |
| - file.toURI().toURL().toString())); |
| - err.flush(); |
| - } catch (MalformedURLException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - } |
| - } |
| - |
| - private enum State { |
| - EXPECTING_INVALID_FILES, EXPECTING_VALID_FILES, EXPECTING_ANYTHING |
| - } |
| - |
| - private void checkTestDirectoryAgainstSchema(File directory, |
| - String schemaUrl) throws SAXException, Exception { |
| - validator.setUpMainSchema(schemaUrl, this); |
| - checkTestFiles(directory, State.EXPECTING_ANYTHING); |
| - } |
| - |
| - private void checkTestFiles(File directory, State state) |
| - throws SAXException, IOException { |
| - File[] files = directory.listFiles(); |
| - List<File> validFiles = new ArrayList<File>(); |
| - List<File> invalidFiles = new ArrayList<File>(); |
| - List<File> hasWarningFiles = new ArrayList<File>(); |
| - if (files == null) { |
| - if (verbose) { |
| - try { |
| - out.println(String.format( |
| - "\"%s\": warning: No files found in directory.", |
| - directory.toURI().toURL().toString())); |
| - out.flush(); |
| - } catch (MalformedURLException mue) { |
| - throw new RuntimeException(mue); |
| - } |
| - } |
| - return; |
| - } |
| - for (int i = 0; i < files.length; i++) { |
| - File file = files[i]; |
| - if (file.isDirectory()) { |
| - if (state != State.EXPECTING_ANYTHING) { |
| - checkTestFiles(file, state); |
| - } else if ("invalid".equals(file.getName())) { |
| - checkTestFiles(file, State.EXPECTING_INVALID_FILES); |
| - } else if ("valid".equals(file.getName())) { |
| - checkTestFiles(file, State.EXPECTING_VALID_FILES); |
| - } else { |
| - checkTestFiles(file, State.EXPECTING_ANYTHING); |
| - } |
| - } else if (isCheckableFile(file)) { |
| - if (state == State.EXPECTING_INVALID_FILES) { |
| - invalidFiles.add(file); |
| - } else if (state == State.EXPECTING_VALID_FILES) { |
| - validFiles.add(file); |
| - } else if (file.getPath().indexOf("novalid") > 0) { |
| - invalidFiles.add(file); |
| - } else if (file.getPath().indexOf("haswarn") > 0) { |
| - hasWarningFiles.add(file); |
| - } else { |
| - validFiles.add(file); |
| - } |
| - } |
| - } |
| - if (validFiles.size() > 0) { |
| - validator.setUpValidatorAndParsers(this, false, false); |
| - checkFiles(validFiles); |
| - } |
| - if (invalidFiles.size() > 0) { |
| - validator.setUpValidatorAndParsers(this, false, false); |
| - checkInvalidFiles(invalidFiles); |
| - } |
| - if (hasWarningFiles.size() > 0) { |
| - validator.setUpValidatorAndParsers(this, false, false); |
| - checkHasWarningFiles(hasWarningFiles); |
| - } |
| - if (writeMessages) { |
| - OutputStreamWriter out = new OutputStreamWriter( |
| - new FileOutputStream(messagesFile), "utf-8"); |
| - BufferedWriter bw = new BufferedWriter(out); |
| - bw.write(JSON.toString(reportedMessages)); |
| - bw.close(); |
| - } |
| - } |
| - |
| - public boolean runTestSuite() throws SAXException, Exception { |
| - if (messagesFile != null) { |
| - baseDir = messagesFile.getAbsoluteFile().getParent(); |
| - FileInputStream fis = new FileInputStream(messagesFile); |
| - InputStreamReader reader = new InputStreamReader(fis, "UTF-8"); |
| - expectedMessages = (HashMap<String, String>) JSON.parse(reader); |
| - } else { |
| - baseDir = System.getProperty("user.dir"); |
| - } |
| - for (File directory : new File(baseDir).listFiles()) { |
| - if (directory.isDirectory()) { |
| - if (directory.getName().contains("rdfalite")) { |
| - checkTestDirectoryAgainstSchema(directory, |
| - "http://s.validator.nu/html5-rdfalite.rnc"); |
| - } else if (directory.getName().contains("xhtml")) { |
| - checkTestDirectoryAgainstSchema(directory, |
| - "http://s.validator.nu/xhtml5-all.rnc"); |
| - } else { |
| - checkTestDirectoryAgainstSchema(directory, schema); |
| - } |
| - } |
| - } |
| - if (verbose) { |
| - if (failed) { |
| - out.println("Failure!"); |
| - out.flush(); |
| - } else { |
| - out.println("Success!"); |
| - out.flush(); |
| - } |
| - } |
| - return !failed; |
| - } |
| - |
| - private void emitMessage(SAXParseException e, String messageType) { |
| - String systemId = e.getSystemId(); |
| - err.write((systemId == null) ? "" : '\"' + systemId + '\"'); |
| - err.write(":"); |
| - err.write(Integer.toString(e.getLineNumber())); |
| - err.write(":"); |
| - err.write(Integer.toString(e.getColumnNumber())); |
| - err.write(": "); |
| - err.write(messageType); |
| - err.write(": "); |
| - err.write(e.getMessage()); |
| - err.write("\n"); |
| - err.flush(); |
| - } |
| - |
| - public void warning(SAXParseException e) throws SAXException { |
| - if (emitMessages) { |
| - emitMessage(e, "warning"); |
| - } else if (exception == null && !expectingError) { |
| - exception = e; |
| - exceptionIsWarning = true; |
| - } |
| - } |
| - |
| - public void error(SAXParseException e) throws SAXException { |
| - if (emitMessages) { |
| - emitMessage(e, "error"); |
| - } else if (exception == null) { |
| - exception = e; |
| - if (e instanceof BadAttributeValueException) { |
| - BadAttributeValueException ex = (BadAttributeValueException) e; |
| - Map<String, DatatypeException> datatypeErrors = ex.getExceptions(); |
| - for (Map.Entry<String, DatatypeException> entry : datatypeErrors.entrySet()) { |
| - DatatypeException dex = entry.getValue(); |
| - if (dex instanceof Html5DatatypeException) { |
| - Html5DatatypeException ex5 = (Html5DatatypeException) dex; |
| - if (ex5.isWarning()) { |
| - exceptionIsWarning = true; |
| - return; |
| - } |
| - } |
| - } |
| - } |
| - } |
| - inError = true; |
| - } |
| - |
| - public void fatalError(SAXParseException e) throws SAXException { |
| - inError = true; |
| - if (emitMessages) { |
| - emitMessage(e, "fatal error"); |
| - return; |
| - } else if (exception == null) { |
| - exception = e; |
| - } |
| - } |
| - |
| - public void reset() { |
| - exception = null; |
| - inError = false; |
| - emitMessages = false; |
| - exceptionIsWarning = false; |
| - } |
| - |
| - public static void main(String[] args) throws SAXException, Exception { |
| - if (args.length < 1) { |
| - usage(); |
| - System.exit(0); |
| - } |
| - verbose = false; |
| - String messagesFilename = null; |
| - System.setProperty("nu.validator.datatype.warn", "true"); |
| - for (int i = 0; i < args.length; i++) { |
| - if ("--verbose".equals(args[i])) { |
| - verbose = true; |
| - } else if ("--errors-only".equals(args[i])) { |
| - System.setProperty("nu.validator.datatype.warn", "false"); |
| - } else if ("--write-messages".equals(args[i])) { |
| - writeMessages = true; |
| - } else if (args[i].startsWith("--ignore=")) { |
| - ignoreList = args[i].substring(9, args[i].length()).split(","); |
| - } else if (args[i].startsWith("--")) { |
| - System.out.println(String.format( |
| - "\nError: There is no option \"%s\".", args[i])); |
| - usage(); |
| - System.exit(1); |
| - } else { |
| - if (args[i].endsWith(".json")) { |
| - messagesFilename = args[i]; |
| - } else { |
| - System.out.println("\nError: Expected the name of a messages" |
| - + " file with a .json extension."); |
| - usage(); |
| - System.exit(1); |
| - } |
| - } |
| - } |
| - if (messagesFilename != null) { |
| - messagesFile = new File(messagesFilename); |
| - if (!messagesFile.exists()) { |
| - System.out.println("\nError: \"" + messagesFilename |
| - + "\" file not found."); |
| - System.exit(1); |
| - } else if (!messagesFile.isFile()) { |
| - System.out.println("\nError: \"" + messagesFilename |
| - + "\" is not a file."); |
| - System.exit(1); |
| - } |
| - } else if (writeMessages) { |
| - System.out.println("\nError: Expected the name of a messages" |
| - + " file with a .json extension."); |
| - usage(); |
| - System.exit(1); |
| - } |
| - TestRunner tr = new TestRunner(); |
| - if (tr.runTestSuite()) { |
| - System.exit(0); |
| - } else { |
| - System.exit(1); |
| - } |
| - } |
| - |
| - private static void usage() { |
| - System.out.println("\nUsage:"); |
| - System.out.println("\n java nu.validator.client.TestRunner [--errors-only] [--write-messages]"); |
| - System.out.println(" [--verbose] [MESSAGES.json]"); |
| - System.out.println("\n...where the MESSAGES.json file contains name/value pairs in which the name is"); |
| - System.out.println("a pathname of a document to check and the value is the first error message or"); |
| - System.out.println("warning message the validator is expected to report when checking that document."); |
| - System.out.println("Use the --write-messages option to create the file."); |
| - } |
| -} |
| diff --git a/src/nu/validator/datatype/FunctionBody.java b/src/nu/validator/datatype/FunctionBody.java |
| index 5e8bd69..35642ef 100644 |
| --- a/src/nu/validator/datatype/FunctionBody.java |
| +++ b/src/nu/validator/datatype/FunctionBody.java |
| @@ -27,9 +27,9 @@ import java.io.IOException; |
| import java.io.Reader; |
| import java.io.StringReader; |
| |
| -import org.mozilla.javascript.Context; |
| -import org.mozilla.javascript.ContextFactory; |
| -import org.mozilla.javascript.RhinoException; |
| +//import org.mozilla.javascript.Context; |
| +//import org.mozilla.javascript.ContextFactory; |
| +//import org.mozilla.javascript.RhinoException; |
| import org.relaxng.datatype.DatatypeException; |
| |
| public class FunctionBody extends AbstractDatatype { |
| @@ -44,25 +44,25 @@ public class FunctionBody extends AbstractDatatype { |
| } |
| |
| public void checkValid(CharSequence literal) throws DatatypeException { |
| - try { |
| - Reader reader = new BufferedReader((new StringReader( |
| - "function(event){" + literal.toString() + "}"))); |
| - reader.mark(1); |
| - try { |
| - Context context = ContextFactory.getGlobal().enterContext(); |
| - context.setOptimizationLevel(0); |
| - context.setLanguageVersion(Context.VERSION_1_6); |
| - // -1 for lineno arg prevents Rhino from appending |
| - // "(unnamed script#1)" to all error messages |
| - context.compileReader(reader, null, -1, null); |
| - } finally { |
| - Context.exit(); |
| - } |
| - } catch (IOException e) { |
| - throw newDatatypeException(e.getMessage()); |
| - } catch (RhinoException e) { |
| - throw newDatatypeException(e.getMessage()); |
| - } |
| +// try { |
| +// Reader reader = new BufferedReader((new StringReader( |
| +// "function(event){" + literal.toString() + "}"))); |
| +// reader.mark(1); |
| +// try { |
| +// Context context = ContextFactory.getGlobal().enterContext(); |
| +// context.setOptimizationLevel(0); |
| +// context.setLanguageVersion(Context.VERSION_1_6); |
| +// // -1 for lineno arg prevents Rhino from appending |
| +// // "(unnamed script#1)" to all error messages |
| +// context.compileReader(reader, null, -1, null); |
| +// } finally { |
| +// Context.exit(); |
| +// } |
| +// } catch (IOException e) { |
| +// throw newDatatypeException(e.getMessage()); |
| +// } catch (RhinoException e) { |
| +// throw newDatatypeException(e.getMessage()); |
| +// } |
| } |
| |
| @Override public String getName() { |
| diff --git a/src/nu/validator/datatype/IriRef.java b/src/nu/validator/datatype/IriRef.java |
| index e9d6fff..2b42415 100644 |
| --- a/src/nu/validator/datatype/IriRef.java |
| +++ b/src/nu/validator/datatype/IriRef.java |
| @@ -29,18 +29,18 @@ import java.io.InputStream; |
| import java.io.Reader; |
| import java.io.StringReader; |
| |
| -import org.mozilla.javascript.Context; |
| -import org.mozilla.javascript.ContextFactory; |
| -import org.mozilla.javascript.RhinoException; |
| +//import org.mozilla.javascript.Context; |
| +//import org.mozilla.javascript.ContextFactory; |
| +//import org.mozilla.javascript.RhinoException; |
| import org.relaxng.datatype.DatatypeException; |
| import nu.validator.io.DataUri; |
| import nu.validator.io.DataUriException; |
| import nu.validator.io.Utf8PercentDecodingReader; |
| |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.URLParsingSettings; |
| -import io.mola.galimatias.GalimatiasParseException; |
| -import io.mola.galimatias.StrictErrorHandler; |
| +//import io.mola.galimatias.URL; |
| +//import io.mola.galimatias.URLParsingSettings; |
| +//import io.mola.galimatias.GalimatiasParseException; |
| +//import io.mola.galimatias.StrictErrorHandler; |
| |
| public class IriRef extends AbstractDatatype { |
| |
| @@ -93,112 +93,112 @@ public class IriRef extends AbstractDatatype { |
| } |
| |
| public void checkValid(CharSequence literal) throws DatatypeException { |
| - String messagePrologue = ""; |
| - int length = literal.length(); |
| - if (reportValue()) { |
| - if (length < ELIDE_LIMIT) { |
| - messagePrologue = "\u201c" + literal + "\u201d: "; |
| - } else { |
| - StringBuilder sb = new StringBuilder(ELIDE_LIMIT + 1); |
| - sb.append(literal, 0, ELIDE_LIMIT / 2); |
| - sb.append('\u2026'); |
| - sb.append(literal, length - ELIDE_LIMIT / 2, length); |
| - messagePrologue = "\u201c" + sb.toString() + "\u201d: "; |
| - } |
| - } |
| - if ("".equals(trimHtmlSpaces(literal.toString()))) { |
| - throw newDatatypeException("Must be non-empty."); |
| - } |
| - URL url = null; |
| - URLParsingSettings settings = URLParsingSettings.create().withErrorHandler( |
| - StrictErrorHandler.getInstance()); |
| - boolean data = false; |
| - try { |
| - CharSequencePair pair = splitScheme(literal); |
| - if (pair == null) { |
| - // no scheme or scheme is private |
| - if (isAbsolute()) { |
| - throw newDatatypeException("The string \u201c" + literal |
| - + "\u201d is not an absolute URL."); |
| - } else { |
| - // in this case, doc's actual base URL isn't relevant, |
| - // so just use http://example.org/foo/bar as base |
| - url = URL.parse(settings, |
| - URL.parse("http://example.org/foo/bar"), |
| - literal.toString()); |
| - } |
| - } else { |
| - CharSequence scheme = pair.getHead(); |
| - CharSequence tail = pair.getTail(); |
| - if (isWellKnown(scheme)) { |
| - url = URL.parse(settings, literal.toString()); |
| - } else if ("javascript".contentEquals(scheme)) { |
| - // StringBuilder sb = new StringBuilder(2 + |
| - // literal.length()); |
| - // sb.append("x-").append(literal); |
| - // iri = fac.construct(sb.toString()); |
| - url = null; // Don't bother user with generic IRI syntax |
| - Reader reader = new BufferedReader( |
| - new Utf8PercentDecodingReader(new StringReader( |
| - "function(event){" + tail.toString() + "}"))); |
| - // XXX CharSequenceReader |
| - reader.mark(1); |
| - int c = reader.read(); |
| - if (c != 0xFEFF) { |
| - reader.reset(); |
| - } |
| - try { |
| - Context context = ContextFactory.getGlobal().enterContext(); |
| - context.setOptimizationLevel(0); |
| - context.setLanguageVersion(Context.VERSION_1_6); |
| - // -1 for lineno arg prevents Rhino from appending |
| - // "(unnamed script#1)" to all error messages |
| - context.compileReader(reader, null, -1, null); |
| - } finally { |
| - Context.exit(); |
| - } |
| - } else if ("data".contentEquals(scheme)) { |
| - data = true; |
| - url = URL.parse(settings, literal.toString()); |
| - } else if (isHttpAlias(scheme)) { |
| - StringBuilder sb = new StringBuilder(5 + tail.length()); |
| - sb.append("http:").append(tail); |
| - url = URL.parse(settings, sb.toString()); |
| - } else { |
| - StringBuilder sb = new StringBuilder(2 + literal.length()); |
| - sb.append("x-").append(literal); |
| - url = URL.parse(settings, sb.toString()); |
| - } |
| - } |
| - } catch (GalimatiasParseException e) { |
| - throw newDatatypeException(messagePrologue + e.getMessage() + "."); |
| - } catch (IOException e) { |
| - throw newDatatypeException(messagePrologue + e.getMessage()); |
| - } catch (RhinoException e) { |
| - throw newDatatypeException(messagePrologue + e.getMessage()); |
| - } |
| - if (url != null) { |
| - if (data) { |
| - try { |
| - DataUri dataUri = new DataUri(url); |
| - InputStream is = dataUri.getInputStream(); |
| - while (is.read() >= 0) { |
| - // spin |
| - } |
| - } catch (DataUriException e) { |
| - throw newDatatypeException(e.getIndex(), e.getHead(), |
| - e.getLiteral(), e.getTail()); |
| - } catch (IOException e) { |
| - String msg = e.getMessage(); |
| - if (WARN |
| - && "Fragment is not allowed for data: URIs according to RFC 2397.".equals(msg)) { |
| - throw newDatatypeException(messagePrologue + msg, WARN); |
| - } else { |
| - throw newDatatypeException(messagePrologue + msg); |
| - } |
| - } |
| - } |
| - } |
| +// String messagePrologue = ""; |
| +// int length = literal.length(); |
| +// if (reportValue()) { |
| +// if (length < ELIDE_LIMIT) { |
| +// messagePrologue = "\u201c" + literal + "\u201d: "; |
| +// } else { |
| +// StringBuilder sb = new StringBuilder(ELIDE_LIMIT + 1); |
| +// sb.append(literal, 0, ELIDE_LIMIT / 2); |
| +// sb.append('\u2026'); |
| +// sb.append(literal, length - ELIDE_LIMIT / 2, length); |
| +// messagePrologue = "\u201c" + sb.toString() + "\u201d: "; |
| +// } |
| +// } |
| +// if ("".equals(trimHtmlSpaces(literal.toString()))) { |
| +// throw newDatatypeException("Must be non-empty."); |
| +// } |
| +// URL url = null; |
| +// URLParsingSettings settings = URLParsingSettings.create().withErrorHandler( |
| +// StrictErrorHandler.getInstance()); |
| +// boolean data = false; |
| +// try { |
| +// CharSequencePair pair = splitScheme(literal); |
| +// if (pair == null) { |
| +// // no scheme or scheme is private |
| +// if (isAbsolute()) { |
| +// throw newDatatypeException("The string \u201c" + literal |
| +// + "\u201d is not an absolute URL."); |
| +// } else { |
| +// // in this case, doc's actual base URL isn't relevant, |
| +// // so just use http://example.org/foo/bar as base |
| +// url = URL.parse(settings, |
| +// URL.parse("http://example.org/foo/bar"), |
| +// literal.toString()); |
| +// } |
| +// } else { |
| +// CharSequence scheme = pair.getHead(); |
| +// CharSequence tail = pair.getTail(); |
| +// if (isWellKnown(scheme)) { |
| +// url = URL.parse(settings, literal.toString()); |
| +// } else if ("javascript".contentEquals(scheme)) { |
| +// // StringBuilder sb = new StringBuilder(2 + |
| +// // literal.length()); |
| +// // sb.append("x-").append(literal); |
| +// // iri = fac.construct(sb.toString()); |
| +// url = null; // Don't bother user with generic IRI syntax |
| +// Reader reader = new BufferedReader( |
| +// new Utf8PercentDecodingReader(new StringReader( |
| +// "function(event){" + tail.toString() + "}"))); |
| +// // XXX CharSequenceReader |
| +// reader.mark(1); |
| +// int c = reader.read(); |
| +// if (c != 0xFEFF) { |
| +// reader.reset(); |
| +// } |
| +// try { |
| +// Context context = ContextFactory.getGlobal().enterContext(); |
| +// context.setOptimizationLevel(0); |
| +// context.setLanguageVersion(Context.VERSION_1_6); |
| +// // -1 for lineno arg prevents Rhino from appending |
| +// // "(unnamed script#1)" to all error messages |
| +// context.compileReader(reader, null, -1, null); |
| +// } finally { |
| +// Context.exit(); |
| +// } |
| +// } else if ("data".contentEquals(scheme)) { |
| +// data = true; |
| +// url = URL.parse(settings, literal.toString()); |
| +// } else if (isHttpAlias(scheme)) { |
| +// StringBuilder sb = new StringBuilder(5 + tail.length()); |
| +// sb.append("http:").append(tail); |
| +// url = URL.parse(settings, sb.toString()); |
| +// } else { |
| +// StringBuilder sb = new StringBuilder(2 + literal.length()); |
| +// sb.append("x-").append(literal); |
| +// url = URL.parse(settings, sb.toString()); |
| +// } |
| +// } |
| +// } catch (GalimatiasParseException e) { |
| +// throw newDatatypeException(messagePrologue + e.getMessage() + "."); |
| +// } catch (IOException e) { |
| +// throw newDatatypeException(messagePrologue + e.getMessage()); |
| +// } catch (RhinoException e) { |
| +// throw newDatatypeException(messagePrologue + e.getMessage()); |
| +// } |
| +// if (url != null) { |
| +// if (data) { |
| +// try { |
| +// DataUri dataUri = new DataUri(url); |
| +// InputStream is = dataUri.getInputStream(); |
| +// while (is.read() >= 0) { |
| +// // spin |
| +// } |
| +// } catch (DataUriException e) { |
| +// throw newDatatypeException(e.getIndex(), e.getHead(), |
| +// e.getLiteral(), e.getTail()); |
| +// } catch (IOException e) { |
| +// String msg = e.getMessage(); |
| +// if (WARN |
| +// && "Fragment is not allowed for data: URIs according to RFC 2397.".equals(msg)) { |
| +// throw newDatatypeException(messagePrologue + msg, WARN); |
| +// } else { |
| +// throw newDatatypeException(messagePrologue + msg); |
| +// } |
| +// } |
| +// } |
| +// } |
| } |
| |
| private final boolean isHttpAlias(CharSequence scheme) { |
| diff --git a/src/nu/validator/datatype/Language.java b/src/nu/validator/datatype/Language.java |
| index b61913d..24fb4a4 100644 |
| --- a/src/nu/validator/datatype/Language.java |
| +++ b/src/nu/validator/datatype/Language.java |
| @@ -227,7 +227,7 @@ public final class Language extends AbstractDatatype { |
| checkPrivateUse(i, subtags); |
| return; |
| } |
| - if (subtag.length() == 4 & isLowerCaseAlpha(subtag)) { |
| + if (subtag.length() == 4 && isLowerCaseAlpha(subtag)) { |
| if (!isScript(subtag)) { |
| throw newDatatypeException("Bad script subtag."); |
| } |
| diff --git a/src/nu/validator/datatype/Pattern.java b/src/nu/validator/datatype/Pattern.java |
| index aa10750..67766c7 100644 |
| --- a/src/nu/validator/datatype/Pattern.java |
| +++ b/src/nu/validator/datatype/Pattern.java |
| @@ -22,10 +22,10 @@ |
| |
| package nu.validator.datatype; |
| |
| -import org.mozilla.javascript.Context; |
| -import org.mozilla.javascript.ContextFactory; |
| -import org.mozilla.javascript.EcmaError; |
| -import org.mozilla.javascript.regexp.RegExpImpl; |
| +//import org.mozilla.javascript.Context; |
| +//import org.mozilla.javascript.ContextFactory; |
| +//import org.mozilla.javascript.EcmaError; |
| +//import org.mozilla.javascript.regexp.RegExpImpl; |
| import org.relaxng.datatype.DatatypeException; |
| |
| /** |
| @@ -58,18 +58,18 @@ public final class Pattern extends AbstractDatatype { |
| public void checkValid(CharSequence literal) |
| throws DatatypeException { |
| // TODO find out what kind of thread concurrency guarantees are made |
| - ContextFactory cf = new ContextFactory(); |
| - Context cx = cf.enterContext(); |
| - cx.setOptimizationLevel(0); |
| - RegExpImpl rei = new RegExpImpl(); |
| - String anchoredRegex = "^(?:" + literal + ")$"; |
| - try { |
| - rei.compileRegExp(cx, anchoredRegex, ""); |
| - } catch (EcmaError ee) { |
| - throw newDatatypeException(ee.getErrorMessage()); |
| - } finally { |
| - Context.exit(); |
| - } |
| +// ContextFactory cf = new ContextFactory(); |
| +// Context cx = cf.enterContext(); |
| +// cx.setOptimizationLevel(0); |
| +// RegExpImpl rei = new RegExpImpl(); |
| +// String anchoredRegex = "^(?:" + literal + ")$"; |
| +// try { |
| +// rei.compileRegExp(cx, anchoredRegex, ""); |
| +// } catch (EcmaError ee) { |
| +// throw newDatatypeException(ee.getErrorMessage()); |
| +// } finally { |
| +// Context.exit(); |
| +// } |
| } |
| |
| @Override |
| diff --git a/src/nu/validator/datatype/SourceSizeList.java b/src/nu/validator/datatype/SourceSizeList.java |
| index 1c61f81..e3bd20a 100644 |
| --- a/src/nu/validator/datatype/SourceSizeList.java |
| +++ b/src/nu/validator/datatype/SourceSizeList.java |
| @@ -26,7 +26,6 @@ import java.text.ParseException; |
| import java.util.LinkedHashSet; |
| import java.util.Set; |
| |
| -import nu.validator.datatype.tools.CssParser; |
| import org.relaxng.datatype.DatatypeException; |
| |
| public class SourceSizeList extends AbstractDatatype { |
| @@ -41,8 +40,6 @@ public class SourceSizeList extends AbstractDatatype { |
| |
| private static final StringBuilder VALID_UNITS = new StringBuilder(); |
| |
| - private static CssParser cssParser = new CssParser(); |
| - |
| static { |
| /* font-relative lengths */ |
| LENGTH_UNITS.add("em"); |
| @@ -119,18 +116,6 @@ public class SourceSizeList extends AbstractDatatype { |
| errEmpty(isFirst, isLast, extract); |
| return; |
| } |
| - try { |
| - cssParser.tokenize(unparsedSize.toString()); |
| - if ('(' == unparsedSize.codePointAt(0)) { |
| - cssParser.parseARule("@media " + unparsedSize.toString() |
| - + " {}"); |
| - } else { |
| - cssParser.parseARule(".foo { width: " + unparsedSize.toString() |
| - + " }"); |
| - } |
| - } catch (ParseException e) { |
| - errCssParseError(e.getMessage(), unparsedSize, extract); |
| - } |
| if (')' == unparsedSize.charAt(unparsedSize.length() - 1)) { |
| checkCalc(unparsedSize, extract, isLast); |
| return; |
| diff --git a/src/nu/validator/datatype/tools/CssParser.java b/src/nu/validator/datatype/tools/CssParser.java |
| deleted file mode 100644 |
| index 9daa67f..0000000 |
| --- a/src/nu/validator/datatype/tools/CssParser.java |
| +++ /dev/null |
| @@ -1,88 +0,0 @@ |
| -/* |
| - * Copyright (c) 2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.datatype.tools; |
| - |
| -import java.io.BufferedReader; |
| -import java.io.IOException; |
| -import java.io.InputStreamReader; |
| -import java.text.ParseException; |
| - |
| -import org.mozilla.javascript.Context; |
| -import org.mozilla.javascript.ContextFactory; |
| -import org.mozilla.javascript.Function; |
| -import org.mozilla.javascript.JavaScriptException; |
| -import org.mozilla.javascript.ScriptableObject; |
| - |
| -public class CssParser { |
| - |
| - private static ScriptableObject scope; |
| - |
| - private static Function tokenizer; |
| - |
| - private static Function ruleParser; |
| - |
| - static { |
| - try { |
| - BufferedReader br = new BufferedReader( |
| - new InputStreamReader( |
| - CssParser.class.getClassLoader().getResourceAsStream( |
| - "nu/validator/localentities/files/parse-css-js"))); |
| - br.mark(1); |
| - Context context = ContextFactory.getGlobal().enterContext(); |
| - context.setOptimizationLevel(1); |
| - context.setLanguageVersion(Context.VERSION_1_6); |
| - scope = context.initStandardObjects(); |
| - context.evaluateReader(scope, br, null, -1, null); |
| - tokenizer = (Function) scope.get("tokenize", scope); |
| - ruleParser = (Function) scope.get("parseARule", scope); |
| - } catch (IOException e) { |
| - } |
| - } |
| - |
| - public String[] tokenize(CharSequence cs) throws ParseException { |
| - try { |
| - Context context = ContextFactory.getGlobal().enterContext(); |
| - context.setOptimizationLevel(0); |
| - context.setLanguageVersion(Context.VERSION_1_6); |
| - return (String[]) Context.jsToJava( |
| - tokenizer.call(context, scope, scope, new Object[] { cs }), |
| - String[].class); |
| - } catch (JavaScriptException e) { |
| - throw new ParseException(e.details(), -1); |
| - } |
| - } |
| - |
| - public String parseARule(CharSequence cs) throws ParseException { |
| - try { |
| - Context context = ContextFactory.getGlobal().enterContext(); |
| - context.setOptimizationLevel(0); |
| - context.setLanguageVersion(Context.VERSION_1_6); |
| - return (String) Context.jsToJava(ruleParser.call(context, scope, scope, |
| - new Object[] { tokenizer.call(context, scope, scope, |
| - new Object[] { cs }) }), String.class); |
| - } catch (JavaScriptException e) { |
| - throw new ParseException(e.details(), -1); |
| - } |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/io/DataUri.java b/src/nu/validator/io/DataUri.java |
| index 74811a9..9677758 100644 |
| --- a/src/nu/validator/io/DataUri.java |
| +++ b/src/nu/validator/io/DataUri.java |
| @@ -22,13 +22,14 @@ |
| |
| package nu.validator.io; |
| |
| +import com.hp.hpl.jena.iri.IRIFactory; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.StringReader; |
| import java.net.MalformedURLException; |
| |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.GalimatiasParseException; |
| +//import io.mola.galimatias.URL; |
| +//import io.mola.galimatias.GalimatiasParseException; |
| |
| public class DataUri { |
| |
| @@ -54,17 +55,17 @@ public class DataUri { |
| * @throws MalformedURLException |
| * @throws IOException |
| */ |
| - protected void init(URL url) throws IOException, MalformedURLException { |
| - if (!url.scheme().equals("data")) { |
| + protected void init(com.hp.hpl.jena.iri.IRI url) throws IOException, MalformedURLException { |
| + if (!url.getScheme().equals("data")) { |
| throw new IllegalArgumentException("The input did not start with data:."); |
| } |
| |
| - if (url.fragment() != null) { |
| + if (url.getRawFragment() != null) { |
| throw new MalformedURLException( |
| "Fragment is not allowed for data: URIs according to RFC 2397."); |
| } |
| |
| - InputStream is = new PercentDecodingReaderInputStream(new StringReader(url.schemeData())); |
| + InputStream is = new PercentDecodingReaderInputStream(new StringReader(url.getRawPath())); |
| StringBuilder sb = new StringBuilder(); |
| State state = State.AT_START; |
| int i = 0; // string counter |
| @@ -254,11 +255,15 @@ public class DataUri { |
| } |
| |
| public DataUri(String url) throws IOException { |
| - try { |
| - init(URL.parse(url)); |
| - } catch (GalimatiasParseException e) { |
| - throw new MalformedURLException(e.getMessage()); |
| - } |
| + |
| + IRIFactory fac = new IRIFactory(); |
| + fac.shouldViolation(true, false); |
| + fac.securityViolation(true, false); |
| + fac.dnsViolation(true, false); |
| + fac.mintingViolation(false, false); |
| + fac.useSpecificationIRI(true); |
| + init(fac.construct(url)); |
| + |
| } |
| |
| /** |
| @@ -266,7 +271,7 @@ public class DataUri { |
| * @throws MalformedURLException |
| * @throws IOException |
| */ |
| - public DataUri(URL url) throws IOException, MalformedURLException { |
| + public DataUri(com.hp.hpl.jena.iri.IRI url) throws IOException, MalformedURLException { |
| init(url); |
| } |
| |
| diff --git a/src/nu/validator/localentities/LocalCacheEntityResolver.java b/src/nu/validator/localentities/LocalCacheEntityResolver.java |
| index 8b6ac69..18de3b8 100644 |
| --- a/src/nu/validator/localentities/LocalCacheEntityResolver.java |
| +++ b/src/nu/validator/localentities/LocalCacheEntityResolver.java |
| @@ -4,6 +4,7 @@ import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| +import java.net.URL; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| @@ -41,7 +42,7 @@ public class LocalCacheEntityResolver implements EntityResolver { |
| } |
| |
| public static InputStream getPresetsAsStream() { |
| - return LOADER.getResourceAsStream("nu/validator/localentities/files/presets"); |
| + return LOADER.getResourceAsStream("nu/validator/localentities/presets"); |
| } |
| |
| public static InputStream getHtml5SpecAsStream() { |
| @@ -53,18 +54,27 @@ public class LocalCacheEntityResolver implements EntityResolver { |
| private boolean allowRnc = false; |
| |
| /** |
| + * The map must be safe for concurrent reads. |
| + * |
| + * @param pathMap |
| * @param delegate |
| */ |
| public LocalCacheEntityResolver(EntityResolver delegate) { |
| this.delegate = delegate; |
| } |
| |
| + public static URL getResource(String systemId) { |
| + String path = PATH_MAP.get(systemId); |
| + return path != null ? LOADER.getResource(path) : null; |
| + } |
| + |
| /** |
| * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, |
| * java.lang.String) |
| */ |
| public InputSource resolveEntity(String publicId, String systemId) |
| throws SAXException, IOException { |
| + long a = System.currentTimeMillis(); |
| String path = PATH_MAP.get(systemId); |
| if (path != null) { |
| InputStream stream = LOADER.getResourceAsStream(path); |
| @@ -89,6 +99,7 @@ public class LocalCacheEntityResolver implements EntityResolver { |
| return is; |
| } |
| } |
| + System.out.println("resolve :" + publicId +" " + systemId); |
| return delegate.resolveEntity(publicId, systemId); |
| } |
| |
| @@ -106,4 +117,4 @@ public class LocalCacheEntityResolver implements EntityResolver { |
| public void setAllowRnc(boolean allowRnc) { |
| this.allowRnc = allowRnc; |
| } |
| -} |
| +} |
| \ No newline at end of file |
| diff --git a/src/nu/validator/localentities/presets b/src/nu/validator/localentities/presets |
| new file mode 100644 |
| index 0000000..7966803 |
| --- /dev/null |
| +++ b/src/nu/validator/localentities/presets |
| @@ -0,0 +1,10 @@ |
| +-1 - HTML5 + SVG 1.1 + MathML 3.0 http://s.validator.nu/html5.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| +-1 - HTML5 + SVG 1.1 + MathML 3.0 + ITS 2.0 http://s.validator.nu/html5-its.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| +3 - HTML5 + SVG 1.1 + MathML 3.0 + RDFa Lite 1.1 http://s.validator.nu/html5-rdfalite.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| +2 - HTML 4.01 Strict + IRI / XHTML 1.0 Strict + IRI http://s.validator.nu/xhtml10/xhtml-strict.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all-html4/ |
| +1 - HTML 4.01 Transitional + IRI / XHTML 1.0 Transitional + IRI http://s.validator.nu/xhtml10/xhtml-transitional.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all-html4/ |
| +-1 - HTML 4.01 Frameset + IRI / XHTML 1.0 Frameset + IRI http://s.validator.nu/xhtml10/xhtml-frameset.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all-html4/ |
| +-1 - XHTML5 + SVG 1.1 + MathML 3.0 http://s.validator.nu/xhtml5.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| +7 http://www.w3.org/1999/xhtml XHTML5 + SVG 1.1 + MathML 3.0 + RDFa Lite 1.1 http://s.validator.nu/xhtml5-rdfalite.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| +-1 - XHTML 1.0 Strict + IRI + Ruby + SVG 1.1 + MathML 3.0 http://s.validator.nu/xhtml1-ruby-rdf-svg-mathml.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all-html4/ |
| +-1 http://www.w3.org/2000/svg SVG 1.1 + IRI + XHTML5 + MathML 3.0 http://s.validator.nu/svg-xhtml5-rdf-mathml.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/ |
| \ No newline at end of file |
| diff --git a/src/nu/validator/messages/BufferingRootNamespaceSniffer.java b/src/nu/validator/messages/BufferingRootNamespaceSniffer.java |
| new file mode 100644 |
| index 0000000..13e5b07 |
| --- /dev/null |
| +++ b/src/nu/validator/messages/BufferingRootNamespaceSniffer.java |
| @@ -0,0 +1,172 @@ |
| +/* |
| + * Copyright (c) 2006 Henri Sivonen |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a |
| + * copy of this software and associated documentation files (the "Software"), |
| + * to deal in the Software without restriction, including without limitation |
| + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| + * and/or sell copies of the Software, and to permit persons to whom the |
| + * Software is furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| + * DEALINGS IN THE SOFTWARE. |
| + */ |
| + |
| +package nu.validator.messages; |
| + |
| +import java.util.Iterator; |
| +import java.util.LinkedList; |
| +import java.util.List; |
| +import org.xml.sax.Attributes; |
| +import org.xml.sax.ContentHandler; |
| +import org.xml.sax.Locator; |
| +import org.xml.sax.SAXException; |
| + |
| +public class BufferingRootNamespaceSniffer implements ContentHandler { |
| + |
| + private ContentHandler ch = null; |
| + |
| + private Locator locator = null; |
| + |
| + private List<String[]> namespaces = new LinkedList<String[]>(); |
| + |
| + private ValidationTransaction vst; |
| + |
| + public BufferingRootNamespaceSniffer(ValidationTransaction vst) { |
| + super(); |
| + this.vst = vst; |
| + } |
| + |
| + public void setContentHandler(ContentHandler contentHandler) throws SAXException { |
| + this.ch = contentHandler; |
| + if (locator != null) { |
| + ch.setDocumentLocator(locator); |
| + } |
| + ch.startDocument(); |
| + for (Iterator<String[]> iter = namespaces.iterator(); iter.hasNext();) { |
| + String[] element = iter.next(); |
| + ch.startPrefixMapping(element[0], element[1]); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#characters(char[], int, int) |
| + */ |
| + public void characters(char[] arg0, int arg1, int arg2) throws SAXException { |
| + if (ch != null) { |
| + ch.characters(arg0, arg1, arg2); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endDocument() |
| + */ |
| + public void endDocument() throws SAXException { |
| + if (ch != null) { |
| + ch.endDocument(); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endElement(java.lang.String, |
| + * java.lang.String, java.lang.String) |
| + */ |
| + public void endElement(String arg0, String arg1, String arg2) |
| + throws SAXException { |
| + if (ch != null) { |
| + ch.endElement(arg0, arg1, arg2); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) |
| + */ |
| + public void endPrefixMapping(String arg0) throws SAXException { |
| + if (ch != null) { |
| + ch.endPrefixMapping(arg0); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) |
| + */ |
| + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) |
| + throws SAXException { |
| + if (ch != null) { |
| + ch.ignorableWhitespace(arg0, arg1, arg2); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, |
| + * java.lang.String) |
| + */ |
| + public void processingInstruction(String arg0, String arg1) |
| + throws SAXException { |
| + if (ch != null) { |
| + ch.processingInstruction(arg0, arg1); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) |
| + */ |
| + public void setDocumentLocator(Locator arg0) { |
| + locator = arg0; |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) |
| + */ |
| + public void skippedEntity(String arg0) throws SAXException { |
| + if (ch != null) { |
| + ch.skippedEntity(arg0); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startDocument() |
| + */ |
| + public void startDocument() throws SAXException { |
| + |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startElement(java.lang.String, |
| + * java.lang.String, java.lang.String, org.xml.sax.Attributes) |
| + */ |
| + public void startElement(String arg0, String arg1, String arg2, |
| + Attributes arg3) throws SAXException { |
| + if (ch != null) { |
| + ch.startElement(arg0, arg1, arg2, arg3); |
| + } else { |
| + vst.rootNamespace(arg0, locator); |
| + ch.startElement(arg0, arg1, arg2, arg3); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, |
| + * java.lang.String) |
| + */ |
| + public void startPrefixMapping(String arg0, String arg1) |
| + throws SAXException { |
| + if (ch != null) { |
| + ch.startPrefixMapping(arg0, arg1); |
| + } else { |
| + String[] arr = new String[2]; |
| + arr[0] = arg0; |
| + arr[1] = arg1; |
| + namespaces.add(arr); |
| + } |
| + } |
| + |
| +} |
| diff --git a/src/nu/validator/messages/RootNamespaceSniffer.java b/src/nu/validator/messages/RootNamespaceSniffer.java |
| new file mode 100644 |
| index 0000000..1981475 |
| --- /dev/null |
| +++ b/src/nu/validator/messages/RootNamespaceSniffer.java |
| @@ -0,0 +1,121 @@ |
| +/* |
| + * Copyright (c) 2006 Henri Sivonen |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a |
| + * copy of this software and associated documentation files (the "Software"), |
| + * to deal in the Software without restriction, including without limitation |
| + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| + * and/or sell copies of the Software, and to permit persons to whom the |
| + * Software is furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| + * DEALINGS IN THE SOFTWARE. |
| + */ |
| + |
| +package nu.validator.messages; |
| + |
| +import org.xml.sax.Attributes; |
| +import org.xml.sax.ContentHandler; |
| +import org.xml.sax.Locator; |
| +import org.xml.sax.SAXException; |
| + |
| +public class RootNamespaceSniffer implements ContentHandler { |
| + |
| + private ValidationTransaction vst; |
| + private ContentHandler ch; |
| + private Locator locator; |
| + |
| + public RootNamespaceSniffer(ValidationTransaction vst, ContentHandler ch) { |
| + super(); |
| + this.vst = vst; |
| + this.ch = ch; |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#characters(char[], int, int) |
| + */ |
| + public void characters(char[] arg0, int arg1, int arg2) throws SAXException { |
| + ch.characters(arg0, arg1, arg2); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endDocument() |
| + */ |
| + public void endDocument() throws SAXException { |
| + ch.endDocument(); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) |
| + */ |
| + public void endElement(String arg0, String arg1, String arg2) throws SAXException { |
| + ch.endElement(arg0, arg1, arg2); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) |
| + */ |
| + public void endPrefixMapping(String arg0) throws SAXException { |
| + ch.endPrefixMapping(arg0); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) |
| + */ |
| + public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { |
| + ch.ignorableWhitespace(arg0, arg1, arg2); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) |
| + */ |
| + public void processingInstruction(String arg0, String arg1) throws SAXException { |
| + ch.processingInstruction(arg0, arg1); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) |
| + */ |
| + public void setDocumentLocator(Locator arg0) { |
| + this.locator = arg0; |
| + ch.setDocumentLocator(arg0); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) |
| + */ |
| + public void skippedEntity(String arg0) throws SAXException { |
| + ch.skippedEntity(arg0); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startDocument() |
| + */ |
| + public void startDocument() throws SAXException { |
| + ch.startDocument(); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) |
| + */ |
| + public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException { |
| + vst.rootNamespace(arg0, locator); |
| + ch.startElement(arg0, arg1, arg2, arg3); |
| + } |
| + |
| + /** |
| + * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) |
| + */ |
| + public void startPrefixMapping(String arg0, String arg1) throws SAXException { |
| + ch.startPrefixMapping(arg0, arg1); |
| + } |
| + |
| +} |
| diff --git a/src/nu/validator/messages/ValidationTransaction.java b/src/nu/validator/messages/ValidationTransaction.java |
| new file mode 100644 |
| index 0000000..9b60092 |
| --- /dev/null |
| +++ b/src/nu/validator/messages/ValidationTransaction.java |
| @@ -0,0 +1,466 @@ |
| +package nu.validator.messages; |
| + |
| +import com.thaiopensource.relaxng.impl.CombineValidator; |
| +import com.thaiopensource.util.PropertyMap; |
| +import com.thaiopensource.validate.IncorrectSchemaException; |
| +import com.thaiopensource.validate.Schema; |
| +import com.thaiopensource.validate.SchemaReader; |
| +import com.thaiopensource.validate.SchemaResolver; |
| +import com.thaiopensource.validate.Validator; |
| +import com.thaiopensource.validate.auto.AutoSchemaReader; |
| +import com.thaiopensource.validate.prop.wrap.WrapProperty; |
| +import com.thaiopensource.validate.rng.CompactSchemaReader; |
| +import java.io.IOException; |
| +import java.lang.ref.SoftReference; |
| +import java.util.Arrays; |
| +import java.util.HashMap; |
| +import java.util.Map; |
| +import java.util.logging.Level; |
| +import java.util.logging.Logger; |
| +import java.util.regex.Pattern; |
| +import nu.validator.checker.XmlPiChecker; |
| +import nu.validator.checker.jing.CheckerSchema; |
| +import nu.validator.htmlparser.common.DocumentMode; |
| +import nu.validator.htmlparser.common.DocumentModeHandler; |
| +import nu.validator.htmlparser.sax.HtmlParser; |
| +import nu.validator.localentities.LocalCacheEntityResolver; |
| +import nu.validator.spec.Spec; |
| +import nu.validator.xml.TypedInputSource; |
| +import org.xml.sax.ContentHandler; |
| +import org.xml.sax.EntityResolver; |
| +import org.xml.sax.Locator; |
| +import org.xml.sax.SAXException; |
| +import org.xml.sax.SAXParseException; |
| +import org.xml.sax.XMLReader; |
| +import org.xml.sax.ext.LexicalHandler; |
| + |
| +/** |
| + * This class code was mainly extracted from the original class {@link VerifierServletTransaction}. |
| + * |
| + * @author hsivonen, mfukala@netbeans.org |
| + */ |
| +public class ValidationTransaction implements DocumentModeHandler, SchemaResolver { |
| + private static final Logger LOGGER = Logger.getLogger(ValidationTransaction.class.getCanonicalName()); |
| + |
| + // XXX SVG!!! |
| + private static final String[] KNOWN_CONTENT_TYPES = { |
| + "application/atom+xml", "application/docbook+xml", |
| + "application/xhtml+xml", "application/xv+xml", "image/svg+xml"}; |
| + private static final String[] NAMESPACES_FOR_KNOWN_CONTENT_TYPES = { |
| + "http://www.w3.org/2005/Atom", "http://docbook.org/ns/docbook", |
| + "http://www.w3.org/1999/xhtml", "http://www.w3.org/1999/xhtml", |
| + "http://www.w3.org/2000/svg"}; |
| + protected static final String[] ALL_CHECKERS = { |
| + "http://c.validator.nu/table/", "http://c.validator.nu/nfc/", |
| + "http://c.validator.nu/text-content/", |
| + "http://c.validator.nu/unchecked/", |
| + "http://c.validator.nu/usemap/", "http://c.validator.nu/obsolete/", |
| + "http://c.validator.nu/xml-pi/"}; |
| + private static final String[] ALL_CHECKERS_HTML4 = { |
| + "http://c.validator.nu/table/", "http://c.validator.nu/nfc/", |
| + "http://c.validator.nu/unchecked/", "http://c.validator.nu/usemap/"}; |
| + |
| + protected BufferingRootNamespaceSniffer bufferingRootNamespaceSniffer = null; |
| + protected boolean rootNamespaceSeen = false; |
| + protected String contentType = null; |
| + |
| + protected static int[] presetDoctypes; |
| + protected static String[] presetLabels; |
| + protected static String[] presetUrls; |
| + protected static String[] presetNamespaces; |
| + |
| + protected MessageEmitterAdapter errorHandler; |
| + protected static String[] preloadedSchemaUrls; |
| + protected static Schema[] preloadedSchemas; |
| + |
| + private Map<String, Validator> loadedValidatorUrls = new HashMap<String, Validator>(); |
| + |
| + protected Validator validator = null; |
| + protected LocalCacheEntityResolver entityResolver; |
| + |
| + private static final Pattern SPACE = Pattern.compile("\\s+"); |
| + protected static final int HTML5_SCHEMA = 3; |
| + protected static final int XHTML1STRICT_SCHEMA = 2; |
| + protected static final int XHTML1FRAMESET_SCHEMA = 4; |
| + protected static final int XHTML1TRANSITIONAL_SCHEMA = 1; |
| + protected static final int XHTML5_SCHEMA = 7; |
| + |
| + public HtmlParser htmlParser = null; |
| + protected PropertyMap jingPropertyMap; |
| + protected static Spec html5spec; |
| + |
| + protected XMLReader reader; |
| + protected LexicalHandler lexicalHandler; |
| + |
| + public void rootNamespace(String namespace, Locator locator) throws SAXException { |
| + if (validator == null) { |
| + int index = -1; |
| + for (int i = 0; i < presetNamespaces.length; i++) { |
| + if (namespace.equals(presetNamespaces[i])) { |
| + index = i; |
| + break; |
| + } |
| + } |
| + if (index == -1) { |
| + String message = "Cannot find preset schema for namespace: \u201C" |
| + + namespace + "\u201D."; |
| + SAXException se = new SAXException(message); |
| + errorHandler.schemaError(se); |
| + throw se; |
| + } |
| + String label = presetLabels[index]; |
| + String urls = presetUrls[index]; |
| + errorHandler.info("Using the preset for " + label |
| + + " based on the root namespace " + namespace); |
| + try { |
| + validator = validatorByUrls(urls); |
| + } catch (IOException ioe) { |
| + // At this point the schema comes from memory. |
| + throw new RuntimeException(ioe); |
| + } catch (IncorrectSchemaException e) { |
| + // At this point the schema comes from memory. |
| + throw new RuntimeException(e); |
| + } |
| + if (bufferingRootNamespaceSniffer == null) { |
| + throw new RuntimeException( |
| + "Bug! bufferingRootNamespaceSniffer was null."); |
| + } |
| + bufferingRootNamespaceSniffer.setContentHandler(validator.getContentHandler()); |
| + } |
| + |
| + if (!rootNamespaceSeen) { |
| + rootNamespaceSeen = true; |
| + if (contentType != null) { |
| + int i; |
| + if ((i = Arrays.binarySearch(KNOWN_CONTENT_TYPES, contentType)) > -1) { |
| + if (!NAMESPACES_FOR_KNOWN_CONTENT_TYPES[i].equals(namespace)) { |
| + String message = "".equals(namespace) ? "\u201C" |
| + + contentType |
| + + "\u201D is not an appropriate Content-Type for a document whose root element is not in a namespace." |
| + : "\u201C" |
| + + contentType |
| + + "\u201D is not an appropriate Content-Type for a document whose root namespace is \u201C" |
| + + namespace + "\u201D."; |
| + SAXParseException spe = new SAXParseException(message, |
| + locator); |
| + errorHandler.warning(spe); |
| + } |
| + } |
| + } |
| + } |
| + } |
| + |
| + @Override |
| + public void documentMode(DocumentMode mode, String publicIdentifier, |
| + String systemIdentifier, boolean html4SpecificAdditionalErrorChecks) |
| + throws SAXException { |
| + if (validator == null) { |
| + try { |
| + if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicIdentifier)) { |
| + errorHandler.info("XHTML 1.0 Transitional doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for " |
| + + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| + : "")); |
| + validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| + } else if ("-//W3C//DTD XHTML 1.0 Strict//EN".equals(publicIdentifier)) { |
| + errorHandler.info("XHTML 1.0 Strict doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for " |
| + + getPresetLabel(XHTML1STRICT_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| + : "")); |
| + validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| + } else if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier)) { |
| + errorHandler.info("HTML 4.01 Transitional doctype seen. Using the schema for " |
| + + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? "" |
| + : " HTML4-specific tokenization errors are not enabled.")); |
| + validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| + } else if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) { |
| + errorHandler.info("HTML 4.01 Strict doctype seen. Using the schema for " |
| + + getPresetLabel(XHTML1STRICT_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? "" |
| + : " HTML4-specific tokenization errors are not enabled.")); |
| + validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| + } else if ("-//W3C//DTD HTML 4.0 Transitional//EN".equals(publicIdentifier)) { |
| + errorHandler.info("Legacy HTML 4.0 Transitional doctype seen. Please consider using HTML 4.01 Transitional instead. Proceeding anyway for your convenience with the schema for " |
| + + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? "" |
| + : " HTML4-specific tokenization errors are not enabled.")); |
| + validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| + } else if ("-//W3C//DTD HTML 4.0//EN".equals(publicIdentifier)) { |
| + errorHandler.info("Legacy HTML 4.0 Strict doctype seen. Please consider using HTML 4.01 instead. Proceeding anyway for your convenience with the schema for " |
| + + getPresetLabel(XHTML1STRICT_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? "" |
| + : " HTML4-specific tokenization errors are not enabled.")); |
| + validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| + } else { |
| + errorHandler.info("Using the schema for " |
| + + getPresetLabel(HTML5_SCHEMA) |
| + + "." |
| + + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| + : "")); |
| + validator = validatorByDoctype(HTML5_SCHEMA); |
| + } |
| + } catch (IOException ioe) { |
| + // At this point the schema comes from memory. |
| + throw new RuntimeException(ioe); |
| + } catch (IncorrectSchemaException e) { |
| + // At this point the schema comes from memory. |
| + throw new RuntimeException(e); |
| + } |
| + ContentHandler ch = validator.getContentHandler(); |
| + ch.setDocumentLocator(htmlParser.getDocumentLocator()); |
| + ch.startDocument(); |
| + reader.setContentHandler(ch); |
| + } else { |
| + if (html4SpecificAdditionalErrorChecks) { |
| + errorHandler.info("HTML4-specific tokenization errors are enabled."); |
| + } |
| + } |
| + } |
| + |
| + public Schema resolveSchema(String url, PropertyMap options) |
| + throws SAXException, IOException, IncorrectSchemaException { |
| + int i = Arrays.binarySearch(preloadedSchemaUrls, url); |
| + if (i > -1) { |
| + Schema rv = preloadedSchemas[i]; |
| + if (options.contains(WrapProperty.ATTRIBUTE_OWNER)) { |
| + if(rv instanceof ValidationTransaction.ProxySchema && ((ValidationTransaction.ProxySchema)rv).getWrappedSchema() instanceof CheckerSchema) { |
| + errorHandler.error(new SAXParseException( |
| + "A non-schema checker cannot be used as an attribute schema.", |
| + null, url, -1, -1)); |
| + throw new IncorrectSchemaException(); |
| + } else { |
| + // ugly fall through |
| + } |
| + } else { |
| + return rv; |
| + } |
| + } |
| + |
| + //this code line should not normally be encountered since the necessary |
| + //schemas have been preloaded |
| + LOGGER.log(Level.INFO, "Going to create a non preloaded Schema for {0}", url); //NOI18N |
| + |
| + TypedInputSource schemaInput = (TypedInputSource) entityResolver.resolveEntity( |
| + null, url); |
| + SchemaReader sr = null; |
| + if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) { |
| + sr = CompactSchemaReader.getInstance(); |
| + } else { |
| + sr = new AutoSchemaReader(); |
| + } |
| + Schema sch = sr.createSchema(schemaInput, options); |
| + return sch; |
| + } |
| + |
| + /** |
| + * @param validator |
| + * @return |
| + * @throws SAXException |
| + * @throws IOException |
| + * @throws IncorrectSchemaException |
| + */ |
| + protected Validator validatorByUrls(String schemaList) throws SAXException, |
| + IOException, IncorrectSchemaException { |
| + Validator v = null; |
| + String[] schemas = SPACE.split(schemaList); |
| + for (int i = schemas.length - 1; i > -1; i--) { |
| + String url = schemas[i]; |
| + if ("http://c.validator.nu/all/".equals(url) |
| + || "http://hsivonen.iki.fi/checkers/all/".equals(url)) { |
| + for (int j = 0; j < ALL_CHECKERS.length; j++) { |
| + v = combineValidatorByUrl(v, ALL_CHECKERS[j]); |
| + } |
| + } else if ("http://c.validator.nu/all-html4/".equals(url) |
| + || "http://hsivonen.iki.fi/checkers/all-html4/".equals(url)) { |
| + for (int j = 0; j < ALL_CHECKERS_HTML4.length; j++) { |
| + v = combineValidatorByUrl(v, ALL_CHECKERS_HTML4[j]); |
| + } |
| + } else { |
| + v = combineValidatorByUrl(v, url); |
| + } |
| + } |
| + return v; |
| + } |
| + |
| + /** |
| + * @param val |
| + * @param url |
| + * @return |
| + * @throws SAXException |
| + * @throws IOException |
| + * @throws IncorrectSchemaException |
| + */ |
| + private Validator combineValidatorByUrl(Validator val, String url) |
| + throws SAXException, IOException, IncorrectSchemaException { |
| + if (!"".equals(url)) { |
| + Validator v = validatorByUrl(url); |
| + if (val == null) { |
| + val = v; |
| + } else { |
| + val = new CombineValidator(v, val); |
| + } |
| + } |
| + return val; |
| + } |
| + |
| + /** |
| + * @param url |
| + * @return |
| + * @throws SAXException |
| + * @throws IOException |
| + * @throws IncorrectSchemaException |
| + */ |
| + private Validator validatorByUrl(String url) throws SAXException, |
| + IOException, IncorrectSchemaException { |
| + Validator v = loadedValidatorUrls.get(url); |
| + if (v != null) { |
| + return v; |
| + } |
| + |
| + |
| + if ("http://s.validator.nu/html5/html5full-aria.rnc".equals(url) |
| + || "http://s.validator.nu/xhtml5-aria-rdf-svg-mathml.rnc".equals(url) |
| + || "http://s.validator.nu/html5/html5full.rnc".equals(url) |
| + || "http://s.validator.nu/html5/xhtml5full-xhtml.rnc".equals(url) |
| + || "http://s.validator.nu/html5-aria-svg-mathml.rnc".equals(url)) { |
| + errorHandler.setSpec(html5spec); |
| + } |
| + Schema sch = resolveSchema(url, jingPropertyMap); |
| + Validator validatorInstance = sch.createValidator(jingPropertyMap); |
| + if (validatorInstance.getContentHandler() instanceof XmlPiChecker) { |
| + lexicalHandler = (LexicalHandler) validatorInstance.getContentHandler(); |
| + } |
| + |
| + loadedValidatorUrls.put(url, v); |
| + return validatorInstance; |
| + } |
| + |
| + private String getPresetLabel(int schemaId) { |
| + for (int i = 0; i < presetDoctypes.length; i++) { |
| + if (presetDoctypes[i] == schemaId) { |
| + return presetLabels[i]; |
| + } |
| + } |
| + return "unknown"; |
| + } |
| + |
| + protected Validator validatorByDoctype(int schemaId) throws SAXException, |
| + IOException, IncorrectSchemaException { |
| + if (schemaId == 0) { |
| + return null; |
| + } |
| + for (int i = 0; i < presetDoctypes.length; i++) { |
| + if (presetDoctypes[i] == schemaId) { |
| + return validatorByUrls(presetUrls[i]); |
| + } |
| + } |
| + throw new RuntimeException("Doctype mappings not initialized properly."); |
| + } |
| + |
| + |
| + /** |
| + * @param url |
| + * @return |
| + * @throws SAXException |
| + * @throws IOException |
| + * @throws IncorrectSchemaException |
| + */ |
| + private static Schema schemaByUrl(String url, EntityResolver resolver, |
| + PropertyMap pMap) throws SAXException, IOException, |
| + IncorrectSchemaException { |
| + LOGGER.fine(String.format("Will load schema: %s", url)); |
| + long a = System.currentTimeMillis(); |
| + TypedInputSource schemaInput; |
| + try { |
| + schemaInput = (TypedInputSource) resolver.resolveEntity( |
| + null, url); |
| + } catch (ClassCastException e) { |
| + LOGGER.log(Level.SEVERE, url, e); |
| + throw e; |
| + } |
| + |
| + SchemaReader sr = null; |
| + if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) { |
| + sr = CompactSchemaReader.getInstance(); |
| + LOGGER.log(Level.FINE, "Used CompactSchemaReader"); |
| + } else { |
| + sr = new AutoSchemaReader(); |
| + LOGGER.log(Level.FINE, "Used AutoSchemaReader"); |
| + } |
| + long c = System.currentTimeMillis(); |
| + |
| + Schema sch = sr.createSchema(schemaInput, pMap); |
| + LOGGER.log(Level.FINE, String.format("Schema created in %s ms.", (System.currentTimeMillis() - c))); |
| + return sch; |
| + } |
| + |
| + protected static Schema proxySchemaByUrl(String uri, EntityResolver resolver, PropertyMap pMap) { |
| + return new ProxySchema(uri, resolver, pMap); |
| + } |
| + |
| + /** |
| + * A Schema instance delegate, the delegated instance if softly reachable so it should |
| + * not be GCed so often. If the delegate is GCed a new instance is recreated. |
| + */ |
| + private static class ProxySchema implements Schema { |
| + |
| + private String uri; |
| + private EntityResolver resolver; |
| + private PropertyMap pMap; |
| + |
| + private SoftReference<Schema> delegateWeakRef; |
| + |
| + private ProxySchema(String uri, EntityResolver resolver, PropertyMap pMap) { |
| + this.uri = uri; |
| + this.resolver = resolver; |
| + this.pMap = pMap; |
| + } |
| + |
| + //exposing just because of some instanceof test used in the code |
| + private Schema getWrappedSchema() throws SAXException, IOException, IncorrectSchemaException { |
| + return getSchemaDelegate(); |
| + } |
| + |
| + public Validator createValidator(PropertyMap pm) { |
| + try { |
| + return getSchemaDelegate().createValidator(pm); |
| + } catch (Exception ex) { //SAXException, IOException, IncorrectSchemaException |
| + LOGGER.log(Level.INFO, "Cannot create schema delegate", ex); //NOI18N |
| + } |
| + return null; |
| + } |
| + |
| + public PropertyMap getProperties() { |
| + try { |
| + return getSchemaDelegate().getProperties(); |
| + } catch (Exception ex) { //SAXException, IOException, IncorrectSchemaException |
| + LOGGER.log(Level.INFO, "Cannot create schema delegate", ex); //NOI18N |
| + } |
| + return null; |
| + } |
| + |
| + private synchronized Schema getSchemaDelegate() throws SAXException, IOException, IncorrectSchemaException { |
| + Schema delegate = delegateWeakRef != null ? delegateWeakRef.get() : null; |
| + if(delegate == null) { |
| + long a = System.currentTimeMillis(); |
| + delegate = schemaByUrl(uri, resolver, pMap); |
| + long b = System.currentTimeMillis(); |
| + delegateWeakRef = new SoftReference<Schema>(delegate); |
| + LOGGER.log(Level.FINE, "Created new Schema instance for {0} in {1}ms.", new Object[]{uri, (b-a)}); |
| + } else { |
| + LOGGER.log(Level.FINE, "Using cached Schema instance for {0}", uri); |
| + } |
| + return delegate; |
| + } |
| + |
| + |
| + } |
| + |
| +} |
| diff --git a/src/nu/validator/servlet/BufferingRootNamespaceSniffer.java b/src/nu/validator/servlet/BufferingRootNamespaceSniffer.java |
| deleted file mode 100644 |
| index f339667..0000000 |
| --- a/src/nu/validator/servlet/BufferingRootNamespaceSniffer.java |
| +++ /dev/null |
| @@ -1,173 +0,0 @@ |
| -/* |
| - * Copyright (c) 2006 Henri Sivonen |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.util.Iterator; |
| -import java.util.LinkedList; |
| -import java.util.List; |
| - |
| -import org.xml.sax.Attributes; |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| - |
| -public class BufferingRootNamespaceSniffer implements ContentHandler { |
| - |
| - private ContentHandler ch = null; |
| - |
| - private Locator locator = null; |
| - |
| - private List<String[]> namespaces = new LinkedList<String[]>(); |
| - |
| - private VerifierServletTransaction vst; |
| - |
| - public BufferingRootNamespaceSniffer(VerifierServletTransaction vst) { |
| - super(); |
| - this.vst = vst; |
| - } |
| - |
| - public void setContentHandler(ContentHandler contentHandler) throws SAXException { |
| - this.ch = contentHandler; |
| - if (locator != null) { |
| - ch.setDocumentLocator(locator); |
| - } |
| - ch.startDocument(); |
| - for (Iterator<String[]> iter = namespaces.iterator(); iter.hasNext();) { |
| - String[] element = iter.next(); |
| - ch.startPrefixMapping(element[0], element[1]); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#characters(char[], int, int) |
| - */ |
| - public void characters(char[] arg0, int arg1, int arg2) throws SAXException { |
| - if (ch != null) { |
| - ch.characters(arg0, arg1, arg2); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endDocument() |
| - */ |
| - public void endDocument() throws SAXException { |
| - if (ch != null) { |
| - ch.endDocument(); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endElement(java.lang.String, |
| - * java.lang.String, java.lang.String) |
| - */ |
| - public void endElement(String arg0, String arg1, String arg2) |
| - throws SAXException { |
| - if (ch != null) { |
| - ch.endElement(arg0, arg1, arg2); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) |
| - */ |
| - public void endPrefixMapping(String arg0) throws SAXException { |
| - if (ch != null) { |
| - ch.endPrefixMapping(arg0); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) |
| - */ |
| - public void ignorableWhitespace(char[] arg0, int arg1, int arg2) |
| - throws SAXException { |
| - if (ch != null) { |
| - ch.ignorableWhitespace(arg0, arg1, arg2); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, |
| - * java.lang.String) |
| - */ |
| - public void processingInstruction(String arg0, String arg1) |
| - throws SAXException { |
| - if (ch != null) { |
| - ch.processingInstruction(arg0, arg1); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) |
| - */ |
| - public void setDocumentLocator(Locator arg0) { |
| - locator = arg0; |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) |
| - */ |
| - public void skippedEntity(String arg0) throws SAXException { |
| - if (ch != null) { |
| - ch.skippedEntity(arg0); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startDocument() |
| - */ |
| - public void startDocument() throws SAXException { |
| - |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startElement(java.lang.String, |
| - * java.lang.String, java.lang.String, org.xml.sax.Attributes) |
| - */ |
| - public void startElement(String arg0, String arg1, String arg2, |
| - Attributes arg3) throws SAXException { |
| - if (ch != null) { |
| - ch.startElement(arg0, arg1, arg2, arg3); |
| - } else { |
| - vst.rootNamespace(arg0, locator); |
| - ch.startElement(arg0, arg1, arg2, arg3); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, |
| - * java.lang.String) |
| - */ |
| - public void startPrefixMapping(String arg0, String arg1) |
| - throws SAXException { |
| - if (ch != null) { |
| - ch.startPrefixMapping(arg0, arg1); |
| - } else { |
| - String[] arr = new String[2]; |
| - arr[0] = arg0; |
| - arr[1] = arg1; |
| - namespaces.add(arr); |
| - } |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/CharsetEmitter.java b/src/nu/validator/servlet/CharsetEmitter.java |
| deleted file mode 100644 |
| index 6b795b8..0000000 |
| --- a/src/nu/validator/servlet/CharsetEmitter.java |
| +++ /dev/null |
| @@ -1,38 +0,0 @@ |
| -/* This code was generated by nu.validator.tools.SaxCompiler. Please regenerate instead of editing. */ |
| -package nu.validator.servlet; |
| -public final class CharsetEmitter { |
| -private CharsetEmitter() {} |
| -public static void emit(org.xml.sax.ContentHandler contentHandler, nu.validator.servlet.VerifierServletTransaction t) throws org.xml.sax.SAXException { |
| -org.xml.sax.helpers.AttributesImpl __attrs__ = new org.xml.sax.helpers.AttributesImpl(); |
| -contentHandler.startPrefixMapping("", "http://www.w3.org/1999/xhtml"); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "Override for transfer protocol character encoding declaration."); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "for", "for", "CDATA", "charset"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "label", "label", __attrs__); |
| -contentHandler.characters(__chars__, 0, 8); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "label", "label"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "id", "id", "CDATA", "charset"); |
| -__attrs__.addAttribute("", "name", "name", "CDATA", "charset"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "select", "select", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "value", "value", "CDATA", ""); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "option", "option", __attrs__); |
| -contentHandler.characters(__chars__, 8, 25); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "option", "option"); |
| -t.emitCharsetOptions(); |
| - |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "select", "select"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -contentHandler.endPrefixMapping(""); |
| -} |
| -private static final char[] __chars__ = { 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', 'A', 's', ' ', 's', 'e', 't', ' ', 'b', 'y', ' ', 't', 'h', 'e', ' ', 's', 'e', 'r', 'v', 'e', 'r', '/', 'p', 'a', 'g', 'e' }; |
| -} |
| diff --git a/src/nu/validator/servlet/CssDetector.java b/src/nu/validator/servlet/CssDetector.java |
| deleted file mode 100644 |
| index e9308d7..0000000 |
| --- a/src/nu/validator/servlet/CssDetector.java |
| +++ /dev/null |
| @@ -1,160 +0,0 @@ |
| -/* |
| - * Copyright (c) 2008 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.util.regex.Matcher; |
| -import java.util.regex.Pattern; |
| - |
| -import nu.validator.checker.AttributeUtil; |
| -import org.xml.sax.Attributes; |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.DTDHandler; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| - |
| -import com.thaiopensource.validate.Validator; |
| - |
| -public class CssDetector implements Validator, ContentHandler { |
| - |
| - public static boolean lowerCaseLiteralEqualsIgnoreAsciiCase(String lowerCaseLiteral, |
| - String string) { |
| - if (string == null) { |
| - return false; |
| - } |
| - if (lowerCaseLiteral.length() != string.length()) { |
| - return false; |
| - } |
| - for (int i = 0; i < lowerCaseLiteral.length(); i++) { |
| - char c0 = lowerCaseLiteral.charAt(i); |
| - char c1 = string.charAt(i); |
| - if (c1 >= 'A' && c1 <= 'Z') { |
| - c1 += 0x20; |
| - } |
| - if (c0 != c1) { |
| - return false; |
| - } |
| - } |
| - return true; |
| - } |
| - |
| - private static final Pattern TEXT_CSS = Pattern.compile("^[tT][eE][xX][tT]/[cC][sS][sS]\\s*(?:;.*)?$"); |
| - |
| - private boolean sawCss = false; |
| - |
| - public ContentHandler getContentHandler() { |
| - return this; |
| - } |
| - |
| - public DTDHandler getDTDHandler() { |
| - return null; |
| - } |
| - |
| - public void reset() { |
| - sawCss = false; |
| - } |
| - |
| - public void characters(char[] ch, int start, int length) |
| - throws SAXException { |
| - |
| - } |
| - |
| - public void endDocument() throws SAXException { |
| - |
| - } |
| - |
| - public void endElement(String uri, String localName, String name) |
| - throws SAXException { |
| - |
| - } |
| - |
| - public void endPrefixMapping(String prefix) throws SAXException { |
| - // TODO Auto-generated method stub |
| - |
| - } |
| - |
| - public void ignorableWhitespace(char[] ch, int start, int length) |
| - throws SAXException { |
| - |
| - } |
| - |
| - public void processingInstruction(String target, String data) |
| - throws SAXException { |
| - |
| - } |
| - |
| - public void setDocumentLocator(Locator locator) { |
| - |
| - } |
| - |
| - public void skippedEntity(String name) throws SAXException { |
| - |
| - } |
| - |
| - public void startDocument() throws SAXException { |
| - reset(); |
| - } |
| - |
| - public void startElement(String uri, String localName, String name, |
| - Attributes atts) throws SAXException { |
| - if ("http://www.w3.org/1999/xhtml" == uri) { |
| - if ("style" == localName) { |
| - checkType(atts); |
| - return; |
| - } else if ("link" == localName) { |
| - String rel = atts.getValue("", "rel"); |
| - if (rel != null) { |
| - String[] tokens = AttributeUtil.split(rel); |
| - for (int i = 0; i < tokens.length; i++) { |
| - String token = tokens[i]; |
| - if (lowerCaseLiteralEqualsIgnoreAsciiCase("stylesheet", token)) { |
| - checkType(atts); |
| - return; |
| - } |
| - } |
| - } |
| - } else { |
| - if (atts.getIndex("", "style") > -1) { |
| - sawCss = true; |
| - } |
| - } |
| - } |
| - } |
| - |
| - private void checkType(Attributes atts) { |
| - String type = atts.getValue("", "type"); |
| - if (type == null) { |
| - sawCss = true; |
| - } else { |
| - Matcher m = TEXT_CSS.matcher(type); |
| - if (m.matches()) { |
| - sawCss = true; |
| - } |
| - } |
| - } |
| - |
| - public void startPrefixMapping(String prefix, String uri) |
| - throws SAXException { |
| - |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/DelegatingServletInputStream.java b/src/nu/validator/servlet/DelegatingServletInputStream.java |
| deleted file mode 100644 |
| index db669fa..0000000 |
| --- a/src/nu/validator/servlet/DelegatingServletInputStream.java |
| +++ /dev/null |
| @@ -1,166 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.io.InputStream; |
| - |
| -import javax.servlet.ReadListener; |
| -import javax.servlet.ServletInputStream; |
| - |
| -public final class DelegatingServletInputStream extends ServletInputStream { |
| - |
| - private final InputStream delegate; |
| - |
| - public DelegatingServletInputStream(InputStream delegate) { |
| - this.delegate = delegate; |
| - } |
| - |
| - /** |
| - * @return |
| - * @throws IOException |
| - * @see java.io.InputStream#available() |
| - */ |
| - public int available() throws IOException { |
| - return delegate.available(); |
| - } |
| - |
| - /** |
| - * @throws IOException |
| - * @see java.io.InputStream#close() |
| - */ |
| - public void close() throws IOException { |
| - delegate.close(); |
| - } |
| - |
| - /** |
| - * @param obj |
| - * @return |
| - * @see java.lang.Object#equals(java.lang.Object) |
| - */ |
| - public boolean equals(Object obj) { |
| - return delegate.equals(obj); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see java.lang.Object#hashCode() |
| - */ |
| - public int hashCode() { |
| - return delegate.hashCode(); |
| - } |
| - |
| - /** |
| - * @param readlimit |
| - * @see java.io.InputStream#mark(int) |
| - */ |
| - public void mark(int readlimit) { |
| - delegate.mark(readlimit); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see java.io.InputStream#markSupported() |
| - */ |
| - public boolean markSupported() { |
| - return delegate.markSupported(); |
| - } |
| - |
| - /** |
| - * @return |
| - * @throws IOException |
| - * @see java.io.InputStream#read() |
| - */ |
| - public int read() throws IOException { |
| - return delegate.read(); |
| - } |
| - |
| - /** |
| - * @param b |
| - * @param off |
| - * @param len |
| - * @return |
| - * @throws IOException |
| - * @see java.io.InputStream#read(byte[], int, int) |
| - */ |
| - public int read(byte[] b, int off, int len) throws IOException { |
| - return delegate.read(b, off, len); |
| - } |
| - |
| - /** |
| - * @param b |
| - * @return |
| - * @throws IOException |
| - * @see java.io.InputStream#read(byte[]) |
| - */ |
| - public int read(byte[] b) throws IOException { |
| - return delegate.read(b); |
| - } |
| - |
| - /** |
| - * @throws IOException |
| - * @see java.io.InputStream#reset() |
| - */ |
| - public void reset() throws IOException { |
| - delegate.reset(); |
| - } |
| - |
| - /** |
| - * @param n |
| - * @return |
| - * @throws IOException |
| - * @see java.io.InputStream#skip(long) |
| - */ |
| - public long skip(long n) throws IOException { |
| - return delegate.skip(n); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see java.lang.Object#toString() |
| - */ |
| - public String toString() { |
| - return delegate.toString(); |
| - } |
| - |
| - /** |
| - * @return |
| - */ |
| - @Override public boolean isFinished() { |
| - return false; |
| - } |
| - |
| - /** |
| - * @return |
| - */ |
| - @Override public boolean isReady() { |
| - return false; |
| - } |
| - |
| - /** |
| - * @param arg0 |
| - */ |
| - @Override public void setReadListener(ReadListener arg0) { |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/Html5ConformanceCheckerTransaction.java b/src/nu/validator/servlet/Html5ConformanceCheckerTransaction.java |
| deleted file mode 100644 |
| index f9837f8..0000000 |
| --- a/src/nu/validator/servlet/Html5ConformanceCheckerTransaction.java |
| +++ /dev/null |
| @@ -1,194 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005, 2006 Henri Sivonen |
| - * Copyright (c) 2007-2010 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| - |
| -import javax.servlet.ServletException; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import nu.validator.htmlparser.common.DoctypeExpectation; |
| - |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXNotRecognizedException; |
| -import org.xml.sax.SAXNotSupportedException; |
| -import org.xml.sax.SAXParseException; |
| - |
| -import com.thaiopensource.validate.IncorrectSchemaException; |
| - |
| - |
| -public class Html5ConformanceCheckerTransaction extends |
| - VerifierServletTransaction { |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#isSimple() |
| - */ |
| - @Override |
| - protected boolean isSimple() { |
| - return true; |
| - } |
| - |
| - private final static String GENERIC_FACET = (VerifierServlet.GENERIC_HOST.isEmpty() ? "" : ("//" + VerifierServlet.GENERIC_HOST)) + VerifierServlet.GENERIC_PATH; |
| - |
| - private static final char[] GENERIC_UI = "More options".toCharArray(); |
| - |
| - private static final char[] SERVICE_TITLE = (System.getProperty( |
| - "nu.validator.servlet.service-name", "Validator.nu") + " (X)HTML5 Validator ").toCharArray(); |
| - |
| - private static final char[] TECHNOLOGY_PREVIEW = "(Living Validator)".toCharArray(); |
| - |
| - private static final char[] RESULTS_TITLE = "(X)HTML5 validation results".toCharArray(); |
| - |
| - private static final char[] FOR = " for ".toCharArray(); |
| - |
| - private static final String SUCCESS_HTML = "The document is valid HTML5 + ARIA + SVG 1.1 + MathML 2.0 (subject to the utter previewness of this service)."; |
| - |
| - private static final String SUCCESS_XHTML = "The document is valid XHTML5 + ARIA + SVG 1.1 + MathML 2.0 (subject to the utter previewness of this service)."; |
| - |
| - private static final String FAILURE_HTML = "There were errors. (Tried in the text/html mode.)"; |
| - |
| - private static final String FAILURE_XHTML = "There were errors. (Tried in the XHTML mode.)"; |
| - |
| - private boolean usingHtml = false; |
| - |
| - public Html5ConformanceCheckerTransaction(HttpServletRequest request, |
| - HttpServletResponse response) { |
| - super(request, response); |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#successMessage() |
| - */ |
| - protected String successMessage() throws SAXException { |
| - if (usingHtml) { |
| - return SUCCESS_HTML; |
| - } else { |
| - return SUCCESS_XHTML; |
| - } |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#loadDocAndSetupParser() |
| - */ |
| - protected void loadDocAndSetupParser() throws SAXException, IOException, IncorrectSchemaException, SAXNotRecognizedException, SAXNotSupportedException { |
| - setAllowGenericXml(false); |
| - setAcceptAllKnownXmlTypes(false); |
| - setAllowHtml(true); |
| - setAllowXhtml(true); |
| - loadDocumentInput(); |
| - String type = documentInput.getType(); |
| - if ("text/html".equals(type) || "text/html-sandboxed".equals(type)) { |
| - validator = validatorByDoctype(HTML5_SCHEMA); |
| - usingHtml = true; |
| - newHtmlParser(); |
| - htmlParser.setDoctypeExpectation(DoctypeExpectation.HTML); |
| - htmlParser.setDocumentModeHandler(this); |
| - htmlParser.setContentHandler(validator.getContentHandler()); |
| - reader = htmlParser; |
| - } else { |
| - validator = validatorByDoctype(XHTML5_SCHEMA); |
| - setupXmlParser(); |
| - if (!("application/xhtml+xml".equals(type) || "application/xml".equals(type))) { |
| - String message = "The preferred Content-Type for XHTML5 is application/xhtml+xml. The Content-Type was " + type + "."; |
| - SAXParseException spe = new SAXParseException(message, null, documentInput.getSystemId(), -1, -1); |
| - errorHandler.warning(spe); |
| - } |
| - } |
| - |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#setup() |
| - */ |
| - protected void setup() throws ServletException { |
| - // No-op |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#emitTitle() |
| - */ |
| - void emitTitle(boolean markupAllowed) throws SAXException { |
| - if (willValidate()) { |
| - emitter.characters(RESULTS_TITLE); |
| - if (document != null && document.length() > 0) { |
| - emitter.characters(FOR); |
| - emitter.characters(scrub(shortenDataUri(document))); |
| - } |
| - } else { |
| - emitter.characters(SERVICE_TITLE); |
| - if (markupAllowed && System.getProperty("nu.validator.servlet.service-name", "Validator.nu").equals("Validator.nu")) { |
| - emitter.startElement("span"); |
| - emitter.characters(TECHNOLOGY_PREVIEW); |
| - emitter.endElement("span"); |
| - } |
| - } |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#tryToSetupValidator() |
| - */ |
| - protected void tryToSetupValidator() throws SAXException, IOException, IncorrectSchemaException { |
| - // No-op |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#failureMessage() |
| - */ |
| - protected String failureMessage() throws SAXException { |
| - if (usingHtml) { |
| - return FAILURE_HTML; |
| - } else { |
| - return FAILURE_XHTML; |
| - } |
| - } |
| - |
| - /** |
| - * @see nu.validator.servlet.VerifierServletTransaction#emitFormContent() |
| - */ |
| - protected void emitFormContent() throws SAXException { |
| - Html5FormEmitter.emit(contentHandler, this); |
| - } |
| - |
| - void maybeEmitNsfilterField() throws SAXException { |
| - if (request.getParameter("nsfilter") != null) { |
| - NsFilterEmitter.emit(contentHandler, this); |
| - } |
| - } |
| - |
| - void maybeEmitCharsetField() throws SAXException { |
| - if (request.getParameter("charset") != null) { |
| - CharsetEmitter.emit(contentHandler, this); |
| - } |
| - } |
| - |
| - void emitOtherFacetLink() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("href", GENERIC_FACET); |
| - emitter.startElement("a", attrs); |
| - emitter.characters(GENERIC_UI); |
| - emitter.endElement("a"); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/Html5FormEmitter.java b/src/nu/validator/servlet/Html5FormEmitter.java |
| deleted file mode 100644 |
| index a2901ba..0000000 |
| --- a/src/nu/validator/servlet/Html5FormEmitter.java |
| +++ /dev/null |
| @@ -1,90 +0,0 @@ |
| -/* This code was generated by nu.validator.tools.SaxCompiler. Please regenerate instead of editing. */ |
| -package nu.validator.servlet; |
| -public final class Html5FormEmitter { |
| -private Html5FormEmitter() {} |
| -public static void emit(org.xml.sax.ContentHandler contentHandler, nu.validator.servlet.VerifierServletTransaction t) throws org.xml.sax.SAXException { |
| -org.xml.sax.helpers.AttributesImpl __attrs__ = new org.xml.sax.helpers.AttributesImpl(); |
| -contentHandler.startPrefixMapping("", "http://www.w3.org/1999/xhtml"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "fieldset", "fieldset", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "legend", "legend", __attrs__); |
| -contentHandler.characters(__chars__, 0, 15); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "legend", "legend"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "table", "table", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tbody", "tbody", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "The document to validate."); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "for", "for", "CDATA", "doc"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "label", "label", __attrs__); |
| -contentHandler.characters(__chars__, 15, 8); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "label", "label"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -t.emitDocField(); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -t.maybeEmitCharsetField(); t.maybeEmitNsfilterField(); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "Display a report about the textual alternatives for images."); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "for", "for", "CDATA", "showimagereport"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "label", "label", __attrs__); |
| -t.emitShowImageReportField(); |
| - |
| -contentHandler.characters(__chars__, 23, 18); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "label", "label"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "Display the markup source of the input document."); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "for", "for", "CDATA", "showsource"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "label", "label", __attrs__); |
| -t.emitShowSourceField(); |
| - |
| -contentHandler.characters(__chars__, 41, 12); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "label", "label"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "value", "value", "CDATA", "Validate"); |
| -__attrs__.addAttribute("", "type", "type", "CDATA", "submit"); |
| -__attrs__.addAttribute("", "id", "id", "CDATA", "submit"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "input", "input", __attrs__); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "input", "input"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tbody", "tbody"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "table", "table"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "fieldset", "fieldset"); |
| -contentHandler.endPrefixMapping(""); |
| -} |
| -private static final char[] __chars__ = { 'V', 'a', 'l', 'i', 'd', 'a', 't', 'o', 'r', ' ', 'I', 'n', 'p', 'u', 't', 'D', 'o', 'c', 'u', 'm', 'e', 'n', 't', ' ', 'S', 'h', 'o', 'w', ' ', 'I', 'm', 'a', 'g', 'e', ' ', 'R', 'e', 'p', 'o', 'r', 't', ' ', 'S', 'h', 'o', 'w', ' ', 'S', 'o', 'u', 'r', 'c', 'e' }; |
| -} |
| diff --git a/src/nu/validator/servlet/InboundGzipFilter.java b/src/nu/validator/servlet/InboundGzipFilter.java |
| deleted file mode 100644 |
| index e5c13a9..0000000 |
| --- a/src/nu/validator/servlet/InboundGzipFilter.java |
| +++ /dev/null |
| @@ -1,180 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007-2008 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.util.ArrayList; |
| -import java.util.Collections; |
| -import java.util.Enumeration; |
| -import java.util.List; |
| -import java.util.zip.GZIPInputStream; |
| - |
| -import javax.servlet.Filter; |
| -import javax.servlet.FilterChain; |
| -import javax.servlet.FilterConfig; |
| -import javax.servlet.ServletException; |
| -import javax.servlet.ServletInputStream; |
| -import javax.servlet.ServletRequest; |
| -import javax.servlet.ServletResponse; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletRequestWrapper; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -public final class InboundGzipFilter implements Filter { |
| - |
| - public void destroy() { |
| - } |
| - |
| - public void doFilter(ServletRequest req, ServletResponse res, |
| - FilterChain chain) throws IOException, ServletException { |
| - HttpServletRequest request = (HttpServletRequest) req; |
| - HttpServletResponse response = (HttpServletResponse) res; |
| - response.setHeader("Accept-Encoding", "gzip"); |
| - String ce = request.getHeader("Content-Encoding"); |
| - if (ce != null && "gzip".equalsIgnoreCase(ce.trim())) { |
| - chain.doFilter(new RequestWrapper(request), res); |
| - } else { |
| - chain.doFilter(req, res); |
| - } |
| - } |
| - |
| - public void init(FilterConfig config) throws ServletException { |
| - } |
| - |
| - private final class RequestWrapper extends HttpServletRequestWrapper { |
| - |
| - private ServletInputStream stream = null; |
| - |
| - public RequestWrapper(HttpServletRequest req) throws IOException { |
| - super(req); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getDateHeader(java.lang.String) |
| - */ |
| - @Override |
| - public long getDateHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else { |
| - return super.getDateHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeader(java.lang.String) |
| - */ |
| - @Override |
| - public String getHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return null; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return null; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return null; |
| - } else { |
| - return super.getHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeaderNames() |
| - */ |
| - @Override |
| - public Enumeration getHeaderNames() { |
| - Enumeration e = super.getHeaderNames(); |
| - List<String> list = new ArrayList<String>(); |
| - while (e.hasMoreElements()) { |
| - String name = (String) e.nextElement(); |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - continue; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - continue; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - continue; |
| - } else { |
| - list.add(name); |
| - } |
| - } |
| - return Collections.enumeration(list); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeaders(java.lang.String) |
| - */ |
| - @SuppressWarnings("unchecked") |
| - @Override |
| - public Enumeration getHeaders(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else { |
| - return super.getHeaders(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getIntHeader(java.lang.String) |
| - */ |
| - @Override |
| - public int getIntHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else { |
| - return super.getIntHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getContentLength() |
| - */ |
| - @Override |
| - public int getContentLength() { |
| - return -1; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getInputStream() |
| - */ |
| - @Override |
| - public ServletInputStream getInputStream() throws IOException { |
| - if (stream == null) { |
| - stream = new DelegatingServletInputStream(new GZIPInputStream(super.getInputStream())); |
| - } |
| - return stream; |
| - } |
| - |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/InboundSizeLimitFilter.java b/src/nu/validator/servlet/InboundSizeLimitFilter.java |
| deleted file mode 100644 |
| index dc8b6ee..0000000 |
| --- a/src/nu/validator/servlet/InboundSizeLimitFilter.java |
| +++ /dev/null |
| @@ -1,91 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007-2008 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| - |
| -import javax.servlet.Filter; |
| -import javax.servlet.FilterChain; |
| -import javax.servlet.FilterConfig; |
| -import javax.servlet.ServletException; |
| -import javax.servlet.ServletInputStream; |
| -import javax.servlet.ServletRequest; |
| -import javax.servlet.ServletResponse; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletRequestWrapper; |
| - |
| -import nu.validator.io.BoundedInputStream; |
| -import nu.validator.io.StreamBoundException; |
| - |
| -public final class InboundSizeLimitFilter implements Filter { |
| - |
| - private long sizeLimit; |
| - |
| - /** |
| - * @param sizeLimit |
| - */ |
| - public InboundSizeLimitFilter(final long sizeLimit) { |
| - this.sizeLimit = sizeLimit; |
| - } |
| - |
| - public InboundSizeLimitFilter() { |
| - this(Long.MAX_VALUE); |
| - } |
| - |
| - public void destroy() { |
| - } |
| - |
| - public void doFilter(ServletRequest req, ServletResponse res, |
| - FilterChain chain) throws IOException, ServletException { |
| - HttpServletRequest request = (HttpServletRequest) req; |
| - chain.doFilter(new RequestWrapper(request), res); |
| - } |
| - |
| - public void init(FilterConfig config) throws ServletException { |
| - // XXX add configurability |
| - } |
| - |
| - private final class RequestWrapper extends HttpServletRequestWrapper { |
| - |
| - private ServletInputStream stream = null; |
| - |
| - public RequestWrapper(HttpServletRequest req) throws IOException { |
| - super(req); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getInputStream() |
| - */ |
| - @Override |
| - public ServletInputStream getInputStream() throws IOException { |
| - if (stream == null) { |
| - if (super.getContentLength() > sizeLimit) { |
| - throw new StreamBoundException("Resource size exceeds limit."); |
| - } |
| - stream = new DelegatingServletInputStream(new BoundedInputStream(super.getInputStream(), sizeLimit, super.getHeader("Content-Location"))); |
| - } |
| - return stream; |
| - } |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/ListErrorHandler.java b/src/nu/validator/servlet/ListErrorHandler.java |
| deleted file mode 100644 |
| index 90bb994..0000000 |
| --- a/src/nu/validator/servlet/ListErrorHandler.java |
| +++ /dev/null |
| @@ -1,66 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007 Henri Sivonen |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.util.LinkedList; |
| - |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXParseException; |
| - |
| -public class ListErrorHandler implements ErrorHandler { |
| - |
| - private boolean fatal = false; |
| - |
| - private LinkedList<String> errors = new LinkedList<String>(); |
| - |
| - public void error(SAXParseException spe) throws SAXException { |
| - errors.add(Integer.toString(spe.getColumnNumber()) + ": " + spe.getMessage()); |
| - } |
| - |
| - public void fatalError(SAXParseException arg0) throws SAXException { |
| - fatal = true; |
| - } |
| - |
| - public void warning(SAXParseException arg0) throws SAXException { |
| - } |
| - |
| - /** |
| - * Returns the errors. |
| - * |
| - * @return the errors |
| - */ |
| - public LinkedList<String> getErrors() { |
| - return errors; |
| - } |
| - |
| - /** |
| - * Returns the fatal. |
| - * |
| - * @return the fatal |
| - */ |
| - public boolean isFatal() { |
| - return fatal; |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/Main.java b/src/nu/validator/servlet/Main.java |
| deleted file mode 100644 |
| index 631e57b..0000000 |
| --- a/src/nu/validator/servlet/Main.java |
| +++ /dev/null |
| @@ -1,121 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005 Henri Sivonen |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.InputStream; |
| -import java.io.OutputStream; |
| -import java.net.ConnectException; |
| -import java.net.InetAddress; |
| -import java.net.ServerSocket; |
| -import java.net.Socket; |
| -import java.util.EnumSet; |
| - |
| -import javax.servlet.DispatcherType; |
| - |
| -import org.apache.log4j.PropertyConfigurator; |
| -import org.eclipse.jetty.server.Connector; |
| -import org.eclipse.jetty.server.HttpConfiguration; |
| -import org.eclipse.jetty.server.HttpConnectionFactory; |
| -import org.eclipse.jetty.server.Server; |
| -import org.eclipse.jetty.server.ServerConnector; |
| -import org.eclipse.jetty.servlet.ServletContextHandler; |
| -import org.eclipse.jetty.servlet.FilterHolder; |
| -import org.eclipse.jetty.servlet.ServletHolder; |
| -import org.eclipse.jetty.servlets.GzipFilter; |
| -import org.eclipse.jetty.util.thread.QueuedThreadPool; |
| - |
| -/** |
| - * @version $Id$ |
| - * @author hsivonen |
| - */ |
| -public class Main { |
| - |
| - private static final long SIZE_LIMIT = Integer.parseInt(System.getProperty( |
| - "nu.validator.servlet.max-file-size", "2097152")); |
| - |
| - public static void main(String[] args) throws Exception { |
| - if (!"1".equals(System.getProperty("nu.validator.servlet.read-local-log4j-properties"))) { |
| - PropertyConfigurator.configure(Main.class.getClassLoader().getResource( |
| - "nu/validator/localentities/files/log4j.properties")); |
| - } else { |
| - PropertyConfigurator.configure(System.getProperty( |
| - "nu.validator.servlet.log4j-properties", "log4j.properties")); |
| - } |
| - |
| - ServletContextHandler contextHandler = new ServletContextHandler(); |
| - contextHandler.setContextPath("/"); |
| - contextHandler.addFilter(new FilterHolder(new GzipFilter()), "/*", |
| - EnumSet.of(DispatcherType.REQUEST)); |
| - contextHandler.addFilter(new FilterHolder(new InboundSizeLimitFilter( |
| - SIZE_LIMIT)), "/*", EnumSet.of(DispatcherType.REQUEST)); |
| - contextHandler.addFilter(new FilterHolder(new InboundGzipFilter()), |
| - "/*", EnumSet.of(DispatcherType.REQUEST)); |
| - contextHandler.addFilter( |
| - new FilterHolder(new MultipartFormDataFilter()), "/*", |
| - EnumSet.of(DispatcherType.REQUEST)); |
| - contextHandler.addServlet(new ServletHolder(new VerifierServlet()), |
| - "/*"); |
| - |
| - Server server = new Server(new QueuedThreadPool(100)); |
| - server.setHandler(contextHandler); |
| - |
| - ServerConnector serverConnector = new ServerConnector(server, |
| - new HttpConnectionFactory(new HttpConfiguration())); |
| - int port = args.length > 0 ? Integer.parseInt(args[0]) : 8888; |
| - serverConnector.setPort(port); |
| - server.setConnectors(new Connector[] { serverConnector }); |
| - |
| - int stopPort = -1; |
| - if (args.length > 1) { |
| - stopPort = Integer.parseInt(args[1]); |
| - } |
| - if (stopPort != -1) { |
| - try { |
| - Socket clientSocket = new Socket( |
| - InetAddress.getByName("127.0.0.1"), stopPort); |
| - InputStream in = clientSocket.getInputStream(); |
| - in.read(); |
| - in.close(); |
| - clientSocket.close(); |
| - } catch (ConnectException e) { |
| - |
| - } |
| - |
| - server.start(); |
| - |
| - ServerSocket serverSocket = new ServerSocket(stopPort, 0, |
| - InetAddress.getByName("127.0.0.1")); |
| - Socket s = serverSocket.accept(); |
| - |
| - server.stop(); |
| - |
| - OutputStream out = s.getOutputStream(); |
| - out.close(); |
| - s.close(); |
| - serverSocket.close(); |
| - } else { |
| - server.start(); |
| - } |
| - } |
| -} |
| diff --git a/src/nu/validator/servlet/MultipartFormDataFilter.java b/src/nu/validator/servlet/MultipartFormDataFilter.java |
| deleted file mode 100644 |
| index 4c976ab..0000000 |
| --- a/src/nu/validator/servlet/MultipartFormDataFilter.java |
| +++ /dev/null |
| @@ -1,400 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.BufferedReader; |
| -import java.io.ByteArrayInputStream; |
| -import java.io.IOException; |
| -import java.io.InputStream; |
| -import java.io.InputStreamReader; |
| -import java.io.Reader; |
| -import java.nio.charset.CharacterCodingException; |
| -import java.nio.charset.Charset; |
| -import java.nio.charset.CharsetDecoder; |
| -import java.nio.charset.CodingErrorAction; |
| -import java.util.ArrayList; |
| -import java.util.Collections; |
| -import java.util.Enumeration; |
| -import java.util.HashMap; |
| -import java.util.List; |
| -import java.util.Map; |
| -import java.util.regex.Matcher; |
| -import java.util.regex.Pattern; |
| - |
| -import javax.servlet.Filter; |
| -import javax.servlet.FilterChain; |
| -import javax.servlet.FilterConfig; |
| -import javax.servlet.ServletException; |
| -import javax.servlet.ServletInputStream; |
| -import javax.servlet.ServletRequest; |
| -import javax.servlet.ServletResponse; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletRequestWrapper; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import org.apache.commons.fileupload.FileItemIterator; |
| -import org.apache.commons.fileupload.FileItemStream; |
| -import org.apache.commons.fileupload.FileUploadException; |
| -import org.apache.commons.fileupload.servlet.ServletFileUpload; |
| - |
| -public final class MultipartFormDataFilter implements Filter { |
| - |
| - private static Pattern EXTENSION = Pattern.compile("^.*\\.(.+)$"); |
| - |
| - private final static Map<String, String> EXTENSION_TO_TYPE = new HashMap<String, String>(); |
| - |
| - static { |
| - EXTENSION_TO_TYPE.put("html", "text/html"); |
| - EXTENSION_TO_TYPE.put("htm", "text/html"); |
| - EXTENSION_TO_TYPE.put("xhtml", "application/xhtml+xml"); |
| - EXTENSION_TO_TYPE.put("xht", "application/xhtml+xml"); |
| - EXTENSION_TO_TYPE.put("atom", "application/atom+xml"); |
| - EXTENSION_TO_TYPE.put("rng", "application/xml"); |
| - EXTENSION_TO_TYPE.put("xsl", "application/xml"); |
| - EXTENSION_TO_TYPE.put("xml", "application/xml"); |
| - EXTENSION_TO_TYPE.put("dbk", "application/xml"); |
| - EXTENSION_TO_TYPE.put("csl", "application/xml"); |
| - } |
| - |
| - private static String utf8ByteStreamToString(InputStream stream) |
| - throws IOException { |
| - CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); |
| - dec.onMalformedInput(CodingErrorAction.REPORT); |
| - dec.onUnmappableCharacter(CodingErrorAction.REPORT); |
| - Reader reader = new InputStreamReader(stream, dec); |
| - StringBuilder builder = new StringBuilder(); |
| - int c; |
| - int i = 0; |
| - while ((c = reader.read()) != -1) { |
| - if (i > 2048) { |
| - throw new IOException("Form field value too large."); |
| - } |
| - builder.append((char) c); |
| - i++; |
| - } |
| - return builder.toString(); |
| - } |
| - |
| - private static void putParam(Map<String, String[]> params, String key, |
| - String value) { |
| - String[] oldVal = params.get(key); |
| - if (oldVal == null) { |
| - String[] arr = new String[1]; |
| - arr[0] = value; |
| - params.put(key, arr); |
| - } else { |
| - for (int i = 0; i < oldVal.length; i++) { |
| - String string = oldVal[i]; |
| - if (string.equals(value)) { |
| - return; |
| - } |
| - } |
| - String[] arr = new String[oldVal.length + 1]; |
| - System.arraycopy(oldVal, 0, arr, 0, oldVal.length); |
| - arr[oldVal.length] = value; |
| - params.put(key, arr); |
| - } |
| - } |
| - |
| - public void destroy() { |
| - } |
| - |
| - public void doFilter(ServletRequest req, ServletResponse res, |
| - FilterChain chain) throws IOException, ServletException { |
| - HttpServletRequest request = (HttpServletRequest) req; |
| - HttpServletResponse response = (HttpServletResponse) res; |
| - if (ServletFileUpload.isMultipartContent(request)) { |
| - try { |
| - boolean utf8 = false; |
| - String contentType = null; |
| - Map<String, String[]> params = new HashMap<String, String[]>(); |
| - InputStream fileStream = null; |
| - ServletFileUpload upload = new ServletFileUpload(); |
| - FileItemIterator iter = upload.getItemIterator(request); |
| - while (iter.hasNext()) { |
| - FileItemStream fileItemStream = iter.next(); |
| - if (fileItemStream.isFormField()) { |
| - String fieldName = fileItemStream.getFieldName(); |
| - if ("content".equals(fieldName)) { |
| - utf8 = true; |
| - String[] parser = params.get("parser"); |
| - if (parser != null && parser[0].startsWith("xml")) { |
| - contentType = "application/xml"; |
| - } else { |
| - contentType = "text/html"; |
| - } |
| - request.setAttribute("nu.validator.servlet.MultipartFormDataFilter.type", "textarea"); |
| - fileStream = fileItemStream.openStream(); |
| - break; |
| - } else { |
| - putParam( |
| - params, |
| - fieldName, |
| - utf8ByteStreamToString(fileItemStream.openStream())); |
| - } |
| - } else { |
| - String fileName = fileItemStream.getName(); |
| - if (fileName != null) { |
| - putParam(params, fileItemStream.getFieldName(), |
| - fileName); |
| - request.setAttribute( |
| - "nu.validator.servlet.MultipartFormDataFilter.filename", |
| - fileName); |
| - Matcher m = EXTENSION.matcher(fileName); |
| - if (m.matches()) { |
| - contentType = EXTENSION_TO_TYPE.get(m.group(1)); |
| - } |
| - } |
| - if (contentType == null) { |
| - contentType = fileItemStream.getContentType(); |
| - } |
| - request.setAttribute("nu.validator.servlet.MultipartFormDataFilter.type", "file"); |
| - fileStream = fileItemStream.openStream(); |
| - break; |
| - } |
| - } |
| - if (fileStream == null) { |
| - fileStream = new ByteArrayInputStream(new byte[0]); |
| - } |
| - if (contentType == null) { |
| - contentType = "application/octet-stream"; |
| - } |
| - chain.doFilter(new RequestWrapper(request, params, contentType, |
| - utf8, fileStream), response); |
| - } catch (FileUploadException e) { |
| - response.sendError(415, e.getMessage()); |
| - } catch (CharacterCodingException e) { |
| - response.sendError(415, e.getMessage()); |
| - } catch (IOException e) { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - e.getMessage()); |
| - } |
| - } else { |
| - chain.doFilter(req, res); |
| - } |
| - } |
| - |
| - public void init(FilterConfig arg0) throws ServletException { |
| - } |
| - |
| - private final class RequestWrapper extends HttpServletRequestWrapper { |
| - |
| - private final Map<String, String[]> params; |
| - |
| - private final String contentType; |
| - |
| - private final boolean utf8; |
| - |
| - private final ServletInputStream stream; |
| - |
| - public RequestWrapper(HttpServletRequest req, |
| - Map<String, String[]> params, String contentType, boolean utf8, |
| - InputStream stream) { |
| - super(req); |
| - this.params = Collections.unmodifiableMap(params); |
| - this.contentType = contentType; |
| - this.utf8 = utf8; |
| - this.stream = new DelegatingServletInputStream(stream); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getDateHeader(java.lang.String) |
| - */ |
| - @Override |
| - public long getDateHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Type".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else { |
| - return super.getDateHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeader(java.lang.String) |
| - */ |
| - @Override |
| - public String getHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return null; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return null; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return null; |
| - } else if ("Content-Type".equalsIgnoreCase(name)) { |
| - return getContentType(); |
| - } else { |
| - return super.getHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeaderNames() |
| - */ |
| - @Override |
| - public Enumeration getHeaderNames() { |
| - Enumeration e = super.getHeaderNames(); |
| - List<String> list = new ArrayList<String>(); |
| - while (e.hasMoreElements()) { |
| - String name = (String) e.nextElement(); |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - continue; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - continue; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - continue; |
| - } else if ("Content-Type".equalsIgnoreCase(name)) { |
| - list.add(getContentType()); |
| - } else { |
| - list.add(name); |
| - } |
| - } |
| - return Collections.enumeration(list); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getHeaders(java.lang.String) |
| - */ |
| - @SuppressWarnings("unchecked") |
| - @Override |
| - public Enumeration getHeaders(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.EMPTY_SET); |
| - } else if ("Content-Type".equalsIgnoreCase(name)) { |
| - return Collections.enumeration(Collections.singleton(getContentType())); |
| - } else { |
| - return super.getHeaders(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServletRequestWrapper#getIntHeader(java.lang.String) |
| - */ |
| - @Override |
| - public int getIntHeader(String name) { |
| - if ("Content-Length".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-MD5".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Encoding".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else if ("Content-Type".equalsIgnoreCase(name)) { |
| - return -1; |
| - } else { |
| - return super.getIntHeader(name); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getCharacterEncoding() |
| - */ |
| - @Override |
| - public String getCharacterEncoding() { |
| - return utf8 ? "utf-8" : null; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getContentLength() |
| - */ |
| - @Override |
| - public int getContentLength() { |
| - return -1; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getContentType() |
| - */ |
| - @Override |
| - public String getContentType() { |
| - return utf8 ? contentType + "; charset=utf-8" : contentType; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getInputStream() |
| - */ |
| - @Override |
| - public ServletInputStream getInputStream() throws IOException { |
| - return stream; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String) |
| - */ |
| - @Override |
| - public String getParameter(String key) { |
| - String[] arr = params.get(key); |
| - if (arr == null) { |
| - return null; |
| - } else { |
| - return arr[0]; |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getParameterMap() |
| - */ |
| - @Override |
| - public Map getParameterMap() { |
| - return params; |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getParameterNames() |
| - */ |
| - @Override |
| - public Enumeration getParameterNames() { |
| - return Collections.enumeration(params.keySet()); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String) |
| - */ |
| - @Override |
| - public String[] getParameterValues(String key) { |
| - return params.get(key); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.ServletRequestWrapper#getReader() |
| - */ |
| - @Override |
| - public BufferedReader getReader() throws IOException { |
| - CharsetDecoder dec = Charset.forName("UTF-8").newDecoder(); |
| - dec.onMalformedInput(CodingErrorAction.REPORT); |
| - dec.onUnmappableCharacter(CodingErrorAction.REPORT); |
| - Reader reader = new InputStreamReader(stream, dec); |
| - return new BufferedReader(reader); |
| - } |
| - |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/NsFilterEmitter.java b/src/nu/validator/servlet/NsFilterEmitter.java |
| deleted file mode 100644 |
| index d9e23be..0000000 |
| --- a/src/nu/validator/servlet/NsFilterEmitter.java |
| +++ /dev/null |
| @@ -1,33 +0,0 @@ |
| -/* This code was generated by nu.validator.tools.SaxCompiler. Please regenerate instead of editing. */ |
| -package nu.validator.servlet; |
| -public final class NsFilterEmitter { |
| -private NsFilterEmitter() {} |
| -public static void emit(org.xml.sax.ContentHandler contentHandler, nu.validator.servlet.VerifierServletTransaction t) throws org.xml.sax.SAXException { |
| -org.xml.sax.helpers.AttributesImpl __attrs__ = new org.xml.sax.helpers.AttributesImpl(); |
| -contentHandler.startPrefixMapping("", "http://www.w3.org/1999/xhtml"); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "Space-separated list of namespace URIs."); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "tr", "tr", __attrs__); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "th", "th", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "for", "for", "CDATA", "nsfilter"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "label", "label", __attrs__); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "title", "title", "CDATA", "XML namespace"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "abbr", "abbr", __attrs__); |
| -contentHandler.characters(__chars__, 0, 5); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "abbr", "abbr"); |
| -contentHandler.characters(__chars__, 5, 1); |
| -contentHandler.characters(__chars__, 6, 6); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "label", "label"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "th", "th"); |
| -__attrs__.clear(); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "td", "td", __attrs__); |
| -t.emitNsfilterField(); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "td", "td"); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "tr", "tr"); |
| -contentHandler.endPrefixMapping(""); |
| -} |
| -private static final char[] __chars__ = { 'X', 'M', 'L', 'N', 'S', '\u00a0', 'F', 'i', 'l', 't', 'e', 'r' }; |
| -} |
| diff --git a/src/nu/validator/servlet/OutlineBuildingXMLReaderWrapper.java b/src/nu/validator/servlet/OutlineBuildingXMLReaderWrapper.java |
| deleted file mode 100644 |
| index a22b654..0000000 |
| --- a/src/nu/validator/servlet/OutlineBuildingXMLReaderWrapper.java |
| +++ /dev/null |
| @@ -1,847 +0,0 @@ |
| -/* |
| - * Copyright (c) 2012 Vadim Zaslawski, Ontos AG |
| - * Copyright (c) 2012-2014 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - * |
| - * This code contains comments that are verbatim quotations from the |
| - * document "HTML: The Living Standard", which has the following copyright |
| - * and permission notice: |
| - * |
| - * Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and |
| - * Opera Software ASA. You are granted a license to use, reproduce and |
| - * create derivative works of this document. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.util.Arrays; |
| -import java.util.Deque; |
| -import java.util.LinkedList; |
| -import java.util.regex.Pattern; |
| - |
| -import javax.servlet.http.HttpServletRequest; |
| - |
| -import org.xml.sax.Attributes; |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.DTDHandler; |
| -import org.xml.sax.EntityResolver; |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.InputSource; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXNotRecognizedException; |
| -import org.xml.sax.SAXNotSupportedException; |
| -import org.xml.sax.XMLReader; |
| - |
| -public final class OutlineBuildingXMLReaderWrapper implements XMLReader, |
| - ContentHandler { |
| - |
| - private final XMLReader wrappedReader; |
| - |
| - private final HttpServletRequest request; |
| - |
| - private ContentHandler contentHandler; |
| - |
| - public OutlineBuildingXMLReaderWrapper(XMLReader wrappedReader, |
| - HttpServletRequest request) { |
| - this.request = request; |
| - this.wrappedReader = wrappedReader; |
| - this.contentHandler = wrappedReader.getContentHandler(); |
| - wrappedReader.setContentHandler(this); |
| - } |
| - |
| - private static final int MAX_EXCERPT = 500; |
| - |
| - private static final String[] SECTIONING_CONTENT_ELEMENTS = { "article", |
| - "aside", "nav", "section" }; |
| - |
| - private static final String[] SECTIONING_ROOT_ELEMENTS = { "blockquote", |
| - "body", "details", "fieldset", "figure", "td" }; |
| - |
| - private static final String[] HEADING_CONTENT_ELEMENTS = { "h1", "h2", |
| - "h3", "h4", "h5", "h6", "hgroup", }; |
| - |
| - private Deque<Section> outline; |
| - |
| - public Deque<Section> getOutline() { |
| - return this.outline; |
| - } |
| - |
| - protected void setOutline(Deque<Section> outline) { |
| - this.outline = outline; |
| - } |
| - |
| - // an outlinee, a heading content element, or an element with a hidden |
| - // attribute; |
| - // during a walk over the nodes of a DOM tree, nodes are identified with |
| - // their depth and local name |
| - private class Element { |
| - // the depth of element in the DOM |
| - final private int depth; |
| - |
| - // the local name of element |
| - final private String name; |
| - |
| - // whether the element is hidden |
| - final private boolean hidden; |
| - |
| - // the outline for a sectioning content element or a sectioning root |
| - // element consists of a list of one or more potentially nested sections |
| - final private Deque<Section> outline = new LinkedList<Section>(); |
| - |
| - public Element(int depth, String name, boolean hidden) { |
| - this.depth = depth; |
| - this.name = name; |
| - this.hidden = hidden; |
| - } |
| - |
| - public boolean isHidden() { |
| - return hidden; |
| - } |
| - |
| - public boolean equals(int depth, String name) { |
| - return this.depth == depth && this.name.equals(name); |
| - } |
| - |
| - /** |
| - * @return the outline |
| - */ |
| - public Deque<Section> getOutline() { |
| - return outline; |
| - } |
| - |
| - /** |
| - * @return 1-6 for a heading content element MAX_VALUE for an implied |
| - * heading -1 for no section |
| - */ |
| - public int getLastSectionHeadingRank() { |
| - Section section = outline.peekLast(); |
| - return section != null ? section.getHeadingRank() : -1; |
| - } |
| - } |
| - |
| - // a section is a container that corresponds to some nodes in the original |
| - // DOM tree |
| - public class Section { |
| - // the section that contains this section |
| - private Section parent; |
| - |
| - // an outlinee or a heading content element |
| - final String elementName; |
| - |
| - // each section can have one heading associated with it |
| - final private StringBuilder headingTextBuilder = new StringBuilder(); |
| - |
| - // we generate an "implied heading" for some sections that lack headings |
| - private boolean hasImpliedHeading; |
| - |
| - // Generating a special kind of implied heading specifically for |
| - // the "empty heading" case (e.g., empty <h1></h1> descendant) as |
| - // opposed to the "no heading" case (no h1-h6 descendants at all) |
| - // isn't required by the spec, but it's nonetheless useful. |
| - private boolean hasEmptyHeading; |
| - |
| - // MAX_VALUE for an implied heading, 1-6 for a heading content element |
| - private int headingRank = Integer.MAX_VALUE; |
| - |
| - // each section can contain any number of further nested sections |
| - final public Deque<Section> sections = new LinkedList<Section>(); |
| - |
| - public Section(String elementName) { |
| - this.elementName = elementName; |
| - } |
| - |
| - /** |
| - * @return the parent section |
| - */ |
| - public Section getParent() { |
| - return parent; |
| - } |
| - |
| - /** |
| - * @return the lement name |
| - */ |
| - public String getElementName() { |
| - return elementName; |
| - } |
| - |
| - /** |
| - * @param parent |
| - * the parent section to set |
| - */ |
| - public void setParent(Section parent) { |
| - this.parent = parent; |
| - } |
| - |
| - /** |
| - * @return the heading text builder |
| - */ |
| - public StringBuilder getHeadingTextBuilder() { |
| - return headingTextBuilder; |
| - } |
| - |
| - /** |
| - * @return the heading rank |
| - */ |
| - public int getHeadingRank() { |
| - return headingRank; |
| - } |
| - |
| - /** |
| - * @return the sections |
| - */ |
| - public Deque<Section> getSections() { |
| - return sections; |
| - } |
| - |
| - public void setHeadingRank(int headingRank) { |
| - this.headingRank = headingRank; |
| - } |
| - |
| - public boolean hasHeading() { |
| - return headingRank < 7 || hasImpliedHeading; |
| - } |
| - |
| - public void createImpliedHeading() { |
| - hasImpliedHeading = true; |
| - } |
| - |
| - public void createEmptyHeading() { |
| - hasEmptyHeading = true; |
| - } |
| - |
| - public boolean hasEmptyHeading() { |
| - return hasEmptyHeading; |
| - } |
| - } |
| - |
| - // tracks the depth of walk through the DOM |
| - private int currentWalkDepth; |
| - |
| - // holds the element whose outline is being created; |
| - // a sectioning content element or a sectioning root element |
| - private Element currentOutlinee; |
| - |
| - // A stack (not defined in the spec) to hold all open elements. We just |
| - // use this stack for the purpose of checking whether there are any |
| - // open elements at all with a "hidden" attribute -- including elements |
| - // that may be descendants of heading-content elements (which per the |
| - // spec never end up on the outline stack). |
| - private Deque<Element> elementStack = new LinkedList<Element>(); |
| - |
| - private boolean inHiddenSubtree() { |
| - for (Element element : elementStack) { |
| - if (element.isHidden()) { |
| - return true; |
| - } |
| - } |
| - return false; |
| - } |
| - |
| - // A stack, defined in the spec, to which we only add open |
| - // heading-content elements and elements with a "hidden" attribute that |
| - // are ancestors to heading-content elements. |
| - private Deque<Element> outlineStack = new LinkedList<Element>(); |
| - |
| - // The top of the outline stack defined in the spec is always either a |
| - // heading content element or an element with a hidden attribute. |
| - private boolean inHeadingContentOrHiddenElement; |
| - |
| - private boolean needHeading; |
| - |
| - private boolean skipHeading; |
| - |
| - // holds a pointer to a section, so that elements in the DOM can all be |
| - // associated with a section |
| - private Section currentSection; |
| - |
| - private boolean isWalkOver; |
| - |
| - private static final Pattern excerptPattern = Pattern.compile("\\W*\\S*$"); |
| - |
| - private static final Pattern whitespacePattern = Pattern.compile("\\s+"); |
| - |
| - /* |
| - * Returns the string excerpt. |
| - */ |
| - private String excerpt(String str, int maxLength) { |
| - return str.length() > maxLength ? excerptPattern.matcher( |
| - str.substring(0, maxLength)).replaceFirst("…") : str; |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.helpers.XMLFilterImpl#characters(char[], int, int) |
| - */ |
| - public void characters(char[] ch, int start, int length) |
| - throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - if (isWalkOver) { |
| - contentHandler.characters(ch, start, length); |
| - return; |
| - } |
| - |
| - if (inHeadingContentOrHiddenElement && !inHiddenSubtree()) { |
| - currentSection.getHeadingTextBuilder().append(ch, start, length); |
| - } |
| - contentHandler.characters(ch, start, length); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.helpers.XMLFilterImpl#endElement(java.lang.String, |
| - * java.lang.String, java.lang.String) |
| - */ |
| - public void endElement(String uri, String localName, String qName) |
| - throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - elementStack.pop(); |
| - if ("hgroup".equals(localName)) { |
| - needHeading = false; |
| - skipHeading = false; |
| - } |
| - if (isWalkOver) { |
| - contentHandler.endElement(uri, localName, qName); |
| - return; |
| - } |
| - |
| - int depth = currentWalkDepth--; |
| - |
| - if (inHeadingContentOrHiddenElement) { |
| - // When exiting an element, if that element is the element at the |
| - // top of the stack |
| - // Note: The element being exited is a heading content element or an |
| - // element with a hidden attribute. |
| - Element topElement = outlineStack.peek(); |
| - assert topElement != null; |
| - if (topElement.equals(depth, localName)) { |
| - // Pop that element from the stack. |
| - outlineStack.pop(); |
| - inHeadingContentOrHiddenElement = false; |
| - |
| - if (currentSection != null) { |
| - StringBuilder headingTextBuilder = currentSection.getHeadingTextBuilder(); |
| - String heading = excerpt( |
| - whitespacePattern.matcher(headingTextBuilder).replaceAll( |
| - " ").trim(), MAX_EXCERPT); |
| - headingTextBuilder.setLength(0); |
| - if (heading.length() > 0) { |
| - headingTextBuilder.append(heading); |
| - } else { |
| - currentSection.createEmptyHeading(); |
| - } |
| - } |
| - } |
| - |
| - // If the top of the stack is a heading content element or an |
| - // element with a hidden attribute |
| - // Do nothing. |
| - contentHandler.endElement(uri, localName, qName); |
| - return; |
| - } |
| - |
| - if (Arrays.binarySearch(SECTIONING_CONTENT_ELEMENTS, localName) > -1) { |
| - // When exiting a sectioning content element, if the stack is not |
| - // empty |
| - if (!outlineStack.isEmpty()) { |
| - // If the current section has no heading, |
| - if (currentSection != null && !currentSection.hasHeading()) { |
| - // create an implied heading and let that be the heading for |
| - // the current section. |
| - currentSection.createImpliedHeading(); |
| - } |
| - Element exitedSectioningContentElement = currentOutlinee; |
| - assert exitedSectioningContentElement != null; |
| - |
| - // Pop the top element from the stack, and let the current |
| - // outlinee be that element. |
| - currentOutlinee = outlineStack.pop(); |
| - |
| - // Let current section be the last section in the outline of the |
| - // current outlinee element. |
| - currentSection = currentOutlinee.getOutline().peekLast(); |
| - assert currentSection != null; |
| - |
| - // Append the outline of the sectioning content element being |
| - // exited to the current section. |
| - // (This does not change which section is the last section in |
| - // the outline.) |
| - for (Section section : exitedSectioningContentElement.outline) { |
| - section.setParent(currentSection); |
| - currentSection.sections.add(section); |
| - } |
| - } |
| - } else if (Arrays.binarySearch(SECTIONING_ROOT_ELEMENTS, localName) > -1) { |
| - // When exiting a sectioning root element, if the stack is not empty |
| - if (!outlineStack.isEmpty()) { |
| - // Run these steps: |
| - |
| - // If the current section has no heading, |
| - if (currentSection != null && !currentSection.hasHeading()) { |
| - // create an implied heading and let that be the heading for |
| - // the current section. |
| - currentSection.createImpliedHeading(); |
| - } |
| - |
| - // Pop the top element from the stack, and let the current |
| - // outlinee be that element. |
| - currentOutlinee = outlineStack.pop(); |
| - |
| - // Let current section be the last section in the outline of the |
| - // current outlinee element. |
| - currentSection = currentOutlinee.getOutline().peekLast(); |
| - |
| - // Finding the deepest child: |
| - // If current section has no child sections, stop these steps. |
| - while (!currentSection.sections.isEmpty()) |
| - // Let current section be the last child section of the |
| - // current current section. |
| - currentSection = currentSection.sections.peekLast(); |
| - // Go back to the substep labeled finding the deepest child. |
| - } |
| - } else { |
| - // neither a sectioning content element nor a sectioning root |
| - // element |
| - contentHandler.endElement(uri, localName, qName); |
| - return; |
| - } |
| - |
| - // When exiting a sectioning content element or a sectioning root |
| - // element |
| - // Note: The current outlinee is the element being exited, and |
| - // it is the sectioning content element or a sectioning root element at |
| - // the root of the subtree for which an outline is being generated. |
| - |
| - // If the current section has no heading, |
| - if (currentSection != null && !currentSection.hasHeading()) { |
| - // create an implied heading and let that be the heading for the |
| - // current section. |
| - currentSection.createImpliedHeading(); |
| - } |
| - |
| - // Skip to the next step in the overall set of steps. |
| - // (The walk is over.) |
| - // / isWalkOver = true; |
| - |
| - contentHandler.endElement(uri, localName, qName); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.helpers.XMLFilterImpl#startDocument() |
| - */ |
| - public void startDocument() throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.startDocument(); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.helpers.XMLFilterImpl#startElement(java.lang.String, |
| - * java.lang.String, java.lang.String, org.xml.sax.Attributes) |
| - */ |
| - public void startElement(String uri, String localName, String qName, |
| - Attributes atts) throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - if (isWalkOver) { |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } |
| - |
| - ++currentWalkDepth; |
| - |
| - boolean hidden = atts.getIndex("", "hidden") >= 0; |
| - elementStack.push(new Element(currentWalkDepth, localName, hidden)); |
| - |
| - // If the top of the stack is a heading content element or an element |
| - // with a hidden attribute |
| - if (inHeadingContentOrHiddenElement) { |
| - if (!inHiddenSubtree() && "img".equals(localName) |
| - && atts.getIndex("", "alt") >= 0) { |
| - currentSection.getHeadingTextBuilder().append( |
| - atts.getValue("", "alt")); |
| - } |
| - // Do nothing. |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } |
| - |
| - // When entering an element with a hidden attribute |
| - if (hidden) { |
| - // Push the element being entered onto the stack. (This causes the |
| - // algorithm to skip that element and any descendants of the |
| - // element.) |
| - outlineStack.push(new Element(currentWalkDepth, localName, hidden)); |
| - inHeadingContentOrHiddenElement = true; |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } |
| - |
| - // When entering a sectioning content element or a sectioning root |
| - // element |
| - if (Arrays.binarySearch(SECTIONING_CONTENT_ELEMENTS, localName) > -1 |
| - || Arrays.binarySearch(SECTIONING_ROOT_ELEMENTS, localName) > -1) { |
| - if (currentOutlinee != null) { |
| - // If current outlinee is not null, and the current section has |
| - // no heading, |
| - // create an implied heading and let that be the heading for the |
| - // current section. |
| - if (currentSection != null && !currentSection.hasHeading()) { |
| - currentSection.createImpliedHeading(); |
| - } |
| - // If current outlinee is not null, push current outlinee onto |
| - // the stack. |
| - outlineStack.push(currentOutlinee); |
| - } |
| - |
| - // Let current outlinee be the element that is being entered. |
| - currentOutlinee = new Element(currentWalkDepth, localName, hidden); |
| - |
| - // Let current section be a newly created section for the current |
| - // outlinee element. |
| - // Associate current outlinee with current section. |
| - currentSection = new Section(localName); |
| - |
| - // Let there be a new outline for the new current outlinee, |
| - // initialized with just the new current section as the only section |
| - // in the outline. |
| - currentOutlinee.getOutline().add(currentSection); |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } |
| - |
| - // When entering a heading content element |
| - // Note: Recall that h1 has the highest rank, and h6 has the lowest |
| - // rank. |
| - if (Arrays.binarySearch(HEADING_CONTENT_ELEMENTS, localName) > -1 |
| - && currentOutlinee != null) { |
| - if ("hgroup".equals(localName)) { |
| - needHeading = true; |
| - skipHeading = false; |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } else if (skipHeading) { |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - return; |
| - } else if (needHeading) { |
| - skipHeading = true; |
| - needHeading = false; |
| - } |
| - int rank = localName.charAt(1) - '0'; |
| - |
| - // If the current section has no heading, |
| - // let the element being entered be the heading for the current |
| - // section. |
| - if (currentSection != null && !currentSection.hasHeading()) { |
| - currentSection.setHeadingRank(rank); |
| - } |
| - // Otherwise, if the element being entered has a rank equal to |
| - // or higher than the heading of the last section of the |
| - // outline of the current outlinee, or if the heading of the |
| - // last section of the outline of the current outlinee is an |
| - // implied heading, |
| - else if (rank <= currentOutlinee.getLastSectionHeadingRank()) { |
| - // then create a new section and append it to the outline |
| - // of the current outlinee element, so that this new |
| - // section is the new last section of that outline. |
| - // Let current section be that new section. |
| - currentSection = new Section(localName); |
| - currentOutlinee.getOutline().add(currentSection); |
| - |
| - // Let the element being entered be the new heading for the |
| - // current section. |
| - currentSection.setHeadingRank(rank); |
| - } |
| - // Otherwise, run these substeps: |
| - else { |
| - // Let candidate section be current section. |
| - Section candidateSection = currentSection; |
| - |
| - // Heading loop: |
| - while (candidateSection != null) { |
| - // If the element being entered has a rank lower than the |
| - // rank of the heading of the candidate section, |
| - if (rank > candidateSection.getHeadingRank()) { |
| - // then create a new section, and append it to candidate |
| - // section. |
| - // (This does not change which section is the last |
| - // section in the outline.) |
| - // Let current section be this new section. |
| - currentSection = new Section(localName); |
| - currentSection.setParent(candidateSection); |
| - candidateSection.getSections().add(currentSection); |
| - |
| - // Let the element being entered be the new heading for |
| - // the current section. |
| - currentSection.setHeadingRank(rank); |
| - |
| - // Abort these substeps. |
| - break; |
| - } |
| - |
| - // Let new candidate section be the section that contains |
| - // candidate section in the outline of current outlinee. |
| - // Let candidate section be new candidate section. |
| - candidateSection = candidateSection.getParent(); |
| - |
| - // Return to the step labeled heading loop. |
| - } |
| - } |
| - |
| - // Push the element being entered onto the stack. |
| - // (This causes the algorithm to skip any descendants of the |
| - // element.) |
| - outlineStack.push(new Element(currentWalkDepth, localName, hidden)); |
| - inHeadingContentOrHiddenElement = true; |
| - } |
| - contentHandler.startElement(uri, localName, qName, atts); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.helpers.XMLFilterImpl#setDocumentLocator(org.xml.sax.Locator) |
| - */ |
| - public void setDocumentLocator(Locator locator) { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.setDocumentLocator(locator); |
| - } |
| - |
| - public ContentHandler getContentHandler() { |
| - return contentHandler; |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#endDocument() |
| - */ |
| - public void endDocument() throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - if (currentOutlinee != null) { |
| - request.setAttribute( |
| - "http://validator.nu/properties/document-outline", |
| - (Deque<Section>) currentOutlinee.outline); |
| - setOutline(currentOutlinee.outline); |
| - } |
| - contentHandler.endDocument(); |
| - } |
| - |
| - /** |
| - * @param prefix |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) |
| - */ |
| - public void endPrefixMapping(String prefix) throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.endPrefixMapping(prefix); |
| - } |
| - |
| - /** |
| - * @param ch |
| - * @param start |
| - * @param length |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) |
| - */ |
| - public void ignorableWhitespace(char[] ch, int start, int length) |
| - throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.ignorableWhitespace(ch, start, length); |
| - } |
| - |
| - /** |
| - * @param target |
| - * @param data |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, |
| - * java.lang.String) |
| - */ |
| - public void processingInstruction(String target, String data) |
| - throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.processingInstruction(target, data); |
| - } |
| - |
| - /** |
| - * @param name |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) |
| - */ |
| - public void skippedEntity(String name) throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.skippedEntity(name); |
| - } |
| - |
| - /** |
| - * @param prefix |
| - * @param uri |
| - * @throws SAXException |
| - * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, |
| - * java.lang.String) |
| - */ |
| - public void startPrefixMapping(String prefix, String uri) |
| - throws SAXException { |
| - if (contentHandler == null) { |
| - return; |
| - } |
| - contentHandler.startPrefixMapping(prefix, uri); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see org.xml.sax.XMLReader#getDTDHandler() |
| - */ |
| - public DTDHandler getDTDHandler() { |
| - return wrappedReader.getDTDHandler(); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see org.xml.sax.XMLReader#getEntityResolver() |
| - */ |
| - public EntityResolver getEntityResolver() { |
| - return wrappedReader.getEntityResolver(); |
| - } |
| - |
| - /** |
| - * @return |
| - * @see org.xml.sax.XMLReader#getErrorHandler() |
| - */ |
| - public ErrorHandler getErrorHandler() { |
| - return wrappedReader.getErrorHandler(); |
| - } |
| - |
| - /** |
| - * @param name |
| - * @return |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - * @see org.xml.sax.XMLReader#getFeature(java.lang.String) |
| - */ |
| - public boolean getFeature(String name) throws SAXNotRecognizedException, |
| - SAXNotSupportedException { |
| - return wrappedReader.getFeature(name); |
| - } |
| - |
| - /** |
| - * @param name |
| - * @return |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - * @see org.xml.sax.XMLReader#getProperty(java.lang.String) |
| - */ |
| - public Object getProperty(String name) throws SAXNotRecognizedException, |
| - SAXNotSupportedException { |
| - return wrappedReader.getProperty(name); |
| - } |
| - |
| - /** |
| - * @param input |
| - * @throws IOException |
| - * @throws SAXException |
| - * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource) |
| - */ |
| - public void parse(InputSource input) throws IOException, SAXException { |
| - wrappedReader.parse(input); |
| - } |
| - |
| - /** |
| - * @param systemId |
| - * @throws IOException |
| - * @throws SAXException |
| - * @see org.xml.sax.XMLReader#parse(java.lang.String) |
| - */ |
| - public void parse(String systemId) throws IOException, SAXException { |
| - wrappedReader.parse(systemId); |
| - } |
| - |
| - /** |
| - * @param handler |
| - * @see org.xml.sax.XMLReader#setContentHandler(org.xml.sax.ContentHandler) |
| - */ |
| - public void setContentHandler(ContentHandler handler) { |
| - contentHandler = handler; |
| - } |
| - |
| - /** |
| - * @param handler |
| - * @see org.xml.sax.XMLReader#setDTDHandler(org.xml.sax.DTDHandler) |
| - */ |
| - public void setDTDHandler(DTDHandler handler) { |
| - wrappedReader.setDTDHandler(handler); |
| - } |
| - |
| - /** |
| - * @param resolver |
| - * @see org.xml.sax.XMLReader#setEntityResolver(org.xml.sax.EntityResolver) |
| - */ |
| - public void setEntityResolver(EntityResolver resolver) { |
| - wrappedReader.setEntityResolver(resolver); |
| - } |
| - |
| - /** |
| - * @param handler |
| - * @see org.xml.sax.XMLReader#setErrorHandler(org.xml.sax.ErrorHandler) |
| - */ |
| - public void setErrorHandler(ErrorHandler handler) { |
| - wrappedReader.setErrorHandler(handler); |
| - } |
| - |
| - /** |
| - * @param name |
| - * @param value |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - * @see org.xml.sax.XMLReader#setFeature(java.lang.String, boolean) |
| - */ |
| - public void setFeature(String name, boolean value) |
| - throws SAXNotRecognizedException, SAXNotSupportedException { |
| - wrappedReader.setFeature(name, value); |
| - } |
| - |
| - /** |
| - * @param name |
| - * @param value |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - * @see org.xml.sax.XMLReader#setProperty(java.lang.String, |
| - * java.lang.Object) |
| - */ |
| - public void setProperty(String name, Object value) |
| - throws SAXNotRecognizedException, SAXNotSupportedException { |
| - wrappedReader.setProperty(name, value); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/ParseTreePrinter.java b/src/nu/validator/servlet/ParseTreePrinter.java |
| deleted file mode 100644 |
| index 4203c1c..0000000 |
| --- a/src/nu/validator/servlet/ParseTreePrinter.java |
| +++ /dev/null |
| @@ -1,198 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.io.OutputStreamWriter; |
| -import java.io.StringReader; |
| -import java.io.Writer; |
| - |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import nu.validator.gnu.xml.aelfred2.SAXDriver; |
| -import nu.validator.htmlparser.common.Heuristics; |
| -import nu.validator.htmlparser.common.XmlViolationPolicy; |
| -import nu.validator.io.BoundedInputStream; |
| -import nu.validator.io.StreamBoundException; |
| -import nu.validator.xml.ContentTypeParser; |
| -import nu.validator.xml.NullEntityResolver; |
| -import nu.validator.xml.PrudentHttpEntityResolver; |
| -import nu.validator.xml.TypedInputSource; |
| - |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.XMLReader; |
| - |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.GalimatiasParseException; |
| - |
| -public class ParseTreePrinter { |
| - |
| - private static final String FORM_HTML = "<!DOCTYPE html><title>Parse Tree Dump</title><form><p><input type='url' name='doc' id='doc' pattern='(?:https?://.+)?'> <input name='submit' value='Print Tree' type='submit' id='submit'></form><hr><form><p><select id=parser name=parser><option value=xml>XML; don\u2019t load external entities</option><option value=html5 selected>HTML5</option></select><p><textarea name=content rows=20 cols=72></textarea> <input name='submit' value='Print Tree' type='submit' id='submit'></form>"; |
| - |
| - private static final long SIZE_LIMIT = Integer.parseInt(System.getProperty( |
| - "nu.validator.servlet.max-file-size", "2097152")); |
| - |
| - private final HttpServletRequest request; |
| - |
| - private final HttpServletResponse response; |
| - |
| - /** |
| - * @param request |
| - * @param response |
| - */ |
| - public ParseTreePrinter(final HttpServletRequest request, |
| - final HttpServletResponse response) { |
| - this.request = request; |
| - this.response = response; |
| - } |
| - |
| - private String scrubUrl(String urlStr) { |
| - if (urlStr == null) { |
| - return null; |
| - } |
| - try { |
| - return URL.parse(urlStr).toString(); |
| - } catch (GalimatiasParseException e) { |
| - return null; |
| - } |
| - } |
| - |
| - public void service() throws IOException { |
| - request.setCharacterEncoding("utf-8"); |
| - String content = null; |
| - String document = scrubUrl(request.getParameter("doc")); |
| - document = ("".equals(document)) ? null : document; |
| - Writer writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8"); |
| - if (document == null && methodIsGet() && (content = request.getParameter("content")) == null) { |
| - response.setContentType("text/html; charset=utf-8"); |
| - writer.write(FORM_HTML); |
| - writer.flush(); |
| - writer.close(); |
| - return; |
| - } else { |
| - response.setContentType("text/plain; charset=utf-8"); |
| - try { |
| - PrudentHttpEntityResolver entityResolver = new PrudentHttpEntityResolver( |
| - 2048 * 1024, false, null); |
| - entityResolver.setAllowGenericXml(false); |
| - entityResolver.setAcceptAllKnownXmlTypes(false); |
| - entityResolver.setAllowHtml(true); |
| - entityResolver.setAllowXhtml(true); |
| - TypedInputSource documentInput; |
| - if (methodIsGet()) { |
| - if (content == null) { |
| - documentInput = (TypedInputSource) entityResolver.resolveEntity( |
| - null, document); |
| - } else { |
| - documentInput = new TypedInputSource(new StringReader(content)); |
| - if ("xml".equals(request.getParameter("parser"))) { |
| - documentInput.setType("application/xhtml+xml"); |
| - } else { |
| - documentInput.setType("text/html"); |
| - } |
| - } |
| - } else { // POST |
| - String postContentType = request.getContentType(); |
| - if (postContentType == null) { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "Content-Type missing"); |
| - return; |
| - } else if (postContentType.trim().toLowerCase().startsWith( |
| - "application/x-www-form-urlencoded")) { |
| - response.sendError( |
| - HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, |
| - "application/x-www-form-urlencoded not supported. Please use multipart/form-data."); |
| - return; |
| - } |
| - long len = request.getContentLength(); |
| - if (len > SIZE_LIMIT) { |
| - throw new StreamBoundException("Resource size exceeds limit."); |
| - } |
| - ContentTypeParser contentTypeParser = new ContentTypeParser(null, false); |
| - contentTypeParser.setAllowGenericXml(false); |
| - contentTypeParser.setAcceptAllKnownXmlTypes(false); |
| - contentTypeParser.setAllowHtml(true); |
| - contentTypeParser.setAllowXhtml(true); |
| - documentInput = contentTypeParser.buildTypedInputSource(document, |
| - null, postContentType); |
| - documentInput.setByteStream(len < 0 ? new BoundedInputStream( |
| - request.getInputStream(), SIZE_LIMIT, document) |
| - : request.getInputStream()); |
| - documentInput.setSystemId(request.getHeader("Content-Location")); |
| - } |
| - String type = documentInput.getType(); |
| - XMLReader parser; |
| - if ("text/html".equals(type) || "text/html-sandboxed".equals(type)) { |
| - writer.write("HTML parser\n\n#document\n"); |
| - parser = new nu.validator.htmlparser.sax.HtmlParser(); |
| - parser.setProperty("http://validator.nu/properties/heuristics", Heuristics.ALL); |
| - parser.setProperty("http://validator.nu/properties/xml-policy", XmlViolationPolicy.ALLOW); |
| - } else if ("application/xhtml+xml".equals(type)) { |
| - writer.write("XML parser\n\n#document\n"); |
| - parser = new SAXDriver(); |
| - parser.setFeature( |
| - "http://xml.org/sax/features/external-general-entities", |
| - false); |
| - parser.setFeature( |
| - "http://xml.org/sax/features/external-parameter-entities", |
| - false); |
| - parser.setEntityResolver(new NullEntityResolver()); |
| - } else { |
| - writer.write("Unsupported content type.\n"); |
| - writer.flush(); |
| - writer.close(); |
| - return; |
| - } |
| - TreeDumpContentHandler treeDumpContentHandler = new TreeDumpContentHandler(writer, false); |
| - ListErrorHandler listErrorHandler = new ListErrorHandler(); |
| - parser.setContentHandler(treeDumpContentHandler); |
| - parser.setProperty("http://xml.org/sax/properties/lexical-handler", treeDumpContentHandler); |
| - parser.setErrorHandler(listErrorHandler); |
| - parser.parse(documentInput); |
| - writer.write("#errors\n"); |
| - for (String err : listErrorHandler.getErrors()) { |
| - writer.write(err); |
| - writer.write('\n'); |
| - } |
| - } catch (SAXException e) { |
| - writer.write("SAXException:\n"); |
| - writer.write(e.getMessage()); |
| - writer.write("\n"); |
| - } catch (IOException e) { |
| - writer.write("IOException:\n"); |
| - writer.write(e.getMessage()); |
| - writer.write("\n"); |
| - } finally { |
| - writer.flush(); |
| - writer.close(); |
| - } |
| - } |
| - } |
| - |
| - private boolean methodIsGet() { |
| - return "GET".equals(request.getMethod()) |
| - || "HEAD".equals(request.getMethod()); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/RootNamespaceSniffer.java b/src/nu/validator/servlet/RootNamespaceSniffer.java |
| deleted file mode 100644 |
| index df4bad2..0000000 |
| --- a/src/nu/validator/servlet/RootNamespaceSniffer.java |
| +++ /dev/null |
| @@ -1,121 +0,0 @@ |
| -/* |
| - * Copyright (c) 2006 Henri Sivonen |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import org.xml.sax.Attributes; |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| - |
| -public class RootNamespaceSniffer implements ContentHandler { |
| - |
| - private VerifierServletTransaction vst; |
| - private ContentHandler ch; |
| - private Locator locator; |
| - |
| - public RootNamespaceSniffer(VerifierServletTransaction vst, ContentHandler ch) { |
| - super(); |
| - this.vst = vst; |
| - this.ch = ch; |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#characters(char[], int, int) |
| - */ |
| - public void characters(char[] arg0, int arg1, int arg2) throws SAXException { |
| - ch.characters(arg0, arg1, arg2); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endDocument() |
| - */ |
| - public void endDocument() throws SAXException { |
| - ch.endDocument(); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) |
| - */ |
| - public void endElement(String arg0, String arg1, String arg2) throws SAXException { |
| - ch.endElement(arg0, arg1, arg2); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) |
| - */ |
| - public void endPrefixMapping(String arg0) throws SAXException { |
| - ch.endPrefixMapping(arg0); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) |
| - */ |
| - public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { |
| - ch.ignorableWhitespace(arg0, arg1, arg2); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) |
| - */ |
| - public void processingInstruction(String arg0, String arg1) throws SAXException { |
| - ch.processingInstruction(arg0, arg1); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) |
| - */ |
| - public void setDocumentLocator(Locator arg0) { |
| - this.locator = arg0; |
| - ch.setDocumentLocator(arg0); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) |
| - */ |
| - public void skippedEntity(String arg0) throws SAXException { |
| - ch.skippedEntity(arg0); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startDocument() |
| - */ |
| - public void startDocument() throws SAXException { |
| - ch.startDocument(); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) |
| - */ |
| - public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException { |
| - vst.rootNamespace(arg0, locator); |
| - ch.startElement(arg0, arg1, arg2, arg3); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) |
| - */ |
| - public void startPrefixMapping(String arg0, String arg1) throws SAXException { |
| - ch.startPrefixMapping(arg0, arg1); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/Statistics.java b/src/nu/validator/servlet/Statistics.java |
| deleted file mode 100644 |
| index 37ada19..0000000 |
| --- a/src/nu/validator/servlet/Statistics.java |
| +++ /dev/null |
| @@ -1,248 +0,0 @@ |
| -/* |
| - * Copyright (c) 2012 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.text.DecimalFormat; |
| - |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import nu.validator.htmlparser.sax.HtmlSerializer; |
| -import nu.validator.xml.EmptyAttributes; |
| - |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.SAXException; |
| - |
| -public class Statistics { |
| - |
| - public static final Statistics STATISTICS; |
| - |
| - private static final char[] VALIDATOR_STATISTICS = "Validator statistics".toCharArray(); |
| - |
| - private static final char[] COUNTER_NAME = "Counter".toCharArray(); |
| - |
| - private static final char[] COUNTER_VALUE = "Value".toCharArray(); |
| - |
| - private static final char[] COUNTER_PROPORTION = "Proportion".toCharArray(); |
| - |
| - private static final char[] TOTAL_VALIDATIONS = "Total number of validations".toCharArray(); |
| - |
| - private static final char[] UPTIME_DAYS = "Uptime in days".toCharArray(); |
| - |
| - private static final char[] VALIDATIONS_PER_SECOND = "Validations per second".toCharArray(); |
| - |
| - public enum Field { |
| - // Sigh. Eclipse's formatting of the following code is sad. |
| - CUSTOM_ENC("Manually set character encoding"), AUTO_SCHEMA( |
| - "Automatically chosen schema"), PRESET_SCHEMA("Preset schema"), BUILT_IN_NON_PRESET( |
| - "Custom schema combined from built-ins"), HTML5_SCHEMA( |
| - "(X)HTML5 schema"), HTML5_RDFA_LITE_SCHEMA( |
| - "(X)HTML5+RDFa Lite schema"), HTML4_STRICT_SCHEMA( |
| - "Legacy Strict schema"), HTML4_TRANSITIONAL_SCHEMA( |
| - "Legacy Transitional schema"), HTML4_FRAMESET_SCHEMA( |
| - "Legacy Frameset schema"), XHTML1_COMPOUND_SCHEMA( |
| - "Legacy XHTML+SVG+MathML schema"), SVG_SCHEMA("SVG schema"), EXTERNAL_SCHEMA_NON_SCHEMATRON( |
| - "non-Schematron custom schema"), EXTERNAL_SCHEMA_SCHEMATRON( |
| - "Schematron custom schema"), LOGIC_ERROR( |
| - "Logic errors in schema stats"), PARSER_XML_EXTERNAL( |
| - "Parser set to XML with external entities"), PARSER_HTML4( |
| - "Parser set to explicit HTML4 mode"), XMLNS_FILTER( |
| - "XMLNS filter set"), LAX_TYPE( |
| - "Being lax about HTTP content type"), IMAGE_REPORT( |
| - "Image report"), SHOW_SOURCE("Show source"), SHOW_OUTLINE( |
| - "Show outline"), INPUT_GET("GET-based input"), INPUT_POST( |
| - "POST-based input"), INPUT_TEXT_FIELD("\u2514 Text-field input"), INPUT_FILE_UPLOAD( |
| - "\u2514 File-upload input"), INPUT_ENTITY_BODY( |
| - "\u2514 Entity-body input"), OUTPUT_HTML("HTML output"), OUTPUT_XHTML( |
| - "XHTML output"), OUTPUT_XML("XML output"), OUTPUT_JSON( |
| - "JSON output"), OUTPUT_GNU("GNU output"), OUTPUT_TEXT( |
| - "Text output"), INPUT_HTML("HTML input"), INPUT_XML("XML input"); |
| - |
| - Field(String description) { |
| - this.description = description; |
| - } |
| - |
| - private final String description; |
| - |
| - /** |
| - * @see java.lang.Enum#toString() |
| - */ |
| - @Override public String toString() { |
| - return description; |
| - } |
| - } |
| - |
| - static { |
| - if ("1".equals(System.getProperty("nu.validator.servlet.statistics"))) { |
| - STATISTICS = new Statistics(); |
| - } else { |
| - STATISTICS = null; |
| - } |
| - } |
| - |
| - private final long startTime = System.currentTimeMillis(); |
| - |
| - private long total = 0; |
| - |
| - private final long[] counters; |
| - |
| - private Statistics() { |
| - counters = new long[Field.values().length]; |
| - } |
| - |
| - public void incrementTotal() { |
| - total++; |
| - } |
| - |
| - public void incrementField(Field field) { |
| - counters[field.ordinal()]++; |
| - } |
| - |
| - public void writeToResponse(HttpServletResponse response) |
| - throws IOException { |
| - try { |
| - long totalCopy; |
| - long[] countersCopy = new long[counters.length]; |
| - synchronized (this) { |
| - totalCopy = total; |
| - System.arraycopy(counters, 0, countersCopy, 0, counters.length); |
| - } |
| - double totalDouble = (double) totalCopy; |
| - double uptimeMillis = (double) (System.currentTimeMillis() - startTime); |
| - response.setContentType("text/html; charset=utf-8"); |
| - ContentHandler ch = new HtmlSerializer(response.getOutputStream()); |
| - try { |
| - ch.startDocument(); |
| - startElement(ch, "html"); |
| - startElement(ch, "head"); |
| - startElement(ch, "title"); |
| - characters(ch, VALIDATOR_STATISTICS); |
| - endElement(ch, "title"); |
| - endElement(ch, "head"); |
| - startElement(ch, "body"); |
| - startElement(ch, "h1"); |
| - characters(ch, VALIDATOR_STATISTICS); |
| - endElement(ch, "h1"); |
| - |
| - startElement(ch, "dl"); |
| - startElement(ch, "dt"); |
| - characters(ch, TOTAL_VALIDATIONS); |
| - endElement(ch, "dt"); |
| - startElement(ch, "dd"); |
| - characters(ch, totalCopy); |
| - endElement(ch, "dd"); |
| - |
| - startElement(ch, "dt"); |
| - characters(ch, UPTIME_DAYS); |
| - endElement(ch, "dt"); |
| - startElement(ch, "dd"); |
| - characters(ch, uptimeMillis / (1000 * 60 * 60 * 24)); |
| - endElement(ch, "dd"); |
| - |
| - startElement(ch, "dt"); |
| - characters(ch, VALIDATIONS_PER_SECOND); |
| - endElement(ch, "dt"); |
| - startElement(ch, "dd"); |
| - characters(ch, totalDouble / (uptimeMillis / 1000.0)); |
| - endElement(ch, "dd"); |
| - |
| - endElement(ch, "dl"); |
| - |
| - startElement(ch, "table"); |
| - startElement(ch, "thead"); |
| - startElement(ch, "tr"); |
| - startElement(ch, "th"); |
| - characters(ch, COUNTER_NAME); |
| - endElement(ch, "th"); |
| - startElement(ch, "th"); |
| - characters(ch, COUNTER_VALUE); |
| - endElement(ch, "th"); |
| - startElement(ch, "th"); |
| - characters(ch, COUNTER_PROPORTION); |
| - endElement(ch, "th"); |
| - endElement(ch, "tr"); |
| - endElement(ch, "thead"); |
| - startElement(ch, "tbody"); |
| - for (int i = 0; i < countersCopy.length; i++) { |
| - long count = countersCopy[i]; |
| - startElement(ch, "tr"); |
| - startElement(ch, "td"); |
| - |
| - characters(ch, Field.values()[i].toString()); |
| - |
| - endElement(ch, "td"); |
| - startElement(ch, "td"); |
| - |
| - characters(ch, count); |
| - |
| - endElement(ch, "td"); |
| - startElement(ch, "td"); |
| - |
| - characters(ch, ((double) count) / totalDouble); |
| - |
| - endElement(ch, "td"); |
| - endElement(ch, "tr"); |
| - } |
| - endElement(ch, "tbody"); |
| - endElement(ch, "table"); |
| - endElement(ch, "body"); |
| - endElement(ch, "html"); |
| - } finally { |
| - ch.endDocument(); |
| - } |
| - } catch (SAXException e) { |
| - throw new IOException(e); |
| - } |
| - } |
| - |
| - private void characters(ContentHandler ch, double d) throws SAXException { |
| - // Let's just create a new DecimalFormat each time to avoid the |
| - // complexity of recycling an instance correctly without threading |
| - // hazards. |
| - DecimalFormat df = new DecimalFormat("#,###,##0.000000"); |
| - characters(ch, df.format(d)); |
| - } |
| - |
| - private void characters(ContentHandler ch, long l) throws SAXException { |
| - characters(ch, Long.toString(l)); |
| - } |
| - |
| - private void characters(ContentHandler ch, String str) throws SAXException { |
| - characters(ch, str.toCharArray()); |
| - } |
| - |
| - private void characters(ContentHandler ch, char[] cs) throws SAXException { |
| - ch.characters(cs, 0, cs.length); |
| - } |
| - |
| - private void endElement(ContentHandler ch, String name) throws SAXException { |
| - ch.endElement("http://www.w3.org/1999/xhtml", name, name); |
| - } |
| - |
| - private void startElement(ContentHandler ch, String name) |
| - throws SAXException { |
| - ch.startElement("http://www.w3.org/1999/xhtml", name, name, |
| - EmptyAttributes.EMPTY_ATTRIBUTES); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/StatsEmitter.java b/src/nu/validator/servlet/StatsEmitter.java |
| deleted file mode 100644 |
| index 9ed17a1..0000000 |
| --- a/src/nu/validator/servlet/StatsEmitter.java |
| +++ /dev/null |
| @@ -1,18 +0,0 @@ |
| -/* This code was generated by nu.validator.tools.SaxCompiler. Please regenerate instead of editing. */ |
| -package nu.validator.servlet; |
| -public final class StatsEmitter { |
| -private StatsEmitter() {} |
| -public static void emit(org.xml.sax.ContentHandler contentHandler, nu.validator.servlet.VerifierServletTransaction t) throws org.xml.sax.SAXException { |
| -org.xml.sax.helpers.AttributesImpl __attrs__ = new org.xml.sax.helpers.AttributesImpl(); |
| -contentHandler.startPrefixMapping("", "http://www.w3.org/1999/xhtml"); |
| -__attrs__.clear(); |
| -__attrs__.addAttribute("", "class", "class", "CDATA", "stats"); |
| -contentHandler.startElement("http://www.w3.org/1999/xhtml", "p", "p", __attrs__); |
| -contentHandler.characters(__chars__, 0, 21); |
| -t.emitTotalDuration(); |
| -contentHandler.characters(__chars__, 21, 14); |
| -contentHandler.endElement("http://www.w3.org/1999/xhtml", "p", "p"); |
| -contentHandler.endPrefixMapping(""); |
| -} |
| -private static final char[] __chars__ = { 'T', 'o', 't', 'a', 'l', ' ', 'e', 'x', 'e', 'c', 'u', 't', 'i', 'o', 'n', ' ', 't', 'i', 'm', 'e', ' ', ' ', 'm', 'i', 'l', 'l', 'i', 's', 'e', 'c', 'o', 'n', 'd', 's', '.' }; |
| -} |
| diff --git a/src/nu/validator/servlet/TreeDumpContentHandler.java b/src/nu/validator/servlet/TreeDumpContentHandler.java |
| deleted file mode 100644 |
| index 5728c8d..0000000 |
| --- a/src/nu/validator/servlet/TreeDumpContentHandler.java |
| +++ /dev/null |
| @@ -1,232 +0,0 @@ |
| -/* |
| - * Copyright (c) 2007 Henri Sivonen |
| - * Copyright (c) 2008 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.io.Writer; |
| -import java.util.Map; |
| -import java.util.TreeMap; |
| - |
| -import org.xml.sax.Attributes; |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.ext.LexicalHandler; |
| - |
| -public class TreeDumpContentHandler implements ContentHandler, LexicalHandler { |
| - |
| - private final Writer writer; |
| - |
| - private int level = 0; |
| - |
| - private boolean inCharacters = false; |
| - |
| - private boolean close; |
| - |
| - /** |
| - * @param writer |
| - */ |
| - public TreeDumpContentHandler(final Writer writer, boolean close) { |
| - this.writer = writer; |
| - this.close = close; |
| - } |
| - |
| - public TreeDumpContentHandler(final Writer writer) { |
| - this(writer, true); |
| - } |
| - |
| - private void printLead() throws IOException { |
| - if (inCharacters) { |
| - writer.write("\"\n"); |
| - inCharacters = false; |
| - } |
| - writer.write("| "); |
| - for (int i = 0; i < level; i++) { |
| - writer.write(" "); |
| - } |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.ContentHandler#characters(char[], int, int) |
| - */ |
| - public void characters(char[] ch, int start, int length) |
| - throws SAXException { |
| - try { |
| - if (!inCharacters) { |
| - printLead(); |
| - writer.write('"'); |
| - inCharacters = true; |
| - } |
| - writer.write(ch, start, length); |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void endElement(String uri, String localName, String qName) |
| - throws SAXException { |
| - try { |
| - if (inCharacters) { |
| - writer.write("\"\n"); |
| - inCharacters = false; |
| - } |
| - level--; |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void startElement(String uri, String localName, String qName, |
| - Attributes atts) throws SAXException { |
| - try { |
| - printLead(); |
| - writer.write('<'); |
| - if ("http://www.w3.org/1998/Math/MathML" == uri) { |
| - writer.write("math "); |
| - } else if ("http://www.w3.org/2000/svg" == uri) { |
| - writer.write("svg "); |
| - } else if ("http://www.w3.org/1999/xhtml" != uri) { |
| - writer.write("otherns "); |
| - } |
| - writer.write(localName); |
| - writer.write(">\n"); |
| - level++; |
| - |
| - TreeMap<String, String> map = new TreeMap<String, String>(); |
| - for (int i = 0; i < atts.getLength(); i++) { |
| - String ns = atts.getURI(i); |
| - String name; |
| - if ("http://www.w3.org/1999/xlink" == ns) { |
| - name = "xlink " + atts.getLocalName(i); |
| - } else if ("http://www.w3.org/XML/1998/namespace" == ns) { |
| - name = "xml " + atts.getLocalName(i); |
| - } else if ("http://www.w3.org/2000/xmlns/" == ns) { |
| - name = "xmlns " + atts.getLocalName(i); |
| - } else if ("" != uri) { |
| - name = atts.getLocalName(i); |
| - } else { |
| - name = "otherns " + atts.getLocalName(i); |
| - } |
| - map.put(name, atts.getValue(i)); |
| - } |
| - for (Map.Entry<String, String> entry : map.entrySet()) { |
| - printLead(); |
| - writer.write(entry.getKey()); |
| - writer.write("=\""); |
| - writer.write(entry.getValue()); |
| - writer.write("\"\n"); |
| - } |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void comment(char[] ch, int offset, int len) throws SAXException { |
| - try { |
| - printLead(); |
| - writer.write("<!-- "); |
| - writer.write(ch, offset, len); |
| - writer.write(" -->\n"); |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void startDTD(String name, String publicIdentifier, |
| - String systemIdentifier) throws SAXException { |
| - try { |
| - printLead(); |
| - writer.write("<!DOCTYPE "); |
| - writer.write(name); |
| - if (publicIdentifier.length() > 0 || systemIdentifier.length() > 0) { |
| - writer.write(' '); |
| - writer.write('\"'); |
| - writer.write(publicIdentifier); |
| - writer.write('\"'); |
| - writer.write(' '); |
| - writer.write('\"'); |
| - writer.write(systemIdentifier); |
| - writer.write('\"'); |
| - } |
| - writer.write(">\n"); |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void endDocument() throws SAXException { |
| - try { |
| - if (inCharacters) { |
| - writer.write("\"\n"); |
| - inCharacters = false; |
| - } |
| - if (close) { |
| - writer.flush(); |
| - writer.close(); |
| - } |
| - } catch (IOException e) { |
| - throw new SAXException(e); |
| - } |
| - } |
| - |
| - public void startPrefixMapping(String prefix, String uri) |
| - throws SAXException { |
| - } |
| - |
| - public void startEntity(String arg0) throws SAXException { |
| - } |
| - |
| - public void endCDATA() throws SAXException { |
| - } |
| - |
| - public void endDTD() throws SAXException { |
| - } |
| - |
| - public void endEntity(String arg0) throws SAXException { |
| - } |
| - |
| - public void startCDATA() throws SAXException { |
| - } |
| - |
| - public void endPrefixMapping(String prefix) throws SAXException { |
| - } |
| - |
| - public void ignorableWhitespace(char[] ch, int start, int length) |
| - throws SAXException { |
| - } |
| - |
| - public void processingInstruction(String target, String data) |
| - throws SAXException { |
| - } |
| - |
| - public void setDocumentLocator(Locator locator) { |
| - } |
| - |
| - public void skippedEntity(String name) throws SAXException { |
| - } |
| - |
| - public void startDocument() throws SAXException { |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/VerifierServlet.java b/src/nu/validator/servlet/VerifierServlet.java |
| deleted file mode 100644 |
| index 987fed9..0000000 |
| --- a/src/nu/validator/servlet/VerifierServlet.java |
| +++ /dev/null |
| @@ -1,306 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005 Henri Sivonen |
| - * Copyright (c) 2007-2014 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.io.InputStream; |
| -import java.io.OutputStream; |
| -import java.io.ByteArrayOutputStream; |
| -import java.io.UnsupportedEncodingException; |
| - |
| -import javax.servlet.ServletException; |
| -import javax.servlet.http.HttpServlet; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import nu.validator.messages.MessageEmitterAdapter; |
| -import nu.validator.xml.PrudentHttpEntityResolver; |
| - |
| -import org.apache.log4j.Logger; |
| - |
| - |
| -/** |
| - * @version $Id$ |
| - * @author hsivonen |
| - */ |
| -public class VerifierServlet extends HttpServlet { |
| - /** |
| - * |
| - */ |
| - private static final long serialVersionUID = 7811043632732680935L; |
| - |
| - private static final Logger log4j = Logger.getLogger(VerifierServlet.class); |
| - |
| - static final String GENERIC_HOST = System.getProperty("nu.validator.servlet.host.generic", ""); |
| - |
| - static final String HTML5_HOST = System.getProperty("nu.validator.servlet.host.html5", ""); |
| - |
| - static final String PARSETREE_HOST = System.getProperty("nu.validator.servlet.host.parsetree", ""); |
| - |
| - static final String GENERIC_PATH = System.getProperty("nu.validator.servlet.path.generic", "/"); |
| - |
| - static final String HTML5_PATH = System.getProperty("nu.validator.servlet.path.html5", "/html5/"); |
| - |
| - static final String PARSETREE_PATH = System.getProperty("nu.validator.servlet.path.parsetree", "/parsetree/"); |
| - |
| - private static final byte[] GENERIC_ROBOTS_TXT; |
| - |
| - private static final byte[] HTML5_ROBOTS_TXT; |
| - |
| - private static final byte[] PARSETREE_ROBOTS_TXT; |
| - |
| - private static final byte[] STYLE_CSS; |
| - |
| - private static final byte[] SCRIPT_JS; |
| - |
| - private static final byte[] ICON_PNG; |
| - |
| - private static final byte[] ABOUT_HTML; |
| - |
| - static { |
| - try { |
| - GENERIC_ROBOTS_TXT = buildRobotsTxt(GENERIC_HOST, GENERIC_PATH, HTML5_HOST, HTML5_PATH, PARSETREE_HOST, PARSETREE_PATH); |
| - HTML5_ROBOTS_TXT = buildRobotsTxt(HTML5_HOST, HTML5_PATH, GENERIC_HOST, GENERIC_PATH, PARSETREE_HOST, PARSETREE_PATH); |
| - PARSETREE_ROBOTS_TXT = buildRobotsTxt(PARSETREE_HOST, PARSETREE_PATH, HTML5_HOST, HTML5_PATH, GENERIC_HOST, GENERIC_PATH); |
| - } catch (UnsupportedEncodingException e) { |
| - throw new RuntimeException(e); |
| - } |
| - try { |
| - STYLE_CSS = readFromClassLoaderIntoByteArray("nu/validator/localentities/files/style.css"); |
| - SCRIPT_JS = readFromClassLoaderIntoByteArray("nu/validator/localentities/files/script.js"); |
| - ICON_PNG = readFromClassLoaderIntoByteArray("nu/validator/localentities/files/icon.png"); |
| - ABOUT_HTML = readFromClassLoaderIntoByteArray("nu/validator/localentities/files/about.html"); |
| - } catch (IOException e) { |
| - throw new RuntimeException(e); |
| - } |
| - PrudentHttpEntityResolver.setParams( |
| - Integer.parseInt(System.getProperty("nu.validator.servlet.connection-timeout","5000")), |
| - Integer.parseInt(System.getProperty("nu.validator.servlet.socket-timeout","5000")), |
| - 100); |
| - // force some class loading |
| - new VerifierServletTransaction(null, null); |
| - new MessageEmitterAdapter(null, false, null, 0, false, null); |
| - } |
| - |
| - /** |
| - * @return |
| - * @throws UnsupportedEncodingException |
| - */ |
| - private static byte[] buildRobotsTxt(String primaryHost, String primaryPath, String secondaryHost, String secondaryPath, String tertiaryHost, String tertiaryPath) throws UnsupportedEncodingException { |
| - StringBuilder builder = new StringBuilder(); |
| - builder.append("User-agent: *\nDisallow: "); |
| - builder.append(primaryPath); |
| - builder.append("?\n"); |
| - if (primaryHost.equals(secondaryHost)) { |
| - builder.append("Disallow: "); |
| - builder.append(secondaryPath); |
| - builder.append("?\n"); |
| - } |
| - if (primaryHost.equals(tertiaryHost)) { |
| - builder.append("Disallow: "); |
| - builder.append(tertiaryPath); |
| - builder.append("?\n"); |
| - } |
| - return builder.toString().getBytes("UTF-8"); |
| - } |
| - |
| - private static byte[] readFromClassLoaderIntoByteArray(String name) |
| - throws IOException { |
| - InputStream ios = VerifierServlet.class.getClassLoader().getResourceAsStream( |
| - name); |
| - ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| - try { |
| - for (int b = ios.read(); b != -1; b = ios.read()) { |
| - baos.write(b); |
| - } |
| - ios.close(); |
| - baos.close(); |
| - } catch (IOException e) { |
| - throw new RuntimeException(e); |
| - } |
| - return baos.toByteArray(); |
| - } |
| - |
| - private void writeResponse(byte[] buffer, String type, |
| - HttpServletResponse response) throws IOException { |
| - try { |
| - response.setContentType(type); |
| - response.setContentLength(buffer.length); |
| - response.setDateHeader("Expires", |
| - System.currentTimeMillis() + 43200000); // 12 hours |
| - OutputStream out = response.getOutputStream(); |
| - out.write(buffer); |
| - out.flush(); |
| - out.close(); |
| - } catch (IOException e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) |
| - */ |
| - @Override |
| - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| - if ("/robots.txt".equals(request.getPathInfo())) { |
| - String serverName = request.getServerName(); |
| - byte[] robotsTxt = null; |
| - if (hostMatch(GENERIC_HOST, serverName)) { |
| - robotsTxt = GENERIC_ROBOTS_TXT; |
| - } else if (hostMatch(HTML5_HOST, serverName)) { |
| - robotsTxt = HTML5_ROBOTS_TXT; |
| - } else if (hostMatch(PARSETREE_HOST, serverName)) { |
| - robotsTxt = PARSETREE_ROBOTS_TXT; |
| - } else { |
| - response.sendError(HttpServletResponse.SC_NOT_FOUND); |
| - return; |
| - } |
| - writeResponse(robotsTxt, "text/plain; charset=utf-8", response); |
| - return; |
| - } else if ("/style.css".equals(request.getPathInfo())) { |
| - writeResponse(STYLE_CSS, "text/css; charset=utf-8", response); |
| - return; |
| - } else if ("/script.js".equals(request.getPathInfo())) { |
| - writeResponse(SCRIPT_JS, "text/javascript; charset=utf-8", response); |
| - return; |
| - } else if ("/icon.png".equals(request.getPathInfo())) { |
| - writeResponse(ICON_PNG, "image/png", response); |
| - return; |
| - } else if ("/about.html".equals(request.getPathInfo())) { |
| - writeResponse(ABOUT_HTML, "text/html; charset=utf-8", response); |
| - return; |
| - } else if (Statistics.STATISTICS != null && "/stats.html".equals(request.getPathInfo())) { |
| - Statistics.STATISTICS.writeToResponse(response); |
| - return; |
| - } |
| - doPost(request, response); |
| - } |
| - |
| - private boolean hostMatch(String reference, String host) { |
| - if ("".equals(reference)) { |
| - return true; |
| - } else { |
| - // XXX case-sensitivity |
| - return reference.equalsIgnoreCase(host); |
| - } |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServlet#doOptions(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) |
| - */ |
| - @Override |
| - protected void doOptions(HttpServletRequest request, |
| - HttpServletResponse response) throws ServletException, IOException { |
| - String pathInfo = request.getPathInfo(); |
| - if ("*".equals(pathInfo)) { // useless RFC 2616 complication |
| - return; |
| - } else if ("/robots.txt".equals(pathInfo)) { |
| - String serverName = request.getServerName(); |
| - if (hostMatch(GENERIC_HOST, serverName) |
| - || hostMatch(HTML5_HOST, serverName) |
| - || hostMatch(PARSETREE_HOST, serverName)) { |
| - sendGetOnlyOptions(request, response); |
| - return; |
| - } else { |
| - response.sendError(HttpServletResponse.SC_NOT_FOUND); |
| - return; |
| - } |
| - } |
| - doPost(request, response); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServlet#doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) |
| - */ |
| - @Override |
| - protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
| - response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); |
| - } |
| - |
| - /** |
| - * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, |
| - * javax.servlet.http.HttpServletResponse) |
| - */ |
| - protected void doPost(HttpServletRequest request, |
| - HttpServletResponse response) throws ServletException, IOException { |
| - String pathInfo = request.getPathInfo(); |
| - if (pathInfo == null) { |
| - pathInfo = "/"; // Fix for Jigsaw |
| - } |
| - String serverName = request.getServerName(); |
| - if ("/robots.txt".equals(pathInfo)) { |
| - // if we get here, we've got a POST |
| - response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); |
| - return; |
| - } |
| - log4j.debug("pathInfo: " + pathInfo); |
| - log4j.debug("serverName: " + serverName); |
| - boolean isOptions = "OPTIONS".equals(request.getMethod()); |
| - |
| - if ("validator.nu".equals(serverName) && "/html5/".equals(pathInfo)) { |
| - response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); |
| - String queryString = request.getQueryString(); |
| - response.setHeader("Location", "http://html5.validator.nu/" + (queryString == null ? "" : "?" + queryString)); |
| - } else if (hostMatch(GENERIC_HOST, serverName) && GENERIC_PATH.equals(pathInfo)) { |
| - response.setHeader("Access-Control-Allow-Origin", "*"); |
| - response.setHeader("Access-Control-Allow-Headers", "content-type"); |
| - if (isOptions) { |
| - sendOptions(request, response); |
| - } else { |
| - new VerifierServletTransaction(request, response).service(); |
| - } |
| - } else if (hostMatch(HTML5_HOST, serverName) && HTML5_PATH.equals(pathInfo)) { |
| - response.setHeader("Access-Control-Allow-Origin", "*"); |
| - response.setHeader("Access-Control-Allow-Headers", "content-type"); |
| - if (isOptions) { |
| - sendOptions(request, response); |
| - } else { |
| - new Html5ConformanceCheckerTransaction(request, response).service(); |
| - } |
| - } else if (hostMatch(PARSETREE_HOST, serverName) && PARSETREE_PATH.equals(pathInfo)) { |
| - if (isOptions) { |
| - sendGetOnlyOptions(request, response); |
| - } else { |
| - new ParseTreePrinter(request, response).service(); |
| - } |
| - } else { |
| - response.sendError(HttpServletResponse.SC_NOT_FOUND); |
| - } |
| - } |
| - |
| - private void sendGetOnlyOptions(HttpServletRequest request, HttpServletResponse response) { |
| - response.setHeader("Allow", "GET, HEAD, OPTIONS"); |
| - response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, OPTIONS"); |
| - response.setContentType("application/octet-stream"); |
| - response.setContentLength(0); |
| - } |
| - |
| - private void sendOptions(HttpServletRequest request, HttpServletResponse response) { |
| - response.setHeader("Access-Control-Max-Age", "43200"); // 12 hours |
| - response.setHeader("Allow", "GET, HEAD, POST, OPTIONS"); |
| - response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, OPTIONS"); |
| - response.setContentType("application/octet-stream"); |
| - response.setContentLength(0); |
| - } |
| -} |
| diff --git a/src/nu/validator/servlet/VerifierServletTransaction.java b/src/nu/validator/servlet/VerifierServletTransaction.java |
| deleted file mode 100644 |
| index 5239a06..0000000 |
| --- a/src/nu/validator/servlet/VerifierServletTransaction.java |
| +++ /dev/null |
| @@ -1,2051 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005, 2006 Henri Sivonen |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.BufferedReader; |
| -import java.io.IOException; |
| -import java.io.InputStreamReader; |
| -import java.io.OutputStream; |
| -import java.util.Arrays; |
| -import java.util.Deque; |
| -import java.util.HashMap; |
| -import java.util.HashSet; |
| -import java.util.LinkedHashSet; |
| -import java.util.LinkedList; |
| -import java.util.List; |
| -import java.util.Map; |
| -import java.util.Properties; |
| -import java.util.Set; |
| -import java.util.SortedMap; |
| -import java.util.TreeMap; |
| -import java.util.regex.Matcher; |
| -import java.util.regex.Pattern; |
| - |
| -import javax.servlet.ServletException; |
| -import javax.servlet.http.HttpServletRequest; |
| -import javax.servlet.http.HttpServletResponse; |
| - |
| -import nu.validator.checker.XmlPiChecker; |
| -import nu.validator.checker.jing.CheckerSchema; |
| -import nu.validator.gnu.xml.aelfred2.SAXDriver; |
| -import nu.validator.htmlparser.common.DoctypeExpectation; |
| -import nu.validator.htmlparser.common.DocumentMode; |
| -import nu.validator.htmlparser.common.DocumentModeHandler; |
| -import nu.validator.htmlparser.common.Heuristics; |
| -import nu.validator.htmlparser.common.XmlViolationPolicy; |
| -import nu.validator.htmlparser.sax.HtmlParser; |
| -import nu.validator.htmlparser.sax.HtmlSerializer; |
| -import nu.validator.htmlparser.sax.XmlSerializer; |
| -import nu.validator.io.BoundedInputStream; |
| -import nu.validator.io.DataUri; |
| -import nu.validator.io.StreamBoundException; |
| -import nu.validator.localentities.LocalCacheEntityResolver; |
| -import nu.validator.messages.GnuMessageEmitter; |
| -import nu.validator.messages.JsonMessageEmitter; |
| -import nu.validator.messages.MessageEmitterAdapter; |
| -import nu.validator.messages.TextMessageEmitter; |
| -import nu.validator.messages.TooManyErrorsException; |
| -import nu.validator.messages.XhtmlMessageEmitter; |
| -import nu.validator.messages.XmlMessageEmitter; |
| -import nu.validator.servlet.imagereview.ImageCollector; |
| -import nu.validator.servlet.OutlineBuildingXMLReaderWrapper.Section; |
| -import nu.validator.source.SourceCode; |
| -import nu.validator.spec.Spec; |
| -import nu.validator.spec.html5.Html5SpecBuilder; |
| -import nu.validator.xml.AttributesImpl; |
| -import nu.validator.xml.AttributesPermutingXMLReaderWrapper; |
| -import nu.validator.xml.BaseUriTracker; |
| -import nu.validator.xml.CharacterUtil; |
| -import nu.validator.xml.CombineContentHandler; |
| -import nu.validator.xml.ContentTypeParser; |
| -import nu.validator.xml.DataUriEntityResolver; |
| -import nu.validator.xml.IdFilter; |
| -import nu.validator.xml.NamespaceDroppingXMLReaderWrapper; |
| -import nu.validator.xml.NullEntityResolver; |
| -import nu.validator.xml.PrudentHttpEntityResolver; |
| -import nu.validator.xml.SystemErrErrorHandler; |
| -import nu.validator.xml.TypedInputSource; |
| -import nu.validator.xml.WiretapXMLReaderWrapper; |
| -import nu.validator.xml.XhtmlSaxEmitter; |
| -import nu.validator.xml.dataattributes.DataAttributeDroppingSchemaWrapper; |
| -import nu.validator.xml.langattributes.XmlLangAttributeDroppingSchemaWrapper; |
| -import nu.validator.xml.roleattributes.RoleAttributeFilteringSchemaWrapper; |
| - |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.EntityResolver; |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.Locator; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXNotRecognizedException; |
| -import org.xml.sax.SAXNotSupportedException; |
| -import org.xml.sax.SAXParseException; |
| -import org.xml.sax.XMLReader; |
| -import org.xml.sax.ext.LexicalHandler; |
| - |
| -import com.thaiopensource.relaxng.impl.CombineValidator; |
| -import com.thaiopensource.util.PropertyMap; |
| -import com.thaiopensource.util.PropertyMapBuilder; |
| -import com.thaiopensource.validate.IncorrectSchemaException; |
| -import com.thaiopensource.validate.Schema; |
| -import com.thaiopensource.validate.SchemaReader; |
| -import com.thaiopensource.validate.SchemaResolver; |
| -import com.thaiopensource.validate.ValidateProperty; |
| -import com.thaiopensource.validate.Validator; |
| -import com.thaiopensource.validate.auto.AutoSchemaReader; |
| -import com.thaiopensource.validate.prop.rng.RngProperty; |
| -import com.thaiopensource.validate.prop.wrap.WrapProperty; |
| -import com.thaiopensource.validate.rng.CompactSchemaReader; |
| - |
| -import org.apache.log4j.Logger; |
| -import com.ibm.icu.text.Normalizer; |
| - |
| -/** |
| - * @version $Id: VerifierServletTransaction.java,v 1.10 2005/07/24 07:32:48 |
| - * hsivonen Exp $ |
| - * @author hsivonen |
| - */ |
| -class VerifierServletTransaction implements DocumentModeHandler, SchemaResolver { |
| - |
| - private enum OutputFormat { |
| - HTML, XHTML, TEXT, XML, JSON, RELAXED, SOAP, UNICORN, GNU |
| - } |
| - |
| - private static final Logger log4j = Logger.getLogger(VerifierServletTransaction.class); |
| - |
| - private static final Pattern SPACE = Pattern.compile("\\s+"); |
| - |
| - private static final Pattern JS_IDENTIFIER = Pattern.compile("[\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}_\\$][\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}_\\$\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}]*"); |
| - |
| - private static final String[] JS_RESERVED_WORDS = { "abstract", "boolean", |
| - "break", "byte", "case", "catch", "char", "class", "const", |
| - "continue", "debugger", "default", "delete", "do", "double", |
| - "else", "enum", "export", "extends", "final", "finally", "float", |
| - "for", "function", "goto", "if", "implements", "import", "in", |
| - "instanceof", "int", "interface", "long", "native", "new", |
| - "package", "private", "protected", "public", "return", "short", |
| - "static", "super", "switch", "synchronized", "this", "throw", |
| - "throws", "transient", "try", "typeof", "var", "void", "volatile", |
| - "while", "with" }; |
| - |
| - private static final String[] CHARSETS = { "UTF-8", "UTF-16", |
| - "Windows-1250", "Windows-1251", "Windows-1252", "Windows-1253", |
| - "Windows-1254", "Windows-1255", "Windows-1256", "Windows-1257", |
| - "Windows-1258", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", |
| - "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", |
| - "ISO-8859-8", "ISO-8859-9", "ISO-8859-13", "ISO-8859-15", "KOI8-R", |
| - "TIS-620", "GBK", "GB18030", "Big5", "Big5-HKSCS", "Shift_JIS", |
| - "ISO-2022-JP", "EUC-JP", "ISO-2022-KR", "EUC-KR" }; |
| - |
| - private static final char[][] CHARSET_DESCRIPTIONS = { |
| - "UTF-8 (Global)".toCharArray(), "UTF-16 (Global)".toCharArray(), |
| - "Windows-1250 (Central European)".toCharArray(), |
| - "Windows-1251 (Cyrillic)".toCharArray(), |
| - "Windows-1252 (Western)".toCharArray(), |
| - "Windows-1253 (Greek)".toCharArray(), |
| - "Windows-1254 (Turkish)".toCharArray(), |
| - "Windows-1255 (Hebrew)".toCharArray(), |
| - "Windows-1256 (Arabic)".toCharArray(), |
| - "Windows-1257 (Baltic)".toCharArray(), |
| - "Windows-1258 (Vietnamese)".toCharArray(), |
| - "ISO-8859-1 (Western)".toCharArray(), |
| - "ISO-8859-2 (Central European)".toCharArray(), |
| - "ISO-8859-3 (South European)".toCharArray(), |
| - "ISO-8859-4 (Baltic)".toCharArray(), |
| - "ISO-8859-5 (Cyrillic)".toCharArray(), |
| - "ISO-8859-6 (Arabic)".toCharArray(), |
| - "ISO-8859-7 (Greek)".toCharArray(), |
| - "ISO-8859-8 (Hebrew)".toCharArray(), |
| - "ISO-8859-9 (Turkish)".toCharArray(), |
| - "ISO-8859-13 (Baltic)".toCharArray(), |
| - "ISO-8859-15 (Western)".toCharArray(), |
| - "KOI8-R (Russian)".toCharArray(), "TIS-620 (Thai)".toCharArray(), |
| - "GBK (Chinese, simplified)".toCharArray(), |
| - "GB18030 (Chinese, simplified)".toCharArray(), |
| - "Big5 (Chinese, traditional)".toCharArray(), |
| - "Big5-HKSCS (Chinese, traditional)".toCharArray(), |
| - "Shift_JIS (Japanese)".toCharArray(), |
| - "ISO-2022-JP (Japanese)".toCharArray(), |
| - "EUC-JP (Japanese)".toCharArray(), |
| - "ISO-2022-KR (Korean)".toCharArray(), |
| - "EUC-KR (Korean)".toCharArray() }; |
| - |
| - protected static final int HTML5_SCHEMA = 3; |
| - |
| - protected static final int XHTML1STRICT_SCHEMA = 2; |
| - |
| - protected static final int XHTML1TRANSITIONAL_SCHEMA = 1; |
| - |
| - protected static final int XHTML5_SCHEMA = 7; |
| - |
| - private static final char[] SERVICE_TITLE; |
| - |
| - private static final char[] LIVING_VERSION = "Living Validator".toCharArray(); |
| - |
| - private static final char[] VERSION; |
| - |
| - private static final char[] RESULTS_TITLE; |
| - |
| - private static final char[] FOR = " for ".toCharArray(); |
| - |
| - private static final char[] ABOUT_THIS_SERVICE = "About this Service".toCharArray(); |
| - |
| - private static final char[] SIMPLE_UI = "Simplified Interface".toCharArray(); |
| - |
| - private static final String USER_AGENT; |
| - |
| - private static Spec html5spec; |
| - |
| - private static int[] presetDoctypes; |
| - |
| - private static String[] presetLabels; |
| - |
| - private static String[] presetUrls; |
| - |
| - private static String[] presetNamespaces; |
| - |
| - // XXX SVG!!! |
| - |
| - private static final String[] KNOWN_CONTENT_TYPES = { |
| - "application/atom+xml", "application/docbook+xml", |
| - "application/xhtml+xml", "application/xv+xml", "image/svg+xml" }; |
| - |
| - private static final String[] NAMESPACES_FOR_KNOWN_CONTENT_TYPES = { |
| - "http://www.w3.org/2005/Atom", "http://docbook.org/ns/docbook", |
| - "http://www.w3.org/1999/xhtml", "http://www.w3.org/1999/xhtml", |
| - "http://www.w3.org/2000/svg" }; |
| - |
| - private static final String[] ALL_CHECKERS = { |
| - "http://c.validator.nu/table/", "http://c.validator.nu/nfc/", |
| - "http://c.validator.nu/text-content/", |
| - "http://c.validator.nu/unchecked/", |
| - "http://c.validator.nu/usemap/", "http://c.validator.nu/obsolete/", |
| - "http://c.validator.nu/xml-pi/", "http://c.validator.nu/unsupported/", |
| - "http://c.validator.nu/microdata/" }; |
| - |
| - private static final String[] ALL_CHECKERS_HTML4 = { |
| - "http://c.validator.nu/table/", "http://c.validator.nu/nfc/", |
| - "http://c.validator.nu/unchecked/", "http://c.validator.nu/usemap/" }; |
| - |
| - private long start = System.currentTimeMillis(); |
| - |
| - protected final HttpServletRequest request; |
| - |
| - private final HttpServletResponse response; |
| - |
| - protected String document = null; |
| - |
| - private ParserMode parser = ParserMode.AUTO; |
| - |
| - private String profile = ""; |
| - |
| - private boolean laxType = false; |
| - |
| - protected ContentHandler contentHandler; |
| - |
| - protected XhtmlSaxEmitter emitter; |
| - |
| - protected MessageEmitterAdapter errorHandler; |
| - |
| - protected final AttributesImpl attrs = new AttributesImpl(); |
| - |
| - private OutputStream out; |
| - |
| - private PropertyMap jingPropertyMap; |
| - |
| - protected LocalCacheEntityResolver entityResolver; |
| - |
| - private static long lastModified; |
| - |
| - private static String[] preloadedSchemaUrls; |
| - |
| - private static Schema[] preloadedSchemas; |
| - |
| - private final static String ABOUT_PAGE = System.getProperty( |
| - "nu.validator.servlet.about-page", "https://about.validator.nu/"); |
| - |
| - private final static String HTML5_FACET = (VerifierServlet.HTML5_HOST.isEmpty() ? "" : ("//" + VerifierServlet.HTML5_HOST)) + VerifierServlet.HTML5_PATH; |
| - |
| - private final static String STYLE_SHEET = System.getProperty( |
| - "nu.validator.servlet.style-sheet", |
| - "style.css"); |
| - |
| - private final static String ICON = System.getProperty( |
| - "nu.validator.servlet.icon", |
| - "icon.png"); |
| - |
| - private final static String SCRIPT = System.getProperty( |
| - "nu.validator.servlet.script", |
| - "script.js"); |
| - |
| - private final static String[] LEGACY_HOSTS = System.getProperty( |
| - "nu.validator.servlet.host.legacy", "").split("\\s+"); |
| - |
| - private static final long SIZE_LIMIT = Integer.parseInt(System.getProperty( |
| - "nu.validator.servlet.max-file-size", "2097152")); |
| - |
| - private String schemaUrls = null; |
| - |
| - protected Validator validator = null; |
| - |
| - private BufferingRootNamespaceSniffer bufferingRootNamespaceSniffer = null; |
| - |
| - private String contentType = null; |
| - |
| - protected HtmlParser htmlParser = null; |
| - |
| - protected SAXDriver xmlParser = null; |
| - |
| - protected XMLReader reader; |
| - |
| - protected TypedInputSource documentInput; |
| - |
| - protected PrudentHttpEntityResolver httpRes; |
| - |
| - protected DataUriEntityResolver dataRes; |
| - |
| - protected ContentTypeParser contentTypeParser; |
| - |
| - private Set<String> loadedValidatorUrls = new HashSet<String>(); |
| - |
| - private boolean checkNormalization = false; |
| - |
| - private boolean rootNamespaceSeen = false; |
| - |
| - private OutputFormat outputFormat; |
| - |
| - private String postContentType; |
| - |
| - private boolean methodIsGet; |
| - |
| - private SourceCode sourceCode = new SourceCode(); |
| - |
| - private Deque<Section> outline; |
| - |
| - private boolean showSource; |
| - |
| - private boolean showOutline; |
| - |
| - private String userAgent; |
| - |
| - private BaseUriTracker baseUriTracker = null; |
| - |
| - private String charsetOverride = null; |
| - |
| - private Set<String> filteredNamespaces = new LinkedHashSet<String>(); // linked |
| - |
| - private LexicalHandler lexicalHandler; |
| - |
| - // for |
| - // UI |
| - // stability |
| - |
| - protected ImageCollector imageCollector; |
| - |
| - private boolean externalSchema = false; |
| - |
| - private boolean externalSchematron = false; |
| - |
| - private String schemaListForStats = null; |
| - |
| - static { |
| - try { |
| - log4j.debug("Starting static initializer."); |
| - |
| - lastModified = 0; |
| - BufferedReader r = new BufferedReader(new InputStreamReader(LocalCacheEntityResolver.getPresetsAsStream(), "UTF-8")); |
| - String line; |
| - List<String> doctypes = new LinkedList<String>(); |
| - List<String> namespaces = new LinkedList<String>(); |
| - List<String> labels = new LinkedList<String>(); |
| - List<String> urls = new LinkedList<String>(); |
| - Properties props = new Properties(); |
| - |
| - log4j.debug("Reading miscellaneous properties."); |
| - |
| - props.load(VerifierServlet.class.getClassLoader().getResourceAsStream( |
| - "nu/validator/localentities/files/misc.properties")); |
| - SERVICE_TITLE = (System.getProperty( |
| - "nu.validator.servlet.service-name", |
| - props.getProperty("nu.validator.servlet.service-name", |
| - "Validator.nu")) + " ").toCharArray(); |
| - RESULTS_TITLE = (System.getProperty( |
| - "nu.validator.servlet.results-title", props.getProperty( |
| - "nu.validator.servlet.results-title", |
| - "Validation results"))).toCharArray(); |
| - VERSION = (System.getProperty("nu.validator.servlet.version", |
| - props.getProperty("nu.validator.servlet.version", |
| - "Living Validator"))).toCharArray(); |
| - USER_AGENT= (System.getProperty("nu.validator.servlet.user-agent", |
| - props.getProperty("nu.validator.servlet.user-agent", |
| - "Validator.nu/LV"))); |
| - |
| - log4j.debug("Starting to loop over config file lines."); |
| - |
| - while ((line = r.readLine()) != null) { |
| - if ("".equals(line.trim())) { |
| - break; |
| - } |
| - String s[] = line.split("\t"); |
| - doctypes.add(s[0]); |
| - namespaces.add(s[1]); |
| - labels.add(s[2]); |
| - urls.add(s[3]); |
| - } |
| - |
| - log4j.debug("Finished reading config."); |
| - |
| - String[] presetDoctypesAsStrings = doctypes.toArray(new String[0]); |
| - presetNamespaces = namespaces.toArray(new String[0]); |
| - presetLabels = labels.toArray(new String[0]); |
| - presetUrls = urls.toArray(new String[0]); |
| - |
| - log4j.debug("Converted config to arrays."); |
| - |
| - for (int i = 0; i < presetNamespaces.length; i++) { |
| - String str = presetNamespaces[i]; |
| - if ("-".equals(str)) { |
| - presetNamespaces[i] = null; |
| - } else { |
| - presetNamespaces[i] = presetNamespaces[i].intern(); |
| - } |
| - } |
| - |
| - log4j.debug("Prepared namespace array."); |
| - |
| - presetDoctypes = new int[presetDoctypesAsStrings.length]; |
| - for (int i = 0; i < presetDoctypesAsStrings.length; i++) { |
| - presetDoctypes[i] = Integer.parseInt(presetDoctypesAsStrings[i]); |
| - } |
| - |
| - log4j.debug("Parsed doctype numbers into ints."); |
| - |
| - String prefix = System.getProperty("nu.validator.servlet.cachepathprefix"); |
| - |
| - log4j.debug("The cache path prefix is: " + prefix); |
| - |
| - ErrorHandler eh = new SystemErrErrorHandler(); |
| - LocalCacheEntityResolver er = new LocalCacheEntityResolver(new NullEntityResolver()); |
| - er.setAllowRnc(true); |
| - PropertyMapBuilder pmb = new PropertyMapBuilder(); |
| - pmb.put(ValidateProperty.ERROR_HANDLER, eh); |
| - pmb.put(ValidateProperty.ENTITY_RESOLVER, er); |
| - pmb.put(ValidateProperty.XML_READER_CREATOR, |
| - new VerifierServletXMLReaderCreator(eh, er)); |
| - RngProperty.CHECK_ID_IDREF.add(pmb); |
| - PropertyMap pMap = pmb.toPropertyMap(); |
| - |
| - log4j.debug("Parsing set up. Starting to read schemas."); |
| - |
| - SortedMap<String, Schema> schemaMap = new TreeMap<String, Schema>(); |
| - |
| - schemaMap.put("http://c.validator.nu/table/", |
| - CheckerSchema.TABLE_CHECKER); |
| - schemaMap.put("http://hsivonen.iki.fi/checkers/table/", |
| - CheckerSchema.TABLE_CHECKER); |
| - schemaMap.put("http://c.validator.nu/nfc/", |
| - CheckerSchema.NORMALIZATION_CHECKER); |
| - schemaMap.put("http://hsivonen.iki.fi/checkers/nfc/", |
| - CheckerSchema.NORMALIZATION_CHECKER); |
| - schemaMap.put("http://c.validator.nu/debug/", |
| - CheckerSchema.DEBUG_CHECKER); |
| - schemaMap.put("http://hsivonen.iki.fi/checkers/debug/", |
| - CheckerSchema.DEBUG_CHECKER); |
| - schemaMap.put("http://c.validator.nu/text-content/", |
| - CheckerSchema.TEXT_CONTENT_CHECKER); |
| - schemaMap.put("http://hsivonen.iki.fi/checkers/text-content/", |
| - CheckerSchema.TEXT_CONTENT_CHECKER); |
| - schemaMap.put("http://c.validator.nu/usemap/", |
| - CheckerSchema.USEMAP_CHECKER); |
| - schemaMap.put("http://n.validator.nu/checkers/usemap/", |
| - CheckerSchema.USEMAP_CHECKER); |
| - schemaMap.put("http://c.validator.nu/unchecked/", |
| - CheckerSchema.UNCHECKED_SUBTREE_WARNER); |
| - schemaMap.put("http://s.validator.nu/html5/assertions.sch", |
| - CheckerSchema.ASSERTION_SCH); |
| - schemaMap.put("http://s.validator.nu/html4/assertions.sch", |
| - CheckerSchema.HTML4ASSERTION_SCH); |
| - schemaMap.put("http://c.validator.nu/obsolete/", |
| - CheckerSchema.CONFORMING_BUT_OBSOLETE_WARNER); |
| - schemaMap.put("http://c.validator.nu/xml-pi/", |
| - CheckerSchema.XML_PI_CHECKER); |
| - schemaMap.put("http://c.validator.nu/unsupported/", |
| - CheckerSchema.UNSUPPORTED_CHECKER); |
| - schemaMap.put("http://c.validator.nu/microdata/", |
| - CheckerSchema.MICRODATA_CHECKER); |
| - schemaMap.put("http://c.validator.nu/rdfalite/", |
| - CheckerSchema.RDFALITE_CHECKER); |
| - |
| - for (int i = 0; i < presetUrls.length; i++) { |
| - String[] urls1 = SPACE.split(presetUrls[i]); |
| - for (int j = 0; j < urls1.length; j++) { |
| - String url = urls1[j]; |
| - if (schemaMap.get(url) == null && !isCheckerUrl(url)) { |
| - Schema sch = schemaByUrl(url, er, pMap); |
| - schemaMap.put(url, sch); |
| - } |
| - } |
| - } |
| - |
| - log4j.debug("Schemas read."); |
| - |
| - preloadedSchemaUrls = new String[schemaMap.size()]; |
| - preloadedSchemas = new Schema[schemaMap.size()]; |
| - int i = 0; |
| - for (Map.Entry<String, Schema> entry : schemaMap.entrySet()) { |
| - preloadedSchemaUrls[i] = entry.getKey().intern(); |
| - Schema s = entry.getValue(); |
| - String u = entry.getKey(); |
| - if (isDataAttributeDroppingSchema(u)) { |
| - s = new DataAttributeDroppingSchemaWrapper( |
| - s); |
| - } |
| - if (isXmlLangAllowingSchema(u)) { |
| - s = new XmlLangAttributeDroppingSchemaWrapper(s); |
| - } |
| - if (isRoleAttributeFilteringSchema(u)) { |
| - s = new RoleAttributeFilteringSchemaWrapper(s); |
| - } |
| - preloadedSchemas[i] = s; |
| - i++; |
| - } |
| - |
| - log4j.debug("Reading spec."); |
| - |
| - html5spec = Html5SpecBuilder.parseSpec(LocalCacheEntityResolver.getHtml5SpecAsStream()); |
| - |
| - log4j.debug("Spec read."); |
| - |
| - log4j.debug("Initialization complete."); |
| - } catch (Exception e) { |
| - throw new RuntimeException(e); |
| - } |
| - } |
| - |
| - protected static String scrub(CharSequence s) { |
| - return Normalizer.normalize( |
| - CharacterUtil.prudentlyScrubCharacterData(s), Normalizer.NFC); |
| - } |
| - |
| - private static boolean isDataAttributeDroppingSchema(String key) { |
| - return ("http://s.validator.nu/xhtml5.rnc".equals(key) |
| - || "http://s.validator.nu/html5.rnc".equals(key) |
| - || "http://s.validator.nu/html5-all.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-all.rnc".equals(key) |
| - || "http://s.validator.nu/html5-its.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-rdfalite.rnc".equals(key) |
| - || "http://s.validator.nu/html5-rdfalite.rnc".equals(key)); |
| - } |
| - |
| - private static boolean isXmlLangAllowingSchema(String key) { |
| - return ("http://s.validator.nu/xhtml5.rnc".equals(key) |
| - || "http://s.validator.nu/html5.rnc".equals(key) |
| - || "http://s.validator.nu/html5-all.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-all.rnc".equals(key) |
| - || "http://s.validator.nu/html5-its.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-rdfalite.rnc".equals(key) |
| - || "http://s.validator.nu/html5-rdfalite.rnc".equals(key)); |
| - } |
| - |
| - private static boolean isRoleAttributeFilteringSchema(String key) { |
| - return ("http://s.validator.nu/xhtml5.rnc".equals(key) |
| - || "http://s.validator.nu/html5.rnc".equals(key) |
| - || "http://s.validator.nu/html5-all.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-all.rnc".equals(key) |
| - || "http://s.validator.nu/html5-its.rnc".equals(key) |
| - || "http://s.validator.nu/xhtml5-rdfalite.rnc".equals(key) |
| - || "http://s.validator.nu/html5-rdfalite.rnc".equals(key)); |
| - } |
| - |
| - private static boolean isCheckerUrl(String url) { |
| - if ("http://c.validator.nu/all/".equals(url) |
| - || "http://hsivonen.iki.fi/checkers/all/".equals(url)) { |
| - return true; |
| - } else if ("http://c.validator.nu/all-html4/".equals(url) |
| - || "http://hsivonen.iki.fi/checkers/all-html4/".equals(url)) { |
| - return true; |
| - } else if ("http://c.validator.nu/base/".equals(url)) { |
| - return true; |
| - } else if ("http://c.validator.nu/rdfalite/".equals(url)) { |
| - return true; |
| - } |
| - for (int i = 0; i < ALL_CHECKERS.length; i++) { |
| - if (ALL_CHECKERS[i].equals(url)) { |
| - return true; |
| - } |
| - } |
| - return false; |
| - } |
| - |
| - /** |
| - * @param request |
| - * @param response |
| - */ |
| - VerifierServletTransaction(HttpServletRequest request, |
| - HttpServletResponse response) { |
| - this.request = request; |
| - this.response = response; |
| - } |
| - |
| - protected boolean willValidate() { |
| - if (methodIsGet) { |
| - return document != null; |
| - } else { // POST |
| - return true; |
| - } |
| - } |
| - |
| - void service() throws ServletException, IOException { |
| - this.methodIsGet = "GET".equals(request.getMethod()) |
| - || "HEAD".equals(request.getMethod()); |
| - |
| - this.out = response.getOutputStream(); |
| - |
| - System.setProperty("nu.validator.servlet.request.legacy", "false"); |
| - |
| - if (Arrays.asList(LEGACY_HOSTS).contains(request.getRemoteHost())) { |
| - System.setProperty("nu.validator.servlet.request.legacy", "true"); |
| - } |
| - |
| - try { |
| - request.setCharacterEncoding("utf-8"); |
| - } catch (NoSuchMethodError e) { |
| - log4j.debug("Vintage Servlet API doesn't support setCharacterEncoding().", e); |
| - } |
| - |
| - if (!methodIsGet) { |
| - postContentType = request.getContentType(); |
| - if (postContentType == null) { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "Content-Type missing"); |
| - return; |
| - } else if (postContentType.trim().toLowerCase().startsWith( |
| - "application/x-www-form-urlencoded")) { |
| - response.sendError( |
| - HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, |
| - "application/x-www-form-urlencoded not supported. Please use multipart/form-data."); |
| - return; |
| - } |
| - } |
| - |
| - String outFormat = request.getParameter("out"); |
| - if (outFormat == null) { |
| - outputFormat = OutputFormat.HTML; |
| - } else { |
| - if ("html".equals(outFormat)) { |
| - outputFormat = OutputFormat.HTML; |
| - } else if ("xhtml".equals(outFormat)) { |
| - outputFormat = OutputFormat.XHTML; |
| - } else if ("text".equals(outFormat)) { |
| - outputFormat = OutputFormat.TEXT; |
| - } else if ("gnu".equals(outFormat)) { |
| - outputFormat = OutputFormat.GNU; |
| - } else if ("xml".equals(outFormat)) { |
| - outputFormat = OutputFormat.XML; |
| - } else if ("json".equals(outFormat)) { |
| - outputFormat = OutputFormat.JSON; |
| - } else { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "Unsupported output format"); |
| - return; |
| - } |
| - } |
| - |
| - if (!methodIsGet) { |
| - document = request.getHeader("Content-Location"); |
| - } |
| - if (document == null) { |
| - document = request.getParameter("doc"); |
| - } |
| - if (document == null) { |
| - document = request.getParameter("file"); |
| - } |
| - |
| - document = ("".equals(document)) ? null : document; |
| - |
| - String callback = null; |
| - if (outputFormat == OutputFormat.JSON) { |
| - callback = request.getParameter("callback"); |
| - if (callback != null) { |
| - Matcher m = JS_IDENTIFIER.matcher(callback); |
| - if (m.matches()) { |
| - if (Arrays.binarySearch(JS_RESERVED_WORDS, callback) >= 0) { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "Callback is a reserved word."); |
| - return; |
| - } |
| - } else { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "Callback is not a valid ECMA 262 IdentifierName."); |
| - return; |
| - } |
| - } |
| - } |
| - |
| - if (willValidate()) { |
| - response.setDateHeader("Expires", 0); |
| - response.setHeader("Cache-Control", "no-cache"); |
| - } else if (outputFormat == OutputFormat.HTML |
| - || outputFormat == OutputFormat.XHTML) { |
| - response.setDateHeader("Last-Modified", lastModified); |
| - } else { |
| - response.sendError(HttpServletResponse.SC_BAD_REQUEST, |
| - "No input document"); |
| - return; |
| - } |
| - |
| - setup(); |
| - |
| - if (request.getParameter("useragent") != null) { |
| - userAgent = scrub(request.getParameter("useragent")); |
| - } else { |
| - userAgent = USER_AGENT; |
| - } |
| - showSource = (request.getParameter("showsource") != null); |
| - showOutline = (request.getParameter("showoutline") != null); |
| - if (request.getParameter("showimagereport") != null) { |
| - imageCollector = new ImageCollector(sourceCode); |
| - } |
| - |
| - String charset = request.getParameter("charset"); |
| - if (charset != null) { |
| - charset = scrub(charset.trim()); |
| - if (!"".equals(charset)) { |
| - charsetOverride = charset; |
| - } |
| - } |
| - |
| - String nsfilter = request.getParameter("nsfilter"); |
| - if (nsfilter != null) { |
| - String[] nsfilterArr = SPACE.split(nsfilter); |
| - for (int i = 0; i < nsfilterArr.length; i++) { |
| - String ns = nsfilterArr[i]; |
| - if (ns.length() > 0) { |
| - filteredNamespaces.add(ns); |
| - } |
| - } |
| - } |
| - |
| - boolean errorsOnly = ("error".equals(request.getParameter("level"))); |
| - |
| - boolean asciiQuotes = (request.getParameter("asciiquotes") != null); |
| - |
| - int lineOffset = 0; |
| - String lineOffsetStr = request.getParameter("lineoffset"); |
| - if (lineOffsetStr != null) { |
| - try { |
| - lineOffset = Integer.parseInt(lineOffsetStr); |
| - } catch (NumberFormatException e) { |
| - |
| - } |
| - } |
| - |
| - try { |
| - if (outputFormat == OutputFormat.HTML |
| - || outputFormat == OutputFormat.XHTML) { |
| - if (outputFormat == OutputFormat.HTML) { |
| - response.setContentType("text/html; charset=utf-8"); |
| - contentHandler = new HtmlSerializer(out); |
| - } else { |
| - response.setContentType("application/xhtml+xml"); |
| - contentHandler = |
| - new XmlSerializer(out); |
| - } |
| - emitter = new XhtmlSaxEmitter(contentHandler); |
| - errorHandler = new MessageEmitterAdapter(sourceCode, |
| - showSource, imageCollector, lineOffset, false, |
| - new XhtmlMessageEmitter(contentHandler)); |
| - PageEmitter.emit(contentHandler, this); |
| - } else { |
| - if (outputFormat == OutputFormat.TEXT) { |
| - response.setContentType("text/plain; charset=utf-8"); |
| - errorHandler = new MessageEmitterAdapter(sourceCode, |
| - showSource, null, lineOffset, false, |
| - new TextMessageEmitter(out, asciiQuotes)); |
| - } else if (outputFormat == OutputFormat.GNU) { |
| - response.setContentType("text/plain; charset=utf-8"); |
| - errorHandler = new MessageEmitterAdapter(sourceCode, |
| - showSource, null, lineOffset, false, |
| - new GnuMessageEmitter(out, asciiQuotes)); |
| - } else if (outputFormat == OutputFormat.XML) { |
| - response.setContentType("application/xml"); |
| - errorHandler = new MessageEmitterAdapter(sourceCode, |
| - showSource, null, lineOffset, false, |
| - new XmlMessageEmitter(new XmlSerializer(out))); |
| - } else if (outputFormat == OutputFormat.JSON) { |
| - if (callback == null) { |
| - response.setContentType("application/json; charset=utf-8"); |
| - } else { |
| - response.setContentType("application/javascript; charset=utf-8"); |
| - } |
| - errorHandler = new MessageEmitterAdapter(sourceCode, |
| - showSource, null, lineOffset, false, |
| - new JsonMessageEmitter( |
| - new nu.validator.json.Serializer(out), |
| - callback)); |
| - } else { |
| - throw new RuntimeException("Unreachable."); |
| - } |
| - errorHandler.setErrorsOnly(errorsOnly); |
| - validate(); |
| - } |
| - } catch (SAXException e) { |
| - throw new ServletException(e); |
| - } |
| - } |
| - |
| - /** |
| - * @throws ServletException |
| - */ |
| - protected void setup() throws ServletException { |
| - String preset = request.getParameter("preset"); |
| - |
| - if (preset != null && !"".equals(preset)) { |
| - schemaUrls = preset; |
| - } else { |
| - schemaUrls = request.getParameter("schema"); |
| - } |
| - if (schemaUrls == null) { |
| - schemaUrls = ""; |
| - } |
| - |
| - String parserStr = request.getParameter("parser"); |
| - |
| - if ("html".equals(parserStr)) { |
| - parser = ParserMode.HTML_AUTO; |
| - } else if ("xmldtd".equals(parserStr)) { |
| - parser = ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION; |
| - } else if ("xml".equals(parserStr)) { |
| - parser = ParserMode.XML_NO_EXTERNAL_ENTITIES; |
| - } else if ("html5".equals(parserStr)) { |
| - parser = ParserMode.HTML; |
| - } else if ("html4".equals(parserStr)) { |
| - parser = ParserMode.HTML401_STRICT; |
| - } else if ("html4tr".equals(parserStr)) { |
| - parser = ParserMode.HTML401_TRANSITIONAL; |
| - } // else auto |
| - |
| - laxType = (request.getParameter("laxtype") != null); |
| - } |
| - |
| - private boolean useHtml5Schema() { |
| - if ("".equals(schemaUrls)) { |
| - return false; |
| - } |
| - return (schemaUrls.contains("http://s.validator.nu/html5.rnc") |
| - || schemaUrls.contains("http://s.validator.nu/html5-all.rnc") |
| - || schemaUrls.contains("http://s.validator.nu/html5-its.rnc") |
| - || schemaUrls.contains("http://s.validator.nu/html5-rdfalite.rnc")); |
| - } |
| - |
| - private boolean isHtmlUnsafePreset() { |
| - if ("".equals(schemaUrls)) { |
| - return false; |
| - } |
| - boolean preset = false; |
| - for (int i = 0; i < presetUrls.length; i++) { |
| - if (presetUrls[i].equals(schemaUrls)) { |
| - preset = true; |
| - break; |
| - } |
| - } |
| - if (!preset) { |
| - return false; |
| - } |
| - return !(schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-basic.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-strict.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-transitional.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-frameset.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/html5.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/html5-all.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/html5-its.rnc") |
| - || schemaUrls.startsWith("http://s.validator.nu/html5-rdfalite.rnc")); |
| - |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - */ |
| - @SuppressWarnings("deprecation") void validate() throws SAXException { |
| - if (!willValidate()) { |
| - return; |
| - } |
| - |
| - boolean isHtmlOrXhtml = (outputFormat == OutputFormat.HTML || outputFormat == OutputFormat.XHTML); |
| - if (isHtmlOrXhtml) { |
| - try { |
| - out.flush(); |
| - } catch (IOException e1) { |
| - throw new SAXException(e1); |
| - } |
| - } |
| - httpRes = new PrudentHttpEntityResolver(SIZE_LIMIT, laxType, |
| - errorHandler); |
| - httpRes.setUserAgent(userAgent); |
| - dataRes = new DataUriEntityResolver(httpRes, laxType, errorHandler); |
| - contentTypeParser = new ContentTypeParser(errorHandler, laxType); |
| - entityResolver = new LocalCacheEntityResolver(dataRes); |
| - setAllowRnc(true); |
| - try { |
| - this.errorHandler.start(document); |
| - PropertyMapBuilder pmb = new PropertyMapBuilder(); |
| - pmb.put(ValidateProperty.ERROR_HANDLER, errorHandler); |
| - pmb.put(ValidateProperty.ENTITY_RESOLVER, entityResolver); |
| - pmb.put(ValidateProperty.XML_READER_CREATOR, |
| - new VerifierServletXMLReaderCreator(errorHandler, |
| - entityResolver)); |
| - pmb.put(ValidateProperty.SCHEMA_RESOLVER, this); |
| - RngProperty.CHECK_ID_IDREF.add(pmb); |
| - jingPropertyMap = pmb.toPropertyMap(); |
| - |
| - tryToSetupValidator(); |
| - |
| - setAllowRnc(false); |
| - |
| - loadDocAndSetupParser(); |
| - setErrorProfile(); |
| - |
| - reader.setErrorHandler(errorHandler); |
| - contentType = documentInput.getType(); |
| - sourceCode.initialize(documentInput); |
| - if (validator == null) { |
| - checkNormalization = true; |
| - } |
| - if (checkNormalization) { |
| - reader.setFeature( |
| - "http://xml.org/sax/features/unicode-normalization-checking", |
| - true); |
| - } |
| - WiretapXMLReaderWrapper wiretap = new WiretapXMLReaderWrapper( |
| - reader); |
| - ContentHandler recorder = sourceCode.getLocationRecorder(); |
| - if (baseUriTracker == null) { |
| - wiretap.setWiretapContentHander(recorder); |
| - } else { |
| - wiretap.setWiretapContentHander(new CombineContentHandler( |
| - recorder, baseUriTracker)); |
| - } |
| - wiretap.setWiretapLexicalHandler((LexicalHandler) recorder); |
| - reader = wiretap; |
| - if (htmlParser != null) { |
| - htmlParser.addCharacterHandler(sourceCode); |
| - htmlParser.setMappingLangToXmlLang(true); |
| - htmlParser.setErrorHandler(errorHandler.getExactErrorHandler()); |
| - htmlParser.setTreeBuilderErrorHandlerOverride(errorHandler); |
| - errorHandler.setHtml(true); |
| - } else if (xmlParser != null) { |
| - // this must be after wiretap! |
| - if (!filteredNamespaces.isEmpty()) { |
| - reader = new NamespaceDroppingXMLReaderWrapper(reader, |
| - filteredNamespaces); |
| - } |
| - xmlParser.setErrorHandler(errorHandler.getExactErrorHandler()); |
| - xmlParser.lockErrorHandler(); |
| - } else { |
| - throw new RuntimeException("Bug. Unreachable."); |
| - } |
| - reader = new AttributesPermutingXMLReaderWrapper(reader); // make |
| - // RNG |
| - // validation |
| - // better |
| - if (charsetOverride != null) { |
| - String charset = documentInput.getEncoding(); |
| - if (charset == null) { |
| - errorHandler.warning(new SAXParseException( |
| - "Overriding document character encoding from none to \u201C" |
| - + charsetOverride + "\u201D.", null)); |
| - } else { |
| - errorHandler.warning(new SAXParseException( |
| - "Overriding document character encoding from \u201C" |
| - + charset + "\u201D to \u201C" |
| - + charsetOverride + "\u201D.", null)); |
| - } |
| - documentInput.setEncoding(charsetOverride); |
| - } |
| - if (showOutline) { |
| - reader = new OutlineBuildingXMLReaderWrapper(reader, request); |
| - reader.parse(documentInput); |
| - outline = (Deque<Section>) request.getAttribute("http://validator.nu/properties/document-outline"); |
| - } else { |
| - reader.parse(documentInput); |
| - } |
| - } catch (TooManyErrorsException e) { |
| - log4j.debug("TooManyErrorsException", e); |
| - errorHandler.fatalError(e); |
| - } catch (SAXException e) { |
| - log4j.debug("SAXException", e); |
| - } catch (IOException e) { |
| - isHtmlOrXhtml = false; |
| - log4j.info("IOException", e); |
| - errorHandler.ioError(e); |
| - } catch (IncorrectSchemaException e) { |
| - log4j.debug("IncorrectSchemaException", e); |
| - errorHandler.schemaError(e); |
| - } catch (RuntimeException e) { |
| - isHtmlOrXhtml = false; |
| - log4j.error("RuntimeException, doc: " + document + " schema: " |
| - + schemaUrls + " lax: " + laxType, e); |
| - errorHandler.internalError( |
| - e, |
| - "Oops. That was not supposed to happen. A bug manifested itself in the application internals. Unable to continue. Sorry. The admin was notified."); |
| - } catch (Error e) { |
| - isHtmlOrXhtml = false; |
| - log4j.error("Error, doc: " + document + " schema: " + schemaUrls |
| - + " lax: " + laxType, e); |
| - errorHandler.internalError( |
| - e, |
| - "Oops. That was not supposed to happen. A bug manifested itself in the application internals. Unable to continue. Sorry. The admin was notified."); |
| - } finally { |
| - errorHandler.end(successMessage(), failureMessage()); |
| - gatherStatistics(); |
| - } |
| - if (isHtmlOrXhtml) { |
| - XhtmlOutlineEmitter outlineEmitter = new XhtmlOutlineEmitter( |
| - contentHandler, outline); |
| - outlineEmitter.emit(); |
| - StatsEmitter.emit(contentHandler, this); |
| - } |
| - } |
| - |
| - private void gatherStatistics() { |
| - Statistics stats = Statistics.STATISTICS; |
| - if (stats == null) { |
| - return; |
| - } |
| - synchronized (stats) { |
| - stats.incrementTotal(); |
| - if (charsetOverride != null) { |
| - stats.incrementField(Statistics.Field.CUSTOM_ENC); |
| - } |
| - switch (parser) { |
| - case HTML401_STRICT: |
| - case HTML401_TRANSITIONAL: |
| - stats.incrementField(Statistics.Field.PARSER_HTML4); |
| - break; |
| - case XML_EXTERNAL_ENTITIES_NO_VALIDATION: |
| - stats.incrementField(Statistics.Field.PARSER_XML_EXTERNAL); |
| - break; |
| - } |
| - if (!filteredNamespaces.isEmpty()) { |
| - stats.incrementField(Statistics.Field.XMLNS_FILTER); |
| - } |
| - if (laxType) { |
| - stats.incrementField(Statistics.Field.LAX_TYPE); |
| - } |
| - if (imageCollector != null) { |
| - stats.incrementField(Statistics.Field.IMAGE_REPORT); |
| - } |
| - if (showSource) { |
| - stats.incrementField(Statistics.Field.SHOW_SOURCE); |
| - } |
| - if (showOutline) { |
| - stats.incrementField(Statistics.Field.SHOW_OUTLINE); |
| - } |
| - if (methodIsGet) { |
| - stats.incrementField(Statistics.Field.INPUT_GET); |
| - } else { // POST |
| - stats.incrementField(Statistics.Field.INPUT_POST); |
| - Object inputType = request.getAttribute("nu.validator.servlet.MultipartFormDataFilter.type"); |
| - if ("textarea".equals(inputType)) { |
| - stats.incrementField(Statistics.Field.INPUT_TEXT_FIELD); |
| - } else if ("file".equals(inputType)) { |
| - stats.incrementField(Statistics.Field.INPUT_FILE_UPLOAD); |
| - } else { |
| - stats.incrementField(Statistics.Field.INPUT_ENTITY_BODY); |
| - } |
| - } |
| - if (htmlParser != null) { |
| - stats.incrementField(Statistics.Field.INPUT_HTML); |
| - } |
| - if (xmlParser != null) { |
| - stats.incrementField(Statistics.Field.INPUT_XML); |
| - } |
| - switch (outputFormat) { |
| - case GNU: |
| - stats.incrementField(Statistics.Field.OUTPUT_GNU); |
| - break; |
| - case HTML: |
| - stats.incrementField(Statistics.Field.OUTPUT_HTML); |
| - break; |
| - case JSON: |
| - stats.incrementField(Statistics.Field.OUTPUT_JSON); |
| - break; |
| - case TEXT: |
| - stats.incrementField(Statistics.Field.OUTPUT_TEXT); |
| - break; |
| - case XHTML: |
| - stats.incrementField(Statistics.Field.OUTPUT_XHTML); |
| - break; |
| - case XML: |
| - stats.incrementField(Statistics.Field.OUTPUT_XML); |
| - break; |
| - } |
| - if (schemaListForStats == null) { |
| - stats.incrementField(Statistics.Field.LOGIC_ERROR); |
| - } else { |
| - boolean preset = false; |
| - for (int i = 0; i < presetUrls.length; i++) { |
| - if (presetUrls[i].equals(schemaListForStats)) { |
| - preset = true; |
| - if (externalSchema || externalSchematron) { |
| - stats.incrementField(Statistics.Field.LOGIC_ERROR); |
| - } else { |
| - stats.incrementField(Statistics.Field.PRESET_SCHEMA); |
| - /* |
| - * XXX WARNING WARNING: These mappings correspond to |
| - * values in the presets.txt file in the validator |
| - * source repo. They might be bogus if a custom |
| - * presets file is used instead. |
| - */ |
| - switch (i) { |
| - case 0: |
| - case 5: |
| - stats.incrementField(Statistics.Field.HTML5_SCHEMA); |
| - break; |
| - case 1: |
| - case 6: |
| - stats.incrementField(Statistics.Field.HTML5_RDFA_LITE_SCHEMA); |
| - break; |
| - case 2: |
| - stats.incrementField(Statistics.Field.HTML4_STRICT_SCHEMA); |
| - break; |
| - case 3: |
| - stats.incrementField(Statistics.Field.HTML4_TRANSITIONAL_SCHEMA); |
| - break; |
| - case 4: |
| - stats.incrementField(Statistics.Field.HTML4_FRAMESET_SCHEMA); |
| - break; |
| - case 7: |
| - stats.incrementField(Statistics.Field.XHTML1_COMPOUND_SCHEMA); |
| - break; |
| - case 8: |
| - stats.incrementField(Statistics.Field.SVG_SCHEMA); |
| - break; |
| - default: |
| - stats.incrementField(Statistics.Field.LOGIC_ERROR); |
| - break; |
| - } |
| - } |
| - break; |
| - } |
| - } |
| - if (!preset && !externalSchema) { |
| - stats.incrementField(Statistics.Field.BUILT_IN_NON_PRESET); |
| - } |
| - } |
| - if ("".equals(schemaUrls)) { |
| - stats.incrementField(Statistics.Field.AUTO_SCHEMA); |
| - if (externalSchema) { |
| - stats.incrementField(Statistics.Field.LOGIC_ERROR); |
| - } |
| - } else if (externalSchema) { |
| - if (externalSchematron) { |
| - stats.incrementField(Statistics.Field.EXTERNAL_SCHEMA_SCHEMATRON); |
| - } else { |
| - stats.incrementField(Statistics.Field.EXTERNAL_SCHEMA_NON_SCHEMATRON); |
| - } |
| - } else if (externalSchematron) { |
| - stats.incrementField(Statistics.Field.LOGIC_ERROR); |
| - } |
| - } |
| - } |
| - |
| - /** |
| - * @return |
| - * @throws SAXException |
| - */ |
| - protected String successMessage() throws SAXException { |
| - return "The document validates according to the specified schema(s) and to additional constraints checked by the validator."; |
| - } |
| - |
| - protected String failureMessage() throws SAXException { |
| - return "There were errors."; |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - */ |
| - protected void tryToSetupValidator() throws SAXException, IOException, |
| - IncorrectSchemaException { |
| - validator = validatorByUrls(schemaUrls); |
| - } |
| - |
| - protected void setErrorProfile() { |
| - profile = request.getParameter("profile"); |
| - |
| - HashMap<String, String> profileMap = new HashMap<String, String>(); |
| - |
| - if ("pedagogical".equals(profile)) { |
| - profileMap.put("xhtml1", "warn"); |
| - } else if ("polyglot".equals(profile)) { |
| - profileMap.put("xhtml1", "warn"); |
| - profileMap.put("xhtml2", "warn"); |
| - } else { |
| - return; // presumed to be permissive |
| - } |
| - |
| - htmlParser.setErrorProfile(profileMap); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - */ |
| - protected void loadDocAndSetupParser() throws SAXException, IOException, |
| - IncorrectSchemaException, SAXNotRecognizedException, |
| - SAXNotSupportedException { |
| - switch (parser) { |
| - case HTML_AUTO: |
| - case HTML: |
| - case HTML401_STRICT: |
| - case HTML401_TRANSITIONAL: |
| - if (isHtmlUnsafePreset()) { |
| - String message = "The chosen preset schema is not appropriate for HTML."; |
| - SAXException se = new SAXException(message); |
| - errorHandler.schemaError(se); |
| - throw se; |
| - } |
| - setAllowGenericXml(false); |
| - setAllowHtml(true); |
| - setAcceptAllKnownXmlTypes(false); |
| - setAllowXhtml(false); |
| - loadDocumentInput(); |
| - newHtmlParser(); |
| - DoctypeExpectation doctypeExpectation; |
| - int schemaId; |
| - switch (parser) { |
| - case HTML: |
| - doctypeExpectation = DoctypeExpectation.HTML; |
| - schemaId = HTML5_SCHEMA; |
| - break; |
| - case HTML401_STRICT: |
| - doctypeExpectation = DoctypeExpectation.HTML401_STRICT; |
| - schemaId = XHTML1STRICT_SCHEMA; |
| - break; |
| - case HTML401_TRANSITIONAL: |
| - doctypeExpectation = DoctypeExpectation.HTML401_TRANSITIONAL; |
| - schemaId = XHTML1TRANSITIONAL_SCHEMA; |
| - break; |
| - default: |
| - doctypeExpectation = DoctypeExpectation.AUTO; |
| - schemaId = 0; |
| - break; |
| - } |
| - htmlParser.setDoctypeExpectation(doctypeExpectation); |
| - htmlParser.setDocumentModeHandler(this); |
| - reader = htmlParser; |
| - if (validator == null) { |
| - validator = validatorByDoctype(schemaId); |
| - } |
| - if (validator != null) { |
| - reader.setContentHandler(validator.getContentHandler()); |
| - } |
| - break; |
| - case XML_NO_EXTERNAL_ENTITIES: |
| - case XML_EXTERNAL_ENTITIES_NO_VALIDATION: |
| - setAllowGenericXml(true); |
| - setAllowHtml(false); |
| - setAcceptAllKnownXmlTypes(true); |
| - setAllowXhtml(true); |
| - loadDocumentInput(); |
| - setupXmlParser(); |
| - break; |
| - default: |
| - setAllowGenericXml(true); |
| - setAllowHtml(true); |
| - setAcceptAllKnownXmlTypes(true); |
| - setAllowXhtml(true); |
| - loadDocumentInput(); |
| - String type = documentInput.getType(); |
| - if ("text/html".equals(type) || "text/html-sandboxed".equals(type)) { |
| - if (isHtmlUnsafePreset()) { |
| - String message = "The Content-Type was \u201C" + type + "\u201D, but the chosen preset schema is not appropriate for HTML."; |
| - SAXException se = new SAXException(message); |
| - errorHandler.schemaError(se); |
| - throw se; |
| - } |
| - errorHandler.info("The Content-Type was \u201C" + type + "\u201D. Using the HTML parser."); |
| - newHtmlParser(); |
| - if (useHtml5Schema()) { |
| - htmlParser.setDoctypeExpectation(DoctypeExpectation.HTML); |
| - } else { |
| - htmlParser.setDoctypeExpectation(DoctypeExpectation.AUTO); |
| - } |
| - htmlParser.setDocumentModeHandler(this); |
| - reader = htmlParser; |
| - if (validator != null) { |
| - reader.setContentHandler(validator.getContentHandler()); |
| - } |
| - } else { |
| - errorHandler.info("The Content-Type was \u201C" |
| - + type |
| - + "\u201D. Using the XML parser (not resolving external entities)."); |
| - setupXmlParser(); |
| - } |
| - break; |
| - } |
| - } |
| - |
| - /** |
| - * |
| - */ |
| - protected void newHtmlParser() { |
| - htmlParser = new HtmlParser(); |
| - htmlParser.setCommentPolicy(XmlViolationPolicy.ALLOW); |
| - htmlParser.setContentNonXmlCharPolicy(XmlViolationPolicy.ALLOW); |
| - htmlParser.setContentSpacePolicy(XmlViolationPolicy.ALTER_INFOSET); |
| - htmlParser.setNamePolicy(XmlViolationPolicy.ALLOW); |
| - htmlParser.setStreamabilityViolationPolicy(XmlViolationPolicy.FATAL); |
| - htmlParser.setXmlnsPolicy(XmlViolationPolicy.ALTER_INFOSET); |
| - htmlParser.setMappingLangToXmlLang(true); |
| - htmlParser.setHtml4ModeCompatibleWithXhtml1Schemata(true); |
| - htmlParser.setHeuristics(Heuristics.ALL); |
| - } |
| - |
| - protected Validator validatorByDoctype(int schemaId) throws SAXException, |
| - IOException, IncorrectSchemaException { |
| - if (schemaId == 0) { |
| - return null; |
| - } |
| - for (int i = 0; i < presetDoctypes.length; i++) { |
| - if (presetDoctypes[i] == schemaId) { |
| - return validatorByUrls(presetUrls[i]); |
| - } |
| - } |
| - throw new RuntimeException("Doctype mappings not initialized properly."); |
| - } |
| - |
| - /** |
| - * @throws SAXNotRecognizedException |
| - * @throws SAXNotSupportedException |
| - */ |
| - protected void setupXmlParser() throws SAXNotRecognizedException, |
| - SAXNotSupportedException { |
| - xmlParser = new SAXDriver(); |
| - xmlParser.setCharacterHandler(sourceCode); |
| - if (lexicalHandler != null) { |
| - xmlParser.setProperty("http://xml.org/sax/properties/lexical-handler", |
| - (LexicalHandler) lexicalHandler); |
| - } |
| - reader = new IdFilter(xmlParser); |
| - reader.setFeature("http://xml.org/sax/features/string-interning", true); |
| - reader.setFeature( |
| - "http://xml.org/sax/features/external-general-entities", |
| - parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION); |
| - reader.setFeature( |
| - "http://xml.org/sax/features/external-parameter-entities", |
| - parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION); |
| - if (parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION) { |
| - reader.setEntityResolver(entityResolver); |
| - } else { |
| - reader.setEntityResolver(new NullEntityResolver()); |
| - } |
| - if (validator == null) { |
| - bufferingRootNamespaceSniffer = new BufferingRootNamespaceSniffer( |
| - this); |
| - reader.setContentHandler(bufferingRootNamespaceSniffer); |
| - } else { |
| - reader.setContentHandler(new RootNamespaceSniffer(this, |
| - validator.getContentHandler())); |
| - reader.setDTDHandler(validator.getDTDHandler()); |
| - } |
| - } |
| - |
| - /** |
| - * @param validator |
| - * @return |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - */ |
| - private Validator validatorByUrls(String schemaList) throws SAXException, |
| - IOException, IncorrectSchemaException { |
| - System.setProperty("nu.validator.schema.rdfa-full", "0"); |
| - schemaListForStats = schemaList; |
| - Validator v = null; |
| - String[] schemas = SPACE.split(schemaList); |
| - for (int i = schemas.length - 1; i > -1; i--) { |
| - String url = schemas[i]; |
| - if ("http://s.validator.nu/html5-all.rnc".equals(url)) { |
| - System.setProperty("nu.validator.schema.rdfa-full", "1"); |
| - } |
| - if ("http://c.validator.nu/all/".equals(url) |
| - || "http://hsivonen.iki.fi/checkers/all/".equals(url)) { |
| - for (int j = 0; j < ALL_CHECKERS.length; j++) { |
| - v = combineValidatorByUrl(v, ALL_CHECKERS[j]); |
| - } |
| - } else if ("http://c.validator.nu/all-html4/".equals(url) |
| - || "http://hsivonen.iki.fi/checkers/all-html4/".equals(url)) { |
| - for (int j = 0; j < ALL_CHECKERS_HTML4.length; j++) { |
| - v = combineValidatorByUrl(v, ALL_CHECKERS_HTML4[j]); |
| - } |
| - } else { |
| - v = combineValidatorByUrl(v, url); |
| - } |
| - } |
| - if (imageCollector != null && v != null) { |
| - v = new CombineValidator(imageCollector, v); |
| - } |
| - return v; |
| - } |
| - |
| - /** |
| - * @param val |
| - * @param url |
| - * @return |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - */ |
| - private Validator combineValidatorByUrl(Validator val, String url) |
| - throws SAXException, IOException, IncorrectSchemaException { |
| - if (!"".equals(url)) { |
| - Validator v = validatorByUrl(url); |
| - if (val == null) { |
| - val = v; |
| - } else { |
| - val = new CombineValidator(v, val); |
| - } |
| - } |
| - return val; |
| - } |
| - |
| - /** |
| - * @param url |
| - * @return |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - */ |
| - private Validator validatorByUrl(String url) throws SAXException, |
| - IOException, IncorrectSchemaException { |
| - if (loadedValidatorUrls.contains(url)) { |
| - return null; |
| - } |
| - loadedValidatorUrls.add(url); |
| - if ("http://s.validator.nu/xhtml5.rnc".equals(url) |
| - || "http://s.validator.nu/html5.rnc".equals(url) |
| - || "http://s.validator.nu/html5-all.rnc".equals(url) |
| - || "http://s.validator.nu/xhtml5-all.rnc".equals(url) |
| - || "http://s.validator.nu/html5-its.rnc".equals(url) |
| - || "http://s.validator.nu/xhtml5-rdfalite.rnc".equals(url) |
| - || "http://s.validator.nu/html5-rdfalite.rnc".equals(url)) { |
| - errorHandler.setSpec(html5spec); |
| - } |
| - Schema sch = resolveSchema(url, jingPropertyMap); |
| - Validator validator = sch.createValidator(jingPropertyMap); |
| - if (validator.getContentHandler() instanceof XmlPiChecker) { |
| - lexicalHandler = (LexicalHandler) validator.getContentHandler(); |
| - } |
| - return validator; |
| - } |
| - |
| - public Schema resolveSchema(String url, PropertyMap options) |
| - throws SAXException, IOException, IncorrectSchemaException { |
| - int i = Arrays.binarySearch(preloadedSchemaUrls, url); |
| - if (i > -1) { |
| - Schema rv = preloadedSchemas[i]; |
| - if (options.contains(WrapProperty.ATTRIBUTE_OWNER)) { |
| - if (rv instanceof CheckerSchema) { |
| - errorHandler.error(new SAXParseException( |
| - "A non-schema checker cannot be used as an attribute schema.", |
| - null, url, -1, -1)); |
| - throw new IncorrectSchemaException(); |
| - } else { |
| - // ugly fall through |
| - } |
| - } else { |
| - return rv; |
| - } |
| - } |
| - |
| - externalSchema = true; |
| - |
| - TypedInputSource schemaInput = (TypedInputSource) entityResolver.resolveEntity( |
| - null, url); |
| - SchemaReader sr = null; |
| - if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) { |
| - sr = CompactSchemaReader.getInstance(); |
| - } else { |
| - sr = new AutoSchemaReader(); |
| - } |
| - Schema sch = sr.createSchema(schemaInput, options); |
| - |
| - if (Statistics.STATISTICS != null && "com.thaiopensource.validate.schematron.SchemaImpl".equals(sch.getClass().getName())) { |
| - externalSchematron = true; |
| - } |
| - |
| - return sch; |
| - } |
| - |
| - /** |
| - * @param url |
| - * @return |
| - * @throws SAXException |
| - * @throws IOException |
| - * @throws IncorrectSchemaException |
| - */ |
| - private static Schema schemaByUrl(String url, EntityResolver resolver, |
| - PropertyMap pMap) throws SAXException, IOException, |
| - IncorrectSchemaException { |
| - log4j.debug("Will load schema: " + url); |
| - TypedInputSource schemaInput; |
| - try { |
| - schemaInput = (TypedInputSource) resolver.resolveEntity( |
| - null, url); |
| - } catch (ClassCastException e) { |
| - log4j.fatal(url, e); |
| - throw e; |
| - } |
| - SchemaReader sr = null; |
| - if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) { |
| - sr = CompactSchemaReader.getInstance(); |
| - } else { |
| - sr = new AutoSchemaReader(); |
| - } |
| - Schema sch = sr.createSchema(schemaInput, pMap); |
| - return sch; |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - */ |
| - void emitTitle(boolean markupAllowed) throws SAXException { |
| - if (willValidate()) { |
| - emitter.characters(RESULTS_TITLE); |
| - emitter.characters(FOR); |
| - if (document != null && document.length() > 0) { |
| - emitter.characters(scrub(shortenDataUri(document))); |
| - } else if (request.getAttribute("nu.validator.servlet.MultipartFormDataFilter.filename") != null) { |
| - emitter.characters("uploaded file " |
| - + scrub(request.getAttribute( |
| - "nu.validator.servlet.MultipartFormDataFilter.filename").toString())); |
| - } else { |
| - emitter.characters("contents of text-input area"); |
| - } |
| - } else { |
| - emitter.characters(SERVICE_TITLE); |
| - if (markupAllowed |
| - && System.getProperty("nu.validator.servlet.service-name", |
| - "").equals("Validator.nu")) { |
| - emitter.startElement("span"); |
| - emitter.characters(LIVING_VERSION); |
| - emitter.endElement("span"); |
| - } |
| - } |
| - } |
| - |
| - protected String shortenDataUri(String uri) { |
| - if (DataUri.startsWithData(uri)) { |
| - return "data:\u2026"; |
| - } else { |
| - return uri; |
| - } |
| - } |
| - |
| - void emitForm() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("method", "get"); |
| -// attrs.addAttribute("action", request.getRequestURL().toString()); |
| - if (isSimple()) { |
| - attrs.addAttribute("class", "simple"); |
| - } |
| - // attrs.addAttribute("onsubmit", "formSubmission()"); |
| - emitter.startElement("form", attrs); |
| - emitFormContent(); |
| - emitter.endElement("form"); |
| - } |
| - |
| - protected boolean isSimple() { |
| - return false; |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - */ |
| - protected void emitFormContent() throws SAXException { |
| - FormEmitter.emit(contentHandler, this); |
| - } |
| - |
| - void emitSchemaField() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("name", "schema"); |
| - attrs.addAttribute("id", "schema"); |
| - // attrs.addAttribute("onchange", "schemaChanged();"); |
| - attrs.addAttribute( |
| - "pattern", |
| - "(?:(?:(?:https?://\\S+)|(?:data:\\S+))(?:\\s+(?:(?:https?://\\S+)|(?:data:\\S+)))*)?"); |
| - attrs.addAttribute("title", |
| - "Space-separated list of schema IRIs. (Leave blank to let the service guess.)"); |
| - if (schemaUrls != null) { |
| - attrs.addAttribute("value", scrub(schemaUrls)); |
| - } |
| - emitter.startElement("input", attrs); |
| - emitter.endElement("input"); |
| - } |
| - |
| - void emitDocField() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("type", "url"); |
| - attrs.addAttribute("name", "doc"); |
| - attrs.addAttribute("id", "doc"); |
| - attrs.addAttribute("pattern", "(?:(?:https?://.+)|(?:data:.+))?"); |
| - attrs.addAttribute("title", |
| - "Absolute IRI (http, https or data only) of the document to be checked."); |
| - if (document != null) { |
| - attrs.addAttribute("value", scrub(document)); |
| - } |
| - Object att = request.getAttribute("nu.validator.servlet.MultipartFormDataFilter.type"); |
| - if (att != null) { |
| - attrs.addAttribute("class", att.toString()); |
| - } |
| - emitter.startElement("input", attrs); |
| - emitter.endElement("input"); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitSchemaDuration() throws SAXException { |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitDocDuration() throws SAXException { |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitTotalDuration() throws SAXException { |
| - emitter.characters("" + (System.currentTimeMillis() - start)); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitPresetOptions() throws SAXException { |
| - for (int i = 0; i < presetUrls.length; i++) { |
| - emitter.option(presetLabels[i], presetUrls[i], false); |
| - } |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitParserOptions() throws SAXException { |
| - emitter.option("Automatically from Content-Type", "", |
| - (parser == ParserMode.AUTO)); |
| - emitter.option("XML; don\u2019t load external entities", "xml", |
| - (parser == ParserMode.XML_NO_EXTERNAL_ENTITIES)); |
| - emitter.option("XML; load external entities", "xmldtd", |
| - (parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION)); |
| - emitter.option("HTML; flavor from doctype", "html", |
| - (parser == ParserMode.HTML_AUTO)); |
| - emitter.option("HTML5", "html5", (parser == ParserMode.HTML)); |
| - emitter.option("HTML 4.01 Strict", "html4", |
| - (parser == ParserMode.HTML401_STRICT)); |
| - emitter.option("HTML 4.01 Transitional", "html4tr", |
| - (parser == ParserMode.HTML401_TRANSITIONAL)); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitProfileOptions() throws SAXException { |
| - profile = request.getParameter("profile"); |
| - |
| - emitter.option("Permissive: only what the spec requires", |
| - "", ("".equals(profile))); |
| - emitter.option("Pedagogical: suitable for teaching purposes", |
| - "pedagogical", ("pedagogical".equals(profile))); |
| - emitter.option("Polyglot: works both as HTML and as XML", |
| - "polyglot", ("polyglot".equals(profile))); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitLaxTypeField() throws SAXException { |
| - emitter.checkbox("laxtype", "yes", laxType); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitShowSourceField() throws SAXException { |
| - emitter.checkbox("showsource", "yes", showSource); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitShowOutlineField() throws SAXException { |
| - emitter.checkbox("showoutline", "yes", showOutline); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * |
| - */ |
| - void emitShowImageReportField() throws SAXException { |
| - emitter.checkbox("showimagereport", "yes", imageCollector != null); |
| - } |
| - |
| - void rootNamespace(String namespace, Locator locator) throws SAXException { |
| - if (validator == null) { |
| - int index = -1; |
| - for (int i = 0; i < presetNamespaces.length; i++) { |
| - if (namespace.equals(presetNamespaces[i])) { |
| - index = i; |
| - break; |
| - } |
| - } |
| - if (index == -1) { |
| - String message = "Cannot find preset schema for namespace: \u201C" |
| - + namespace + "\u201D."; |
| - SAXException se = new SAXException(message); |
| - errorHandler.schemaError(se); |
| - throw se; |
| - } |
| - String label = presetLabels[index]; |
| - String urls = presetUrls[index]; |
| - errorHandler.info("Using the preset for " + label |
| - + " based on the root namespace."); |
| - try { |
| - validator = validatorByUrls(urls); |
| - } catch (IOException ioe) { |
| - // At this point the schema comes from memory. |
| - throw new RuntimeException(ioe); |
| - } catch (IncorrectSchemaException e) { |
| - // At this point the schema comes from memory. |
| - throw new RuntimeException(e); |
| - } |
| - if (bufferingRootNamespaceSniffer == null) { |
| - throw new RuntimeException( |
| - "Bug! bufferingRootNamespaceSniffer was null."); |
| - } |
| - bufferingRootNamespaceSniffer.setContentHandler(validator.getContentHandler()); |
| - } |
| - |
| - if (!rootNamespaceSeen) { |
| - rootNamespaceSeen = true; |
| - if (contentType != null) { |
| - int i; |
| - if ((i = Arrays.binarySearch(KNOWN_CONTENT_TYPES, contentType)) > -1) { |
| - if (!NAMESPACES_FOR_KNOWN_CONTENT_TYPES[i].equals(namespace)) { |
| - String message = "".equals(namespace) ? "\u201C" |
| - + contentType |
| - + "\u201D is not an appropriate Content-Type for a document whose root element is not in a namespace." |
| - : "\u201C" |
| - + contentType |
| - + "\u201D is not an appropriate Content-Type for a document whose root namespace is \u201C" |
| - + namespace + "\u201D."; |
| - SAXParseException spe = new SAXParseException(message, |
| - locator); |
| - errorHandler.warning(spe); |
| - } |
| - } |
| - } |
| - } |
| - } |
| - |
| - public void documentMode(DocumentMode mode, String publicIdentifier, |
| - String systemIdentifier, boolean html4SpecificAdditionalErrorChecks) |
| - throws SAXException { |
| - if (validator == null) { |
| - try { |
| - if ("yes".equals(request.getParameter("sniffdoctype"))) { |
| - if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicIdentifier)) { |
| - errorHandler.info("XHTML 1.0 Transitional doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for " |
| - + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| - : "")); |
| - validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| - } else if ("-//W3C//DTD XHTML 1.0 Strict//EN".equals(publicIdentifier)) { |
| - errorHandler.info("XHTML 1.0 Strict doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for " |
| - + getPresetLabel(XHTML1STRICT_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| - : "")); |
| - validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| - } else if ("-//W3C//DTD HTML 4.01 Transitional//EN".equals(publicIdentifier)) { |
| - errorHandler.info("HTML 4.01 Transitional doctype seen. Using the schema for " |
| - + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? "" |
| - : " HTML4-specific tokenization errors are not enabled.")); |
| - validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| - } else if ("-//W3C//DTD HTML 4.01//EN".equals(publicIdentifier)) { |
| - errorHandler.info("HTML 4.01 Strict doctype seen. Using the schema for " |
| - + getPresetLabel(XHTML1STRICT_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? "" |
| - : " HTML4-specific tokenization errors are not enabled.")); |
| - validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| - } else if ("-//W3C//DTD HTML 4.0 Transitional//EN".equals(publicIdentifier)) { |
| - errorHandler.info("Legacy HTML 4.0 Transitional doctype seen. Please consider using HTML 4.01 Transitional instead. Proceeding anyway for your convenience with the schema for " |
| - + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? "" |
| - : " HTML4-specific tokenization errors are not enabled.")); |
| - validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA); |
| - } else if ("-//W3C//DTD HTML 4.0//EN".equals(publicIdentifier)) { |
| - errorHandler.info("Legacy HTML 4.0 Strict doctype seen. Please consider using HTML 4.01 instead. Proceeding anyway for your convenience with the schema for " |
| - + getPresetLabel(XHTML1STRICT_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? "" |
| - : " HTML4-specific tokenization errors are not enabled.")); |
| - validator = validatorByDoctype(XHTML1STRICT_SCHEMA); |
| - } |
| - } else { |
| - errorHandler.info("Using the schema for " |
| - + getPresetLabel(HTML5_SCHEMA) |
| - + "." |
| - + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled." |
| - : "")); |
| - validator = validatorByDoctype(HTML5_SCHEMA); |
| - } |
| - } catch (IOException ioe) { |
| - // At this point the schema comes from memory. |
| - throw new RuntimeException(ioe); |
| - } catch (IncorrectSchemaException e) { |
| - // At this point the schema comes from memory. |
| - throw new RuntimeException(e); |
| - } |
| - ContentHandler ch = validator.getContentHandler(); |
| - ch.setDocumentLocator(htmlParser.getDocumentLocator()); |
| - ch.startDocument(); |
| - reader.setContentHandler(ch); |
| - } else { |
| - if (html4SpecificAdditionalErrorChecks) { |
| - errorHandler.info("HTML4-specific tokenization errors are enabled."); |
| - } |
| - } |
| - } |
| - |
| - private String getPresetLabel(int schemaId) { |
| - for (int i = 0; i < presetDoctypes.length; i++) { |
| - if (presetDoctypes[i] == schemaId) { |
| - return presetLabels[i]; |
| - } |
| - } |
| - return "unknown"; |
| - } |
| - |
| - /** |
| - * @param acceptAllKnownXmlTypes |
| - * @see nu.validator.xml.ContentTypeParser#setAcceptAllKnownXmlTypes(boolean) |
| - */ |
| - protected void setAcceptAllKnownXmlTypes(boolean acceptAllKnownXmlTypes) { |
| - contentTypeParser.setAcceptAllKnownXmlTypes(acceptAllKnownXmlTypes); |
| - dataRes.setAcceptAllKnownXmlTypes(acceptAllKnownXmlTypes); |
| - httpRes.setAcceptAllKnownXmlTypes(acceptAllKnownXmlTypes); |
| - } |
| - |
| - /** |
| - * @param allowGenericXml |
| - * @see nu.validator.xml.ContentTypeParser#setAllowGenericXml(boolean) |
| - */ |
| - protected void setAllowGenericXml(boolean allowGenericXml) { |
| - contentTypeParser.setAllowGenericXml(allowGenericXml); |
| - httpRes.setAllowGenericXml(allowGenericXml); |
| - dataRes.setAllowGenericXml(allowGenericXml); |
| - } |
| - |
| - /** |
| - * @param allowHtml |
| - * @see nu.validator.xml.ContentTypeParser#setAllowHtml(boolean) |
| - */ |
| - protected void setAllowHtml(boolean allowHtml) { |
| - contentTypeParser.setAllowHtml(allowHtml); |
| - httpRes.setAllowHtml(allowHtml); |
| - dataRes.setAllowHtml(allowHtml); |
| - } |
| - |
| - /** |
| - * @param allowRnc |
| - * @see nu.validator.xml.ContentTypeParser#setAllowRnc(boolean) |
| - */ |
| - protected void setAllowRnc(boolean allowRnc) { |
| - contentTypeParser.setAllowRnc(allowRnc); |
| - httpRes.setAllowRnc(allowRnc); |
| - dataRes.setAllowRnc(allowRnc); |
| - entityResolver.setAllowRnc(allowRnc); |
| - } |
| - |
| - /** |
| - * @param allowXhtml |
| - * @see nu.validator.xml.ContentTypeParser#setAllowXhtml(boolean) |
| - */ |
| - protected void setAllowXhtml(boolean allowXhtml) { |
| - contentTypeParser.setAllowXhtml(allowXhtml); |
| - httpRes.setAllowXhtml(allowXhtml); |
| - dataRes.setAllowXhtml(allowXhtml); |
| - } |
| - |
| - /** |
| - * @throws SAXException |
| - * @throws IOException |
| - */ |
| - protected void loadDocumentInput() throws SAXException, IOException { |
| - if (methodIsGet) { |
| - documentInput = (TypedInputSource) entityResolver.resolveEntity( |
| - null, document); |
| - errorHandler.setLoggingOk(true); |
| - } else { // POST |
| - long len = request.getContentLength(); |
| - if (len > SIZE_LIMIT) { |
| - throw new StreamBoundException("Resource size exceeds limit."); |
| - } |
| - documentInput = contentTypeParser.buildTypedInputSource(document, |
| - null, postContentType); |
| - documentInput.setByteStream(len < 0 ? new BoundedInputStream( |
| - request.getInputStream(), SIZE_LIMIT, document) |
| - : request.getInputStream()); |
| - documentInput.setSystemId(request.getHeader("Content-Location")); |
| - } |
| - if (imageCollector != null) { |
| - baseUriTracker = new BaseUriTracker(documentInput.getSystemId(), |
| - documentInput.getLanguage()); |
| - imageCollector.initializeContext(baseUriTracker); |
| - } |
| - } |
| - |
| - void emitStyle() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("href", STYLE_SHEET); |
| - attrs.addAttribute("rel", "stylesheet"); |
| - emitter.startElement("link", attrs); |
| - emitter.endElement("link"); |
| - } |
| - |
| - void emitIcon() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("href", ICON); |
| - attrs.addAttribute("rel", "icon"); |
| - emitter.startElement("link", attrs); |
| - emitter.endElement("link"); |
| - } |
| - |
| - void emitScript() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("src", SCRIPT); |
| - emitter.startElement("script", attrs); |
| - emitter.endElement("script"); |
| - } |
| - |
| - void emitAbout() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("href", ABOUT_PAGE); |
| - emitter.startElement("a", attrs); |
| - emitter.characters(ABOUT_THIS_SERVICE); |
| - emitter.endElement("a"); |
| - } |
| - |
| - void emitVersion() throws SAXException { |
| - emitter.characters(VERSION); |
| - } |
| - |
| - void emitUserAgentInput() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("name", "useragent"); |
| - attrs.addAttribute("list", "useragents"); |
| - attrs.addAttribute("value", userAgent); |
| - emitter.startElement("input", attrs); |
| - emitter.endElement("input"); |
| - } |
| - |
| - void emitOtherFacetLink() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("href", HTML5_FACET); |
| - emitter.startElement("a", attrs); |
| - emitter.characters(SIMPLE_UI); |
| - emitter.endElement("a"); |
| - } |
| - |
| - void emitNsfilterField() throws SAXException { |
| - attrs.clear(); |
| - attrs.addAttribute("name", "nsfilter"); |
| - attrs.addAttribute("id", "nsfilter"); |
| - attrs.addAttribute("pattern", "(?:.+:.+(?:\\s+.+:.+)*)?"); |
| - attrs.addAttribute("title", |
| - "Space-separated namespace URIs for vocabularies to be filtered out."); |
| - if (!filteredNamespaces.isEmpty()) { |
| - StringBuilder sb = new StringBuilder(); |
| - boolean first = true; |
| - for (String ns : filteredNamespaces) { |
| - if (!first) { |
| - sb.append(' '); |
| - } |
| - sb.append(ns); |
| - first = false; |
| - } |
| - attrs.addAttribute("value", scrub(sb)); |
| - } |
| - emitter.startElement("input", attrs); |
| - emitter.endElement("input"); |
| - } |
| - |
| - void maybeEmitNsfilterField() throws SAXException { |
| - NsFilterEmitter.emit(contentHandler, this); |
| - } |
| - |
| - void emitCharsetOptions() throws SAXException { |
| - boolean found = false; |
| - for (int i = 0; i < CHARSETS.length; i++) { |
| - String charset = CHARSETS[i]; |
| - boolean selected = charset.equalsIgnoreCase(charsetOverride); // XXX |
| - // use |
| - // ASCII-caseinsensitivity |
| - emitter.option(CHARSET_DESCRIPTIONS[i], charset, selected); |
| - if (selected) { |
| - found = true; |
| - } |
| - } |
| - if (!found && charsetOverride != null) { |
| - emitter.option(charsetOverride, charsetOverride, true); |
| - } |
| - } |
| - |
| - void maybeEmitCharsetField() throws SAXException { |
| - CharsetEmitter.emit(contentHandler, this); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/VerifierServletXMLReaderCreator.java b/src/nu/validator/servlet/VerifierServletXMLReaderCreator.java |
| deleted file mode 100644 |
| index 9fb99e1..0000000 |
| --- a/src/nu/validator/servlet/VerifierServletXMLReaderCreator.java |
| +++ /dev/null |
| @@ -1,69 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005, 2006 Henri Sivonen |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import nu.validator.gnu.xml.aelfred2.SAXDriver; |
| - |
| -import org.xml.sax.EntityResolver; |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.XMLReader; |
| - |
| -import com.thaiopensource.xml.sax.XMLReaderCreator; |
| - |
| - |
| -/** |
| - * @version $Id$ |
| - * @author hsivonen |
| - */ |
| -public class VerifierServletXMLReaderCreator implements XMLReaderCreator { |
| - |
| - private ErrorHandler errorHandler; |
| - |
| - private EntityResolver entityResolver; |
| - |
| - /** |
| - * @param errorHandler |
| - * @param entityResolver |
| - */ |
| - public VerifierServletXMLReaderCreator(ErrorHandler errorHandler, |
| - EntityResolver entityResolver) { |
| - this.errorHandler = errorHandler; |
| - this.entityResolver = entityResolver; |
| - } |
| - |
| - /** |
| - * @see com.thaiopensource.xml.sax.XMLReaderCreator#createXMLReader() |
| - */ |
| - public XMLReader createXMLReader() throws SAXException { |
| - XMLReader r = new SAXDriver(); |
| - r.setFeature("http://xml.org/sax/features/external-general-entities", |
| - true); |
| - r.setFeature("http://xml.org/sax/features/external-parameter-entities", |
| - true); |
| - r.setEntityResolver(this.entityResolver); |
| - r.setErrorHandler(this.errorHandler); |
| - return r; |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/servlet/XhtmlOutlineEmitter.java b/src/nu/validator/servlet/XhtmlOutlineEmitter.java |
| deleted file mode 100644 |
| index e34feef..0000000 |
| --- a/src/nu/validator/servlet/XhtmlOutlineEmitter.java |
| +++ /dev/null |
| @@ -1,101 +0,0 @@ |
| -/* |
| - * Copyright (c) 2012 Vadim Zaslawski, Ontos AG |
| - * Copyright (c) 2012 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.servlet; |
| - |
| -import java.io.IOException; |
| -import java.util.Deque; |
| - |
| -import nu.validator.servlet.OutlineBuildingXMLReaderWrapper.Section; |
| -import nu.validator.xml.AttributesImpl; |
| -import nu.validator.xml.XhtmlSaxEmitter; |
| - |
| -import org.xml.sax.ContentHandler; |
| -import org.xml.sax.SAXException; |
| - |
| -public class XhtmlOutlineEmitter { |
| - |
| - private static final char[] OUTLINE = "Outline".toCharArray(); |
| - |
| - private final Deque<Section> outline; |
| - |
| - private final XhtmlSaxEmitter emitter; |
| - |
| - private final AttributesImpl attrs = new AttributesImpl(); |
| - |
| - public XhtmlOutlineEmitter(final ContentHandler contentHandler, |
| - final Deque<Section> outline) { |
| - this.emitter = new XhtmlSaxEmitter(contentHandler); |
| - this.outline = outline; |
| - } |
| - |
| - public void emit() throws SAXException { |
| - if (outline != null) { |
| - attrs.clear(); |
| - attrs.addAttribute("id", "outline"); |
| - emitter.startElement("section", attrs); |
| - emitter.startElement("h2"); |
| - emitter.characters(OUTLINE); |
| - emitter.endElement("h2"); |
| - try { |
| - emitOutline(outline, 0); |
| - } catch (IOException e) { |
| - throw new RuntimeException(e); |
| - } |
| - emitter.endElement("section"); |
| - } |
| - } |
| - |
| - protected void emitOutline(Deque<Section> outline, int currentDepth) |
| - throws IOException, SAXException { |
| - emitter.startElement("ol"); |
| - for (Section section : outline) { |
| - emitter.startElement("li"); |
| - StringBuilder headingText = section.getHeadingTextBuilder(); |
| - if (headingText.length() > 0) { |
| - emitter.startElementWithClass("span", "heading"); |
| - emitter.characters(headingText.toString().toCharArray()); |
| - emitter.endElement("span"); |
| - } else if (section.hasEmptyHeading()) { |
| - emitter.characters(("[" + section.getElementName() + " element with empty heading]").toCharArray()); |
| - } else if ("h1".equals(section.getElementName()) |
| - || "h2".equals(section.getElementName()) |
| - || "h3".equals(section.getElementName()) |
| - || "h4".equals(section.getElementName()) |
| - || "h5".equals(section.getElementName()) |
| - || "h6".equals(section.getElementName())) { |
| - emitter.characters(("[section implied by empty " |
| - + section.getElementName() + " element]").toCharArray()); |
| - } else { |
| - emitter.characters(("[" + section.getElementName() + " element with no heading]").toCharArray()); |
| - } |
| - Deque<Section> sections = section.sections; |
| - if (!sections.isEmpty()) { |
| - emitOutline(sections, currentDepth + 1); |
| - } |
| - emitter.endElement("li"); |
| - } |
| - emitter.endElement("ol"); |
| - } |
| - |
| -} |
| diff --git a/src/nu/validator/xml/BaseUriTracker.java b/src/nu/validator/xml/BaseUriTracker.java |
| index 8a4c91b..afea01c 100644 |
| --- a/src/nu/validator/xml/BaseUriTracker.java |
| +++ b/src/nu/validator/xml/BaseUriTracker.java |
| @@ -32,17 +32,17 @@ import org.xml.sax.ContentHandler; |
| import org.xml.sax.Locator; |
| import org.xml.sax.SAXException; |
| |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.GalimatiasParseException; |
| +import com.hp.hpl.jena.iri.IRI; |
| +import com.hp.hpl.jena.iri.IRIFactory; |
| |
| public class BaseUriTracker implements ContentHandler, UriLangContext { |
| - |
| + |
| private enum Direction { |
| LTR, RTL, INHERIT |
| } |
| |
| private class Node { |
| - public URL currentAbsolute; // not null |
| + public URI currentAbsolute; // not null |
| |
| public String originalRelative; // null if no xml:base |
| |
| @@ -56,7 +56,7 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| * @param currentAbsolute |
| * @param originalRelative |
| */ |
| - public Node(URL currentAbsolute, String originalRelative, String lang, |
| + public Node(URI currentAbsolute, String originalRelative, String lang, |
| boolean langSpecified, boolean rtl) { |
| this.currentAbsolute = currentAbsolute; |
| this.originalRelative = originalRelative; |
| @@ -66,6 +66,8 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| } |
| } |
| |
| + private final IRIFactory iriFactory; |
| + |
| private LinkedList<Node> stack = new LinkedList<Node>(); |
| |
| private boolean baseSeen = false; |
| @@ -110,13 +112,26 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| |
| public BaseUriTracker(String systemId, String contentLanguage) { |
| |
| - URL url = null; |
| + this.iriFactory = new IRIFactory(); |
| + this.iriFactory.shouldViolation(false, false); |
| + this.iriFactory.securityViolation(false, false); |
| + this.iriFactory.dnsViolation(false, false); |
| + this.iriFactory.mintingViolation(false, false); |
| + this.iriFactory.useSpecificationIRI(false); |
| + this.iriFactory.useSchemeSpecificRules("http", false); |
| + this.iriFactory.useSchemeSpecificRules("https", false); |
| + this.iriFactory.useSchemeSpecificRules("ftp", false); |
| + this.iriFactory.useSchemeSpecificRules("data", false); |
| + |
| + URI uri = null; |
| try { |
| - url = URL.parse(systemId); |
| - } catch (GalimatiasParseException e) { |
| - url = null; |
| + IRI iri = iriFactory.construct(systemId); |
| + uri = new URI(iri.toASCIIString()); |
| + if (!uri.isAbsolute()) { |
| + uri = null; |
| + } |
| } catch (Exception e) { |
| - url = null; |
| + uri = null; |
| } |
| |
| String lang = ""; |
| @@ -131,8 +146,8 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| } catch (DatatypeException e) { |
| } |
| } |
| - stack.add(new Node(url, null, lang, langSpecified, false)); |
| - stack.add(new Node(url, null, lang, false, false)); // base/content-language placeholder |
| + stack.add(new Node(uri, null, lang, langSpecified, false)); |
| + stack.add(new Node(uri, null, lang, false, false)); // base/content-language placeholder |
| } |
| |
| private Node peek() { |
| @@ -158,7 +173,7 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| } |
| |
| Node curr = peek(); |
| - URL base = curr.currentAbsolute; |
| + URI base = curr.currentAbsolute; |
| if (!langSpecified) { |
| lang = curr.lang; |
| } |
| @@ -178,19 +193,19 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| if (relative == null) { |
| stack.addLast(new Node(base, null, lang, langSpecified, rtl)); |
| } else { |
| - URL newBase; |
| + URI newBase; |
| String ascii = null; |
| try { |
| + IRI relIri = iriFactory.construct(relative); |
| + ascii = relIri.toASCIIString(); |
| if (base != null) { |
| - try { |
| - newBase = base.resolve(relative); |
| - } catch (GalimatiasParseException e) { |
| + newBase = base.resolve(ascii); |
| + if (!newBase.isAbsolute()) { |
| newBase = base; |
| } |
| } else { |
| - try { |
| - newBase = URL.parse((new URI(ascii)).toString()); |
| - } catch (GalimatiasParseException e) { |
| + newBase = new URI(ascii); |
| + if (!newBase.isAbsolute()) { |
| newBase = null; |
| } |
| } |
| @@ -283,22 +298,23 @@ public class BaseUriTracker implements ContentHandler, UriLangContext { |
| */ |
| public String toAbsoluteUriWithCurrentBase(String uri) { |
| try { |
| - URL relUrl = URL.parse(uri); |
| + IRI relIri = iriFactory.construct(uri); |
| String ascii; |
| - ascii = relUrl.toString(); |
| + ascii = relIri.toASCIIString(); |
| |
| - URL base = stack.getLast().currentAbsolute; |
| - URL rv; |
| - try { |
| - if (base == null) { |
| - rv = URL.parse(ascii); |
| - } else { |
| - rv = base.resolve(ascii); |
| - } |
| - } catch (GalimatiasParseException e) { |
| + URI base = stack.getLast().currentAbsolute; |
| + URI rv; |
| + if (base == null) { |
| + rv = new URI(ascii); |
| + } else { |
| + rv = base.resolve(ascii); |
| + |
| + } |
| + if (rv.isAbsolute()) { |
| + return rv.toASCIIString(); |
| + } else { |
| return null; |
| } |
| - return rv.toString(); |
| } catch (Exception e) { |
| return null; |
| } |
| diff --git a/src/nu/validator/xml/DataUriEntityResolver.java b/src/nu/validator/xml/DataUriEntityResolver.java |
| index eaacb82..2eac45a 100644 |
| --- a/src/nu/validator/xml/DataUriEntityResolver.java |
| +++ b/src/nu/validator/xml/DataUriEntityResolver.java |
| @@ -31,8 +31,11 @@ import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.GalimatiasParseException; |
| +//import io.mola.galimatias.URL; |
| +//import io.mola.galimatias.GalimatiasParseException; |
| +import com.hp.hpl.jena.iri.IRI; |
| +import com.hp.hpl.jena.iri.IRIException; |
| +import com.hp.hpl.jena.iri.IRIFactory; |
| |
| public class DataUriEntityResolver implements EntityResolver { |
| |
| @@ -51,6 +54,8 @@ public class DataUriEntityResolver implements EntityResolver { |
| private boolean acceptAllKnownXmlTypes = false; |
| |
| private boolean allowGenericXml = true; |
| + |
| + private final IRIFactory iriFactory; |
| |
| private final ContentTypeParser contentTypeParser; |
| |
| @@ -61,6 +66,9 @@ public class DataUriEntityResolver implements EntityResolver { |
| ErrorHandler errorHandler) { |
| this.laxContentType = laxContentType; |
| this.errorHandler = errorHandler; |
| + this.iriFactory = new IRIFactory(); |
| + this.iriFactory.useSpecificationXMLSystemID(true); |
| + this.iriFactory.useSchemeSpecificRules("data", true); |
| this.contentTypeParser = new ContentTypeParser(errorHandler, |
| laxContentType, this.allowRnc, this.allowHtml, this.allowXhtml, |
| this.acceptAllKnownXmlTypes, this.allowGenericXml); |
| @@ -74,10 +82,10 @@ public class DataUriEntityResolver implements EntityResolver { |
| public InputSource resolveEntity(String publicId, String systemId) |
| throws SAXException, IOException { |
| if (DataUri.startsWithData(systemId)) { |
| - URL url; |
| + IRI iri; |
| try { |
| - url = URL.parse(systemId); |
| - } catch (GalimatiasParseException e) { |
| + iri = iriFactory.construct(systemId); |
| + } catch (IRIException e) { |
| IOException ioe = (IOException) new IOException(e.getMessage()).initCause(e); |
| SAXParseException spe = new SAXParseException(e.getMessage(), |
| publicId, systemId, -1, -1, ioe); |
| @@ -86,7 +94,7 @@ public class DataUriEntityResolver implements EntityResolver { |
| } |
| throw spe; |
| } |
| - systemId = url.toString(); |
| + systemId = iri.toASCIIString(); |
| DataUri du = new DataUri(systemId); |
| TypedInputSource is = contentTypeParser.buildTypedInputSource(systemId, publicId, |
| du.getContentType()); |
| diff --git a/src/nu/validator/xml/PrudentHttpEntityResolver.java b/src/nu/validator/xml/PrudentHttpEntityResolver.java |
| deleted file mode 100644 |
| index 1a172f1..0000000 |
| --- a/src/nu/validator/xml/PrudentHttpEntityResolver.java |
| +++ /dev/null |
| @@ -1,548 +0,0 @@ |
| -/* |
| - * Copyright (c) 2005 Henri Sivonen |
| - * Copyright (c) 2007-2015 Mozilla Foundation |
| - * |
| - * Permission is hereby granted, free of charge, to any person obtaining a |
| - * copy of this software and associated documentation files (the "Software"), |
| - * to deal in the Software without restriction, including without limitation |
| - * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| - * and/or sell copies of the Software, and to permit persons to whom the |
| - * Software is furnished to do so, subject to the following conditions: |
| - * |
| - * The above copyright notice and this permission notice shall be included in |
| - * all copies or substantial portions of the Software. |
| - * |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| - * DEALINGS IN THE SOFTWARE. |
| - */ |
| - |
| -package nu.validator.xml; |
| - |
| -import java.io.IOException; |
| -import java.io.InputStream; |
| -import java.security.KeyManagementException; |
| -import java.security.KeyStoreException; |
| -import java.security.NoSuchAlgorithmException; |
| -import java.security.cert.CertificateException; |
| -import java.security.cert.X509Certificate; |
| -import java.util.zip.GZIPInputStream; |
| - |
| -import javax.net.ssl.HostnameVerifier; |
| -import javax.net.ssl.SSLContext; |
| - |
| -import nu.validator.io.BoundedInputStream; |
| -import nu.validator.io.ObservableInputStream; |
| -import nu.validator.io.StreamBoundException; |
| -import nu.validator.io.StreamObserver; |
| -import nu.validator.io.SystemIdIOException; |
| - |
| -import org.apache.http.Header; |
| -import org.apache.http.HttpEntity; |
| -import org.apache.http.HttpResponse; |
| -import org.apache.http.client.HttpClient; |
| -import org.apache.http.client.config.CookieSpecs; |
| -import org.apache.http.client.config.RequestConfig; |
| -import org.apache.http.client.methods.HttpGet; |
| -import org.apache.http.config.Registry; |
| -import org.apache.http.config.RegistryBuilder; |
| -import org.apache.http.conn.socket.ConnectionSocketFactory; |
| -import org.apache.http.conn.socket.PlainConnectionSocketFactory; |
| -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
| -import org.apache.http.conn.ssl.SSLContextBuilder; |
| -import org.apache.http.conn.ssl.TrustStrategy; |
| -import org.apache.http.impl.client.HttpClientBuilder; |
| -import org.apache.http.impl.client.HttpClients; |
| -import org.apache.http.impl.client.LaxRedirectStrategy; |
| -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
| -import org.apache.log4j.Logger; |
| - |
| -import org.xml.sax.EntityResolver; |
| -import org.xml.sax.ErrorHandler; |
| -import org.xml.sax.InputSource; |
| -import org.xml.sax.SAXException; |
| -import org.xml.sax.SAXParseException; |
| - |
| -import io.mola.galimatias.URL; |
| -import io.mola.galimatias.GalimatiasParseException; |
| - |
| -/** |
| - * @version $Id: PrudentHttpEntityResolver.java,v 1.1 2005/01/08 08:11:26 |
| - * hsivonen Exp $ |
| - * @author hsivonen |
| - */ |
| -@SuppressWarnings("deprecation") public class PrudentHttpEntityResolver |
| - implements EntityResolver { |
| - |
| - private static final Logger log4j = Logger.getLogger(PrudentHttpEntityResolver.class); |
| - |
| - private static HttpClient client; |
| - |
| - private static int maxRequests; |
| - |
| - private long sizeLimit; |
| - |
| - private final ErrorHandler errorHandler; |
| - |
| - private int requestsLeft; |
| - |
| - private boolean allowRnc = false; |
| - |
| - private boolean allowHtml = false; |
| - |
| - private boolean allowXhtml = false; |
| - |
| - private boolean acceptAllKnownXmlTypes = false; |
| - |
| - private boolean allowGenericXml = true; |
| - |
| - private final ContentTypeParser contentTypeParser; |
| - |
| - private String userAgent; |
| - |
| - /** |
| - * Sets the timeouts of the HTTP client. |
| - * |
| - * @param connectionTimeout |
| - * timeout until connection established in milliseconds. Zero |
| - * means no timeout. |
| - * @param socketTimeout |
| - * timeout for waiting for data in milliseconds. Zero means no |
| - * timeout. |
| - * @param maxRequests |
| - * maximum number of connections to a particuar host |
| - */ |
| - public static void setParams(int connectionTimeout, int socketTimeout, |
| - int maxRequests) { |
| - PrudentHttpEntityResolver.maxRequests = maxRequests; |
| - PoolingHttpClientConnectionManager phcConnMgr; |
| - Registry<ConnectionSocketFactory> registry = // |
| - RegistryBuilder.<ConnectionSocketFactory> create() // |
| - .register("http", PlainConnectionSocketFactory.getSocketFactory()) // |
| - .register("https", SSLConnectionSocketFactory.getSocketFactory()) // |
| - .build(); |
| - HttpClientBuilder builder = HttpClients.custom(); |
| - builder.setRedirectStrategy(new LaxRedirectStrategy()); |
| - builder.setMaxConnPerRoute(maxRequests); |
| - builder.setMaxConnTotal(200); |
| - if ("true".equals(System.getProperty( |
| - "nu.validator.xml.promiscuous-ssl", "false"))) { // |
| - try { |
| - SSLContext promiscuousSSLContext = new SSLContextBuilder() // |
| - .loadTrustMaterial(null, new TrustStrategy() { |
| - public boolean isTrusted(X509Certificate[] arg0, String arg1) |
| - throws CertificateException { |
| - return true; |
| - } |
| - }).build(); |
| - builder.setSslcontext(promiscuousSSLContext); |
| - HostnameVerifier verifier = // |
| - SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; |
| - SSLConnectionSocketFactory promiscuousSSLConnSocketFactory = // |
| - new SSLConnectionSocketFactory(promiscuousSSLContext, verifier); |
| - registry = RegistryBuilder.<ConnectionSocketFactory> create() // |
| - .register("https", promiscuousSSLConnSocketFactory) // |
| - .register("http", |
| - PlainConnectionSocketFactory.getSocketFactory()) // |
| - .build(); |
| - } catch (KeyManagementException e) { |
| - e.printStackTrace(); |
| - } catch (NumberFormatException e) { |
| - e.printStackTrace(); |
| - } catch (NoSuchAlgorithmException e) { |
| - e.printStackTrace(); |
| - } catch (KeyStoreException e) { |
| - e.printStackTrace(); |
| - } |
| - } |
| - phcConnMgr = new PoolingHttpClientConnectionManager(registry); |
| - phcConnMgr.setDefaultMaxPerRoute(maxRequests); |
| - phcConnMgr.setMaxTotal(200); |
| - builder.setConnectionManager(phcConnMgr); |
| - RequestConfig.Builder config = RequestConfig.custom(); |
| - config.setCircularRedirectsAllowed(true); |
| - config.setMaxRedirects(20); // Gecko default |
| - config.setConnectTimeout(connectionTimeout); |
| - config.setCookieSpec(CookieSpecs.BEST_MATCH); |
| - config.setSocketTimeout(socketTimeout); |
| - client = builder.setDefaultRequestConfig(config.build()).build(); |
| - } |
| - |
| - public void setUserAgent(String ua) { |
| - userAgent = ua; |
| - } |
| - |
| - /** |
| - * @param sizeLimit |
| - * @param laxContentType |
| - * @param errorHandler |
| - */ |
| - public PrudentHttpEntityResolver(long sizeLimit, boolean laxContentType, |
| - ErrorHandler errorHandler) { |
| - this.sizeLimit = sizeLimit; |
| - this.requestsLeft = maxRequests; |
| - this.errorHandler = errorHandler; |
| - this.contentTypeParser = new ContentTypeParser(errorHandler, |
| - laxContentType, this.allowRnc, this.allowHtml, this.allowXhtml, |
| - this.acceptAllKnownXmlTypes, this.allowGenericXml); |
| - } |
| - |
| - /** |
| - * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, |
| - * java.lang.String) |
| - */ |
| - public InputSource resolveEntity(String publicId, String systemId) |
| - throws SAXException, IOException { |
| - if (requestsLeft > -1) { |
| - if (requestsLeft == 0) { |
| - throw new IOException( |
| - "Number of permitted HTTP requests exceeded."); |
| - } else { |
| - requestsLeft--; |
| - } |
| - } |
| - HttpGet m = null; |
| - try { |
| - URL url; |
| - try { |
| - url = URL.parse(systemId); |
| - } catch (GalimatiasParseException e) { |
| - IOException ioe = (IOException) new IOException(e.getMessage()).initCause(e); |
| - SAXParseException spe = new SAXParseException(e.getMessage(), |
| - publicId, systemId, -1, -1, ioe); |
| - if (errorHandler != null) { |
| - errorHandler.fatalError(spe); |
| - } |
| - throw spe; |
| - } |
| - String scheme = url.scheme(); |
| - if (!("http".equals(scheme) || "https".equals(scheme))) { |
| - String msg = "Unsupported URI scheme: \u201C" + scheme |
| - + "\u201D."; |
| - SAXParseException spe = new SAXParseException(msg, publicId, |
| - systemId, -1, -1, new IOException(msg)); |
| - if (errorHandler != null) { |
| - errorHandler.fatalError(spe); |
| - } |
| - throw spe; |
| - } |
| - systemId = url.toString(); |
| - try { |
| - m = new HttpGet(systemId); |
| - } catch (IllegalArgumentException e) { |
| - SAXParseException spe = new SAXParseException( |
| - e.getMessage(), |
| - publicId, |
| - systemId, |
| - -1, |
| - -1, |
| - (IOException) new IOException(e.getMessage()).initCause(e)); |
| - if (errorHandler != null) { |
| - errorHandler.fatalError(spe); |
| - } |
| - throw spe; |
| - } |
| - m.setHeader("User-Agent", userAgent); |
| - m.setHeader("Accept", buildAccept()); |
| - m.setHeader("Accept-Encoding", "gzip"); |
| - log4j.info(systemId); |
| - HttpResponse response = client.execute(m); |
| - int statusCode = response.getStatusLine().getStatusCode(); |
| - if (statusCode != 200) { |
| - String msg = "HTTP resource not retrievable. The HTTP status from the remote server was: " |
| - + statusCode + "."; |
| - SAXParseException spe = new SAXParseException(msg, publicId, |
| - m.getURI().toString(), -1, -1, new IOException(msg)); |
| - if (errorHandler != null) { |
| - errorHandler.fatalError(spe); |
| - } |
| - throw spe; |
| - } |
| - HttpEntity entity = response.getEntity(); |
| - long len = entity.getContentLength(); |
| - if (sizeLimit > -1 && len > sizeLimit) { |
| - SAXParseException spe = new SAXParseException( |
| - "Resource size exceeds limit.", |
| - publicId, |
| - m.getURI().toString(), |
| - -1, |
| - -1, |
| - new StreamBoundException("Resource size exceeds limit.")); |
| - if (errorHandler != null) { |
| - errorHandler.fatalError(spe); |
| - } |
| - throw spe; |
| - } |
| - TypedInputSource is; |
| - org.apache.http.Header ct = response.getFirstHeader("Content-Type"); |
| - String contentType = null; |
| - final String baseUri = m.getURI().toString(); |
| - if (ct != null) { |
| - contentType = ct.getValue(); |
| - } |
| - is = contentTypeParser.buildTypedInputSource(baseUri, publicId, |
| - contentType); |
| - |
| - Header cl = response.getFirstHeader("Content-Language"); |
| - if (cl != null) { |
| - is.setLanguage(cl.getValue().trim()); |
| - } |
| - |
| - Header xuac = response.getFirstHeader("X-UA-Compatible"); |
| - if (xuac != null) { |
| - String val = xuac.getValue().trim(); |
| - if (!"ie=edge".equalsIgnoreCase(val)) { |
| - SAXParseException spe = new SAXParseException( |
| - "X-UA-Compatible HTTP header must have the value \u201CIE=edge\u201D," |
| - + " was \u201C" + val + "\u201D.", |
| - publicId, systemId, -1, -1); |
| - errorHandler.error(spe); |
| - } |
| - } |
| - |
| - final HttpGet meth = m; |
| - InputStream stream = entity.getContent(); |
| - if (sizeLimit > -1) { |
| - stream = new BoundedInputStream(stream, sizeLimit, baseUri); |
| - } |
| - Header ce = response.getFirstHeader("Content-Encoding"); |
| - if (ce != null) { |
| - String val = ce.getValue().trim(); |
| - if ("gzip".equalsIgnoreCase(val) |
| - || "x-gzip".equalsIgnoreCase(val)) { |
| - stream = new GZIPInputStream(stream); |
| - if (sizeLimit > -1) { |
| - stream = new BoundedInputStream(stream, sizeLimit, |
| - baseUri); |
| - } |
| - } |
| - } |
| - is.setByteStream(new ObservableInputStream(stream, |
| - new StreamObserver() { |
| - private final Logger log4j = Logger.getLogger("nu.validator.xml.PrudentEntityResolver.StreamObserver"); |
| - |
| - private boolean released = false; |
| - |
| - public void closeCalled() { |
| - log4j.debug("closeCalled"); |
| - if (!released) { |
| - log4j.debug("closeCalled, not yet released"); |
| - released = true; |
| - try { |
| - meth.releaseConnection(); |
| - } catch (Exception e) { |
| - log4j.debug( |
| - "closeCalled, releaseConnection", e); |
| - } |
| - } |
| - } |
| - |
| - public void exceptionOccurred(Exception ex) |
| - throws IOException { |
| - if (!released) { |
| - released = true; |
| - try { |
| - meth.abort(); |
| - } catch (Exception e) { |
| - log4j.debug("exceptionOccurred, abort", e); |
| - } finally { |
| - try { |
| - meth.releaseConnection(); |
| - } catch (Exception e) { |
| - log4j.debug( |
| - "exceptionOccurred, releaseConnection", |
| - e); |
| - } |
| - } |
| - } |
| - if (ex instanceof SystemIdIOException) { |
| - SystemIdIOException siie = (SystemIdIOException) ex; |
| - throw siie; |
| - } else if (ex instanceof IOException) { |
| - IOException ioe = (IOException) ex; |
| - throw new SystemIdIOException(baseUri, |
| - ioe.getMessage(), ioe); |
| - } else if (ex instanceof RuntimeException) { |
| - RuntimeException re = (RuntimeException) ex; |
| - throw re; |
| - } else { |
| - throw new RuntimeException( |
| - "API contract violation. Wrong exception type.", |
| - ex); |
| - } |
| - } |
| - |
| - public void finalizerCalled() { |
| - if (!released) { |
| - released = true; |
| - try { |
| - meth.abort(); |
| - } catch (Exception e) { |
| - log4j.debug("finalizerCalled, abort", e); |
| - } finally { |
| - try { |
| - meth.releaseConnection(); |
| - } catch (Exception e) { |
| - log4j.debug( |
| - "finalizerCalled, releaseConnection", |
| - e); |
| - } |
| - } |
| - } |
| - } |
| - |
| - })); |
| - return is; |
| - } catch (IOException e) { |
| - if (m != null) { |
| - try { |
| - m.abort(); |
| - } catch (Exception ex) { |
| - log4j.debug("abort", ex); |
| - } finally { |
| - try { |
| - m.releaseConnection(); |
| - } catch (Exception ex) { |
| - log4j.debug("releaseConnection", ex); |
| - } |
| - } |
| - } |
| - throw e; |
| - } catch (SAXException e) { |
| - if (m != null) { |
| - try { |
| - m.abort(); |
| - } catch (Exception ex) { |
| - log4j.debug("abort", ex); |
| - } finally { |
| - try { |
| - m.releaseConnection(); |
| - } catch (Exception ex) { |
| - log4j.debug("releaseConnection", ex); |
| - } |
| - } |
| - } |
| - throw e; |
| - } catch (RuntimeException e) { |
| - if (m != null) { |
| - try { |
| - m.abort(); |
| - } catch (Exception ex) { |
| - log4j.debug("abort", ex); |
| - } finally { |
| - try { |
| - m.releaseConnection(); |
| - } catch (Exception ex) { |
| - log4j.debug("releaseConnection", ex); |
| - } |
| - } |
| - } |
| - throw e; |
| - } |
| - } |
| - |
| - /** |
| - * @return Returns the allowRnc. |
| - */ |
| - public boolean isAllowRnc() { |
| - return allowRnc; |
| - } |
| - |
| - /** |
| - * @param allowRnc |
| - * The allowRnc to set. |
| - */ |
| - public void setAllowRnc(boolean allowRnc) { |
| - this.allowRnc = allowRnc; |
| - this.contentTypeParser.setAllowRnc(allowRnc); |
| - } |
| - |
| - /** |
| - * @param allowHtml |
| - */ |
| - public void setAllowHtml(boolean allowHtml) { |
| - this.allowHtml = allowHtml; |
| - this.contentTypeParser.setAllowHtml(allowHtml); |
| - } |
| - |
| - /** |
| - * Returns the acceptAllKnownXmlTypes. |
| - * |
| - * @return the acceptAllKnownXmlTypes |
| - */ |
| - public boolean isAcceptAllKnownXmlTypes() { |
| - return acceptAllKnownXmlTypes; |
| - } |
| - |
| - /** |
| - * Sets the acceptAllKnownXmlTypes. |
| - * |
| - * @param acceptAllKnownXmlTypes |
| - * the acceptAllKnownXmlTypes to set |
| - */ |
| - public void setAcceptAllKnownXmlTypes(boolean acceptAllKnownXmlTypes) { |
| - this.acceptAllKnownXmlTypes = acceptAllKnownXmlTypes; |
| - this.contentTypeParser.setAcceptAllKnownXmlTypes(acceptAllKnownXmlTypes); |
| - } |
| - |
| - /** |
| - * Returns the allowGenericXml. |
| - * |
| - * @return the allowGenericXml |
| - */ |
| - public boolean isAllowGenericXml() { |
| - return allowGenericXml; |
| - } |
| - |
| - /** |
| - * Sets the allowGenericXml. |
| - * |
| - * @param allowGenericXml |
| - * the allowGenericXml to set |
| - */ |
| - public void setAllowGenericXml(boolean allowGenericXml) { |
| - this.allowGenericXml = allowGenericXml; |
| - this.contentTypeParser.setAllowGenericXml(allowGenericXml); |
| - } |
| - |
| - /** |
| - * Returns the allowXhtml. |
| - * |
| - * @return the allowXhtml |
| - */ |
| - public boolean isAllowXhtml() { |
| - return allowXhtml; |
| - } |
| - |
| - /** |
| - * Sets the allowXhtml. |
| - * |
| - * @param allowXhtml |
| - * the allowXhtml to set |
| - */ |
| - public void setAllowXhtml(boolean allowXhtml) { |
| - this.allowXhtml = allowXhtml; |
| - this.contentTypeParser.setAllowXhtml(allowXhtml); |
| - } |
| - |
| - private String buildAccept() { |
| - return "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; |
| - } |
| - |
| - /** |
| - * Returns the allowHtml. |
| - * |
| - * @return the allowHtml |
| - */ |
| - public boolean isAllowHtml() { |
| - return allowHtml; |
| - } |
| - |
| - public boolean isOnlyHtmlAllowed() { |
| - return !isAllowGenericXml() && !isAllowRnc() && !isAllowXhtml(); |
| - } |
| -} |