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