1 /*
2 * $LynxId: HTUU.c,v 1.11 2010/09/21 23:55:12 tom Exp $
3 *
4 * MODULE HTUU.c
5 * UUENCODE AND UUDECODE
6 *
7 * ACKNOWLEDGEMENT:
8 * This code is taken from rpem distribution, and was originally
9 * written by Mark Riordan.
10 *
11 * AUTHORS:
12 * MR Mark Riordan riordanmr@clvax1.cl.msu.edu
13 * AL Ari Luotonen luotonen@dxcern.cern.ch
14 *
15 * HISTORY:
16 * Added as part of the WWW library and edited to conform
17 * with the WWW project coding standards by: AL 5 Aug 1993
18 * Originally written by: MR 12 Aug 1990
19 * Original header text:
20 * -------------------------------------------------------------
21 * File containing routines to convert a buffer
22 * of bytes to/from RFC 1113 printable encoding format.
23 *
24 * This technique is similar to the familiar Unix uuencode
25 * format in that it maps 6 binary bits to one ASCII
26 * character (or more aptly, 3 binary bytes to 4 ASCII
27 * characters). However, RFC 1113 does not use the same
28 * mapping to printable characters as uuencode.
29 *
30 * Mark Riordan 12 August 1990 and 17 Feb 1991.
31 * This code is hereby placed in the public domain.
32 * -------------------------------------------------------------
33 */
34
35 #include <HTUtils.h>
36 #include <HTUU.h>
37
38 #include <LYLeaks.h>
39
40 static char six2pr[64] =
41 {
42 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
43 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
44 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
45 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
46 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
47 };
48
49 static unsigned char pr2six[256];
50
51 /*--- function HTUU_encode -----------------------------------------------
52 *
53 * Encode a single line of binary data to a standard format that
54 * uses only printing ASCII characters (but takes up 33% more bytes).
55 *
56 * Entry bufin points to a buffer of bytes. If nbytes is not
57 * a multiple of three, then the byte just beyond
58 * the last byte in the buffer must be 0.
59 * nbytes is the number of bytes in that buffer.
60 * This cannot be more than 48.
61 * bufcoded points to an output buffer. Be sure that this
62 * can hold at least 1 + (4*nbytes)/3 characters.
63 *
64 * Exit bufcoded contains the coded line. The first 4*nbytes/3 bytes
65 * contain printing ASCII characters representing
66 * those binary bytes. This may include one or
67 * two '=' characters used as padding at the end.
68 * The last byte is a zero byte.
69 * Returns the number of ASCII characters in "bufcoded".
70 */
HTUU_encode(unsigned char * bufin,size_t nbytes,char * bufcoded)71 int HTUU_encode(unsigned char *bufin,
72 size_t nbytes,
73 char *bufcoded)
74 {
75 /* ENC is the basic 1 character encoding function to make a char printing */
76 #define ENC(c) six2pr[c]
77
78 register char *outptr = bufcoded;
79 size_t i;
80
81 /* This doesn't seem to be needed (AL): register unsigned char *inptr = bufin; */
82
83 for (i = 0; i < nbytes; i += 3) {
84 *(outptr++) = ENC(*bufin >> 2); /* c1 */
85 *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2 */
86 *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /*c3 */
87 *(outptr++) = ENC(bufin[2] & 077); /* c4 */
88
89 bufin += 3;
90 }
91
92 /* If nbytes was not a multiple of 3, then we have encoded too
93 * many characters. Adjust appropriately.
94 */
95 if (i == nbytes + 1) {
96 /* There were only 2 bytes in that last group */
97 outptr[-1] = '=';
98 } else if (i == nbytes + 2) {
99 /* There was only 1 byte in that last group */
100 outptr[-1] = '=';
101 outptr[-2] = '=';
102 }
103 *outptr = '\0';
104 return (int) (outptr - bufcoded);
105 }
106
107 /*--- function HTUU_decode ------------------------------------------------
108 *
109 * Decode an ASCII-encoded buffer back to its original binary form.
110 *
111 * Entry bufcoded points to a uuencoded string. It is
112 * terminated by any character not in
113 * the printable character table six2pr, but
114 * leading whitespace is stripped.
115 * bufplain points to the output buffer; must be big
116 * enough to hold the decoded string (generally
117 * shorter than the encoded string) plus
118 * as many as two extra bytes used during
119 * the decoding process.
120 * outbufsize is the maximum number of bytes that
121 * can fit in bufplain.
122 *
123 * Exit Returns the number of binary bytes decoded.
124 * bufplain contains these bytes.
125 */
HTUU_decode(char * bufcoded,unsigned char * bufplain,int outbufsize)126 int HTUU_decode(char *bufcoded,
127 unsigned char *bufplain,
128 int outbufsize)
129 {
130 /* single character decode */
131 #define DEC(c) pr2six[(int)c]
132 #define MAXVAL 63
133
134 static int first = 1;
135
136 int nbytesdecoded, j;
137 register char *bufin;
138 register unsigned char *bufout = bufplain;
139 register int nprbytes;
140
141 /* If this is the first call, initialize the mapping table.
142 * This code should work even on non-ASCII machines.
143 */
144 if (first) {
145 first = 0;
146 for (j = 0; j < 256; j++)
147 pr2six[j] = MAXVAL + 1;
148
149 for (j = 0; j < 64; j++)
150 pr2six[UCH(six2pr[j])] = UCH(j);
151 #if 0
152 /* *INDENT-OFF* */
153 pr2six['A']= 0; pr2six['B']= 1; pr2six['C']= 2; pr2six['D']= 3;
154 pr2six['E']= 4; pr2six['F']= 5; pr2six['G']= 6; pr2six['H']= 7;
155 pr2six['I']= 8; pr2six['J']= 9; pr2six['K']=10; pr2six['L']=11;
156 pr2six['M']=12; pr2six['N']=13; pr2six['O']=14; pr2six['P']=15;
157 pr2six['Q']=16; pr2six['R']=17; pr2six['S']=18; pr2six['T']=19;
158 pr2six['U']=20; pr2six['V']=21; pr2six['W']=22; pr2six['X']=23;
159 pr2six['Y']=24; pr2six['Z']=25; pr2six['a']=26; pr2six['b']=27;
160 pr2six['c']=28; pr2six['d']=29; pr2six['e']=30; pr2six['f']=31;
161 pr2six['g']=32; pr2six['h']=33; pr2six['i']=34; pr2six['j']=35;
162 pr2six['k']=36; pr2six['l']=37; pr2six['m']=38; pr2six['n']=39;
163 pr2six['o']=40; pr2six['p']=41; pr2six['q']=42; pr2six['r']=43;
164 pr2six['s']=44; pr2six['t']=45; pr2six['u']=46; pr2six['v']=47;
165 pr2six['w']=48; pr2six['x']=49; pr2six['y']=50; pr2six['z']=51;
166 pr2six['0']=52; pr2six['1']=53; pr2six['2']=54; pr2six['3']=55;
167 pr2six['4']=56; pr2six['5']=57; pr2six['6']=58; pr2six['7']=59;
168 pr2six['8']=60; pr2six['9']=61; pr2six['+']=62; pr2six['/']=63;
169 /* *INDENT-ON* */
170
171 #endif
172 }
173
174 /* Strip leading whitespace. */
175
176 while (*bufcoded == ' ' || *bufcoded == '\t')
177 bufcoded++;
178
179 /* Figure out how many characters are in the input buffer.
180 * If this would decode into more bytes than would fit into
181 * the output buffer, adjust the number of input bytes downwards.
182 */
183 bufin = bufcoded;
184 while (pr2six[UCH(*(bufin++))] <= MAXVAL) ;
185 nprbytes = (int) (bufin - bufcoded - 1);
186 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
187 if (nbytesdecoded > outbufsize) {
188 nprbytes = (outbufsize * 4) / 3;
189 }
190
191 bufin = bufcoded;
192
193 while (nprbytes > 0) {
194 *(bufout++) = UCH((DEC(bufin[0]) << 2) | (DEC(bufin[1]) >> 4));
195 *(bufout++) = UCH((DEC(bufin[1]) << 4) | (DEC(bufin[2]) >> 2));
196 *(bufout++) = UCH((DEC(bufin[2]) << 6) | (DEC(bufin[3])));
197 bufin += 4;
198 nprbytes -= 4;
199 }
200
201 if (nprbytes & 03) {
202 if (pr2six[(int) bufin[-2]] > MAXVAL) {
203 nbytesdecoded -= 2;
204 } else {
205 nbytesdecoded -= 1;
206 }
207 }
208
209 return (nbytesdecoded);
210 }
211