home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Mail / Bundles / EnhanceMail-2.1-MIHS / mailtoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-30  |  8.4 KB  |  306 lines

  1. /* -*-C-*-
  2. *******************************************************************************
  3. *
  4. * File:         mailtoc.c
  5. * RCS:          /usr/local/sources/CVS/EnhanceMail/mailtoc.c,v 1.4 1997/05/31 01:31:32 tom Exp
  6. * Description:  Table-of-contents access routines for Mail.app utilities
  7. * Author:       Carl Edman
  8. * Created:      Sun Apr 25 10:31:24 1993
  9. * Modified:     Fri May 30 00:47:20 1997 Tom Hageman <tom@basil.icce.rug.nl>
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       Experimental (Do Not Distribute)
  13. *
  14. * (C) Copyright 1993, but otherwise this file is perfect freeware.
  15. *
  16. *******************************************************************************
  17. */
  18.  
  19. #import <libc.h>
  20. //#import <stdlib.h>
  21. //#import <stdio.h>
  22. //#import <string.h>
  23. //#import <time.h>
  24. //#import <sys/file.h>
  25. //#import <sys/param.h>
  26. //#import <sys/types.h>
  27. //#import <sys/stat.h>
  28. //#import <sys/dir.h>
  29. #import <errno.h>
  30.  
  31. #import "mailtoc.h"
  32.  
  33. #define TOC_MAGIC 890712
  34. #define TOC_MESSAGE_INDEX_MAX 100000
  35.    /* arbitrary limit on message index record size, to avoid crashes on corrupt mailboxes. */
  36.  
  37. static void swap_table_of_contents_header_to_host(struct table_of_contents_header *toc)
  38. {
  39.    toc->magic=NXSwapBigLongToHost(toc->magic);
  40.    toc->num_msgs=NXSwapBigLongToHost(toc->num_msgs);
  41.    toc->mbox_time=NXSwapBigLongToHost(toc->mbox_time);
  42.    toc->list=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->list));
  43.    toc->window.origin.x=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.x));
  44.    toc->window.origin.y=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.y));
  45.    toc->window.size.width=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.width));
  46.    toc->window.size.height=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.height));
  47. }
  48.  
  49. struct table_of_contents_header *get_table_of_contents_header(FILE *f,int createflag)
  50. {
  51.    int n;
  52.    struct table_of_contents_header *toc;
  53.    toc=malloc(sizeof(*toc));
  54.    if(toc==NULL) return 0;
  55.    errno=0;
  56.    if ((n=fread((void *)toc,1,sizeof(*toc),f))!=sizeof(*toc))
  57.    {
  58.       if (!(createflag && n==0))
  59.       {
  60.      free(toc);
  61.      return 0;
  62.       }
  63.       toc->magic=TOC_MAGIC;
  64.       toc->num_msgs=0;
  65.       toc->mbox_time=-1;
  66.       toc->list=102.0;
  67.       toc->window.origin.x=271.0;
  68.       toc->window.origin.y=151.0;
  69.       toc->window.size.width=557.0;
  70.       toc->window.size.height=532.0;
  71.       /* Write table of contents immediately, so space for it is allocated.
  72.      Caveat: this will byteswap the contents of the in-memory toc,
  73.      so we'll fall through to the unswapping code below. */
  74.       if (put_table_of_contents_header(f,toc)!=0)
  75.       {
  76.      free(toc);
  77.      return 0;
  78.       }
  79.    }
  80.    else
  81.    {
  82.       swap_table_of_contents_header_to_host(toc);
  83.    }
  84.    if (toc->magic!=TOC_MAGIC) /* basic sanity check. */
  85.    {
  86.       free(toc);
  87.       return 0;
  88.    }
  89.    return toc;
  90. }
  91.  
  92. static inline void swap_message_index_to_host(struct message_index *mi)
  93. {
  94.    mi->mes_offset=NXSwapBigLongToHost(mi->mes_offset);
  95.    mi->mes_length=NXSwapBigLongToHost(mi->mes_length);
  96.    mi->mes_date=NXSwapBigLongToHost(mi->mes_date);
  97. }
  98.  
  99. struct message_index *get_message_index(FILE *f)
  100. {
  101.    long rl;
  102.    struct message_index *mi;
  103.    errno=0;
  104.    if (fread(&rl,1,sizeof(rl),f)!=sizeof(rl)) return 0;
  105.    rl=NXSwapBigLongToHost(rl);
  106.    if (rl > TOC_MESSAGE_INDEX_MAX) return 0;
  107.    mi=malloc(rl);
  108.    if(mi==NULL) return 0;
  109.    mi->record_length=rl;
  110.    if (fread(((char *)mi)+sizeof(rl),1,rl-sizeof(rl),f)!=rl-sizeof(rl))
  111.    {
  112.       free(mi);
  113.       return 0;
  114.    }
  115.    swap_message_index_to_host(mi);
  116.    return mi;
  117. }
  118.  
  119. static inline void swap_message_index_to_disk(struct message_index *mi)
  120. {
  121.    mi->mes_offset=NXSwapHostLongToBig(mi->mes_offset);
  122.    mi->mes_length=NXSwapHostLongToBig(mi->mes_length);
  123.    mi->mes_date=NXSwapHostLongToBig(mi->mes_date);
  124. }
  125.  
  126. int put_message_index(FILE *f,struct message_index *mi)
  127. {
  128.    long reclen=mi->record_length;
  129.    int ret;
  130.    mi->record_length=NXSwapHostLongToBig(mi->record_length);
  131.    swap_message_index_to_disk(mi);
  132.    errno=0;
  133.    ret=(fwrite(mi,1,reclen,f)!=reclen);
  134.    mi->record_length=NXSwapBigLongToHost(mi->record_length);
  135.    swap_message_index_to_host(mi);
  136.    return ret;
  137. }
  138.  
  139. static void swap_table_of_contents_header_to_disk(struct table_of_contents_header *toc)
  140. {
  141.    toc->magic=NXSwapHostLongToBig(toc->magic);
  142.    toc->num_msgs=NXSwapHostLongToBig(toc->num_msgs);
  143.    toc->mbox_time=NXSwapHostLongToBig(toc->mbox_time);
  144.    toc->list=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->list));
  145.    toc->window.origin.x=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.x));
  146.    toc->window.origin.y=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.y));
  147.    toc->window.size.width=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.width));
  148.    toc->window.size.height=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.height));
  149. }
  150.  
  151. int put_table_of_contents_header(FILE *f,struct table_of_contents_header *toc)
  152. {
  153.    int ret;
  154.    swap_table_of_contents_header_to_disk(toc);
  155.    errno=0;
  156.    rewind(f);
  157.    ret=(fwrite(toc,1,sizeof(*toc),f)!=sizeof(*toc));
  158.    swap_table_of_contents_header_to_host(toc);
  159.    return ret;
  160. }
  161.  
  162. long message_current_date(void)
  163. {
  164.    time_t clock;
  165.    struct tm *ctm;
  166.    time(&clock);
  167.    ctm=localtime(&clock);
  168.    return ((ctm->tm_mday&0x1f)
  169.            +(((ctm->tm_mon+1)&0xf)<<5)
  170.            +((ctm->tm_year+1900)<<9));
  171. }
  172.  
  173. long message_date(int year,const char *month,int day)
  174. {
  175.    static const char months[][4]=
  176.    {
  177.       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  178.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  179.    };
  180.    int m;
  181.    
  182.    for(m=0;m<12;m++) if (!strncmp(month,months[m],3)) break;
  183.    m=(m%12)+1; /* Wrap around to January for unidentifiable month
  184.                   It's better than failing for an unattended program */
  185.    
  186.    return (day&0x1f) + ((m&0xf)<<5) + (year << 9);
  187. }
  188.  
  189. char *message_from(const struct message_index *mi)
  190. {
  191.    char *p=mi->data;
  192.    return p;
  193. }
  194.  
  195. char *message_subject(const struct message_index *mi)
  196. {
  197.    char *p=mi->data;
  198.    p+=strlen(p)+1;
  199.    return p;
  200. }
  201.  
  202. char *message_reference(const struct message_index *mi)
  203. {
  204.    char *p=mi->data;
  205.    p+=strlen(p)+1;
  206.    p+=strlen(p)+1;
  207.    return p;
  208. }
  209.  
  210. int message_attachsize(const struct message_index *mi)
  211. {
  212.    const unsigned char *p=mi->data;
  213.    p+=strlen(p)+1;
  214.    p+=strlen(p)+1;
  215.    p+=strlen(p)+1;
  216.    p+=sizeof(int);   
  217.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  218.    return (int)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
  219. }
  220.  
  221. int message_set_attachsize(struct message_index *mi,int size)
  222. {
  223.    unsigned char *p=mi->data;
  224.    p+=strlen(p)+1;
  225.    p+=strlen(p)+1;
  226.    p+=strlen(p)+1;
  227.    p+=sizeof(int);
  228.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  229.    p[-4]=size>>24;
  230.    p[-3]=size>>16;
  231.    p[-2]=size>> 8;
  232.    p[-1]=size>> 0;
  233.    return size;
  234. }
  235.  
  236. time_t message_attachtime(const struct message_index *mi)
  237. {
  238.    const unsigned char *p=mi->data;
  239.    p+=strlen(p)+1;
  240.    p+=strlen(p)+1;
  241.    p+=strlen(p)+1;
  242.    p+=sizeof(int);
  243.    p+=sizeof(time_t);
  244.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  245.    return (time_t)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
  246. }
  247.  
  248. time_t message_set_attachtime(struct message_index *mi,time_t time)
  249. {
  250.    unsigned char *p=mi->data;
  251.    p+=strlen(p)+1;
  252.    p+=strlen(p)+1;
  253.    p+=strlen(p)+1;
  254.    p+=sizeof(int);
  255.    p+=sizeof(time_t);
  256.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  257.    p[-4]=((int)time)>>24;
  258.    p[-3]=((int)time)>>16;
  259.    p[-2]=((int)time)>> 8;
  260.    p[-1]=((int)time)>> 0;
  261.    return time;
  262. }
  263.  
  264. int message_priority(const struct message_index *mi)
  265. {
  266.    const unsigned char *p=mi->data;
  267.    p+=strlen(p)+1;
  268.    p+=strlen(p)+1;
  269.    p+=strlen(p)+1;
  270.    p+=sizeof(int);
  271.    p+=sizeof(time_t);
  272.    p+=sizeof(int);
  273.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  274.    return ((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);
  275. }
  276.  
  277. int message_set_priority(struct message_index *mi,int priority)
  278. {
  279.    unsigned char *p=mi->data;
  280.    p+=strlen(p)+1;
  281.    p+=strlen(p)+1;
  282.    p+=strlen(p)+1;
  283.    p+=sizeof(int);
  284.    p+=sizeof(time_t);
  285.    p+=sizeof(int);
  286.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  287.    p[-4]=priority>>24;
  288.    p[-3]=priority>>16;
  289.    p[-2]=priority>> 8;
  290.    p[-1]=priority>> 0;
  291.    return priority;
  292. }
  293.  
  294. int message_age(const struct message_index *mi)
  295. {   
  296.    time_t ctmt,mtmt;
  297.    struct tm *tmp;
  298.    time(&ctmt);
  299.    tmp=localtime(&ctmt);
  300.    tmp->tm_year=(mi->mes_date>>9)-1900;
  301.    tmp->tm_mon =((mi->mes_date>>5)&0xf)-1;
  302.    tmp->tm_mday=mi->mes_date&0x1f;
  303.    mtmt=mktime(tmp);
  304.    return ((ctmt-mtmt+(86400/2))/86400);
  305. }
  306.