parser.c - rohrpost - A commandline mail client to change the world as we see it.
(HTM) git clone git://r-36.net/rohrpost
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
parser.c (6974B)
---
1 /*
2 * Copy me if you can.
3 * by 20h
4 */
5
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11
12 #include "ind.h"
13 #include "net.h"
14 #include "strio.h"
15 #include "parser.h"
16 #include "base64.h"
17
18 enum {
19 PARSER_NET = 0x00,
20 PARSER_STRING
21 };
22 static char *parsernames[] = {
23 [PARSER_NET] = "net",
24 [PARSER_STRING] = "string"
25 };
26
27 parser_t *
28 parser_new(char *type, void *struc)
29 {
30 parser_t *ret;
31 int ttype, i;
32
33 for (i = 0, ttype = -1; i < nelem(parsernames); i++)
34 if (!strcmp(parsernames[i], type))
35 ttype = i;
36 if (ttype > -1) {
37 ret = mallocz(sizeof(parser_t), 2);
38 ret->type = ttype;
39 ret->types = memdup(type, strlen(type)+1);
40 ret->struc = struc;
41 } else
42 return NULL;
43 return ret;
44 }
45
46 void
47 parser_free(parser_t *parser)
48 {
49 if (parser->types != NULL)
50 free(parser->types);
51 free(parser);
52 }
53
54 int
55 parser_read(parser_t *parser, char *buf, int len)
56 {
57 //int r;
58
59 switch(parser->type) {
60 case PARSER_NET:
61 //r = net_read((net_t *)parser->struc, buf, len);
62 //printf(buf);
63 //return r;
64 return net_read((net_t *)parser->struc, buf, len);
65 case PARSER_STRING:
66 //r = strio_read((strio_t *)parser->struc, buf, len);
67 //printf(buf);
68 //return r;
69 return strio_read((strio_t *)parser->struc, buf, len);
70 default:
71 break;
72 }
73
74 return -1;
75 }
76
77 int
78 parser_readall(parser_t *parser, char *buf, int len)
79 {
80 //int r;
81
82 switch(parser->type) {
83 case PARSER_NET:
84 //r = net_readall((net_t *)parser->struc, buf, len);
85 //printf(buf);
86 //return r;
87 return net_readall((net_t *)parser->struc, buf, len);
88 case PARSER_STRING:
89 //r = strio_readall((strio_t *)parser->struc, buf, len);
90 //printf(buf);
91 //return r;
92 return strio_readall((strio_t *)parser->struc, buf, len);
93 default:
94 break;
95 }
96
97 return -1;
98 }
99
100 char *
101 parser_getuntil(parser_t *parser, void *str, int slen)
102 {
103 char *ret;
104 int len, pos;
105
106 pos = 0;
107 len = 1;
108 ret = mallocz(len, 2);
109 while (parser_read(parser, &ret[len-1], 1) > 0 && len < MAXLINESIZE) {
110 if (ret[len-1] == ((char *)str)[pos]) {
111 pos++;
112 if (pos >= slen)
113 break;
114 } else
115 pos = 0;
116
117 ret = reallocz(ret, ++len + 1, 0);
118 }
119 ret[len] = '\0';
120
121 return ret;
122 }
123
124 char *
125 parser_encodeplainlogin(char *user, char *pass)
126 {
127 char *authstr, *b64a;
128 int len;
129
130 authstr = memdup("\0", 1);
131 len = 1;
132 authstr = memdupcat(authstr, len, user, strlen(user)+1);
133 len += strlen(user) + 1;
134 authstr = memdupcat(authstr, len, pass, strlen(pass)+1);
135 len += strlen(pass);
136 b64a = b64enc(authstr, len);
137 free(authstr);
138
139 return b64a;
140 }
141
142 char *
143 parser_encodestring(char *str)
144 {
145 if (strchr(str, '\n') || strchr(str, '\r') || strchr(str, '"'))
146 return smprintf("{%d+}\r\n%s", strlen(str), str);
147 else
148 return smprintf("\"%s\"", str);
149 }
150
151 char *
152 parser_parsesieve(parser_t *parser, char *ptr)
153 {
154 int len;
155 char *ret;
156
157 switch (ptr[0]) {
158 case '"':
159 sscanf(ptr+1, "%1024m[^\"]%*[^\n]", &ret);
160 break;
161 case '{':
162 sscanf(ptr, "{%d+}%*[^\n]", &len);
163 if (len > 0) {
164 ret = mallocz(len+1, 2);
165 parser_readall(parser, ret, len);
166 } else
167 return NULL;
168 break;
169 default:
170 sscanf(ptr, "%1024m[^ ]%*[^\n]", &ret);
171 break;
172 }
173
174 return ret;
175 }
176
177 char *
178 parser_simplestring(char *str)
179 {
180 char *ret;
181
182 switch (str[0]) {
183 case '"':
184 sscanf(str+1, "%1024m[^\"]%*[^\n]", &ret);
185 break;
186 default:
187 sscanf(str, "%1024m[^ ]%*[^\n]", &ret);
188 break;
189 }
190
191 return ret;
192 }
193
194 llist_t *
195 parser_parseimapstructinternal(parser_t *parser, llist_t *ret)
196 {
197 llist_t *res;
198 llistelem_t *lce, *pope;
199 char buf[1025], *dbuf, lc, cchar;
200 int i, len, incomment;
201
202 memset(buf, 0, sizeof(buf));
203
204 parsestructagain:
205 i = 1;
206 if (parser_read(parser, buf, 1) <= 0)
207 return NULL;
208 //printf("%s", buf);
209 switch (buf[0]) {
210 case '{':
211 for (; parser_read(parser, &buf[i], 1) > 0 && i < sizeof(buf);
212 i++) {
213 if (buf[i] == '}')
214 break;
215 }
216 lc = buf[i];
217 buf[i] = '\0';
218
219 len = atoi(&buf[1]);
220
221 if (len < 1)
222 llist_add(ret, "nil", NULL, 0);
223 else {
224 dbuf = mallocz(len+1, 2);
225 parser_readall(parser, dbuf, 2);
226 parser_readall(parser, dbuf, len);
227 llist_add(ret, "literal", dbuf, len+1);
228 }
229 llist_add(ret, "lc", &lc, 1);
230 free(dbuf);
231 break;
232 case '"':
233 for (i = 0, incomment = 0; parser_read(parser, &buf[i], 1) > 0
234 && i < sizeof(buf); i++) {
235 switch (buf[i]) {
236 case '"':
237 if (incomment)
238 break;
239 if (buf[i-1] == '\\') {
240 buf[i-1] = '"';
241 i--;
242 } else
243 goto parsestructend;
244 break;
245 case '\\':
246 if (buf[i-1] == '\\') {
247 buf[i-1] = '\\';
248 i--;
249 }
250 break;
251 case '(':
252 case '[':
253 if (!incomment) {
254 if (buf[i] == '(')
255 cchar = ')';
256 else
257 cchar = ']';
258 incomment = 1;
259 }
260 break;
261 case ')':
262 case ']':
263 if (cchar == buf[i] && incomment) {
264 incomment = 0;
265 break;
266 }
267 goto parsestructend;
268 default:
269 break;
270 }
271 }
272 parsestructend:
273 lc = buf[i];
274 buf[i] = '\0';
275 llist_add(ret, "string", buf, strlen(buf)+1);
276 llist_add(ret, "lc", &lc, 1);
277 break;
278 case '(':
279 res = llist_new();
280 llist_addraw(ret, NULL, res, sizeof(res));
281 for(;;) {
282 res = llist_new();
283 if (parser_parseimapstructinternal(parser, res)
284 == NULL) {
285 llist_free(res);
286 break;
287 }
288 if (res->first->key != NULL &&
289 !strcmp(res->first->key, "listend")) {
290 llist_free(res);
291 break;
292 }
293
294 pope = llist_pop(res);
295 llist_addelem((llist_t *)ret->first->data, pope);
296
297 lce = llist_get(res, "lc");
298 if (lce != NULL) {
299 lc = ((char *)lce->data)[0];
300 } else
301 lc = '\0';
302 llist_efree(res);
303
304 if (lc == ')')
305 break;
306 }
307 break;
308 case '0':
309 case '1':
310 case '2':
311 case '3':
312 case '4':
313 case '5':
314 case '6':
315 case '7':
316 case '8':
317 case '9':
318 for (; parser_read(parser, &buf[i], 1) > 0 && i < sizeof(buf);
319 i++)
320 if (buf[i] > '9' || buf[i] < '0')
321 break;
322 lc = buf[i];
323 buf[i] = '\0';
324 llist_add(ret, "number", buf, strlen(buf)+1);
325 llist_add(ret, "lc", &lc, 1);
326 break;
327 case ' ':
328 case '\t':
329 case '\r':
330 case '\f':
331 case '\v':
332 goto parsestructagain;
333 case '\n':
334 return NULL;
335 case ')':
336 llist_add(ret, "listend", NULL, 0);
337 llist_add(ret, "lc", &lc, 1);
338 break;
339 default:
340 for (; parser_read(parser, &buf[i], 1) > 0 && i < sizeof(buf);
341 i++) {
342 switch (buf[i]) {
343 case ' ':
344 case '\t':
345 case '\r':
346 case '\n':
347 case '"':
348 case ')':
349 goto atomshouldstop;
350 default:
351 break;
352 };
353 }
354 atomshouldstop:
355 lc = buf[i];
356 buf[i] = '\0';
357 if (!strcmp(buf, "NIL"))
358 llist_add(ret, "nil", NULL, 0);
359 else
360 llist_add(ret, "atom", buf, strlen(buf)+1);
361 llist_add(ret, "lc", &lc, 1);
362 break;
363 }
364
365 return ret;
366 }
367
368 llistelem_t *
369 parser_parseimapstruct(parser_t *parser)
370 {
371 llist_t *res;
372 llistelem_t *ret;
373
374 res = llist_new();
375 if (parser_parseimapstructinternal(parser, res) == NULL) {
376 llist_efree(res);
377 return NULL;
378 }
379 if (res->len < 1) {
380 llist_efree(res);
381 return NULL;
382 }
383
384 if (res->first->key != NULL && !strcmp(res->first->key, "listend")) {
385 llist_efree(res);
386 return NULL;
387 }
388
389 ret = llist_pop(res);
390 llist_efree(res);
391
392
393 return ret;
394 }
395