📄 unix.c
字号:
(elt = mail_elt (stream,nmsgs))->valid = T; recent++; /* assume recent by default */ elt->recent = T; /* note position/size of internal header */ elt->private.special.offset = j; elt->private.msg.header.offset = elt->private.special.text.size = i; /* generate plausible IMAPish date string */ date[2] = date[6] = date[20] = '-'; date[11] = ' '; date[14] = date[17] = ':'; /* dd */ date[0] = t[ti - 2]; date[1] = t[ti - 1]; /* mmm */ date[3] = t[ti - 6]; date[4] = t[ti - 5]; date[5] = t[ti - 4]; /* hh */ date[12] = t[ti + 1]; date[13] = t[ti + 2]; /* mm */ date[15] = t[ti + 4]; date[16] = t[ti + 5]; if (t[ti += 6] == ':') {/* ss */ date[18] = t[++ti]; date[19] = t[++ti]; ti++; /* move to space */ } else date[18] = date[19] = '0'; /* yy -- advance over timezone if necessary */ if (zn == ti) ti += (((t[zn+1] == '+') || (t[zn+1] == '-')) ? 6 : 4); date[7] = t[ti + 1]; date[8] = t[ti + 2]; date[9] = t[ti + 3]; date[10] = t[ti + 4]; /* zzz */ t = zn ? (t + zn + 1) : (unsigned char *) "LCL"; date[21] = *t++; date[22] = *t++; date[23] = *t++; if ((date[21] != '+') && (date[21] != '-')) date[24] = '\0'; else { /* numeric time zone */ date[24] = *t++; date[25] = *t++; date[26] = '\0'; date[20] = ' '; } /* set internal date */ if (!mail_parse_date (elt,date)) { sprintf (tmp,"Unable to parse internal date: %s",(char *) date); MM_LOG (tmp,WARN); } do { /* look for message body */ s = t = unix_mbxline (stream,&bs,&i); if (i) switch (*s) { /* check header lines */ case 'X': /* possible X-???: line */ if (s[1] == '-') { /* must be immediately followed by hyphen */ /* X-Status: becomes Status: in S case */ if (s[2] == 'S' && s[3] == 't' && s[4] == 'a' && s[5] == 't' && s[6] == 'u' && s[7] == 's' && s[8] == ':') s += 2; /* possible X-Keywords */ else if (s[2] == 'K' && s[3] == 'e' && s[4] == 'y' && s[5] == 'w' && s[6] == 'o' && s[7] == 'r' && s[8] == 'd' && s[9] == 's' && s[10] == ':') { SIZEDTEXT uf; retain = NIL; /* don't retain continuation */ s += 11; /* flush leading whitespace */ while (*s && (*s != '\n') && ((*s != '\r') || (s[1] != '\n'))){ while (*s == ' ') s++; /* find end of keyword */ if (!(u = strpbrk (s," \n\r"))) u = s + strlen (s); /* got a keyword? */ if ((k = (u - s)) && (k <= MAXUSERFLAG)) { uf.data = (unsigned char *) s; uf.size = k; for (j = 0; (j < NUSERFLAGS) && stream->user_flags[j]; ++j) if (!compare_csizedtext (stream->user_flags[j],&uf)) { elt->user_flags |= ((long) 1) << j; break; } } s = u; /* advance to next keyword */ } break; } /* possible X-IMAP */ else if ((s[2] == 'I') && (s[3] == 'M') && (s[4] == 'A') && (s[5] == 'P') && ((m = (s[6] == ':')) || ((s[6] == 'b') && (s[7] == 'a') && (s[8] == 's') && (s[9] == 'e') && (s[10] == ':')))) { retain = NIL; /* don't retain continuation */ if ((nmsgs == 1) && !stream->uid_validity) { /* advance to data */ s += m ? 7 : 11; /* flush whitespace */ while (*s == ' ') s++; j = 0; /* slurp UID validity */ /* found a digit? */ while (isdigit (*s)) { j *= 10; /* yes, add it in */ j += *s++ - '0'; } /* flush whitespace */ while (*s == ' ') s++; /* must have valid UID validity and UID last */ if (j && isdigit (*s)) { /* pseudo-header seen if X-IMAP */ if (m) pseudoseen = LOCAL->pseudo = T; /* save UID validity */ stream->uid_validity = j; j = 0; /* slurp UID last */ while (isdigit (*s)) { j *= 10; /* yes, add it in */ j += *s++ - '0'; } /* save UID last */ stream->uid_last = j; /* process keywords */ for (j = 0; (*s != '\n') && ((*s != '\r')||(s[1] != '\n')); s = u,j++) { /* flush leading whitespace */ while (*s == ' ') s++; u = strpbrk (s," \n\r"); /* got a keyword? */ if ((j < NUSERFLAGS) && (k = (u - s)) && (k <= MAXUSERFLAG)) { if (stream->user_flags[j]) fs_give ((void **) &stream->user_flags[j]); stream->user_flags[j] = (char *) fs_get (k + 1); strncpy (stream->user_flags[j],s,k); stream->user_flags[j][k] = '\0'; } } } } break; } /* possible X-UID */ else if (s[2] == 'U' && s[3] == 'I' && s[4] == 'D' && s[5] == ':') { retain = NIL; /* don't retain continuation */ /* only believe if have a UID validity */ if (stream->uid_validity && ((nmsgs > 1) || !pseudoseen)) { s += 6; /* advance to UID value */ /* flush whitespace */ while (*s == ' ') s++; j = 0; /* found a digit? */ while (isdigit (*s)) { j *= 10; /* yes, add it in */ j += *s++ - '0'; } /* flush remainder of line */ while (*s != '\n') s++; /* make sure not duplicated */ if (elt->private.uid) sprintf (tmp,"Message %lu UID %lu already has UID %lu", pseudoseen ? elt->msgno - 1 : elt->msgno, j,elt->private.uid); /* make sure UID doesn't go backwards */ else if (j <= prevuid) sprintf (tmp,"Message %lu UID %lu less than %lu", pseudoseen ? elt->msgno - 1 : elt->msgno, j,prevuid + 1);#if 0 /* this is currently broken by UIDPLUS */ /* or skip by mailbox's recorded last */ else if (j > stream->uid_last) sprintf (tmp,"Message %lu UID %lu greater than last %lu", pseudoseen ? elt->msgno - 1 : elt->msgno, j,stream->uid_last);#endif else { /* normal UID case */ prevuid = elt->private.uid = j;#if 1 /* temporary kludge for UIDPLUS */ if (prevuid > stream->uid_last) { stream->uid_last = prevuid; LOCAL->ddirty = LOCAL->dirty = T; } #endif break; /* exit this cruft */ } MM_LOG (tmp,WARN); /* invalidate UID validity */ stream->uid_validity = 0; elt->private.uid = 0; } break; } } /* otherwise fall into S case */ case 'S': /* possible Status: line */ if (s[0] == 'S' && s[1] == 't' && s[2] == 'a' && s[3] == 't' && s[4] == 'u' && s[5] == 's' && s[6] == ':') { retain = NIL; /* don't retain continuation */ s += 6; /* advance to status flags */ do switch (*s++) {/* parse flags */ case 'R': /* message read */ elt->seen = T; break; case 'O': /* message old */ if (elt->recent) { elt->recent = NIL; recent--; /* it really wasn't recent */ } break; case 'D': /* message deleted */ elt->deleted = T; break; case 'F': /* message flagged */ elt->flagged = T; 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 != '\r') && (c != '\n'))); *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 */ for (j = k = 0; j < i; ++j) if (s[j] != '\r') ++k; /* "internal" header size */ elt->private.spare.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.spare.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; LOCAL->ddirty = T; /* force update */ } 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 += i; for (j = 0; j < i; ++j) switch (s[j]) { case '\r': /* squeeze out CRs */ elt->rfc822_size -= 1; break; case '\n': /* LF becomes CRLF */ elt->rfc822_size += 1; break; default: break; } if ((i == 1) && (*s == '\n')) { k = 2; m = 1; } else if ((i == 2) && (*s == '\r') && (s[1] == '\n')) k = m = 2; else k = m = 0; /* file does not end with newline! */ /* 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); /* flush ending blank line */ elt->private.msg.text.text.size -= m; elt->rfc822_size -= k; /* until end of buffer */ } while (!stream->sniff && i); 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 */ /* make dirty to restart UID epoch */ LOCAL->ddirty = LOCAL->dirty = T; /* 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; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -