⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmdf.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  if (!ret || fsync (fd)) {	/* force out the update */    sprintf (LOCAL->buf,"Message copy failed: %s",strerror (errno));    ftruncate (fd,sbuf.st_size);    ret = NIL;  }				/* force UIDVALIDITY assignment now */  if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0);				/* return sets if doing COPYUID */  if (cu && ret) (*cu) (stream,mailbox,tstream->uid_validity,source,dest);  else {			/* flush any sets we may have built */    mail_free_searchset (&source);    mail_free_searchset (&dest);  }  tp[1] = time (0);		/* set mtime to now */  if (ret) tp[0] = tp[1] - 1;	/* set atime to now-1 if successful copy */  else tp[0] =			/* else preserve \Marked status */	 ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?	 sbuf.st_atime : tp[1];  utime (file,tp);		/* set the times */  mmdf_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  if (tstream) {		/* update last UID if we can */    MMDFLOCAL *local = (MMDFLOCAL *) tstream->local;    local->dirty = T;		/* do a rewrite */    local->appending = T;	/* but not at the cost of marking as old */    tstream = mail_close (tstream);  }				/* log the error */  if (!ret) MM_LOG (LOCAL->buf,ERROR);				/* delete if requested message */  else if (options & CP_MOVE) for (i = 1; i <= stream->nmsgs; i++)    if ((elt = mail_elt (stream,i))->sequence)      elt->deleted = elt->private.dirty = LOCAL->dirty = T;  MM_NOCRITICAL (stream);	/* release critical */  return ret;}/* MMDF mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */#define BUFLEN 8*MAILTMPLENlong mmdf_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct stat sbuf;  int fd;  unsigned long i;  char *flags,*date,buf[BUFLEN],tmp[MAILTMPLEN],file[MAILTMPLEN];  time_t tp[2];  FILE *sf,*df;  MESSAGECACHE elt;  DOTLOCK lock;  STRING *message;  unsigned long uidlocation = 0;  appenduid_t au = (appenduid_t)    (mail_parameters (NIL,GET_USERHASNOLIFE,NIL) ? NIL :     mail_parameters (NIL,GET_APPENDUID,NIL));  SEARCHSET *dst = au ? mail_newsearchset () : NIL;  long ret = LONGT;  MAILSTREAM *tstream = NIL;				/* default stream to prototype */  if (!stream) {		/* stream specified? */    stream = &mmdfproto;	/* no, default stream to prototype */    for (i = 0; i < NUSERFLAGS && stream->user_flags[i]; ++i)      fs_give ((void **) &stream->user_flags[i]);  }  if (!mmdf_valid (mailbox)) switch (errno) {  case ENOENT:			/* no such file? */    if (compare_cstring (mailbox,"INBOX")) {      MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }    mmdf_create (NIL,"INBOX");	/* create empty INBOX */  case 0:			/* merely empty file? */    tstream = stream;    break;  case EACCES:			/* file protected */    sprintf (tmp,"Can't access destination: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  case EINVAL:    sprintf (tmp,"Invalid MMDF-format mailbox name: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a MMDF-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get sniffing stream for keywords */  else if (!(tstream = mail_open (NIL,mailbox,				  OP_READONLY|OP_SILENT|OP_NOKOD|OP_SNIFF))) {    sprintf (tmp,"Unable to examine mailbox for APPEND: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!MM_APPEND (af) (tstream,data,&flags,&date,&message)) return NIL;  if (!(sf = tmpfile ())) {	/* must have scratch file */    sprintf (tmp,".%lx.%lx",(unsigned long) time (0),(unsigned long)getpid ());    if (!stat (tmp,&sbuf) || !(sf = fopen (tmp,"wb+"))) {      sprintf (tmp,"Unable to create scratch file: %.80s",strerror (errno));      MM_LOG (tmp,ERROR);      return NIL;    }    unlink (tmp);  }  do {				/* parse date */    if (!date) rfc822_date (date = tmp);    if (!mail_parse_date (&elt,date)) {      sprintf (tmp,"Bad date in append: %.80s",date);      MM_LOG (tmp,ERROR);    }    else {			/* user wants to suppress time zones? */      if (mail_parameters (NIL,GET_NOTIMEZONES,NIL)) {	time_t when = mail_longdate (&elt);	date = ctime (&when);	/* use traditional date */      }				/* use POSIX-style date */      else date = mail_cdate (tmp,&elt);      if (!SIZE (message)) MM_LOG ("Append of zero-length message",ERROR);      else if (!mmdf_collect_msg (tstream,sf,flags,date,message)) {	sprintf (tmp,"Error writing scratch file: %.80s",strerror (errno));	MM_LOG (tmp,ERROR);      }				/* get next message */      else if (MM_APPEND (af) (tstream,data,&flags,&date,&message)) continue;    }    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  } while (message);		/* until no more messages */  if (fflush (sf)) {    sprintf (tmp,"Error finishing scratch file: %.80s",strerror (errno));    MM_LOG (tmp,ERROR);    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  }  i = ftell (sf);		/* size of scratch file */  if (tstream != stream) tstream = mail_close (tstream);  MM_CRITICAL (stream);		/* go critical */				/* try to open readwrite for UIDPLUS */  if ((tstream = mail_open_work (&mmdfdriver,NIL,mailbox,				 OP_SILENT|OP_NOKOD)) && tstream->rdonly)    tstream = mail_close (tstream);  if (au && !tstream) {		/* wanted an APPENDUID? */    sprintf (tmp,"Unable to re-open mailbox for APPENDUID: %.80s",mailbox);    MM_LOG (tmp,WARN);    au = NIL;  }  if (((fd = mmdf_lock (dummy_file (file,mailbox),O_WRONLY|O_APPEND,			(long) mail_parameters (NIL,GET_MBXPROTECTION,NIL),			&lock,LOCK_EX)) < 0) ||      !(df = fdopen (fd,"ab"))) {    MM_NOCRITICAL (stream);	/* done with critical */    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }  fstat (fd,&sbuf);		/* get current file size */  rewind (sf);  tp[1] = time (0);		/* set mtime to now */				/* write all messages */  if (!mmdf_append_msgs (tstream,sf,df,au ? dst : NIL) ||      (fflush (df) == EOF) || fsync (fd)) {    sprintf (buf,"Message append failed: %s",strerror (errno));    MM_LOG (buf,ERROR);    ftruncate (fd,sbuf.st_size);    tp[0] =			/* preserve \Marked status */      ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?      sbuf.st_atime : tp[1];    ret = NIL;			/* return error */  }  else tp[0] = tp[1] - 1;	/* set atime to now-1 if successful copy */  utime (file,tp);		/* set the times */  fclose (sf);			/* done with scratch file */				/* force UIDVALIDITY assignment now */  if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0);				/* return sets if doing APPENDUID */  if (au && ret) (*au) (mailbox,tstream->uid_validity,dst);  else mail_free_searchset (&dst);  mmdf_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  fclose (df);  if (tstream) {		/* update last UID if we can */    MMDFLOCAL *local = (MMDFLOCAL *) tstream->local;    local->dirty = T;		/* do a rewrite */    local->appending = T;	/* but not at the cost of marking as old */    tstream = mail_close (tstream);  }  MM_NOCRITICAL (stream);	/* release critical */  return ret;}/* Collect and write single message to append scratch file * Accepts: MAIL stream *	    scratch file *	    flags *	    date *	    message stringstruct * Returns: NIL if write error, else T */int mmdf_collect_msg (MAILSTREAM *stream,FILE *sf,char *flags,char *date,  		     STRING *msg){  unsigned char *s,*t;  unsigned long uf;  long f = mail_parse_flags (stream,flags,&uf);				/* write metadata, note date ends with NL */  if (fprintf (sf,"%ld %lu %s",f,SIZE (msg) + 1,date) < 0) return NIL;  while (uf)			/* write user flags */        if ((s = stream->user_flags[find_rightmost_bit (&uf)]) &&	(fprintf (sf," %s",s) < 0)) return NIL;  if (putc ('\n',sf) == EOF) return NIL;  while (SIZE (msg)) {		/* copy text to scratch file */    for (s = (unsigned char *) msg->curpos, t = s + msg->cursize; s < t; ++s)      if (!*s) *s = 0x80;	/* disallow NUL */				/* write buffered text */    if (fwrite (msg->curpos,1,msg->cursize,sf) == msg->cursize)      SETPOS (msg,GETPOS (msg) + msg->cursize);    else return NIL;		/* failed */  }				/* write trailing newline and return */  return (putc ('\n',sf) == EOF) ? NIL : T;}/* Append messages from scratch file to mailbox * Accepts: MAIL stream *	    source file *	    destination file *	    uidset to update if non-NIL * Returns: T if success, NIL if failure */int mmdf_append_msgs (MAILSTREAM *stream,FILE *sf,FILE *df,SEARCHSET *set){  int c;  long f;  unsigned long i,j;  char *x,tmp[MAILTMPLEN];  int hdrp = T;				/* get message metadata line */  while (fgets (tmp,MAILTMPLEN,sf)) {    if (!(isdigit (tmp[0]) && strchr (tmp,'\n'))) return NIL;    f = strtol (tmp,&x,10);	/* get flags */    if (!((*x++ == ' ') && isdigit (*x))) return NIL;    i = strtoul (x,&x,10);	/* get message size */    if ((*x++ != ' ') ||	/* build initial header */	(fprintf (df,"%sFrom %s@%s %sStatus: ",mmdfhdr,myusername(),		  mylocalhost(),x) < 0) ||	(f&fSEEN && (putc ('R',df) == EOF)) ||	(fputs ("\nX-Status: ",df) == EOF) ||	(f&fDELETED && (putc ('D',df) == EOF)) ||	(f&fFLAGGED && (putc ('F',df) == EOF)) ||	(f&fANSWERED && (putc ('A',df) == EOF)) ||	(f&fDRAFT && (putc ('T',df) == EOF)) ||	(fputs ("\nX-Keywords:",df) == EOF)) return NIL;				/* copy keywords */    while ((c = getc (sf)) != '\n') switch (c) {    case EOF:      return NIL;    default:      if (putc (c,df) == EOF) return NIL;    }    if ((putc ('\n',df) == EOF) ||	(set && (fprintf (df,"X-UID: %lu\n",++(stream->uid_last)) < 0)))      return NIL;    for (c = '\n'; i && fgets (tmp,MAILTMPLEN,sf); c = tmp[j-1]) {				/* get read line length */      if (i < (j = strlen (tmp))) fatal ("mmdf_append_msgs overrun");      i -= j;			/* number of bytes left */				/* squish out ^A and CRs (note copies NUL) */      for (x = tmp; x = strpbrk (x,"\01\r"); --j) memmove (x,x+1,j-(x-tmp));      if (!j) continue;		/* do nothing if line emptied */				/* start of line? */      if ((c == '\n')) switch (tmp[0]) {      case 'S': case 's':	/* possible "Status:" */	if (hdrp && (j > 6) && ((tmp[1] == 't') || (tmp[1] == 'T')) &&	    ((tmp[2] == 'a') || (tmp[2] == 'A')) &&	    ((tmp[3] == 't') || (tmp[3] == 'T')) &&	    ((tmp[4] == 'u') || (tmp[4] == 'U')) &&	    ((tmp[5] == 's') || (tmp[5] == 'S')) && (tmp[6] == ':') &&	    (fputs ("X-Original-",df) == EOF)) return NIL;	break;      case 'X': case 'x':	/* possible X-??? header */	if (hdrp && (tmp[1] == '-') &&				/* possible X-UID: */	    (((j > 5) && ((tmp[2] == 'U') || (tmp[2] == 'u')) &&	      ((tmp[3] == 'I') || (tmp[3] == 'i')) &&	      ((tmp[4] == 'D') || (tmp[4] == 'd')) && (tmp[5] == ':')) ||				/* possible X-IMAP: */	     ((j > 6) && ((tmp[2] == 'I') || (tmp[2] == 'i')) &&	      ((tmp[3] == 'M') || (tmp[3] == 'm')) &&	      ((tmp[4] == 'A') || (tmp[4] == 'a')) &&	      ((tmp[5] == 'P') || (tmp[5] == 'p')) &&	      ((tmp[6] == ':') ||				/* or X-IMAPbase: */	       ((j > 10) && ((tmp[6] == 'b') || (tmp[6] == 'B')) &&		((tmp[7] == 'a') || (tmp[7] == 'A')) &&		((tmp[8] == 's') || (tmp[8] == 'S')) &&		((tmp[9] == 'e') || (tmp[9] == 'E')) && (tmp[10] == ':')))) ||				/* possible X-Status: */	     ((j > 8) && ((tmp[2] == 'S') || (tmp[2] == 's')) &&	      ((tmp[3] == 't') || (tmp[3] == 'T')) &&	      ((tmp[4] == 'a') || (tmp[4] == 'A')) &&	      ((tmp[5] == 't') || (tmp[5] == 'T')) &&	      ((tmp[6] == 'u') || (tmp[6] == 'U')) &&	      ((tmp[7] == 's') || (tmp[7] == 'S')) && (tmp[8] == ':')) ||				/* possible X-Keywords: */	     ((j > 10) && ((tmp[2] == 'K') || (tmp[2] == 'k')) &&	      ((tmp[3] == 'e') || (tmp[3] == 'E')) &&	      ((tmp[4] == 'y') || (tmp[4] == 'Y')) &&	      ((tmp[5] == 'w') || (tmp[5] == 'W')) &&	      ((tmp[6] == 'o') || (tmp[6] == 'O')) &&	      ((tmp[7] == 'r') || (tmp[7] == 'R')) &&	      ((tmp[8] == 'd') || (tmp[8] == 'D')) &&	      ((tmp[9] == 's') || (tmp[9] == 'S')) && (tmp[10] == ':'))) &&	    (fputs ("X-Original-",df) == EOF)) return NIL;	break;      case '\n':		/* blank line */	hdrp = NIL;	break;      default:			/* nothing to do */	break;      }				/* just write the line */      if (fwrite (tmp,1,j,df) != j) return NIL;    }				/* make sure read entire msg & wrote trailer */    if (i || (fputs (mmdfhdr,df) == EOF)) return NIL;				/* update set */    if (stream) mail_append_set (set,stream->uid_last);  }  return T;}/* Internal routines *//* MMDF mail abort stream * Accepts: MAIL stream */void mmdf_abort (MAILSTREAM *stream){  if (LOCAL) {			/* only if a file is open */    if (LOCAL->fd >= 0) close (LOCAL->fd);    if (LOCAL->ld >= 0) {	/* have a mailbox lock? */      flock (LOCAL->ld,LOCK_UN);/* yes, release the lock */      close (LOCAL->ld);	/* close the lock file */      unlink (LOCAL->lname);	/* and delete it */    }    if (LOCAL->lname) fs_give ((void **) &LOCAL->lname);				/* free local text buffers */    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);    if (LOCAL->text.data) fs_give ((void **) &LOCAL->text.data);    if (LOCAL->linebuf) fs_give ((void **) &LOCAL->linebuf);    if (LOCAL->line) fs_give ((void **) &LOCAL->line);				/* nuke the local data */    fs_give ((void **) &stream->local);    stream->dtb = NIL;		/* log out the DTB */  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -