ftp.nice.ch/pub/next/unix/communication/ft_bbs.1.0.s.tar.gz#/ft_bbs-1.0/mail.c

This is mail.c in view mode; [Download] [Up]

/* $Id: mail.c,v 1.1 1995/12/19 19:30:47 eilts Exp eilts $ */
#include "bbs.h"

int mimerecode(const char *file, const char *encoding,
               const confrecordtyp *confrecord)
{
  char scratch[PATH_MAX+1], sstr[3], c;
  FILE *infp, *outfp;

  if (encoding == NULL) {
    return 0;
  }
  if (strcasecmp(encoding,"quoted-printable") == 0) {
    if ((infp=fopen(file,"r")) == NULL) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","minerecode",
               "fopen %s: %m",file);
      return -1;
    }
    scratchfilename(scratch,"mime",NULL,confrecord->maildir);
    if ((outfp=fopen(scratch,"w")) == NULL) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","minerecode",
               "fopen %s: %m",scratch);
      return -1;
    }
   sstr[2] = '\0';
    while ((c=getc(infp)) != EOF) {
      if (c == '=') {
        if ((sstr[0]=getc(infp)) == EOF)  return -1;
        if ((sstr[1]=getc(infp)) == EOF)  return -1;
        if (strcmp(sstr,AE_U_QP) == 0) {
          putc(AE_U_L1,outfp);
        }
        else if (strcmp(sstr,AE_L_QP) == 0) {
          putc(AE_L_L1,outfp);
        }
        else if (strcmp(sstr,OE_U_QP) == 0) {
          putc(OE_U_L1,outfp);
        }
        else if (strcmp(sstr,OE_L_QP) == 0) {
          putc(OE_L_L1,outfp);
        }
        else if (strcmp(sstr,UE_U_QP) == 0) {
          putc(UE_U_L1,outfp);
        }
        else if (strcmp(sstr,UE_L_QP) == 0) {
          putc(UE_L_L1,outfp);
        }
        else if (strcmp(sstr,SS_QP) == 0) {
          putc(SS_L1,outfp);
        }
        else if (strcmp(sstr,EQCHAR_QP) == 0) {
          putc('=',outfp);
        }
        else {
          putc('=',outfp);
          fputs(sstr,outfp);
        }
      }
      else {
        putc(c,outfp);
      }
    }
    fclose(infp);
    fclose(outfp);
    if (rename(scratch,file) < 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","minerecode",
               "rename %s to %s: %m",scratch,file);
      return -1;
    }
    chmod(file,0600);
  }
  return 0;
}


int addresstyp(const char *address, const confrecordtyp *confrecord)
  /*
  Returnwerte:
    -1: falscher Addresssyntax
     0: Message-Addresse
     1: Sysop
     2: lokale E-Mail Addresse
     3: nichtlokale E-Mail Addresse
  */
{
  int n, k, rw = 0;
  char *sp, *host, *splits[MAXARGS+1], addr[ARG_MAX+1], dest[S_STRLEN+1],
       realname[S_STRLEN+1];
  struct hostent *hostentp;
  extern int h_errno;

  strmaxcpy(addr,address,ARG_MAX);
  splitstring(splits,addr,',',MAXARGS);

  for (k=0; splits[k]!=NULL; k++) {
    parseaddrline(dest,realname,splits[k]);
    n = -1;
    if (strchr(dest,'!') != NULL) {
      n = -1;
    }
    else if (strcmp(dest,confrecord->sysop) == 0) {
      n = 1;
    }
    else if ((host=strchr(dest,'@')) != NULL) {
      host++;
      if ((hostentp=gethostbyname(host)) == NULL) {
	switch (h_errno) {
	case HOST_NOT_FOUND:
	  sp = "Authoritative Answer Host not found";
	  break;
	case TRY_AGAIN:
	  sp = "Non-Authoritive Host not found, or SERVERFAIL";
	  break;
	case NO_RECOVERY:
	  sp = "Non recoverable errors, FORMERR, REFUSED, NOTIMP";
	  break;
	case NO_DATA:
	  sp = "Valid name, no data record of requested type";
	  break;
	default:
	  sp = "failed";
	}
/*
	errormsg(E_LOGFILE|E_USER,confrecord,"bbs","addresstyp",
		  "gethostbyname %s: %s",host,sp);
	return(-1);
*/
      }
      if (hostentp != NULL &&
          strcmp(hostentp->h_name,confrecord->hostname) == 0) {
        n = 2;
      }
      else {
        n = 3;
      }
    }
    else {
      n = 0;
    }
    if (n < 0)  return n;
    if (n > rw)  rw = n;
  }
  return rw;
}


int mailreply(char cmd[], const int nr, const char *msg_id,
              const menuetyp bbsmenue[], const chrootrecordtyp *chrootrecord,
              const confrecordtyp *confrecord)
{
  int n;
  char subject[STRLEN+1], addr[ARG_MAX+1], scratch[PATH_MAX+1], key,
       *hdrbuf = NULL;
  mailheadertyp mailhdr;
  
  if (makereplytext(scratch,&mailhdr,nr,msg_id,hdrbuf,confrecord) < 0) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","reader_c",
             "cannot copy message Nr: %d, Id: %s",nr,msg_id);
    n = -1;
  }
  else {
    strcpy(subject,"Re: ");
    strmaxcat(subject,mailhdr.subject,STRLEN-1);
    if (*mailhdr.reply_to != '\0') {
      strcpy(addr,mailhdr.reply_to);
    }
    else {
      strcpy(addr,mailhdr.from);
    }
    if (*mailhdr.cc != '\0') {
      key = getkeyonprompt(msg("mail",0,confrecord->userrecord.lang),
                           "JYN",TRUE,FALSE,NULL,confrecord);
      if (key == 'Y' || key == 'J') {
        strcat(addr,",");
        strcat(addr,mailhdr.cc);
      }
    }
    if ((n=addresstyp(addr,confrecord)) < 0)  return n;
    if (n < 2) {
      key = getkeyonprompt(msg("mail",1,confrecord->userrecord.lang),
                           "NME",TRUE,FALSE,NULL,confrecord);
      if (key == 'E') {
        key = EMAIL_KEY;
      }
      else {
        key = MESSAGE_KEY;
      }
    }
    else {
      key = EMAIL_KEY;
    }
    *cmd = '\0';
    n = 0;
    while (bbsmenue[n].key!='\0') {
      if (bbsmenue[n].key==key && *(bbsmenue[n].dec)!='\0') {
        strcpy(cmd,bbsmenue[n].cmd);
        break;
      }
      n++;
    }
    if (key == MESSAGE_KEY) {
      n = sendmessage_c(cmd,scratch,addr,subject,chrootrecord, confrecord);
    }
    else {
      n = sendmail_c(cmd,scratch,addr,subject,FALSE,chrootrecord,confrecord);
    }
  }
  if (hdrbuf != NULL)  free(hdrbuf);
  return n;
}


int makereplytext(char scratch[], mailheadertyp *mailhdr, const int nr,
                  const char *mesg_id, char *hdrbuf,
		  const confrecordtyp *confrecord)
{
  char path[PATH_MAX+1], zeile[STRLEN+1];
  FILE *fp, *sfp;
  
  scratch[0] = '\0';
  if (getmessage(path,nr,mesg_id,confrecord) < 0) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","makereplytext",
	      "message Nr %d, Msg-ID %s, not found",nr,mesg_id);
    return -1;
  }
  if ((fp=fopen(path,"r")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","makereplytext",
             "fopen %s: %m",path);
    return -1;
  }
  unlink(path);
  if ((hdrbuf=parsemailheader(mailhdr,fp,confrecord)) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","makereplytext",
             "parsemailheader of %s failed",path);
    return -1;
  }
  rewind(fp);
  scratchfilename(scratch,"reply.",NULL,confrecord->scratchdir);
  if ((sfp=fopen(scratch,"w")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","makereplytext",
             "fopen %s: %m",scratch);
    return -1;
  }
  fprintf(sfp,"In reply of:\n");
  while (fgetnln(zeile,STRLEN,fp) >= 0) {
    fputs("> ",sfp);
    fputs(zeile,sfp);
    putc('\n',sfp);
  }
  fclose(fp);
  fclose(sfp);
  return 0;
}


#ifndef NO_REGCOMP
#define NO_RE_COMP
#endif
int checkmailperms(const char *address, const confrecordtyp *confrecord)
{
  int a_anz, p_anz, p, k, n;
  char *asplits[MAXARGS+1], *psplits[MAXARGS+1], astr[ARG_MAX+1],
       pstr[STRLEN+1], pattern[STRLEN+1], *psp, c;
#ifdef NeXT
  char hoststr[S_STRLEN+1];
#endif
  const char *sp;
#ifndef NO_REGCOMP
  regex_t preg;
  regmatch_t pmatch[1];
#else
#endif
  struct hostent *hostentp;

  strmaxcpy(astr,address,ARG_MAX);
  a_anz = splitstring(asplits,astr,',',MAXARGS);
  for (k=0; k<a_anz; k++) {
    parseaddrline(pstr,pattern,asplits[k]);
    strcpy(asplits[k],pstr);
  }
  strmaxcpy(pstr,confrecord->userrecord.permittions,STRLEN);
  p_anz = splitstring(psplits,pstr,':',MAXARGS);
  for (n=0; psplits[n] != NULL; n++) {
    if (*psplits[n] == 'N' || *psplits[n] == 'P') {
      continue;
    }
    else if (*psplits[n] == 'E') {
      strcpy(pattern,&(psplits[n][1]));
    }
    else if (strcmp(psplits[n],"L") == 0) {
      for (k=0; k < a_anz; k++) {
	if ((sp=strchr(asplits[k],'@')) != NULL) {
          sp++;
        }
        else if (strchr(asplits[k],'!') == NULL) {
          sp = confrecord->hostname;
        }
        else {
          sp = "@";
        }
#ifdef NeXT
	strmaxcpy(hoststr,sp,S_STRLEN);
	if ((hostentp=gethostbyname(hoststr)) != NULL &&
#else
	if ((hostentp=gethostbyname(sp)) != NULL &&
#endif
	    strcmp(confrecord->hostname,hostentp->h_name) == 0) {
	  asplits[k--] = asplits[--a_anz];
	  asplits[a_anz] = NULL;
	}
      }
    }
    else {
      p = 0;
      pattern[p++] = '^';
      psp = psplits[n];
      while ((c=*psp++) != '\0') {
        switch (c) {
          case '.':
          pattern[p++] = '\\';
          pattern[p++] = '.';
          break;
          case '*':
          pattern[p++] = '.';
          pattern[p++] = '*';
          break;
#ifndef NO_REGCOMP
          case '?':
          pattern[p++] = '.';
          break;
#endif
          default:
          pattern[p++] = c;
        }
      }
      pattern[p++] = '$';
      pattern[p] = '\0';
    }

#ifndef NO_REGCOMP
    if ((k=regcomp(&preg,pattern,REG_ICASE|REG_EXTENDED|REG_NOSUB)) != 0) {
      regerror(k,&preg,pattern,STRLEN);
#else
#ifndef NO_RE_COMP
    if ((sp=re_comp(pattern)) != (char *)0) {
      strmaxcpy(pattern,sp,STRLEN);
#endif
#endif
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","checkmailperms",
               "wrong pattern: %s",pattern);
      return(-1);
    }
    
    for (k=0; k < a_anz; k++) {
#ifndef NO_REGCOMP
      if ((p=regexec(&preg,asplits[k],0,pmatch,0)) == 0) {
#else
#ifndef NO_RE_COMP
      lowercases(asplits[k]);
      if ((p=re_exec(asplits[k])) == 1) {
#endif
#endif
        asplits[k--] = asplits[--a_anz];
        asplits[a_anz] = NULL;
      }
#ifndef NO_REGCOMP
      else if (p != REG_NOMATCH) {
        regerror(p,&preg,pattern,STRLEN);
        errormsg(E_LOGFILE|E_USER,confrecord,"bbs","checkmailperms",
                 "regexec: %s",pattern);
        regfree(&preg);
#else
#ifndef NO_RE_COMP
      else if (p < 0) {
        errormsg(E_LOGFILE|E_USER,confrecord,"bbs","checkmailperms",
	  	  "re_exec: internal error");
#endif
#endif
        return(-1);
      }
    }
#ifndef NO_REGCOMP
    regfree(&preg);
#endif
  }
  return a_anz;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.