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