home *** CD-ROM | disk | FTP | other *** search
- /* -*-C-*-
- *******************************************************************************
- *
- * File: mailtoc.c
- * RCS: /usr/local/sources/CVS/mailapp-utilities/mailtoc.c,v 1.5 1997/12/17 16:41:04 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) /* OPENSTEP */
- # 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);
- }
-