home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / trn-3.3 / part04 / head.c next >
C/C++ Source or Header  |  1993-11-27  |  11KB  |  445 lines

  1. /* $Id: head.c,v 3.0 1992/02/23 21:25:39 davison Trn $
  2.  */
  3. /* This software is Copyright 1991 by Stan Barber. 
  4.  *
  5.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  6.  * use this software as long as: there is no monetary profit gained
  7.  * specifically from the use or reproduction of this software, it is not
  8.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  9.  * included prominently in any copy made. 
  10.  *
  11.  * The authors make no claims as to the fitness or correctness of this software
  12.  * for any use whatsoever, and it is provided as is. Any use of this software
  13.  * is at the user's own risk. 
  14.  */
  15.  
  16. #include "EXTERN.h"
  17. #include "common.h"
  18. #include "artio.h"
  19. #include "cache.h"
  20. #include "ng.h"
  21. #include "ngdata.h"
  22. #include "util.h"
  23. #include "hash.h"
  24. #include "rthread.h"
  25. #include "rt-process.h"
  26. #include "rt-util.h"
  27. #include "final.h"
  28. #include "nntp.h"
  29. #include "INTERN.h"
  30. #include "head.h"
  31.  
  32. bool first_one;        /* is this the 1st occurance of this header line? */
  33.  
  34. static char htypeix[26] =
  35.     {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  36.  
  37. void
  38. head_init()
  39. {
  40.     register int i;
  41.  
  42.     for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
  43.     htypeix[*htype[i].ht_name - 'a'] = i;
  44.  
  45.     headbuf_size = LBUFLEN * 8;
  46.     headbuf = safemalloc(headbuf_size);
  47. }
  48.  
  49. #ifdef DEBUG
  50. void
  51. dumpheader(where)
  52. char *where;
  53. {
  54.     register int i;
  55.  
  56.     printf("header: %d %s", parsed_art, where);
  57.  
  58.     for (i=0; i<HEAD_LAST; i++) {
  59.     printf("%15s %4d %4d %03o\n",htype[i].ht_name,
  60.         htype[i].ht_minpos,
  61.         htype[i].ht_maxpos,
  62.         htype[i].ht_flags) FLUSH;
  63.     }
  64. }
  65. #endif
  66.  
  67. int
  68. set_line_type(bufptr,colon)
  69. char *bufptr;
  70. register char *colon;
  71. {
  72.     char lc[LONGKEY+3];
  73.     register char *t, *f;
  74.     register int i, len;
  75.  
  76.     if (colon-bufptr > LONGKEY+2)
  77.     return SOME_LINE;
  78.  
  79.     for (t=lc,f=bufptr; f<colon; f++, t++) {
  80.     if (isspace(*f))
  81.     /* guard against space before : */
  82.         break;
  83.     *t = isupper(*f) ? tolower(*f) : *f;
  84.     }
  85.     *t = '\0';
  86.     f = lc;                /* get lc into register */
  87.     len = t - f;
  88.  
  89.     /* now scan the headtype table, backwards so we don't have to supply an
  90.      * extra terminating value, using first letter as index, and length as
  91.      * optimization to avoid calling subroutine strEQ unnecessarily.  Hauls.
  92.      */
  93.     if (islower(*f)) {
  94.     for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
  95.         if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
  96.         return i;
  97.         }
  98.     }
  99.     }
  100.     return SOME_LINE;
  101. }
  102.  
  103. void
  104. start_header(artnum)
  105. ART_NUM artnum;
  106. {
  107.     register int i;
  108.  
  109. #ifdef DEBUG
  110.     if (debug & DEB_HEADER)
  111.     dumpheader("start_header\n");
  112. #endif
  113.     for (i=0; i<HEAD_LAST; i++) {
  114.     htype[i].ht_minpos = -1;
  115.     htype[i].ht_maxpos = 0;
  116.     }
  117.     in_header = SOME_LINE;
  118.     first_one = FALSE;
  119.     parsed_art = artnum;
  120. }
  121.  
  122. void
  123. end_header_line()
  124. {
  125.     if (first_one) {        /* did we just pass 1st occurance? */
  126.     first_one = FALSE;
  127.     /* remember where line left off */
  128.     htype[in_header].ht_maxpos = artpos;
  129.     if (htype[in_header].ht_flags & HT_CACHED) {
  130.         ARTICLE *ap = article_ptr(parsed_art);
  131.         if (!get_cached_line(ap, in_header, TRUE)) {
  132.         int start = htype[in_header].ht_minpos
  133.               + htype[in_header].ht_length + 1;
  134.         MEM_SIZE size;
  135.         char *s;
  136.         while (headbuf[start] == ' ' || headbuf[start] == '\t')
  137.             start++;
  138.         size = artpos - start + 1 - 1;    /* pre-strip newline */
  139.         if (in_header == SUBJ_LINE)
  140.             set_subj_line(ap,headbuf+start,size-1);
  141.         else {
  142.             s = safemalloc(size);
  143.             *s = '\0';
  144.             safecat(s,headbuf+start,size);
  145.             set_cached_line(ap,in_header,s);
  146.         }
  147.         }
  148.     }
  149.     }
  150. }
  151.  
  152. bool
  153. parseline(art_buf,newhide,oldhide)
  154. char *art_buf;
  155. int newhide, oldhide;
  156. {
  157.     if (*art_buf == ' ' || *art_buf == '\t') {
  158.                     /* header continuation line? */
  159.     return oldhide;
  160.     } else {                /* maybe another header line */
  161.     char *s;
  162.     end_header_line();
  163.     s = index(art_buf,':');
  164.     if (s == Nullch) {    /* is it the end of the header? */
  165. #ifdef USE_NNTP
  166.         /* Did NNTP ship us a mal-formed header line? */
  167.         if (*art_buf && *art_buf != '\n') {
  168.         in_header = SOME_LINE;
  169.         return newhide;
  170.         }
  171. #endif
  172.         in_header = PAST_HEADER;
  173.     } else {        /* it is a new header line */
  174.         in_header = set_line_type(art_buf,s);
  175.         first_one = (htype[in_header].ht_minpos < 0);
  176.         if (first_one) {
  177.         htype[in_header].ht_minpos = artpos;
  178.         if (in_header == DATE_LINE) {
  179.             register ARTICLE *ap = article_ptr(parsed_art);
  180.             if (!ap->date)
  181.             ap->date = parsedate(art_buf+6);
  182.         }
  183.         }
  184. #ifdef DEBUG
  185.         if (debug & DEB_HEADER)
  186.         dumpheader(art_buf);
  187. #endif
  188.         if (htype[in_header].ht_flags & HT_HIDE)
  189.         return newhide;
  190.     }
  191.     }
  192.     return FALSE;            /* don't hide this line */
  193. }
  194.  
  195. void
  196. end_header()
  197. {
  198.     register ARTICLE *ap = article_ptr(parsed_art);
  199.  
  200.     end_header_line();
  201.     in_header = PAST_HEADER;    /* just to be sure */
  202.  
  203.     if (!ap->subj) {
  204. #if 0
  205.     uncache_article(ap,FALSE);
  206.     return;
  207. #else
  208.     set_subj_line(ap,"Subject: <none>",15);
  209. #endif
  210.     }
  211.  
  212. #ifndef DBM_XREFS
  213.     if (htype[XREF_LINE].ht_minpos < 0)
  214.     article_ptr(parsed_art)->xrefs = nullstr;
  215. #endif
  216. #ifdef USE_NNTP
  217.     htype[PAST_HEADER].ht_minpos = artpos+1;  /* remember where body starts */
  218. #else
  219.     htype[PAST_HEADER].ht_minpos = ftell(artfp);
  220. #endif
  221.  
  222.     if (ThreadedGroup && !(ap->flags & AF_THREADED)) {
  223.     if (valid_article(ap)) {
  224.         ARTICLE *artp_hold = artp;
  225.         references = fetchlines(parsed_art, REFS_LINE);
  226.         thread_article(ap);
  227.         free(references);
  228.         artp = artp_hold;
  229.         check_poster(ap);
  230.     }
  231.     } else if (!(ap->flags & AF_CACHED)) {
  232.     cache_article(ap);
  233.     check_poster(ap);
  234.     }
  235. }
  236.  
  237. /* read the header into memory and parse it if we haven't already */
  238.  
  239. bool
  240. parseheader(artnum)
  241. ART_NUM artnum;
  242. {
  243.     register char *bp;
  244.     register int len;
  245.  
  246.     if (parsed_art == artnum)
  247.     return TRUE;
  248.     if (artnum > lastart)
  249.     return FALSE;
  250.     spin(20);
  251. #ifdef USE_NNTP
  252.     if (!nntp_header(artnum)) {
  253.     uncache_article(article_ptr(artnum),FALSE);
  254.     return FALSE;
  255.     }
  256. #else
  257.     if (!artopen(artnum))
  258.     return FALSE;
  259. #endif
  260.     start_header(artnum);
  261.     artpos = 0;
  262.     bp = headbuf;
  263.     while (in_header) {
  264.     if (headbuf_size < artpos + LBUFLEN) {
  265.         headbuf_size += LBUFLEN * 4;
  266.         headbuf = saferealloc(headbuf,headbuf_size);
  267.     }
  268. #ifdef USE_NNTP
  269.     nntp_gets(bp,LBUFLEN);
  270.     if (*bp == '.') {
  271.         if (!bp[1]) {
  272.         *bp++ = '\n';        /* tag the end with an empty line */
  273.         break;
  274.         }
  275.         strcpy(bp,bp+1);
  276.     }
  277.     len = strlen(bp);
  278.     bp[len++] = '\n';
  279.     bp[len] = '\0';
  280. #else
  281.     if (fgets(bp,LBUFLEN,artfp) == Nullch)
  282.         break;
  283.     len = strlen(bp);
  284. #endif
  285.     parseline(bp,FALSE,FALSE);
  286.     artpos += len;
  287.     bp += len;
  288.     }
  289.     *bp = '\0';   /* this probably isn't needed */
  290.     end_header();
  291.     return TRUE;
  292. }
  293.  
  294. /* get a header line from an article */
  295.  
  296. char *
  297. fetchlines(artnum,which_line)
  298. ART_NUM artnum;                /* article to get line from */
  299. int which_line;                /* type of line desired */
  300. {
  301.     char *s, *t;
  302.     register ART_POS firstpos;
  303.     register ART_POS lastpos;
  304.     int size;
  305.  
  306.     /* Only return a cached subject line if it isn't the current article */
  307.     if (which_line != SUBJ_LINE || parsed_art != artnum) {
  308.     s = fetchcache(artnum,which_line,FILL_CACHE);
  309.     if (s)
  310.         return savestr(s);
  311.     }
  312.     if ((firstpos = htype[which_line].ht_minpos) < 0)
  313.     return savestr(nullstr);
  314.  
  315.     firstpos += htype[which_line].ht_length + 1;
  316.     lastpos = htype[which_line].ht_maxpos;
  317.     size = lastpos - firstpos;
  318. #ifdef DEBUG
  319.     if (debug && (size < 1 || size > 1000)) {
  320.     printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
  321.     gets(cmd_buf);
  322.     }
  323. #endif
  324.     s = safemalloc((MEM_SIZE)size);
  325.     t = headbuf + firstpos;
  326.     while (*t == ' ' || *t == '\t') t++;
  327.     *s = '\0';
  328.     safecat(s,t,size);
  329.     return s;
  330. }
  331.  
  332. /* prefetch a header line from one or more articles */
  333.  
  334. char *
  335. prefetchlines(artnum,which_line,copy)
  336. ART_NUM artnum;                /* article to get line from */
  337. int which_line;                /* type of line desired */
  338. bool_int copy;                /* do you want it savestr()ed? */
  339. {
  340.     char *s, *t;
  341.     register ART_POS firstpos;
  342.     register ART_POS lastpos;
  343.     int size;
  344.  
  345. #ifdef USE_NNTP
  346.     if (parsed_art != artnum) {
  347.     ARTICLE *ap;
  348.     int size;
  349.     register ART_NUM num, priornum, lastnum;
  350.     bool cached;
  351.  
  352.     s = fetchcache(artnum,which_line,DONT_FILL_CACHE);
  353.     if (s) {
  354.         if (copy)
  355.         s = savestr(s);
  356.         return s;
  357.     }
  358.  
  359.     spin(20);
  360.     if (copy)
  361.         s = safemalloc((MEM_SIZE)(size = LBUFLEN));
  362.     else {
  363.         s = cmd_buf;
  364.         size = sizeof cmd_buf;
  365.     }
  366.     *s = '\0';
  367.     priornum = artnum-1;
  368.     if ((cached = (htype[which_line].ht_flags & HT_CACHED)) != 0) {
  369.         lastnum = artnum + PREFETCH_SIZE - 1;
  370.         if (lastnum > lastart)
  371.         lastnum = lastart;
  372.         sprintf(ser_line,"XHDR %s %ld-%ld",htype[which_line].ht_name,
  373.         artnum,lastnum);
  374.     } else {
  375.         lastnum = artnum;
  376.         sprintf(ser_line,"XHDR %s %ld",htype[which_line].ht_name,artnum);
  377.     }
  378.     nntp_command(ser_line);
  379.     if (nntp_check(TRUE) == NNTP_CLASS_OK) {
  380.         for (ap = find_article(artnum); ; ) {
  381.         nntp_gets(ser_line, sizeof ser_line);
  382. # ifdef DEBUG
  383.         if (debug & DEB_NNTP)
  384.             printf("<%s\n", ser_line) FLUSH;
  385. # endif
  386.         if (ser_line[0] == '.')
  387.             break;
  388.         if ((t = index(ser_line, '\r')) != Nullch)
  389.             *t = '\0';
  390.         if (!(t = index(ser_line, ' ')))
  391.             continue;
  392.         t++;
  393.         num = atol(ser_line);
  394.         if (num < artnum || num > lastnum)
  395.             continue;
  396.         while (++priornum < num)
  397.             uncache_article(ap++,FALSE);
  398.         if (which_line == SUBJ_LINE)
  399.             set_subj_line(ap++, t, strlen(t));
  400.         else if (cached)
  401.             set_cached_line(ap++, which_line, savestr(t));
  402.         if (num == artnum)
  403.             safecat(s,t,size);
  404.         }
  405.     } else {
  406.         fprintf(stderr,"\nUnexpected close of server socket.\n");
  407.         finalize(1);
  408.     }
  409.     while (priornum++ < lastnum)
  410.         uncache_article(ap++,FALSE);
  411.     if (copy)
  412.         s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
  413.     return s;
  414.     }
  415. #endif
  416.  
  417.     /* Only return a cached subject line if it isn't the current article */
  418.     s = Nullch;
  419.     if (which_line != SUBJ_LINE || parsed_art != artnum)
  420.     s = fetchcache(artnum,which_line,FILL_CACHE);
  421.     if ((firstpos = htype[which_line].ht_minpos) < 0)
  422.     s = nullstr;
  423.     if (s) {
  424.     if (copy)
  425.         s = savestr(s);
  426.     return s;
  427.     }
  428.  
  429.     firstpos += htype[which_line].ht_length + 1;
  430.     lastpos = htype[which_line].ht_maxpos;
  431.     size = lastpos - firstpos;
  432.     if (copy)
  433.     s = safemalloc((MEM_SIZE)size);
  434.     else {                /* hope this is okay--we're */
  435.     s = cmd_buf;            /* really scraping for space here */
  436.     if (size > sizeof cmd_buf)
  437.         size = sizeof cmd_buf;
  438.     }
  439.     t = headbuf + firstpos;
  440.     while (*t == ' ' || *t == '\t') t++;
  441.     *s = '\0';
  442.     safecat(s,t,size);
  443.     return s;
  444. }
  445.