📄 imapd.c
字号:
/* no more last error or literal */ if (lstwrn) fs_give ((void **) &lstwrn); if (lsterr) fs_give ((void **) &lsterr); if (lstref) fs_give ((void **) &lstref); 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 ? (char *) 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 (!(s = 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 (s); /* canonicalize command case */ /* UID command? */ if (!strcmp (s,"UID") && strtok (NIL," \015\012")) { uid = T; /* a UID command */ s[3] = ' '; /* restore the space delimiter */ ucase (s); /* make sure command all uppercase */ } else uid = NIL; /* not a UID command */ /* flush previous saved command */ if (cmd) fs_give ((void **) &cmd); cmd = cpystr (s); /* save current command */ /* snarf argument, see if possible litplus */ if ((arg = strtok (NIL,"\015\012")) && ((i = strlen (arg)) > 3) && (arg[i - 1] == '}') && (arg[i - 2] == '+') && isdigit (arg[i - 3])) { /* back over possible count */ for (i -= 4; i && isdigit (arg[i]); i--); if (arg[i] == '{') { /* found a literal? */ litplus.ok = T; /* yes, note LITERAL+ in effect, set size */ litplus.size = strtoul (arg + i + 1,NIL,10); } } /* 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,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); if (lastsel) fs_give ((void **) &lastsel); if (state == OPEN) stream = mail_close (stream); state = LOGOUT; 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); }#ifdef NETSCAPE_BRAIN_DAMAGE else if (!strcmp (cmd,"NETSCAPE")) { PSOUT ("* OK [NETSCAPE]\015\012* VERSION 1.0 UNIX\015\012* ACCOUNT-URL \""); PSOUT (NETSCAPE_BRAIN_DAMAGE); PBOUT ('"'); CRLF; }#endif else switch (state) { /* dispatch depending upon state */ case LOGIN: /* waiting to get logged in */ /* new style authentication */ if (!strcmp (cmd,"AUTHENTICATE")) { if (user) fs_give ((void **) &user); if (pass) fs_give ((void **) &pass); initial = NIL; /* no initial argument */ cancelled = NIL; /* not cancelled */ /* mandatory first argument */ if (!(s = snarf (&arg))) response = misarg; else if (arg && !(initial = snarf_base64 (&arg))) response = misarg; /* optional second argument */ else if (arg) response = badarg; else if (!strcmp (ucase (s),"ANONYMOUS") && !stat (ANOFILE,&sbuf)) { if (!(s = imap_responder ("",0,NIL))) response ="%.80s BAD AUTHENTICATE ANONYMOUS cancelled\015\012"; else if (anonymous_login (argc,argv)) { anonymous = T; /* note we are anonymous */ user = cpystr ("ANONYMOUS"); pass = cpystr ("*"); state = SELECT; /* make select */ alerttime = 0; /* force alert */ response = logwin;/* return logged-in capabilities */ syslog (LOG_INFO,"Authenticated anonymous=%.80s host=%.80s",s, tcp_clienthost ()); fs_give ((void **) &s); } else response ="%.80s NO AUTHENTICATE ANONYMOUS failed\015\012"; } else if (user = cpystr (mail_auth (s,imap_responder,argc,argv))) { pass = cpystr ("*"); state = SELECT; /* make select */ alerttime = 0; /* force alert */ response = logwin; /* return logged-in capabilities */ syslog (LOG_INFO,"Authenticated user=%.80s host=%.80s mech=%.80s", user,tcp_clienthost (),s); } else { AUTHENTICATOR *auth = mail_lookup_auth (1); char *msg = (char *) fs_get (strlen (cmd) + strlen (s) + 2); sprintf (msg,"%s %s",cmd,s); fs_give ((void **) &cmd); cmd = msg; for (i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL); auth && compare_cstring (s,auth->name); auth = auth->next); /* Failed authentication when hidden looks like invalid command. * This is intentional but confused me when I was debugging. */ if (auth && auth->server && !(auth->flags & AU_DISABLE) && !(auth->flags & AU_HIDE) && (i || (auth->flags & AU_SECURE))) { response = lose; if (cancelled) { if (lsterr) fs_give ((void **) &lsterr); lsterr = cpystr ("cancelled by user"); } if (!lsterr) /* catch-all */ lsterr = cpystr ("Invalid authentication credentials"); syslog (LOG_INFO,"AUTHENTICATE %.80s failure host=%.80s",s, tcp_clienthost ()); } else { response = badcmd; syslog (LOG_INFO,"AUTHENTICATE %.80s invalid host=%.80s",s, tcp_clienthost ()); } } } /* plaintext login with password */ else if (!strcmp (cmd,"LOGIN")) { if (user) fs_give ((void **) &user); if (pass) fs_give ((void **) &pass); /* two arguments */ if (!((user = cpystr (snarf (&arg))) && (pass = cpystr (snarf (&arg))))) response = misarg; else if (arg) response = badarg; /* see if we allow anonymous */ else if (!compare_cstring (user,"ANONYMOUS") && !stat (ANOFILE,&sbuf) && anonymous_login (argc,argv)) { anonymous = T; /* note we are anonymous */ ucase (user); /* make all uppercase for consistency */ state = SELECT; /* make select */ alerttime = 0; /* force alert */ response = logwin; /* return logged-in capabilities */ syslog (LOG_INFO,"Login anonymous=%.80s host=%.80s",pass, tcp_clienthost ()); } else { /* delimit user from possible admin */ if (s = strchr (user,'*')) *s++ ='\0'; /* see if username and password are OK */ if (server_login (user,pass,s,argc,argv)) { state = SELECT; /* make select */ alerttime = 0; /* force alert */ response = logwin;/* return logged-in capabilities */ syslog (LOG_INFO,"Login user=%.80s host=%.80s",user, tcp_clienthost ()); } else { response = lose; if (!lsterr) lsterr = cpystr ("Invalid login credentials"); } } } /* start TLS security */ else if (!strcmp (cmd,"STARTTLS")) { if (arg) response = badarg; else if (lsterr = ssl_start_tls (pgmname)) response = lose; } else response = badcmd; break; case OPEN: /* valid only when mailbox open */ /* fetch mailbox attributes */ if (!strcmp (cmd,"FETCH") || !strcmp (cmd,"UID FETCH")) { if (!(arg && (s = strtok (arg," ")) && (t = strtok(NIL,"\015\012")))) response = misarg; else if (uid ? mail_uid_sequence (stream,s) : mail_sequence (stream,s)) fetch (t,uid); else response = badseq; } /* store mailbox attributes */ else if (!strcmp (cmd,"STORE") || !strcmp (cmd,"UID STORE")) { /* must have three arguments */ if (!(arg && (s = strtok (arg," ")) && (v = strtok (NIL," ")) && (t = strtok (NIL,"\015\012")))) response = misarg; else if (!(uid ? mail_uid_sequence (stream,s) : mail_sequence (stream,s))) response = badseq; else { f = ST_SET | (uid ? ST_UID : NIL)|((v[5]&&v[6]) ? ST_SILENT : NIL); if (!strcmp (ucase (v),"FLAGS") || !strcmp (v,"FLAGS.SILENT")) { strcpy (tmp,"\\Answered \\Flagged \\Deleted \\Draft \\Seen"); for (i = 0, u = tmp; (i < NUSERFLAGS) && (v = stream->user_flags[i]); i++) if (strlen (v) < ((size_t) (MAILTMPLEN - ((u += strlen (u)) + 2 - tmp)))) { *u++ = ' '; /* write next flag */ strcpy (u,v); } mail_flag (stream,s,tmp,f & ~ST_SET); } else if (!strcmp (v,"-FLAGS") || !strcmp (v,"-FLAGS.SILENT")) f &= ~ST_SET; /* clear flags */ else if (strcmp (v,"+FLAGS") && strcmp (v,"+FLAGS.SILENT")) { response = badatt; break; } /* find last keyword */ for (i = 0; (i < NUSERFLAGS) && stream->user_flags[i]; i++); mail_flag (stream,s,t,f); /* any new keywords appeared? */ if (i < NUSERFLAGS && stream->user_flags[i]) new_flags (stream); /* return flags if silence not wanted */ if (uid ? mail_uid_sequence (stream,s) : mail_sequence (stream,s)) for (i = 1; i <= nmsgs; i++) if (mail_elt(stream,i)->sequence) mail_elt (stream,i)->spare2 = (f & ST_SILENT) ? NIL : T; } } /* check for new mail */ else if (!strcmp (cmd,"CHECK")) { /* no arguments */ if (arg) response = badarg; else if (!anonymous) { mail_check (stream); /* remember last check time */ lastcheck = time (0); } } /* expunge deleted messages */ else if (!(anonymous || (strcmp (cmd,"EXPUNGE") && strcmp (cmd,"UID EXPUNGE")))) { if (uid && !arg) response = misarg; else if (!uid && arg) response = badarg; else { /* expunge deleted or specified UIDs */ mail_expunge_full (stream,arg,arg ? EX_UID : NIL); /* remember last checkpoint */ lastcheck = time (0); } } /* close mailbox */ else if (!strcmp (cmd,"CLOSE") || !strcmp (cmd,"UNSELECT")) { /* no arguments */ if (arg) response = badarg; else { /* no last uid */ uidvalidity = lastuid = 0; if (lastsel) fs_give ((void **) &lastsel); if (lastid) fs_give ((void **) &lastid); if (lastst.data) fs_give ((void **) &lastst.data); stream = mail_close_full (stream,((*cmd == 'C') && !anonymous) ? CL_EXPUNGE : NIL); state = SELECT; /* no longer opened */ lastcheck = 0; /* no last checkpoint */ } } else if (!anonymous && /* copy message(s) */ (!strcmp (cmd,"COPY") || !strcmp (cmd,"UID COPY"))) { trycreate = NIL; /* no trycreate status */ if (!(arg && (s = strtok (arg," ")) && (arg = strtok(NIL,"\015\012")) && (t = snarf (&arg)))) response = misarg; else if (arg) response = badarg; else if (!nmsgs) { response = lose; if (!lsterr) lsterr = cpystr ("Mailbox is empty"); } else if (!(uid ? mail_uid_sequence (stream,s) : mail_sequence (stream,s))) response = badseq; /* try copy */ else if (!mail_copy_full (stream,s,t,uid ? CP_UID : NIL)) { response = trycreate ? losetry : lose; if (!lsterr) lsterr = cpystr ("No such destination mailbox"); } } /* sort mailbox */ else if (!strcmp (cmd,"SORT") || !strcmp (cmd,"UID SORT")) { /* must have four arguments */ if (!(arg && (*arg == '(') && (t = strchr (s = arg + 1,')')) && (t[1] == ' ') && (*(arg = t + 2)))) response = misarg; else { /* read criteria */ SEARCHPGM *spg = NIL; char *cs = NIL; SORTPGM *pgm = NIL,*pg = NIL; unsigned long *slst,*sl; *t = NIL; /* tie off criteria list */ if (!(s = strtok (ucase (s)," "))) response = badatt; else { do { /* parse sort attributes */ if (pg) pg = pg->next = mail_newsortpgm (); else pgm = pg = mail_newsortpgm (); if (!strcmp (s,"REVERSE")) { pg->reverse = T; if (!(s = strtok (NIL," "))) { s = ""; /* end of attributes */ break; } } if (!strcmp (s,"DATE")) pg->function = SORTDATE; else if (!strcmp (s,"ARRIVAL")) pg->function = SORTARRIVAL; else if (!strcmp (s,"FROM")) pg->function = SORTFROM; else if (!strcmp (s,"SUBJECT")) pg->function = SORTSUBJECT; else if (!strcmp (s,"TO")) pg->function = SORTTO; else if (!strcmp (s,"CC")) pg->function = SORTCC; else if (!strcmp (s,"SIZE")) pg->function = SORTSIZE; else break; } while (s = strtok (NIL," ")); /* bad SORT attribute */ if (s) response = badatt; /* get charset and search criteria */ else if (!((t = snarf (&arg)) && (cs = cpystr (t)) && arg && *arg)) response = misarg; /* parse search criteria */ else if (!parse_criteria (spg = mail_newsearchpgm (),&arg,nmsgs, uidmax (stream),0)) response = badatt; else if (arg && *arg) response = badarg; else if (slst = mail_sort (stream,cs,spg,pgm,uid ? SE_UID:NIL)) { PSOUT ("* SORT"); for (sl = slst; *sl; sl++) { PBOUT (' '); pnum (*sl); } CRLF; fs_give ((void **) &slst); } } if (pgm) mail_free_sortpgm (&pgm); if (spg) mail_free_searchpgm (&spg); if (cs) fs_give ((void **) &cs); } } /* thread mailbox */ else if (!strcmp (cmd,"THREAD") || !strcmp (cmd,"UID THREAD")) { THREADNODE *thr; SEARCHPGM *spg = NIL; char *cs = NIL; /* must have four arguments */ if (!(arg && (s = strtok (arg," ")) && (cs = strtok (NIL," ")) && (cs = cpystr (cs)) && (arg = strtok (NIL,"\015\012")))) response = misarg; else if (!parse_criteria (spg = mail_newsearchpgm (),&arg,nmsgs, uidmax (stream),0)) response = badatt; else if (arg && *arg) response = badarg; else { if (thr = mail_thread (stream,s,cs,spg,uid ? SE_UID : NIL)) { PSOUT ("* THREAD "); pthread (thr); mail_free_threadnode (&thr); } else PSOUT ("* THREAD"); CRLF; } if (spg) mail_free_searchpgm (&spg); if (cs) fs_give ((void **) &cs); } /* search mailbox */ else if (!strcmp (cmd,"SEARCH") || !strcmp (cmd,"UID SEARCH")) { int retval = NIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -