home *** CD-ROM | disk | FTP | other *** search
- /*
- * (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;
- }
-