/* WIDE AREA INFORMATION SERVER SOFTWARE:
   No guarantees or restrictions.  See the readme file for the full standard
   disclaimer.

   Brewster@think.com
*/

/* this file defines a set of helper functions
 * for indexing common types of files.
 * -brewster 7/90
 */

/* I encourage adding customizations.
 * (too bad they all have to be hard coded, but
 *  C did not have convenient dynamic linking facilities)
 *
 * Add three functions to this file:
 * boolean foo_separator_function(char *line){}
 * void foo_header_function(char *line){}
 * long foo_date_function(char *line){}
 * void foo_finish_header_function(char *header){}
 *
 * then add the prototypes to ircfiles.h
 * then add the functions to the big case statement in irbuild.c
 *
 *
 * to do:
 *   filter for digests
 *
 */


/* Change log:
 * 8/90 brewster added the library customizations
 * 6/91 and before - added a bunch of other filters - JG
 */

#include <string.h>
#include <ctype.h>
#include "cutil.h"
#include "ircfiles.h"

#define MAX_HEADER_LEN 100

static char* trim_trailing_newline _AP((char* string));

static char*
trim_trailing_newline(string)
char* string;
{
  if(string)
    if(strlen(string) > 0)
      if(string[strlen(string) -1] == '\n')
	string[strlen(string) -1] = '\0';
  return(string);
}

/* =================================
 * ===  Groliers Customizations  ===
 * =================================
 */

boolean groliers_separator_function(line)
char *line;
{
  if((strlen(line) > strlen("ARTICLE")) &&
     substrcmp(line, "ARTICLE")){
    /* printf("hit %s\n", line); */
    return(true);
  }
  else{
    return(false);
  }
}

char groliers_header[MAX_HEADER_LEN + 1];

void groliers_header_function(line)
char *line;
{
  if(groliers_separator_function(line)){
    strncpy(groliers_header, line + strlen("ARTICLE") + 2, MAX_HEADER_LEN);
  }
}

void groliers_finish_header_function(header)
char *header;
{
  if(strlen(groliers_header) == 0){
    strncpy(header, "Unknown Title", MAX_HEADER_LEN);
  }
  else{
    strncpy(header, groliers_header, MAX_HEADER_LEN);
  }
  groliers_header[0] = '\0';
}


/* ==============================
 * ===  RMail Customizations  ===
 * ==============================
 */

/* this is just a preliminary version. A good version would
 * produce a headline like gnu emacs RMAIL
 */


boolean mail_separator_function(line)
char *line;
{
  /* this should really look for a "<cr><cr>From " rather than "<cr>From " */
  if((strlen(line) > strlen("From ")) &&
     substrcmp(line, "From ")){
    return(true);
  }
  else{
    return(false);
  }
}

boolean rmail_separator_function(line)
char *line;
{
  if(0 == strcmp(line, "\n")){
    return(true);
  }
  else{
    return(false);
  }
}

/* This one is portable, but might get the wrong answer.
   I'm open to better code.  - Jonny G
*/

static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
			"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};

long getdate(line)
char *line;
{
  char date[255], *temp;
  int day, month, year;
  char cmonth[25];

  strcpy(date, line);

  temp = date;

  while(!isdigit(*temp)) temp++;

  sscanf(temp, "%d %s %d", &day, cmonth, &year);

  for(month = 0; months[month] != NULL; month++)
    if(!strcmp(cmonth, months[month])) break;

  if (year > 99) year = year % 100;

  if(day > 0 && 
     month < 12 &&
     year > 0) {
    return (10000 * year + 100 * (month+1) + day);
  }
  sscanf(temp, "%d/%d/%d", &month, &day, &year);

  if (year > 99) year = year % 100;

  if(day > 0 && 
     month < 12 &&
     year > 0) {
    return (10000 * year + 100 * (month+1) + day);
  }
  sscanf(temp, "%d/%d/%d", &year, &month, &day);

  if (year > 99) year = year % 100;

  if(day > 0 && 
     month < 12 &&
     year > 0) {
    return (10000 * year + 100 * (month+1) + day);
  }
  return 0;
}

long mail_date_function(line)
char *line;
{
  if((strlen(line) > strlen("Date: ")) &&
     substrcmp(line, "Date: ")){
    return(getdate(line+6));
  }
  else return -1;
}

  

char mail_subject[MAX_HEADER_LEN + 1];
char mail_from[MAX_HEADER_LEN + 1];

void mail_header_function(line)
char *line;
{
  if((strlen(line) > strlen("Subject: ")) &&
     substrcmp(line, "Subject: ") &&
     (strlen(mail_subject) == 0)){
    strcpy(mail_subject, "Re: ");
    s_strncat(mail_subject, line + strlen("Subject: "), MAX_HEADER_LEN, MAX_HEADER_LEN);
    trim_trailing_newline(mail_subject);
  }
  else if((strlen(line) > strlen("From: ")) &&
     substrcmp(line, "From: ") &&
     (strlen(mail_from) == 0)){
    /* this should find the <foo@bar> field in the from list */
    strncpy(mail_from, line + strlen("From: "), MAX_HEADER_LEN);
    trim_trailing_newline(mail_from);
  }
  
}

void mail_finish_header_function(header)
char *header;
{
  if(strlen(mail_subject) != 0 &&
     strlen(mail_from) != 0){
    /* trim the from line if needed */
    if(strlen(mail_from) > 10){
      mail_from[10] = '\0';
    }
    strncpy(header, mail_from, MAX_HEADER_LEN);
    s_strncat(header, " ", MAX_HEADER_LEN, MAX_HEADER_LEN);
    s_strncat(header, mail_subject, MAX_HEADER_LEN, MAX_HEADER_LEN);
    /* printf("%s\n", header); */
  }
  else if(strlen(mail_subject) != 0){
    strncpy(header, mail_subject, MAX_HEADER_LEN);
  }
  else if(strlen(mail_from) != 0){
    strncpy(header, mail_from, MAX_HEADER_LEN);
  }
  else{
    strcpy(header, "Unknown Subject");
  }
  mail_from[0] = '\0';
  mail_subject[0] = '\0';
}




boolean mail_or_rmail_separator(line)
char *line;
{
  static boolean blank_line = false;

  if((strlen(line) > strlen("From ")) &&
     substrcmp(line, "From ") &&
     blank_line == true){
    blank_line = false;
    return(true);
  }
  
  if(substrcmp(line, "")){
    blank_line = true;
    return(true);
  }    
  
  if(!strcmp(line, "\n")){
      blank_line = true;
    }
    else{
      blank_line = false;
    }

  return(false);
}


/* ========================================
 * ===  Mail Digest Customizations     ====
 * ========================================
 */

boolean mail_digest_separator_function(line)
char *line;
{
  if((strlen(line) > strlen("-----------------------------")) &&
     substrcmp(line, "------------------------------")){
    return(true);
  }
  else{
    return(false);
  }
}


/* ========================================
 * ===  Library Catalog Customizations  ===
 * ========================================
 */

/* just use the title */

boolean catalog_separator_function(line)
char *line;
{
  if((strlen(line) > strlen("Call:")) &&
     (substrcmp(line, "Call:"))){
    return(true);
  }
  else{
    return(false);
  }
}

char catalog_header[MAX_HEADER_LEN + 1];

void catalog_header_function(line)
char *line;
{
  if((strlen(line) > strlen("Title:")) && 
     (substrcmp(line, "Title:"))){    
    strncpy(catalog_header, line + strlen("Title:"), MAX_HEADER_LEN);
  }
}

void catalog_finish_header_function(header)
char *header;
{
  if(strlen(catalog_header) == 0){
    strcpy(header, "Unknown Title");
  }
  else{
    strncpy(header, catalog_header, MAX_HEADER_LEN);
  }
  catalog_header[0] = '\0';
}



/* ============================
 * ===  Bio Customizations  ===
 * ============================
 */

/* customizations for a DB of genetic abstracts */

boolean hit_header = false;

boolean bio_separator_function(line)
char *line;
{
  if((strlen(line) > strlen(">>>")) &&
     substrcmp(line, ">>>")){
    return(true);
  }
  else{
    return(false);
  }
}

char bio_header[MAX_HEADER_LEN + 1];

void bio_header_function(line)
char *line;

{
  if(hit_header			/* we just hit a seperator previous to this */
     && (!bio_separator_function(line)) /* we are not on the separator now */
     && strlen(bio_header) == 0){ /* and we have not saved the headline yet */
    strcpy(bio_header, line);
    waislog(WLOG_MEDIUM, WLOG_INDEX, "storing line: %s", bio_header);
    hit_header = false;
  }
}

void bio_finish_header_function(header)
char *header;

{
  hit_header = true; /* turn on the flag */
  if(strlen(bio_header) == 0){
    strcpy(header, "Unknown Title");
  }
  else{
    strcpy(header, bio_header);
  }
  bio_header[0] = '\0';
}

/* =================================
 * ===  CMApp   Customizations  ===
 * =================================
 */

boolean cmapp_separator_function(line)
char *line;
{
  if((strlen(line) > strlen("@A")) &&
     substrcmp(line, "@A")){
    /* printf("hit %s\n", line); */
    return(true);
  }
  else{
    return(false);
  }
}

char cmapp_header[MAX_HEADER_LEN + 1];

void cmapp_header_function(line)
char *line;
{
  if((strlen(line) > strlen("APPLICATION:")) &&
     substrcmp(line, "APPLICATION:")){
    /* printf("hit %s\n", line); */
    strncpy(cmapp_header, line + strlen("APPLICATION:"), MAX_HEADER_LEN);
  }
}

void cmapp_finish_header_function(header)
char *header;
{
  if(strlen(cmapp_header) == 0){
    strncpy(header, "Unknown Title", MAX_HEADER_LEN);
  }
  else{
    strncpy(header, cmapp_header, MAX_HEADER_LEN);
  }
  cmapp_header[0] = '\0';
}

/* =================================
 * ===  Jargon   Customizations  ===
 * =================================
 */

boolean jargon_separator_function(line)
char *line;
{
  if((strlen(line) > 0) && line[0] =='<'){
    /* printf("hit %s\n", line); */
    return(true);
  }
  else{
    return(false);
  }
}

char jargon_header[MAX_HEADER_LEN + 1];

void jargon_header_function(line)
char *line;
{
  if((strlen(line) > 0) && line[0] =='<'){
    char *end_ptr = strchr(line, '>');
    if(NULL != end_ptr){
      strncpy(jargon_header, (1+ line), MIN(MAX_HEADER_LEN, end_ptr - line));
      jargon_header[end_ptr-line-1] = '\0';
    }
  }
}	

void jargon_finish_header_function(header)
char *header;
{
  if(strlen(jargon_header) == 0){
    strncpy(header, "Introduction to the Jargon file", MAX_HEADER_LEN);
  }
  else{
    strncpy(header, jargon_header, MAX_HEADER_LEN);
  }
  jargon_header[0] = '\0';
}



/* =================================
 * ===  Internet Resource Guide  ===
 * =================================
 */


char irg_header[MAX_HEADER_LEN + 1];
boolean irg_header_set = FALSE;

boolean irg_separator_function(line)
char *line;
{
  if(line[0] == 12){  /* control L */
    irg_header_set = FALSE;
    return(true);
  }
  else
    return(false);
}

void irg_header_function(line)
char *line;
{
  if((irg_header_set == FALSE) &&
     (line[0] == 32 )){ /* space */
    strncpy(irg_header, line + strspn(line, " "), MAX_HEADER_LEN);
    irg_header_set = TRUE;
  }
  
}

void irg_finish_header_function(header)
char *header;
{
  if(strlen(irg_header) == 0){
    strncpy(header, "Unknown Title", MAX_HEADER_LEN);
  }
  else{
    strncpy(header, irg_header, MAX_HEADER_LEN);
  }
  irg_header[0] = '\0';
  irg_header_set = FALSE;
}

/* ========================
 * ===  Dash Separator  ===
 * ========================
 */


/*
 * dash-seperate entries
 * used in Introduction to Algorithms bug.list, suggestions, etc.
 * --------------------... at least 20 dashes
 * header
 * item
 *  ..
 * --------------------... at least 20 dashes
 */

boolean dash_hit_header = false;

boolean dash_separator_function(line)
char *line;
{
  if((strlen(line) > 20) && substrcmp(line,"--------------------")){
    /* printf("hit %s\n", line); */
    return(true);
  }
  else{
    return(false);
  }
}

char dash_header[MAX_HEADER_LEN + 1];

void dash_header_function(line)
char *line;
{
  if(dash_hit_header
     && (!dash_separator_function(line))
     && strlen(dash_header) == 0) {
    strncpy(dash_header, line, MAX_HEADER_LEN);
    dash_hit_header = false;
  }
}

void dash_finish_header_function(header)
char *header;

{
  dash_hit_header = true; /* turn on the flag */
  if (strlen(dash_header) == 0) {
    strcpy(header, "No Title");
  }
  else {
    strncpy(header, dash_header, MAX_HEADER_LEN);
  }
  dash_header[0] = '\0';
}


/* ============================
 * ===  one_line Separator  ===
 * ============================
 */

/* this is where each line is a document (good for databases) */

boolean one_line_hit_header = false;

boolean one_line_separator_function(line)
char *line;
{
    return(true);
}

char one_line_header[MAX_HEADER_LEN + 1];

void one_line_header_function(line)
char *line;
{
    strncpy(one_line_header, line, MAX_HEADER_LEN);
}

void one_line_finish_header_function(header)
char *header;
{
  if (strlen(one_line_header) == 0) {
    strcpy(header, "No Title");
  }
  else {
    strncpy(header, one_line_header, MAX_HEADER_LEN);
  }
  one_line_header[0] = '\0';
}

/* =============================
 * ===  Paragraph Separator  ===
 * =============================
 */

/* paragraph files - seperated by a blank line.  Next line is the header */

char para_header[MAX_HEADER_LEN +1];
static boolean para_start = true;

boolean para_separator_function(line)
char *line;
{
  if (para_start == true) {
    para_start = false;
    return true;
  }
  if (strlen(line) < 2)
    para_start = true;
  return false;
}

void para_header_function(line)
char *line;
{
  if (para_header[0] == 0)
    strncpy(para_header, line, MAX_HEADER_LEN);
}

void para_finish_header_function(header)
char *header;
{
  if (strlen(para_header) == 0) {
    strcpy(header, "No Title");
  }
  else {
    strncpy(header, para_header, MAX_HEADER_LEN);
  }
  para_header[0] = 0;
}  

/* ==========================
 * ===  Seeker Separator  ===
 * ==========================
 */

boolean seeker_separator_function(line)
char *line;
{
  return(dash_separator_function(line));
}

char seeker_header[MAX_HEADER_LEN + 1];
boolean in_headline = FALSE;

void seeker_header_function(line)
char *line;
{
  if(strlen(line) > strlen("Headline:") &&
     substrcmp(line, "Headline:")){
    in_headline = TRUE;
    seeker_header[0] = '\0';
    /* printf("hit headline!\n"); */
  }
  else if(in_headline == TRUE &&
	  (strlen(seeker_header) < (MAX_HEADER_LEN - 1))){
    s_strncat(seeker_header, line, 
	      MAX_HEADER_LEN, MAX_HEADER_LEN);
    trim_trailing_newline(seeker_header);
  }
}

void seeker_finish_header_function(header)
char *header;
{
  if (strlen(seeker_header) == 0) {
    strcpy(header, "No Title");
  }
  else {
    strncpy(header, seeker_header, MAX_HEADER_LEN);
  }
  seeker_header[0] = '\0';
  in_headline = TRUE;
}  

/* ==========================
 * ===  RLIN Separator  ===
 * ==========================
 */

boolean rlin_separator_function(line)
char *line;
{
  return(dash_separator_function(line));
}

char rlin_header[MAX_HEADER_LEN + 1];
boolean rlin_in_headline = FALSE;

void rlin_header_function(line)
char *line;
{
  if(rlin_separator_function(line)){
    rlin_in_headline = TRUE;
    rlin_header[0] = '\0';
    /* printf("hit headline!\n"); */
  }
  else if(rlin_in_headline == TRUE &&
	  (strlen(rlin_header) < (MAX_HEADER_LEN - 1))){
    s_strncat(rlin_header, line, 
	      MAX_HEADER_LEN, MAX_HEADER_LEN);
    trim_trailing_newline(rlin_header);
  }
}

void rlin_finish_header_function(header)
char *header;
{
  if (strlen(rlin_header) == 0) {
    strcpy(header, "No Title");
  }
  else {
    strncpy(header, rlin_header, MAX_HEADER_LEN);
  }
  rlin_header[0] = '\0';
  in_headline = TRUE;
}  

/* ========================================
 * ===  MH_BBoard  Customizations     ====
 * ========================================
 */

/* gcardwel@uci.edu
MH bboards use a series of control A's to do a blank line.. yuk!
*/

boolean mh_bboard_separator_function(line)
char *line;
{
  static boolean blank_line = false;

  if((strlen(line) > strlen("BBoard-ID: ")) &&
     substrcmp(line, "BBoard-ID: ") &&
     blank_line == true){
    blank_line = false;
    return(true);
  }
  
  if(!strcmp(line, "\001\001\001\001\n")){
    blank_line = true;
  }
  else{
    blank_line = false;
  }
  return (false);
}

