17dd7cddfSDavid du Colombier /* 27dd7cddfSDavid du Colombier * mailbox and message representations 37dd7cddfSDavid du Colombier * 47dd7cddfSDavid du Colombier * these structures are allocated with emalloc and must be explicitly freed 57dd7cddfSDavid du Colombier */ 67dd7cddfSDavid du Colombier typedef struct Box Box; 77dd7cddfSDavid du Colombier typedef struct Header Header; 87dd7cddfSDavid du Colombier typedef struct MAddr MAddr; 97dd7cddfSDavid du Colombier typedef struct MbLock MbLock; 107dd7cddfSDavid du Colombier typedef struct MimeHdr MimeHdr; 117dd7cddfSDavid du Colombier typedef struct Msg Msg; 127dd7cddfSDavid du Colombier typedef struct NamedInt NamedInt; 137dd7cddfSDavid du Colombier typedef struct Pair Pair; 147dd7cddfSDavid du Colombier 157dd7cddfSDavid du Colombier enum 167dd7cddfSDavid du Colombier { 177dd7cddfSDavid du Colombier StrAlloc = 32, /* characters allocated at a time */ 187dd7cddfSDavid du Colombier BufSize = 8*1024, /* size of transfer block */ 197dd7cddfSDavid du Colombier NDigest = 40, /* length of digest string */ 207dd7cddfSDavid du Colombier NUid = 10, /* length of .imp uid string */ 217dd7cddfSDavid du Colombier NFlags = 8, /* length of .imp flag string */ 227dd7cddfSDavid du Colombier LockSecs = 5 * 60, /* seconds to wait for acquiring a locked file */ 23*9a747e4fSDavid du Colombier MboxNameLen = 256, /* max. length of upas/fs mbox name */ 24*9a747e4fSDavid du Colombier MsgNameLen = 32, /* max. length of a file in a upas/fs mbox */ 25*9a747e4fSDavid du Colombier UserNameLen = 64, /* max. length of user's name */ 267dd7cddfSDavid du Colombier 277dd7cddfSDavid du Colombier MUtf7Max = 6, /* max length for a modified utf7 character: &bbbb- */ 287dd7cddfSDavid du Colombier 297dd7cddfSDavid du Colombier /* 307dd7cddfSDavid du Colombier * message flags 317dd7cddfSDavid du Colombier */ 327dd7cddfSDavid du Colombier MSeen = 1 << 0, 337dd7cddfSDavid du Colombier MAnswered = 1 << 1, 347dd7cddfSDavid du Colombier MFlagged = 1 << 2, 357dd7cddfSDavid du Colombier MDeleted = 1 << 3, 367dd7cddfSDavid du Colombier MDraft = 1 << 4, 377dd7cddfSDavid du Colombier MRecent = 1 << 5, 3880ee5cbfSDavid du Colombier 3980ee5cbfSDavid du Colombier /* 4080ee5cbfSDavid du Colombier * message bogus flags 4180ee5cbfSDavid du Colombier */ 4280ee5cbfSDavid du Colombier NotBogus = 0, /* the message is displayable */ 4380ee5cbfSDavid du Colombier BogusHeader = 1, /* the header had bad characters */ 4480ee5cbfSDavid du Colombier BogusBody = 2, /* the body had bad characters */ 4580ee5cbfSDavid du Colombier BogusTried = 4, /* attempted to open the fake message */ 467dd7cddfSDavid du Colombier }; 477dd7cddfSDavid du Colombier 487dd7cddfSDavid du Colombier struct Box 497dd7cddfSDavid du Colombier { 507dd7cddfSDavid du Colombier char *name; /* path name of mailbox */ 517dd7cddfSDavid du Colombier char *fs; /* fs name of mailbox */ 527dd7cddfSDavid du Colombier char *fsDir; /* /mail/fs/box->fs */ 537dd7cddfSDavid du Colombier char *imp; /* path name of .imp file */ 547dd7cddfSDavid du Colombier uchar writable; /* can write back messages? */ 557dd7cddfSDavid du Colombier uchar dirtyImp; /* .imp file needs to be written? */ 567dd7cddfSDavid du Colombier uchar sendFlags; /* need flags update */ 577dd7cddfSDavid du Colombier Qid qid; /* qid of fs mailbox */ 587dd7cddfSDavid du Colombier Qid impQid; /* qid of .imp when last synched */ 597dd7cddfSDavid du Colombier long mtime; /* file mtime when last read */ 607dd7cddfSDavid du Colombier ulong max; /* maximum msgs->seq, same as number of messages */ 617dd7cddfSDavid du Colombier ulong toldMax; /* last value sent to client */ 627dd7cddfSDavid du Colombier ulong recent; /* number of recently received messaged */ 637dd7cddfSDavid du Colombier ulong toldRecent; /* last value sent to client */ 647dd7cddfSDavid du Colombier ulong uidnext; /* next uid value assigned to a message */ 657dd7cddfSDavid du Colombier ulong uidvalidity; /* uid of mailbox */ 667dd7cddfSDavid du Colombier Msg *msgs; 677dd7cddfSDavid du Colombier }; 687dd7cddfSDavid du Colombier 697dd7cddfSDavid du Colombier /* 707dd7cddfSDavid du Colombier * fields of Msg->info 717dd7cddfSDavid du Colombier */ 727dd7cddfSDavid du Colombier enum 737dd7cddfSDavid du Colombier { 747dd7cddfSDavid du Colombier /* 757dd7cddfSDavid du Colombier * read from upasfs 767dd7cddfSDavid du Colombier */ 777dd7cddfSDavid du Colombier IFrom, 787dd7cddfSDavid du Colombier ITo, 797dd7cddfSDavid du Colombier ICc, 807dd7cddfSDavid du Colombier IReplyTo, 817dd7cddfSDavid du Colombier IUnixDate, 827dd7cddfSDavid du Colombier ISubject, 837dd7cddfSDavid du Colombier IType, 847dd7cddfSDavid du Colombier IDisposition, 857dd7cddfSDavid du Colombier IFilename, 867dd7cddfSDavid du Colombier IDigest, 877dd7cddfSDavid du Colombier IBcc, 887dd7cddfSDavid du Colombier IInReplyTo, /* aka internal date */ 897dd7cddfSDavid du Colombier IDate, 907dd7cddfSDavid du Colombier ISender, 917dd7cddfSDavid du Colombier IMessageId, 927dd7cddfSDavid du Colombier ILines, /* number of lines of raw body */ 937dd7cddfSDavid du Colombier 947dd7cddfSDavid du Colombier IMax 957dd7cddfSDavid du Colombier }; 967dd7cddfSDavid du Colombier 977dd7cddfSDavid du Colombier struct Header 987dd7cddfSDavid du Colombier { 997dd7cddfSDavid du Colombier char *buf; /* header, including terminating \r\n */ 1007dd7cddfSDavid du Colombier ulong size; /* strlen(buf) */ 1017dd7cddfSDavid du Colombier ulong lines; /* number of \n characters in buf */ 1027dd7cddfSDavid du Colombier 1037dd7cddfSDavid du Colombier /* 1047dd7cddfSDavid du Colombier * pre-parsed mime headers 1057dd7cddfSDavid du Colombier */ 1067dd7cddfSDavid du Colombier MimeHdr *type; /* content-type */ 1077dd7cddfSDavid du Colombier MimeHdr *id; /* content-id */ 1087dd7cddfSDavid du Colombier MimeHdr *description; /* content-description */ 1097dd7cddfSDavid du Colombier MimeHdr *encoding; /* content-transfer-encoding */ 1107dd7cddfSDavid du Colombier MimeHdr *md5; /* content-md5 */ 1117dd7cddfSDavid du Colombier MimeHdr *disposition; /* content-disposition */ 1127dd7cddfSDavid du Colombier MimeHdr *language; /* content-language */ 1137dd7cddfSDavid du Colombier }; 1147dd7cddfSDavid du Colombier 1157dd7cddfSDavid du Colombier struct Msg 1167dd7cddfSDavid du Colombier { 1177dd7cddfSDavid du Colombier Msg *next; 1187dd7cddfSDavid du Colombier Msg *prev; 1197dd7cddfSDavid du Colombier Msg *kids; 12080ee5cbfSDavid du Colombier Msg *parent; 1217dd7cddfSDavid du Colombier char *fsDir; /* box->fsDir of enclosing message */ 1227dd7cddfSDavid du Colombier Header head; /* message header */ 1237dd7cddfSDavid du Colombier Header mime; /* mime header from enclosing multipart spec */ 1247dd7cddfSDavid du Colombier int flags; 1257dd7cddfSDavid du Colombier uchar sendFlags; /* flags value needs to be sent to client */ 1267dd7cddfSDavid du Colombier uchar expunged; /* message actually expunged, but not yet reported to client */ 1277dd7cddfSDavid du Colombier uchar matched; /* search succeeded? */ 12880ee5cbfSDavid du Colombier uchar bogus; /* implies the message is invalid, ie contains nulls; see flags above */ 1297dd7cddfSDavid du Colombier ulong uid; /* imap unique identifier */ 1307dd7cddfSDavid du Colombier ulong seq; /* position in box; 1 is oldest */ 1317dd7cddfSDavid du Colombier ulong id; /* number of message directory in upas/fs */ 1327dd7cddfSDavid du Colombier char *fs; /* name of message directory */ 1337dd7cddfSDavid du Colombier char *efs; /* pointer after / in fs; enough space for file name */ 1347dd7cddfSDavid du Colombier 13580ee5cbfSDavid du Colombier ulong size; /* size of fs/rawbody, in bytes, with \r added before \n */ 1367dd7cddfSDavid du Colombier ulong lines; /* number of lines in rawbody */ 1377dd7cddfSDavid du Colombier 1387dd7cddfSDavid du Colombier char *iBuf; 1397dd7cddfSDavid du Colombier char *info[IMax]; /* all info about message */ 1407dd7cddfSDavid du Colombier 1417dd7cddfSDavid du Colombier char *unixDate; 1427dd7cddfSDavid du Colombier MAddr *unixFrom; 1437dd7cddfSDavid du Colombier 1447dd7cddfSDavid du Colombier MAddr *to; /* parsed out address lines */ 1457dd7cddfSDavid du Colombier MAddr *from; 1467dd7cddfSDavid du Colombier MAddr *replyTo; 1477dd7cddfSDavid du Colombier MAddr *sender; 1487dd7cddfSDavid du Colombier MAddr *cc; 1497dd7cddfSDavid du Colombier MAddr *bcc; 1507dd7cddfSDavid du Colombier }; 1517dd7cddfSDavid du Colombier 1527dd7cddfSDavid du Colombier /* 1537dd7cddfSDavid du Colombier * pre-parsed header lines 1547dd7cddfSDavid du Colombier */ 1557dd7cddfSDavid du Colombier struct MAddr 1567dd7cddfSDavid du Colombier { 1577dd7cddfSDavid du Colombier char *personal; 1587dd7cddfSDavid du Colombier char *box; 1597dd7cddfSDavid du Colombier char *host; 1607dd7cddfSDavid du Colombier MAddr *next; 1617dd7cddfSDavid du Colombier }; 1627dd7cddfSDavid du Colombier 1637dd7cddfSDavid du Colombier struct MimeHdr 1647dd7cddfSDavid du Colombier { 1657dd7cddfSDavid du Colombier char *s; 1667dd7cddfSDavid du Colombier char *t; 1677dd7cddfSDavid du Colombier MimeHdr *next; 1687dd7cddfSDavid du Colombier }; 1697dd7cddfSDavid du Colombier 1707dd7cddfSDavid du Colombier /* 1717dd7cddfSDavid du Colombier * mapping of integer & names 1727dd7cddfSDavid du Colombier */ 1737dd7cddfSDavid du Colombier struct NamedInt 1747dd7cddfSDavid du Colombier { 1757dd7cddfSDavid du Colombier char *name; 1767dd7cddfSDavid du Colombier int v; 1777dd7cddfSDavid du Colombier }; 1787dd7cddfSDavid du Colombier 1797dd7cddfSDavid du Colombier /* 1807dd7cddfSDavid du Colombier * lock for all mail file operations 1817dd7cddfSDavid du Colombier */ 1827dd7cddfSDavid du Colombier struct MbLock 1837dd7cddfSDavid du Colombier { 1847dd7cddfSDavid du Colombier int fd; 1857dd7cddfSDavid du Colombier }; 1867dd7cddfSDavid du Colombier 1877dd7cddfSDavid du Colombier /* 1887dd7cddfSDavid du Colombier * parse nodes for imap4rev1 protocol 1897dd7cddfSDavid du Colombier * 1907dd7cddfSDavid du Colombier * important: all of these items are allocated 1917dd7cddfSDavid du Colombier * in one can, so they can be tossed out at the same time. 1927dd7cddfSDavid du Colombier * this allows leakless parse error recovery by simply tossing the can away. 1937dd7cddfSDavid du Colombier * however, it means these structures cannot be mixed with the mailbox structures 1947dd7cddfSDavid du Colombier */ 1957dd7cddfSDavid du Colombier 1967dd7cddfSDavid du Colombier typedef struct Fetch Fetch; 1977dd7cddfSDavid du Colombier typedef struct NList NList; 1987dd7cddfSDavid du Colombier typedef struct SList SList; 1997dd7cddfSDavid du Colombier typedef struct MsgSet MsgSet; 2007dd7cddfSDavid du Colombier typedef struct Store Store; 2017dd7cddfSDavid du Colombier typedef struct Search Search; 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier /* 2047dd7cddfSDavid du Colombier * parse tree for fetch command 2057dd7cddfSDavid du Colombier */ 2067dd7cddfSDavid du Colombier enum 2077dd7cddfSDavid du Colombier { 2087dd7cddfSDavid du Colombier FEnvelope, 2097dd7cddfSDavid du Colombier FFlags, 2107dd7cddfSDavid du Colombier FInternalDate, 2117dd7cddfSDavid du Colombier FRfc822, 2127dd7cddfSDavid du Colombier FRfc822Head, 2137dd7cddfSDavid du Colombier FRfc822Size, 2147dd7cddfSDavid du Colombier FRfc822Text, 2157dd7cddfSDavid du Colombier FBodyStruct, 2167dd7cddfSDavid du Colombier FUid, 2177dd7cddfSDavid du Colombier FBody, /* BODY */ 2187dd7cddfSDavid du Colombier FBodySect, /* BODY [...] */ 2197dd7cddfSDavid du Colombier FBodyPeek, 2207dd7cddfSDavid du Colombier 2217dd7cddfSDavid du Colombier FMax 2227dd7cddfSDavid du Colombier }; 2237dd7cddfSDavid du Colombier 2247dd7cddfSDavid du Colombier enum 2257dd7cddfSDavid du Colombier { 2267dd7cddfSDavid du Colombier FPAll, 2277dd7cddfSDavid du Colombier FPHead, 2287dd7cddfSDavid du Colombier FPHeadFields, 2297dd7cddfSDavid du Colombier FPHeadFieldsNot, 2307dd7cddfSDavid du Colombier FPMime, 2317dd7cddfSDavid du Colombier FPText, 2327dd7cddfSDavid du Colombier 2337dd7cddfSDavid du Colombier FPMax 2347dd7cddfSDavid du Colombier }; 2357dd7cddfSDavid du Colombier 2367dd7cddfSDavid du Colombier struct Fetch 2377dd7cddfSDavid du Colombier { 2387dd7cddfSDavid du Colombier uchar op; /* F.* operator */ 2397dd7cddfSDavid du Colombier uchar part; /* FP.* subpart for body[] & body.peek[]*/ 2407dd7cddfSDavid du Colombier uchar partial; /* partial fetch? */ 2417dd7cddfSDavid du Colombier long start; /* partial fetch amounts */ 2427dd7cddfSDavid du Colombier long size; 2437dd7cddfSDavid du Colombier NList *sect; 2447dd7cddfSDavid du Colombier SList *hdrs; 2457dd7cddfSDavid du Colombier Fetch *next; 2467dd7cddfSDavid du Colombier }; 2477dd7cddfSDavid du Colombier 2487dd7cddfSDavid du Colombier /* 2497dd7cddfSDavid du Colombier * status items 2507dd7cddfSDavid du Colombier */ 2517dd7cddfSDavid du Colombier enum{ 2527dd7cddfSDavid du Colombier SMessages = 1 << 0, 2537dd7cddfSDavid du Colombier SRecent = 1 << 1, 2547dd7cddfSDavid du Colombier SUidNext = 1 << 2, 2557dd7cddfSDavid du Colombier SUidValidity = 1 << 3, 2567dd7cddfSDavid du Colombier SUnseen = 1 << 4, 2577dd7cddfSDavid du Colombier }; 2587dd7cddfSDavid du Colombier 2597dd7cddfSDavid du Colombier /* 2607dd7cddfSDavid du Colombier * parse tree for store command 2617dd7cddfSDavid du Colombier */ 2627dd7cddfSDavid du Colombier enum 2637dd7cddfSDavid du Colombier { 2647dd7cddfSDavid du Colombier STFlags, 2657dd7cddfSDavid du Colombier STFlagsSilent, 2667dd7cddfSDavid du Colombier 2677dd7cddfSDavid du Colombier STMax 2687dd7cddfSDavid du Colombier }; 2697dd7cddfSDavid du Colombier 2707dd7cddfSDavid du Colombier struct Store 2717dd7cddfSDavid du Colombier { 2727dd7cddfSDavid du Colombier uchar sign; 2737dd7cddfSDavid du Colombier uchar op; 2747dd7cddfSDavid du Colombier int flags; 2757dd7cddfSDavid du Colombier }; 2767dd7cddfSDavid du Colombier 2777dd7cddfSDavid du Colombier /* 2787dd7cddfSDavid du Colombier * parse tree for search command 2797dd7cddfSDavid du Colombier */ 2807dd7cddfSDavid du Colombier enum 2817dd7cddfSDavid du Colombier { 2827dd7cddfSDavid du Colombier SKNone, 2837dd7cddfSDavid du Colombier 2847dd7cddfSDavid du Colombier SKCharset, 2857dd7cddfSDavid du Colombier 2867dd7cddfSDavid du Colombier SKAll, 2877dd7cddfSDavid du Colombier SKAnswered, 2887dd7cddfSDavid du Colombier SKBcc, 2897dd7cddfSDavid du Colombier SKBefore, 2907dd7cddfSDavid du Colombier SKBody, 2917dd7cddfSDavid du Colombier SKCc, 2927dd7cddfSDavid du Colombier SKDeleted, 2937dd7cddfSDavid du Colombier SKDraft, 2947dd7cddfSDavid du Colombier SKFlagged, 2957dd7cddfSDavid du Colombier SKFrom, 2967dd7cddfSDavid du Colombier SKHeader, 2977dd7cddfSDavid du Colombier SKKeyword, 2987dd7cddfSDavid du Colombier SKLarger, 2997dd7cddfSDavid du Colombier SKNew, 3007dd7cddfSDavid du Colombier SKNot, 3017dd7cddfSDavid du Colombier SKOld, 3027dd7cddfSDavid du Colombier SKOn, 3037dd7cddfSDavid du Colombier SKOr, 3047dd7cddfSDavid du Colombier SKRecent, 3057dd7cddfSDavid du Colombier SKSeen, 3067dd7cddfSDavid du Colombier SKSentBefore, 3077dd7cddfSDavid du Colombier SKSentOn, 3087dd7cddfSDavid du Colombier SKSentSince, 3097dd7cddfSDavid du Colombier SKSet, 3107dd7cddfSDavid du Colombier SKSince, 3117dd7cddfSDavid du Colombier SKSmaller, 3127dd7cddfSDavid du Colombier SKSubject, 3137dd7cddfSDavid du Colombier SKText, 3147dd7cddfSDavid du Colombier SKTo, 3157dd7cddfSDavid du Colombier SKUid, 3167dd7cddfSDavid du Colombier SKUnanswered, 3177dd7cddfSDavid du Colombier SKUndeleted, 3187dd7cddfSDavid du Colombier SKUndraft, 3197dd7cddfSDavid du Colombier SKUnflagged, 3207dd7cddfSDavid du Colombier SKUnkeyword, 3217dd7cddfSDavid du Colombier SKUnseen, 3227dd7cddfSDavid du Colombier 3237dd7cddfSDavid du Colombier SKMax 3247dd7cddfSDavid du Colombier }; 3257dd7cddfSDavid du Colombier 3267dd7cddfSDavid du Colombier struct Search 3277dd7cddfSDavid du Colombier { 3287dd7cddfSDavid du Colombier int key; 3297dd7cddfSDavid du Colombier char *s; 3307dd7cddfSDavid du Colombier char *hdr; 3317dd7cddfSDavid du Colombier ulong num; 3327dd7cddfSDavid du Colombier int year; 3337dd7cddfSDavid du Colombier int mon; 3347dd7cddfSDavid du Colombier int mday; 3357dd7cddfSDavid du Colombier MsgSet *set; 3367dd7cddfSDavid du Colombier Search *left; 3377dd7cddfSDavid du Colombier Search *right; 3387dd7cddfSDavid du Colombier Search *next; 3397dd7cddfSDavid du Colombier }; 3407dd7cddfSDavid du Colombier 3417dd7cddfSDavid du Colombier struct NList 3427dd7cddfSDavid du Colombier { 3437dd7cddfSDavid du Colombier ulong n; 3447dd7cddfSDavid du Colombier NList *next; 3457dd7cddfSDavid du Colombier }; 3467dd7cddfSDavid du Colombier 3477dd7cddfSDavid du Colombier struct SList 3487dd7cddfSDavid du Colombier { 3497dd7cddfSDavid du Colombier char *s; 3507dd7cddfSDavid du Colombier SList *next; 3517dd7cddfSDavid du Colombier }; 3527dd7cddfSDavid du Colombier 3537dd7cddfSDavid du Colombier struct MsgSet 3547dd7cddfSDavid du Colombier { 3557dd7cddfSDavid du Colombier ulong from; 3567dd7cddfSDavid du Colombier ulong to; 3577dd7cddfSDavid du Colombier MsgSet *next; 3587dd7cddfSDavid du Colombier }; 3597dd7cddfSDavid du Colombier 3607dd7cddfSDavid du Colombier struct Pair 3617dd7cddfSDavid du Colombier { 3627dd7cddfSDavid du Colombier ulong start; 3637dd7cddfSDavid du Colombier ulong stop; 3647dd7cddfSDavid du Colombier }; 3657dd7cddfSDavid du Colombier 36680ee5cbfSDavid du Colombier #include "bin.h" 3677dd7cddfSDavid du Colombier 36880ee5cbfSDavid du Colombier extern Bin *parseBin; 3697dd7cddfSDavid du Colombier extern Biobuf bout; 3707dd7cddfSDavid du Colombier extern Biobuf bin; 371*9a747e4fSDavid du Colombier extern char username[UserNameLen]; 372*9a747e4fSDavid du Colombier extern char mboxDir[MboxNameLen]; 3737dd7cddfSDavid du Colombier extern char *fetchPartNames[FPMax]; 3747dd7cddfSDavid du Colombier extern char *site; 37580ee5cbfSDavid du Colombier extern char *remote; 376*9a747e4fSDavid du Colombier extern int debug; 3777dd7cddfSDavid du Colombier 3787dd7cddfSDavid du Colombier #include "fns.h" 379