imapext-2007

diff src/osdep/unix/phile.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/osdep/unix/phile.c	Mon Sep 14 15:17:45 2009 +0900
     1.3 @@ -0,0 +1,553 @@
     1.4 +/* ========================================================================
     1.5 + * Copyright 1988-2006 University of Washington
     1.6 + *
     1.7 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.8 + * you may not use this file except in compliance with the License.
     1.9 + * You may obtain a copy of the License at
    1.10 + *
    1.11 + *     http://www.apache.org/licenses/LICENSE-2.0
    1.12 + *
    1.13 + * 
    1.14 + * ========================================================================
    1.15 + */
    1.16 +
    1.17 +/*
    1.18 + * Program:	File routines
    1.19 + *
    1.20 + * Author:	Mark Crispin
    1.21 + *		Networks and Distributed Computing
    1.22 + *		Computing & Communications
    1.23 + *		University of Washington
    1.24 + *		Administration Building, AG-44
    1.25 + *		Seattle, WA  98195
    1.26 + *		Internet: MRC@CAC.Washington.EDU
    1.27 + *
    1.28 + * Date:	25 August 1993
    1.29 + * Last Edited:	9 May 2006
    1.30 + */
    1.31 +
    1.32 +
    1.33 +#include <stdio.h>
    1.34 +#include <ctype.h>
    1.35 +#include <errno.h>
    1.36 +extern int errno;		/* just in case */
    1.37 +#include <signal.h>
    1.38 +#include "mail.h"
    1.39 +#include "osdep.h"
    1.40 +#include <pwd.h>
    1.41 +#include <sys/stat.h>
    1.42 +#include <sys/time.h>
    1.43 +#include "rfc822.h"
    1.44 +#include "misc.h"
    1.45 +#include "dummy.h"
    1.46 +
    1.47 +/* Types returned from phile_type() */
    1.48 +
    1.49 +#define PTYPEBINARY 0		/* binary data */
    1.50 +#define PTYPETEXT 1		/* textual data */
    1.51 +#define PTYPECRTEXT 2		/* textual data with CR */
    1.52 +#define PTYPE8 4		/* textual 8bit data */
    1.53 +#define PTYPEISO2022JP 8	/* textual Japanese */
    1.54 +#define PTYPEISO2022KR 16	/* textual Korean */
    1.55 +#define PTYPEISO2022CN 32	/* textual Chinese */
    1.56 +
    1.57 +
    1.58 +/* PHILE I/O stream local data */
    1.59 +	
    1.60 +typedef struct phile_local {
    1.61 +  ENVELOPE *env;		/* file envelope */
    1.62 +  BODY *body;			/* file body */
    1.63 +  char tmp[MAILTMPLEN];		/* temporary buffer */
    1.64 +} PHILELOCAL;
    1.65 +
    1.66 +
    1.67 +/* Convenient access to local data */
    1.68 +
    1.69 +#define LOCAL ((PHILELOCAL *) stream->local)
    1.70 +
    1.71 +
    1.72 +/* Function prototypes */
    1.73 +
    1.74 +DRIVER *phile_valid (char *name);
    1.75 +int phile_isvalid (char *name,char *tmp);
    1.76 +void *phile_parameters (long function,void *value);
    1.77 +void phile_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
    1.78 +void phile_list (MAILSTREAM *stream,char *ref,char *pat);
    1.79 +void phile_lsub (MAILSTREAM *stream,char *ref,char *pat);
    1.80 +long phile_create (MAILSTREAM *stream,char *mailbox);
    1.81 +long phile_delete (MAILSTREAM *stream,char *mailbox);
    1.82 +long phile_rename (MAILSTREAM *stream,char *old,char *newname);
    1.83 +long phile_status (MAILSTREAM *stream,char *mbx,long flags);
    1.84 +MAILSTREAM *phile_open (MAILSTREAM *stream);
    1.85 +int phile_type (unsigned char *s,unsigned long i,unsigned long *j);
    1.86 +void phile_close (MAILSTREAM *stream,long options);
    1.87 +ENVELOPE *phile_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body,
    1.88 +			   long flags);
    1.89 +char *phile_header (MAILSTREAM *stream,unsigned long msgno,
    1.90 +		    unsigned long *length,long flags);
    1.91 +long phile_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
    1.92 +long phile_ping (MAILSTREAM *stream);
    1.93 +void phile_check (MAILSTREAM *stream);
    1.94 +long phile_expunge (MAILSTREAM *stream,char *sequence,long options);
    1.95 +long phile_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
    1.96 +long phile_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
    1.97 +
    1.98 +/* File routines */
    1.99 +
   1.100 +
   1.101 +/* Driver dispatch used by MAIL */
   1.102 +
   1.103 +DRIVER philedriver = {
   1.104 +  "phile",			/* driver name */
   1.105 +				/* driver flags */
   1.106 +  DR_LOCAL|DR_READONLY|DR_NOSTICKY,
   1.107 +  (DRIVER *) NIL,		/* next driver */
   1.108 +  phile_valid,			/* mailbox is valid for us */
   1.109 +  phile_parameters,		/* manipulate parameters */
   1.110 +  phile_scan,			/* scan mailboxes */
   1.111 +  phile_list,			/* list mailboxes */
   1.112 +  phile_lsub,			/* list subscribed mailboxes */
   1.113 +  NIL,				/* subscribe to mailbox */
   1.114 +  NIL,				/* unsubscribe from mailbox */
   1.115 +  dummy_create,			/* create mailbox */
   1.116 +  dummy_delete,			/* delete mailbox */
   1.117 +  dummy_rename,			/* rename mailbox */
   1.118 +  phile_status,			/* status of mailbox */
   1.119 +  phile_open,			/* open mailbox */
   1.120 +  phile_close,			/* close mailbox */
   1.121 +  NIL,				/* fetch message "fast" attributes */
   1.122 +  NIL,				/* fetch message flags */
   1.123 +  NIL,				/* fetch overview */
   1.124 +  phile_structure,		/* fetch message envelopes */
   1.125 +  phile_header,			/* fetch message header only */
   1.126 +  phile_text,			/* fetch message body only */
   1.127 +  NIL,				/* fetch partial message text */
   1.128 +  NIL,				/* unique identifier */
   1.129 +  NIL,				/* message number */
   1.130 +  NIL,				/* modify flags */
   1.131 +  NIL,				/* per-message modify flags */
   1.132 +  NIL,				/* search for message based on criteria */
   1.133 +  NIL,				/* sort messages */
   1.134 +  NIL,				/* thread messages */
   1.135 +  phile_ping,			/* ping mailbox to see if still alive */
   1.136 +  phile_check,			/* check for new messages */
   1.137 +  phile_expunge,		/* expunge deleted messages */
   1.138 +  phile_copy,			/* copy messages to another mailbox */
   1.139 +  phile_append,			/* append string message to mailbox */
   1.140 +  NIL				/* garbage collect stream */
   1.141 +};
   1.142 +
   1.143 +				/* prototype stream */
   1.144 +MAILSTREAM phileproto = {&philedriver};
   1.145 +
   1.146 +/* File validate mailbox
   1.147 + * Accepts: mailbox name
   1.148 + * Returns: our driver if name is valid, NIL otherwise
   1.149 + */
   1.150 +
   1.151 +DRIVER *phile_valid (char *name)
   1.152 +{
   1.153 +  char tmp[MAILTMPLEN];
   1.154 +  return phile_isvalid (name,tmp) ? &philedriver : NIL;
   1.155 +}
   1.156 +
   1.157 +
   1.158 +/* File test for valid mailbox
   1.159 + * Accepts: mailbox name
   1.160 + * Returns: T if valid, NIL otherwise
   1.161 + */
   1.162 +
   1.163 +int phile_isvalid (char *name,char *tmp)
   1.164 +{
   1.165 +  struct stat sbuf;
   1.166 +  char *s;
   1.167 +				/* INBOX never accepted, any other name is */
   1.168 +  return ((s = mailboxfile (tmp,name)) && *s && !stat (s,&sbuf) &&
   1.169 +	  !(sbuf.st_mode & S_IFDIR) &&
   1.170 +				/* only allow empty files if no empty proto
   1.171 +				   or if #ftp */
   1.172 +	  (sbuf.st_size || !default_proto (T) ||
   1.173 +	   ((*name == '#') && ((name[1] == 'f') || (name[1] == 'F')) &&
   1.174 +	    ((name[2] == 't') || (name[2] == 'T')) &&
   1.175 +	    ((name[3] == 'p') || (name[3] == 'P')) && (name[4] == '/'))));
   1.176 +}
   1.177 +
   1.178 +/* File manipulate driver parameters
   1.179 + * Accepts: function code
   1.180 + *	    function-dependent value
   1.181 + * Returns: function-dependent return value
   1.182 + */
   1.183 +
   1.184 +void *phile_parameters (long function,void *value)
   1.185 +{
   1.186 +  return NIL;
   1.187 +}
   1.188 +
   1.189 +/* File mail scan mailboxes
   1.190 + * Accepts: mail stream
   1.191 + *	    reference
   1.192 + *	    pattern to search
   1.193 + *	    string to scan
   1.194 + */
   1.195 +
   1.196 +void phile_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
   1.197 +{
   1.198 +  if (stream) dummy_scan (NIL,ref,pat,contents);
   1.199 +}
   1.200 +
   1.201 +
   1.202 +/* File list mailboxes
   1.203 + * Accepts: mail stream
   1.204 + *	    reference
   1.205 + *	    pattern to search
   1.206 + */
   1.207 +
   1.208 +void phile_list (MAILSTREAM *stream,char *ref,char *pat)
   1.209 +{
   1.210 +  if (stream) dummy_list (NIL,ref,pat);
   1.211 +}
   1.212 +
   1.213 +
   1.214 +/* File list subscribed mailboxes
   1.215 + * Accepts: mail stream
   1.216 + *	    reference
   1.217 + *	    pattern to search
   1.218 + */
   1.219 +
   1.220 +void phile_lsub (MAILSTREAM *stream,char *ref,char *pat)
   1.221 +{
   1.222 +  if (stream) dummy_lsub (NIL,ref,pat);
   1.223 +}
   1.224 +
   1.225 +
   1.226 +/* File status
   1.227 + * Accepts: mail stream
   1.228 + *	    mailbox name
   1.229 + *	    status flags
   1.230 + * Returns: T on success, NIL on failure
   1.231 + */
   1.232 +
   1.233 +long phile_status (MAILSTREAM *stream,char *mbx,long flags)
   1.234 +{
   1.235 +  char *s,tmp[MAILTMPLEN];
   1.236 +  MAILSTATUS status;
   1.237 +  struct stat sbuf;
   1.238 +  long ret = NIL;
   1.239 +  if ((s = mailboxfile (tmp,mbx)) && *s && !stat (s,&sbuf)) {
   1.240 +    status.flags = flags;	/* return status values */
   1.241 +    status.unseen = (stream && mail_elt (stream,1)->seen) ? 0 : 1;
   1.242 +    status.messages = status.recent = status.uidnext = 1;
   1.243 +    status.uidvalidity = sbuf.st_mtime;
   1.244 +				/* pass status to main program */
   1.245 +    mm_status (stream,mbx,&status);
   1.246 +    ret = LONGT;		/* success */
   1.247 +  }
   1.248 +  return ret;
   1.249 +}
   1.250 +
   1.251 +/* File open
   1.252 + * Accepts: Stream to open
   1.253 + * Returns: Stream on success, NIL on failure
   1.254 + */
   1.255 +
   1.256 +MAILSTREAM *phile_open (MAILSTREAM *stream)
   1.257 +{
   1.258 +  int i,k,fd;
   1.259 +  unsigned long j,m;
   1.260 +  char *s,tmp[MAILTMPLEN];
   1.261 +  struct passwd *pw;
   1.262 +  struct stat sbuf;
   1.263 +  struct tm *t;
   1.264 +  MESSAGECACHE *elt;
   1.265 +  SIZEDTEXT *buf;
   1.266 +				/* return prototype for OP_PROTOTYPE call */
   1.267 +  if (!stream) return &phileproto;
   1.268 +  if (stream->local) fatal ("phile recycle stream");
   1.269 +				/* open associated file */
   1.270 +  if (!mailboxfile (tmp,stream->mailbox) || !tmp[0] || stat (tmp,&sbuf) ||
   1.271 +      (fd = open (tmp,O_RDONLY,NIL)) < 0) {
   1.272 +    sprintf (tmp,"Unable to open file %s",stream->mailbox);
   1.273 +    mm_log (tmp,ERROR);
   1.274 +    return NIL;
   1.275 +  }
   1.276 +  fs_give ((void **) &stream->mailbox);
   1.277 +  stream->mailbox = cpystr (tmp);
   1.278 +  stream->local = fs_get (sizeof (PHILELOCAL));
   1.279 +  mail_exists (stream,1);	/* make sure upper level knows */
   1.280 +  mail_recent (stream,1);
   1.281 +  elt = mail_elt (stream,1);	/* instantiate cache element */
   1.282 +  elt->valid = elt->recent = T;	/* mark valid flags */
   1.283 +  stream->sequence++;		/* bump sequence number */
   1.284 +  stream->rdonly = T;		/* make sure upper level knows readonly */
   1.285 +				/* instantiate a new envelope and body */
   1.286 +  LOCAL->env = mail_newenvelope ();
   1.287 +  LOCAL->body = mail_newbody ();
   1.288 +
   1.289 +  t = gmtime (&sbuf.st_mtime);	/* get UTC time and Julian day */
   1.290 +  i = t->tm_hour * 60 + t->tm_min;
   1.291 +  k = t->tm_yday;
   1.292 +  t = localtime(&sbuf.st_mtime);/* get local time */
   1.293 +				/* calculate time delta */
   1.294 +  i = t->tm_hour * 60 + t->tm_min - i;
   1.295 +  if (k = t->tm_yday - k) i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60;
   1.296 +  k = abs (i);			/* time from UTC either way */
   1.297 +  elt->hours = t->tm_hour; elt->minutes = t->tm_min; elt->seconds = t->tm_sec;
   1.298 +  elt->day = t->tm_mday; elt->month = t->tm_mon + 1;
   1.299 +  elt->year = t->tm_year - (BASEYEAR - 1900);
   1.300 +  elt->zoccident = (k == i) ? 0 : 1;
   1.301 +  elt->zhours = k/60;
   1.302 +  elt->zminutes = k % 60;
   1.303 +  sprintf (tmp,"%s, %d %s %d %02d:%02d:%02d %c%02d%02d",
   1.304 +	   days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,
   1.305 +	   t->tm_hour,t->tm_min,t->tm_sec,elt->zoccident ? '-' : '+',
   1.306 +	   elt->zhours,elt->zminutes);
   1.307 +				/* set up Date field */
   1.308 +  LOCAL->env->date = cpystr (tmp);
   1.309 +
   1.310 +				/* fill in From field from file owner */
   1.311 +  LOCAL->env->from = mail_newaddr ();
   1.312 +  if (pw = getpwuid (sbuf.st_uid)) strcpy (tmp,pw->pw_name);
   1.313 +  else sprintf (tmp,"User-Number-%ld",(long) sbuf.st_uid);
   1.314 +  LOCAL->env->from->mailbox = cpystr (tmp);
   1.315 +  LOCAL->env->from->host = cpystr (mylocalhost ());
   1.316 +				/* set subject to be mailbox name */
   1.317 +  LOCAL->env->subject = cpystr (stream->mailbox);
   1.318 +				/* slurp the data */
   1.319 +  (buf = &elt->private.special.text)->size = sbuf.st_size;
   1.320 +  read (fd,buf->data = (unsigned char *) fs_get (buf->size + 1),buf->size);
   1.321 +  buf->data[buf->size] = '\0';
   1.322 +  close (fd);			/* close the file */
   1.323 +				/* analyze data type */
   1.324 +  if (i = phile_type (buf->data,buf->size,&j)) {
   1.325 +    LOCAL->body->type = TYPETEXT;
   1.326 +    LOCAL->body->subtype = cpystr ("PLAIN");
   1.327 +    if (!(i & PTYPECRTEXT)) {	/* change Internet newline format as needed */
   1.328 +      s = (char *) buf->data;	/* make copy of UNIX-format string */
   1.329 +      buf->data = NIL;		/* zap the buffer */
   1.330 +      buf->size = strcrlfcpy (&buf->data,&m,s,buf->size);
   1.331 +      fs_give ((void **) &s);	/* flush original UNIX-format string */
   1.332 +    }
   1.333 +    LOCAL->body->parameter = mail_newbody_parameter ();
   1.334 +    LOCAL->body->parameter->attribute = cpystr ("charset");
   1.335 +    LOCAL->body->parameter->value =
   1.336 +      cpystr ((i & PTYPEISO2022JP) ? "ISO-2022-JP" :
   1.337 +	      (i & PTYPEISO2022KR) ? "ISO-2022-KR" :
   1.338 +	      (i & PTYPEISO2022CN) ? "ISO-2022-CN" :
   1.339 +	      (i & PTYPE8) ? "X-UNKNOWN" : "US-ASCII");
   1.340 +    LOCAL->body->encoding = (i & PTYPE8) ? ENC8BIT : ENC7BIT;
   1.341 +    LOCAL->body->size.lines = j;
   1.342 +  }
   1.343 +  else {			/* binary data */
   1.344 +    LOCAL->body->type = TYPEAPPLICATION;
   1.345 +    LOCAL->body->subtype = cpystr ("OCTET-STREAM");
   1.346 +    LOCAL->body->parameter = mail_newbody_parameter ();
   1.347 +    LOCAL->body->parameter->attribute = cpystr ("name");
   1.348 +    LOCAL->body->parameter->value =
   1.349 +      cpystr ((s = (strrchr (stream->mailbox,'/'))) ? s+1 : stream->mailbox);
   1.350 +    LOCAL->body->encoding = ENCBASE64;
   1.351 +    buf->data = rfc822_binary (s = (char *) buf->data,buf->size,&buf->size);
   1.352 +    fs_give ((void **) &s);	/* flush originary binary contents */
   1.353 +  }
   1.354 +  phile_header (stream,1,&j,NIL);
   1.355 +  LOCAL->body->size.bytes = LOCAL->body->contents.text.size = buf->size;
   1.356 +  elt->rfc822_size = j + buf->size;
   1.357 +				/* only one message ever... */
   1.358 +  stream->uid_validity = sbuf.st_mtime;
   1.359 +  stream->uid_last = elt->private.uid = 1;
   1.360 +  return stream;		/* return stream alive to caller */
   1.361 +}
   1.362 +
   1.363 +/* File determine data type
   1.364 + * Accepts: data to examine
   1.365 + *	    size of data
   1.366 + *	    pointer to line count return
   1.367 + * Returns: PTYPE mask of data type
   1.368 + */
   1.369 +
   1.370 +int phile_type (unsigned char *s,unsigned long i,unsigned long *j)
   1.371 +{
   1.372 +  int ret = PTYPETEXT;
   1.373 +  char *charvec = "bbbbbbbaaalaacaabbbbbbbbbbbebbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
   1.374 +  *j = 0;			/* no lines */
   1.375 +				/* check type of every character */
   1.376 +  while (i--) switch (charvec[*s++]) {
   1.377 +  case 'A':
   1.378 +    ret |= PTYPE8;		/* 8bit character */
   1.379 +    break;
   1.380 +  case 'a':
   1.381 +    break;			/* ASCII character */
   1.382 +  case 'b':
   1.383 +    return PTYPEBINARY;		/* binary byte seen, stop immediately */
   1.384 +  case 'c':
   1.385 +    ret |= PTYPECRTEXT;		/* CR indicates Internet text */
   1.386 +    break;
   1.387 +  case 'e':			/* ESC */
   1.388 +    if (*s == '$') {		/* ISO-2022 sequence? */
   1.389 +      switch (s[1]) {
   1.390 +      case 'B': case '@': ret |= PTYPEISO2022JP; break;
   1.391 +      case ')':
   1.392 +	switch (s[2]) {
   1.393 +	case 'A': case 'E': case 'G': ret |= PTYPEISO2022CN; break;
   1.394 +	case 'C': ret |= PTYPEISO2022KR; break;
   1.395 +	}
   1.396 +      case '*':
   1.397 +	switch (s[2]) {
   1.398 +	case 'H': ret |= PTYPEISO2022CN; break;
   1.399 +	}
   1.400 +      case '+':
   1.401 +	switch (s[2]) {
   1.402 +	case 'I': case 'J': case 'K': case 'L': case 'M':
   1.403 +	  ret |= PTYPEISO2022CN; break;
   1.404 +	}
   1.405 +      }
   1.406 +    }
   1.407 +    break;
   1.408 +  case 'l':			/* newline */
   1.409 +    (*j)++;
   1.410 +    break;
   1.411 +  }
   1.412 +  return ret;			/* return type of data */
   1.413 +}
   1.414 +
   1.415 +/* File close
   1.416 + * Accepts: MAIL stream
   1.417 + *	    close options
   1.418 + */
   1.419 +
   1.420 +void phile_close (MAILSTREAM *stream,long options)
   1.421 +{
   1.422 +  if (LOCAL) {			/* only if a file is open */
   1.423 +    fs_give ((void **) &mail_elt (stream,1)->private.special.text.data);
   1.424 +				/* nuke the local data */
   1.425 +    fs_give ((void **) &stream->local);
   1.426 +    stream->dtb = NIL;		/* log out the DTB */
   1.427 +  }
   1.428 +}
   1.429 +
   1.430 +/* File fetch structure
   1.431 + * Accepts: MAIL stream
   1.432 + *	    message # to fetch
   1.433 + *	    pointer to return body
   1.434 + *	    option flags
   1.435 + * Returns: envelope of this message, body returned in body value
   1.436 + *
   1.437 + * Fetches the "fast" information as well
   1.438 + */
   1.439 +
   1.440 +ENVELOPE *phile_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body,
   1.441 +			   long flags)
   1.442 +{
   1.443 +  if (body) *body = LOCAL->body;
   1.444 +  return LOCAL->env;		/* return the envelope */
   1.445 +}
   1.446 +
   1.447 +
   1.448 +/* File fetch message header
   1.449 + * Accepts: MAIL stream
   1.450 + *	    message # to fetch
   1.451 + *	    pointer to returned header text length
   1.452 + *	    option flags
   1.453 + * Returns: message header in RFC822 format
   1.454 + */
   1.455 +
   1.456 +char *phile_header (MAILSTREAM *stream,unsigned long msgno,
   1.457 +		    unsigned long *length,long flags)
   1.458 +{
   1.459 +  rfc822_header (LOCAL->tmp,LOCAL->env,LOCAL->body);
   1.460 +  *length = strlen (LOCAL->tmp);
   1.461 +  return LOCAL->tmp;
   1.462 +}
   1.463 +
   1.464 +
   1.465 +/* File fetch message text (body only)
   1.466 + * Accepts: MAIL stream
   1.467 + *	    message # to fetch
   1.468 + *	    pointer to returned stringstruct
   1.469 + *	    option flags
   1.470 + * Returns: T, always
   1.471 + */
   1.472 +
   1.473 +long phile_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags)
   1.474 +{
   1.475 +  SIZEDTEXT *buf = &mail_elt (stream,msgno)->private.special.text;
   1.476 +  if (!(flags &FT_PEEK)) {	/* mark message as seen */
   1.477 +    mail_elt (stream,msgno)->seen = T;
   1.478 +    mm_flags (stream,msgno);
   1.479 +  }
   1.480 +  INIT (bs,mail_string,buf->data,buf->size);
   1.481 +  return T;
   1.482 +}
   1.483 +
   1.484 +/* File ping mailbox
   1.485 + * Accepts: MAIL stream
   1.486 + * Returns: T if stream alive, else NIL
   1.487 + * No-op for readonly files, since read/writer can expunge it from under us!
   1.488 + */
   1.489 +
   1.490 +long phile_ping (MAILSTREAM *stream)
   1.491 +{
   1.492 +  return T;
   1.493 +}
   1.494 +
   1.495 +/* File check mailbox
   1.496 + * Accepts: MAIL stream
   1.497 + * No-op for readonly files, since read/writer can expunge it from under us!
   1.498 + */
   1.499 +
   1.500 +void phile_check (MAILSTREAM *stream)
   1.501 +{
   1.502 +  mm_log ("Check completed",NIL);
   1.503 +}
   1.504 +
   1.505 +/* File expunge mailbox
   1.506 + * Accepts: MAIL stream
   1.507 + *	    sequence to expunge if non-NIL
   1.508 + *	    expunge options
   1.509 + * Returns: T if success, NIL if failure
   1.510 + */
   1.511 +
   1.512 +long phile_expunge (MAILSTREAM *stream,char *sequence,long options)
   1.513 +{
   1.514 +  if (!stream->silent) mm_log ("Expunge ignored on readonly mailbox",NIL);
   1.515 +  return LONGT;
   1.516 +}
   1.517 +
   1.518 +/* File copy message(s)
   1.519 + * Accepts: MAIL stream
   1.520 + *	    sequence
   1.521 + *	    destination mailbox
   1.522 + *	    copy options
   1.523 + * Returns: T if copy successful, else NIL
   1.524 + */
   1.525 +
   1.526 +long phile_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
   1.527 +{
   1.528 +  char tmp[MAILTMPLEN];
   1.529 +  mailproxycopy_t pc =
   1.530 +    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);
   1.531 +  if (pc) return (*pc) (stream,sequence,mailbox,options);
   1.532 +  sprintf (tmp,"Can't copy - file \"%s\" is not in valid mailbox format",
   1.533 +	   stream->mailbox);
   1.534 +  mm_log (tmp,ERROR);
   1.535 +  return NIL;
   1.536 +}
   1.537 +
   1.538 +
   1.539 +/* File append message from stringstruct
   1.540 + * Accepts: MAIL stream
   1.541 + *	    destination mailbox
   1.542 + *	    append callback function
   1.543 + *	    data for callback
   1.544 + * Returns: T if append successful, else NIL
   1.545 + */
   1.546 +
   1.547 +long phile_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
   1.548 +{
   1.549 +  char tmp[MAILTMPLEN],file[MAILTMPLEN];
   1.550 +  char *s = mailboxfile (file,mailbox);
   1.551 +  if (s && *s) 
   1.552 +    sprintf (tmp,"Can't append - not in valid mailbox format: %.80s",s);
   1.553 +  else sprintf (tmp,"Can't append - invalid name: %.80s",mailbox);
   1.554 +  mm_log (tmp,ERROR);
   1.555 +  return NIL;
   1.556 +}

UW-IMAP'd extensions by yuuji