home *** CD-ROM | disk | FTP | other *** search
- // $Id: kill.cc 1.18 1997/01/20 16:05:53 hardy Exp $
- //
- // This progam/module was written by Hardy Griech based on ideas and
- // pieces of code from Chin Huang (cthuang@io.org). Bug reports should
- // be submitted to rgriech@ibm.net.
- //
- // This file is part of soup++ for OS/2. Soup++ including this file
- // is freeware. There is no warranty of any kind implied. The terms
- // of the GNU Gernal Public Licence are valid for this piece of software.
- //
- // Kill file processing
- //
-
-
- #include <ctype.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdio.h>
- #include <regexp.h>
- #include <unistd.h>
- #include <sys/nls.h>
-
- #include "kill.hh"
- #include "mts.hh"
-
-
-
- TKillFile::TKillFile( void )
- {
- groupKillList = actGroupList = NULL;
- actGroupName = xstrdup("");
- } // TKillFile::TKillFile
-
-
-
- void TKillFile::killGroup( Group *gp )
- {
- Exp *ep1, *ep2;
-
- if (gp == NULL)
- return;
-
- ep1 = gp->expList;
- while (ep1 != NULL) {
- if (ep1->re != NULL) {
- delete ep1->re;
- }
- ep2 = ep1->next;
- delete ep1;
- ep1 = ep2;
- }
- delete gp->grpPat;
- delete gp;
- } // TKillFile::killGroup
-
-
-
- TKillFile::~TKillFile()
- {
- Group *gp1, *gp2;
-
- gp1 = groupKillList;
- while (gp1 != NULL) {
- gp2 = gp1->next;
- killGroup( gp1 );
- gp1 = gp2;
- }
-
- gp1 = actGroupList;
- while (gp1 != NULL) {
- gp2 = gp1->next;
- delete gp1;
- gp1 = gp2;
- }
- delete actGroupName;
- } // TKillFile::~TKillFile
-
-
-
- TKillFile::Exp *TKillFile::genRegExp(const char *searchIn, const char *searchFor)
- {
- char exp[BUFSIZ];
- Exp *result;
-
- if (searchFor[0] == '\0')
- return NULL;
-
- if (stricmp(searchIn, "header") == 0)
- strcpy( exp,searchFor );
- else
- sprintfT( exp,"^%s:.*%s", searchIn,searchFor );
-
- result = new Exp;
- result->next = NULL;
- _nls_strlwr( (unsigned char *)exp );
- result->re = regcompT( exp );
- return result;
- } // TKillFile::genRegExp
-
-
-
- void TKillFile::stripBlanks( char *line )
- {
- char *p1, *p2;
- int len;
-
- p1 = line;
- while (*p1 == ' ' || *p1 == '\t')
- ++p1;
- p2 = line + strlen(line) - 1;
- while (p2 >= p1 && (*p2 == ' ' || *p2 == '\t'))
- --p2;
- len = p2-p1+1;
- if (len > 0) {
- memmove( line,p1,len );
- line[len] = '\0';
- }
- else
- line[0] = '\0';
- } // TKillFile::stripBlanks
-
-
-
- int TKillFile::readLine( char *line, int n, TFile &inf, int &lineNum )
- //
- // fetch the next line from file
- // blanks are stripped
- // blank lines & lines with '#' in the beginning are skipped
- // on EOF NULL is returned
- //
- {
- for (;;) {
- if (inf.fgets(line,n,1) == NULL)
- return 0;
- ++lineNum;
- stripBlanks( line );
- if (line[0] != '\0' && line[0] != '#')
- break;
- }
- return 1;
- } // TKillFile::readLine
-
-
-
- int TKillFile::readFile( const char *killFile )
- //
- // Read kill file and compile regular expressions.
- // Return: -1 -> file not found, 0 -> syntax error, 1 -> ok
- // Nicht so hanz das optimale: besser wäre es eine Zustandsmaschine
- // zusammenzubasteln...
- //
- {
- char buf[1000], name[1000], tmp[1000];
- char searchIn[1000], searchFor[1000];
- TFile inf;
- Group *pGroup, *pLastGroup;
- Exp *pExp, *pLastExp;
- char ok;
- int lineNum;
-
- groupKillList = NULL;
-
- if ( !inf.open(killFile,TFile::mread,TFile::otext))
- return -1;
-
- sema.Request();
-
- pLastGroup = NULL;
- ok = 1;
-
- //
- // read newsgroup name
- //
- lineNum = 0;
- while (ok && readLine(buf,sizeof(buf),inf,lineNum)) {
- #ifdef DEBUG_ALL
- printfT( "line: '%s'\n",buf );
- #endif
- if (sscanfT(buf,"%s%s",name,tmp) == 1)
- readLine(tmp,sizeof(tmp),inf,lineNum);
-
- if (tmp[0] != '{' || tmp[1] != '\0') {
- ok = 0;
- break;
- }
-
- if (stricmp(name, "all") == 0)
- strcpy( name,".*" ); // use 'special' pattern which matches all group names
- else
- _nls_strlwr( (unsigned char *)name );
- pGroup = new Group;
- pGroup->grpPat = regcompT( name );
- pGroup->expList = NULL;
- pGroup->next = NULL;
-
- if (pLastGroup == NULL)
- groupKillList = pGroup;
- else
- pLastGroup->next = pGroup;
- pLastGroup = pGroup;
-
- //
- // Read kill expressions until closing brace.
- //
- pLastExp = NULL;
- while (readLine(buf,sizeof(buf),inf,lineNum)) {
- *searchIn = *searchFor = '\0';
- sscanfT( buf,"%s%[^\n]",searchIn,searchFor );
- stripBlanks( searchFor );
-
- if (searchIn[0] == '}' && searchIn[1] == '\0') {
- ok = (searchFor[0] == '\0');
- break;
- }
- if (searchFor[0] == '\0') {
- ok = 0;
- break;
- }
- #ifdef DEBUG_ALL
- printfT( "search: '%s', '%s'\n",searchIn,searchFor );
- #endif
- if ((pExp = genRegExp(searchIn,searchFor)) == NULL) {
- ok = 0;
- break;
- }
-
- //
- // append entry to list
- //
- if (pLastExp == NULL)
- pGroup->expList = pExp;
- else
- pLastExp->next = pExp;
- pLastExp = pExp;
- }
- }
- sema.Release();
-
- inf.close();
-
- if ( !ok)
- hprintfT( STDERR_FILENO, "error in kill file %s,\n\tsection %s, line %d\n",
- killFile,name,lineNum);
- return ok;
- } // TKillFile::readFile
-
-
-
- TKillFile::Group *TKillFile::buildActGroupList( const char *groupName )
- //
- // return group kill for *groupName
- //
- {
- Group *p;
- Group **pp;
- char *name;
-
- #ifdef TRACE_ALL
- printfT( "TKillFile::buildActGroupList(%s)\n",groupName );
- #endif
-
- name = (char *)xstrdup( groupName );
- _nls_strlwr( (unsigned char *)name );
-
- if (stricmp(name,actGroupName) != 0) {
- pp = &actGroupList;
- for (p = groupKillList; p != NULL; p = p->next) {
- //
- // is groupname matched by a killgroup regexp?
- //
- if (regexecT(p->grpPat,name)) {
- //
- // does the killgroup regexp match the complete groupname?
- //
- if (name == p->grpPat->startp[0] &&
- name+strlen(name) == p->grpPat->endp[0]) {
- #ifdef DEBUG_ALL
- printfT( "regexec: %p,%ld %p %p\n", name,strlen(name), p->grpPat->startp[0], p->grpPat->endp[0] );
- #endif
- if (*pp == NULL) {
- *pp = new Group;
- (*pp)->next = NULL;
- }
- (*pp)->expList = p->expList;
- pp = &((*pp)->next);
- }
- }
- }
- if (*pp != NULL)
- (*pp)->expList = NULL;
- xstrdup( &actGroupName, name );
- }
-
- delete name;
- return actGroupList;
- } // TKillFile::buildActGroupList
-
-
-
- int TKillFile::matchLine( const char *groupName, const char *line )
- //
- // Check if line matches kill criteria (line must be already in lower case!)
- // Return TRUE if article should be killed.
- //
- {
- int res = 0;
- Group *pGroup;
- Exp *pExp;
-
- sema.Request();
-
- buildActGroupList( groupName );
- for (pGroup = actGroupList;
- pGroup != NULL && pGroup->expList != NULL;
- pGroup = pGroup->next) {
- for (pExp = pGroup->expList; pExp != NULL; pExp = pExp->next) {
- if (regexecT(pExp->re, line)) {
- res = 1;
- break;
- }
- }
- if (res)
- break;
- }
-
- sema.Release();
- return res;
- } // TKillFile::matchLine
-
-
-
- int TKillFile::doKillQ( const char *groupName )
- {
- Group *p;
-
- sema.Request();
- p = buildActGroupList(groupName);
- sema.Release();
- return p != NULL && p->expList != NULL; // minimum one match
- } // doKillQ
-