home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / INTERNET / USENET / PAPERBOY / SOURCE.ZIP / AREAS.C next >
Encoding:
C/C++ Source or Header  |  1994-10-02  |  9.9 KB  |  447 lines

  1. /*      areas.c -- parse SOUP's AREAS file
  2.     This file is part of Paperboy, an offline mail/newsreader for Windows
  3.     Copyright (C) 1994  Michael H. Vartanian
  4.         vart@clark.net
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. /*
  24. #include <direct.h>
  25. */
  26. #include "areas.h"
  27. #include "soup.h"
  28. #include "error.h"
  29. #include "structs.h"
  30. #include "msgs.h"
  31. #include "reclaim.h"
  32.  
  33. static struct llareas * areahead=NULL;    /* Top of all data structures */
  34. char * packetpath=NULL;
  35.  
  36. int fgetlf (int max, FILE * stream, char * s)
  37. {
  38.     int c=0;
  39.     char * p;
  40.  
  41.     assert(stream!=NULL);
  42.     assert(s!=NULL);
  43.     assert(max>0);
  44.     
  45.  
  46. /* If feof, return NULL */
  47.     if (feof(stream)) return 0;
  48.  
  49. /* Read in characters from stream until
  50.     a) LF character reached 
  51.     b) EOF is reached
  52.     c) max-1 characters are read in
  53. */
  54.     p=s;
  55. /* TODO: Optimize this function, since it's been profiled as > 50% of our CPU time! */
  56.     while ( (c!=LFCHAR) && !(feof(stream)) && ((p-s)<(max-1)) )
  57.     {
  58.         c=getc(stream);
  59.         *p++=(char)c;
  60.     }
  61.  
  62.  
  63. /* Strip off LF, NULL terminate the string */
  64.     if (c==LFCHAR) p--;
  65.     *p='\0';    /* Null terminate the string */
  66.     return strlen(s);
  67. }
  68.  
  69.  
  70.  
  71. int savepath (const char * fname)
  72. {
  73.     char * endofpath;
  74.  
  75.     packetpath=strdup(fname);
  76.     if (packetpath==NULL) return ERRMEM;
  77.     endofpath=strrchr(packetpath,PATH_SEP);
  78.     if (endofpath==NULL) return ERRIO; /* Path has no slashes? */
  79.     endofpath++;
  80.     *endofpath='\0';    /* NULL terminate after last slash */
  81.     return 0;    /* Everything OK */
  82. }
  83.  
  84.  
  85.  
  86. void areatype (char * encoding)
  87. {
  88. /*    m?, M? and b? become ??m (private mail)
  89.     u?, B? and i? become ??n (public news)
  90.     everything else becomes ??u (unknown)    */
  91.  
  92.     char areatype;
  93.     
  94.     if (encoding[3]=='\0')    /* If we need to figure this out */
  95.     {
  96.         switch (encoding[0])
  97.         {
  98.             case MAILTYPE:
  99.                 areatype=MAILTYPE;
  100.                 break;
  101.             case MAILMMDF:
  102.                 areatype=MAILTYPE;
  103.                 break;
  104.             case BINMAIL:
  105.                 areatype=MAILTYPE;
  106.                 break;
  107.             case RNEWSTYPE:
  108.                 areatype=NEWSTYPE;
  109.                 break;
  110.             case BINNEWS:
  111.                 areatype=NEWSTYPE;
  112.                 break;
  113.             default:
  114.                 areatype=UNKTYPE;
  115.                 break;
  116.         }
  117.         encoding[2]=areatype;
  118.     }
  119. }
  120.  
  121. static int comparearea (const void * a1, const void * a2)
  122. {
  123.     struct llareas * p1, * p2;
  124.     struct llareas ** p;
  125.     
  126.     assert(a1!=NULL);
  127.     assert(a2!=NULL);
  128.     p=(struct llareas **)a1;
  129.     p1=(struct llareas *)*p;
  130.     p=(struct llareas **)a2;
  131.     p2=(struct llareas *)*p;
  132.     assert(p1!=NULL);
  133.     assert(p2!=NULL);
  134.     assert(p1->magic==AREAMAGIC);
  135.     assert(p2->magic==AREAMAGIC);
  136.  
  137.     if (p1->isfolder && !p2->isfolder) return -1;
  138.     if (!p1->isfolder && p2->isfolder) return  1;
  139.  
  140.     return strcmp(p1->name,p2->name);
  141. }
  142.  
  143. int sortareas(void)
  144. /* Sort the areas, email first, alphabetically */
  145. {
  146.     struct llareas ** areas;
  147.     struct llareas * cur;
  148.     int p, numareas;
  149.     unsigned int arraysize;
  150.  
  151.     /* We create an array large enough to hold all the areas */
  152.     arraysize=sizeof(struct llareas)*GetNumAreas();
  153.     areas=(struct llareas **)malloc(arraysize);
  154.     if (areas==NULL) return ERRMEM;
  155.     memset(areas,0,sizeof(arraysize));
  156.  
  157.     /* Stuff pointers into the array */
  158.     cur=areahead;
  159.     numareas=GetNumAreas();
  160.     for (p=0; p<numareas; p++)
  161.     {
  162.         assert(cur!=NULL);
  163.         assert(cur->magic==AREAMAGIC);
  164.         areas[p]=cur;
  165.         cur=cur->next;
  166.     }
  167.  
  168.     /* Sort the array */
  169.     qsort(areas, numareas, sizeof(struct llareas *), comparearea);
  170.  
  171.     /* Reassmeble the linked list */
  172.     areahead=areas[0];
  173.     for (p=0; p<numareas-1; p++)
  174.         areas[p]->next=areas[p+1];
  175.  
  176.     areas[p]->next=NULL;    /* End of list */
  177.  
  178.     free(areas);
  179.     return 0;
  180. }
  181.  
  182. int DLLFUNC LoadAreas (const char * areasfname)
  183. {
  184.     int result;
  185.     int holderror;
  186.     struct llareas * cur;
  187.     
  188.     holderror=0;
  189.  
  190. /* Save path for future use */
  191.     result=savepath(areasfname);
  192.     if (result) holderror=result;
  193.  
  194. /* Read through AREAS file, recording all pertinent information */
  195.     result=parseareas (areasfname);
  196.     if (result) holderror=result;
  197.     
  198. /* Figure out the message type from the encoding */
  199.     cur=areahead;
  200.     while (cur!=NULL)
  201.     {
  202.         areatype(cur->encoding);
  203.         cur=cur->next;
  204.     }
  205.  
  206. /* Sort areas */
  207.     result=sortareas();
  208.     if (result) holderror=result;
  209.  
  210. /* Load in message summaries from whatever index (or not) we can use */
  211.     cur=areahead;
  212.     while (cur!=NULL)
  213.     {
  214.         result=parsemsg (cur);
  215.         if (result) holderror=result;
  216.         cur=cur->next;
  217.     }
  218.     return holderror;
  219. }
  220.  
  221. void DLLFUNC RemoveArea (char * foldername)
  222. {
  223.     struct llareas * cur, * prev;
  224.  
  225.     assert(foldername!=NULL);
  226.     
  227.     /* See if a folder with that name already exists, delete if so */
  228.     /* Case 0,1 */
  229.     while ( areahead && (strcmp(areahead->name,foldername)==0) )
  230.     {
  231.         /* Remove from head of list */
  232.         cur=areahead;
  233.         areahead=areahead->next;
  234.         reclaimgroup(cur);
  235.         free(cur);
  236.     }
  237.  
  238.     /* Case 2,3 */
  239.     prev=areahead;
  240.     while (prev!=NULL && prev->next!=NULL)
  241.     {
  242.         if (strcmp(prev->next->name,foldername)==0)
  243.         {
  244.             /* Remove from middle of list */
  245.             cur=prev->next;
  246.             prev->next=cur->next;
  247.             reclaimgroup(cur);
  248.             free(cur);
  249.         }
  250.         else prev=prev->next;
  251.     }
  252. }
  253.  
  254. int DLLFUNC LoadFolder (char * foldername, char * folderfile, char * folderdesc)
  255. {
  256.     struct llareas * cur;
  257.     int holderror,result;
  258.  
  259.     holderror=0;
  260.  
  261.     assert(foldername!=NULL);
  262.     assert(folderfile!=NULL);
  263.     assert(folderdesc!=NULL);
  264.  
  265.     /* Delete if we've already used it */
  266.     RemoveArea(foldername);
  267.     
  268.     /* Create new folder */
  269.     cur=(struct llareas *) malloc(sizeof(struct llareas));
  270.     if (cur==NULL) return ERRMEM;
  271.     memset(cur,0,sizeof(struct llareas)); /* Zero it out */
  272.     cur->magic=AREAMAGIC;
  273.     cur->isfolder=1;
  274.  
  275.     /* Add new folder to top of arealist */
  276.     cur->next=areahead;
  277.     areahead=cur;
  278.     
  279.     /* Add data to folder */
  280.     cur->head=NULL;    /* No messages yet */
  281.     cur->name=strdup(foldername);
  282.     if (cur->name==NULL) return ERRMEM;
  283.     cur->prefix=strdup(folderfile);
  284.     if (cur->prefix==NULL) return ERRMEM;
  285.     cur->desc=strdup(folderdesc);
  286.     if (cur->desc==NULL) return ERRMEM;
  287.     strcpy(cur->encoding,"bnm");    /* Binary mail, no index, private mail */ 
  288.  
  289.     /* Sort areas */
  290.     result=sortareas();
  291.     if (result) holderror=result;
  292.  
  293.     result=parsemsg(cur);    /* Read in messages */
  294.     if (result) holderror=result;
  295.  
  296.     return (holderror);
  297. }
  298.  
  299. int parseareas (const char * areasfname)
  300. {
  301.     FILE * fareas;
  302.     char * prefix, * name, * encode, * desc;
  303.     struct llareas * cur;
  304.     char line[MAXLINE];
  305.     char newprefix[MAXLINE];
  306.  
  307. /* Check for existence of file, return error if doesn't exist */
  308.     if (areasfname==NULL) return ERRIO;
  309.     fareas=fopen(areasfname,"rb");    /* MS-DOS C compilers like binary */
  310.     if (fareas==NULL) return ERRIO;
  311.  
  312. /* Until EOF, read in each line of AREAS file, adding to top of linked list 
  313.         Check for EOF
  314.         Get next line, terminated by LF
  315.         Extract prefix, Extract area name, Extract encoding, 
  316.         Extract description, if exists
  317.         Add to end of linked list 
  318.  */
  319.  
  320.     while (!feof(fareas))
  321.     {
  322.         fgetlf(sizeof(line)-1,fareas,line);
  323.         prefix=strtok(line,SOUPSEP);
  324.         name=strtok(NULL,SOUPSEP);
  325.         encode=strtok(NULL,SOUPSEP);
  326.         desc=strtok(NULL,SOUPSEP);        /* NULL if not present */
  327.         /* Remaining fields we ignore */
  328.  
  329.         /* If we don't get all valid fields, we skip this record */
  330.         if ( !prefix || !(*prefix) ) continue;
  331.         if ( !name   || !(*name  ) ) continue;
  332.         if ( !encode || !(*encode) ) continue;
  333.         if (strlen(encode)<2) continue;    /* Need two valid characters */
  334.  
  335.         /* Allocate and add to head of linked list */
  336.         cur=(struct llareas    *)malloc(sizeof(struct llareas));
  337.         if (cur==NULL) return ERRMEM;
  338.         memset(cur,0,sizeof(struct llareas));    /* Zero it out */
  339.         cur->magic=AREAMAGIC;
  340.         cur->next=areahead;
  341.         areahead=cur;
  342.  
  343.         /* Put data into linked-list structure */
  344.         cur->head=NULL;     /* No messages yet */
  345.         /* Create a fully qualified pathname for prefix */
  346.         assert(packetpath!=NULL);
  347.         strcpy(newprefix,packetpath);
  348.         strcat(newprefix,prefix);
  349.         strcat(newprefix,MSGEXT);
  350.         cur->prefix=strdup(newprefix);
  351.         if (cur->prefix==NULL) return ERRMEM;
  352.         cur->name=strdup(name);
  353.         if (cur->name==NULL) return ERRMEM;
  354.         if (desc!=NULL)
  355.         {
  356.             cur->desc=strdup(desc);
  357.             if (cur->desc==NULL) return ERRMEM;
  358.         } else cur->desc=strdup("");    /* No description available */
  359.         strncpy(cur->encoding,encode,sizeof(cur->encoding)-1);
  360.     }
  361.  
  362.     fclose(fareas);
  363.     return 0;
  364. }
  365.  
  366.  
  367.  
  368. int DLLFUNC GetNumAreas (void)
  369. {
  370. /* Count number of nodes in linked list */
  371.     struct llareas * cur;
  372.     unsigned int count=0;
  373.  
  374.     cur=areahead;
  375.  
  376.     while (cur!=NULL)
  377.     {
  378.         cur=cur->next;
  379.         count++;
  380.     }
  381.  
  382.     return count;
  383. }
  384.  
  385. struct llareas * findarea (int index)
  386. /* Goes to [index] entry in linked list */
  387. {
  388.     struct llareas * cur;
  389.     int max;
  390.     int count=1;
  391.  
  392.     assert(index>0);
  393.     max=GetNumAreas();
  394.     assert(index<=max);
  395.  
  396.     cur=areahead;
  397.  
  398.     while (cur!=NULL && count!=index)
  399.     {
  400.         cur=cur->next;
  401.         count++;
  402.     }
  403.  
  404.     assert(cur!=NULL);
  405.  
  406.     return cur;
  407. }
  408.  
  409.  
  410. int DLLFUNC IsFolder (int index)
  411. {
  412.     struct llareas * cur;
  413.     cur=findarea(index);
  414.     return cur->isfolder;
  415. }
  416.  
  417. char * DLLFUNC GetAreaName (int index)
  418. {
  419.     struct llareas * cur;
  420. /* Find node matching index */
  421.     cur=findarea(index);
  422.     return cur->name;
  423. }
  424.  
  425.  
  426.  
  427. char * DLLFUNC GetAreaEncoding (int index)
  428. {
  429.     struct llareas * cur;
  430. /* Find node matching index */
  431.     cur=findarea(index);
  432.     return cur->encoding;
  433. }
  434.  
  435.  
  436.  
  437. char * DLLFUNC GetAreaDesc (int index)
  438. {
  439.     struct llareas * cur;
  440. /* Find node matching index */
  441.     cur=findarea(index);
  442.     if (cur->desc) return cur->desc;
  443.     return "";
  444. }
  445.  
  446.  
  447.