7 /* quote/unquote text, xtext style.
11 /* VSTRING *xtext_quote(quoted, unquoted, special)
13 /* const char *unquoted;
14 /* const char *special;
16 /* VSTRING *xtext_quote_append(unquoted, quoted, special)
18 /* const char *quoted;
19 /* const char *special;
21 /* VSTRING *xtext_unquote(unquoted, quoted)
23 /* const char *quoted;
25 /* xtext_quote() takes a null-terminated string and replaces characters
26 /* +, <33(10) and >126(10), as well as characters specified with "special"
27 /* by +XX, XX being the two-digit uppercase hexadecimal equivalent.
29 /* xtext_quote_append() is like xtext_quote(), but appends the conversion
30 /* result to the result buffer.
32 /* xtext_unquote() performs the opposite transformation. This function
33 /* understands lowercase, uppercase, and mixed case +XX sequences. The
34 /* result value is the unquoted argument in case of success, a null pointer
37 /* This module cannot process null characters in data.
41 /* The Secure Mailer license must be distributed with this software.
44 /* IBM T.J. Watson Research
46 /* Yorktown Heights, NY 10598, USA
55 /* Utility library. */
61 /* Application-specific. */
63 #define STR(x) vstring_str(x)
64 #define LEN(x) VSTRING_LEN(x)
66 /* xtext_quote_append - append unquoted data to quoted data */
68 VSTRING
*xtext_quote_append(VSTRING
*quoted
, const char *unquoted
,
74 for (cp
= unquoted
; (ch
= *(unsigned const char *) cp
) != 0; cp
++) {
75 if (ch
!= '+' && ch
> 32 && ch
< 127
76 && (*special
== 0 || strchr(special
, ch
) == 0)) {
77 VSTRING_ADDCH(quoted
, ch
);
79 vstring_sprintf_append(quoted
, "+%02X", ch
);
82 VSTRING_TERMINATE(quoted
);
86 /* xtext_quote - unquoted data to quoted */
88 VSTRING
*xtext_quote(VSTRING
*quoted
, const char *unquoted
, const char *special
)
90 VSTRING_RESET(quoted
);
91 xtext_quote_append(quoted
, unquoted
, special
);
95 /* xtext_unquote - quoted data to unquoted */
97 VSTRING
*xtext_unquote(VSTRING
*unquoted
, const char *quoted
)
102 VSTRING_RESET(unquoted
);
103 for (cp
= quoted
; (ch
= *cp
) != 0; cp
++) {
106 ch
= (cp
[1] - '0') << 4;
107 else if (cp
[1] >= 'a' && cp
[1] <= 'f')
108 ch
= (cp
[1] - 'a' + 10) << 4;
109 else if (cp
[1] >= 'A' && cp
[1] <= 'F')
110 ch
= (cp
[1] - 'A' + 10) << 4;
115 else if (cp
[2] >= 'a' && cp
[2] <= 'f')
116 ch
|= (cp
[2] - 'a' + 10);
117 else if (cp
[2] >= 'A' && cp
[2] <= 'F')
118 ch
|= (cp
[2] - 'A' + 10);
123 VSTRING_ADDCH(unquoted
, ch
);
125 VSTRING_TERMINATE(unquoted
);
132 * Proof-of-concept test program: convert to quoted and back.
138 static ssize_t
read_buf(VSTREAM
*fp
, VSTRING
*buf
)
143 len
= vstream_fread(fp
, STR(buf
), vstring_avail(buf
));
144 VSTRING_AT_OFFSET(buf
, len
); /* XXX */
145 VSTRING_TERMINATE(buf
);
149 int main(int unused_argc
, char **unused_argv
)
151 VSTRING
*unquoted
= vstring_alloc(BUFLEN
);
152 VSTRING
*quoted
= vstring_alloc(100);
155 while ((len
= read_buf(VSTREAM_IN
, unquoted
)) > 0) {
156 xtext_quote(quoted
, STR(unquoted
), "+=");
157 if (xtext_unquote(unquoted
, STR(quoted
)) == 0)
158 msg_fatal("bad input: %.100s", STR(quoted
));
159 if (LEN(unquoted
) != len
)
160 msg_fatal("len %ld != unquoted len %ld",
161 (long) len
, (long) LEN(unquoted
));
162 if (vstream_fwrite(VSTREAM_OUT
, STR(unquoted
), LEN(unquoted
)) != LEN(unquoted
))
163 msg_fatal("write error: %m");
165 vstream_fflush(VSTREAM_OUT
);
166 vstring_free(unquoted
);
167 vstring_free(quoted
);