Back to index

courier  0.68.2
autoresponse.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2001 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "autoresponse.h"
00007 #include      "autoresponsequota.h"
00008 #include      <stdlib.h>
00009 #include      <string.h>
00010 #include      <stdio.h>
00011 #include      <ctype.h>
00012 #include      <errno.h>
00013 #if    HAVE_UNISTD_H
00014 #include      <unistd.h>
00015 #endif
00016 #include <sys/types.h>
00017 #if HAVE_SYS_STAT_H
00018 #include <sys/stat.h>
00019 #endif
00020 #if HAVE_DIRENT_H
00021 #include <dirent.h>
00022 #define NAMLEN(dirent) strlen((dirent)->d_name)
00023 #else
00024 #define dirent direct
00025 #define NAMLEN(dirent) (dirent)->d_namlen
00026 #if HAVE_SYS_NDIR_H
00027 #include <sys/ndir.h>
00028 #endif
00029 #if HAVE_SYS_DIR_H
00030 #include <sys/dir.h>
00031 #endif
00032 #if HAVE_NDIR_H
00033 #include <ndir.h>
00034 #endif
00035 #endif
00036 
00037 
00038 struct maildir_autoresponse_quota {
00039        unsigned files;
00040        unsigned long bytes;
00041 } ;
00042 
00043 struct temp_autoresponse_list {
00044        struct temp_autoresponse_list *next;
00045        char *filename;
00046 } ;
00047 
00048 char **maildir_autoresponse_list(const char *maildir)
00049 {
00050        char *d, **a;
00051        struct temp_autoresponse_list *list=NULL;
00052        unsigned list_cnt;
00053        struct temp_autoresponse_list *p;
00054 
00055        DIR *dirp;
00056 
00057        if (!maildir)
00058               maildir=".";
00059 
00060        d=malloc(strlen(maildir)+sizeof("/autoresponses"));
00061 
00062        if (!d)
00063               return (NULL);
00064 
00065        strcat(strcpy(d, maildir), "/autoresponses");
00066 
00067        dirp=opendir(d);
00068        free(d);
00069 
00070        list_cnt=0;
00071 
00072        if (dirp)
00073        {
00074               struct dirent *de;
00075 
00076               while ((de=readdir(dirp)) != NULL)
00077               {
00078                      if (strchr(de->d_name, '.'))
00079                             continue;
00080 
00081                      p=(struct temp_autoresponse_list *)
00082                             malloc(sizeof(struct temp_autoresponse_list));
00083                      if (p)
00084                      {
00085                             if ((p->filename=strdup(de->d_name)) == NULL)
00086                             {
00087                                    free(p);
00088                                    p=NULL;
00089                             }
00090                      }
00091 
00092                      if (!p)
00093                      {
00094                             closedir(dirp);
00095 
00096                             while (list)
00097                             {
00098                                    p=list;
00099                                    list=p->next;
00100                                    free(p->filename);
00101                                    free(p);
00102                             }
00103                             return (NULL);
00104                      }
00105                      p->next=list;
00106                      list=p;
00107                      ++list_cnt;
00108               }
00109               closedir(dirp);
00110        }
00111 
00112        a=malloc( (list_cnt+1)*sizeof(char *));
00113 
00114        if (!a)
00115        {
00116               while (list)
00117               {
00118                      p=list;
00119                      list=p->next;
00120                      free(p->filename);
00121                      free(p);
00122               }
00123               return (NULL);
00124        }
00125 
00126        list_cnt=0;
00127 
00128        while (list)
00129        {
00130               p=list;
00131               list=p->next;
00132               a[list_cnt]=p->filename;
00133               free(p);
00134               ++list_cnt;
00135        }
00136        a[list_cnt]=0;
00137        return (a);
00138 }
00139 
00140 void maildir_autoresponse_list_free(char **a)
00141 {
00142        unsigned i;
00143 
00144        for (i=0; a[i]; i++)
00145               free(a[i]);
00146        free(a);
00147 }
00148 
00149 static char *afilename(const char *maildir, const char *filename)
00150 {
00151        char *p;
00152 
00153        if (!maildir)
00154               maildir=".";
00155 
00156        if (strchr(filename, '.') || strchr(filename, '/')
00157            || strchr(filename, '\'') || strchr(filename, '\"')
00158            || strchr(filename, '*') || strchr(filename, '?')
00159            || strchr(filename, '[') || strchr(filename, ']')
00160            || strchr(filename, ' ') || strchr(filename, '\n')
00161            || strchr(filename, '\t') || strchr(filename, '\r')
00162            || strchr(filename, '~') || !*filename)
00163        {
00164               errno=EINVAL;
00165               return (NULL);
00166        }
00167 
00168        p=malloc(strlen(maildir)+strlen(filename)+
00169                sizeof("/autoresponsesXXXXXXXXXXXXXXXXXXXXXXXX"));
00170 
00171        if (!p)
00172               return (NULL);
00173        return (strcat(strcat(strcpy(p, maildir), "/autoresponses/"),
00174                      filename));
00175 }
00176 
00177 int maildir_autoresponse_validate(const char *maildir, const char *filename)
00178 {
00179        char *p=afilename(maildir, filename);
00180 
00181        if (!p)
00182               return (-1);
00183        free(p);
00184        return (0);
00185 }
00186 
00187 /* Delete autoreply scratch file (optionally the autoreply file itself) */
00188 
00189 static void deletefiles(const char *dir, const char *filename, int deleteall)
00190 {
00191        DIR *dirp=opendir(dir);
00192        struct dirent *de;
00193        int l=strlen(filename);
00194 
00195        if (!dirp)
00196               return;
00197 
00198        while ((de=readdir(dirp)) != 0)
00199        {
00200               char *q;
00201 
00202               if (strncmp(de->d_name, filename, l))
00203                      continue;
00204 
00205               if (de->d_name[l] == 0)
00206               {
00207                      if (!deleteall)
00208                             continue;
00209               }
00210               else if (de->d_name[l] != '.')
00211                      continue;
00212 
00213               q=malloc(strlen(dir)+strlen(de->d_name)+2);
00214 
00215               if (q)
00216               {
00217                      unlink(strcat(strcat(strcpy(q, dir), "/"),de->d_name));
00218                      free(q);
00219               }
00220        }
00221        closedir(dirp);
00222 }
00223 
00224 void maildir_autoresponse_delete(const char *maildir, const char *filename)
00225 {
00226        char *p=afilename(maildir, filename);
00227 
00228        char *q;
00229 
00230        if (!p)
00231               return;
00232 
00233        q=strrchr(p, '/');
00234        *q++=0;
00235 
00236        deletefiles(p, q, 1);
00237        free(p);
00238 }
00239 
00240 static void read_quota(struct maildir_autoresponse_quota *q, const char *f)
00241 {
00242        char buf[BUFSIZ];
00243        FILE *fp;
00244        const char *p;
00245 
00246        if ((fp=fopen(f, "r")) == NULL)
00247               return;
00248        if (fgets(buf, sizeof(buf), fp) == NULL)
00249        {
00250               fclose(fp);
00251               return;
00252        }
00253        fclose(fp);
00254 
00255        for (p=buf; *p; )
00256        {
00257               if (*p == 'C')
00258               {
00259                      q->files=0;
00260                      for ( ++p; *p; ++p)
00261                      {
00262                             if (!isdigit((int)(unsigned char)*p))
00263                                    break;
00264                             q->files=q->files * 10 + (*p-'0');
00265                      }
00266                      continue;
00267               }
00268 
00269               if (*p == 'S')
00270               {
00271                      q->bytes=0;
00272                      for ( ++p; *p; ++p)
00273                      {
00274                             if (!isdigit((int)(unsigned char)*p))
00275                                    break;
00276                             q->bytes=q->bytes * 10 + (*p-'0');
00277                      }
00278                      continue;
00279               }
00280               ++p;
00281        }
00282 }
00283 
00284 static int get_quota(struct maildir_autoresponse_quota *q, const char *maildir)
00285 {
00286        char *p;
00287 
00288        q->files=0;
00289        q->bytes=0;
00290        read_quota(q, AUTORESPONSEQUOTA);
00291 
00292        if (!maildir)
00293               maildir=".";
00294 
00295        p=malloc(strlen(maildir)+sizeof("/autoresponsesquota"));
00296        if (!p)
00297               return (-1);
00298        strcat(strcpy(p, maildir), "/autoresponsesquota");
00299        read_quota(q, p);
00300        free(p);
00301        return (0);
00302 }
00303 
00304 static void add_quota(struct maildir_autoresponse_quota *q, const char *file, int sign)
00305 {
00306        struct stat stat_buf;
00307 
00308        if (stat(file, &stat_buf))
00309               return;
00310        q->files += sign;
00311        q->bytes += (long)stat_buf.st_size*sign;
00312 }
00313 
00314 static int calc_quota(struct maildir_autoresponse_quota *q, const char *maildir)
00315 {
00316        char *p;
00317        DIR *dirp;
00318        struct dirent *de;
00319 
00320        q->files=0;
00321        q->bytes=0;
00322 
00323        if (!maildir)
00324               maildir=".";
00325 
00326        p=malloc(strlen(maildir)+sizeof("/autoresponses"));
00327        if (!p)
00328               return (-1);
00329        strcat(strcpy(p, maildir), "/autoresponses");
00330        dirp=opendir(p);
00331        free(p);
00332        if (!dirp)
00333               return (0);
00334        while ((de=readdir(dirp)) != 0)
00335        {
00336               if (strchr(de->d_name, '.'))
00337                      continue;
00338 
00339               p=malloc(strlen(maildir)+strlen(de->d_name)
00340                       +sizeof("/autoresponses/"));
00341               if (!p)
00342               {
00343                      closedir(dirp);
00344                      return (-1);
00345               }
00346 
00347               strcat(strcat(strcpy(p, maildir), "/autoresponses/"),
00348                      de->d_name);
00349               add_quota(q, p, 1);
00350               free(p);
00351        }
00352        closedir(dirp);
00353        return (0);
00354 }
00355 
00356 static int check_quota(struct maildir_autoresponse_quota *setquota,
00357                      struct maildir_autoresponse_quota *newquota)
00358 {
00359        if (setquota->files > 0 && newquota->files > setquota->files)
00360               return (-1);
00361        if (setquota->bytes > 0 && newquota->bytes > setquota->bytes)
00362               return (-1);
00363        return (0);
00364 }
00365 
00366 FILE *maildir_autoresponse_create(const char *maildir, const char *filename)
00367 {
00368        char *p=afilename(maildir, filename);
00369        FILE *fp;
00370        char *q;
00371 
00372        if (!p)
00373               return (NULL);
00374 
00375        strcat(p, ".tmp");
00376        fp=fopen(p, "w");
00377 
00378        if (!fp)      /* Perhaps we need to create the autoresponse dir? */
00379        {
00380               q=strrchr(p, '/');
00381               *q=0;
00382               mkdir(p, 0700);
00383               *q='/';
00384               fp=fopen(p, "w");
00385        }
00386        free(p);
00387        return (fp);
00388 }
00389 
00390 int maildir_autoresponse_create_finish(const char *maildir, const char *filename,
00391                             FILE *fp)
00392 {
00393        char *p, *q;
00394        struct maildir_autoresponse_quota set_quota, new_quota;
00395 
00396        fclose(fp);
00397        p=afilename(maildir, filename);
00398 
00399        if (!p)
00400               return (0);
00401        q=strdup(p);
00402 
00403        if (q)
00404        {
00405               if (get_quota(&set_quota, maildir)
00406                   || calc_quota(&new_quota, maildir))
00407               {
00408                      strcat(p, ".tmp");
00409                      unlink(p);
00410                      free(q);
00411                      free(p);
00412                      return (-1);
00413               }
00414 
00415               add_quota(&new_quota, p, -1);
00416               strcat(p, ".tmp");
00417               add_quota(&new_quota, p, 1);
00418               if (check_quota(&set_quota, &new_quota))
00419               {
00420                      unlink(p);
00421                      free(p);
00422                      free(q);
00423                      errno=ENOSPC;
00424                      return (-1);
00425               }
00426 
00427               rename(p, q);
00428               free(q);
00429        }
00430        free(p);
00431        return (0);
00432 }
00433 
00434 FILE *maildir_autoresponse_open(const char *maildir, const char *filename)
00435 {
00436        char *p=afilename(maildir, filename);
00437        FILE *fp;
00438 
00439        if (!p)
00440               return (NULL);
00441 
00442        fp=fopen(p, "r");
00443        free(p);
00444        return (fp);
00445 }