home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Mail / mailapp-utilities-2.1-MIHS / Source / mailtoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-12-17  |  9.2 KB  |  333 lines

  1. /* -*-C-*-
  2. *******************************************************************************
  3. *
  4. * File:         mailtoc.c
  5. * RCS:          /usr/local/sources/CVS/mailapp-utilities/mailtoc.c,v 1.5 1997/12/17 16:41:04 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. #if (NS_TARGET_MAJOR >= 4) /* OPENSTEP */
  34. #  import <Foundation/NSByteOrder.h>
  35. #  define NXSwapBigLongToHost        NSSwapBigLongToHost
  36. #  define NXSwapBigFloatToHost        NSSwapBigFloatToHost
  37. #  define NXConvertHostFloatToSwapped    NSConvertHostFloatToSwapped
  38. #  define NXSwapHostLongToBig        NSSwapHostLongToBig
  39. #  define NXSwapHostFloatToBig        NSSwapHostFloatToBig
  40. #  define NXConvertSwappedFloatToHost    NSConvertSwappedFloatToHost
  41. #endif
  42.  
  43. #define TOC_MAGIC 890712
  44. #define TOC_MESSAGE_INDEX_MAX 100000
  45.    /* arbitrary limit on message index record size, to avoid crashes on corrupt mailboxes. */
  46.  
  47. static void swap_table_of_contents_header_to_host(struct table_of_contents_header *toc)
  48. {
  49.    toc->magic=NXSwapBigLongToHost(toc->magic);
  50.    toc->num_msgs=NXSwapBigLongToHost(toc->num_msgs);
  51.    toc->mbox_time=NXSwapBigLongToHost(toc->mbox_time);
  52.    toc->list=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->list));
  53.    toc->window.origin.x=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.x));
  54.    toc->window.origin.y=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.origin.y));
  55.    toc->window.size.width=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.width));
  56.    toc->window.size.height=NXSwapBigFloatToHost(NXConvertHostFloatToSwapped(toc->window.size.height));
  57. }
  58.  
  59. struct table_of_contents_header *get_table_of_contents_header(FILE *f,int createflag)
  60. {
  61.    int n;
  62.    struct table_of_contents_header *toc;
  63.    toc=malloc(sizeof(*toc));
  64.    if(toc==NULL) return 0;
  65.    errno=0;
  66.    if ((n=fread((void *)toc,1,sizeof(*toc),f))!=sizeof(*toc))
  67.    {
  68.       if (!(createflag && n==0))
  69.       {
  70.      free(toc);
  71.      return 0;
  72.       }
  73.       toc->magic=TOC_MAGIC;
  74.       toc->num_msgs=0;
  75.       toc->mbox_time=-1;
  76.       toc->list=102.0;
  77.       toc->window.origin.x=271.0;
  78.       toc->window.origin.y=151.0;
  79.       toc->window.size.width=557.0;
  80.       toc->window.size.height=532.0;
  81.       /* Write table of contents immediately, so space for it is allocated
  82.          on-disk.  {{Does NOT fall through to byteswapping below anymore,
  83.      since this is handled in put_table_of_contents_header itself now.}} */
  84.       if (put_table_of_contents_header(f,toc)!=0)
  85.       {
  86.      free(toc);
  87.      return 0;
  88.       }
  89.    }
  90.    else
  91.    {
  92.       swap_table_of_contents_header_to_host(toc);
  93.    }
  94.    if (toc->magic!=TOC_MAGIC) /* basic sanity check. */
  95.    {
  96.       free(toc);
  97.       return 0;
  98.    }
  99.    return toc;
  100. }
  101.  
  102. static inline void swap_message_index_to_host(struct message_index *mi)
  103. {
  104.    mi->mes_offset=NXSwapBigLongToHost(mi->mes_offset);
  105.    mi->mes_length=NXSwapBigLongToHost(mi->mes_length);
  106.    mi->mes_date=NXSwapBigLongToHost(mi->mes_date);
  107. }
  108.  
  109. struct message_index *get_message_index(FILE *f)
  110. {
  111.    long rl;
  112.    struct message_index *mi;
  113.    errno=0;
  114.    if (fread(&rl,1,sizeof(rl),f)!=sizeof(rl)) return 0;
  115.    rl=NXSwapBigLongToHost(rl);
  116.    if (rl > TOC_MESSAGE_INDEX_MAX) return 0;
  117.    mi=malloc(rl);
  118.    if(mi==NULL) return 0;
  119.    mi->record_length=rl;
  120.    if (fread(((char *)mi)+sizeof(rl),1,rl-sizeof(rl),f)!=rl-sizeof(rl))
  121.    {
  122.       free(mi);
  123.       return 0;
  124.    }
  125.    swap_message_index_to_host(mi);
  126.    return mi;
  127. }
  128.  
  129. static inline void swap_message_index_to_disk(struct message_index *mi)
  130. {
  131.    mi->mes_offset=NXSwapHostLongToBig(mi->mes_offset);
  132.    mi->mes_length=NXSwapHostLongToBig(mi->mes_length);
  133.    mi->mes_date=NXSwapHostLongToBig(mi->mes_date);
  134. }
  135.  
  136. int put_message_index(FILE *f,struct message_index *mi)
  137. {
  138.    long reclen=mi->record_length;
  139.    int ret;
  140.    mi->record_length=NXSwapHostLongToBig(mi->record_length);
  141.    swap_message_index_to_disk(mi);
  142.    errno=0;
  143.    ret=(fwrite(mi,1,reclen,f)!=reclen);
  144.    mi->record_length=NXSwapBigLongToHost(mi->record_length);
  145.    swap_message_index_to_host(mi);
  146.    return ret;
  147. }
  148.  
  149. static void swap_table_of_contents_header_to_disk(struct table_of_contents_header *toc)
  150. {
  151.    toc->magic=NXSwapHostLongToBig(toc->magic);
  152.    toc->num_msgs=NXSwapHostLongToBig(toc->num_msgs);
  153.    toc->mbox_time=NXSwapHostLongToBig(toc->mbox_time);
  154.    toc->list=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->list));
  155.    toc->window.origin.x=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.x));
  156.    toc->window.origin.y=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.origin.y));
  157.    toc->window.size.width=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.width));
  158.    toc->window.size.height=NXConvertSwappedFloatToHost(NXSwapHostFloatToBig(toc->window.size.height));
  159. }
  160.  
  161. int put_table_of_contents_header(FILE *f,struct table_of_contents_header *toc)
  162. {
  163.    int ret;
  164.    swap_table_of_contents_header_to_disk(toc);
  165.    errno=0;
  166.    rewind(f);
  167.    ret=(fwrite(toc,1,sizeof(*toc),f)!=sizeof(*toc));
  168.    swap_table_of_contents_header_to_host(toc);
  169.    return ret;
  170. }
  171.  
  172. #define MESSAGE_DATE(y,m,d)   ((d)+((m)<<5)+((y)<<9))
  173.  
  174. long message_current_date(void)
  175. {
  176.    time_t clock;
  177.    struct tm *ctm;
  178.    time(&clock);
  179.    ctm=localtime(&clock);
  180.    return MESSAGE_DATE(ctm->tm_year-1900, ctm->tm_mon+1, ctm->tm_mday);
  181. }
  182.  
  183. long message_date(int year,const char *month,int day)
  184. {
  185.    static const char months[][4]=
  186.    {
  187.       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  188.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  189.    };
  190.    int m;
  191.  
  192.    for(m=0;m<12;m++) if (!strncasecmp(month,months[m],3)) break;
  193.    m=(m%12)+1; /* Wrap around to January for unidentifiable month
  194.                   It's better than failing for an unattended program */
  195.  
  196.    if (year < 200) year += (year < 70 ? 2000 : 1900);
  197.    /* Y2K fix -- we don't expect e-mail from before 200AD :-) */
  198.  
  199.    if (day <= 0) day = 1; else if (day > 31) day = 31;
  200.  
  201.    return MESSAGE_DATE(year, m, day);
  202. }
  203.  
  204. char *message_from(const struct message_index *mi)
  205. {
  206.    char *p=mi->data;
  207.    return p;
  208. }
  209.  
  210. char *message_subject(const struct message_index *mi)
  211. {
  212.    char *p=mi->data;
  213.    p+=strlen(p)+1;
  214.    return p;
  215. }
  216.  
  217. char *message_reference(const struct message_index *mi)
  218. {
  219.    char *p=mi->data;
  220.    p+=strlen(p)+1;
  221.    p+=strlen(p)+1;
  222.    return p;
  223. }
  224.  
  225. int message_attachsize(const struct message_index *mi)
  226. {
  227.    const unsigned char *p=mi->data;
  228.    p+=strlen(p)+1;
  229.    p+=strlen(p)+1;
  230.    p+=strlen(p)+1;
  231.    p+=sizeof(int);   
  232.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  233.    return (int)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
  234. }
  235.  
  236. int message_set_attachsize(struct message_index *mi,int size)
  237. {
  238.    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.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  244.    p[-4]=size>>24;
  245.    p[-3]=size>>16;
  246.    p[-2]=size>> 8;
  247.    p[-1]=size>> 0;
  248.    return size;
  249. }
  250.  
  251. time_t message_attachtime(const struct message_index *mi)
  252. {
  253.    const unsigned char *p=mi->data;
  254.    p+=strlen(p)+1;
  255.    p+=strlen(p)+1;
  256.    p+=strlen(p)+1;
  257.    p+=sizeof(int);
  258.    p+=sizeof(time_t);
  259.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  260.    return (time_t)((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);   
  261. }
  262.  
  263. time_t message_set_attachtime(struct message_index *mi,time_t time)
  264. {
  265.    unsigned char *p=mi->data;
  266.    p+=strlen(p)+1;
  267.    p+=strlen(p)+1;
  268.    p+=strlen(p)+1;
  269.    p+=sizeof(int);
  270.    p+=sizeof(time_t);
  271.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  272.    p[-4]=((int)time)>>24;
  273.    p[-3]=((int)time)>>16;
  274.    p[-2]=((int)time)>> 8;
  275.    p[-1]=((int)time)>> 0;
  276.    return time;
  277. }
  278.  
  279. int message_priority(const struct message_index *mi)
  280. {
  281.    const unsigned char *p=mi->data;
  282.    p+=strlen(p)+1;
  283.    p+=strlen(p)+1;
  284.    p+=strlen(p)+1;
  285.    p+=sizeof(int);
  286.    p+=sizeof(time_t);
  287.    p+=sizeof(int);
  288.    if (p-(const unsigned char *)mi>mi->record_length) return -1;
  289.    return ((p[-4]<<24)+(p[-3]<<16)+(p[-2]<<8)+p[-1]);
  290. }
  291.  
  292. int message_set_priority(struct message_index *mi,int priority)
  293. {
  294.    unsigned char *p=mi->data;
  295.    p+=strlen(p)+1;
  296.    p+=strlen(p)+1;
  297.    p+=strlen(p)+1;
  298.    p+=sizeof(int);
  299.    p+=sizeof(time_t);
  300.    p+=sizeof(int);
  301.    if (p-(unsigned char *)mi>mi->record_length) return -1;
  302.    p[-4]=priority>>24;
  303.    p[-3]=priority>>16;
  304.    p[-2]=priority>> 8;
  305.    p[-1]=priority>> 0;
  306.    return priority;
  307. }
  308.  
  309. inline
  310. void message_get_date(const struct message_index *mi, int *year, int *month, int *day)
  311. {
  312.    (*year) = mi->mes_date >> 9;
  313.    (*month) = (mi->mes_date >> 5) & 0xf;
  314.    (*day) = mi->mes_date & 0x1f;
  315. }
  316.  
  317.  
  318. int message_age(const struct message_index *mi)
  319. {   
  320.    time_t ctmt,mtmt;
  321.    struct tm *tmp;
  322.    int y, m, d;
  323.  
  324.    time(&ctmt);
  325.    tmp=localtime(&ctmt);
  326.    message_get_date(mi, &y, &m, &d);
  327.    tmp->tm_year = y - 1900;
  328.    tmp->tm_mon  = m - 1;
  329.    tmp->tm_mday = d;
  330.    mtmt=mktime(tmp);
  331.    return ((ctmt-mtmt+(86400/2))/86400);
  332. }
  333.