7 /* quote/unquote text, HTTP style.
9 /* #include <hex_quote.h>
11 /* VSTRING *hex_quote(hex, raw)
15 /* VSTRING *hex_unquote(raw, hex)
19 /* hex_quote() takes a null-terminated string and replaces non-printable
20 /* and whitespace characters and the % by %XX, XX being the two-digit
21 /* hexadecimal equivalent.
22 /* The hexadecimal codes are produced as upper-case characters. The result
23 /* value is the hex argument.
25 /* hex_unquote() performs the opposite transformation. This function
26 /* understands lowercase, uppercase, and mixed case %XX sequences. The
27 /* result value is the raw argument in case of success, a null pointer
30 /* hex_quote() cannot process null characters in data.
34 /* The Secure Mailer license must be distributed with this software.
37 /* IBM T.J. Watson Research
39 /* Yorktown Heights, NY 10598, USA
47 /* Utility library. */
51 #include "hex_quote.h"
53 /* Application-specific. */
55 #define STR(x) vstring_str(x)
56 #define LEN(x) VSTRING_LEN(x)
58 /* hex_quote - raw data to quoted */
60 VSTRING
*hex_quote(VSTRING
*hex
, const char *raw
)
66 for (cp
= raw
; (ch
= *(unsigned const char *) cp
) != 0; cp
++) {
67 if (ch
!= '%' && !ISSPACE(ch
) && ISPRINT(ch
)) {
68 VSTRING_ADDCH(hex
, ch
);
70 vstring_sprintf_append(hex
, "%%%02X", ch
);
73 VSTRING_TERMINATE(hex
);
77 /* hex_unquote - quoted data to raw */
79 VSTRING
*hex_unquote(VSTRING
*raw
, const char *hex
)
85 for (cp
= hex
; (ch
= *cp
) != 0; cp
++) {
88 ch
= (cp
[1] - '0') << 4;
89 else if (cp
[1] >= 'a' && cp
[1] <= 'f')
90 ch
= (cp
[1] - 'a' + 10) << 4;
91 else if (cp
[1] >= 'A' && cp
[1] <= 'F')
92 ch
= (cp
[1] - 'A' + 10) << 4;
97 else if (cp
[2] >= 'a' && cp
[2] <= 'f')
98 ch
|= (cp
[2] - 'a' + 10);
99 else if (cp
[2] >= 'A' && cp
[2] <= 'F')
100 ch
|= (cp
[2] - 'A' + 10);
105 VSTRING_ADDCH(raw
, ch
);
107 VSTRING_TERMINATE(raw
);
114 * Proof-of-concept test program: convert to hex and back.
120 static ssize_t
read_buf(VSTREAM
*fp
, VSTRING
*buf
)
125 len
= vstream_fread(fp
, STR(buf
), vstring_avail(buf
));
126 VSTRING_AT_OFFSET(buf
, len
); /* XXX */
127 VSTRING_TERMINATE(buf
);
131 int main(int unused_argc
, char **unused_argv
)
133 VSTRING
*raw
= vstring_alloc(BUFLEN
);
134 VSTRING
*hex
= vstring_alloc(100);
137 while ((len
= read_buf(VSTREAM_IN
, raw
)) > 0) {
138 hex_quote(hex
, STR(raw
));
139 if (hex_unquote(raw
, STR(hex
)) == 0)
140 msg_fatal("bad input: %.100s", STR(hex
));
142 msg_fatal("len %ld != raw len %ld", (long) len
, (long) LEN(raw
));
143 if (vstream_fwrite(VSTREAM_OUT
, STR(raw
), LEN(raw
)) != LEN(raw
))
144 msg_fatal("write error: %m");
146 vstream_fflush(VSTREAM_OUT
);