Metropoli BBS
VIEWER: header.c MODE: TEXT (ASCII)
/************************************************************************/
/*                                                                      */
/*  News header file processing                                         */
/*                                                                      */
/*  This source is public domain. Bug reports should be sent to         */
/*                                                                      */
/*  harald@os2point.ping.de                                             */
/*  harald@haport.sesam.com                                             */
/*  Fido: 2:2448/434                                                    */
/*                                                                      */
/************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <lprintf.h>
#include <jobid.h>
#include <history.h>
#include <active.h>
#include <header.h>

static KEYWORD key[] = {
    { "Approved"    , ID_Approved     },
    { "Control"     , ID_Control      },
    { "Date"        , ID_Date         },
    { "Distribution", ID_Distribution },
    { "Expires"     , ID_Expires      },
    { "Followup-To" , ID_Followup_To  },
    { "From"        , ID_From         },
    { "Keywords"    , ID_Keywords     },
    { "Lines"       , ID_Lines        },
    { "Message-ID"  , ID_Message_ID   },
    { "Newsgroups"  , ID_Newsgroups   },
    { "Organization", ID_Organization },
    { "Path"        , ID_Path         },
    { "References"  , ID_References   },
    { "Reply-To"    , ID_Reply_To     },
    { "Sender"      , ID_Sender       },
    { "Subject"     , ID_Subject      },
    { "Summary"     , ID_Summary      },
    { "X-Newsgroups", ID_X_Newsgroups },
    { "Xref"        , ID_Xref         }
};

HEADER header[ID_LASTENTRY];

char *xheader[MAX_XHEADER];
int  nxheader;

int nkeys = (sizeof(key) / sizeof(*key));

static int cmpkey(char *line, KEYWORD *pkey);

/************************************************************************/
/*                                                                      */
/*  read_header                                                         */
/*                                                                      */
/*  Reads an article header from file fp into buf with size bufsiz.     */
/*  Note that buf may contain a previously read string.                 */
/*                                                                      */
/*  Returns number of bytes read or zero on any error.                  */
/*                                                                      */
/************************************************************************/
long read_header(FILE *fp, char *buf, int *bufsiz)
{
    long rv = 0;
    char *line = buf;
    int  buflen = *bufsiz;
    int  boff = strlen(buf);    /* Any previously read characters */
    int  first = 1;
    int  cont;
    char *cp, *cp1, *cp2;
    int  i;

    *bufsiz = 0;
    /*
     * Initialize header storage
     */
    nxheader = 0;
    memset(header, 0, sizeof(header));
    for(i = 0; i < nkeys; i++)
        header[key[i].idx].key = key[i].name;

    /*
     * Read all lines upto the first empty line and
     * interpret them as header lines.
     */
    while(buflen > boff && fgets(line + boff, buflen - boff, fp)) {
        /*
         * If linefeed is missing, either the input file
         * is broken or we ran out of space.
         */
        if((cp = strchr(line, '\r')) == NULL)
            cp = strchr(line, '\n');
        if(cp == NULL) {
            lprintf("Article header too big or article broken");
            rv = 0;
            break;
        }

        /*
         * Chop off the line feed and check if this line is empty.
         */
        *cp = '\0';
        rv += strlen(line) + 1 + boff;
        boff = 0;
        if(*line == '\0')
            break;

        /*
         * Continuation lines start with space or tab. Ignore
         * them until we found our first real header entry.
         */
        if((cont = (*line == ' ' || *line == '\t')) != 0 && first)
            continue;

        /*
         * Ignore 'From ' and 'Received: ' lines which may have been
         * left over by some mailers.
         */
        if(!strnicmp(line, "From ", 5) || !strnicmp(line, ">From ", 6))
            continue;
        if(!strnicmp(line, "Received: ", 10))
            continue;

        /*
         * Pack the line by removing extra spaces and control characters.
         */
        cp1 = line - 1;
        cp2 = line;
        while(*cp2) {
            if(*cp2 == ' ' || *cp2 == '\t') {
                if(*cp1 && *cp1 != ' ' && *cp1 != '\t')
                    *++cp1 = ' ';
            }
            else if(!iscntrl(*cp2))
                *++cp1 = *cp2;
            cp2++;
        }
        *(cp1 + 1) = '\0';
        while(*cp1 == ' ')
            *cp1-- = '\0';

        /*
         * On continuation lines we will change the string delimiter
         * of our previous line to a space.
         */
        if(cont) {
            *(line - 1) = ' ';
            cont = 0;
        }
        else {
            cp = strchr(line, ':');
            if(cp) {
                KEYWORD *pkey;

                *cp = '\0';
                pkey = bsearch(line, key, nkeys, sizeof(KEYWORD), cmpkey);
                *cp = ':';
                if(pkey) {
                    for(cp++; *cp == ' ' || *cp == '\t'; cp++) ;
                    header[pkey->idx].info = cp;
                }
                else {
                    if(nxheader < MAX_XHEADER) {
                        xheader[nxheader++] = line;
                    }
                }
            }
        }

        first = strlen(line) + 1;
        buflen -= first;
        *bufsiz += first;
        first = 0;
        line = cp1 + 2;
    }
    return(rv);
}

static int cmpkey(char *line, KEYWORD *pkey)
{
    return(stricmp(line, pkey->name));
}

/************************************************************************/
/*                                                                      */
/*                                                                      */
/************************************************************************/
char *rfc_date(char *buf, int bufsiz)
{
    time_t t;

    time(&t);
    strftime(buf, bufsiz, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));

    return(buf);
}

/************************************************************************/
/*                                                                      */
/*  write_header                                                        */
/*                                                                      */
/*  Writes an article header to a file pointed at by fp.                */
/*                                                                      */
/************************************************************************/
long write_header(FILE *fp)
{
    long rv = 0;
    int i;

    for(i = 0; i < ID_Lines; i++)
        if(header[i].info)
            rv += fprintf(fp, "%s: %s\n", header[i].key, header[i].info);

    for(i = 0; i < nxheader; i++)
        rv += fprintf(fp, "%s\n", xheader[i]);

    return(rv);
}

/************************************************************************/
/*                                                                      */
/*                                                                      */
/*                                                                      */
/************************************************************************/
int write_xref(FILE *fp, char *node, char **ngarray)
{
    int  rv = 0;
    int  cxref = 0;
    char *line = NULL;
    int  i;
    char snum[12];
    long himsg;

    for(i = 0; ngarray[i] != NULL; i++) {
        if(find_active(NULL, ngarray[i], NULL, &himsg)) {
            if(line == NULL) {
                line = malloc(MAX_XREFSIZE);
                strcpy(line, "Xref: ");
                strcat(line, node);
            }
            strcat(line, " ");
            strcat(line, ngarray[i]);
            strcat(line, ":");
            strcat(line, ltoa(himsg + 1, snum, 10));
            cxref++;
        }
    }
    if(line) {
        if(cxref > 1)
            rv = fprintf(fp, "%s\n", line);
        free(line);
    }
    return(rv);
}
[ RETURN TO DIRECTORY ]