📄 mail.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: Mailbox Access routines * * Author: Mark Crispin * UW Technology * University of Washington * Seattle, WA 98195 * Internet: MRC@Washington.EDU * * Date: 22 November 1989 * Last Edited: 15 April 2008 */#include <ctype.h>#include <stdio.h>#include <time.h>#include "c-client.h"char *UW_copyright = "Copyright 1988-2007 University of Washington\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n";/* c-client global data */ /* version of this library */static char *mailcclientversion = CCLIENTVERSION; /* list of mail drivers */static DRIVER *maildrivers = NIL; /* list of authenticators */static AUTHENTICATOR *mailauthenticators = NIL; /* SSL driver pointer */static NETDRIVER *mailssldriver = NIL; /* pointer to alternate gets function */static mailgets_t mailgets = NIL; /* pointer to read progress function */static readprogress_t mailreadprogress = NIL; /* mail cache manipulation function */static mailcache_t mailcache = mm_cache; /* RFC-822 output generator */static rfc822out_t mail822out = NIL; /* RFC-822 output generator (new style) */static rfc822outfull_t mail822outfull = NIL; /* SMTP verbose callback */static smtpverbose_t mailsmtpverbose = mm_dlog; /* proxy copy routine */static mailproxycopy_t mailproxycopy = NIL; /* RFC-822 external line parse */static parseline_t mailparseline = NIL; /* RFC-822 external phrase parser */static parsephrase_t mailparsephrase = NIL;static kinit_t mailkinit = NIL; /* application kinit callback */ /* note network sent command */static sendcommand_t mailsendcommand = NIL; /* newsrc file name decision function */static newsrcquery_t mailnewsrcquery = NIL; /* ACL results callback */static getacl_t mailaclresults = NIL; /* list rights results callback */static listrights_t maillistrightsresults = NIL; /* my rights results callback */static myrights_t mailmyrightsresults = NIL; /* quota results callback */static quota_t mailquotaresults = NIL; /* quota root results callback */static quotaroot_t mailquotarootresults = NIL; /* sorted results callback */static sortresults_t mailsortresults = NIL; /* threaded results callback */static threadresults_t mailthreadresults = NIL; /* COPY UID results */static copyuid_t mailcopyuid = NIL; /* APPEND UID results */static appenduid_t mailappenduid = NIL; /* free elt extra stuff callback */static freeeltsparep_t mailfreeeltsparep = NIL; /* free envelope extra stuff callback */static freeenvelopesparep_t mailfreeenvelopesparep = NIL; /* free body extra stuff callback */static freebodysparep_t mailfreebodysparep = NIL; /* free stream extra stuff callback */static freestreamsparep_t mailfreestreamsparep = NIL; /* SSL start routine */static sslstart_t mailsslstart = NIL; /* SSL certificate query */static sslcertificatequery_t mailsslcertificatequery = NIL; /* SSL client certificate */static sslclientcert_t mailsslclientcert = NIL; /* SSL client private key */static sslclientkey_t mailsslclientkey = NIL; /* SSL failure notify */static sslfailure_t mailsslfailure = NIL; /* snarf interval */static long mailsnarfinterval = 60; /* snarf preservation */static long mailsnarfpreserve = NIL; /* newsrc name uses canonical host */static long mailnewsrccanon = LONGT; /* supported threaders */static THREADER mailthreadordsub = { "ORDEREDSUBJECT",mail_thread_orderedsubject,NIL};static THREADER mailthreadlist = { "REFERENCES",mail_thread_references,&mailthreadordsub}; /* server name */static char *servicename = "unknown"; /* server externally-set authentication ID */static char *externalauthid = NIL;static int expungeatping = T; /* mail_ping() may call mm_expunged() */static int trysslfirst = NIL; /* always try SSL first */static int notimezones = NIL; /* write timezones in "From " header */static int trustdns = T; /* do DNS canonicalization */static int saslusesptrname = T; /* SASL uses name from DNS PTR lookup */ /* trustdns also must be set */static int debugsensitive = NIL;/* debug telemetry includes sensitive data *//* Default mail cache handler * Accepts: pointer to cache handle * message number * caching function * Returns: cache data */void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op){ size_t n; void *ret = NIL; unsigned long i; switch ((int) op) { /* what function? */ case CH_INIT: /* initialize cache */ if (stream->cache) { /* flush old cache contents */ while (stream->cachesize) { mm_cache (stream,stream->cachesize,CH_FREE); mm_cache (stream,stream->cachesize--,CH_FREESORTCACHE); } fs_give ((void **) &stream->cache); fs_give ((void **) &stream->sc); stream->nmsgs = 0; /* can't have any messages now */ } break; case CH_SIZE: /* (re-)size the cache */ if (!stream->cache) { /* have a cache already? */ /* no, create new cache */ n = (stream->cachesize = msgno + CACHEINCREMENT) * sizeof (void *); stream->cache = (MESSAGECACHE **) memset (fs_get (n),0,n); stream->sc = (SORTCACHE **) memset (fs_get (n),0,n); } /* is existing cache size large neough */ else if (msgno > stream->cachesize) { i = stream->cachesize; /* remember old size */ n = (stream->cachesize = msgno + CACHEINCREMENT) * sizeof (void *); fs_resize ((void **) &stream->cache,n); fs_resize ((void **) &stream->sc,n); while (i < stream->cachesize) { stream->cache[i] = NIL; stream->sc[i++] = NIL; } } break; case CH_MAKEELT: /* return elt, make if necessary */ if (!stream->cache[msgno - 1]) stream->cache[msgno - 1] = mail_new_cache_elt (msgno); /* falls through */ case CH_ELT: /* return elt */ ret = (void *) stream->cache[msgno - 1]; break; case CH_SORTCACHE: /* return sortcache entry, make if needed */ if (!stream->sc[msgno - 1]) stream->sc[msgno - 1] = (SORTCACHE *) memset (fs_get (sizeof (SORTCACHE)),0,sizeof (SORTCACHE)); ret = (void *) stream->sc[msgno - 1]; break; case CH_FREE: /* free elt */ mail_free_elt (&stream->cache[msgno - 1]); break; case CH_FREESORTCACHE: if (stream->sc[msgno - 1]) { if (stream->sc[msgno - 1]->from) fs_give ((void **) &stream->sc[msgno - 1]->from); if (stream->sc[msgno - 1]->to) fs_give ((void **) &stream->sc[msgno - 1]->to); if (stream->sc[msgno - 1]->cc) fs_give ((void **) &stream->sc[msgno - 1]->cc); if (stream->sc[msgno - 1]->subject) fs_give ((void **) &stream->sc[msgno - 1]->subject); if (stream->sc[msgno - 1]->unique && (stream->sc[msgno - 1]->unique != stream->sc[msgno - 1]->message_id)) fs_give ((void **) &stream->sc[msgno - 1]->unique); if (stream->sc[msgno - 1]->message_id) fs_give ((void **) &stream->sc[msgno - 1]->message_id); if (stream->sc[msgno - 1]->references) mail_free_stringlist (&stream->sc[msgno - 1]->references); fs_give ((void **) &stream->sc[msgno - 1]); } break; case CH_EXPUNGE: /* expunge cache slot */ for (i = msgno - 1; msgno < stream->nmsgs; i++,msgno++) { if (stream->cache[i] = stream->cache[msgno]) stream->cache[i]->msgno = msgno; stream->sc[i] = stream->sc[msgno]; } stream->cache[i] = NIL; /* top of cache goes away */ stream->sc[i] = NIL; break; default: fatal ("Bad mm_cache op"); break; } return ret;}/* Dummy string driver for complete in-memory strings */static void mail_string_init (STRING *s,void *data,unsigned long size);static char mail_string_next (STRING *s);static void mail_string_setpos (STRING *s,unsigned long i);STRINGDRIVER mail_string = { mail_string_init, /* initialize string structure */ mail_string_next, /* get next byte in string structure */ mail_string_setpos /* set position in string structure */};/* Initialize mail string structure for in-memory string * Accepts: string structure * pointer to string * size of string */static void mail_string_init (STRING *s,void *data,unsigned long size){ /* set initial string pointers */ s->chunk = s->curpos = (char *) (s->data = data); /* and sizes */ s->size = s->chunksize = s->cursize = size; s->data1 = s->offset = 0; /* never any offset */}/* Get next character from string * Accepts: string structure * Returns: character, string structure chunk refreshed */static char mail_string_next (STRING *s){ return *s->curpos++; /* return the last byte */}/* Set string pointer position * Accepts: string structure * new position */static void mail_string_setpos (STRING *s,unsigned long i){ s->curpos = s->chunk + i; /* set new position */ s->cursize = s->chunksize - i;/* and new size */}/* Mail routines * * mail_xxx routines are the interface between this module and the outside * world. Only these routines should be referenced by external callers. * * Note that there is an important difference between a "sequence" and a * "message #" (msgno). A sequence is a string representing a sequence in * {"n", "n:m", or combination separated by commas} format, whereas a msgno * is a single integer. * *//* Mail version check * Accepts: version */void mail_versioncheck (char *version){ /* attempt to protect again wrong .h */ if (strcmp (version,mailcclientversion)) { char tmp[MAILTMPLEN]; sprintf (tmp,"c-client library version skew, app=%.100s library=%.100s", version,mailcclientversion); fatal (tmp); }}/* Mail link driver * Accepts: driver to add to list */void mail_link (DRIVER *driver){ DRIVER **d = &maildrivers; while (*d) d = &(*d)->next; /* find end of list of drivers */ *d = driver; /* put driver at the end */ driver->next = NIL; /* this driver is the end of the list */}/* Mail manipulate driver parameters * Accepts: mail stream * function code * function-dependent value * Returns: function-dependent return value */void *mail_parameters (MAILSTREAM *stream,long function,void *value){ void *r,*ret = NIL; DRIVER *d; AUTHENTICATOR *a; switch ((int) function) { case SET_INBOXPATH: fatal ("SET_INBOXPATH not permitted"); case GET_INBOXPATH: if ((stream || (stream = mail_open (NIL,"INBOX",OP_PROTOTYPE))) && stream->dtb) ret = (*stream->dtb->parameters) (function,value); break; case SET_THREADERS: fatal ("SET_THREADERS not permitted"); case GET_THREADERS: /* use stream dtb instead of global */ ret = (stream && stream->dtb) ? /* KLUDGE ALERT: note stream passed as value */ (*stream->dtb->parameters) (function,stream) : (void *) &mailthreadlist; break; case SET_NAMESPACE: fatal ("SET_NAMESPACE not permitted"); break; case SET_NEWSRC: /* too late on open stream */ if (stream && stream->dtb && (stream != ((*stream->dtb->open) (NIL)))) fatal ("SET_NEWSRC not permitted"); else ret = env_parameters (function,value); break; case GET_NAMESPACE: case GET_NEWSRC: /* use stream dtb instead of environment */ ret = (stream && stream->dtb) ? /* KLUDGE ALERT: note stream passed as value */ (*stream->dtb->parameters) (function,stream) : env_parameters (function,value); break; case ENABLE_DEBUG: fatal ("ENABLE_DEBUG not permitted"); case DISABLE_DEBUG: fatal ("DISABLE_DEBUG not permitted"); case SET_DIRFMTTEST: fatal ("SET_DIRFMTTEST not permitted"); case GET_DIRFMTTEST: if (!(stream && stream->dtb && (ret = (*stream->dtb->parameters) (function,NIL)))) fatal ("GET_DIRFMTTEST not permitted"); break; case SET_DRIVERS: fatal ("SET_DRIVERS not permitted"); case GET_DRIVERS: /* always return global */ ret = (void *) maildrivers; break; case SET_DRIVER: fatal ("SET_DRIVER not permitted"); case GET_DRIVER: for (d = maildrivers; d && compare_cstring (d->name,(char *) value); d = d->next); ret = (void *) d; break; case ENABLE_DRIVER: for (d = maildrivers; d && compare_cstring (d->name,(char *) value); d = d->next); if (ret = (void *) d) d->flags &= ~DR_DISABLE; break; case DISABLE_DRIVER: for (d = maildrivers; d && compare_cstring (d->name,(char *) value); d = d->next); if (ret = (void *) d) d->flags |= DR_DISABLE; break; case ENABLE_AUTHENTICATOR: for (a = mailauthenticators;/* scan authenticators */ a && compare_cstring (a->name,(char *) value); a = a->next);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -