home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume22
/
nn6.4
/
part18
/
news.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-07
|
7KB
|
323 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Article header parsing.
*/
#include "config.h"
#include "news.h"
export 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);
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++;
bp++;
while (*bp && isascii(*bp) && isspace(*bp) && *bp != NL) bp++;
*fptr = bp;
}
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 '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);
if (news.ng_from == NULL)
check("ender:", 6, ng_from);
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_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_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 (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) == 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) == 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;
}