Fix URL encoding again (#3044)

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
DingDongSoLong4 2022-10-28 08:46:39 +02:00 committed by GitHub
parent 2cd9ef6302
commit b1fa933868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 66 additions and 14 deletions

View File

@ -145,18 +145,69 @@ export class ListFilterModel {
jsonParameters = [params.c!];
}
params.c = jsonParameters.map((jsonString) => {
let decodedJson = jsonString;
// replace () back to {}
decodedJson = decodedJson.replaceAll("(", "{");
decodedJson = decodedJson.replaceAll(")", "}");
// decode all other characters
decodedJson = decodeURIComponent(decodedJson);
return decodedJson;
const decoding = true;
return ListFilterModel.translateSpecialCharacters(
decodeURIComponent(jsonString),
decoding
);
});
}
return params;
}
private static translateSpecialCharacters(input: string, decoding: boolean) {
let inString = false;
let escape = false;
return [...input]
.map((c) => {
if (escape) {
// this character has been escaped, skip
escape = false;
return c;
}
switch (c) {
case "\\":
// escape the next character if in a string
if (inString) {
escape = true;
}
break;
case '"':
// unescaped quote, toggle inString
inString = !inString;
break;
case "(":
// decode only: restore ( to { if not in a string
if (decoding && !inString) {
return "{";
}
break;
case ")":
// decode only: restore ) to } if not in a string
if (decoding && !inString) {
return "}";
}
break;
case "{":
// encode only: replace { with ( if not in a string
if (!decoding && !inString) {
return "(";
}
break;
case "}":
// encode only: replace } with ) if not in a string
if (!decoding && !inString) {
return ")";
}
break;
}
return c;
})
.join("");
}
public configureFromQueryString(query: string) {
const parsed = queryString.parse(query, { decode: false });
const decoded = ListFilterModel.decodeQueryParameters(parsed);
@ -192,15 +243,15 @@ export class ListFilterModel {
// Returns query parameters with necessary parts encoded
public getQueryParameters(): IQueryParameters {
const encodedCriteria: string[] = this.criteria.map((criterion) => {
let str = criterion.toJSON();
const decoding = false;
let str = ListFilterModel.translateSpecialCharacters(
criterion.toJSON(),
decoding
);
// URL-encode other characters
str = encodeURI(str);
// force URL-encode existing ()
str = str.replaceAll("(", "%28");
str = str.replaceAll(")", "%29");
// replace JSON '{'(%7B) '}'(%7D) with explicitly unreserved ()
str = str.replaceAll("%7B", "(");
str = str.replaceAll("%7D", ")");
// only the reserved characters ?#&;=+ need to be URL-encoded
// as they have special meaning in query strings
str = str.replaceAll("?", encodeURIComponent("?"));
@ -209,6 +260,7 @@ export class ListFilterModel {
str = str.replaceAll(";", encodeURIComponent(";"));
str = str.replaceAll("=", encodeURIComponent("="));
str = str.replaceAll("+", encodeURIComponent("+"));
return str;
});