summaryrefslogtreecommitdiff
path: root/tests/quoted-printable.scm
blob: 415feb0cfec8edf8e28d7b83e0b243bb1fb40462 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
;;; guile-email --- Guile email parser
;;; Copyright © 2018, 2020 Arun Isaac <arunisaac@systemreboot.net>
;;; Copyright © 2023 Andrew Whatson <whatson@tailcall.au>
;;;
;;; This file is part of guile-email.
;;;
;;; guile-email is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU Affero General Public License as
;;; published by the Free Software Foundation; either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; guile-email is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Affero General Public License for more details.
;;;
;;; You should have received a copy of the GNU Affero General Public
;;; License along with guile-email.  If not, see
;;; <http://www.gnu.org/licenses/>.

(use-modules (email quoted-printable)
             (ice-9 iconv)
             (rnrs bytevectors)
             (srfi srfi-1)
             (srfi srfi-64))

(load "encoding.scm")

(define (string-has-only-quoted-printable-valid-characters? str)
  (string-every (char-set-union
                 (char-set #\newline #\return #\space)
                 (ucs-range->char-set 33 127))
                str))

(define (quoted-printable-escape-encode-char chr)
  (format #f "=~:@(~2,'0x~)" (char->integer chr)))

(test-begin "quoted-printable")

(let ((decoded-text
       "J'interdis aux marchands de vanter trop leur marchandises. Car ils se font vite pédagogues et t'enseignent comme but ce qui n'est par essence qu'un moyen, et te trompant ainsi sur la route à suivre les voilà bientôt qui te dégradent, car si leur musique est vulgaire ils te fabriquent pour te la vendre une âme vulgaire.")
      (encoded-text
       "J'interdis aux marchands de vanter trop leur marchandises. Car ils se font =
vite p=C3=A9dagogues et t'enseignent comme but ce qui n'est par essence qu'=
un moyen, et te trompant ainsi sur la route =C3=A0 suivre les voil=C3=A0 bi=
ent=C3=B4t qui te d=C3=A9gradent, car si leur musique est vulgaire ils te f=
abriquent pour te la vendre une =C3=A2me vulgaire.")
      (charset "UTF-8"))
  (test-equal "quoted-printable wikipedia example: decoding"
    (bytevector->string (quoted-printable-decode encoded-text) charset)
    decoded-text)

  (test-equal "quoted-printable wikipedia example: encoding"
    (quoted-printable-encode
     (string->bytevector decoded-text charset))
    encoded-text)

  (test-assert "quoted-printable wikipedia example: encoded output should not be more than 76 columns wide"
    (each-line-has-a-maximum-of-76-characters?
     (quoted-printable-encode
      (string->bytevector decoded-text charset)))))

(test-equal "quoted-printable encoding of special characters"
  (quoted-printable-encode
   (string->bytevector "=\r\n" "UTF-8"))
  (string-append
   (quoted-printable-escape-encode-char #\=)
   (quoted-printable-escape-encode-char #\return)
   (quoted-printable-escape-encode-char #\newline)))

(test-equal "quoted-printable decoding of soft line breaks (=\\n)"
  (quoted-printable-decode "=\n") #vu8())

(test-equal "quoted-printable decoding of soft line breaks (=\\r\\n)"
  (quoted-printable-decode "=\r\n") #vu8())

(test-assert "quoted-printable random bytevector: quoted-printable-encode and quoted-printable-decode are inverses of each other"
  (every (lambda (len)
           (let ((x (random-bytevector len)))
             (equal? x (quoted-printable-decode (quoted-printable-encode x)))))
         (iota 1000)))

(test-assert "quoted-printable random bytevector: encoded output should not be more than 76 columns wide"
  (every (lambda (len)
           (each-line-has-a-maximum-of-76-characters?
            (quoted-printable-encode
             (random-bytevector len))))
         (iota 1000)))

(test-assert "quoted-printable random bytevector: encoded output must only consist of printable ASCII characters"
  (every (lambda (len)
           (string-has-only-quoted-printable-valid-characters?
            (quoted-printable-encode (random-bytevector len))))
         (iota 1000)))

(let ((encoded-text "=A1Hola,_se=F1or!")
      (decoded-text "¡Hola, señor!")
      (charset "ISO-8859-1"))
  (test-equal "q-encoding wikipedia example: decoding"
    (q-encoding-encode
     (string->bytevector decoded-text charset))
    encoded-text)

  (test-equal "q-encoding wikipedia example: encoding"
    (bytevector->string
     (q-encoding-decode encoded-text)
     charset)
    decoded-text))

(test-equal "q-encoding of special characters"
  (q-encoding-encode (string->bytevector " _?" "UTF-8"))
  (string-append "_"
                 (quoted-printable-escape-encode-char #\_)
                 (quoted-printable-escape-encode-char #\?)))

(test-assert "q-encoding random bytevector: q-encoding-encode and q-encoding-decode are inverses of each other"
  (every (lambda (len)
           (let ((x (random-bytevector len)))
             (equal? x (q-encoding-decode (q-encoding-encode x)))))
         (iota 1000)))

(test-end "quoted-printable")