Metropoli BBS
VIEWER: history.c MODE: TEXT (ASCII)
/*
 *  This part deals with the history database and had
 *  been originally written by
 *
 *  Kai Uwe Rommel <rommel@ars.muc.de>
 *
 *  Bug reports related to THIS heavily modified version
 *  should be sent to
 *
 *  harald@os2point.ping.de
 *  harald@haport.sesam.com
 *  Fido: 2:2448/434
 *
 */
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <time.h>

#include <fcntl.h>

#include <dbgheap.h>

#include <lprintf.h>
#include <dbm.h>
#include <datetime.h>
#include <active.h>
#include <history.h>

/************************************************************************/
/*                                                                      */
/* gethistart                                                           */
/*                                                                      */
/* Finds an article entry in the history file by it's id and            */
/* returns the path name of this article if found.                      */
/*                                                                      */
/* Parameter    Description                                             */
/* ------------ ------------------------------------------------------- */
/* historyfile  Points to a string that specifies the name of the       */
/*              history data base. Usually this will be "history".      */
/*                                                                      */
/* msg_id       Points to a string that specifies the id of the         */
/*              message to search for.                                  */
/*                                                                      */
/* artpath      Points to a buffer that receives the path to the        */
/*              message if found. This buffer must be preinitialized    */
/*              with the name of the newsgroup's home directory.        */
/*              If the caller doesn't need the path then this pointer   */
/*              may be NULL.                                            */
/* ------------ ------------------------------------------------------- */
/* Return value True if found, false otherwise.                         */
/*                                                                      */
/************************************************************************/
int gethistart(const char *historyfile, char *msg_id, char *artpath)
{
    register char  *cp;
    register char  *cp1;
    char  *line;
    DBM   *db;
    datum key, val;
    char  *histpag;
    int   isvirgin;

    /*
     * If no history file exists we assume that we were
     * started in a virgin environment. We check this first
     * to avoid an error message while opening the database.
     */
    histpag = malloc(strlen(historyfile) + 5);
    strcat(strcpy(histpag, historyfile), ".pag");
    isvirgin = access(histpag, 0);
    free(histpag);
    if(isvirgin)
        return(0);

    /*
     * Fetch the entry with the given message id
     */
    if((db = dbm_open(historyfile, O_RDONLY, 0)) != NULL) {
        key.dptr = msg_id;
        key.dsize = strlen(msg_id) + 1;
        val = dbm_fetch(db, key);

        if (val.dptr == NULL) {
            dbm_close(db);
            return(0);  /* article not found */
        }
        if(artpath == NULL) {
            dbm_close(db);
            return(1);  /* article found, caller doesn't need path */
        }

        /*
         * We need to copy the history line because dbm_close
         * will free the read buffer of the database.
         */
        line = strdup(val.dptr);
        dbm_close(db);
    }
    else {
        lprintf("Failed to open %s", historyfile);
        return(0);
    }

    /*
     * We assume this structure of our history line
     * <msg_id> <time> <size> <grp:num>[,<grp:num>]
     * Field separators may be space or tab. The last
     * field <grp:num> may be repeated and separated
     * by commas.
     */
    cp = line;
    while(*cp && *cp != ' ' && *cp != '\t')
        cp++;
    while(*cp == ' ' || *cp == '\t')
        cp++;
    while(*cp && *cp != ' ' && *cp != '\t')
        cp++;
    while(*cp == ' ' || *cp == '\t')
        cp++;

    if(*cp) {
        /*
         * Now cp points to the first <grp:num> item.
         * Append the path of this message to artpath.
         */
        cp1 = strchr(artpath, '\0');
        *cp1++ = '\\';
        while(*cp && *cp != ' ' && *cp != '\t' && *cp != ',') {
            if(*cp == '.' || *cp == ':')
                *cp1++ = '\\';
            else
                *cp1++ = *cp;
            cp++;
        }
        *cp1 = '\0';

        free(line);
        return(1);  /* article found, path supplied */
    }

    free(line);
    return (0);     /* article found, but could not supply path */
}

/************************************************************************/
/*                                                                      */
/*  addhistart                                                          */
/*                                                                      */
/*                                                                      */
/************************************************************************/
int addhistart(const char *historyfile, char *messageID,
               char **ngarray, long art_size)
{
    int groups_found = 0;
    char *hist_record = malloc(HISTRECSIZE);
    char snum[12];
    long himsg;
    datum key, val;
    void *hfp;
    int  i;

    /*
     * Create history record
     */
    sprintf(hist_record, "%ld %ld ", local_to_gmt(time(NULL)), art_size);
    for(i = 0; ngarray[i] != NULL; i++) {
        if(find_active(NULL, ngarray[i], NULL, &himsg)) {
            if (groups_found)
                strcat(hist_record, ",");
            strcat(hist_record, ngarray[i]);
            strcat(hist_record, ":");
            strcat(hist_record, ltoa(himsg, snum, 10));
            groups_found++;
        }
    }

    if(groups_found) {
        /*
         * Add history record to database
         */
        if((hfp = dbm_open(historyfile, O_RDWR | O_CREAT, 0666)) != NULL) {
            key.dptr = messageID;
            key.dsize = strlen(key.dptr) + 1;
            val.dptr = hist_record;
            val.dsize = strlen(val.dptr) + 1;
            if (dbm_store(hfp, key, val, DBM_REPLACE))
                lprintf("Failed to store history record");
            dbm_close(hfp);
        }
        else
            lprintf("Failed to open %s", historyfile);
    }

    free(hist_record);
    return(groups_found != 0);
}

/************************************************************************/
/*                                                                      */
/* delhistart                                                           */
/*                                                                      */
/* Finds an article entry in the history file by it's id and deletes    */
/* this entry if found.                                                 */
/*                                                                      */
/* Parameter    Description                                             */
/* ------------ ------------------------------------------------------- */
/* historyfile  Points to a string that specifies the name of the       */
/*              history data base. Usually this will be "history".      */
/*                                                                      */
/* msg_id       Points to a string that specifies the id of the         */
/*              message to search for.                                  */
/*                                                                      */
/* artlist      Points to a buffer that receives a list of messages     */
/*              in the format <grp:num>[,<grp:num>]. If no entry was    */
/*              found in historyfile, then this string will be empty.   */
/* ------------ ------------------------------------------------------- */
/* Return value Pointer to artlist.                                     */
/*                                                                      */
/************************************************************************/
char *delhistart(const char *historyfile, char *msg_id, char *artlist)
{
    datum key, val;
    void *hfp;
    char *line;
    char *cp;

    *artlist = '\0';

    /*
     * Search history file
     */
    if((hfp = dbm_open(historyfile, O_RDWR | O_CREAT, 0666)) == NULL) {
        lprintf("Failed to open %s", historyfile);
        return(artlist);
    }

    key.dptr = msg_id;
    key.dsize = strlen(key.dptr) + 1;
    val = dbm_fetch(hfp, key);
    if(val.dptr == NULL) {
        dbm_close(hfp);
        lprintf("Can't find %s to cancel", msg_id);
        return(artlist);
    }

    line = strdup(val.dptr);

    /*
     * Delete entry
     */
    key.dptr = msg_id; /* To check: Is this really needed? */
    key.dsize = strlen(key.dptr) + 1;

    if(dbm_cancel(hfp, key))
        lprintf("Failed to remove article(s) from history");

    dbm_close(hfp);

    /*
     * Copy result into buffer
     */
    cp = line;
    while(*cp && *cp != ' ' && *cp != '\t')
        cp++;
    while(*cp == ' ' || *cp == '\t')
        cp++;
    while(*cp && *cp != ' ' && *cp != '\t')
        cp++;
    while(*cp == ' ' || *cp == '\t')
        cp++;

    if(cp)
        strcpy(artlist, cp);

    free(line);

    return(artlist);
}
[ RETURN TO DIRECTORY ]