Postfix3.3.1
hex_code.c
[詳解]
1 /*++
2 /* NAME
3 /* hex_code 3
4 /* SUMMARY
5 /* encode/decode data, hexadecimal style
6 /* SYNOPSIS
7 /* #include <hex_code.h>
8 /*
9 /* VSTRING *hex_encode(result, in, len)
10 /* VSTRING *result;
11 /* const char *in;
12 /* ssize_t len;
13 /*
14 /* VSTRING *hex_decode(result, in, len)
15 /* VSTRING *result;
16 /* const char *in;
17 /* ssize_t len;
18 /* DESCRIPTION
19 /* hex_encode() takes a block of len bytes and encodes it as one
20 /* upper-case null-terminated string. The result value is
21 /* the result argument.
22 /*
23 /* hex_decode() performs the opposite transformation on
24 /* lower-case, upper-case or mixed-case input. The result
25 /* value is the result argument. The result is null terminated,
26 /* whether or not that makes sense.
27 /* DIAGNOSTICS
28 /* hex_decode() returns a null pointer when the input contains
29 /* characters not in the hexadecimal alphabet.
30 /* LICENSE
31 /* .ad
32 /* .fi
33 /* The Secure Mailer license must be distributed with this software.
34 /* AUTHOR(S)
35 /* Wietse Venema
36 /* IBM T.J. Watson Research
37 /* P.O. Box 704
38 /* Yorktown Heights, NY 10598, USA
39 /*--*/
40 
41 /* System library. */
42 
43 #include <sys_defs.h>
44 #include <ctype.h>
45 #include <string.h>
46 
47 /* Utility library. */
48 
49 #include <msg.h>
50 #include <mymalloc.h>
51 #include <vstring.h>
52 #include <hex_code.h>
53 
54 /* Application-specific. */
55 
56 static const unsigned char hex_chars[] = "0123456789ABCDEF";
57 
58 #define UCHAR_PTR(x) ((const unsigned char *)(x))
59 
60 /* hex_encode - raw data to encoded */
61 
62 VSTRING *hex_encode(VSTRING *result, const char *in, ssize_t len)
63 {
64  const unsigned char *cp;
65  int ch;
66  ssize_t count;
67 
68  VSTRING_RESET(result);
69  for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) {
70  ch = *cp;
71  VSTRING_ADDCH(result, hex_chars[(ch >> 4) & 0xf]);
72  VSTRING_ADDCH(result, hex_chars[ch & 0xf]);
73  }
74  VSTRING_TERMINATE(result);
75  return (result);
76 }
77 
78 /* hex_decode - encoded data to raw */
79 
80 VSTRING *hex_decode(VSTRING *result, const char *in, ssize_t len)
81 {
82  const unsigned char *cp;
83  ssize_t count;
84  unsigned int hex;
85  unsigned int bin;
86 
87  VSTRING_RESET(result);
88  for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) {
89  if (count < 2)
90  return (0);
91  hex = cp[0];
92  if (hex >= '0' && hex <= '9')
93  bin = (hex - '0') << 4;
94  else if (hex >= 'A' && hex <= 'F')
95  bin = (hex - 'A' + 10) << 4;
96  else if (hex >= 'a' && hex <= 'f')
97  bin = (hex - 'a' + 10) << 4;
98  else
99  return (0);
100  hex = cp[1];
101  if (hex >= '0' && hex <= '9')
102  bin |= (hex - '0');
103  else if (hex >= 'A' && hex <= 'F')
104  bin |= (hex - 'A' + 10);
105  else if (hex >= 'a' && hex <= 'f')
106  bin |= (hex - 'a' + 10);
107  else
108  return (0);
109  VSTRING_ADDCH(result, bin);
110  }
111  VSTRING_TERMINATE(result);
112  return (result);
113 }
114 
115 #ifdef TEST
116 
117  /*
118  * Proof-of-concept test program: convert to hexadecimal and back.
119  */
120 
121 #define STR(x) vstring_str(x)
122 #define LEN(x) VSTRING_LEN(x)
123 
124 int main(int unused_argc, char **unused_argv)
125 {
126  VSTRING *b1 = vstring_alloc(1);
127  VSTRING *b2 = vstring_alloc(1);
128  char *test = "this is a test";
129 
130 #define DECODE(b,x,l) { \
131  if (hex_decode((b),(x),(l)) == 0) \
132  msg_panic("bad hex: %s", (x)); \
133  }
134 #define VERIFY(b,t) { \
135  if (strcmp((b), (t)) != 0) \
136  msg_panic("bad test: %s", (b)); \
137  }
138 
139  hex_encode(b1, test, strlen(test));
140  DECODE(b2, STR(b1), LEN(b1));
141  VERIFY(STR(b2), test);
142 
143  hex_encode(b1, test, strlen(test));
144  hex_encode(b2, STR(b1), LEN(b1));
145  hex_encode(b1, STR(b2), LEN(b2));
146  DECODE(b2, STR(b1), LEN(b1));
147  DECODE(b1, STR(b2), LEN(b2));
148  DECODE(b2, STR(b1), LEN(b1));
149  VERIFY(STR(b2), test);
150 
151  hex_encode(b1, test, strlen(test));
152  hex_encode(b2, STR(b1), LEN(b1));
153  hex_encode(b1, STR(b2), LEN(b2));
154  hex_encode(b2, STR(b1), LEN(b1));
155  hex_encode(b1, STR(b2), LEN(b2));
156  DECODE(b2, STR(b1), LEN(b1));
157  DECODE(b1, STR(b2), LEN(b2));
158  DECODE(b2, STR(b1), LEN(b1));
159  DECODE(b1, STR(b2), LEN(b2));
160  DECODE(b2, STR(b1), LEN(b1));
161  VERIFY(STR(b2), test);
162 
163  vstring_free(b1);
164  vstring_free(b2);
165  return (0);
166 }
167 
168 #endif
int main(int argc, char **argv)
Definition: anvil.c:1010
#define LEN
Definition: cleanup_addr.c:106
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
VSTRING * hex_encode(VSTRING *result, const char *in, ssize_t len)
Definition: hex_code.c:62
#define VSTRING_RESET(vp)
Definition: vstring.h:77
#define STR(x)
Definition: anvil.c:518
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define UCHAR_PTR(x)
Definition: hex_code.c:58
VSTRING * hex_decode(VSTRING *result, const char *in, ssize_t len)
Definition: hex_code.c:80