Back to index

courier  0.68.2
faxstub.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2002 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      "courier.h"
00010 #include      "comfax.h"
00011 #include      "rw.h"
00012 #include      "rfc822/rfc822.h"
00013 #include      <sys/types.h>
00014 #include      <sys/stat.h>
00015 #include      <stdlib.h>
00016 #include      <string.h>
00017 #include      <ctype.h>
00018 #if    HAVE_UNISTD_H
00019 #include      <unistd.h>
00020 #endif
00021 
00022 #define VALIDCHAR(c) strchr("0123456789ABCD#+*-,W", toupper((unsigned char)(c)))
00023 
00024 static void rw_fax(struct rw_info *, void (*)(struct rw_info *));
00025 static void rw_del_fax(struct rw_info *, void (*)(struct rw_info *),
00026               void (*)(struct rw_info *, const struct rfc822token *,
00027                      const struct rfc822token *));
00028 
00029 struct rw_list *fax_rw_install(const struct rw_install_info *p)
00030 {
00031 static struct rw_list fax_info={0, "module.fax - " COURIER_COPYRIGHT,
00032                             rw_fax, rw_del_fax, 0};
00033 
00034        return (&fax_info);
00035 }
00036 
00037 const char *fax_rw_init()
00038 {
00039        return (0);
00040 }
00041 
00042 static int is_fax(struct rfc822token **headptr,
00043                 struct rfc822token ***atptr,
00044                 struct rfc822token *faxhostt)
00045 {
00046        struct rfc822token **p=NULL, *q;
00047        int dummy;
00048 
00049        for ( ; *headptr; headptr=&(*headptr)->next)
00050               if ( (*headptr)->token == '@')
00051                      p=headptr;
00052 
00053        if (!p)
00054        {
00055               return (0);
00056        }
00057 
00058        q= (*p)->next;
00059 
00060        if (!q || q->next || q->token != 0)
00061               return (0);
00062 
00063        if (comgetfaxoptsn(q->ptr, q->len, &dummy) == 0)
00064        {
00065               *faxhostt= *q;
00066               *atptr=p;
00067               return (1);
00068        }
00069 
00070        return (0);
00071 }
00072 
00073 
00074 static void rw_fax(struct rw_info *p, void (*func)(struct rw_info *))
00075 {
00076        struct rfc822token **dummy, dummy2;
00077 
00078        if (is_fax(&p->ptr, &dummy, &dummy2))
00079               return;
00080 
00081        (*func)(p);
00082 }
00083 
00084 #define       MAXLEN 80
00085 
00086 #define MATCH_PREFIX 1
00087 #define MATCH_REPEAT 2
00088 
00089 /*
00090 ** Poor man's pattern matcher.
00091 */
00092 
00093 static int matches(const char *num, const char *pat, int *match_buf,
00094                  int flags)
00095 {
00096        int p;
00097 
00098        int l=strlen(num);
00099        int i;
00100 
00101        int next_string_num=0;
00102        int in_string=0;
00103 
00104        for (i=0; i<l; i++)
00105               match_buf[i]= -1;
00106 
00107        p=0;
00108 
00109        while (*pat)
00110        {
00111               int c;
00112 
00113               if (*pat == '(')
00114               {
00115                      if (in_string)
00116                             return (0);   /* Nested ( are N/A */
00117 
00118                      ++in_string;
00119                      ++next_string_num;
00120                      ++pat;
00121                      continue;
00122               }
00123 
00124               if (*pat == ')' && in_string > 0)
00125               {
00126                      --in_string;
00127                      ++pat;
00128                      continue;
00129               }
00130 
00131               if (!num[p])
00132                      return (0);
00133 
00134               c=toupper((unsigned char)*pat);
00135 
00136               if (c == 'N')
00137               {
00138                      if (!isdigit((int)(unsigned char)num[p]))
00139                             return (0);
00140               }
00141               else if (c != '.')
00142                      if (toupper((int)(unsigned char)num[p]) != c)
00143                             return (0);
00144 
00145               if (in_string)
00146                      match_buf[p]=next_string_num;
00147               ++pat;
00148               ++p;
00149        }
00150 
00151        if (num[p])
00152        {
00153               if (!(flags & MATCH_PREFIX))
00154                      return (0);
00155 
00156               while (num[p])
00157               {
00158                      match_buf[p]=9;
00159                      ++p;
00160               }
00161        }
00162        return (1);
00163 }
00164 
00165 static char *rwfax(const char *a, const char *module, char *buffer)
00166 {
00167        static char *faxrc=0, *faxrcbuf;
00168        char *p;
00169        int matched_strings[MAXLEN];
00170        char *nextl;
00171 
00172        int accepted=0;
00173 
00174        if (!module)
00175               accepted=1;   /* Not called from SUBMIT, that's OK */
00176 
00177        /* The first time up, read the config file */
00178 
00179        if (!faxrc)
00180        {
00181               struct stat stat_buf;
00182               char *n=config_localfilename("faxrc");
00183               FILE *f=fopen(n, "r");
00184 
00185               free(n);
00186 
00187               if (!f)
00188                      return (NULL);
00189 
00190               if (fstat(fileno(f), &stat_buf) < 0
00191                   || fread ( (faxrc=courier_malloc(stat_buf.st_size+1)),
00192                             stat_buf.st_size, 1, f) != 1)
00193               {
00194                      clog_msg_prerrno();
00195                      fclose(f);
00196                      return (NULL);
00197               }
00198               faxrc[stat_buf.st_size] = 0;
00199               fclose(f);
00200               faxrcbuf=courier_malloc(stat_buf.st_size+1);
00201        }
00202 
00203        if (strlen(a) > MAXLEN)
00204               return (NULL);
00205 
00206        strcpy(buffer, a);
00207 
00208        /*
00209        ** DTMF '#' conflicts with the comment character in faxrc.
00210        ** Temporarily replace all #s by ~s, then restore them later.
00211        **
00212        ** Convert all the dashes to ,s, pluses to @s
00213        */
00214        for (p=buffer; *p; p++)
00215        {
00216               if (*p == '#')
00217                      *p='~';
00218 
00219               if (*p == '-')
00220                      *p=',';
00221 
00222               if (*p == '+')
00223                      *p='@';
00224        }
00225 
00226        strcpy(faxrcbuf, faxrc);
00227 
00228        for (p=nextl=faxrcbuf; *nextl; )
00229        {
00230               char *q;
00231 
00232               p=nextl;
00233 
00234               for (nextl=p; *nextl; nextl++)
00235               {
00236                      if (*nextl == '\n')
00237                      {
00238                             *nextl++ = 0;
00239                             break;
00240                      }
00241               }
00242 
00243               if ((q=strchr(p, '#')) != 0) *q=0;
00244 
00245               q=strtok(p, " \t\r");
00246               if (!q)
00247                      continue;
00248 
00249               if (strncmp(q, "rw", 2) == 0)
00250               {
00251                      int flags=0;
00252                      int cnt=0;
00253 
00254                      for (q += 2; *q; q++)
00255                      {
00256                             if (*q == '^')
00257                                    flags |= MATCH_PREFIX;
00258                             else if (*q == '*')
00259                                    flags |= MATCH_REPEAT;
00260                      }
00261 
00262                      q=strtok(NULL, " \t\r");
00263                      if (!q)
00264                             continue;
00265 
00266                      while (matches(buffer, q, matched_strings, flags))
00267                      {
00268                             char new_buffer[MAXLEN+1];
00269                             int i=0;
00270 
00271                             /* Build the replacement string */
00272 
00273                             q=strtok(NULL, " \t\r");
00274                             while (q && *q)
00275                             {
00276                                    int n;
00277                                    int j;
00278 
00279                                    if (*q != '$')
00280                                    {
00281                                           if (i >= MAXLEN)
00282                                                  return (NULL);
00283                                           new_buffer[i++] = *q;
00284                                           ++q;
00285                                           continue;
00286                                    }
00287                                    if (!*++q)
00288                                           continue;
00289 
00290                                    n= *q - '0';
00291                                    if (n < 0 || n > 9)
00292                                    {
00293                                           ++q;
00294                                           continue;
00295                                    }
00296 
00297                                    for (j=0; j<strlen(buffer); j++)
00298                                           if (matched_strings[j]  == n)
00299                                           {
00300                                                  if (i >= MAXLEN)
00301                                                         return(NULL);
00302                                                  new_buffer[i++]=
00303                                                         buffer[j];
00304                                           }
00305                                    ++q;
00306                             }
00307 
00308                             new_buffer[i]=0;
00309                             strcpy(buffer, new_buffer);
00310 
00311                             if (!(flags & MATCH_REPEAT))
00312                                    break;
00313 
00314                             if (++cnt > MAXLEN+10)
00315                                    break;
00316                      }
00317               }
00318               else if (strncmp(q, "accept", 6) == 0)
00319               {
00320                      int flags=0;
00321 
00322                      for (q += 6; *q; q++)
00323                      {
00324                             if (*q == '^')
00325                                    flags |= MATCH_PREFIX;
00326                      }
00327 
00328                      q=strtok(NULL, " \t\r");
00329 
00330                      if (!q)
00331                             continue;
00332 
00333                      if (!matches(buffer, q, matched_strings, flags))
00334                             continue;
00335 
00336                      q=strtok(NULL, " \t\r");
00337 
00338                      if (q && module && strcmp(q, module) == 0)
00339                             accepted=1;
00340                      continue;
00341               }
00342               else if (strncmp(q, "reject", 6) == 0)
00343               {
00344                      int flags=0;
00345 
00346                      for (q += 6; *q; q++)
00347                      {
00348                             if (*q == '^')
00349                                    flags |= MATCH_PREFIX;
00350                      }
00351 
00352                      q=strtok(NULL, " \t\r");
00353 
00354                      if (!q)
00355                             continue;
00356 
00357                      if (matches(buffer, q, matched_strings, flags))
00358                      {
00359                             q=strtok(NULL, " \t\r");
00360 
00361                             if (q && module && strcmp(q, module) == 0)
00362                                    return (0);
00363                      }
00364               }
00365        }
00366 
00367        for (p=buffer; *p; p++)
00368               if (*p == '~')
00369                      *p='#';
00370 
00371        if (!accepted)
00372               return (NULL);
00373 
00374        return (buffer);
00375 }
00376 
00377 static void rw_del_fax(struct rw_info *rwi,
00378                      void (*nextfunc)(struct rw_info *),
00379                      void (*delfunc)(struct rw_info *,
00380                                    const struct rfc822token *,
00381                                    const struct rfc822token *))
00382 {
00383        struct rfc822token **p;
00384        char *a, *b, *c;
00385        struct rfc822token t, ht;
00386        char curnum[MAXLEN+1];
00387 
00388        if (!is_fax(&rwi->ptr, &p, &ht))
00389        {
00390               (*nextfunc)(rwi);
00391               return;
00392        }
00393 
00394        *p=0;
00395 
00396        a=rfc822_gettok(rwi->ptr);
00397 
00398        if (!a)
00399        {
00400               clog_msg_errno();
00401               (*rwi->err_func)(550, "Out of memory", rwi);
00402               return;
00403        }
00404 
00405        for (b=c=a; *b; b++)
00406        {
00407               if (VALIDCHAR(*b))
00408                      *c++ = *b;
00409        }
00410        *c=0;
00411        if (*a == 0)
00412        {
00413               free(a);
00414               (*rwi->err_func)(550, "Invalid fax phone number", rwi);
00415               return;
00416        }
00417 
00418        b=rwfax(a, rwi->mode & RW_SUBMIT ? rwi->smodule:NULL, curnum);
00419        free(a);
00420 
00421        if (!b || !*b)
00422        {
00423               (*rwi->err_func)(550, "Invalid fax phone number", rwi);
00424               return;
00425        }
00426 
00427        t.token=0;
00428        t.next=0;
00429        t.ptr=b;
00430        t.len=strlen(b);
00431 
00432        (*delfunc)(rwi, &ht, &t);
00433 }