home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / uucp / amigauucpsrc / dnews / refs.c < prev    next >
C/C++ Source or Header  |  1994-06-29  |  7KB  |  420 lines

  1.  
  2. /*
  3.  *  REFS.C
  4.  *
  5.  *  Handles the References: line
  6.  */
  7.  
  8. #include "defs.h"
  9.  
  10. /*
  11.  *  hash table for killed references
  12.  */
  13.  
  14. #define HSIZE    256
  15. #define HMASK    (HSIZE-1)
  16.  
  17. Prototype void AddKillFile(char *, int, int);
  18. Prototype void RemKillFile(char *);
  19. Prototype void LoadKillFile(char *);
  20. Prototype void SaveKillFile(char *);
  21.  
  22. Prototype char *FromLineOf(NGroup *, int);
  23. Prototype char *ReferenceLineOf(NGroup *, int);
  24. Prototype char *NewsMessageIdOf(NGroup *, int);
  25. Prototype char *SubjectOf(NGroup *, int, int);
  26. Prototype char *StripRE(char *);
  27. Prototype int FindArticleReferencing(NGroup *, char *, int);
  28. Prototype int ArticleRefKilled(NGroup *, int);
  29. Prototype char *NextRef(char **);
  30.  
  31. /*
  32.  *  Hash table for references
  33.  */
  34.  
  35. typedef struct Hash {
  36.     struct  Hash *Next;
  37.     time_t  TTerm;    /*  terminate entry after time tterm    */
  38.     char    Id[4];
  39. } Hash;
  40.  
  41. Local Hash **FindRefHash(char *);
  42. Local void AddRefHash(Hash **, char *, time_t);
  43. Local int hash(char *);
  44.  
  45. static Hash *Table[HSIZE];
  46.  
  47. /*
  48.  *  Add References: field to kill file.  Kill file entry will exist for 30
  49.  *  days.
  50.  */
  51.  
  52. void
  53. AddKillFile(refs, days, noBrkUp)
  54. char *refs;
  55. int days;
  56. int noBrkUp;
  57. {
  58.     char *id;
  59.     Hash **ph;
  60.     Hash *h;
  61.  
  62.     if (days)
  63.     days = time(0) + days * 1440 * 60;  /*  seconds  */
  64.  
  65.     if (noBrkUp) {
  66.     ph = FindRefHash(refs);
  67.     if (h = *ph) {
  68.         h->TTerm = days;
  69.     } else {
  70.         AddRefHash(ph, refs, days);
  71.     }
  72.     } else {
  73.     while (id = NextRef(&refs)) {
  74.         ph = FindRefHash(id);
  75.         if (h = *ph) {
  76.         h->TTerm = days;    /*  now seconds */
  77.         } else {
  78.         AddRefHash(ph, id, days);
  79.         }
  80.     }
  81.     }
  82. }
  83.  
  84. void
  85. RemKillFile(refs)
  86. char *refs;
  87. {
  88.     char *id;
  89.     Hash **ph;
  90.     Hash *h;
  91.  
  92.     while (id = NextRef(&refs)) {
  93.     ph = FindRefHash(id);
  94.     if (h = *ph) {
  95.         *ph = h->Next;
  96.         free(h);
  97.     }
  98.     }
  99. }
  100.  
  101. void
  102. LoadKillFile(user)
  103. char *user;
  104. {
  105.     char id[128];
  106.     char buf[64];
  107.     long tterm;
  108.     FILE *fi;
  109.  
  110.     sprintf(buf, "%s.dnewskl", user);
  111.     if (fi = openlib(buf)) {
  112.     while (fgets(TmpBuf, sizeof(TmpBuf), fi)) {
  113.         Hash **ph;
  114.         char *ptr;
  115.         short len;
  116.  
  117.         tterm = strtol(TmpBuf, &ptr, 0);
  118.         while (*ptr == ' ' || *ptr == '\t')
  119.         ++ptr;
  120.         strncpy(id, ptr, sizeof(id) - 1);
  121.         id[sizeof(id)-1] = 0;
  122.         len = strlen(id);
  123.         if (len && id[len-1] == '\n')
  124.         id[--len] = 0;
  125.  
  126.         if (tterm) {
  127.         if (*(ph = FindRefHash(id)) == NULL)
  128.             AddRefHash(ph, id, tterm);
  129.         }
  130.     }
  131.     fclose(fi);
  132.     }
  133. }
  134.  
  135. void
  136. SaveKillFile(user)
  137. char *user;
  138. {
  139.     char buf[64];
  140.     FILE *fo;
  141.     time_t curtime = time(NULL);
  142.  
  143.     sprintf(buf, "%s.dnewskl", user);
  144.     if (fo = openlib_write(buf)) {
  145.     Hash **ph;
  146.     short i;
  147.  
  148.     for (ph = Table, i = 0; i < HSIZE; ++i, ++ph) {
  149.         Hash *h;
  150.         for (h = *ph; h; h = h->Next) {
  151.         if (h->TTerm == -1 || (h->TTerm && h->TTerm > curtime))
  152.             fprintf(fo, "%d %s\n", h->TTerm, h->Id);
  153.         }
  154.     }
  155.     fclose(fo);
  156.     }
  157. }
  158.  
  159. char *
  160. FromLineOf(grp, artno)
  161. NGroup *grp;
  162. int artno;
  163. {
  164.     FILE *fi;
  165.     FNode **pfn = FindFNCache(grp->FromBase, artno);
  166.  
  167.     {
  168.     FNode *fn;
  169.     if (fn = *pfn)
  170.         return(fn->Id);
  171.     }
  172.     {
  173.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  174.         char *field = FindField(fi, "From:");
  175.         fclose(fi);
  176.         if (field) {
  177.         AddFNCache(pfn, artno, field);
  178.         return(field);
  179.         }
  180.     }
  181.     }
  182.     AddFNCache(pfn, artno, NULL);
  183.     return(NULL);
  184. }
  185.  
  186.  
  187. char *
  188. ReferenceLineOf(grp, artno)
  189. NGroup *grp;
  190. int artno;
  191. {
  192.     FILE *fi;
  193.     FNode **pfn = FindFNCache(grp->RefBase, artno);
  194.  
  195.     {
  196.     FNode *fn;
  197.     if (fn = *pfn)
  198.         return(fn->Id);
  199.     }
  200.     {
  201.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  202.         char *field = FindField(fi, "References:");
  203.         fclose(fi);
  204.         if (field) {
  205.         AddFNCache(pfn, artno, field);
  206.         return(field);
  207.         }
  208.     }
  209.     }
  210.     AddFNCache(pfn, artno, NULL);
  211.     return(NULL);
  212. }
  213.  
  214. char *
  215. SubjectOf(grp, artno, stripre)
  216. NGroup *grp;
  217. int artno;
  218. {
  219.     FILE *fi;
  220.     FNode **pfn = FindFNCache(grp->SubBase, artno);
  221.  
  222.     {
  223.     FNode *fn;
  224.     if (fn = *pfn) {
  225.         if (stripre && fn->Id)
  226.         return(StripRE(fn->Id));
  227.         return(fn->Id);
  228.     }
  229.     }
  230.     {
  231.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  232.         char *field = FindField(fi, "Subject:");
  233.         fclose(fi);
  234.         if (field) {
  235.         AddFNCache(pfn, artno, field);
  236.         if (stripre)
  237.             field = StripRE(field);
  238.         return(field);
  239.         }
  240.     }
  241.     }
  242.     AddFNCache(pfn, artno, NULL);
  243.     return(NULL);
  244. }
  245.  
  246.  
  247. char *
  248. NewsMessageIdOf(grp, artno)
  249. NGroup *grp;
  250. int artno;
  251. {
  252.     FILE *fi;
  253.     FNode **pfn = FindFNCache(grp->IdBase, artno);
  254.  
  255.     {
  256.     FNode *fn;
  257.     if (fn = *pfn)
  258.         return(fn->Id);
  259.     }
  260.     {
  261.     if (fi = fopen(FileForArticle(grp, artno), "r")) {
  262.         char *field = FindField(fi, "Message-ID:");
  263.         fclose(fi);
  264.         if (field) {
  265.         AddFNCache(pfn, artno, field);
  266.         return(field);
  267.         }
  268.     }
  269.     }
  270.     AddFNCache(pfn, artno, NULL);
  271.     return(NULL);
  272. }
  273.  
  274.  
  275. /*
  276.  *  Given the msg-id of an article (msgid), find it amoung the References:
  277.  *  line of later articles.
  278.  */
  279.  
  280. int
  281. FindArticleReferencing(grp, msgid, artno)
  282. NGroup *grp;
  283. char *msgid;
  284. int artno;
  285. {
  286.     char *field = ReferenceLineOf(grp, artno);
  287.     char *id;
  288.  
  289.     if (field == NULL)
  290.     return(0);
  291.     while (id = NextRef(&field)) {
  292.     /*printf("COMPARE: %s vs %s artno %d\n", msgid, id, artno);*/
  293.     if (strcmp(msgid, id) == 0)
  294.         break;
  295.     }
  296.     if (id)
  297.     return(1);
  298.     return(0);
  299. }
  300.  
  301. /*
  302.  *  Is the specified article (grp, artno) in the kill list ?  That is, if
  303.  *  any of the fields in the article's References: line are on the kill list
  304.  *  we return TRUE.
  305.  */
  306.  
  307. int
  308. ArticleRefKilled(grp, artno)
  309. NGroup *grp;
  310. int artno;
  311. {
  312.     char *refs;
  313.     char *id;
  314.     Hash **ph;
  315.  
  316.     if (refs = ReferenceLineOf(grp, artno)) {
  317.     while (id = NextRef(&refs)) {
  318.         if (*(ph = FindRefHash(id))) {
  319.         return(1);
  320.         }
  321.     }
  322.     }
  323.     if (refs = SubjectOf(grp, artno, 1)) {
  324.     if (*(ph = FindRefHash(refs))) {
  325.         return(1);
  326.     }
  327.     }
  328.     if (refs = FromLineOf(grp, artno)) {
  329.     if (*(ph = FindRefHash(refs))) {
  330.         return(1);
  331.     }
  332.     }
  333.     return(0);
  334. }
  335.  
  336.  
  337. char *
  338. NextRef(ppt)
  339. char **ppt;
  340. {
  341.     char *ptr = *ppt;
  342.     char *base;
  343.     static char buf[256];
  344.  
  345.     while (*ptr == ' ' || *ptr == 9 || *ptr == '\n')
  346.     ++ptr;
  347.     base = buf;
  348.     while (*ptr && *ptr != ' ' && *ptr != 9 && *ptr != '\n')
  349.     *base++ = *ptr++;
  350.     *base = 0;
  351.     *ppt = ptr;
  352.     if (base == buf)
  353.     return(NULL);
  354.     return(buf);
  355. }
  356.  
  357. /*
  358.  *                HASH TABLE ROUTINES
  359.  */
  360.  
  361. Hash **
  362. FindRefHash(id)
  363. char *id;
  364. {
  365.     Hash **ph = Table + hash(id);
  366.     Hash *h;
  367.  
  368.     while (h = *ph) {
  369.     if (strcmp(id, h->Id) == 0)
  370.         break;
  371.     ph = &h->Next;
  372.     }
  373.     return(ph);
  374. }
  375.  
  376. Local
  377. void
  378. AddRefHash(ph, id, ti)
  379. Hash **ph;
  380. char *id;
  381. time_t ti;
  382. {
  383.     Hash *h = malloc(sizeof(Hash) - sizeof(h->Id) + strlen(id) + 1);
  384.  
  385.     strcpy(h->Id, id);
  386.     h->TTerm = ti;
  387.     h->Next = *ph;
  388.     *ph = h;
  389. }
  390.  
  391. int
  392. hash(ptr)
  393. char *ptr;
  394. {
  395.     long hv = 0x1234ADC3;
  396.  
  397.     while (*ptr) {
  398.     hv = (hv >> 23) ^ (hv << 5) ^ *ptr;
  399.     ++ptr;
  400.     }
  401.     return(hv & HMASK);
  402. }
  403.  
  404. char *
  405. StripRE(str)
  406. char *str;
  407. {
  408.     for (;;) {
  409.     while (*str == ' ' || *str == '\t')
  410.         ++str;
  411.     if (strnicmp(str, "re:", 3) == 0) {
  412.         str += 3;
  413.         continue;
  414.     }
  415.     break;
  416.     }
  417.     return(str);
  418. }
  419.  
  420.