📄 imapd.c
字号:
/* * Program: IMAP4rev1 server * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 5 November 1990 * Last Edited: 13 October 2000 * * Copyright 2000 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appears in all copies and that both the * above copyright notice and this permission notice appear in supporting * documentation, and that the name of the University of Washington not be * used in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. This software is made * available "as is", and * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *//* Primary I/O calls */#define PBIN getchar /* primary byte input */ /* primary string input */#define PSIN(s,n) fgets (s,n,stdin)#define PBOUT(c) putchar (c) /* primary byte output */ /* primary string output */#define PSOUT(s) fputs (s,stdout)#define PFLUSH fflush (stdout) /* flush primary output */#define CRLF PSOUT ("\015\012") /* primary output terpri */ /* server input wait */#define INWAIT(t) server_input_wait (t)/* Parameter files */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include <signal.h>#include <time.h>#include "c-client.h"#include <sys/stat.h>/* Timeouts and timers */#define MINUTES *60#define LOGINTIMEOUT 3 MINUTES /* not logged in autologout timer */#define TIMEOUT 30 MINUTES /* RFC 2060 minimum autologout timer */#define ALERTTIMER 1 MINUTES /* alert check 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 */#define TMPLEN 8192 /* size of temporary buffers *//* 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; /* flags */} TEXTARGS;/* Append data */typedef struct append_data { 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; /* strintstruct 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 clkint (void);void kodint (void);void hupint (void);void trmint (void);void slurp (char *s,int n);char inchar (void);char *flush (void);char *parse_astring (char **arg,unsigned long *i,char *del);char *snarf (char **arg);char *snarf_list (char **arg);STRINGLIST *parse_stringlist (char **s,int *list);long parse_criteria (SEARCHPGM *pgm,char **arg,unsigned long maxmsg, unsigned long maxuid,unsigned long depth);long parse_criterion (SEARCHPGM *pgm,char **arg,unsigned long msgmsg, unsigned long maxuid,unsigned long depth);long crit_date (unsigned short *date,char **arg);long crit_date_work (unsigned short *date,char **arg);long crit_set (SEARCHSET **set,char **arg,unsigned long maxima);long crit_number (unsigned long *number,char **arg);long crit_string (STRINGLIST **string,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_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_rfc822_header_lines (unsigned long i,void *args);void fetch_rfc822_header_lines_not (unsigned long i,void *args);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 pnum (unsigned long i);void pstring (char *s);void pnstring (char *label,SIZEDTEXT *st);void pastring (char *s);void pbodypartstring (unsigned long msgno,char *id,SIZEDTEXT *st,TEXTARGS *ta);void pstringorlist (STRINGLIST *s);void pstringlist (STRINGLIST *s);void psizedtext (SIZEDTEXT *s);void ptext (SIZEDTEXT *s);void pthread (THREADNODE *thr);void pcapability (long flag);long nameok (char *ref,char *name);char *bboardname (char *cmd,char *name);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 mm_list_work (char *what,int delimiter,char *name,long attributes);char *lasterror (void);/* Global storage */char *version = "2000.282"; /* version number of this server */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 */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 */MAILSTREAM *stream = NIL; /* mailbox stream */DRIVER *curdriver = NIL; /* note current driver */MAILSTREAM *tstream = NIL; /* temporary mailbox stream */unsigned long nmsgs =0xffffffff;/* last reported # of messages and recent */unsigned long recent = 0xffffffff;char *user = NIL; /* user name */char *pass = NIL; /* password */char cmdbuf[TMPLEN]; /* command buffer */char *tag; /* tag portion of command */char *cmd; /* command portion of command */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 *response = NIL; /* command response */int litsp = 0; /* literal stack pointer */char *litstk[LITSTKLEN]; /* stack to hold literals */unsigned long lastuid = 0; /* last fetched uid */char *lastid = NIL; /* last fetched body id for this message */SIZEDTEXT lastst = {NIL,0}; /* last sizedtext *//* Response texts which appear in multiple places */char *win = "%.80s OK %.80s completed\015\012";char *altwin = "%.80s OK %.900s\015\012";char *lose = "%.80s NO %.80s failed: %.900s\015\012";char *losetry = "%.80s NO [TRYCREATE] %.80s failed: %.900s\015\012";char *misarg = "%.80s BAD Missing required 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\015\012";char *badatt = "%.80s BAD Bogus attribute list in %.80s\015\012";char *argrdy = "+ Ready for argument\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,j,k,m,uid; long f; char *s,*t,*u,*v,tmp[MAILTMPLEN]; struct stat sbuf; time_t autologouttime = 0;#include "linkage.c" rfc822_date (tmp); /* get date/time at startup */ /* initialize server */ server_init (argv[0],"imap","imaps","imap",clkint,kodint,hupint,trmint); /* forbid automatic untagged expunge */ mail_parameters (NIL,SET_EXPUNGEATPING,NIL); /* arm proxy copy callback */ mail_parameters (NIL,SET_MAILPROXYCOPY,(void *) proxycopy); 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 ("] "); PSOUT (tcp_serverhost ()); PSOUT (" IMAP4rev1 "); 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; } do { /* command processing loop */ slurp (cmdbuf,TMPLEN); /* slurp command */ /* no more last error or literal */ if (lstwrn) fs_give ((void **) &lstwrn); if (lsterr) fs_give ((void **) &lsterr); while (litsp) fs_give ((void **) &litstk[--litsp]); /* find end of line */ if (!strchr (cmdbuf,'\012')) { if (t = strchr (cmdbuf,' ')) *t = '\0'; if ((t - cmdbuf) > 100) t = NIL; flush (); /* flush excess */ if (state == LOGIN) /* error if NLI */ syslog (LOG_INFO,"Line too long before authentication host=%.80s", tcp_clienthost ()); sprintf (tmp,response,t ? cmdbuf : "*"); PSOUT (tmp); } else if (!(tag = strtok (cmdbuf," \015\012"))) { if (state == LOGIN) /* error if NLI */ syslog (LOG_INFO,"Null command before authentication host=%.80s", tcp_clienthost ()); PSOUT ("* BAD Null command\015\012"); } else if (strlen (tag) > 50) PSOUT ("* BAD Excessively long tag\015\012"); else if (!(cmd = strtok (NIL," \015\012"))) { if (state == LOGIN) /* error if NLI */ syslog (LOG_INFO,"Missing command before authentication host=%.80s", tcp_clienthost ()); PSOUT (tag); PSOUT (" BAD Missing command\015\012"); } else { /* parse command */ response = win; /* set default response */ finding = NIL; /* no longer FINDing */ ucase (cmd); /* canonicalize command case */ /* UID command? */ if (!strcmp (cmd,"UID") && strtok (NIL," \015\012")) { uid = T; /* a UID command */ cmd[3] = ' '; /* restore the space delimiter */ ucase (cmd); /* make sure command all uppercase */ } else uid = NIL; /* not a UID command */ /* snarf argument */ arg = strtok (NIL,"\015\012"); /* these commands always valid */ if (!strcmp (cmd,"NOOP")) { if (arg) response = badarg; else if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } else if (!strcmp (cmd,"LOGOUT")) { if (arg) response = badarg; else { /* time to say farewell */ server_init (NIL,NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (state == OPEN) mail_close (stream); state = LOGOUT; stream = NIL; PSOUT ("* BYE "); PSOUT (mylocalhost ()); PSOUT (" IMAP4rev1 server terminating connection\015\012"); } } else if (!strcmp (cmd,"CAPABILITY")) { if (arg) response = badarg; else { PSOUT ("* "); pcapability (0); /* print capabilities */ CRLF; } if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -