📄 imapd.c
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * * ======================================================================== *//* * Program: IMAP4rev1 server * * Author: Mark Crispin * UW Technology * University of Washington * Seattle, WA 98195 * Internet: MRC@Washington.EDU * * Date: 5 November 1990 * Last Edited: 3 March 2008 *//* Parameter files */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include <signal.h>#include <setjmp.h>#include <time.h>#include "c-client.h"#include "newsrc.h"#include <sys/stat.h>#define CRLF PSOUT ("\015\012") /* primary output terpri *//* Timeouts and timers */#define MINUTES *60#define LOGINTIMEOUT 3 MINUTES /* not logged in autologout timer */#define TIMEOUT 30 MINUTES /* RFC 3501 minimum autologout timer */#define INPUTTIMEOUT 5 MINUTES /* timer for additional command input */#define ALERTTIMER 1 MINUTES /* alert check timer */#define SHUTDOWNTIMER 1 MINUTES /* shutdown dally timer */#define IDLETIMER 1 MINUTES /* IDLE command poll timer */#define CHECKTIMER 15 MINUTES /* IDLE command last checkpoint timer */#define LITSTKLEN 20 /* length of literal stack */#define MAXCLIENTLIT 10000 /* maximum non-APPEND client literal size * must be smaller than 4294967295 */#define MAXAPPENDTXT 0x40000000 /* maximum APPEND literal size * must be smaller than 4294967295 */#define CMDLEN 65536 /* size of command buffer *//* Server states */#define LOGIN 0#define SELECT 1#define OPEN 2#define LOGOUT 3/* Body text fetching */typedef struct text_args { char *section; /* body section */ STRINGLIST *lines; /* header lines */ unsigned long first; /* first octet to fetch */ unsigned long last; /* number of octets to fetch */ long flags; /* fetch flags */ long binary; /* binary flags */} TEXTARGS;#define FTB_BINARY 0x1 /* fetch as binary */#define FTB_SIZE 0x2 /* fetch size only *//* Append data */typedef struct append_data { unsigned char *arg; /* append argument pointer */ char *flags; /* message flags */ char *date; /* message date */ char *msg; /* message text */ STRING *message; /* message stringstruct */} APPENDDATA;/* Message pointer */typedef struct msg_data { MAILSTREAM *stream; /* stream */ unsigned long msgno; /* message number */ char *flags; /* current flags */ char *date; /* current date */ STRING *message; /* stringstruct of message */} MSGDATA;/* Function prototypes */int main (int argc,char *argv[]);void ping_mailbox (unsigned long uid);time_t palert (char *file,time_t oldtime);void msg_string_init (STRING *s,void *data,unsigned long size);char msg_string_next (STRING *s);void msg_string_setpos (STRING *s,unsigned long i);void new_flags (MAILSTREAM *stream);void settimeout (unsigned int i);void clkint (void);void kodint (void);void hupint (void);void trmint (void);void staint (void);char *sout (char *s,char *t);char *nout (char *s,unsigned long n,unsigned long base);void slurp (char *s,int n,unsigned long timeout);void inliteral (char *s,unsigned long n);unsigned char *flush (void);void ioerror (FILE *f,char *reason);unsigned char *parse_astring (unsigned char **arg,unsigned long *i, unsigned char *del);unsigned char *snarf (unsigned char **arg);unsigned char *snarf_base64 (unsigned char **arg);unsigned char *snarf_list (unsigned char **arg);STRINGLIST *parse_stringlist (unsigned char **s,int *list);unsigned long uidmax (MAILSTREAM *stream);long parse_criteria (SEARCHPGM *pgm,unsigned char **arg,unsigned long maxmsg, unsigned long maxuid,unsigned long depth);long parse_criterion (SEARCHPGM *pgm,unsigned char **arg,unsigned long msgmsg, unsigned long maxuid,unsigned long depth);long crit_date (unsigned short *date,unsigned char **arg);long crit_date_work (unsigned short *date,unsigned char **arg);long crit_set (SEARCHSET **set,unsigned char **arg,unsigned long maxima);long crit_number (unsigned long *number,unsigned char **arg);long crit_string (STRINGLIST **string,unsigned char **arg);void fetch (char *t,unsigned long uid);typedef void (*fetchfn_t) (unsigned long i,void *args);void fetch_work (char *t,unsigned long uid,fetchfn_t f[],void *fa[]);void fetch_bodystructure (unsigned long i,void *args);void fetch_body (unsigned long i,void *args);void fetch_body_part_mime (unsigned long i,void *args);void fetch_body_part_contents (unsigned long i,void *args);void fetch_body_part_binary (unsigned long i,void *args);void fetch_body_part_header (unsigned long i,void *args);void fetch_body_part_text (unsigned long i,void *args);void remember (unsigned long uid,char *id,SIZEDTEXT *st);void fetch_envelope (unsigned long i,void *args);void fetch_encoding (unsigned long i,void *args);void changed_flags (unsigned long i,int f);void fetch_flags (unsigned long i,void *args);void put_flag (int *c,char *s);void fetch_internaldate (unsigned long i,void *args);void fetch_uid (unsigned long i,void *args);void fetch_rfc822 (unsigned long i,void *args);void fetch_rfc822_header (unsigned long i,void *args);void fetch_rfc822_size (unsigned long i,void *args);void fetch_rfc822_text (unsigned long i,void *args);void penv (ENVELOPE *env);void pbodystructure (BODY *body);void pbody (BODY *body);void pparam (PARAMETER *param);void paddr (ADDRESS *a);void pset (SEARCHSET **set);void pnum (unsigned long i);void pstring (char *s);void pnstring (char *s);void pastring (char *s);void psizedquoted (SIZEDTEXT *s);void psizedliteral (SIZEDTEXT *s,STRING *st);void psizedstring (SIZEDTEXT *s,STRING *st);void psizedastring (SIZEDTEXT *s);void pastringlist (STRINGLIST *s);void pnstringorlist (STRINGLIST *s);void pbodypartstring (unsigned long msgno,char *id,SIZEDTEXT *st,STRING *bs, TEXTARGS *ta);void ptext (SIZEDTEXT *s,STRING *st);void pthread (THREADNODE *thr);void pcapability (long flag);long nameok (char *ref,char *name);char *bboardname (char *cmd,char *name);long isnewsproxy (char *name);long newsproxypattern (char *ref,char *pat,char *pattern,long flag);char *imap_responder (void *challenge,unsigned long clen,unsigned long *rlen);long proxycopy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);long proxy_append (MAILSTREAM *stream,void *data,char **flags,char **date, STRING **message);long append_msg (MAILSTREAM *stream,void *data,char **flags,char **date, STRING **message);void copyuid (MAILSTREAM *stream,char *mailbox,unsigned long uidvalidity, SEARCHSET *sourceset,SEARCHSET *destset);void appenduid (char *mailbox,unsigned long uidvalidity,SEARCHSET *set);char *referral (MAILSTREAM *stream,char *url,long code);void mm_list_work (char *what,int delimiter,char *name,long attributes);char *lasterror (void);/* Global storage */char *version = "404"; /* edit number of this server */char *logout = "Logout"; /* syslogreason for logout */char *goodbye = NIL; /* bye reason */time_t alerttime = 0; /* time of last alert */time_t sysalerttime = 0; /* time of last system alert */time_t useralerttime = 0; /* time of last user alert */time_t lastcheck = 0; /* time of last checkpoint */time_t shutdowntime = 0; /* time of last shutdown */int state = LOGIN; /* server state */int cancelled = NIL; /* authenticate cancelled */int trycreate = 0; /* saw a trycreate */int finding = NIL; /* doing old FIND command */int anonymous = 0; /* non-zero if anonymous */int critical = NIL; /* non-zero if in critical code */int quell_events = NIL; /* non-zero if in FETCH response */int existsquelled = NIL; /* non-zero if an EXISTS was quelled */int proxylist = NIL; /* doing a proxy LIST */MAILSTREAM *stream = NIL; /* mailbox stream */DRIVER *curdriver = NIL; /* note current driver */MAILSTREAM *tstream = NIL; /* temporary mailbox stream */unsigned int nflags = 0; /* current number of keywords */unsigned long nmsgs =0xffffffff;/* last reported # of messages and recent */unsigned long recent = 0xffffffff;char *nntpproxy = NIL; /* NNTP proxy name */unsigned char *user = NIL; /* user name */unsigned char *pass = NIL; /* password */unsigned char *initial = NIL; /* initial response */unsigned char cmdbuf[CMDLEN]; /* command buffer */char *status = "starting up"; /* server status */char *tag; /* tag portion of command */unsigned char *cmd; /* command portion of command */unsigned char *arg; /* pointer to current argument of command */char *lstwrn = NIL; /* last warning message from c-client */char *lsterr = NIL; /* last error message from c-client */char *lstref = NIL; /* last referral from c-client */char *response = NIL; /* command response */struct { unsigned long size; /* size of current LITERAL+ */ unsigned int ok : 1; /* LITERAL+ in effect */} litplus;int litsp = 0; /* literal stack pointer */char *litstk[LITSTKLEN]; /* stack to hold literals */unsigned long uidvalidity = 0; /* last reported UID validity */unsigned long lastuid = 0; /* last fetched uid */char *lastid = NIL; /* last fetched body id for this message */char *lastsel = NIL; /* last selected mailbox name */SIZEDTEXT lastst = {NIL,0}; /* last sizedtext */unsigned long cauidvalidity = 0;/* UIDVALIDITY for COPYUID/APPENDUID */SEARCHSET *csset = NIL; /* COPYUID source set */SEARCHSET *caset = NIL; /* COPYUID/APPENDUID destination set */jmp_buf jmpenv; /* stack context for setjmp *//* Response texts which appear in multiple places */char *win = "%.80s OK ";char *rowin = "%.80s OK [READ-ONLY] %.80s completed\015\012";char *rwwin = "%.80s OK [READ-WRITE] %.80s completed\015\012";char *lose = "%.80s NO ";char *logwin = "%.80s OK [";char *losetry = "%.80s NO [TRYCREATE] %.80s failed: %.900s\015\012";char *loseunknowncte = "%.80s NO [UNKNOWN-CTE] %.80s failed: %.900s\015\012";char *badcmd = "%.80s BAD Command unrecognized: %.80s\015\012";char *misarg = "%.80s BAD Missing or invalid argument to %.80s\015\012";char *badarg = "%.80s BAD Argument given to %.80s when none expected\015\012";char *badseq = "%.80s BAD Bogus sequence in %.80s: %.80s\015\012";char *badatt = "%.80s BAD Bogus attribute list in %.80s\015\012";char *badbin = "%.80s BAD Syntax error in binary specifier\015\012";/* Message string driver for message stringstructs */STRINGDRIVER msg_string = { msg_string_init, /* initialize string structure */ msg_string_next, /* get next byte in string structure */ msg_string_setpos /* set position in string structure */};/* Main program */int main (int argc,char *argv[]){ unsigned long i,uid; long f; unsigned char *s,*t,*u,*v,tmp[MAILTMPLEN]; struct stat sbuf; logouthook_t lgoh; int ret = 0; time_t autologouttime = 0; char *pgmname; /* if case we get borked immediately */ if (setjmp (jmpenv)) _exit (1); pgmname = (argc && argv[0]) ? (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ? (char *) s+1 : argv[0]) : "imapd"; /* set service name before linkage */ mail_parameters (NIL,SET_SERVICENAME,(void *) "imap");#include "linkage.c" rfc822_date (tmp); /* get date/time at startup */ /* initialize server */ server_init (pgmname,"imap","imaps",clkint,kodint,hupint,trmint,staint); /* forbid automatic untagged expunge */ mail_parameters (NIL,SET_EXPUNGEATPING,NIL); /* arm proxy copy callback */ mail_parameters (NIL,SET_MAILPROXYCOPY,(void *) proxycopy); /* arm referral callback */ mail_parameters (NIL,SET_IMAPREFERRAL,(void *) referral); /* arm COPYUID callback */ mail_parameters (NIL,SET_COPYUID,(void *) copyuid); /* arm APPENDUID callback */ mail_parameters (NIL,SET_APPENDUID,(void *) appenduid); if (stat (SHUTDOWNFILE,&sbuf)) { char proxy[MAILTMPLEN]; FILE *nntp = fopen (NNTPFILE,"r"); if (nntp) { /* desire NNTP proxy? */ if (fgets (proxy,MAILTMPLEN,nntp)) { /* remove newline and set NNTP proxy */ if (s = strchr (proxy,'\n')) *s = '\0'; nntpproxy = cpystr (proxy); /* disable the news driver */ mail_parameters (NIL,DISABLE_DRIVER,"news"); } fclose (nntp); /* done reading proxy name */ } s = myusername_full (&i); /* get user name and flags */ switch (i) { case MU_NOTLOGGEDIN: PSOUT ("* OK ["); /* not logged in, ordinary startup */ pcapability (-1); break; case MU_ANONYMOUS: anonymous = T; /* anonymous user, fall into default */ s = "ANONYMOUS"; case MU_LOGGEDIN: PSOUT ("* PREAUTH ["); /* already logged in, pre-authorized */ pcapability (1); user = cpystr (s); /* copy user name */ pass = cpystr ("*"); /* set fake password */ state = SELECT; /* enter select state */ break; default: fatal ("Unknown state from myusername_full()"); } PSOUT ("] "); if (user) { /* preauthenticated as someone? */ PSOUT ("Pre-authenticated user "); PSOUT (user); PBOUT (' '); } } else { /* login disabled */ PSOUT ("* BYE Service not available "); state = LOGOUT; } PSOUT (tcp_serverhost ()); PSOUT (" IMAP4rev1 "); PSOUT (CCLIENTVERSION); PBOUT ('.'); PSOUT (version); PSOUT (" at "); PSOUT (tmp); CRLF; PFLUSH (); /* dump output buffer */ switch (state) { /* do this after the banner */ case LOGIN: autologouttime = time (0) + LOGINTIMEOUT; break; case SELECT: syslog (LOG_INFO,"Preauthenticated user=%.80s host=%.80s", user,tcp_clienthost ()); break; } if (setjmp (jmpenv)) { /* die if a signal handler say so */ /* in case we get borked now */ if (setjmp (jmpenv)) _exit (1); /* need to close stream gracefully? */ if (stream && !stream->lock && (stream->dtb->flags & DR_XPOINT)) stream = mail_close (stream); ret = 1; /* set exit status */ } else while (state != LOGOUT) {/* command processing loop */ slurp (cmdbuf,CMDLEN,TIMEOUT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -