dummy.c   dummy.c 
/* ========================================================================
* Copyright 1988-2006 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: Dummy routines * Program: Dummy routines
* *
* Author: Mark Crispin * Author: Mark Crispin
* Networks and Distributed Computing * Networks and Distributed Computing
* Computing & Communications * Computing & Communications
* University of Washington * University of Washington
* Administration Building, AG-44 * Administration Building, AG-44
* Seattle, WA 98195 * Seattle, WA 98195
* Internet: MRC@CAC.Washington.EDU * Internet: MRC@CAC.Washington.EDU
* *
* Date: 9 May 1991 * Date: 9 May 1991
* Last Edited: 10 November 2004 * Last Edited: 30 August 2006
*
* The IMAP toolkit provided in this Distribution is
* Copyright 1988-2004 University of Washington.
* The full text of our legal notices is contained in the file called
* CPYRIGHT, included with this Distribution.
*/ */
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
extern int errno; /* just in case */ extern int errno; /* just in case */
#include "mail.h" #include "mail.h"
#include "osdep.h" #include "osdep.h"
#include <pwd.h> #include <pwd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "dummy.h" #include "dummy.h"
#include "misc.h" #include "misc.h"
#include "mx.h" /* highly unfortunate */
/* Function prototypes */ /* Function prototypes */
DRIVER *dummy_valid (char *name); DRIVER *dummy_valid (char *name);
void *dummy_parameters (long function,void *value); void *dummy_parameters (long function,void *value);
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents , void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents ,
long level); long level);
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
long attributes,char *contents); long attributes,char *contents);
long dummy_subscribe (MAILSTREAM *stream,char *mailbox); long dummy_subscribe (MAILSTREAM *stream,char *mailbox);
MAILSTREAM *dummy_open (MAILSTREAM *stream); MAILSTREAM *dummy_open (MAILSTREAM *stream);
void dummy_close (MAILSTREAM *stream,long options); void dummy_close (MAILSTREAM *stream,long options);
long dummy_ping (MAILSTREAM *stream); long dummy_ping (MAILSTREAM *stream);
void dummy_check (MAILSTREAM *stream); void dummy_check (MAILSTREAM *stream);
void dummy_expunge (MAILSTREAM *stream); long dummy_expunge (MAILSTREAM *stream,char *sequence,long options);
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long optio ns); long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long optio ns);
long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) ; long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) ;
/* Dummy routines */ /* Dummy routines */
/* Driver dispatch used by MAIL */ /* Driver dispatch used by MAIL */
DRIVER dummydriver = { DRIVER dummydriver = {
"dummy", /* driver name */ "dummy", /* driver name */
DR_LOCAL|DR_MAIL, /* driver flags */ DR_LOCAL|DR_MAIL, /* driver flags */
(DRIVER *) NIL, /* next driver */ (DRIVER *) NIL, /* next driver */
skipping to change at line 222 skipping to change at line 229
* Accepts: mail stream * Accepts: mail stream
* mailbox to add to subscription list * mailbox to add to subscription list
* Returns: T on success, NIL on failure * Returns: T on success, NIL on failure
*/ */
long dummy_subscribe (MAILSTREAM *stream,char *mailbox) long dummy_subscribe (MAILSTREAM *stream,char *mailbox)
{ {
char *s,tmp[MAILTMPLEN]; char *s,tmp[MAILTMPLEN];
struct stat sbuf; struct stat sbuf;
/* must be valid local mailbox */ /* must be valid local mailbox */
if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf) if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf) &&
#if 0 /* disable this temporarily for Netscape */ ((sbuf.st_mode & S_IFMT) == S_IFREG)) return sm_subscribe (mailbox);
&&
((sbuf.st_mode & S_IFMT) == S_IFREG)
#endif
) return sm_subscribe (mailbox);
sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox); sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox);
MM_LOG (tmp,ERROR); MM_LOG (tmp,ERROR);
return NIL; return NIL;
} }
/* Dummy list mailboxes worker routine /* Dummy list mailboxes worker routine
* Accepts: mail stream * Accepts: mail stream
* directory name to search * directory name to search
* search pattern * search pattern
* string to scan * string to scan
* search level * search level
*/ */
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents , void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents ,
long level) long level)
{ {
DRIVER *drivers;
dirfmttest_t dt;
DIR *dp; DIR *dp;
struct direct *d; struct direct *d;
struct stat sbuf; struct stat sbuf;
int ismx;
char tmp[MAILTMPLEN]; char tmp[MAILTMPLEN];
size_t len = 0;
/* punt if bogus name */ /* punt if bogus name */
if (!mailboxdir (tmp,dir,NIL)) return; if (!mailboxdir (tmp,dir,NIL)) return;
if (dp = opendir (tmp)) { /* do nothing if can't open directory */ if (dp = opendir (tmp)) { /* do nothing if can't open directory */
/* list it if not at top-level */ /* see if a non-namespace directory format *
/
for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = N
IL;
!dt && drivers; drivers = drivers->next)
if (!(drivers->flags & DR_DISABLE) && (drivers->flags & DR_DIRFMT) &&
(*drivers->valid) (tmp))
dt = mail_parameters ((*drivers->open) (NIL),GET_DIRFMTTEST,NIL);
/* list it if at top-level */
if (!level && dir && pmatch_full (dir,pat,'/')) if (!level && dir && pmatch_full (dir,pat,'/'))
dummy_listed (stream,'/',dir,LATT_NOSELECT,contents); dummy_listed (stream,'/',dir,dt ? NIL : LATT_NOSELECT,contents);
/* scan directory, ignore . and .. */ /* scan directory, ignore . and .. */
ismx = (!stat (strcat (tmp,MXINDEXNAME),&sbuf) && if (!dir || dir[(len = strlen (dir)) - 1] == '/') while (d = readdir (d
((sbuf.st_mode & S_IFMT) == S_IFREG)); p))
if (!dir || dir[strlen (dir) - 1] == '/') while (d = readdir (dp)) if ((!(dt && (*dt) (d->d_name))) &&
if (((d->d_name[0] != '.') || ((d->d_name[0] != '.') ||
(((int) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL : (((int) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL :
(d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]) && (d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]))))) &&
strcmp (d->d_name+1,MXINDEXNAME+2))))) && ((len + strlen (d->d_name)) <= NETMAXMBX)) {
(strlen (d->d_name) <= NETMAXMBX)) {
/* see if name is useful */ /* see if name is useful */
if (dir) sprintf (tmp,"%s%s",dir,d->d_name); if (dir) sprintf (tmp,"%s%s",dir,d->d_name);
else strcpy (tmp,d->d_name); else strcpy (tmp,d->d_name);
/* make sure useful and can get info */ /* make sure useful and can get info */
if ((pmatch_full (tmp,pat,'/') || if ((pmatch_full (tmp,pat,'/') ||
pmatch_full (strcat (tmp,"/"),pat,'/') || dmatch (tmp,pat,'/')) && pmatch_full (strcat (tmp,"/"),pat,'/') || dmatch (tmp,pat,'/')) &&
mailboxdir (tmp,dir,d->d_name) && tmp[0] && !stat (tmp,&sbuf)) { mailboxdir (tmp,dir,d->d_name) && tmp[0] && !stat (tmp,&sbuf)) {
/* now make name we'd return */ /* now make name we'd return */
if (dir) sprintf (tmp,"%s%s",dir,d->d_name); if (dir) sprintf (tmp,"%s%s",dir,d->d_name);
else strcpy (tmp,d->d_name); else strcpy (tmp,d->d_name);
skipping to change at line 289 skipping to change at line 298
} }
/* try again with trailing / */ /* try again with trailing / */
else if (pmatch_full (strcat (tmp,"/"),pat,'/') && else if (pmatch_full (strcat (tmp,"/"),pat,'/') &&
!dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents)) !dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents))
break; break;
if (dmatch (tmp,pat,'/') && if (dmatch (tmp,pat,'/') &&
(level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))) (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL)))
dummy_list_work (stream,tmp,pat,contents,level+1); dummy_list_work (stream,tmp,pat,contents,level+1);
break; break;
case S_IFREG: /* ordinary name */ case S_IFREG: /* ordinary name */
/* ignore all-digit names from mx */
/* Must use ctime for systems that don't update mtime properly * / /* Must use ctime for systems that don't update mtime properly * /
if (!(ismx && mx_select (d)) && pmatch_full (tmp,pat,'/') && if (pmatch_full (tmp,pat,'/') && compare_cstring (tmp,"INBOX"))
compare_cstring (tmp,"INBOX"))
dummy_listed (stream,'/',tmp,LATT_NOINFERIORS + dummy_listed (stream,'/',tmp,LATT_NOINFERIORS +
((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime ))? ((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime ))?
LATT_MARKED : LATT_UNMARKED),contents); LATT_MARKED : LATT_UNMARKED),contents);
break; break;
} }
} }
} }
closedir (dp); /* all done, flush directory */ closedir (dp); /* all done, flush directory */
} }
} }
/* Scan file for contents /* Scan file for contents
* Accepts: driver to use
* file name
* desired contents
* length of contents
* size of file
* Returns: NIL if contents not found, T if found
*/
long scan_contents (DRIVER *dtb,char *name,char *contents,
unsigned long csiz,unsigned long fsiz)
{
scancontents_t sc = dtb ?
(scancontents_t) (*dtb->parameters) (GET_SCANCONTENTS,NIL) : NIL;
return (*(sc ? sc : dummy_scan_contents)) (name,contents,csiz,fsiz);
}
/* Scan file for contents
* Accepts: file name * Accepts: file name
* desired contents * desired contents
* length of contents
* size of file
* Returns: NIL if contents not found, T if found * Returns: NIL if contents not found, T if found
*/ */
#define BUFSIZE 4*MAILTMPLEN #define BUFSIZE 4*MAILTMPLEN
long dummy_scan_contents (char *name,char *contents,unsigned long csiz, long dummy_scan_contents (char *name,char *contents,unsigned long csiz,
unsigned long fsiz) unsigned long fsiz)
{ {
int fd; int fd;
unsigned long ssiz,bsiz; unsigned long ssiz,bsiz;
skipping to change at line 335 skipping to change at line 361
(unsigned char *) contents,csiz)) break; (unsigned char *) contents,csiz)) break;
memcpy (buf,buf+BUFSIZE,ssiz); memcpy (buf,buf+BUFSIZE,ssiz);
fsiz -= bsiz; /* note that we read that much */ fsiz -= bsiz; /* note that we read that much */
} }
fs_give ((void **) &buf); /* flush buffer */ fs_give ((void **) &buf); /* flush buffer */
close (fd); /* finished with file */ close (fd); /* finished with file */
if (fsiz) return T; /* found */ if (fsiz) return T; /* found */
} }
return NIL; /* not found */ return NIL; /* not found */
} }
/* Mailbox found /* Mailbox found
* Accepts: MAIL stream * Accepts: MAIL stream
* hierarchy delimiter * hierarchy delimiter
* mailbox name * mailbox name
* attributes * attributes
* contents to search before calling mm_list() * contents to search before calling mm_list()
* Returns: NIL if should abort hierarchy search, else T (currently always) * Returns: NIL if should abort hierarchy search, else T (currently always)
*/ */
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
skipping to change at line 359 skipping to change at line 384
unsigned long csiz; unsigned long csiz;
struct stat sbuf; struct stat sbuf;
char *s,tmp[MAILTMPLEN]; char *s,tmp[MAILTMPLEN];
/* don't \NoSelect dir if it has a driver */ /* don't \NoSelect dir if it has a driver */
if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) && if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
(d != &dummydriver)) attributes &= ~LATT_NOSELECT; (d != &dummydriver)) attributes &= ~LATT_NOSELECT;
if (!contents || /* notify main program */ if (!contents || /* notify main program */
(!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) && (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
(s = mailboxfile (tmp,name)) && (s = mailboxfile (tmp,name)) &&
(*s || (s = mail_parameters (NIL,GET_INBOXPATH,tmp))) && (*s || (s = mail_parameters (NIL,GET_INBOXPATH,tmp))) &&
!stat (s,&sbuf) && (csiz <= sbuf.st_size) && !stat (s,&sbuf) && (d || (csiz <= sbuf.st_size)) &&
SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size))) SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size)))
mm_list (stream,delimiter,name,attributes); mm_list (stream,delimiter,name,attributes);
return T; return T;
} }
/* Dummy create mailbox /* Dummy create mailbox
* Accepts: mail stream * Accepts: mail stream
* mailbox name to create * mailbox name to create
* Returns: T on success, NIL on failure * Returns: T on success, NIL on failure
*/ */
skipping to change at line 464 skipping to change at line 489
* new mailbox name * new mailbox name
* Returns: T on success, NIL on failure * Returns: T on success, NIL on failure
*/ */
long dummy_rename (MAILSTREAM *stream,char *old,char *newname) long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
{ {
struct stat sbuf; struct stat sbuf;
char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
/* no trailing / allowed */ /* no trailing / allowed */
if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
((s = strrchr (s,'/')) && !s[1])) { stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] &&
((sbuf.st_mode & S_IFMT) != S_IFDIR))) {
sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname);
MM_LOG (mbx,ERROR); MM_LOG (mbx,ERROR);
return NIL; return NIL;
} }
if (s) { /* found superior to destination name? */ if (s) { /* found a directory delimiter? */
c = *++s; /* remember first character of inferior */ if (!s[1]) *s = '\0'; /* ignore trailing delimiter */
*s = '\0'; /* tie off to get just superior */ else { /* found superior to destination name? */
c = *++s; /* remember first character of infer
ior */
*s = '\0'; /* tie off to get just superior */
/* name doesn't exist, create it */ /* name doesn't exist, create it */
if ((stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && if ((stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
!dummy_create (stream,mbx)) return NIL; !dummy_create (stream,mbx)) return NIL;
*s = c; /* restore full name */ *s = c; /* restore full name */
}
} }
/* rename of non-ex INBOX creates dest */ /* rename of non-ex INBOX creates dest */
if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf))
return dummy_create (NIL,mbx); return dummy_create (NIL,mbx);
if (rename (oldname,mbx)) { if (rename (oldname,mbx)) {
sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname,
strerror (errno)); strerror (errno));
MM_LOG (tmp,ERROR); MM_LOG (tmp,ERROR);
return NIL; return NIL;
} }
skipping to change at line 589 skipping to change at line 618
* No-op for readonly files, since read/writer can expunge it from under us ! * No-op for readonly files, since read/writer can expunge it from under us !
*/ */
void dummy_check (MAILSTREAM *stream) void dummy_check (MAILSTREAM *stream)
{ {
dummy_ping (stream); /* invoke ping */ dummy_ping (stream); /* invoke ping */
} }
/* Dummy expunge mailbox /* Dummy expunge mailbox
* Accepts: MAIL stream * Accepts: MAIL stream
* sequence to expunge if non-NIL
* expunge options
* Returns: T, always
*/ */
void dummy_expunge (MAILSTREAM *stream) long dummy_expunge (MAILSTREAM *stream,char *sequence,long options)
{ {
/* return silently */ return LONGT;
} }
/* Dummy copy message(s) /* Dummy copy message(s)
* Accepts: MAIL stream * Accepts: MAIL stream
* sequence * sequence
* destination mailbox * destination mailbox
* options * options
* Returns: T if copy successful, else NIL * Returns: T if copy successful, else NIL
*/ */
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long optio ns) long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long optio ns)
skipping to change at line 665 skipping to change at line 697
/* Dummy canonicalize name /* Dummy canonicalize name
* Accepts: buffer to write name * Accepts: buffer to write name
* reference * reference
* pattern * pattern
* Returns: T if success, NIL if failure * Returns: T if success, NIL if failure
*/ */
long dummy_canonicalize (char *tmp,char *ref,char *pat) long dummy_canonicalize (char *tmp,char *ref,char *pat)
{ {
unsigned long i;
char *s;
if (ref) { /* preliminary reference check */ if (ref) { /* preliminary reference check */
if (*ref == '{') return NIL;/* remote reference not allowed */ if (*ref == '{') return NIL;/* remote reference not allowed */
else if (!*ref) ref = NIL; /* treat empty reference as no reference */ else if (!*ref) ref = NIL; /* treat empty reference as no reference */
} }
switch (*pat) { switch (*pat) {
case '#': /* namespace name */ case '#': /* namespace name */
if (mailboxfile (tmp,pat)) strcpy (tmp,pat); if (mailboxfile (tmp,pat)) strcpy (tmp,pat);
else return NIL; /* unknown namespace */ else return NIL; /* unknown namespace */
break; break;
case '{': /* remote names not allowed */ case '{': /* remote names not allowed */
skipping to change at line 693 skipping to change at line 727
default: /* apply reference for all other names */ default: /* apply reference for all other names */
if (!ref) strcpy (tmp,pat); /* just copy if no namespace */ if (!ref) strcpy (tmp,pat); /* just copy if no namespace */
else if ((*ref != '#') || mailboxfile (tmp,ref)) { else if ((*ref != '#') || mailboxfile (tmp,ref)) {
/* wants root of name? */ /* wants root of name? */
if (*pat == '/') strcpy (strchr (strcpy (tmp,ref),'/'),pat); if (*pat == '/') strcpy (strchr (strcpy (tmp,ref),'/'),pat);
/* otherwise just append */ /* otherwise just append */
else sprintf (tmp,"%s%s",ref,pat); else sprintf (tmp,"%s%s",ref,pat);
} }
else return NIL; /* unknown namespace */ else return NIL; /* unknown namespace */
} }
/* count wildcards */
for (i = 0, s = tmp; *s; *s++) if ((*s == '*') || (*s == '%')) ++i;
if (i > MAXWILDCARDS) { /* ridiculous wildcarding? */
MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR);
return NIL;
}
return T; return T;
} }
 End of changes. 26 change blocks. 
38 lines changed or deleted 82 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/