Skip to content

Commit cea5a2c

Browse files
committed
Merge branch 'main' into guava-migration-do-less
2 parents 67890ce + e8aa0f1 commit cea5a2c

16 files changed

+338
-21
lines changed

.gitattributes

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/COPYING text
2+
/src/test/resources/org/owasp/html/* text eol=lf
3+
.gitattributes text
4+
.gitignore text
5+
*.html text
6+
*.java text
7+
*.js text
8+
*.json text
9+
*.md text
10+
*.sh text
11+
*.txt text
12+
*.xml text
13+
*.yml text

.github/workflows/maven.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
3+
4+
name: Java CI with Maven
5+
6+
on:
7+
push:
8+
paths-ignore:
9+
- '.github/workflows/*.yml'
10+
- '!.github/workflows/maven.yml'
11+
pull_request:
12+
paths-ignore:
13+
- '.github/workflows/*.yml'
14+
- '!.github/workflows/maven.yml'
15+
16+
permissions:
17+
contents: read
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
23+
strategy:
24+
matrix:
25+
java: [ '11', '17', '21' ]
26+
27+
steps:
28+
- uses: actions/checkout@v4
29+
- name: Set up JDK ${{ matrix.Java }}
30+
uses: actions/setup-java@v4
31+
with:
32+
java-version: ${{ matrix.Java }}
33+
distribution: 'temurin'
34+
cache: maven
35+
- name: Build with Maven
36+
run: mvn --batch-mode --errors --fail-at-end --show-version --update-snapshots verify
37+
- name: Store artifact
38+
if: ${{ matrix.Java == 11 }}
39+
uses: actions/upload-artifact@v4
40+
with:
41+
name: jar-jdk${{ matrix.Java }}
42+
path: target/*.jar
43+
retention-days: 7

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A fast and easy to configure HTML Sanitizer written in Java which lets
77
you include HTML authored by third-parties in your web application while
88
protecting against XSS.
99

10-
The existing dependencies are on guava and JSR 305. The other jars
10+
The existing dependency is on JSR 305. The other jars
1111
are only needed by the test suite. The JSR 305 dependency is a
1212
compile-only dependency, only needed for annotations.
1313

RELEASE-checklist.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ set -e
88

99

1010
# Make sure the build is ok via
11-
mvn -Dguava.version=27.0-jre -f aggregate clean verify javadoc:jar source:jar
1211
mvn -f aggregate clean verify jacoco:report site javadoc:jar source:jar
1312
mvn install
1413
mvn org.sonatype.ossindex.maven:ossindex-maven-plugin:audit -f aggregate

docs/getting_started.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
If you are using Maven then follow the [maven](maven.md) directions to
66
add a dependency. Otherwise,
7-
[download prebuilt jars](https://search.maven.org/#artifactdetails%7Ccom.googlecode.owasp-java-html-sanitizer%7Cowasp-java-html-sanitizer%7C20180219.1%7Cjar)
7+
[download prebuilt jars](https://search.maven.org/artifact/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/)
88
or `git clone git@github.com:OWASP/java-html-sanitizer.git` and build
99
the latest source.
1010

11-
Unless maven is managing your CLASSPATH for you, you need to add both `owasp-java-html-sanitizer.jar` and the
12-
Guava JAR.
11+
Unless maven is managing your CLASSPATH for you, you need to add `owasp-java-html-sanitizer.jar`.
1312

1413
Once you have your CLASSPATH set up correctly with the relevant JARs
1514
you should be able to add

parent/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ application while protecting against XSS.
257257
<dependency>
258258
<groupId>com.google.protobuf</groupId>
259259
<artifactId>protobuf-java</artifactId>
260-
<version>3.9.1</version>
260+
<version>3.16.3</version>
261261
<scope>provided</scope>
262262
</dependency>
263263
<dependency>

src/main/java/org/owasp/html/Encoding.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public final class Encoding {
4343
* @return text/plain
4444
* @deprecated specify whether s is in an attribute value
4545
*/
46+
@Deprecated
4647
public static String decodeHtml(String s) {
4748
return decodeHtml(s, false);
4849
}

src/main/java/org/owasp/html/HtmlEntities.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,6 +2309,7 @@ final class HtmlEntities {
23092309
* @return The offset after the end of the decoded sequence in {@code html}.
23102310
* @deprecated specify whether html is in an attribute value.
23112311
*/
2312+
@Deprecated
23122313
public static int appendDecodedEntity(
23132314
String html, int offset, int limit, StringBuilder sb) {
23142315
return appendDecodedEntity(html, offset, limit, false, sb);

src/main/java/org/owasp/html/HtmlPolicyBuilder.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.util.HashMap;
3434
import java.util.HashSet;
3535
import java.util.LinkedHashMap;
36-
import java.util.LinkedHashSet;
3736
import java.util.List;
3837
import java.util.Map;
3938
import java.util.Set;
@@ -966,12 +965,11 @@ public AttributeBuilder matching(
966965
*/
967966
@SuppressWarnings("synthetic-access")
968967
public HtmlPolicyBuilder globally() {
969-
if(attributeNames.get(0).equals("style")) {
970-
return allowStyling();
971-
} else {
972-
return HtmlPolicyBuilder.this.allowAttributesGlobally(
973-
policy, attributeNames);
968+
if (attributeNames.contains("style")) {
969+
allowStyling();
974970
}
971+
return HtmlPolicyBuilder.this.allowAttributesGlobally(
972+
policy, attributeNames);
975973
}
976974

977975
/**
@@ -1040,6 +1038,7 @@ public String apply(String elementName, List<String> attrs) {
10401038
relValue = DEFAULT_RELS_ON_TARGETTED_LINKS_STR;
10411039
} else {
10421040
StringBuilder sb = new StringBuilder();
1041+
Set<String> present = new HashSet<String>();
10431042
if (relIndex >= 0) {
10441043
// Preserve values that are not explicitly skipped.
10451044
String rels = attrs.get(relIndex);
@@ -1050,25 +1049,34 @@ public String apply(String elementName, List<String> attrs) {
10501049
if (skip.isEmpty()
10511050
|| !skip.contains(
10521051
Strings.toLowerCase(rels.substring(left, i)))) {
1053-
sb.append(rels, left, i).append(' ');
1052+
String rel = rels.substring(left, i);
1053+
present.add(rel);
1054+
sb.append(rel).append(' ');
10541055
}
10551056
}
10561057
left = i + 1;
10571058
}
10581059
}
10591060
}
10601061
for (String s : extra) {
1061-
sb.append(s).append(' ');
1062+
if (!present.contains(s)) {
1063+
sb.append(s).append(' ');
1064+
present.add(s);
1065+
}
10621066
}
10631067
if (hasTarget) {
10641068
for (String s : whenTargetPresent) {
1065-
sb.append(s).append(' ');
1069+
if (!present.contains(s)) {
1070+
sb.append(s).append(' ');
1071+
present.add(s);
1072+
}
10661073
}
10671074
}
10681075
int sblen = sb.length();
10691076
if (sblen == 0) {
10701077
relValue = "";
10711078
} else {
1079+
// Trim last space.
10721080
relValue = sb.substring(0, sb.length() - 1);
10731081
}
10741082
}

src/main/java/org/owasp/html/HtmlStreamRenderer.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.io.IOException;
3434
import java.util.Iterator;
3535
import java.util.List;
36+
import java.util.Set;
3637

3738
import javax.annotation.WillCloseWhenClosed;
3839
import javax.annotation.concurrent.NotThreadSafe;
@@ -57,6 +58,8 @@ public class HtmlStreamRenderer implements HtmlStreamEventReceiver {
5758
private StringBuilder pendingUnescaped;
5859
private HtmlTextEscapingMode escapingMode = HtmlTextEscapingMode.PCDATA;
5960
private boolean open;
61+
/** The count of {@link #foreignContentRootElementNames} opened and not subsequently closed. */
62+
private int foreignContentDepth = 0;
6063

6164
/**
6265
* Factory.
@@ -168,7 +171,25 @@ private void writeOpenTag(
168171
return;
169172
}
170173

171-
escapingMode = HtmlTextEscapingMode.getModeForTag(elementName);
174+
if (foreignContentRootElementNames.contains(elementName)) {
175+
foreignContentDepth += 1;
176+
}
177+
178+
HtmlTextEscapingMode tentativeEscapingMode = HtmlTextEscapingMode.getModeForTag(elementName);
179+
if (foreignContentDepth == 0) {
180+
escapingMode = tentativeEscapingMode;
181+
} else {
182+
switch (tentativeEscapingMode) {
183+
case PCDATA:
184+
case VOID:
185+
escapingMode = tentativeEscapingMode;
186+
break;
187+
default: // escape special characters but do not allow tags
188+
escapingMode = HtmlTextEscapingMode.RCDATA;
189+
break;
190+
}
191+
}
192+
172193

173194
switch (escapingMode) {
174195
case CDATA_SOMETIMES:
@@ -240,6 +261,10 @@ private final void writeCloseTag(String uncanonElementName)
240261
return;
241262
}
242263

264+
if (foreignContentDepth != 0 && foreignContentRootElementNames.contains(elementName)) {
265+
foreignContentDepth -= 1;
266+
}
267+
243268
if (pendingUnescaped != null) {
244269
if (!lastTagOpened.equals(elementName)) {
245270
error("Tag content cannot appear inside CDATA element", elementName);
@@ -436,4 +461,6 @@ public void close() throws IOException {
436461
private static boolean isTagEnd(char ch) {
437462
return ch < 63 && 0 != (TAG_ENDS & (1L << ch));
438463
}
464+
465+
private static final Set<String> foreignContentRootElementNames = Set.of("svg", "math");
439466
}

src/test/java/org/owasp/html/Benchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public class Benchmark {
5858
* specifies a benchmark to run and unspecified ones are not run.
5959
*/
6060
public static void main(String[] args) throws Exception {
61-
String html = Files.readString(new File(args[0]).toPath(), StandardCharsets.UTF_8);
61+
String html = new String(Files.readAllBytes(new File(args[0]).toPath()), StandardCharsets.UTF_8);
6262

6363
boolean timeLibhtmlparser = true;
6464
boolean timeSanitize = true;

src/test/java/org/owasp/html/CssSchemaTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public static final void testDangerousProperties() {
5555
// Prefix corner cases.
5656
"-",
5757
"-moz-",
58+
"-ms-",
59+
"-o-",
60+
"-webkit-",
5861
}) {
5962
assertSame(key, CssSchema.DISALLOWED, CssSchema.DEFAULT.forKey(key));
6063
}

src/test/java/org/owasp/html/HtmlLexerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ public class HtmlLexerTest extends TestCase {
4545
@Test
4646
public final void testHtmlLexer() throws Exception {
4747
// Do the lexing.
48-
String input = new String(Files.readString(Paths.get(getClass().getResource("htmllexerinput1.html").toURI()), StandardCharsets.UTF_8));
48+
String input = new String(Files.readAllBytes(Paths.get(getClass().getResource("htmllexerinput1.html").toURI())), StandardCharsets.UTF_8);
4949
StringBuilder actual = new StringBuilder();
5050
lex(input, actual);
5151

5252
// Get the golden.
53-
String golden = new String(Files.readString(Paths.get(getClass().getResource("htmllexergolden1.txt").toURI()), StandardCharsets.UTF_8));
53+
String golden = new String(Files.readAllBytes(Paths.get(getClass().getResource("htmllexergolden1.txt").toURI())), StandardCharsets.UTF_8);
5454

5555
// Compare.
5656
assertEquals(golden, actual.toString());

0 commit comments

Comments
 (0)