1 /*
2 Copyright (C) 2000 Masanao Izumo <mo@goice.co.jp>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "config.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #ifndef NO_STRING_H
23 #include <string.h>
24 #else
25 #include <strings.h>
26 #endif
27 #include "libarc/url.h"
28
29 typedef struct _URL_uudecode
30 {
31 char common[sizeof(struct _URL)];
32 URL reader;
33 long rpos;
34 int beg, end, eof;
35 unsigned char decodebuf[128];
36 int autoclose;
37 } URL_uudecode;
38
39 static long url_uudecode_read(URL url, void *buff, long n);
40 static int url_uudecode_fgetc(URL url);
41 static long url_uudecode_tell(URL url);
42 static void url_uudecode_close(URL url);
43
url_uudecode_open(URL reader,int autoclose)44 URL url_uudecode_open(URL reader, int autoclose)
45 {
46 URL_uudecode *url;
47
48 url = (URL_uudecode *)alloc_url(sizeof(URL_uudecode));
49 if(url == NULL)
50 {
51 if(autoclose)
52 url_close(reader);
53 url_errno = errno;
54 return NULL;
55 }
56
57 /* common members */
58 URLm(url, type) = URL_uudecode_t;
59 URLm(url, url_read) = url_uudecode_read;
60 URLm(url, url_gets) = NULL;
61 URLm(url, url_fgetc) = url_uudecode_fgetc;
62 URLm(url, url_seek) = NULL;
63 URLm(url, url_tell) = url_uudecode_tell;
64 URLm(url, url_close) = url_uudecode_close;
65
66 /* private members */
67 url->reader = reader;
68 url->rpos = 0;
69 url->beg = 0;
70 url->end = 0;
71 url->eof = 0;
72 memset(url->decodebuf, 0, sizeof(url->decodebuf));
73 url->autoclose = autoclose;
74
75 return (URL)url;
76 }
77
78 #define DEC(c) (((c) - ' ') & 077) /* single character decode */
uudecodeline(URL_uudecode * urlp)79 static int uudecodeline(URL_uudecode *urlp)
80 {
81 unsigned char inbuf[BUFSIZ], *p, *q, ch;
82 int n;
83
84 if(url_gets(urlp->reader, (char *)inbuf, sizeof(inbuf)) == NULL)
85 {
86 urlp->eof = 1;
87 return 1;
88 }
89
90 if((n = DEC(*inbuf)) <= 0)
91 {
92 urlp->eof = 1;
93 return 1;
94 }
95
96 if(uudecode_unquote_html)
97 {
98 int i, j, len;
99
100 len = strlen((char *)inbuf);
101 while(len > 0 &&
102 (inbuf[len - 1] == '\r' || inbuf[len - 1] == '\n' ||
103 inbuf[len - 1] == '\t' || inbuf[len - 1] == ' '))
104 inbuf[--len] = '\0';
105 if(n * 4 != (len - 1) * 3)
106 {
107 /* </>/& */
108 i = j = 0;
109 while(i < len - 3)
110 if(inbuf[i] != '&')
111 inbuf[j++] = inbuf[i++];
112 else
113 {
114 i++;
115 if(strncmp((char *)inbuf + i, "lt;", 3) == 0)
116 {
117 inbuf[j++] = '<';
118 i += 3;
119 }
120 else if(strncmp((char *)inbuf + i, "gt;", 3) == 0)
121 {
122 inbuf[j++] = '>';
123 i += 3;
124 }
125 else if(strncmp((char *)inbuf + i, "amp;", 4) == 0)
126 {
127 inbuf[j++] = '&';
128 i += 4;
129 }
130 else
131 inbuf[j++] = '&';
132 }
133 while(i < len)
134 inbuf[j++] = inbuf[i++];
135 inbuf[j++] = '\0';
136 }
137 }
138
139 p = inbuf + 1;
140 q = urlp->decodebuf;
141 for(; n > 0; p += 4, n -= 3)
142 {
143 if(n >= 3)
144 {
145 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
146 *q++ = ch;
147 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
148 *q++ = ch;
149 ch = DEC(p[2]) << 6 | DEC(p[3]);
150 *q++ = ch;
151 }
152 else
153 {
154 if(n >= 1)
155 {
156 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
157 *q++ = ch;
158 }
159 if(n >= 2)
160 {
161 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
162 *q++ = ch;
163 }
164 if(n >= 3)
165 {
166 ch = DEC(p[2]) << 6 | DEC(p[3]);
167 *q++ = ch;
168 }
169 }
170 }
171 urlp->rpos += urlp->beg;
172 urlp->beg = 0;
173 urlp->end = q - urlp->decodebuf;
174 return 0;
175 }
176
url_uudecode_read(URL url,void * buff,long size)177 static long url_uudecode_read(URL url, void *buff, long size)
178 {
179 URL_uudecode *urlp = (URL_uudecode *)url;
180 unsigned char *p = (unsigned char *)buff;
181 long n;
182
183 if(urlp->eof)
184 return 0;
185
186 n = 0;
187 while(n < size)
188 {
189 int i;
190
191 if(urlp->beg == urlp->end)
192 if(uudecodeline(urlp))
193 break;
194 i = urlp->end - urlp->beg;
195 if(i > size - n)
196 i = size - n;
197 memcpy(p + n, urlp->decodebuf + urlp->beg, i);
198 n += i;
199 urlp->beg += i;
200 }
201 return n;
202 }
203
url_uudecode_fgetc(URL url)204 static int url_uudecode_fgetc(URL url)
205 {
206 URL_uudecode *urlp = (URL_uudecode *)url;
207
208 if(urlp->eof)
209 return EOF;
210 if(urlp->beg == urlp->end)
211 if(uudecodeline(urlp))
212 return EOF;
213
214 return (int)urlp->decodebuf[urlp->beg++];
215 }
216
url_uudecode_tell(URL url)217 static long url_uudecode_tell(URL url)
218 {
219 URL_uudecode *urlp = (URL_uudecode *)url;
220
221 return urlp->rpos + urlp->beg;
222 }
223
url_uudecode_close(URL url)224 static void url_uudecode_close(URL url)
225 {
226 URL_uudecode *urlp = (URL_uudecode *)url;
227
228 if(urlp->autoclose)
229 url_close(urlp->reader);
230 free(url);
231 }
232
233 #ifdef UUDECODE_MAIN
main(int argc,char ** argv)234 void main(int argc, char** argv)
235 {
236 URL uudecoder;
237 char buff[256], *filename;
238 int c;
239
240 if(argc != 2)
241 {
242 fprintf(stderr, "Usage: %s uu-filename\n", argv[0]);
243 exit(1);
244 }
245 filename = argv[1];
246
247 if((uudecoder = url_file_open(filename)) == NULL)
248 {
249 perror(argv[1]);
250 exit(1);
251 }
252
253 for(;;)
254 {
255 if(url_readline(uudecoder, buff, sizeof(buff)) == EOF)
256 {
257 fprintf(stderr, "%s: Not a hqx-file\n", filename);
258 url_close(uudecoder);
259 exit(1);
260 }
261 if(strncmp(buff, "begin ", 6) == 0)
262 break;
263 }
264
265 uudecoder = url_uudecode_open(uudecoder, 1);
266 #if UUDECODE_MAIN
267 while((c = url_getc(uudecoder)) != EOF)
268 putchar(c);
269 #else
270 while((c = url_read(uudecoder, buff, sizeof(buff))) > 0)
271 write(1, buff, c);
272 #endif
273 url_close(uudecoder);
274 exit(0);
275 }
276
277 #endif /* UUDECODE_MAIN */
278