home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / nn6.4 / part18 / news.c < prev    next >
C/C++ Source or Header  |  1990-06-07  |  7KB  |  323 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Article header parsing.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "news.h"
  9.  
  10. export retry_on_error = 0;
  11.  
  12. char *parse_header(f, hdr_field, modes, hdrbuf)
  13. FILE             *f;
  14. char             **(*hdr_field)();
  15. int             modes;
  16. news_header_buffer    hdrbuf;
  17. {
  18.     register char *bp, *cp, **fptr;
  19.     int siz, all, date_only;
  20.     off_t pos;
  21.  
  22.     pos = ftell(f);
  23.  
  24. /* read first NEWS_HEADER_BUFFER bytes (should be more than enough) */
  25.  
  26.     all     = modes & GET_ALL_FIELDS;
  27.     date_only     = modes & GET_DATE_ONLY;
  28.  
  29.     siz = fread(hdrbuf, sizeof(char), NEWS_HEADER_BUFFER, f);
  30.  
  31.     bp = hdrbuf;
  32.     bp[siz-1] = NUL;
  33.  
  34.     /* decode subarticle header */
  35.     while (*bp) {
  36.  
  37.     if (*bp == NL) {    /* empty line following header */
  38.         ++bp;
  39.         fseek(f, pos + (bp - hdrbuf), 0);
  40.         return bp;
  41.     }
  42.  
  43.     if (*bp == SP) {    /* for comp.ai.neural-nets digests */
  44.         bp++;        /* which have <NL><space><NL> after header */
  45.         continue;
  46.     }
  47.  
  48.     if (date_only && *bp != 'D')
  49.         fptr = NULL;
  50.     else
  51.         if (fptr = (*hdr_field)(bp, all)) {
  52.         while (*bp && *bp != ':' && isascii(*bp) && !isspace(*bp))
  53.             bp++;
  54.         bp++;
  55.         while (*bp && isascii(*bp) && isspace(*bp) && *bp != NL) bp++;
  56.         *fptr = bp;
  57.         }
  58.  
  59.     while (*bp && *bp != NL) bp++;
  60.  
  61.     /* Assume that continued lines are never empty! */
  62.     if (fptr && bp == *fptr) *fptr = NULL;
  63.  
  64.     while (*bp) {        /* look for continued lines */
  65.         cp = bp + 1;
  66.         while (*cp && isascii(*cp) && isspace(*cp) && *cp != NL) cp++;
  67.  
  68.         if (cp == bp + 1) {
  69.         /* next line is empty or not indented */
  70.         *bp++ = NUL;
  71.         break;
  72.         }
  73.  
  74.         if (*cp == NUL || *cp == NL) {
  75.         /* next line is not empty, but blank line */
  76.         *bp = NUL;
  77.         bp = cp;    /* assume end of header */
  78.         break;
  79.         }
  80.  
  81.         *bp = SP;        /* substitute NL with SPACE */
  82.         bp = cp;
  83.         while (*bp && *bp != NL) bp++;
  84.     }
  85.     }
  86.  
  87.     return bp;
  88. }
  89.  
  90. static char **art_hdr_field(lp, all)
  91. register char *lp;
  92. int all;
  93. {
  94.  
  95. #define check(name, lgt, field) \
  96.     if (isascii(lp[lgt]) && isspace(lp[lgt]) && strncmp(name, lp, lgt) == 0)\
  97.     return &news.field
  98.  
  99.     switch (*lp++) {
  100.  
  101.      case 'A':
  102.      case 'a':
  103.     if (!all) break;
  104.     check("pproved:",     8, ng_appr);
  105.     break;
  106.  
  107.      case 'B':
  108.      case 'b':
  109.     check("ack-References:", 15, ng_bref);
  110.     break;
  111.  
  112.      case 'D':
  113.      case 'd':
  114.     check("ate:",          4, ng_date);
  115.     if (!all) break;
  116.     check("ate-Received:",    13, ng_rdate);
  117.     check("istribution:",     12, ng_dist);
  118.     break;
  119.  
  120.      case 'F':
  121.      case 'f':
  122.     check("rom:",         4, ng_from);
  123.     if (!all) break;
  124.     check("ollowup-To:",    11, ng_follow);
  125.     check("ollowup-to:",    11, ng_follow);
  126.     break;
  127.  
  128.      case 'K':
  129.      case 'k':
  130.     if (!all) break;
  131.     check("eywords:",     8, ng_keyw);
  132.     break;
  133.  
  134.      case 'L':
  135.      case 'l':
  136.     check("ines:",          5, ng_xlines);
  137.     break;
  138.  
  139.      case 'M':
  140.      case 'm':
  141.     if (!all) break;
  142.     if (strncmp(lp, "essage-", 7)) break;
  143.     lp += 7;
  144.     check("ID:",    3, ng_ident);
  145.     check("Id:",    3, ng_ident);
  146.     check("id:",    3, ng_ident);
  147.     break;
  148.  
  149.      case 'N':
  150.      case 'n':
  151.     check("ewsgroups:",    10, ng_groups);
  152.     break;
  153.  
  154.      case 'O':
  155.      case 'o':
  156.     if (!all) break;
  157.     check("rganization:",    12, ng_org);
  158.     check("rganisation:",    12, ng_org);
  159.     break;
  160.  
  161.      case 'P':
  162.      case 'p':
  163.     if (!all) break;
  164.     check("ath:",         4, ng_path);
  165.     break;
  166.  
  167.      case 'R':
  168.      case 'r':
  169.     check("eferences:",    10, ng_ref);
  170.     check("eply-To:",     8, ng_reply);
  171.     check("eply-to:",     8, ng_reply);
  172.     break;
  173.  
  174.      case 'S':
  175.      case 's':
  176.     check("ubject:",     7, ng_subj);
  177.     if (news.ng_from == NULL)
  178.         check("ender:",     6, ng_from);
  179.     if (!all) break;
  180.     check("ummary:",     7, ng_summ);
  181.     break;
  182.  
  183.      case 'T':
  184.      case 't':
  185.     check("itle:",          5, ng_subj);
  186.     break;
  187.     }
  188.  
  189.     return NULL;
  190.  
  191. #undef check
  192. }
  193.  
  194. is_header_line(line)
  195. char *line;
  196. {
  197.     return art_hdr_field(line, 0) != (char **)NULL;
  198. }
  199.  
  200.  
  201. FILE *open_news_article(art, modes, buffer1, buffer2)
  202. article_header         *art;
  203. int             modes;
  204. news_header_buffer    buffer1, buffer2;
  205. {
  206.     char *body;
  207.     char *digest_buffer;
  208.     char *parse_header();
  209.     struct stat statb;
  210.     int retry;
  211.     FILE *f;
  212. #ifdef NNTP
  213.     int lazy;
  214.     FILE *nntp_get_article();
  215. #endif /* NNTP */
  216.  
  217.     if (art->flag & A_FOLDER) {
  218.     f = open_file(group_path_name, OPEN_READ);
  219.     if (f == NULL) return NULL;
  220.     fseek(f, art->hpos, 0);
  221. #ifdef NNTP
  222.     } else
  223.     if (use_nntp) {
  224.     lazy = (current_group->master_flag & M_ALWAYS_DIGEST) == 0
  225.         && (modes & LAZY_BODY) ? 1 : 0;
  226.     f = nntp_get_article(art->a_number, lazy);
  227.     if (f == NULL) return NULL;
  228. #endif /* NNTP */
  229.     } else {
  230.     sprintf(group_file_name, "%d", art->a_number);
  231.  
  232.     retry = retry_on_error;
  233.     while ((f = open_file(group_path_name, OPEN_READ)) == NULL)
  234.         if (--retry < 0) return NULL;
  235.  
  236.     /* necessary because empty files wreak havoc */
  237.     if (fstat(fileno(f), &statb) < 0 ||
  238.         statb.st_size < art->lpos || statb.st_size <= (off_t)0) {
  239.         fclose(f);
  240.         return who_am_i == I_AM_MASTER ? (FILE *)1 : NULL;
  241.     }
  242.     }
  243.  
  244.     digest_buffer = buffer1;
  245.  
  246.     if (modes & FILL_NEWS_HEADER) {
  247.  
  248.     news.ng_from     = NULL;
  249.     news.ng_reply     = NULL;
  250.     news.ng_name     = NULL;
  251.     news.ng_subj     = NULL;
  252.     news.ng_groups     = NULL;
  253.     news.ng_ref     = NULL;
  254.     news.ng_bref     = NULL;
  255.  
  256.     news.ng_xlines     = NULL;
  257.  
  258.     if (modes & GET_ALL_FIELDS) {
  259.         news.ng_path     = NULL;
  260.         news.ng_reply     = NULL;
  261.         news.ng_ident     = NULL;
  262.         news.ng_follow     = NULL;
  263.         news.ng_keyw     = NULL;
  264.         news.ng_dist     = NULL;
  265.         news.ng_org     = NULL;
  266.         news.ng_appr     = NULL;
  267.         news.ng_summ    = NULL;
  268.         news.ng_date    = NULL;
  269.         news.ng_rdate    = NULL;
  270.     }
  271.  
  272.     if (modes & GET_DATE_ONLY)
  273.         news.ng_date    = NULL;
  274.  
  275.     body = parse_header(f, art_hdr_field, modes, buffer1);
  276.  
  277.     news.ng_lines = news.ng_xlines ? atoi(news.ng_xlines) : -1;
  278.  
  279.     if (modes & FILL_OFFSETS) {
  280.         art->fpos = news.ng_fpos = ftell(f);
  281.  
  282.         fseek(f, (off_t)0, 2);
  283.         news.ng_lpos = ftell(f);
  284.     }
  285. #ifdef NNTP
  286.     else if (use_nntp && (art->flag & A_DIGEST) == 0) {
  287.         fseek(f, (off_t)0, 2);
  288.         art->lpos = ftell(f);
  289.     }
  290. #endif
  291.  
  292.     news.ng_flag = 0;
  293.  
  294.     if (news.ng_appr) news.ng_flag |= N_MODERATED;
  295.  
  296.     if (modes & DIGEST_CHECK && is_digest()) news.ng_flag |= N_DIGEST;
  297.  
  298. #ifdef NNTP
  299.     if (use_nntp && lazy && news.ng_flag & N_DIGEST) {
  300.         fclose(f);
  301.         f = nntp_get_article(art->a_number, 2);
  302.         if (f == NULL) return NULL;
  303.     }
  304. #endif
  305.     digest_buffer = buffer2;
  306.     }
  307. #ifdef NNTP
  308.     else if (use_nntp && (art->flag & A_DIGEST) == 0) {
  309.     fseek(f, (off_t)0, 2);
  310.     art->lpos = ftell(f);
  311.     }
  312. #endif
  313.  
  314.     if (modes & FILL_DIGEST_HEADER) {
  315.     fseek(f, art->hpos, 0);
  316.     parse_digest_header(f, modes & GET_ALL_FIELDS, digest_buffer);
  317.     }
  318.  
  319.     fseek(f, (modes & SKIP_HEADER) ? art->fpos : art->hpos, 0);
  320.  
  321.     return f;
  322. }
  323.