Postfix3.3.1
hex_quote.c
[詳解]
1 /*++
2 /* NAME
3 /* hex_quote 3
4 /* SUMMARY
5 /* quote/unquote text, HTTP style.
6 /* SYNOPSIS
7 /* #include <hex_quote.h>
8 /*
9 /* VSTRING *hex_quote(hex, raw)
10 /* VSTRING *hex;
11 /* const char *raw;
12 /*
13 /* VSTRING *hex_unquote(raw, hex)
14 /* VSTRING *raw;
15 /* const char *hex;
16 /* DESCRIPTION
17 /* hex_quote() takes a null-terminated string and replaces non-printable
18 /* and whitespace characters and the % by %XX, XX being the two-digit
19 /* hexadecimal equivalent.
20 /* The hexadecimal codes are produced as upper-case characters. The result
21 /* value is the hex argument.
22 /*
23 /* hex_unquote() performs the opposite transformation. This function
24 /* understands lowercase, uppercase, and mixed case %XX sequences. The
25 /* result value is the raw argument in case of success, a null pointer
26 /* otherwise.
27 /* BUGS
28 /* hex_quote() cannot process null characters in data.
29 /* LICENSE
30 /* .ad
31 /* .fi
32 /* The Secure Mailer license must be distributed with this software.
33 /* AUTHOR(S)
34 /* Wietse Venema
35 /* IBM T.J. Watson Research
36 /* P.O. Box 704
37 /* Yorktown Heights, NY 10598, USA
38 /*--*/
39 
40 /* System library. */
41 
42 #include "sys_defs.h"
43 #include <ctype.h>
44 
45 /* Utility library. */
46 
47 #include "msg.h"
48 #include "vstring.h"
49 #include "hex_quote.h"
50 
51 /* Application-specific. */
52 
53 #define STR(x) vstring_str(x)
54 #define LEN(x) VSTRING_LEN(x)
55 
56 /* hex_quote - raw data to quoted */
57 
58 VSTRING *hex_quote(VSTRING *hex, const char *raw)
59 {
60  const char *cp;
61  int ch;
62 
63  VSTRING_RESET(hex);
64  for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
65  if (ch != '%' && !ISSPACE(ch) && ISPRINT(ch)) {
66  VSTRING_ADDCH(hex, ch);
67  } else {
68  vstring_sprintf_append(hex, "%%%02X", ch);
69  }
70  }
71  VSTRING_TERMINATE(hex);
72  return (hex);
73 }
74 
75 /* hex_unquote - quoted data to raw */
76 
77 VSTRING *hex_unquote(VSTRING *raw, const char *hex)
78 {
79  const char *cp;
80  int ch;
81 
82  VSTRING_RESET(raw);
83  for (cp = hex; (ch = *cp) != 0; cp++) {
84  if (ch == '%') {
85  if (ISDIGIT(cp[1]))
86  ch = (cp[1] - '0') << 4;
87  else if (cp[1] >= 'a' && cp[1] <= 'f')
88  ch = (cp[1] - 'a' + 10) << 4;
89  else if (cp[1] >= 'A' && cp[1] <= 'F')
90  ch = (cp[1] - 'A' + 10) << 4;
91  else
92  return (0);
93  if (ISDIGIT(cp[2]))
94  ch |= (cp[2] - '0');
95  else if (cp[2] >= 'a' && cp[2] <= 'f')
96  ch |= (cp[2] - 'a' + 10);
97  else if (cp[2] >= 'A' && cp[2] <= 'F')
98  ch |= (cp[2] - 'A' + 10);
99  else
100  return (0);
101  cp += 2;
102  }
103  VSTRING_ADDCH(raw, ch);
104  }
105  VSTRING_TERMINATE(raw);
106  return (raw);
107 }
108 
109 #ifdef TEST
110 
111  /*
112  * Proof-of-concept test program: convert to hex and back.
113  */
114 #include <vstream.h>
115 
116 #define BUFLEN 1024
117 
118 static ssize_t read_buf(VSTREAM *fp, VSTRING *buf)
119 {
120  ssize_t len;
121 
122  VSTRING_RESET(buf);
123  len = vstream_fread(fp, STR(buf), vstring_avail(buf));
124  VSTRING_AT_OFFSET(buf, len); /* XXX */
125  VSTRING_TERMINATE(buf);
126  return (len);
127 }
128 
129 int main(int unused_argc, char **unused_argv)
130 {
131  VSTRING *raw = vstring_alloc(BUFLEN);
132  VSTRING *hex = vstring_alloc(100);
133  ssize_t len;
134 
135  while ((len = read_buf(VSTREAM_IN, raw)) > 0) {
136  hex_quote(hex, STR(raw));
137  if (hex_unquote(raw, STR(hex)) == 0)
138  msg_fatal("bad input: %.100s", STR(hex));
139  if (LEN(raw) != len)
140  msg_fatal("len %ld != raw len %ld", (long) len, (long) LEN(raw));
141  if (vstream_fwrite(VSTREAM_OUT, STR(raw), LEN(raw)) != LEN(raw))
142  msg_fatal("write error: %m");
143  }
145  vstring_free(raw);
146  vstring_free(hex);
147  return (0);
148 }
149 
150 #endif
#define VSTREAM_OUT
Definition: vstream.h:67
#define LEN(x)
Definition: hex_quote.c:54
int main(int argc, char **argv)
Definition: anvil.c:1010
#define VSTREAM_IN
Definition: vstream.h:66
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
#define ISDIGIT(c)
Definition: sys_defs.h:1748
#define VSTRING_RESET(vp)
Definition: vstring.h:77
VSTRING * hex_unquote(VSTRING *raw, const char *hex)
Definition: hex_quote.c:77
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define STR(x)
Definition: hex_quote.c:53
VSTRING * hex_quote(VSTRING *hex, const char *raw)
Definition: hex_quote.c:58
#define vstring_avail(vp)
Definition: vstring.h:86
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define vstream_fread(v, b, n)
Definition: vstream.h:104
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define vstream_fwrite(v, b, n)
Definition: vstream.h:105
#define ISPRINT(c)
Definition: sys_defs.h:1751
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define VSTRING_AT_OFFSET(vp, offset)
Definition: vstring.h:92
#define ISSPACE(c)
Definition: sys_defs.h:1753