ftp.nice.ch/pub/next/connectivity/mail/bundles/EnhanceMail.2.2p1.NIHS.bs.gnutar.gz#/EnhanceMail-2.2p1/Source/mailtoc.c

This is mailtoc.c in view mode; [Download] [Up]

/* -*-C-*-
*******************************************************************************
*
* File:         mailtoc.c
* RCS:          /usr/local/sources/CVS/EnhanceMail/mailtoc.c,v 1.7 1998/05/31 00:39:39 tom Exp
* Description:  Table-of-contents access routines for Mail.app utilities
* Author:       Carl Edman
* Created:      Sun Apr 25 10:31:24 1993
* Modified:     Fri May 30 00:47:20 1997 Tom Hageman <tom@basil.icce.rug.nl>
* Language:     C
* Package:      N/A
* Status:       Experimental (Do Not Distribute)
*
* (C) Copyright 1993, but otherwise this file is perfect freeware.
*
*******************************************************************************
*/

#import <libc.h>
//#import <stdlib.h>
//#import <stdio.h>
//#import <string.h>
//#import <time.h>
//#import <sys/file.h>
//#import <sys/param.h>
//#import <sys/types.h>
//#import <sys/stat.h>
//#import <sys/dir.h>
#import <errno.h>

#import "mailtoc.h"

#if (NS_TARGET_MAJOR >= 4 || defined(__APPLE_CC__)) /* OPENSTEP/Rhapsody */
#  import <Foundation/NSByteOrder.h>
#  define NXSwapBigLongToHost		NSSwapBigLongToHost
#  define NXSwapBigFloatToHost		NSSwapBigFloatToHost
#  define NXConvertHostFloatToSwapped	NSConvertHostFloatToSwapped
#  define NXSwapHostLongToBig		NSSwapHostLongToBig
#  define NXSwapHostFloatToBig		NSSwapHostFloatToBig
#  define NXConvertSwappedFloatToHost	NSConvertSwappedFloatToHost
#endif

#define TOC_MAGIC 890712
#define TOC_MESSAGE_INDEX_MAX 100000
   /* arbitrary limit on message index record size, to avoid crashes on corrupt mailboxes. */

static void swap_table_of_contents_header_to_host(struct table_of_contents_header *toc)
{
   toc->magic=NXSwapBigLongToHost(toc->magic);
   toc->num_msgs=NXSwapBigLongToHost(toc->num_msgs);
   toc->mbox_time=NXSwapBigLongToHost(toc->mbox_time);
   toc->list=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->list));
   toc->window.origin.x=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.x));
   toc->window.origin.y=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.y));
   toc->window.size.width=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.width));
   toc->window.size.height=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.height));
}

struct table_of_contents_header *get_table_of_contents_header(FILE *f,int createflag)
{
   int n;
   struct table_of_contents_header *toc;
   toc=malloc(sizeof(*toc));
   if(toc==NULL) return 0;
   errno=0;
   if ((n=fread((void *)toc,1,sizeof(*toc),f))!=sizeof(*toc))
   {
      if (!(createflag && n==0))
      {
	 free(toc);
	 return 0;
      }
      toc->magic=TOC_MAGIC;
      toc->num_msgs=0;
      toc->mbox_time=-1;
      toc->list=102.0;
      toc->window.origin.x=271.0;
      toc->window.origin.y=151.0;
      toc->window.size.width=557.0;
      toc->window.size.height=532.0;
      /* Write table of contents immediately, so space for it is allocated
         on-disk.  {{Does NOT fall through to byteswapping below anymore,
	 since this is handled in put_table_of_contents_header itself now.}} */
      if (put_table_of_contents_header(f,toc)!=0)
      {
	 free(toc);
	 return 0;
      }
   }
   else
   {
      swap_table_of_contents_header_to_host(toc);
   }
   if (toc->magic!=TOC_MAGIC) /* basic sanity check. */
   {
      free(toc);
      return 0;
   }
   return toc;
}

static inline void swap_message_index_to_host(struct message_index *mi)
{
   mi->mes_offset=NXSwapBigLongToHost(mi->mes_offset);
   mi->mes_length=NXSwapBigLongToHost(mi->mes_length);
   mi->mes_date=NXSwapBigLongToHost(mi->mes_date);
}

struct message_index *get_message_index(FILE *f)
{
   long rl;
   struct message_index *mi;
   errno=0;
   if (fread(&rl,1,sizeof(rl),f)!=sizeof(rl)) return 0;
   rl=NXSwapBigLongToHost(rl);
   if (rl > TOC_MESSAGE_INDEX_MAX) return 0;
   mi=malloc(rl);
   if(mi==NULL) return 0;
   mi->record_length=rl;
   if (fread(((char *)mi)+sizeof(rl),1,rl-sizeof(rl),f)!=rl-sizeof(rl))
   {
      free(mi);
      return 0;
   }
   swap_message_index_to_host(mi);
   return mi;
}

static inline void swap_message_index_to_disk(struct message_index *mi)
{
   mi->mes_offset=NXSwapHostLongToBig(mi->mes_offset);
   mi->mes_length=NXSwapHostLongToBig(mi->mes_length);
   mi->mes_date=NXSwapHostLongToBig(mi->mes_date);
}

int put_message_index(FILE *f,struct message_index *mi)
{
   long reclen=mi->record_length;
   int ret;
   mi->record_length=NXSwapHostLongToBig(mi->record_length);
   swap_message_index_to_disk(mi);
   errno=0;
   ret=(fwrite(mi,1,reclen,f)!=reclen);
   mi->record_length=NXSwapBigLongToHost(mi->record_length);
   swap_message_index_to_host(mi);
   return ret;
}

static void swap_table_of_contents_header_to_disk(struct table_of_contents_header *toc)
{
   toc->magic=NXSwapHostLongToBig(toc->magic);
   toc->num_msgs=NXSwapHostLongToBig(toc->num_msgs);
   toc->mbox_time=NXSwapHostLongToBig(toc->mbox_time);
   toc->list=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->list));
   toc->window.origin.x=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.x));
   toc->window.origin.y=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.y));
   toc->window.size.width=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.width));
   toc->window.size.height=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.height));
}

int put_table_of_contents_header(FILE *f,struct table_of_contents_header *toc)
{
   int ret;
   swap_table_of_contents_header_to_disk(toc);
   errno=0;
   rewind(f);
   ret=(fwrite(toc,1,sizeof(*toc),f)!=sizeof(*toc));
   swap_table_of_contents_header_to_host(toc);
   return ret;
}

#define MESSAGE_DATE(y,m,d)   ((d)+((m)<<5)+((y)<<9))

long message_current_date(void)
{
   time_t clock;
   struct tm *ctm;
   time(&clock);
   ctm=localtime(&clock);
   return MESSAGE_DATE(ctm->tm_year+1900, ctm->tm_mon+1, ctm->tm_mday);
}

long message_date(int year,const char *month,int day)
{
   static const char months[][4]=
   {
      "Jan", "Feb", "Mar", "Apr", "May", "Jun",
      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
   };
   int m;

   for(m=0;m<12;m++) if (!strncasecmp(month,months[m],3)) break;
   m=(m%12)+1; /* Wrap around to January for unidentifiable month
                  It's better than failing for an unattended program */

   if (year < 200) year += (year < 70 ? 2000 : 1900);
   /* Y2K fix -- we don't expect e-mail from before 200AD :-) */

   if (day <= 0) day = 1; else if (day > 31) day = 31;

   return MESSAGE_DATE(year, m, day);
}

char *message_from(const struct message_index *mi)
{
   char *p=mi->data;
   return p;
}

char *message_subject(const struct message_index *mi)
{
   char *p=mi->data;
   p+=strlen(p)+1;
   return p;
}

char *message_reference(const struct message_index *mi)
{
   char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   return p;
}

int message_attachsize(const struct message_index *mi)
{
   const unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);   
   if (p-(const unsigned char *)mi>mi->record_length) return -1;
   return (int)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
}

int message_set_attachsize(struct message_index *mi,int size)
{
   unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);
   if (p-(unsigned char *)mi>mi->record_length) return -1;
   p[-4]=size>>24;
   p[-3]=size>>16;
   p[-2]=size>> 8;
   p[-1]=size>> 0;
   return size;
}

time_t message_attachtime(const struct message_index *mi)
{
   const unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);
   p+=sizeof(time_t);
   if (p-(const unsigned char *)mi>mi->record_length) return -1;
   return (time_t)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
}

time_t message_set_attachtime(struct message_index *mi,time_t time)
{
   unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);
   p+=sizeof(time_t);
   if (p-(unsigned char *)mi>mi->record_length) return -1;
   p[-4]=((int)time)>>24;
   p[-3]=((int)time)>>16;
   p[-2]=((int)time)>> 8;
   p[-1]=((int)time)>> 0;
   return time;
}

int message_priority(const struct message_index *mi)
{
   const unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);
   p+=sizeof(time_t);
   p+=sizeof(int);
   if (p-(const unsigned char *)mi>mi->record_length) return -1;
   return ((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);
}

int message_set_priority(struct message_index *mi,int priority)
{
   unsigned char *p=mi->data;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=strlen(p)+1;
   p+=sizeof(int);
   p+=sizeof(time_t);
   p+=sizeof(int);
   if (p-(unsigned char *)mi>mi->record_length) return -1;
   p[-4]=priority>>24;
   p[-3]=priority>>16;
   p[-2]=priority>> 8;
   p[-1]=priority>> 0;
   return priority;
}

inline
void message_get_date(const struct message_index *mi, int *year, int *month, int *day)
{
   (*year) = mi->mes_date >> 9;
   (*month) = (mi->mes_date >> 5) & 0xf;
   (*day) = mi->mes_date & 0x1f;
}


int message_age(const struct message_index *mi)
{   
   time_t ctmt,mtmt;
   struct tm *tmp;
   int y, m, d;

   time(&ctmt);
   tmp=localtime(&ctmt);
   message_get_date(mi, &y, &m, &d);
   tmp->tm_year = y - 1900;
   tmp->tm_mon  = m - 1;
   tmp->tm_mday = d;
   mtmt=mktime(tmp);
   return ((ctmt-mtmt+(86400/2))/86400);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.