home *** CD-ROM | disk | FTP | other *** search
- /* areas.c -- parse SOUP's AREAS file
- This file is part of Paperboy, an offline mail/newsreader for Windows
- Copyright (C) 1994 Michael H. Vartanian
- vart@clark.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- /*
- #include <direct.h>
- */
- #include "areas.h"
- #include "soup.h"
- #include "error.h"
- #include "structs.h"
- #include "msgs.h"
- #include "reclaim.h"
-
- static struct llareas * areahead=NULL; /* Top of all data structures */
- char * packetpath=NULL;
-
- int fgetlf (int max, FILE * stream, char * s)
- {
- int c=0;
- char * p;
-
- assert(stream!=NULL);
- assert(s!=NULL);
- assert(max>0);
-
-
- /* If feof, return NULL */
- if (feof(stream)) return 0;
-
- /* Read in characters from stream until
- a) LF character reached
- b) EOF is reached
- c) max-1 characters are read in
- */
- p=s;
- /* TODO: Optimize this function, since it's been profiled as > 50% of our CPU time! */
- while ( (c!=LFCHAR) && !(feof(stream)) && ((p-s)<(max-1)) )
- {
- c=getc(stream);
- *p++=(char)c;
- }
-
-
- /* Strip off LF, NULL terminate the string */
- if (c==LFCHAR) p--;
- *p='\0'; /* Null terminate the string */
- return strlen(s);
- }
-
-
-
- int savepath (const char * fname)
- {
- char * endofpath;
-
- packetpath=strdup(fname);
- if (packetpath==NULL) return ERRMEM;
- endofpath=strrchr(packetpath,PATH_SEP);
- if (endofpath==NULL) return ERRIO; /* Path has no slashes? */
- endofpath++;
- *endofpath='\0'; /* NULL terminate after last slash */
- return 0; /* Everything OK */
- }
-
-
-
- void areatype (char * encoding)
- {
- /* m?, M? and b? become ??m (private mail)
- u?, B? and i? become ??n (public news)
- everything else becomes ??u (unknown) */
-
- char areatype;
-
- if (encoding[3]=='\0') /* If we need to figure this out */
- {
- switch (encoding[0])
- {
- case MAILTYPE:
- areatype=MAILTYPE;
- break;
- case MAILMMDF:
- areatype=MAILTYPE;
- break;
- case BINMAIL:
- areatype=MAILTYPE;
- break;
- case RNEWSTYPE:
- areatype=NEWSTYPE;
- break;
- case BINNEWS:
- areatype=NEWSTYPE;
- break;
- default:
- areatype=UNKTYPE;
- break;
- }
- encoding[2]=areatype;
- }
- }
-
- static int comparearea (const void * a1, const void * a2)
- {
- struct llareas * p1, * p2;
- struct llareas ** p;
-
- assert(a1!=NULL);
- assert(a2!=NULL);
- p=(struct llareas **)a1;
- p1=(struct llareas *)*p;
- p=(struct llareas **)a2;
- p2=(struct llareas *)*p;
- assert(p1!=NULL);
- assert(p2!=NULL);
- assert(p1->magic==AREAMAGIC);
- assert(p2->magic==AREAMAGIC);
-
- if (p1->isfolder && !p2->isfolder) return -1;
- if (!p1->isfolder && p2->isfolder) return 1;
-
- return strcmp(p1->name,p2->name);
- }
-
- int sortareas(void)
- /* Sort the areas, email first, alphabetically */
- {
- struct llareas ** areas;
- struct llareas * cur;
- int p, numareas;
- unsigned int arraysize;
-
- /* We create an array large enough to hold all the areas */
- arraysize=sizeof(struct llareas)*GetNumAreas();
- areas=(struct llareas **)malloc(arraysize);
- if (areas==NULL) return ERRMEM;
- memset(areas,0,sizeof(arraysize));
-
- /* Stuff pointers into the array */
- cur=areahead;
- numareas=GetNumAreas();
- for (p=0; p<numareas; p++)
- {
- assert(cur!=NULL);
- assert(cur->magic==AREAMAGIC);
- areas[p]=cur;
- cur=cur->next;
- }
-
- /* Sort the array */
- qsort(areas, numareas, sizeof(struct llareas *), comparearea);
-
- /* Reassmeble the linked list */
- areahead=areas[0];
- for (p=0; p<numareas-1; p++)
- areas[p]->next=areas[p+1];
-
- areas[p]->next=NULL; /* End of list */
-
- free(areas);
- return 0;
- }
-
- int DLLFUNC LoadAreas (const char * areasfname)
- {
- int result;
- int holderror;
- struct llareas * cur;
-
- holderror=0;
-
- /* Save path for future use */
- result=savepath(areasfname);
- if (result) holderror=result;
-
- /* Read through AREAS file, recording all pertinent information */
- result=parseareas (areasfname);
- if (result) holderror=result;
-
- /* Figure out the message type from the encoding */
- cur=areahead;
- while (cur!=NULL)
- {
- areatype(cur->encoding);
- cur=cur->next;
- }
-
- /* Sort areas */
- result=sortareas();
- if (result) holderror=result;
-
- /* Load in message summaries from whatever index (or not) we can use */
- cur=areahead;
- while (cur!=NULL)
- {
- result=parsemsg (cur);
- if (result) holderror=result;
- cur=cur->next;
- }
- return holderror;
- }
-
- void DLLFUNC RemoveArea (char * foldername)
- {
- struct llareas * cur, * prev;
-
- assert(foldername!=NULL);
-
- /* See if a folder with that name already exists, delete if so */
- /* Case 0,1 */
- while ( areahead && (strcmp(areahead->name,foldername)==0) )
- {
- /* Remove from head of list */
- cur=areahead;
- areahead=areahead->next;
- reclaimgroup(cur);
- free(cur);
- }
-
- /* Case 2,3 */
- prev=areahead;
- while (prev!=NULL && prev->next!=NULL)
- {
- if (strcmp(prev->next->name,foldername)==0)
- {
- /* Remove from middle of list */
- cur=prev->next;
- prev->next=cur->next;
- reclaimgroup(cur);
- free(cur);
- }
- else prev=prev->next;
- }
- }
-
- int DLLFUNC LoadFolder (char * foldername, char * folderfile, char * folderdesc)
- {
- struct llareas * cur;
- int holderror,result;
-
- holderror=0;
-
- assert(foldername!=NULL);
- assert(folderfile!=NULL);
- assert(folderdesc!=NULL);
-
- /* Delete if we've already used it */
- RemoveArea(foldername);
-
- /* Create new folder */
- cur=(struct llareas *) malloc(sizeof(struct llareas));
- if (cur==NULL) return ERRMEM;
- memset(cur,0,sizeof(struct llareas)); /* Zero it out */
- cur->magic=AREAMAGIC;
- cur->isfolder=1;
-
- /* Add new folder to top of arealist */
- cur->next=areahead;
- areahead=cur;
-
- /* Add data to folder */
- cur->head=NULL; /* No messages yet */
- cur->name=strdup(foldername);
- if (cur->name==NULL) return ERRMEM;
- cur->prefix=strdup(folderfile);
- if (cur->prefix==NULL) return ERRMEM;
- cur->desc=strdup(folderdesc);
- if (cur->desc==NULL) return ERRMEM;
- strcpy(cur->encoding,"bnm"); /* Binary mail, no index, private mail */
-
- /* Sort areas */
- result=sortareas();
- if (result) holderror=result;
-
- result=parsemsg(cur); /* Read in messages */
- if (result) holderror=result;
-
- return (holderror);
- }
-
- int parseareas (const char * areasfname)
- {
- FILE * fareas;
- char * prefix, * name, * encode, * desc;
- struct llareas * cur;
- char line[MAXLINE];
- char newprefix[MAXLINE];
-
- /* Check for existence of file, return error if doesn't exist */
- if (areasfname==NULL) return ERRIO;
- fareas=fopen(areasfname,"rb"); /* MS-DOS C compilers like binary */
- if (fareas==NULL) return ERRIO;
-
- /* Until EOF, read in each line of AREAS file, adding to top of linked list
- Check for EOF
- Get next line, terminated by LF
- Extract prefix, Extract area name, Extract encoding,
- Extract description, if exists
- Add to end of linked list
- */
-
- while (!feof(fareas))
- {
- fgetlf(sizeof(line)-1,fareas,line);
- prefix=strtok(line,SOUPSEP);
- name=strtok(NULL,SOUPSEP);
- encode=strtok(NULL,SOUPSEP);
- desc=strtok(NULL,SOUPSEP); /* NULL if not present */
- /* Remaining fields we ignore */
-
- /* If we don't get all valid fields, we skip this record */
- if ( !prefix || !(*prefix) ) continue;
- if ( !name || !(*name ) ) continue;
- if ( !encode || !(*encode) ) continue;
- if (strlen(encode)<2) continue; /* Need two valid characters */
-
- /* Allocate and add to head of linked list */
- cur=(struct llareas *)malloc(sizeof(struct llareas));
- if (cur==NULL) return ERRMEM;
- memset(cur,0,sizeof(struct llareas)); /* Zero it out */
- cur->magic=AREAMAGIC;
- cur->next=areahead;
- areahead=cur;
-
- /* Put data into linked-list structure */
- cur->head=NULL; /* No messages yet */
- /* Create a fully qualified pathname for prefix */
- assert(packetpath!=NULL);
- strcpy(newprefix,packetpath);
- strcat(newprefix,prefix);
- strcat(newprefix,MSGEXT);
- cur->prefix=strdup(newprefix);
- if (cur->prefix==NULL) return ERRMEM;
- cur->name=strdup(name);
- if (cur->name==NULL) return ERRMEM;
- if (desc!=NULL)
- {
- cur->desc=strdup(desc);
- if (cur->desc==NULL) return ERRMEM;
- } else cur->desc=strdup(""); /* No description available */
- strncpy(cur->encoding,encode,sizeof(cur->encoding)-1);
- }
-
- fclose(fareas);
- return 0;
- }
-
-
-
- int DLLFUNC GetNumAreas (void)
- {
- /* Count number of nodes in linked list */
- struct llareas * cur;
- unsigned int count=0;
-
- cur=areahead;
-
- while (cur!=NULL)
- {
- cur=cur->next;
- count++;
- }
-
- return count;
- }
-
- struct llareas * findarea (int index)
- /* Goes to [index] entry in linked list */
- {
- struct llareas * cur;
- int max;
- int count=1;
-
- assert(index>0);
- max=GetNumAreas();
- assert(index<=max);
-
- cur=areahead;
-
- while (cur!=NULL && count!=index)
- {
- cur=cur->next;
- count++;
- }
-
- assert(cur!=NULL);
-
- return cur;
- }
-
-
- int DLLFUNC IsFolder (int index)
- {
- struct llareas * cur;
- cur=findarea(index);
- return cur->isfolder;
- }
-
- char * DLLFUNC GetAreaName (int index)
- {
- struct llareas * cur;
- /* Find node matching index */
- cur=findarea(index);
- return cur->name;
- }
-
-
-
- char * DLLFUNC GetAreaEncoding (int index)
- {
- struct llareas * cur;
- /* Find node matching index */
- cur=findarea(index);
- return cur->encoding;
- }
-
-
-
- char * DLLFUNC GetAreaDesc (int index)
- {
- struct llareas * cur;
- /* Find node matching index */
- cur=findarea(index);
- if (cur->desc) return cur->desc;
- return "";
- }
-
-
-