home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 April / PCO_04_97.ISO / filesbbs / os2 / vsoup127.arj / VSOUP127.ZIP / kill.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-20  |  7.2 KB  |  341 lines

  1. //  $Id: kill.cc 1.18 1997/01/20 16:05:53 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //  Kill file processing
  12. //
  13.  
  14.  
  15. #include <ctype.h>
  16. #include <fcntl.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19. #include <regexp.h>
  20. #include <unistd.h>
  21. #include <sys/nls.h>
  22.  
  23. #include "kill.hh"
  24. #include "mts.hh"
  25.  
  26.  
  27.  
  28. TKillFile::TKillFile( void )
  29. {
  30.     groupKillList = actGroupList = NULL;
  31.     actGroupName = xstrdup("");
  32. }   // TKillFile::TKillFile
  33.  
  34.  
  35.  
  36. void TKillFile::killGroup( Group *gp )
  37. {
  38.     Exp *ep1, *ep2;
  39.     
  40.     if (gp == NULL)
  41.     return;
  42.  
  43.     ep1 = gp->expList;
  44.     while (ep1 != NULL) {
  45.     if (ep1->re != NULL) {
  46.         delete ep1->re;
  47.     }
  48.     ep2 = ep1->next;
  49.     delete ep1;
  50.     ep1 = ep2;
  51.     }
  52.     delete gp->grpPat;
  53.     delete gp;
  54. }   // TKillFile::killGroup
  55.  
  56.  
  57.  
  58. TKillFile::~TKillFile()
  59. {
  60.     Group *gp1, *gp2;
  61.  
  62.     gp1 = groupKillList;
  63.     while (gp1 != NULL) {
  64.     gp2 = gp1->next;
  65.     killGroup( gp1 );
  66.     gp1 = gp2;
  67.     }
  68.  
  69.     gp1 = actGroupList;
  70.     while (gp1 != NULL) {
  71.     gp2 = gp1->next;
  72.     delete gp1;
  73.     gp1 = gp2;
  74.     }
  75.     delete actGroupName;
  76. }   // TKillFile::~TKillFile
  77.  
  78.  
  79.  
  80. TKillFile::Exp *TKillFile::genRegExp(const char *searchIn, const char *searchFor)
  81. {
  82.     char exp[BUFSIZ];
  83.     Exp *result;
  84.  
  85.     if (searchFor[0] == '\0')
  86.     return NULL;
  87.  
  88.     if (stricmp(searchIn, "header") == 0)
  89.     strcpy( exp,searchFor );
  90.     else
  91.     sprintfT( exp,"^%s:.*%s", searchIn,searchFor );
  92.  
  93.     result = new Exp;
  94.     result->next = NULL;
  95.     _nls_strlwr( (unsigned char *)exp );
  96.     result->re = regcompT( exp );
  97.     return result;
  98. }   // TKillFile::genRegExp
  99.  
  100.  
  101.  
  102. void TKillFile::stripBlanks( char *line )
  103. {
  104.     char *p1, *p2;
  105.     int  len;
  106.  
  107.     p1 = line;
  108.     while (*p1 == ' '  ||  *p1 == '\t')
  109.     ++p1;
  110.     p2 = line + strlen(line) - 1;
  111.     while (p2 >= p1  &&  (*p2 == ' '  ||  *p2 == '\t'))
  112.     --p2;
  113.     len = p2-p1+1;
  114.     if (len > 0) {
  115.     memmove( line,p1,len );
  116.     line[len] = '\0';
  117.     }
  118.     else
  119.     line[0] = '\0';
  120. }   // TKillFile::stripBlanks
  121.  
  122.  
  123.  
  124. int TKillFile::readLine( char *line, int n, TFile &inf, int &lineNum )
  125. //
  126. //  fetch the next line from file
  127. //  blanks are stripped
  128. //  blank lines & lines with '#' in the beginning are skipped
  129. //  on EOF NULL is returned
  130. //    
  131. {
  132.     for (;;) {
  133.     if (inf.fgets(line,n,1) == NULL)
  134.         return 0;
  135.     ++lineNum;
  136.     stripBlanks( line );
  137.     if (line[0] != '\0'  &&  line[0] != '#')
  138.         break;
  139.     }
  140.     return 1;
  141. }   // TKillFile::readLine
  142.  
  143.  
  144.  
  145. int TKillFile::readFile( const char *killFile )
  146. //
  147. //  Read kill file and compile regular expressions.
  148. //  Return:  -1 -> file not found, 0 -> syntax error, 1 -> ok
  149. //  Nicht so hanz das optimale:  besser wäre es eine Zustandsmaschine
  150. //  zusammenzubasteln...
  151. //
  152. {
  153.     char buf[1000], name[1000], tmp[1000];
  154.     char searchIn[1000], searchFor[1000];
  155.     TFile inf;
  156.     Group *pGroup, *pLastGroup;
  157.     Exp *pExp, *pLastExp;
  158.     char ok;
  159.     int lineNum;
  160.  
  161.     groupKillList = NULL;
  162.  
  163.     if ( !inf.open(killFile,TFile::mread,TFile::otext))
  164.     return -1;
  165.  
  166.     sema.Request();
  167.  
  168.     pLastGroup = NULL;
  169.     ok = 1;
  170.  
  171.     //
  172.     //  read newsgroup name
  173.     //
  174.     lineNum = 0;
  175.     while (ok  &&  readLine(buf,sizeof(buf),inf,lineNum)) {
  176. #ifdef DEBUG_ALL
  177.     printfT( "line: '%s'\n",buf );
  178. #endif
  179.     if (sscanfT(buf,"%s%s",name,tmp) == 1)
  180.         readLine(tmp,sizeof(tmp),inf,lineNum);
  181.  
  182.     if (tmp[0] != '{' || tmp[1] != '\0') {
  183.         ok = 0;
  184.         break;
  185.     }
  186.  
  187.     if (stricmp(name, "all") == 0)
  188.         strcpy( name,".*" );               // use 'special' pattern which matches all group names
  189.     else
  190.         _nls_strlwr( (unsigned char *)name );
  191.     pGroup = new Group;
  192.     pGroup->grpPat = regcompT( name );
  193.     pGroup->expList = NULL;
  194.     pGroup->next = NULL;
  195.  
  196.     if (pLastGroup == NULL)
  197.         groupKillList = pGroup;
  198.     else
  199.         pLastGroup->next = pGroup;
  200.     pLastGroup = pGroup;
  201.  
  202.     //
  203.     //  Read kill expressions until closing brace.
  204.     //
  205.     pLastExp = NULL;
  206.     while (readLine(buf,sizeof(buf),inf,lineNum)) {
  207.         *searchIn = *searchFor = '\0';
  208.         sscanfT( buf,"%s%[^\n]",searchIn,searchFor );
  209.         stripBlanks( searchFor );
  210.  
  211.         if (searchIn[0] == '}'  &&  searchIn[1] == '\0') {
  212.         ok = (searchFor[0] == '\0');
  213.         break;
  214.         }
  215.         if (searchFor[0] == '\0') {
  216.         ok = 0;
  217.         break;
  218.         }
  219. #ifdef DEBUG_ALL
  220.         printfT( "search: '%s', '%s'\n",searchIn,searchFor );
  221. #endif
  222.         if ((pExp = genRegExp(searchIn,searchFor)) == NULL) {
  223.         ok = 0;
  224.         break;
  225.         }
  226.  
  227.         //
  228.         //  append entry to list
  229.         //
  230.         if (pLastExp == NULL)
  231.         pGroup->expList = pExp;
  232.         else
  233.         pLastExp->next = pExp;
  234.         pLastExp = pExp;
  235.     }
  236.     }
  237.     sema.Release();
  238.  
  239.     inf.close();
  240.  
  241.     if ( !ok)
  242.     hprintfT( STDERR_FILENO, "error in kill file %s,\n\tsection %s, line %d\n",
  243.           killFile,name,lineNum);
  244.     return ok;
  245. }   // TKillFile::readFile
  246.  
  247.  
  248.  
  249. TKillFile::Group *TKillFile::buildActGroupList( const char *groupName )
  250. //
  251. //  return group kill for *groupName
  252. //
  253. {
  254.     Group *p;
  255.     Group **pp;
  256.     char *name;
  257.  
  258. #ifdef TRACE_ALL
  259.     printfT( "TKillFile::buildActGroupList(%s)\n",groupName );
  260. #endif
  261.  
  262.     name = (char *)xstrdup( groupName );
  263.     _nls_strlwr( (unsigned char *)name );
  264.  
  265.     if (stricmp(name,actGroupName) != 0) {
  266.     pp = &actGroupList;
  267.     for (p = groupKillList; p != NULL; p = p->next) {
  268.         //
  269.         //  is groupname matched by a killgroup regexp?
  270.         //
  271.         if (regexecT(p->grpPat,name)) {
  272.         //
  273.         //  does the killgroup regexp match the complete groupname?
  274.         //
  275.         if (name              == p->grpPat->startp[0]  &&
  276.             name+strlen(name) == p->grpPat->endp[0]) {
  277. #ifdef DEBUG_ALL
  278.             printfT( "regexec: %p,%ld %p %p\n", name,strlen(name), p->grpPat->startp[0], p->grpPat->endp[0] );
  279. #endif
  280.             if (*pp == NULL) {
  281.             *pp = new Group;
  282.             (*pp)->next = NULL;
  283.             }
  284.             (*pp)->expList = p->expList;
  285.             pp = &((*pp)->next);
  286.         }
  287.         }
  288.     }
  289.     if (*pp != NULL)
  290.         (*pp)->expList = NULL;
  291.     xstrdup( &actGroupName, name );
  292.     }
  293.  
  294.     delete name;
  295.     return actGroupList;
  296. }   // TKillFile::buildActGroupList
  297.  
  298.  
  299.  
  300. int TKillFile::matchLine( const char *groupName, const char *line )
  301. //
  302. //  Check if line matches kill criteria (line must be already in lower case!)
  303. //  Return TRUE if article should be killed.
  304. //
  305. {
  306.     int   res = 0;
  307.     Group *pGroup;
  308.     Exp   *pExp;
  309.     
  310.     sema.Request();
  311.  
  312.     buildActGroupList( groupName );
  313.     for (pGroup = actGroupList;
  314.      pGroup != NULL  &&  pGroup->expList != NULL;
  315.      pGroup = pGroup->next) {
  316.     for (pExp = pGroup->expList; pExp != NULL; pExp = pExp->next) {
  317.         if (regexecT(pExp->re, line)) {
  318.         res = 1;
  319.         break;
  320.         }
  321.     }
  322.     if (res)
  323.         break;
  324.     }
  325.  
  326.     sema.Release();
  327.     return res;
  328. }   // TKillFile::matchLine
  329.  
  330.  
  331.  
  332. int TKillFile::doKillQ( const char *groupName )
  333. {
  334.     Group *p;
  335.     
  336.     sema.Request();
  337.     p = buildActGroupList(groupName);
  338.     sema.Release();
  339.     return p != NULL  &&  p->expList != NULL;    // minimum one match
  340. }   // doKillQ
  341.