form.scm 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. ;; This file is part of scheme-GNUnet. -*- coding: utf-8 -*-
  2. ;; Copyright (C) 2021 GNUnet e.V.
  3. ;;
  4. ;; scheme-GNUnet is free software: you can redistribute it and/or modify it
  5. ;; under the terms of the GNU Affero General Public License as published
  6. ;; by the Free Software Foundation, either version 3 of the License,
  7. ;; or (at your option) any later version.
  8. ;;
  9. ;; scheme-GNUnet is distributed in the hope that it will be useful, but
  10. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Affero General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Affero General Public License
  15. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;;
  17. ;; SPDX-License-Identifier: AGPL-3.0-or-later
  18. (use-modules (web form)
  19. (rnrs bytevectors)
  20. (srfi srfi-64))
  21. (define (urlencoded-string->alist string)
  22. (urlencoded->alist (string->utf8 string)))
  23. (define-syntax-rule (test-decode name from to)
  24. (test-equal name (list to) (list (urlencoded-string->alist from))))
  25. (test-begin "w-www-form-urlencoded")
  26. (test-decode "empty list" "" '())
  27. (test-decode "one field" "x=y" '(("x" . "y")))
  28. (test-decode "two fields" "x=y&z=w" '(("x" . "y") ("z" . "w")))
  29. (test-decode "spaces" "x+x+x=z+z+z" '(("x x x" . "z z z")))
  30. (test-decode "forgot to encode spaces" "x x x=z z z" #f)
  31. (test-decode "%-encoding" "x%01%02=x%03z" '(("x\x01\x02" . "x\x03z")))
  32. (test-decode "%-encoding (NULL)" "%00x%01%02=x%03z" '(("\x00x\x01\x02" . "x\x03z")))
  33. (test-decode "= in keys and values" "x%3Dz=0%3D1" '(("x=z" . "0=1")))
  34. (test-decode "zero-length values" "x=&y=" '(("x" . "") ("y" . "")))
  35. (test-decode "zero-length keys" "=z" '(("" . "z")))
  36. ;; IceCat 78.14.0 (a Firefox derivative) doesn't encode - and _, even though they should
  37. ;; be according to RFC 1866.
  38. (test-decode "Firefox compatibility" "x-yz_w=0-12_3" '(("x-yz_w" . "0-12_3")))
  39. (test-decode "Correct %-encoding of - and _" "%5F=%2D" '(("_" . "-")))
  40. ;; The specification uses uppercase letters.
  41. (test-decode "no lowercase % (0)" "%aA=0" #false)
  42. (test-decode "no lowercase % (1)" "%Aa=0" #false)
  43. (test-decode "no %-encoding of A" "%41=0" #false)
  44. (test-decode "no %-encoding of Z" "%5A=0" #false)
  45. (test-decode "no %-encoding of a" "%61=0" #false)
  46. (test-decode "no %-encoding of z" "%7A=0" #false)
  47. (test-decode "no %-encoding of 0" "%30=0" #false)
  48. (test-decode "no %-encoding of 9" "%39=0" #false)
  49. ;; While it might not be advisable, RFC 1866 does not forbid duplicate
  50. ;; field names.
  51. (test-decode "duplicate field names" "field=value&field=value2"
  52. '(("field" . "value") ("field" . "value2")))
  53. (test-decode "leading &" "&oop=s" #false)
  54. (test-decode "trailing &" "oop=s&" #false)
  55. (test-decode "duplicated &" "o=o&&p=s" #false)
  56. (test-decode "duplicated =" "oo==ps" #false)
  57. (test-decode "too many =" "o=o=ps" #false)
  58. ;; RFC 1866 doesn't specify any character encoding, so assume UTF-8.
  59. (define unicode-input "%C3%A9=%F0%9F%AA%82")
  60. (define unicode-output '(("é" . "🪂")))
  61. (test-decode "non-ASCII" unicode-input unicode-output)
  62. (test-decode "bogus UTF-8" "%ED%9F%C0=z" #f)
  63. (define (test-decode-with-encoding encoding)
  64. (parameterize (((fluid->parameter %default-port-encoding) encoding))
  65. (test-decode (string-append "non-ASCII, with " encoding
  66. " default port encoding")
  67. unicode-input unicode-output)))
  68. ;; 'unescape' calls 'call-with-output-bytevector' without explicitely setting
  69. ;; the port encoding appropriately
  70. (test-decode-with-encoding "UTF-8")
  71. (test-decode-with-encoding "ISO-88519") ; doesn't support Unicode
  72. (test-decode-with-encoding "UTF-16") ; two to four bytes per character
  73. (test-decode-with-encoding "EBCDIC") ; non-ASCII compatible, doesn't support Unicode
  74. (test-decode "non-ASCII input" "é=é" #f)
  75. (test-assert "bogus UTF-8 (before decoding)"
  76. (not (urlencoded->alist #vu8(237 159 192 61 49))))
  77. (test-end "w-www-form-urlencoded")