/* Copyright (c) 1996-97, Ruslan R. Laishev (@RRL) */ #include "nntp.h" #include "nntp_log.h" #include "nntp_lib.h" #include "nntp_netio.h" #include "nntp_feed.h" int nntp_feed_groupi( WorkerContext *, FeedRec *, char *, int, char * ); char IHAVE[] = "IHAVE %.*s\r\n"; char POST[] = "POST\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_feed ( WorkerContext *Wctxp, char *GrpList, char *IP, int PostingType, char *ExcList ) { GrpKey gkey; FeedRec frec; int flag = 0; int rc; unsigned long int lmsg; char lGrpList [ 1024 ]; char lExcList [ 1024 ]; char lIP [ 17 ]; int sz; char MODE_READER[] = "MODE READER\r\n"; char QUIT[] = "QUIT\r\n"; strcpy (lGrpList,GrpList); strcpy (lExcList,ExcList); strcpy (lIP,IP); if ( 0 > nntp_cmd_get (Wctxp->chan,Wctxp->bufp,BUFPSZ) ) return -1; /* * For type of posting 'POST' send MODE READER */ if ( PostingType ) { if ( 0 > send(Wctxp->chan,MODE_READER,sizeof (MODE_READER)-1,0) ) return -1; if ( 0 > nntp_cmd_get (Wctxp->chan,Wctxp->bufp,BUFPSZ) ) return -1; } /* * Get first group with Posting allowed and matched in list */ while ( GrpDBget_seq (&Wctxp->Grprab,&gkey,flag++) ) { NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Check group '%.*s'.", Wctxp->chan,GrpName$_len,gkey.GrpName); gkey.GrpName[GrpName$_len] = 0; if ( (!gkey.PostFlag) || (!strmatch (lGrpList,gkey.GrpName)) ) { NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Skip group '%.*s'.", Wctxp->chan,GrpName$_len,gkey.GrpName); continue; } /* * Get info in Feed database about last feeded message */ lmsg = gkey.Last; sprintf(frec.Host_Grp,"%s,%.*s",lIP,GrpName$_len,gkey.GrpName); if ( FeedDBget(&Wctxp->Feedrab,&frec) ) { NNTP_LOG(LOGW,"[Th:Feed,Ch:%d]'%.*s' last feeded ARTICLE %u.", Wctxp->chan,GrpName$_len,gkey.GrpName,frec.Last); if ( gkey.Last == frec.Last) continue; lmsg = max (gkey.First,frec.Last); lmsg = min (gkey.Last,lmsg); } if ( lmsg == gkey.Last ) continue; NNTP_LOG(LOGW,"[Th:Feed,Ch:%d]Start update '%.*s' at ARTICLE %u.", Wctxp->chan,GrpName$_len,gkey.GrpName,frec.Last); /* * Start FeedUp for one group */ nntp_feed_groupi ( Wctxp,&frec,gkey.GrpName,lmsg,lExcList); if ( lmsg == frec.Last ) continue; /* * Update Feed record in FeedDB */ NNTP_LOG(LOGW,"[Th:Feed,Ch:%d]Update FeedDB for %.*s,last ARTICLE %u", Wctxp->chan,Feed$_len,frec.Host_Grp,frec.Last); if ( !FeedDBput(&Wctxp->Feedrab,&frec) ) NNTP_LOG(LOGE,"[Th:Feed,Ch:%d]Update SuckDB.",Wctxp->chan); } send(Wctxp->chan,QUIT,sizeof (QUIT)-1,0); NNTP_LOG(LOGW,"[Th:Feed,Ch:%d]All Group is Feeded.",Wctxp->chan); return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_feed_groupi( WorkerContext *Wctxp, FeedRec *frec, char *fGrp, int lmsg, char *ExcList ) { int nntp_feed_exclude (char *,char *,int); unsigned long rc,cmsg; int sz,szA,szM; char *cp0,*cp1; char lfGrp [ GrpName$_len + 1 ]; MsgKey *mkeyp = (MsgKey*) Wctxp->MsgBuff; char FieldPath [ ] = {"Path:"}; strncpy (lfGrp,fGrp,GrpName$_len); while (1) { frec->Last = lmsg; lmsg++; /* * Get ARTICLE # in the buffer */ if ( !(szM = MsgDBget_byNum(&Wctxp->Msgrab,lfGrp, lmsg,Wctxp->MsgBuff,MSGBUFFSZ)) ) { NNTP_LOG(LOGW,"[Th:Feed,Ch:%d]'%s' ARTICLE #%u-Retrive.", Wctxp->chan,lfGrp,lmsg); return -1; } Wctxp->MsgBuff[sizeof(MsgKey)+szM] = 0; NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]ARTICLE #%u %.*s (%d bytes)-Retrived.", Wctxp->chan,lmsg,MsgId$_len,mkeyp->MsgId,szM); /* * Extract 'Path:'-field for exclude list */ if ( NULL == (cp0 = strstr(&Wctxp->MsgBuff[sizeof(MsgKey)],FieldPath)) ) return -1; cp0 += sizeof(FieldPath); cp1 = strpbrk(cp0,"\r\t"); strncpy(Wctxp->bufp,cp0,cp1-cp0); Wctxp->bufp[cp1-cp0] = 0; strlwr (Wctxp->bufp); /* * Check for presence in exclude list */ if ( nntp_feed_exclude (Wctxp->bufp,ExcList,strlen(ExcList)) ) { NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]ARTICLE #%d %.*s-Skipped.", Wctxp->chan,lmsg,MsgId$_len,mkeyp->MsgId); continue; } /* * Send 'IHAVE <'Message-ID'>' */ NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Send 'IHAVE %.*s'.", Wctxp->chan,MsgId$_len,mkeyp->MsgId); sz = sprintf(Wctxp->bufp,IHAVE,MsgId$_len,mkeyp->MsgId); if ( 0 > send (Wctxp->chan,Wctxp->bufp,sz,0) ) return -1; /* * Get response from feeder */ if ( 0 > (sz = nntp_cmd_get(Wctxp->chan,Wctxp->bufp,BUFPSZ)) ) return -1; NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Response to 'IHAVE' from Feeder '%.*s'.", Wctxp->chan,sz,Wctxp->bufp); /* * Get status code & dispatch */ if (1 != sscanf(Wctxp->bufp,"%u",&rc) ) return -1; if ( rc == 435 ) continue; if ( rc >= 400 ) return -1; /* * 335 - 'Ok' Send article to feeder host */ NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Send ARTICLE #%d.",Wctxp->chan,lmsg); if ( 0 >= send(Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)],szM,0) ) { NNTP_LOG(LOGE,"[Th:Feed,Ch:%d]Send ARTICLE #%d.", Wctxp->chan,lmsg); return -1; } if ( 0 >= (sz = nntp_cmd_get(Wctxp->chan,Wctxp->bufp,BUFPSZ)) ) return -1; NNTP_LOG(LOGD,"[Th:Feed,Ch:%d]Status after sending ARTICLE from Feed '%.*s'.", Wctxp->chan,sz,Wctxp->bufp); /* * Get status code & check it */ if (1 != sscanf(Wctxp->bufp,"%u",&rc) ) return -1; if ( rc == 235 ) continue; NNTP_LOG(LOGE,"[Th:Feed,Ch:%d]Send ARTICLE %d.",Wctxp->chan,lmsg); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_feed_exclude ( char *sList, char *eList, int eListsz ) { char buf [ 128 ]; int i; for (i = 0;strelem(buf,eList,eListsz,",",i); i++) { if ( strstr(sList,buf) ) return 1; } return 0; }