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 >
Wrap
C/C++ Source or Header
|
1994-06-29
|
7KB
|
420 lines
/*
* REFS.C
*
* Handles the References: line
*/
#include "defs.h"
/*
* hash table for killed references
*/
#define HSIZE 256
#define HMASK (HSIZE-1)
Prototype void AddKillFile(char *, int, int);
Prototype void RemKillFile(char *);
Prototype void LoadKillFile(char *);
Prototype void SaveKillFile(char *);
Prototype char *FromLineOf(NGroup *, int);
Prototype char *ReferenceLineOf(NGroup *, int);
Prototype char *NewsMessageIdOf(NGroup *, int);
Prototype char *SubjectOf(NGroup *, int, int);
Prototype char *StripRE(char *);
Prototype int FindArticleReferencing(NGroup *, char *, int);
Prototype int ArticleRefKilled(NGroup *, int);
Prototype char *NextRef(char **);
/*
* Hash table for references
*/
typedef struct Hash {
struct Hash *Next;
time_t TTerm; /* terminate entry after time tterm */
char Id[4];
} Hash;
Local Hash **FindRefHash(char *);
Local void AddRefHash(Hash **, char *, time_t);
Local int hash(char *);
static Hash *Table[HSIZE];
/*
* Add References: field to kill file. Kill file entry will exist for 30
* days.
*/
void
AddKillFile(refs, days, noBrkUp)
char *refs;
int days;
int noBrkUp;
{
char *id;
Hash **ph;
Hash *h;
if (days)
days = time(0) + days * 1440 * 60; /* seconds */
if (noBrkUp) {
ph = FindRefHash(refs);
if (h = *ph) {
h->TTerm = days;
} else {
AddRefHash(ph, refs, days);
}
} else {
while (id = NextRef(&refs)) {
ph = FindRefHash(id);
if (h = *ph) {
h->TTerm = days; /* now seconds */
} else {
AddRefHash(ph, id, days);
}
}
}
}
void
RemKillFile(refs)
char *refs;
{
char *id;
Hash **ph;
Hash *h;
while (id = NextRef(&refs)) {
ph = FindRefHash(id);
if (h = *ph) {
*ph = h->Next;
free(h);
}
}
}
void
LoadKillFile(user)
char *user;
{
char id[128];
char buf[64];
long tterm;
FILE *fi;
sprintf(buf, "%s.dnewskl", user);
if (fi = openlib(buf)) {
while (fgets(TmpBuf, sizeof(TmpBuf), fi)) {
Hash **ph;
char *ptr;
short len;
tterm = strtol(TmpBuf, &ptr, 0);
while (*ptr == ' ' || *ptr == '\t')
++ptr;
strncpy(id, ptr, sizeof(id) - 1);
id[sizeof(id)-1] = 0;
len = strlen(id);
if (len && id[len-1] == '\n')
id[--len] = 0;
if (tterm) {
if (*(ph = FindRefHash(id)) == NULL)
AddRefHash(ph, id, tterm);
}
}
fclose(fi);
}
}
void
SaveKillFile(user)
char *user;
{
char buf[64];
FILE *fo;
time_t curtime = time(NULL);
sprintf(buf, "%s.dnewskl", user);
if (fo = openlib_write(buf)) {
Hash **ph;
short i;
for (ph = Table, i = 0; i < HSIZE; ++i, ++ph) {
Hash *h;
for (h = *ph; h; h = h->Next) {
if (h->TTerm == -1 || (h->TTerm && h->TTerm > curtime))
fprintf(fo, "%d %s\n", h->TTerm, h->Id);
}
}
fclose(fo);
}
}
char *
FromLineOf(grp, artno)
NGroup *grp;
int artno;
{
FILE *fi;
FNode **pfn = FindFNCache(grp->FromBase, artno);
{
FNode *fn;
if (fn = *pfn)
return(fn->Id);
}
{
if (fi = fopen(FileForArticle(grp, artno), "r")) {
char *field = FindField(fi, "From:");
fclose(fi);
if (field) {
AddFNCache(pfn, artno, field);
return(field);
}
}
}
AddFNCache(pfn, artno, NULL);
return(NULL);
}
char *
ReferenceLineOf(grp, artno)
NGroup *grp;
int artno;
{
FILE *fi;
FNode **pfn = FindFNCache(grp->RefBase, artno);
{
FNode *fn;
if (fn = *pfn)
return(fn->Id);
}
{
if (fi = fopen(FileForArticle(grp, artno), "r")) {
char *field = FindField(fi, "References:");
fclose(fi);
if (field) {
AddFNCache(pfn, artno, field);
return(field);
}
}
}
AddFNCache(pfn, artno, NULL);
return(NULL);
}
char *
SubjectOf(grp, artno, stripre)
NGroup *grp;
int artno;
{
FILE *fi;
FNode **pfn = FindFNCache(grp->SubBase, artno);
{
FNode *fn;
if (fn = *pfn) {
if (stripre && fn->Id)
return(StripRE(fn->Id));
return(fn->Id);
}
}
{
if (fi = fopen(FileForArticle(grp, artno), "r")) {
char *field = FindField(fi, "Subject:");
fclose(fi);
if (field) {
AddFNCache(pfn, artno, field);
if (stripre)
field = StripRE(field);
return(field);
}
}
}
AddFNCache(pfn, artno, NULL);
return(NULL);
}
char *
NewsMessageIdOf(grp, artno)
NGroup *grp;
int artno;
{
FILE *fi;
FNode **pfn = FindFNCache(grp->IdBase, artno);
{
FNode *fn;
if (fn = *pfn)
return(fn->Id);
}
{
if (fi = fopen(FileForArticle(grp, artno), "r")) {
char *field = FindField(fi, "Message-ID:");
fclose(fi);
if (field) {
AddFNCache(pfn, artno, field);
return(field);
}
}
}
AddFNCache(pfn, artno, NULL);
return(NULL);
}
/*
* Given the msg-id of an article (msgid), find it amoung the References:
* line of later articles.
*/
int
FindArticleReferencing(grp, msgid, artno)
NGroup *grp;
char *msgid;
int artno;
{
char *field = ReferenceLineOf(grp, artno);
char *id;
if (field == NULL)
return(0);
while (id = NextRef(&field)) {
/*printf("COMPARE: %s vs %s artno %d\n", msgid, id, artno);*/
if (strcmp(msgid, id) == 0)
break;
}
if (id)
return(1);
return(0);
}
/*
* Is the specified article (grp, artno) in the kill list ? That is, if
* any of the fields in the article's References: line are on the kill list
* we return TRUE.
*/
int
ArticleRefKilled(grp, artno)
NGroup *grp;
int artno;
{
char *refs;
char *id;
Hash **ph;
if (refs = ReferenceLineOf(grp, artno)) {
while (id = NextRef(&refs)) {
if (*(ph = FindRefHash(id))) {
return(1);
}
}
}
if (refs = SubjectOf(grp, artno, 1)) {
if (*(ph = FindRefHash(refs))) {
return(1);
}
}
if (refs = FromLineOf(grp, artno)) {
if (*(ph = FindRefHash(refs))) {
return(1);
}
}
return(0);
}
char *
NextRef(ppt)
char **ppt;
{
char *ptr = *ppt;
char *base;
static char buf[256];
while (*ptr == ' ' || *ptr == 9 || *ptr == '\n')
++ptr;
base = buf;
while (*ptr && *ptr != ' ' && *ptr != 9 && *ptr != '\n')
*base++ = *ptr++;
*base = 0;
*ppt = ptr;
if (base == buf)
return(NULL);
return(buf);
}
/*
* HASH TABLE ROUTINES
*/
Hash **
FindRefHash(id)
char *id;
{
Hash **ph = Table + hash(id);
Hash *h;
while (h = *ph) {
if (strcmp(id, h->Id) == 0)
break;
ph = &h->Next;
}
return(ph);
}
Local
void
AddRefHash(ph, id, ti)
Hash **ph;
char *id;
time_t ti;
{
Hash *h = malloc(sizeof(Hash) - sizeof(h->Id) + strlen(id) + 1);
strcpy(h->Id, id);
h->TTerm = ti;
h->Next = *ph;
*ph = h;
}
int
hash(ptr)
char *ptr;
{
long hv = 0x1234ADC3;
while (*ptr) {
hv = (hv >> 23) ^ (hv << 5) ^ *ptr;
++ptr;
}
return(hv & HMASK);
}
char *
StripRE(str)
char *str;
{
for (;;) {
while (*str == ' ' || *str == '\t')
++str;
if (strnicmp(str, "re:", 3) == 0) {
str += 3;
continue;
}
break;
}
return(str);
}