Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,16 @@ private void check(ApkInfo apkInfo) {
assertEquals(1, apkInfo.getVersionInfo().getVersionCode());
assertEquals("1.0", apkInfo.getVersionInfo().getVersionName());
assertNotNull(apkInfo.getDoNotCompress());
assertEquals(6, apkInfo.getDoNotCompress().size());
assertEquals(10, apkInfo.getDoNotCompress().size());
assertEquals("assets/0byte_file.jpg", apkInfo.getDoNotCompress().get(0));
assertEquals("arsc", apkInfo.getDoNotCompress().get(1));
assertEquals("png", apkInfo.getDoNotCompress().get(2));
assertEquals("mp3", apkInfo.getDoNotCompress().get(3));
assertEquals("stored.file", apkInfo.getDoNotCompress().get(4));
assertEquals("surrogate/pair/😊.test", apkInfo.getDoNotCompress().get(5));
assertEquals("'double-quoted", apkInfo.getDoNotCompress().get(6));
assertEquals("\"single-quoted", apkInfo.getDoNotCompress().get(7));
assertEquals("\\\"single-quoted-with-\\tab", apkInfo.getDoNotCompress().get(8));
assertEquals("\"double-quoted-with-\tab", apkInfo.getDoNotCompress().get(9));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ doNotCompress:
- mp3
- stored.file
- surrogate/pair/😊.test
- "'double-quoted"
- '"single-quoted'
- '\"single-quoted-with-\tab'
- "\"double-quoted-with-\tab"
204 changes: 112 additions & 92 deletions brut.j.yaml/src/main/java/brut/yaml/YamlUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,106 +32,126 @@ public static String escapeString(String str) {
if (len == 0) {
return "\"\"";
}
// Scan for characters that force quoting.
boolean quote = false;
for (int i = 0; i < len; i++) {
char ch = str.charAt(i);
// No-Break Space, Line Separator, and Paragraph Separator are printable but must be escaped.
if (ch == '\u00A0' || ch == '\u2028' || ch == '\u2029') {
quote = true;
// If starts with a quote, quote the rest using the opposite quote character.
char ch = str.charAt(0);
char quote;
if (ch == '\'') {
quote = '"';
} else {
quote = ch == '"' ? '\'' : 0;
// Scan for characters that force double-quoting.
for (int i = 0; i < len; i++) {
ch = str.charAt(i);
// No-Break Space, Line Separator, and Paragraph Separator are printable but must be escaped.
if (ch == '\u00A0' || ch == '\u2028' || ch == '\u2029') {
quote = '"';
break;
}
if (TextUtils.isPrintableChar(ch)) {
continue;
}
// Is this a high surrogate followed by a valid low surrogate?
if (Character.isHighSurrogate(ch) && i + 1 < len && Character.isLowSurrogate(str.charAt(i + 1))) {
i++;
continue;
}
// A non-printable character must be escaped.
quote = '"';
break;
}
if (TextUtils.isPrintableChar(ch)) {
continue;
}
// Is this a high surrogate followed by a valid low surrogate?
if (Character.isHighSurrogate(ch) && i + 1 < len && Character.isLowSurrogate(str.charAt(i + 1))) {
i++;
continue;
}
// A non-printable character must be escaped.
quote = true;
break;
}
// If nothing forced quoting, return the string as-is.
if (!quote) {
return str;
}
// Quoting is needed: escape \, ", and non-printable characters.
StringBuilder sb = new StringBuilder(len * 2 + 2);
sb.append('"');
for (int i = 0; i < len; i++) {
char ch = str.charAt(i);
switch (ch) {
case '\\':
sb.append("\\\\");
continue;
case '"':
sb.append("\\\"");
continue;
case '\0': // Null
sb.append("\\0");
continue;
case '\u0007': // Bell
sb.append("\\a");
continue;
case '\b': // Backspace
sb.append("\\b");
continue;
case '\t': // Character Tabulation
sb.append("\\t");
continue;
case '\n': // Line Feed
sb.append("\\n");
continue;
case '\u000B': // Line Tabulation
sb.append("\\v");
continue;
case '\f': // Form Feed
sb.append("\\f");
continue;
case '\r': // Carriage Return
sb.append("\\r");
continue;
case '\u001B': // Escape
sb.append("\\e");
continue;
case '\u0085': // Next Line
sb.append("\\N");
continue;
case '\u00A0': // No-Break Space
sb.append("\\_");
continue;
case '\u2028': // Line Separator
sb.append("\\L");
continue;
case '\u2029': // Paragraph Separator
sb.append("\\P");
if (quote == '"') {
// Double-quote: escape \, ", and non-printable characters.
StringBuilder sb = new StringBuilder(len * 2 + 2);
sb.append('"');
for (int i = 0; i < len; i++) {
ch = str.charAt(i);
switch (ch) {
case '\\':
sb.append("\\\\");
continue;
case '"':
sb.append("\\\"");
continue;
case '\0': // Null
sb.append("\\0");
continue;
case '\u0007': // Bell
sb.append("\\a");
continue;
case '\b': // Backspace
sb.append("\\b");
continue;
case '\t': // Character Tabulation
sb.append("\\t");
continue;
case '\n': // Line Feed
sb.append("\\n");
continue;
case '\u000B': // Line Tabulation
sb.append("\\v");
continue;
case '\f': // Form Feed
sb.append("\\f");
continue;
case '\r': // Carriage Return
sb.append("\\r");
continue;
case '\u001B': // Escape
sb.append("\\e");
continue;
case '\u0085': // Next Line
sb.append("\\N");
continue;
case '\u00A0': // No-Break Space
sb.append("\\_");
continue;
case '\u2028': // Line Separator
sb.append("\\L");
continue;
case '\u2029': // Paragraph Separator
sb.append("\\P");
continue;
}
if (TextUtils.isPrintableChar(ch)) {
sb.append(ch);
continue;
}
// Is this a high surrogate followed by a valid low surrogate?
if (Character.isHighSurrogate(ch) && i + 1 < len) {
char low = str.charAt(i + 1);
if (Character.isLowSurrogate(low)) {
sb.append(ch).append(low);
i++;
continue;
}
// fallthrough
}
// Java-style Unicode escape the non-printable character.
sb.append("\\u")
.append(Character.forDigit(ch >>> 12, 16))
.append(Character.forDigit(ch >>> 8 & 0xF, 16))
.append(Character.forDigit(ch >>> 4 & 0xF, 16))
.append(Character.forDigit(ch & 0xF, 16));
}
if (TextUtils.isPrintableChar(ch)) {
sb.append(ch);
continue;
}
// Is this a high surrogate followed by a valid low surrogate?
if (Character.isHighSurrogate(ch) && i + 1 < len) {
char low = str.charAt(i + 1);
if (Character.isLowSurrogate(low)) {
sb.append(ch).append(low);
i++;
continue;
sb.append('"');
str = sb.toString();
} else if (quote == '\'') {
// Single-quote: escape ' by doubling it.
StringBuilder sb = new StringBuilder(len * 2 + 2);
sb.append('\'');
for (int i = 0; i < len; i++) {
ch = str.charAt(i);
if (ch == '\'') {
sb.append("''");
} else {
sb.append(ch);
}
// fallthrough
}
// Java-style Unicode escape the non-printable character.
sb.append("\\u")
.append(Character.forDigit(ch >>> 12, 16))
.append(Character.forDigit(ch >>> 8 & 0xF, 16))
.append(Character.forDigit(ch >>> 4 & 0xF, 16))
.append(Character.forDigit(ch & 0xF, 16));
sb.append('\'');
str = sb.toString();
}
sb.append('"');
return sb.toString();
return str;
}

public static String unescapeString(String str) {
Expand Down
Loading