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

📄 unix.c

📁 这是用C编写IMAP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	      case 'A':		/* message answered */		elt->answered = T;		break;	      case 'T':		/* message is a draft */		elt->draft = T;		break;	      default:		/* some other crap */		break;	      } while (*s && (*s != '\n') && ((*s != '\r') || (s[1] != '\n')));	      break;		/* all done */	    }				/* otherwise fall into default case */	  default:		/* ordinary header line */	    if ((*s == 'S') || (*s == 's') ||		(((*s == 'X') || (*s == 'x')) && (s[1] == '-'))) {	      unsigned char *e,*v;				/* must match what mail_filter() does */	      for (u = s,v = tmp,e = u + min (i,MAILTMPLEN - 1);		   (u < e) && ((c = (*u ? *u : (*u = ' '))) != ':') &&		   ((c > ' ') || ((c != ' ') && (c != '\t') &&				  (c != '\015') && (c != '\012')));		   *v++ = *u++);	      *v = '\0';	/* tie off */				/* matches internal header? */	      if (!compare_cstring (tmp,"STATUS") ||		  !compare_cstring (tmp,"X-STATUS") ||		  !compare_cstring (tmp,"X-KEYWORDS") ||		  !compare_cstring (tmp,"X-UID") ||		  !compare_cstring (tmp,"X-IMAP") ||		  !compare_cstring (tmp,"X-IMAPBASE")) {		char err[MAILTMPLEN];		sprintf (err,"Discarding bogus %s header in message %lu",			 (char *) tmp,elt->msgno);		MM_LOG (err,WARN);		retain = NIL;	/* don't retain continuation */		break;		/* different case or something */	      }	    }				/* retain or non-continuation? */	    if (retain || ((*s != ' ') && (*s != '\t'))) {	      retain = T;	/* retaining continuation now */				/* line length in LF format newline */	      k = i - (((i >= 2) && (s[i - 2] == '\r')) ? 1 : 0);				/* "internal" header size */	      elt->private.data += k;				/* message size */	      elt->rfc822_size += k + 1;	    }	    else {	      char err[MAILTMPLEN];	      sprintf (err,"Discarding bogus continuation in msg %lu: %.80s",		      elt->msgno,(char *) s);	      if (u = strpbrk (err,"\r\n")) *u = '\0';	      MM_LOG (err,WARN);	      break;		/* different case or something */	    }	    break;	  }	} while (i && (*t != '\n') && ((*t != '\r') || (t[1] != '\n')));				/* "internal" header sans trailing newline */	if (i) elt->private.data--;				/* assign a UID if none found */	if (((nmsgs > 1) || !pseudoseen) && !elt->private.uid) {	  prevuid = elt->private.uid = ++stream->uid_last;	  elt->private.dirty = T;	}	else elt->private.dirty = elt->recent;				/* note size of header, location of text */	elt->private.msg.header.text.size = 	  (elt->private.msg.text.offset =	   (LOCAL->filesize + GETPOS (&bs)) - elt->private.special.offset) -	     elt->private.special.text.size;	k = m = 0;		/* no previous line size yet */				/* note current position */	j = LOCAL->filesize + GETPOS (&bs);	if (i) do {		/* look for next message */	  s = unix_mbxline (stream,&bs,&i);	  if (i) {		/* got new data? */	    VALID (s,t,ti,zn);	/* yes, parse line */	    if (!ti) {		/* not a header line, add it to message */	      elt->rfc822_size += 		k = i + (m = (((i < 2) || s[i - 2] != '\r') ? 1 : 0));				/* update current position */	      j = LOCAL->filesize + GETPOS (&bs);	    }	  }	} while (i && !ti);	/* until found a header */	elt->private.msg.text.text.size = j -	  (elt->private.special.offset + elt->private.msg.text.offset);	if (k == 2) {		/* last line was blank? */	  elt->private.msg.text.text.size -= (m ? 1 : 2);	  elt->rfc822_size -= 2;	}      } while (i);		/* until end of buffer */      if (pseudoseen) {		/* flush pseudo-message if present */				/* decrement recent count */	if (mail_elt (stream,1)->recent) recent--;				/* and the exists count */	mail_exists (stream,nmsgs--);	mail_expunged(stream,1);/* fake an expunge of that message */      }				/* need to start a new UID validity? */      if (!stream->uid_validity) {	stream->uid_validity = time (0);				/* in case a whiner with no life */	if (mail_parameters (NIL,GET_USERHASNOLIFE,NIL))	  stream->uid_nosticky = T;	else if (nmsgs) {	/* don't bother if empty file */	  LOCAL->dirty = T;	/* make dirty to restart UID epoch */				/* need to rewrite msg 1 if not pseudo */	  if (!LOCAL->pseudo) mail_elt (stream,1)->private.dirty = T;	  MM_LOG ("Assigning new unique identifiers to all messages",NIL);	}      }      stream->nmsgs = oldnmsgs;	/* whack it back down */      stream->silent = silent;	/* restore old silent setting */				/* notify upper level of new mailbox sizes */      mail_exists (stream,nmsgs);      mail_recent (stream,recent);				/* mark dirty so O flags are set */      if (recent) LOCAL->dirty = T;    }  }				/* no change, don't babble if never got time */  else if (LOCAL->filetime && LOCAL->filetime != sbuf.st_mtime)    MM_LOG ("New mailbox modification time but apparently no changes",WARN);				/* update parsed file size and time */  LOCAL->filesize = sbuf.st_size;  LOCAL->filetime = sbuf.st_mtime;  return T;			/* return the winnage */}/* UNIX read line from mailbox * Accepts: mail stream *	    stringstruct *	    pointer to line size * Returns: pointer to input line */char *unix_mbxline (MAILSTREAM *stream,STRING *bs,unsigned long *size){  unsigned long i,j,k,m;  char *s,*t,*te,p1[CHUNK];  char *ret = "";				/* flush old buffer */  if (LOCAL->line) fs_give ((void **) &LOCAL->line);				/* if buffer needs refreshing */  if (!bs->cursize) SETPOS (bs,GETPOS (bs));  if (SIZE (bs)) {		/* find newline */				/* end of fast scan */    te = (t = (s = bs->curpos) + bs->cursize) - 12;    while (s < te) if ((*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n')) {      --s;			/* back up */      break;			/* exit loop */    }				/* final character-at-a-time scan */    while ((s < t) && (*s != '\n')) ++s;				/* difficult case if line spans buffer */    if ((i = s - bs->curpos) == bs->cursize) {      memcpy (p1,bs->curpos,i);	/* remember what we have so far */				/* load next buffer */      SETPOS (bs,k = GETPOS (bs) + i);				/* end of fast scan */      te = (t = (s = bs->curpos) + bs->cursize) - 12;				/* fast scan in overlap buffer */      while (s < te) if ((*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n')) {	--s;			/* back up */	break;			/* exit loop */      }				/* final character-at-a-time scan */      while ((s < t) && (*s != '\n')) ++s;				/* huge line? */      if ((j = s - bs->curpos) == bs->cursize) {	SETPOS (bs,GETPOS (bs) + j);				/* look for end of line (s-l-o-w!!) */	for (m = SIZE (bs); m && (SNX (bs) != '\n'); --m,++j);	SETPOS (bs,k);		/* go back to where it started */      }				/* got size of data, make buffer for return */      ret = LOCAL->line = (char *) fs_get (i + j + 2);      memcpy (ret,p1,i);	/* copy first chunk */      while (j) {		/* copy remainder */	if (!bs->cursize) SETPOS (bs,GETPOS (bs));	memcpy (ret + i,bs->curpos,k = min (j,bs->cursize));	i += k;			/* account for this much read in */	j -= k;	bs->curpos += k;	/* increment new position */	bs->cursize -= k;	/* eat that many bytes */      }      if (!bs->cursize) SETPOS (bs,GETPOS (bs));      if (SIZE (bs)) SNX (bs);	/* skip over newline if one seen */      ret[i++] = '\n';		/* make sure newline at end */      ret[i] = '\0';		/* makes debugging easier */    }    else {			/* this is easy */      ret = bs->curpos;		/* string it at this position */      bs->curpos += ++i;	/* increment new position */      bs->cursize -= i;		/* eat that many bytes */    }    *size = i;			/* return that to user */  }  else *size = 0;		/* end of data, return empty */  return ret;}/* UNIX make pseudo-header * Accepts: MAIL stream *	    buffer to write pseudo-header * Returns: length of pseudo-header */unsigned long unix_pseudo (MAILSTREAM *stream,char *hdr){  int i;  char *s,tmp[MAILTMPLEN];  time_t now = time (0);  rfc822_fixed_date (tmp);  sprintf (hdr,"From %s %.24s\nDate: %s\nFrom: %s <%s@%.80s>\nSubject: %s\nMessage-ID: <%lu@%.80s>\nX-IMAP: %010lu %010lu",	   pseudo_from,ctime (&now),	   tmp,pseudo_name,pseudo_from,mylocalhost (),pseudo_subject,	   (unsigned long) now,mylocalhost (),stream->uid_validity,	   stream->uid_last);  for (s = hdr + strlen (hdr),i = 0; i < NUSERFLAGS; ++i)    if (stream->user_flags[i])      sprintf (s += strlen (s)," %s",stream->user_flags[i]);  sprintf (s += strlen (s),"\nStatus: RO\n\n%s\n\n",pseudo_msg);  return strlen (hdr);		/* return header length */}/* UNIX make status string * Accepts: MAIL stream *	    destination string to write *	    message cache entry *	    non-zero flag to write UID (.LT. 0 to write UID base info too) * Returns: length of string */unsigned long unix_xstatus (MAILSTREAM *stream,char *status,MESSAGECACHE *elt,			    long flag){  char *t,stack[64];  char *s = status;  unsigned long n;  int pad = 50;  /* This used to use sprintf(), but thanks to certain cretinous C libraries     with horribly slow implementations of sprintf() I had to change it to this     mess.  At least it should be fast. */				/* need to write X-IMAPbase: header? */  if ((flag < 0) && !stream->uid_nosticky) {    *s++ = 'X'; *s++ = '-'; *s++ = 'I'; *s++ = 'M'; *s++ = 'A'; *s++ = 'P';    *s++ = 'b'; *s++ = 'a'; *s++ = 's'; *s++ = 'e'; *s++ = ':'; *s++ = ' ';    t = stack;    n = stream->uid_validity;	/* push UID validity digits on the stack */    do *t++ = (char) (n % 10) + '0';    while (n /= 10);				/* pop UID validity digits from stack */    while (t > stack) *s++ = *--t;    *s++ = ' ';    n = stream->uid_last;	/* push UID last digits on the stack */    do *t++ = (char) (n % 10) + '0';    while (n /= 10);				/* pop UID last digits from stack */    while (t > stack) *s++ = *--t;    for (n = 0; n < NUSERFLAGS; ++n) if (t = stream->user_flags[n])      for (*s++ = ' '; *t; *s++ = *t++);    *s++ = '\n';    pad += 30;			/* increased padding if have IMAPbase */  }  *s++ = 'S'; *s++ = 't'; *s++ = 'a'; *s++ = 't'; *s++ = 'u'; *s++ = 's';  *s++ = ':'; *s++ = ' ';  if (elt->seen) *s++ = 'R';  if (flag) *s++ = 'O';		/* only write O if have a UID */  *s++ = '\n';  *s++ = 'X'; *s++ = '-'; *s++ = 'S'; *s++ = 't'; *s++ = 'a'; *s++ = 't';  *s++ = 'u'; *s++ = 's'; *s++ = ':'; *s++ = ' ';  if (elt->deleted) *s++ = 'D';  if (elt->flagged) *s++ = 'F';  if (elt->answered) *s++ = 'A';  if (elt->draft) *s++ = 'T';  *s++ = '\n';  if (!stream->uid_nosticky) {	/* cretins with no life can't use this */    *s++ = 'X'; *s++ = '-'; *s++ = 'K'; *s++ = 'e'; *s++ = 'y'; *s++ = 'w';    *s++ = 'o'; *s++ = 'r'; *s++ = 'd'; *s++ = 's'; *s++ = ':';    if (n = elt->user_flags) do {      *s++ = ' ';      for (t = stream->user_flags[find_rightmost_bit (&n)]; *t; *s++ = *t++);    } while (n);    n = s - status;		/* get size of stuff so far */				/* pad X-Keywords to make size constant */    if (n < pad) for (n = pad - n; n > 0; --n) *s++ = ' ';    *s++ = '\n';    if (flag) {			/* want to include UID? */      t = stack;      n = elt->private.uid;	/* push UID digits on the stack */      do *t++ = (char) (n % 10) + '0';      while (n /= 10);      *s++ = 'X'; *s++ = '-'; *s++ = 'U'; *s++ = 'I'; *s++ = 'D'; *s++ = ':';      *s++ = ' ';				/* pop UID from stack */      while (t > stack) *s++ = *--t;      *s++ = '\n';    }  }  *s++ = '\n'; *s = '\0';	/* end of extended message status */  return s - status;		/* return size of resulting string */}/* Rewrite mailbox file * Accepts: MAIL stream, must be critical and locked *	    return pointer to number of expunged messages if want expunge *	    lock file name * Returns: T if success and mailbox unlocked, NIL if failure */#define OVERFLOWBUFLEN 8192	/* initial overflow buffer length */long unix_rewrite (MAILSTREAM *stream,unsigned long *nexp,DOTLOCK *lock){  MESSAGECACHE *elt;  UNIXFILE f;  char *s;  time_t tp[2];  long ret,flag;  unsigned long i,j;  unsigned long recent = stream->recent;  unsigned long size = LOCAL->pseudo ? unix_pseudo (stream,LOCAL->buf) : 0;  if (nexp) *nexp = 0;		/* initially nothing expunged */				/* calculate size of mailbox after rewrite */  for (i = 1,flag = LOCAL->pseudo ? 1 : -1; i <= stream->nmsgs; i++)    if (!(elt = mail_elt (stream,i))->deleted || !nexp) {				/* add RFC822 size of this message */      size += elt->private.special.text.size + elt->private.data +	unix_xstatus (stream,LOCAL->buf,elt,flag) +	  elt->private.msg.text.text.size + 1;      flag = 1;			/* only count X-IMAPbase once */    }				/* no messages, has a life, and no pseudo */  if (!size && !mail_parameters (NIL,GET_USERHASNOLIFE,NIL)) {    LOCAL->pseudo = T;		/* so make a pseudo-message now */    size = unix_pseudo (stream,LOCAL->buf);  }				/* extend the file as necessary */  if (ret = unix_extend (stream,size)) {    /* Set up buffered I/O file structure     * curpos	current position being written through buffering     * filepos	current position being written physically to the disk     * bufpos	current position being written in the buffer     * protect	current maximum position that can be written to the disk     *		before buffering is forced     * The code tries to buffer so that that disk is written in multiples of     * OVERBLOWBUFLEN bytes.     */    f.stream = stream;		/* note mail stream */    f.curpos = f.filepos = 0;	/* start of file */    f.protect = stream->nmsgs ?	/* initial protection pointer */    mail_elt (stream,1)->private.special.offset : 8192;    f.bufpos = f.buf = (char *) fs_get (f.buflen = OVERFLOWBUFLEN);    if (LOCAL->pseudo)		/* update pseudo-header */      unix_write (&f,LOCAL->buf,unix_pseudo (stream,LOCAL->buf));				/* loop through all messages */    for (i = 1,flag = LOCAL->pseudo ? 1 : -1; i <= st

⌨️ 快捷键说明

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