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 #define DECODEBUFSIZ BUFSIZ
30
31 typedef struct _URL_qsdecode
32 {
33 char common[sizeof(struct _URL)];
34 URL reader;
35 long rpos;
36 int beg, end, eof, eod;
37 unsigned char decodebuf[DECODEBUFSIZ];
38 int autoclose;
39 } URL_qsdecode;
40
41 static long url_qsdecode_read(URL url, void *buff, long n);
42 static int url_qsdecode_fgetc(URL url);
43 static long url_qsdecode_tell(URL url);
44 static void url_qsdecode_close(URL url);
45
url_qsdecode_open(URL reader,int autoclose)46 URL url_qsdecode_open(URL reader, int autoclose)
47 {
48 URL_qsdecode *url;
49
50 url = (URL_qsdecode *)alloc_url(sizeof(URL_qsdecode));
51 if(url == NULL)
52 {
53 if(autoclose)
54 url_close(reader);
55 url_errno = errno;
56 return NULL;
57 }
58
59 /* common members */
60 URLm(url, type) = URL_qsdecode_t;
61 URLm(url, url_read) = url_qsdecode_read;
62 URLm(url, url_gets) = NULL;
63 URLm(url, url_fgetc) = url_qsdecode_fgetc;
64 URLm(url, url_seek) = NULL;
65 URLm(url, url_tell) = url_qsdecode_tell;
66 URLm(url, url_close) = url_qsdecode_close;
67
68 /* private members */
69 url->reader = reader;
70 url->rpos = 0;
71 url->beg = 0;
72 url->end = 0;
73 url->eof = url->eod = 0;
74 memset(url->decodebuf, 0, sizeof(url->decodebuf));
75 url->autoclose = autoclose;
76
77 return (URL)url;
78 }
79
qsdecode(URL_qsdecode * urlp)80 static int qsdecode(URL_qsdecode *urlp)
81 {
82 int n;
83 unsigned char *p;
84 URL url;
85
86 if(urlp->eod)
87 {
88 urlp->eof = 1;
89 return 1;
90 }
91
92 p = urlp->decodebuf;
93 url = urlp->reader;
94 n = 0;
95 while(n < DECODEBUFSIZ)
96 {
97 int c1, c2;
98
99 if((c1 = url_getc(url)) == EOF)
100 break;
101 if(c1 != '=')
102 {
103 p[n++] = c1;
104 continue;
105 }
106
107 /* quoted character */
108 next_quote:
109 if((c1 = url_getc(url)) == EOF)
110 break;
111 if(c1 == '\n')
112 continue;
113 if(c1 == '\r')
114 {
115 if((c1 = url_getc(url)) == EOF)
116 break;
117 if(c1 == '\n')
118 continue;
119 if(c1 == '=')
120 goto next_quote;
121 p[n++] = c1;
122 continue;
123 }
124 if((c2 = url_getc(url)) == EOF)
125 break;
126 if('0' <= c1 && c1 <= '9')
127 c1 -= '0';
128 else if('A' <= c1 && c1 <= 'F')
129 c1 -= 'A' - 10;
130 else
131 c1 = 0;
132 if('0' <= c2 && c2 <= '9')
133 c2 -= '0';
134 else if('A' <= c2 && c2 <= 'F')
135 c2 -= 'A' - 10;
136 else
137 c2 = 0;
138 p[n++] = (c1 << 4 | c2);
139 }
140
141 urlp->rpos += urlp->beg;
142 urlp->beg = 0;
143 urlp->end = n;
144
145 if(n < DECODEBUFSIZ)
146 urlp->eod = 1;
147
148 if(n == 0)
149 {
150 urlp->eof = 1;
151 return 1;
152 }
153
154
155 return 0;
156 }
157
url_qsdecode_read(URL url,void * buff,long size)158 static long url_qsdecode_read(URL url, void *buff, long size)
159 {
160 URL_qsdecode *urlp = (URL_qsdecode *)url;
161 unsigned char *p = (unsigned char *)buff;
162 long n;
163
164 if(urlp->eof)
165 return 0;
166
167 n = 0;
168 while(n < size)
169 {
170 int i;
171
172 if(urlp->beg == urlp->end)
173 if(qsdecode(urlp))
174 break;
175 i = urlp->end - urlp->beg;
176 if(i > size - n)
177 i = size - n;
178 memcpy(p + n, urlp->decodebuf + urlp->beg, i);
179 n += i;
180 urlp->beg += i;
181 }
182 return n;
183 }
184
url_qsdecode_fgetc(URL url)185 static int url_qsdecode_fgetc(URL url)
186 {
187 URL_qsdecode *urlp = (URL_qsdecode *)url;
188
189 if(urlp->eof)
190 return EOF;
191 if(urlp->beg == urlp->end)
192 if(qsdecode(urlp))
193 return EOF;
194
195 return (int)urlp->decodebuf[urlp->beg++];
196 }
197
url_qsdecode_tell(URL url)198 static long url_qsdecode_tell(URL url)
199 {
200 URL_qsdecode *urlp = (URL_qsdecode *)url;
201
202 return urlp->rpos + urlp->beg;
203 }
204
url_qsdecode_close(URL url)205 static void url_qsdecode_close(URL url)
206 {
207 URL_qsdecode *urlp = (URL_qsdecode *)url;
208
209 if(urlp->autoclose)
210 url_close(urlp->reader);
211 free(url);
212 }
213
214 #ifdef QSDECODE_MAIN
main(int argc,char ** argv)215 void main(int argc, char** argv)
216 {
217 URL qsdecoder;
218 char buff[256], *filename;
219 int c;
220
221 if(argc != 2)
222 {
223 fprintf(stderr, "Usage: %s qs-filename\n", argv[0]);
224 exit(1);
225 }
226 filename = argv[1];
227
228 if((qsdecoder = url_file_open(filename)) == NULL)
229 {
230 perror(argv[1]);
231 url_close(qsdecoder);
232 exit(1);
233 }
234
235 qsdecoder = url_qsdecode_open(qsdecoder, 1);
236 #if QSDECODE_MAIN
237 while((c = url_getc(qsdecoder)) != EOF)
238 putchar(c);
239 #else
240 while((c = url_read(qsdecoder, buff, sizeof(buff))) > 0)
241 write(1, buff, c);
242 #endif
243 url_close(qsdecoder);
244 exit(0);
245 }
246
247 #endif /* QSDECODE_MAIN */
248