ftp.nice.ch/pub/next/unix/network/news/nn.6.4.16.s.tar.gz#/nn/news.c

This is news.c in view mode; [Download] [Up]

/*
 *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
 *
 *	Article header parsing.
 */

#include "config.h"
#include "news.h"

export int retry_on_error = 0;

char *parse_header(f, hdr_field, modes, hdrbuf)
FILE 			*f;
char 			**(*hdr_field)();
int 			modes;
news_header_buffer	hdrbuf;
{
    register char *bp, *cp, **fptr;
    int siz, all, date_only;
    off_t pos;

    pos = ftell(f);

/* read first NEWS_HEADER_BUFFER bytes (should be more than enough) */

    all 	= modes & GET_ALL_FIELDS;
    date_only 	= modes & GET_DATE_ONLY;

    siz = fread(hdrbuf, sizeof(char), NEWS_HEADER_BUFFER, f);
    if (siz <= 0) {
	hdrbuf[0] = NUL;
	return hdrbuf;
    }

    bp = hdrbuf;
    bp[siz-1] = NUL;

    /* decode subarticle header */
    while (*bp) {

	if (*bp == NL) {	/* empty line following header */
	    ++bp;
	    fseek(f, pos + (bp - hdrbuf), 0);
	    return bp;
	}

	if (*bp == SP) {	/* for comp.ai.neural-nets digests */
	    bp++;		/* which have <NL><space><NL> after header */
	    continue;
	}

	if (date_only && *bp != 'D')
	    fptr = NULL;
	else
	    if (fptr = (*hdr_field)(bp, all)) {
		while (*bp && *bp != ':' && isascii(*bp) && !isspace(*bp))
		    bp++;
		if (*bp) bp++;
		while (*bp && isascii(*bp) && isspace(*bp) && *bp != NL) bp++;
		*fptr = bp;
	    }
#ifdef NO_HEADER_SEPARATION_HACK
	    else {
		for (cp = bp; *cp && *cp != ':'; cp++) {
		    if (!isascii(*cp)) break;
		    if (*cp == '_' || *cp == '-') continue;
		    if (isalnum(*cp)) continue;
		    break;
		}
		if (*cp != ':') {
		    *bp = NL;
		    pos--;
		    continue;
		}
	    }
#endif

	while (*bp && *bp != NL) bp++;

	/* Assume that continued lines are never empty! */
	if (fptr && bp == *fptr) *fptr = NULL;

	while (*bp) {	    /* look for continued lines */
	    cp = bp + 1;
	    while (*cp && isascii(*cp) && isspace(*cp) && *cp != NL) cp++;

	    if (cp == bp + 1) {
		/* next line is empty or not indented */
		*bp++ = NUL;
		break;
	    }

	    if (*cp == NUL || *cp == NL) {
		/* next line is not empty, but blank line */
		*bp = NUL;
		bp = cp;	/* assume end of header */
		break;
	    }

	    *bp = SP;		/* substitute NL with SPACE */
	    bp = cp;
	    while (*bp && *bp != NL) bp++;
	}
    }

    return bp;
}

static char **art_hdr_field(lp, all)
register char *lp;
int all;
{

#define check(name, lgt, field) \
    if (isascii(lp[lgt]) && isspace(lp[lgt]) && strncmp(name, lp, lgt) == 0)\
	return &news.field

    switch (*lp++) {

     case 'A':
     case 'a':
	if (!all) break;
	check("pproved:",	 8, ng_appr);
	break;

     case 'B':
     case 'b':
	check("ack-References:", 15, ng_bref);
	break;

     case 'C':
     case 'c':
	check("ontrol:",	 7, ng_control);
	break;

     case 'D':
     case 'd':
	check("ate:", 		 4, ng_date);
	if (!all) break;
	check("ate-Received:",	13, ng_rdate);
	check("istribution:", 	12, ng_dist);
	break;

     case 'F':
     case 'f':
	check("rom:",		 4, ng_from);
	if (!all) break;
	check("ollowup-To:",	11, ng_follow);
	check("ollowup-to:",	11, ng_follow);
	break;

     case 'K':
     case 'k':
	if (!all) break;
	check("eywords:",	 8, ng_keyw);
	break;

     case 'L':
     case 'l':
	check("ines:",	 	 5, ng_xlines);
	break;

     case 'M':
     case 'm':
	if (!all) break;
	if (strncmp(lp, "essage-", 7)) break;
	lp += 7;
	check("ID:",	3, ng_ident);
	check("Id:",	3, ng_ident);
	check("id:",	3, ng_ident);
	break;

     case 'N':
     case 'n':
	check("ewsgroups:",	10, ng_groups);
	break;

     case 'O':
     case 'o':
	if (!all) break;
	check("rganization:",	12, ng_org);
	check("rganisation:",	12, ng_org);
	break;

     case 'P':
     case 'p':
	if (!all) break;
	check("ath:",		 4, ng_path);
	break;

     case 'R':
     case 'r':
	check("eferences:",	10, ng_ref);
	check("eply-To:",	 8, ng_reply);
	check("eply-to:",	 8, ng_reply);
	break;

     case 'S':
     case 's':
	check("ubject:",	 7, ng_subj);
	check("ender:",		 6, ng_sender);
	if (!all) break;
	check("ummary:",	 7, ng_summ);
	break;

     case 'T':
     case 't':
	check("itle:",	 	 5, ng_subj);
	break;
    }

    return NULL;

#undef check
}

is_header_line(line)
char *line;
{
    return art_hdr_field(line, 0) != (char **)NULL;
}


FILE *open_news_article(art, modes, buffer1, buffer2)
article_header 		*art;
int 			modes;
news_header_buffer	buffer1, buffer2;
{
    char *body;
    char *digest_buffer;
    char *parse_header();
    struct stat statb;
    int retry;
    FILE *f;
#ifdef NNTP
    int lazy;
    FILE *nntp_get_article();
#endif /* NNTP */

    if (art->flag & A_FOLDER) {
	f = open_file(group_path_name, OPEN_READ);
	if (f == NULL) return NULL;
	fseek(f, art->hpos, 0);
#ifdef NNTP
    } else
    if (use_nntp) {
	lazy = (current_group->master_flag & M_ALWAYS_DIGEST) == 0
	    && (modes & LAZY_BODY) ? 1 : 0;
	f = nntp_get_article(art->a_number, lazy);
	if (f == NULL) return NULL;
#endif /* NNTP */
    } else {
	sprintf(group_file_name, "%d", art->a_number);

	retry = retry_on_error;
	while ((f = open_file(group_path_name, OPEN_READ)) == NULL)
	    if (--retry < 0) return NULL;

	/* necessary because empty files wreak havoc */
	if (fstat(fileno(f), &statb) < 0 ||
	    statb.st_size < art->lpos || statb.st_size <= (off_t)0) {
	    fclose(f);
	    return who_am_i == I_AM_MASTER ? (FILE *)1 : NULL;
	}
    }

    digest_buffer = buffer1;

    if (modes & FILL_NEWS_HEADER) {

	news.ng_from 	= NULL;
	news.ng_reply 	= NULL;
	news.ng_name 	= NULL;
	news.ng_subj 	= NULL;
	news.ng_groups 	= NULL;
	news.ng_ref 	= NULL;
	news.ng_bref 	= NULL;
	news.ng_sender	= NULL;

	news.ng_xlines 	= NULL;

	if (modes & GET_ALL_FIELDS) {
	    news.ng_path 	= NULL;
	    news.ng_reply 	= NULL;
	    news.ng_ident 	= NULL;
	    news.ng_follow 	= NULL;
	    news.ng_keyw 	= NULL;
	    news.ng_dist 	= NULL;
	    news.ng_org 	= NULL;
	    news.ng_appr 	= NULL;
	    news.ng_summ	= NULL;
	    news.ng_control	= NULL;
	    news.ng_date	= NULL;
	    news.ng_rdate	= NULL;
	}

	if (modes & GET_DATE_ONLY)
	    news.ng_date	= NULL;

	body = parse_header(f, art_hdr_field, modes, buffer1);

	news.ng_lines = news.ng_xlines ? atoi(news.ng_xlines) : -1;
	if (news.ng_from == NULL) news.ng_from = news.ng_sender;

	if (modes & FILL_OFFSETS) {
	    art->fpos = news.ng_fpos = ftell(f);

	    fseek(f, (off_t)0, 2);
	    news.ng_lpos = ftell(f);
	}
#ifdef NNTP
	else if (use_nntp && (art->flag & (A_DIGEST | A_FOLDER)) == 0) {
	    fseek(f, (off_t)0, 2);
	    art->lpos = ftell(f);
	}
#endif

	news.ng_flag = 0;

	if (news.ng_appr) news.ng_flag |= N_MODERATED;

	if (modes & DIGEST_CHECK && is_digest()) news.ng_flag |= N_DIGEST;

#ifdef NNTP
	if (use_nntp && lazy && news.ng_flag & N_DIGEST) {
	    fclose(f);
	    f = nntp_get_article(art->a_number, 2);
	    if (f == NULL) return NULL;
	}
#endif
	digest_buffer = buffer2;
    }
#ifdef NNTP
    else if (use_nntp && (art->flag & (A_DIGEST | A_FOLDER)) == 0) {
	fseek(f, (off_t)0, 2);
	art->lpos = ftell(f);
    }
#endif

    if (modes & FILL_DIGEST_HEADER) {
	fseek(f, art->hpos, 0);
	parse_digest_header(f, modes & GET_ALL_FIELDS, digest_buffer);
    }

    fseek(f, (modes & SKIP_HEADER) ? art->fpos : art->hpos, 0);

    return f;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.