📄 client
字号:
/* * Program: Mailbox Access routines * * 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: 22 November 1989 * Last Edited: 18 September 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. * */#include <ctype.h>#include <stdio.h>#include "mail.h"#include "osdep.h"#include <time.h>#include "misc.h"#include "rfc822.h"#include "utf8.h"#include "smtp.h"/* c-client global data */ /* list of mail drivers */static DRIVER *maildrivers = NIL; /* list of authenticators */static AUTHENTICATOR *mailauthenticators = NIL; /* alternative network driver pointer */static NETDRIVER *mailaltdriver = NIL; /* alternative network driver name */static char *mailaltdrivername = NIL; /* alternative network option name */static char *mailaltoptionname = 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; /* 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; /* 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; /* free envelope extra stuff callback */static freeenvelopesparep_t mailfreeenvelopesparep = NIL; /* free envelope extra stuff callback */static freeeltsparep_t mailfreeeltsparep = NIL; /* supported threaders */static THREADER mailthreadordsub = { "ORDEREDSUBJECT",mail_thread_orderedsubject,NIL};static THREADER mailthreadlist = { "REFERENCES",mail_thread_references,&mailthreadordsub}; /* server name */static char *servicename = "unknown";static int expungeatping = T; /* mail_ping() may call mm_expunged() */static int tryaltfirst = NIL; /* always try alt driver first */static int notimezones = NIL; /* write timezones in "From " header *//* 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]->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 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_THREADERS: fatal ("SET_THREADERS not permitted"); case GET_THREADERS: ret = (stream && stream->dtb) ? (*stream->dtb->parameters) (function,stream) : (void *) &mailthreadlist; break; case SET_NAMESPACE: fatal ("SET_NAMESPACE not permitted"); case GET_NAMESPACE: ret = (stream && stream->dtb) ? (*stream->dtb->parameters) (function,stream) : env_parameters (function,stream); break; case SET_DRIVERS: fatal ("SET_DRIVERS not permitted"); case GET_DRIVERS: ret = (void *) maildrivers; break; case SET_DRIVER: fatal ("SET_DRIVER not permitted"); case GET_DRIVER: for (d = maildrivers; d && strcmp (d->name,(char *) value); d = d->next); ret = (void *) d; break; case ENABLE_DRIVER: for (d = maildrivers; d && strcmp (d->name,(char *) value); d = d->next); if (ret = (void *) d) d->flags &= ~DR_DISABLE; break; case DISABLE_DRIVER: for (d = maildrivers; d && strcmp (d->name,(char *) value); d = d->next); if (ret = (void *) d) d->flags |= DR_DISABLE; break; case ENABLE_AUTHENTICATOR: /* punt on this for the nonce */ fatal ("ENABLE_AUTHENTICATOR not permitted"); case DISABLE_AUTHENTICATOR: for (a = mailauthenticators;/* scan authenticators */ a && strcmp (a->name,(char *) value); a = a->next); if (a) { /* if authenticator name found */ a->client = NIL; /* blow it away */ a->server = NIL; } break; case SET_GETS: mailgets = (mailgets_t) value; case GET_GETS: ret = (void *) mailgets; break; case SET_READPROGRESS: mailreadprogress = (readprogress_t) value; case GET_READPROGRESS: ret = (void *) mailreadprogress; break; case SET_CACHE: mailcache = (mailcache_t) value; case GET_CACHE: ret = (void *) mailcache; break; case SET_RFC822OUTPUT: mail822out = (rfc822out_t) value; case GET_RFC822OUTPUT: ret = (void *) mail822out; break; case SET_SMTPVERBOSE: mailsmtpverbose = (smtpverbose_t) value; case GET_SMTPVERBOSE: ret = (void *) mailsmtpverbose; break; case SET_MAILPROXYCOPY: mailproxycopy = (mailproxycopy_t) value; case GET_MAILPROXYCOPY: ret = (void *) mailproxycopy; break; case SET_PARSELINE: mailparseline = (parseline_t) value; case GET_PARSELINE: ret = (void *) mailparseline; break; case SET_PARSEPHRASE: mailparsephrase = (parsephrase_t) value; case GET_PARSEPHRASE: ret = (void *) mailparsephrase; break; case SET_NEWSRCQUERY: mailnewsrcquery = (newsrcquery_t) value; case GET_NEWSRCQUERY: ret = (void *) mailnewsrcquery; break; case SET_FREEENVELOPESPAREP: mailfreeenvelopesparep = (freeenvelopesparep_t) value; case GET_FREEENVELOPESPAREP: ret = (void *) mailfreeenvelopesparep; break; case SET_FREEELTSPAREP: mailfreeeltsparep = (freeeltsparep_t) value; case GET_FREEELTSPAREP: ret = (void *) mailfreeeltsparep; break; case SET_SERVICENAME: servicename = (char *) value; case GET_SERVICENAME: ret = (void *) servicename; break; case SET_EXPUNGEATPING: expungeatping = (int) value; case GET_EXPUNGEATPING:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -