📄 imap4d.c
字号:
return f;}/* * flags : flag | flags ' ' flag * flag : '\' atom | atom */static intflags(void){ int ff, flags; char *s; int c; flags = 0; for(;;){ c = peekc(); if(c == '\\'){ mustBe('\\'); s = atomString(atomStop, "\\"); }else if(strchr(atomStop, c) != nil) s = atom(); else break; ff = mapFlag(s); if(ff == 0) parseErr("flag not supported"); flags |= ff; if(peekc() != ' ') break; mustBe(' '); } if(flags == 0) parseErr("no flags given"); return flags;}/* * storeWhat : osign 'FLAGS' ' ' storeflags * | osign 'FLAGS.SILENT' ' ' storeflags * osign : * | '+' | '-' * storeflags : flagList | flags */static Store*storeWhat(void){ int f; char *s; int c, w; c = peekc(); if(c == '+' || c == '-') mustBe(c); else c = 0; s = atom(); w = 0; if(cistrcmp(s, "flags") == 0) w = STFlags; else if(cistrcmp(s, "flags.silent") == 0) w = STFlagsSilent; else parseErr("illegal store attribute"); mustBe(' '); if(peekc() == '(') f = flagList(); else f = flags(); return mkStore(c, w, f);}/* * fetchWhat : "ALL" | "FULL" | "FAST" | fetchAtt | '(' fetchAtts ')' * fetchAtts : fetchAtt | fetchAtts ' ' fetchAtt */static char *fetchAtom = "(){}%*\"\\[]";static Fetch*fetchWhat(void){ Fetch *f; char *s; if(peekc() == '('){ getc(); f = nil; for(;;){ s = atomString(fetchAtom, ""); f = fetchAtt(s, f); if(peekc() == ')') break; mustBe(' '); } getc(); return revFetch(f); } s = atomString(fetchAtom, ""); if(cistrcmp(s, "all") == 0) f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, mkFetch(FEnvelope, nil)))); else if(cistrcmp(s, "fast") == 0) f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, nil))); else if(cistrcmp(s, "full") == 0) f = mkFetch(FFlags, mkFetch(FInternalDate, mkFetch(FRfc822Size, mkFetch(FEnvelope, mkFetch(FBody, nil))))); else f = fetchAtt(s, nil); return f;}/* * fetchAtt : "ENVELOPE" | "FLAGS" | "INTERNALDATE" * | "RFC822" | "RFC822.HEADER" | "RFC822.SIZE" | "RFC822.TEXT" * | "BODYSTRUCTURE" * | "UID" * | "BODY" * | "BODY" bodysubs * | "BODY.PEEK" bodysubs * bodysubs : sect * | sect '<' number '.' nz-number '>' * sect : '[' sectSpec ']' * sectSpec : sectMsgText * | sectPart * | sectPart '.' sectText * sectPart : nz-number * | sectPart '.' nz-number */static Fetch*fetchAtt(char *s, Fetch *f){ NList *sect; int c; if(cistrcmp(s, "envelope") == 0) return mkFetch(FEnvelope, f); if(cistrcmp(s, "flags") == 0) return mkFetch(FFlags, f); if(cistrcmp(s, "internaldate") == 0) return mkFetch(FInternalDate, f); if(cistrcmp(s, "RFC822") == 0) return mkFetch(FRfc822, f); if(cistrcmp(s, "RFC822.header") == 0) return mkFetch(FRfc822Head, f); if(cistrcmp(s, "RFC822.size") == 0) return mkFetch(FRfc822Size, f); if(cistrcmp(s, "RFC822.text") == 0) return mkFetch(FRfc822Text, f); if(cistrcmp(s, "bodystructure") == 0) return mkFetch(FBodyStruct, f); if(cistrcmp(s, "uid") == 0) return mkFetch(FUid, f); if(cistrcmp(s, "body") == 0){ if(peekc() != '[') return mkFetch(FBody, f); f = mkFetch(FBodySect, f); }else if(cistrcmp(s, "body.peek") == 0) f = mkFetch(FBodyPeek, f); else parseErr("illegal fetch attribute"); mustBe('['); c = peekc(); if(c >= '1' && c <= '9'){ sect = mkNList(number(1), nil); while(peekc() == '.'){ getc(); c = peekc(); if(c >= '1' && c <= '9'){ sect = mkNList(number(1), sect); }else{ break; } } f->sect = revNList(sect); } if(peekc() != ']') sectText(f, f->sect != nil); mustBe(']'); if(peekc() != '<') return f; f->partial = 1; mustBe('<'); f->start = number(0); mustBe('.'); f->size = number(1); mustBe('>'); return f;}/* * sectText : sectMsgText | "MIME" * sectMsgText : "HEADER" * | "TEXT" * | "HEADER.FIELDS" ' ' hdrList * | "HEADER.FIELDS.NOT" ' ' hdrList * hdrList : '(' hdrs ')' * hdrs: : astring * | hdrs ' ' astring */static voidsectText(Fetch *f, int mimeOk){ SList *h; char *s; s = atomString(fetchAtom, ""); if(cistrcmp(s, "header") == 0){ f->part = FPHead; return; } if(cistrcmp(s, "text") == 0){ f->part = FPText; return; } if(mimeOk && cistrcmp(s, "mime") == 0){ f->part = FPMime; return; } if(cistrcmp(s, "header.fields") == 0) f->part = FPHeadFields; else if(cistrcmp(s, "header.fields.not") == 0) f->part = FPHeadFieldsNot; else parseErr("illegal fetch section text"); mustBe(' '); mustBe('('); h = nil; for(;;){ h = mkSList(astring(), h); if(peekc() == ')') break; mustBe(' '); } mustBe(')'); f->hdrs = revSList(h);}/* * searchWhat : "CHARSET" ' ' astring searchkeys | searchkeys * searchkeys : searchkey | searchkeys ' ' searchkey * searchkey : "ALL" | "ANSWERED" | "DELETED" | "FLAGGED" | "NEW" | "OLD" | "RECENT" * | "SEEN" | "UNANSWERED" | "UNDELETED" | "UNFLAGGED" | "DRAFT" | "UNDRAFT" * | astrkey ' ' astring * | datekey ' ' date * | "KEYWORD" ' ' flag | "UNKEYWORD" flag * | "LARGER" ' ' number | "SMALLER" ' ' number * | "HEADER" astring ' ' astring * | set | "UID" ' ' set * | "NOT" ' ' searchkey * | "OR" ' ' searchkey ' ' searchkey * | '(' searchkeys ')' * astrkey : "BCC" | "BODY" | "CC" | "FROM" | "SUBJECT" | "TEXT" | "TO" * datekey : "BEFORE" | "ON" | "SINCE" | "SENTBEFORE" | "SENTON" | "SENTSINCE" */static NamedInt searchMap[] ={ {"ALL", SKAll}, {"ANSWERED", SKAnswered}, {"DELETED", SKDeleted}, {"FLAGGED", SKFlagged}, {"NEW", SKNew}, {"OLD", SKOld}, {"RECENT", SKRecent}, {"SEEN", SKSeen}, {"UNANSWERED", SKUnanswered}, {"UNDELETED", SKUndeleted}, {"UNFLAGGED", SKUnflagged}, {"DRAFT", SKDraft}, {"UNDRAFT", SKUndraft}, {"UNSEEN", SKUnseen}, {nil, 0}};static NamedInt searchMapStr[] ={ {"CHARSET", SKCharset}, {"BCC", SKBcc}, {"BODY", SKBody}, {"CC", SKCc}, {"FROM", SKFrom}, {"SUBJECT", SKSubject}, {"TEXT", SKText}, {"TO", SKTo}, {nil, 0}};static NamedInt searchMapDate[] ={ {"BEFORE", SKBefore}, {"ON", SKOn}, {"SINCE", SKSince}, {"SENTBEFORE", SKSentBefore}, {"SENTON", SKSentOn}, {"SENTSINCE", SKSentSince}, {nil, 0}};static NamedInt searchMapFlag[] ={ {"KEYWORD", SKKeyword}, {"UNKEYWORD", SKUnkeyword}, {nil, 0}};static NamedInt searchMapNum[] ={ {"SMALLER", SKSmaller}, {"LARGER", SKLarger}, {nil, 0}};static Search*searchKeys(int first, Search *tail){ Search *s; for(;;){ if(peekc() == '('){ getc(); tail = searchKeys(0, tail); mustBe(')'); }else{ s = searchKey(first); tail->next = s; tail = s; } first = 0; if(peekc() != ' ') break; getc(); } return tail;}static Search*searchKey(int first){ Search *sr, rock; Tm tm; char *a; int i, c; sr = binalloc(&parseBin, sizeof(Search), 1); if(sr == nil) parseErr("out of memory"); c = peekc(); if(c >= '0' && c <= '9'){ sr->key = SKSet; sr->set = msgSet(0); return sr; } a = atom(); if(i = mapInt(searchMap, a)) sr->key = i; else if(i = mapInt(searchMapStr, a)){ if(!first && i == SKCharset) parseErr("illegal search key"); sr->key = i; mustBe(' '); sr->s = astring(); }else if(i = mapInt(searchMapDate, a)){ sr->key = i; mustBe(' '); c = peekc(); if(c == '"') getc(); a = atom(); if(!imap4Date(&tm, a)) parseErr("bad date format"); sr->year = tm.year; sr->mon = tm.mon; sr->mday = tm.mday; if(c == '"') mustBe('"'); }else if(i = mapInt(searchMapFlag, a)){ sr->key = i; mustBe(' '); c = peekc(); if(c == '\\'){ mustBe('\\'); a = atomString(atomStop, "\\"); }else a = atom(); i = mapFlag(a); if(i == 0) parseErr("flag not supported"); sr->num = i; }else if(i = mapInt(searchMapNum, a)){ sr->key = i; mustBe(' '); sr->num = number(0); }else if(cistrcmp(a, "HEADER") == 0){ sr->key = SKHeader; mustBe(' '); sr->hdr = astring(); mustBe(' '); sr->s = astring(); }else if(cistrcmp(a, "UID") == 0){ sr->key = SKUid; mustBe(' '); sr->set = msgSet(0); }else if(cistrcmp(a, "NOT") == 0){ sr->key = SKNot; mustBe(' '); rock.next = nil; searchKeys(0, &rock); sr->left = rock.next; }else if(cistrcmp(a, "OR") == 0){ sr->key = SKOr; mustBe(' '); rock.next = nil; searchKeys(0, &rock); sr->left = rock.next; mustBe(' '); rock.next = nil; searchKeys(0, &rock); sr->right = rock.next; }else parseErr("illegal search key"); return sr;}/* * set : seqno * | seqno ':' seqno * | set ',' set * seqno: nz-number * | '*' * */static MsgSet*msgSet(int uids){ MsgSet head, *last, *ms; ulong from, to; last = &head; head.next = nil; for(;;){ from = uids ? uidNo() : seqNo(); to = from; if(peekc() == ':'){ getc(); to = uids ? uidNo() : seqNo(); } ms = binalloc(&parseBin, sizeof(MsgSet), 0); if(ms == nil) parseErr("out of memory"); ms->from = from; ms->to = to; ms->next = nil; last->next = ms; last = ms; if(peekc() != ',') break; getc(); } return head.next;}static ulongseqNo(void){ if(peekc() == '*'){ getc(); return ~0UL; } return number(1);}static ulonguidNo(void){ if(peekc() == '*'){ getc(); return ~0UL; } return number(0);}/* * 7 bit, non-ctl chars, no (){%*"\ * NIL is special case for nstring or parenlist */static char *atom(void){ return atomString(atomStop, "");}/* * like an atom, but no + */static char *tag(void){ return atomString("+(){%*\"\\", "");}/* * string or atom allowing %* */static char *listmbox(void){ int c; c = peekc(); if(c == '{') return literal(); if(c == '"') return quoted(); return atomString("(){\"\\", "");}/* * string or atom */static char *astring(void){ int c; c = peekc(); if(c == '{') return literal(); if(c == '"') return quoted(); return atom();}/* * 7 bit, non-ctl chars, none from exception list */static char *atomString(char *disallowed, char *initial){ char *s; int c, ns, as; ns = strlen(initial); s = binalloc(&parseBin, ns + StrAlloc, 0); if(s == nil) parseErr("out of memory"); strcpy(s, initial); as = ns + StrAlloc; for(;;){ c = getc(); if(c <= ' ' || c >= 0x7f || strchr(disallowed, c) != nil){ ungetc(); break; } s[ns++] = c; if(ns >= as){ s = bingrow(&parseBin, s, as, as + StrAlloc, 0); if(s == nil) parseErr("out of memory"); as += StrAlloc; } } if(ns == 0) badsyn(); s[ns] = '\0'; return s;}/* * quoted: '"' chars* '"' * chars: 1-128 except \r and \n */static char *quoted(void){ char *s; int c, ns, as; mustBe('"'); s = binalloc(&parseBin, StrAlloc, 0); if(s == nil) parseErr("out of memory"); as = StrAlloc; ns = 0; for(;;){ c = getc(); if(c == '"') break; if(c < 1 || c > 0x7f || c == '\r' || c == '\n') badsyn(); if(c == '\\'){ c = getc(); if(c != '\\' && c != '"') badsyn(); } s[ns++] = c; if(ns >= as){ s = bingrow(&parseBin, s, as, as + StrAlloc, 0); if(s == nil) parseErr("out of memory"); as += StrAlloc; } } s[ns] = '\0'; return s;}/* * litlen: {number}\r\n */static ulonglitlen(void){ ulong v; mustBe('{'); v = number(0); mustBe('}'); crnl(); return v;}/* * literal: litlen data<0:litlen> */static char *literal(void){ char *s; ulong v; v = litlen(); s = binalloc(&parseBin, v+1, 0); if(s == nil) parseErr("out of memory"); Bprint(&bout, "+ Ready for literal data\r\n"); if(Bflush(&bout) < 0) writeErr(); if(v != 0 && Bread(&bin, s, v) != v) badsyn(); s[v] = '\0'; return s;}/* * digits; number is 32 bits */static ulongnumber(int nonzero){ ulong v; int c, first; v = 0; first = 1; for(;;){ c = getc(); if(c < '0' || c > '9'){ ungetc(); if(first) badsyn(); break; } if(nonzero && first && c == '0') badsyn(); c -= '0'; first = 0; if(v > UlongMax/10 || v == UlongMax/10 && c > UlongMax%10) parseErr("number out of range\r\n"); v = v * 10 + c; } return v;}static intgetc(void){ return Bgetc(&bin);}static voidungetc(void){ Bungetc(&bin);}static intpeekc(void){ int c; c = Bgetc(&bin); Bungetc(&bin); return c;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -