Back to index

courier  0.68.2
fetchinfo.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 1999 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #ifndef       HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 
00010 #include    <stdio.h>
00011 #include    <stdlib.h>
00012 #include    <string.h>
00013 #include    <ctype.h>
00014 #include    <sys/types.h>
00015 
00016 #include      "imaptoken.h"
00017 #include      "imapwrite.h"
00018 #include      "fetchinfo.h"
00019 
00020 
00021 /* This file contains functions to parse a FETCH attribute list */
00022 
00023 static struct fetchinfo *alloc_headerlist(int);
00024 static char *good_section(char *);
00025 
00026 struct fetchinfo *fetchinfo_alloc(int oneonly)
00027 {
00028 struct fetchinfo *list, **listtail, *p;
00029 struct imaptoken *tok;
00030 
00031        list=0;
00032        listtail= &list;
00033 
00034        while ((tok=currenttoken())->tokentype == IT_ATOM)
00035        {
00036               if (oneonly && list) break;
00037               *listtail=p=(struct fetchinfo *)malloc(sizeof(*list));
00038               if (!p)       write_error_exit(0);
00039               p->next=0;
00040               p->name=my_strdup(tok->tokenbuf);
00041               p->bodysection=0;
00042               p->bodysublist=0;
00043               p->ispartial=0;
00044               listtail= &p->next;
00045 
00046               if (strcmp(p->name, "ALL") == 0 ||
00047                      strcmp(p->name, "BODYSTRUCTURE") == 0 ||
00048                      strcmp(p->name, "ENVELOPE") == 0 ||
00049                      strcmp(p->name, "FLAGS") == 0 ||
00050                      strcmp(p->name, "FAST") == 0 ||
00051                      strcmp(p->name, "FULL") == 0 ||
00052                      strcmp(p->name, "INTERNALDATE") == 0 ||
00053                      strcmp(p->name, "RFC822") == 0 ||
00054                      strcmp(p->name, "RFC822.HEADER") == 0 ||
00055                      strcmp(p->name, "RFC822.SIZE") == 0 ||
00056                      strcmp(p->name, "RFC822.TEXT") == 0 ||
00057                      strcmp(p->name, "UID") == 0)
00058               {
00059                      nexttoken();
00060                      continue;
00061               }
00062               if (strcmp(p->name, "BODY") && strcmp(p->name, "BODY.PEEK"))
00063                      break;
00064               if (nexttoken()->tokentype != IT_LBRACKET)       continue;
00065 
00066               /* Parse BODY[ ... ] */
00067 
00068               if ((tok=nexttoken())->tokentype != IT_RBRACKET)
00069               {
00070               char   *s;
00071 
00072                      if ( (tok->tokentype != IT_ATOM &&
00073                             tok->tokentype != IT_NUMBER) ||
00074                             !(s=good_section(tok->tokenbuf)))
00075                      {
00076                             fetchinfo_free(list);
00077                             return (0);
00078                      }
00079                      p->bodysection=my_strdup(tok->tokenbuf);
00080 
00081                      if (strcmp(s, "HEADER.FIELDS") == 0 ||
00082                             strcmp(s, "HEADER.FIELDS.NOT") == 0)
00083                      {
00084                             /* Must be followed by header list */
00085 
00086                             if ((tok=nexttoken_nouc())->tokentype
00087                                           != IT_LPAREN)
00088                             {
00089                                    p->bodysublist=alloc_headerlist(1);
00090                                    if (p->bodysublist == 0)
00091                                    {
00092                                           fetchinfo_free(list);
00093                                           return (0);
00094                                    }
00095                             }
00096                             else
00097                             {
00098                                    nexttoken_nouc();
00099                                    p->bodysublist=alloc_headerlist(0);
00100                                    if ( currenttoken()->tokentype
00101                                           != IT_RPAREN)
00102                                    {
00103                                           fetchinfo_free(list);
00104                                           return (0);
00105                                    }
00106                             }
00107                      }
00108                      tok=nexttoken();
00109                      
00110               }
00111               else p->bodysection=my_strdup("");
00112 
00113               if (tok->tokentype != IT_RBRACKET)
00114               {
00115                      fetchinfo_free(list);
00116                      return (0);
00117               }
00118               tok=nexttoken();
00119               if (tok->tokentype == IT_ATOM && tok->tokenbuf[0] == '<' &&
00120                      tok->tokenbuf[strlen(tok->tokenbuf)-1] == '>' &&
00121                      (p->ispartial=sscanf(tok->tokenbuf+1, "%lu.%lu",
00122                             &p->partialstart, &p->partialend)) > 0)
00123                      nexttoken();
00124        }
00125        return (list);
00126 }
00127 
00128 /* Just validate that the syntax of the attribute is correct */
00129 
00130 static char *good_section(char *p)
00131 {
00132 int    has_mime=0;
00133 
00134        while (isdigit((int)(unsigned char)*p))
00135        {
00136               if (*p == '0')       return (0);
00137               has_mime=1;
00138               while (isdigit((int)(unsigned char)*p))   ++p;
00139               if (*p == '\0')
00140                      return (p);
00141 
00142               if (*p != '.')       return (0);
00143               ++p;
00144        }
00145 
00146        if (strcmp(p, "HEADER") == 0 ||
00147               strcmp(p, "HEADER.FIELDS") == 0 ||
00148               strcmp(p, "HEADER.FIELDS.NOT") == 0 ||
00149               strcmp(p, "TEXT") == 0)
00150               return (p);
00151 
00152        if (strcmp(p, "MIME") == 0 && has_mime)   return (p);
00153        return (0);
00154 }
00155 
00156 /* Header list looks like atoms to me */
00157 
00158 static struct fetchinfo *alloc_headerlist(int oneonly)
00159 {
00160 struct fetchinfo *list, **listtail, *p;
00161 struct imaptoken *tok;
00162 
00163        list=0;
00164        listtail= &list;
00165 
00166        while ((tok=currenttoken())->tokentype == IT_ATOM ||
00167               tok->tokentype == IT_QUOTED_STRING ||
00168               tok->tokentype == IT_NUMBER)
00169        {
00170               *listtail=p=(struct fetchinfo *)malloc(sizeof(*list));
00171               if (!p)       write_error_exit(0);
00172               p->next=0;
00173               p->name=my_strdup(tok->tokenbuf);
00174               p->bodysublist=0;
00175               p->bodysection=0;
00176               listtail= &p->next;
00177               if (oneonly)
00178                      break;
00179               nexttoken_nouc();
00180        }
00181        return (list);
00182 }
00183 
00184 void fetchinfo_free(struct fetchinfo *p)
00185 {
00186 struct fetchinfo *q;
00187 
00188        while (p)
00189        {
00190               if (p->bodysublist)  fetchinfo_free(p->bodysublist);
00191               q=p->next;
00192               if (p->name)  free(p->name);
00193               if (p->bodysection) free(p->bodysection);
00194               free(p);
00195               p=q;
00196        }
00197 }