📄 imapd.c
字号:
/* subscribe to mailbox */ else if (!(anonymous || strcmp (cmd,"SUBSCRIBE"))) { /* get <mailbox> or MAILBOX <mailbox> */ if (!(s = snarf (&arg))) response = misarg; else if (arg) { /* IMAP2bis form */ if (compare_cstring (s,"MAILBOX")) response = badarg; else if (!(s = snarf (&arg))) response = misarg; else if (arg) response = badarg; else mail_subscribe (NIL,s); } else if (isnewsproxy (s)) newsrc_update (NIL,s+6,':'); else mail_subscribe (NIL,s); if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } /* unsubscribe to mailbox */ else if (!(anonymous || strcmp (cmd,"UNSUBSCRIBE"))) { /* get <mailbox> or MAILBOX <mailbox> */ if (!(s = snarf (&arg))) response = misarg; else if (arg) { /* IMAP2bis form */ if (compare_cstring (s,"MAILBOX")) response = badarg; else if (!(s = snarf (&arg))) response = misarg; else if (arg) response = badarg; else if (isnewsproxy (s)) newsrc_update (NIL,s+6,'!'); else mail_unsubscribe (NIL,s); } else mail_unsubscribe (NIL,s); if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } else if (!strcmp (cmd,"NAMESPACE")) { if (arg) response = badarg; else { NAMESPACE **ns = (NAMESPACE **) mail_parameters(NIL,GET_NAMESPACE, NIL); NAMESPACE *n; PARAMETER *p; PSOUT ("* NAMESPACE"); if (ns) for (i = 0; i < 3; i++) { if (n = ns[i]) { PSOUT (" ("); do { PBOUT ('('); pstring (n->name); switch (n->delimiter) { case '\\': /* quoted delimiter */ case '"': PSOUT (" \"\\\\\""); break; case '\0': /* no delimiter */ PSOUT (" NIL"); break; default: /* unquoted delimiter */ PSOUT (" \""); PBOUT (n->delimiter); PBOUT ('"'); break; } /* NAMESPACE extensions are hairy */ if (p = n->param) do { PBOUT (' '); pstring (p->attribute); PSOUT (" ("); do pstring (p->value); while (p->next && !p->next->attribute && (p = p->next)); PBOUT (')'); } while (p = p->next); PBOUT (')'); } while (n = n->next); PBOUT (')'); } else PSOUT (" NIL"); } else PSOUT (" NIL NIL NIL"); CRLF; } if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } /* create mailbox */ else if (!(anonymous || strcmp (cmd,"CREATE"))) { if (!(s = snarf (&arg))) response = misarg; else if (arg) response = badarg; else mail_create (NIL,s); if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } /* delete mailbox */ else if (!(anonymous || strcmp (cmd,"DELETE"))) { if (!(s = snarf (&arg))) response = misarg; else if (arg) response = badarg; else { /* make sure not selected */ if (lastsel && (!strcmp (s,lastsel) || (stream && !strcmp (s,stream->mailbox)))) mm_log ("Can not DELETE the selected mailbox",ERROR); else mail_delete (NIL,s); } if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } /* rename mailbox */ else if (!(anonymous || strcmp (cmd,"RENAME"))) { if (!((s = snarf (&arg)) && (t = snarf (&arg)))) response = misarg; else if (arg) response = badarg; else { /* make sure not selected */ if (!compare_cstring (s,"INBOX")) s = "INBOX"; else if (!compare_cstring (s,"#MHINBOX")) s = "#MHINBOX"; if (lastsel && (!strcmp (s,lastsel) || (stream && !strcmp (s,stream->mailbox)))) mm_log ("Can not RENAME the selected mailbox",ERROR); else mail_rename (NIL,s,t); } if (stream) /* allow untagged EXPUNGE */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING,(void *) stream); } /* idle mode */ else if (!strcmp (cmd,"IDLE")) { /* no arguments */ if (arg) response = badarg; else { /* tell client ready for argument */ unsigned long donefake = 0; PSOUT ("+ Waiting for DONE\015\012"); PFLUSH (); /* dump output buffer */ /* inactivity countdown */ i = ((TIMEOUT) / (IDLETIMER)) + 1; do { /* main idle loop */ if (!donefake) { /* don't ping mailbox if faking */ mail_parameters (stream,SET_ONETIMEEXPUNGEATPING, (void *) stream); ping_mailbox (uid); /* maybe do a checkpoint if not anonymous */ if (!anonymous && stream && (time (0) > lastcheck + CHECKTIMER)) { mail_check (stream); /* cancel likely altwin from mail_check() */ if (lsterr) fs_give ((void **) &lsterr); if (lstwrn) fs_give ((void **) &lstwrn); /* remember last checkpoint */ lastcheck = time (0); } } if (lstwrn) { /* have a warning? */ PSOUT ("* NO "); PSOUT (lstwrn); CRLF; fs_give ((void **) &lstwrn); } if (!(i % 2)) { /* prevent NAT timeouts */ sprintf (tmp,"* OK Timeout in %lu minutes\015\012", (i * IDLETIMER) / 60); PSOUT (tmp); } /* two minutes before the end... */ if ((state == OPEN) && (i <= 2)) { sprintf (tmp,"* %lu EXISTS\015\012* %lu RECENT\015\012", donefake = nmsgs + 1,recent + 1); PSOUT (tmp); /* prod client to wake up */ } PFLUSH (); /* dump output buffer */ } while ((state != LOGOUT) && !INWAIT (IDLETIMER) && --i); /* time to exit idle loop */ if (state != LOGOUT) { if (i) { /* still have time left? */ /* yes, read expected DONE */ slurp (tmp,MAILTMPLEN,INPUTTIMEOUT); if (((tmp[0] != 'D') && (tmp[0] != 'd')) || ((tmp[1] != 'O') && (tmp[1] != 'o')) || ((tmp[2] != 'N') && (tmp[2] != 'n')) || ((tmp[3] != 'E') && (tmp[3] != 'e')) || (((tmp[4] != '\015') || (tmp[5] != '\012')) && (tmp[4] != '\012'))) response = "%.80s BAD Bogus IDLE continuation\015\012"; if (donefake) { /* if faking at the end */ /* send EXPUNGE (should be just 1) */ while (donefake > nmsgs) { sprintf (tmp,"* %lu EXPUNGE\015\012",donefake--); PSOUT (tmp); } sprintf (tmp,"* %lu EXISTS\015\012* %lu RECENT\015\012", nmsgs,recent); PSOUT (tmp); } } else clkint (); /* otherwise do autologout action */ } } } else response = badcmd; break; default: response = "%.80s BAD Unknown state for %.80s command\015\012"; break; } while (litplus.ok) { /* any unread LITERAL+? */ litplus.ok = NIL; /* yes, cancel it now */ clearerr (stdin); /* clear stdin errors */ status = "discarding unread literal"; /* read literal and discard it */ while (i = (litplus.size > MAILTMPLEN) ? MAILTMPLEN : litplus.size) { if (state == LOGOUT) litplus.size = 0; else { settimeout (INPUTTIMEOUT); if (PSINR (tmp,i)) litplus.size -= i; else { ioerror (stdin,status); litplus.size = 0; /* in case it continues */ } } } settimeout (0); /* stop timeout */ /* get new command tail */ slurp (tmp,MAILTMPLEN,INPUTTIMEOUT); /* locate end of line */ if (t = strchr (tmp,'\012')) { /* back over CR */ if ((t > tmp) && (t[-1] == '\015')) --t; *t = NIL; /* tie off CRLF */ /* possible LITERAL+? */ if (((i = strlen (tmp)) > 3) && (tmp[i - 1] == '}') && (tmp[i - 2] == '+') && isdigit (tmp[i - 3])) { /* back over possible count */ for (i -= 4; i && isdigit (tmp[i]); i--); if (tmp[i] == '{') { /* found a literal? */ litplus.ok = T; /* yes, note LITERAL+ in effect, set size */ litplus.size = strtoul (tmp + i + 1,NIL,10); } } } else flush (); /* overlong line after LITERAL+, punt */ } ping_mailbox (uid); /* update mailbox status before response */ if (lstwrn && lsterr) { /* output most recent warning */ PSOUT ("* NO "); PSOUT (lstwrn); CRLF; fs_give ((void **) &lstwrn); } if (response == logwin) { /* authentication win message */ sprintf (tmp,response,lstref ? "*" : tag); PSOUT (tmp); /* start response */ pcapability (1); /* print logged-in capabilities */ PSOUT ("] User "); PSOUT (user); PSOUT (" authenticated\015\012"); if (lstref) { sprintf (tmp,response,tag); PSOUT (tmp); /* start response */ PSOUT ("[REFERRAL "); PSOUT (lstref); PSOUT ("] "); PSOUT (lasterror ()); CRLF; } } else if ((response == win) || (response == lose)) { sprintf (tmp,response,tag); PSOUT (tmp); if (cauidvalidity) { /* COPYUID/APPENDUID response? */ sprintf (tmp,"[%.80sUID %lu ",(char *) ((s = strchr (cmd,' ')) ? s+1 : cmd),cauidvalidity); PSOUT (tmp); cauidvalidity = 0; /* cancel response for future */ if (csset) { pset (&csset); PBOUT (' '); } pset (&caset); PSOUT ("] "); } else if (lstref) { /* have a referral? */ PSOUT ("[REFERRAL "); PSOUT (lstref); PSOUT ("] "); } if (lsterr || lstwrn) PSOUT (lasterror ()); else { PSOUT (cmd); PSOUT ((response == win) ? " completed" : "failed"); } CRLF; } else { /* normal response */ if ((response == rowin) || (response == rwwin)) { if (lstwrn) { /* output most recent warning */ PSOUT ("* NO "); PSOUT (lstwrn); CRLF; fs_give ((void **) &lstwrn); } } sprintf (tmp,response,tag,cmd,lasterror ()); PSOUT (tmp); /* output response */ } } PFLUSH (); /* make sure output blatted */ if (autologouttime) { /* have an autologout in effect? */ /* cancel if no longer waiting for login */ if (state != LOGIN) autologouttime = 0; /* took too long to login */ else if (autologouttime < time (0)) { logout = goodbye = "Autologout"; stream = NIL; state = LOGOUT; /* sayonara */ } } } if (goodbye && !quell_events){/* have a goodbye message? */ PSOUT ("* BYE "); /* utter it */ PSOUT (goodbye); CRLF; PFLUSH (); /* make sure blatted */ } syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout, user ? (char *) user : "???",tcp_clienthost ()); /* do logout hook if needed */ if (lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL)) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL)); _exit (ret); /* all done */ return ret; /* stupid compilers */}/* Ping mailbox during each cycle. Also check alerts * Accepts: last command was UID flag */void ping_mailbox (unsigned long uid){ unsigned long i; char tmp[MAILTMPLEN]; if (state == OPEN) { if (!mail_ping (stream)) { /* make sure stream still alive */ PSOUT ("* BYE "); PSOUT (mylocalhost ()); PSOUT (" Fatal mailbox error: "); PSOUT (lasterror ()); CRLF; stream = NIL; /* don't try to clean up stream */ state = LOGOUT; /* go away */ syslog (LOG_INFO, "Fatal mailbox error user=%.80s host=%.80s mbx=%.80s: %.80s", user ? (char *) user : "???",tcp_clienthost (), (stream && stream->mailbox) ? stream->mailbox : "???", lasterror ()); return; } /* change in number of messages? */ if (existsquelled || (nmsgs != stream->nmsgs)) { PSOUT ("* "); pnum (nmsgs = stream->nmsgs); PSOUT (" EXISTS\015\012"); } /* change in recent messages? */ if (existsquelled || (recent != stream->recent)) { PSOUT ("* "); pnum (recent = stream->recent); PSOUT (" RECENT\015\012"); } existsquelled = NIL; /* don't do this until asked again */ if (stream->uid_validity && (stream->uid_validity != uidvalidity)) { PSOUT ("* OK [UIDVALIDITY "); pnum (stream->uid_validity); PSOUT ("] UID validity status\015\012* OK [UIDNEXT "); pnum (stream->uid_last + 1); PSOUT ("] Predicted next UID\015\012"); if (stream->uid_nosticky) { PSOUT ("* NO [UIDNOTSTICKY] Non-permanent unique identifiers: "); PSOUT (stream->mailbox); CRLF; } uidvalidity = stream->uid_validity; } /* don't bother if driver changed */ if (curdriver == stream->dtb) { /* first report any new flags */ if ((nflags < NUSERFLAGS) && stream->user_flags[nflags]) new_flags (stream); for (i = 1; i <= nmsgs; i++) if (mail_elt (stream,i)->spare2) { PSOUT ("* "); pnum (i); PSOUT (" FETCH ("); fetch_flags (i,NIL); /* output changed flags */ if (uid) { /* need to include UIDs in response? */ PBOUT (' '); fetch_uid (i,NIL); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -