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

📄 mix.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
      break;    MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);    break;  default:    sprintf (tmp,"Not a MIX-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    break;  }				/* get first message */  if (ret && MM_APPEND (af) (stream,data,&flags,&date,&message)) {    MAILSTREAM *astream;    FILE *idxf = NIL;    FILE *msgf = NIL;    FILE *statf = NIL;    if (ret = ((astream = mail_open (NIL,mailbox,OP_SILENT)) &&	       !astream->rdonly &&	       (((MIXLOCAL *) astream->local)->expok = T) &&	       (statf = mix_parse (astream,&idxf,LONGT,NIL))) ?	LONGT : NIL) {      int fd;      unsigned long size,hdrsize;      MESSAGECACHE elt;      MIXLOCAL *local = (MIXLOCAL *) astream->local;      unsigned long seq = mix_modseq (local->metaseq);				/* make sure new modseq fits */      if (local->indexseq > seq) seq = local->indexseq + 1;      if (local->statusseq > seq) seq = local->statusseq + 1;				/* calculate size of per-message header */      sprintf (local->buf,MSRFMT,MSGTOK,0,0,0,0,0,0,0,'+',0,0,0);      hdrsize = strlen (local->buf);      MM_CRITICAL (astream);	/* go critical */      astream->silent = T;	/* no events here */				/* open data file */      if (msgf = mix_data_open (astream,&fd,&size,hdrsize + SIZE (message))) {	appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL);	SEARCHSET *dst = au ? mail_newsearchset () : NIL;	while (ret && message) {/* while good to go and have messages */	  errno = NIL;		/* in case one of these causes failure */				/* guard against zero-length */	  if (!(ret = SIZE (message)))	    MM_LOG ("Append of zero-length message",ERROR);	  else if (date && !(ret = mail_parse_date (&elt,date))) {	    sprintf (tmp,"Bad date in append: %.80s",date);	    MM_LOG (tmp,ERROR);	  }	  else {	    if (!date) {	/* if date not specified, use now */	      internal_date (tmp);	      mail_parse_date (&elt,tmp);	    }	    ret = mix_append_msg (astream,msgf,flags,&elt,message,dst,seq) &&	      MM_APPEND (af) (stream,data,&flags,&date,&message);	  }	}				/* finish write if success */	if (ret && (ret = !fflush (msgf))) {	  fclose (msgf);	/* all good, close the msg file now */				/* write new metadata, index, and status */	  local->metaseq = local->indexseq = local->statusseq = seq;	  if ((ret = (mix_meta_update (astream) &&		      mix_index_update (astream,idxf,LONGT) &&		      mix_status_update (astream,statf,LONGT))) && au) {	      (*au) (mailbox,astream->uid_validity,dst);	      dst = NIL;	/* don't free this set now */	  }	}	else {			/* failure */	  if (errno) {		/* output error message if system call error */	    sprintf (tmp,"Message append failed: %.80s",strerror (errno));	    MM_LOG (tmp,ERROR);	  }	  ftruncate (fd,size);	/* revert all writes to file*/	  close (fd);		/* make sure that fclose doesn't corrupt us */	  fclose (msgf);	/* free the stdio resources */	}				/* flush any set remaining */	mail_free_searchset (&dst);      }      else {			/* message file open failed */	sprintf (tmp,"Error opening append message file: %.80s",		 strerror (errno));	MM_LOG (tmp,ERROR);	ret = NIL;      }      MM_NOCRITICAL (astream);	/* release critical */    }    else MM_LOG ("Can't open append mailbox",ERROR);    if (statf) fclose (statf);	/* close status if still open */    if (idxf) fclose (idxf);	/* close index if still open */    if (astream) mail_close (astream);  }  return ret;}/* MIX mail append single message * Accepts: MAIL stream *	    flags for new message if non-NIL *	    elt with source date if non-NIL *	    stringstruct of message text *	    searchset to place UID *	    modseq of message * Returns: T if success, NIL if failure */long mix_append_msg (MAILSTREAM *stream,FILE *f,char *flags,MESSAGECACHE *delt,		     STRING *msg,SEARCHSET *set,unsigned long seq){  MESSAGECACHE *elt;  int c,cs;  unsigned long i,j,k,uf,hoff;  long sf;  stream->kwd_create = NIL;	/* don't copy unknown keywords */  sf = mail_parse_flags (stream,flags,&uf);				/* swell the cache */  mail_exists (stream,++stream->nmsgs);				/* assign new UID from metadata */  (elt = mail_elt (stream,stream->nmsgs))->private.uid = ++stream->uid_last;  elt->private.mod = seq;	/* set requested modseq in status */  elt->rfc822_size = SIZE (msg);/* copy message size and date to index */  elt->year = delt->year; elt->month = delt->month; elt->day = delt->day;  elt->hours = delt->hours; elt->minutes = delt->minutes;  elt->seconds = delt->seconds; elt->zoccident = delt->zoccident;  elt->zhours = delt->zhours; elt->zminutes = delt->zminutes;  /*   * Do NOT set elt->valid here!  mix_status_update() uses it to determine   * whether a message should be marked as old.   */  if (sf&fSEEN) elt->seen = T;	/* copy flags to status */  if (sf&fDELETED) elt->deleted = T;  if (sf&fFLAGGED) elt->flagged = T;  if (sf&fANSWERED) elt->answered = T;  if (sf&fDRAFT) elt->draft = T;  elt->user_flags |= uf;				/* message is in new message file */  elt->private.spare.data = LOCAL->newmsg;				/* offset to message internal header */  elt->private.special.offset = ftell (f);				/* build header for message */  fprintf (f,MSRFMT,MSGTOK,elt->private.uid,	   elt->year + BASEYEAR,elt->month,elt->day,	   elt->hours,elt->minutes,elt->seconds,	   elt->zoccident ? '-' : '+',elt->zhours,elt->zminutes,	   elt->rfc822_size);				/* offset to header from  internal header */  elt->private.msg.header.offset = ftell (f) - elt->private.special.offset;  for (cs = 0; SIZE (msg); ) {	/* copy message */    if (elt->private.msg.header.text.size) {      if (msg->cursize)		/* blat entire chunk if have it */	for (j = msg->cursize; j; j -= k)	  if (!(k = fwrite (msg->curpos,1,j,f))) return NIL;      SETPOS (msg,GETPOS (msg) + msg->cursize);    }    else {			/* still searching for delimiter */      c = 0xff & SNX (msg);	/* get source character */      if (putc (c,f) == EOF) return NIL;      switch (cs) {		/* decide what to do based on state */      case 0:			/* previous char ordinary */	if (c == '\015') cs = 1;/* advance if CR */	break;      case 1:			/* previous CR, advance if LF */	cs = (c == '\012') ? 2 : 0;	break;      case 2:			/* previous CRLF, advance if CR */	cs = (c == '\015') ? 3 : 0;	break;      case 3:			/* previous CRLFCR, done if LF */	if (c == '\012') elt->private.msg.header.text.size =			   elt->rfc822_size - SIZE (msg);	cs = 0;			/* reset mechanism */	break;      }    }  }				/* if no delimiter, header is entire msg */  if (!elt->private.msg.header.text.size)    elt->private.msg.header.text.size = elt->rfc822_size;				/* add this message to set */  mail_append_set (set,elt->private.uid);  return LONGT;			/* success */}/* MIX mail read metadata, index, and status * Accepts: MAIL stream *	    returned index file *	    index file flags (non-NIL if want to add/remove messages) *	    status file flags (non-NIL if want to update elt->valid and old) * Returns: open status file, or NIL if failure * * Note that this routine can return an open index file even if it fails! */static char *shortmsg =  "message %lu (UID=%.08lx) truncated by %lu byte(s) (%lu < %lu)";FILE *mix_parse (MAILSTREAM *stream,FILE **idxf,long iflags,long sflags){  int fd;  unsigned long i;  char *s,*t;  struct stat sbuf;  FILE *statf = NIL;  short metarepairneeded = 0;  short indexrepairneeded = 0;  short silent = stream->silent;  *idxf = NIL;			/* in case error */				/* readonly means no updates */  if (stream->rdonly) iflags = sflags = NIL;				/* open index file */  if ((fd = open (LOCAL->index,iflags ? O_RDWR : O_RDONLY,NIL)) < 0)    MM_LOG ("Error opening mix index file",ERROR);				/* acquire exclusive access and FILE */  else if (!flock (fd,iflags ? LOCK_EX : LOCK_SH) &&	   !(*idxf = fdopen (fd,iflags ? "r+b" : "rb"))) {    MM_LOG ("Error obtaining stream on mix index file",ERROR);    flock (fd,LOCK_UN);		/* relinquish lock */    close (fd);  }				/* slurp metadata */  else if (s = mix_meta_slurp (stream,&i)) {    unsigned long j = 0;	/* non-zero if UIDVALIDITY/UIDLAST changed */    if (i != LOCAL->metaseq) {	/* metadata changed? */      char *t,*k;      LOCAL->metaseq = i;	/* note new metadata sequence */      while (s && *s) {		/* parse entire metadata file */				/* locate end of line */	if (s = strstr (t = s,"\015\012")) {	  *s = '\0';		/* tie off line */	  s += 2;		/* skip past CRLF */	  switch (*t++) {	/* parse line */	  case 'V':		/* UIDVALIDITY */	    if (!isxdigit (*t) || !(i = strtoul (t,&t,16))) {	      MM_LOG ("Error in mix metadata file UIDVALIDITY record",ERROR);	      return NIL;	/* give up */	    }	    if (i != stream->uid_validity) j = stream->uid_validity = i;	    break;	  case 'L':		/* new UIDLAST */	    if (!isxdigit (*t)) {	      MM_LOG ("Error in mix metadata file UIDLAST record",ERROR);	      return NIL;	/* give up */	    }	    if ((i = strtoul (t,&t,16)) != stream->uid_last)	      j = stream->uid_last = i;	    break;	  case 'N':		/* new message file */	    if (!isxdigit (*t)) {	      MM_LOG ("Error in mix metadata file new msg record",ERROR);	      return NIL;	/* give up */	    }	    if ((i = strtoul (t,&t,16)) != stream->uid_last)	      LOCAL->newmsg = i;	    break;	  case 'K':		/* new keyword list */	    for (i = 0; t && *t && (i < NUSERFLAGS); ++i) {	      if (t = strchr (k = t,' ')) *t++ = '\0';				/* make sure keyword non-empty */	      if (*k && (strlen (k) <= MAXUSERFLAG)) {				/* in case value changes (shouldn't happen) */		if (stream->user_flags[i] && strcmp (stream->user_flags[i],k)){		  char tmp[MAILTMPLEN];		  sprintf (tmp,"flag rename old=%.80s new=%.80s",			   stream->user_flags[i],k);		  MM_LOG (tmp,WARN);		  fs_give ((void **) &stream->user_flags[i]);		}		if (!stream->user_flags[i]) stream->user_flags[i] = cpystr (k);	      }	      else break;	/* empty keyword */	    }	    if ((i < NUSERFLAGS) && stream->user_flags[i]) {	      MM_LOG ("Error in mix metadata file keyword record",ERROR);	      return NIL;	/* give up */	    }	    else if (i == NUSERFLAGS) stream->kwd_create = NIL;	    break;	  }	}	if (t && *t) {		/* junk in line */	  MM_LOG ("Error in mix metadata record",ERROR);	  return NIL;		/* give up */	}      }    }				/* get sequence */    if (!(i = mix_read_sequence (*idxf)) || (i < LOCAL->indexseq)) {      MM_LOG ("Error in mix index file sequence record",ERROR);      return NIL;		/* give up */    }				/* sequence changed from last time? */    else if (j || (i > LOCAL->indexseq)) {      unsigned long uid,nmsgs,curfile,curfilesize,curpos;      char *t,*msg,tmp[MAILTMPLEN];				/* start with no messages */      curfile = curfilesize = curpos = nmsgs = 0;				/* update sequence iff expunging OK */      if (LOCAL->expok) LOCAL->indexseq = i;				/* get first elt */      while ((s = mix_read_record (*idxf,LOCAL->buf,LOCAL->buflen,"index")) &&	     *s)	switch (*s) {	case ':':		/* message record */	  if (!(isxdigit (*++s) && (uid = strtoul (s,&t,16)))) msg = "UID";	  else if (!((*t++ == ':') && isdigit (*t) && isdigit (t[1]) &&		     isdigit (t[2]) && isdigit (t[3]) && isdigit (t[4]) &&		     isdigit (t[5]) && isdigit (t[6]) && isdigit (t[7]) &&		     isdigit (t[8]) && isdigit (t[9]) && isdigit (t[10]) &&		     isdigit (t[11]) && isdigit (t[12]) && isdigit (t[13]) &&		     ((t[14] == '+') || (t[14] == '-')) && 		     isdigit (t[15]) && isdigit (t[16]) && isdigit (t[17]) &&		     isdigit (t[18]))) msg = "internaldate";	  else if ((*(s = t+19) != ':') || !isxdigit (*++s)) msg = "size";	  else {	    unsigned int y = (((*t - '0') * 1000) + ((t[1] - '0') * 100) +			      ((t[2] - '0') * 10) + t[3] - '0') - BASEYEAR;	    unsigned int m = ((t[4] - '0') * 10) + t[5] - '0';	    unsigned int d = ((t[6] - '0') * 10) + t[7] - '0';	    unsigned int hh = ((t[8] - '0') * 10) + t[9] - '0';	    unsigned int mm = ((t[10] - '0') * 10) + t[11] - '0';	    unsigned int ss = ((t[12] - '0') * 10) + t[13] - '0';	    unsigned int z = (t[14] == '-') ? 1 : 0;	    unsigned int zh = ((t[15] - '0') * 10) + t[16] - '0';	    unsigned int zm = ((t[17] - '0') * 10) + t[18] - '0';	    unsigned long size = strtoul (s,&s,16);	    if ((*s++ == ':') && isxdigit (*s)) {	      unsigned long file = strtoul (s,&s,16);	      if ((*s++ == ':') && isxdigit (*s)) {		unsigned long pos = strtoul (s,&s,16);		if ((*s++ == ':') && isxdigit (*s)) {		  unsigned long hpos = strtoul (s,&s,16);		  if ((*s++ == ':') && isxdigit (*s)) {		    unsigned long hsiz = strtoul (s,&s,16);		    if (uid > stream->uid_last) {		      sprintf (tmp,"mix index invalid UID (%08lx < %08lx)",			       uid,stream->uid_last);		      if (stream->rdonly) {			MM_LOG (tmp,ERROR);			return NIL;		      }		      strcat (tmp,", repaired");		      MM_LOG (tmp,WARN);		      stream->uid_last = uid;		      metarepairneeded = T;		    }				/* ignore expansion values */		    if (*s++ == ':') {		      MESSAGECACHE *elt;		      ++nmsgs;	/* this is another mesage */				/* within current known range of messages? */		      while (nmsgs <= stream->nmsgs) {				/* yes, get corresponding elt */			elt = mail_elt (stream,nmsgs);				/* existing message with matching data? */			if (uid == elt->private.uid) {				/* beware of Dracula's resurrection */			  if (elt->private.ghost) {			    sprintf (tmp,"mix index data unexpunged UID: %lx",				     uid);			    MM_LOG (tmp,ERROR);			    return NIL;			  }				/* also of static data changing */			  if ((size != elt->rfc822_size) ||			      (file != elt->private.spare.data) ||			      (pos != elt->private.special.offset) ||			      (hpos != elt->private.msg.header.offset) ||			      (hsiz != elt->private.msg.header.text.size) ||			      (y != elt->year) || (m != elt->month) ||			      (d != elt->day) || (hh != elt->hours) ||			      (mm != elt->minutes) || (ss != elt->seconds) ||			      (z != elt->zoccident) || (zh != elt->zhours) ||			      (zm != elt->zminutes)) {			    

⌨️ 快捷键说明

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