summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorValentin Gagarin <valentin.gagarin@tweag.io>2023-03-04 12:38:57 +0100
committerGitHub <noreply@github.com>2023-03-04 12:38:57 +0100
commit61cf0b2166f06dab508aff47d08ae3e6418de86e (patch)
treea230179ca3acf80b7fe94c8a8299d4f950f1dfa4 /lib
parent2be637c977708ab96ad08cad3285e7f08dd2efcd (diff)
parent7089294f10068dbeeed6e2e4d7a24300bf4bacb6 (diff)
Merge pull request #219235 from patwid/strings-escape-query-for-url-encoding
Diffstat (limited to 'lib')
-rw-r--r--lib/ascii-table.nix5
-rw-r--r--lib/default.nix2
-rw-r--r--lib/strings.nix21
-rw-r--r--lib/tests/misc.nix9
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")