diff options
author | Patrick Widmer <patrick.widmer@tbwnet.ch> | 2023-03-02 21:41:51 +0100 |
---|---|---|
committer | Patrick Widmer <patrick.widmer@tbwnet.ch> | 2023-03-03 20:48:55 +0100 |
commit | 7089294f10068dbeeed6e2e4d7a24300bf4bacb6 (patch) | |
tree | b905d320eb3a640282fff4d98b0e9068fb136fe0 /lib | |
parent | 55fc05fb8ccce47595ce9607ed2b2e4d49538c0a (diff) |
strings: add escapeQuery for url encoding
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ascii-table.nix | 5 | ||||
-rw-r--r-- | lib/default.nix | 2 | ||||
-rw-r--r-- | lib/strings.nix | 21 | ||||
-rw-r--r-- | lib/tests/misc.nix | 9 |
4 files changed, 32 insertions, 5 deletions
diff --git a/lib/ascii-table.nix b/lib/ascii-table.nix index c564e12bcc6ff..74989936ea402 100644 --- a/lib/ascii-table.nix +++ b/lib/ascii-table.nix @@ -1,4 +1,7 @@ -{ " " = 32; +{ "\t" = 9; + "\n" = 10; + "\r" = 13; + " " = 32; "!" = 33; "\"" = 34; "#" = 35; diff --git a/lib/default.nix b/lib/default.nix index dc4df95754186..7948dbd5a1ef4 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -100,7 +100,7 @@ let escapeShellArg escapeShellArgs isStorePath isStringLike isValidPosixName toShellVar toShellVars - escapeRegex escapeXML replaceChars lowerChars + escapeRegex escapeURL escapeXML replaceChars lowerChars upperChars toLower toUpper addContextFrom splitString removePrefix removeSuffix versionOlder versionAtLeast getName getVersion diff --git a/lib/strings.nix b/lib/strings.nix index 68d9309506625..e49ed4382240c 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -34,6 +34,8 @@ rec { unsafeDiscardStringContext ; + asciiTable = import ./ascii-table.nix; + /* Concatenate a list of strings. Type: concatStrings :: [string] -> string @@ -327,9 +329,7 @@ rec { => 40 */ - charToInt = let - table = import ./ascii-table.nix; - in c: builtins.getAttr c table; + charToInt = c: builtins.getAttr c asciiTable; /* Escape occurrence of the elements of `list` in `string` by prefixing it with a backslash. @@ -355,6 +355,21 @@ rec { */ escapeC = list: replaceStrings list (map (c: "\\x${ toLower (lib.toHexString (charToInt c))}") list); + /* Escape the string so it can be safely placed inside a URL + query. + + Type: escapeURL :: string -> string + + Example: + escapeURL "foo/bar baz" + => "foo%2Fbar%20baz" + */ + escapeURL = let + unreserved = [ "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" "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" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "-" "_" "." "~" ]; + toEscape = builtins.removeAttrs asciiTable unreserved; + in + replaceStrings (builtins.attrNames toEscape) (lib.mapAttrsToList (_: c: "%${fixedWidthString 2 "0" (lib.toHexString c)}") toEscape); + /* Quote string to be used safely within the Bourne shell. Type: escapeShellArg :: string -> string diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 406656dac1a92..07d04f5356c7b 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -347,6 +347,15 @@ runTests { expected = "Hello\\x20World"; }; + testEscapeURL = testAllTrue [ + ("" == strings.escapeURL "") + ("Hello" == strings.escapeURL "Hello") + ("Hello%20World" == strings.escapeURL "Hello World") + ("Hello%2FWorld" == strings.escapeURL "Hello/World") + ("42%25" == strings.escapeURL "42%") + ("%20%3F%26%3D%23%2B%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%09%3A%2F%40%24%27%28%29%2A%2C%3B" == strings.escapeURL " ?&=#+%!<>#\"{}|\\^[]`\t:/@$'()*,;") + ]; + testToInt = testAllTrue [ # Naive (123 == toInt "123") |