/* Copyright (c) 1996-97, Ruslan R. Laishev (@RRL) */ #include "nntp.h" int nntp_feed_group ( WorkerContext *, FeedRec *, char *, int, char *, int ); 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_LOGT(Wctxp,LOGD,"Check group '%.*s'.",GrpName$_len,gkey.GrpName); gkey.GrpName[GrpName$_len] = 0; if ( ('n' == gkey.PostFlag) || (!strmatch (lGrpList,gkey.GrpName)) || (gkey.Last == 0) ) { NNTP_LOGT(Wctxp,LOGD,"Skip group '%.*s'.", GrpName$_len,gkey.GrpName); continue; } /* * Get info in Feed database about last feeded message */ lmsg = gkey.First; NNTP_LOGT(Wctxp,LOGW,"'%.*s' first ARTICLE #%u.", GrpName$_len,gkey.GrpName,lmsg); sprintf(frec.Host_Grp,"%s,%.*s",lIP,GrpName$_len,gkey.GrpName); if ( FeedDBget(&Wctxp->Feedrab,&frec) ) { NNTP_LOGT(Wctxp,LOGW,"'%.*s' last feeded ARTICLE #%u.", GrpName$_len,gkey.GrpName,frec.Last); if ( gkey.Last == frec.Last ) continue; lmsg = max (lmsg,frec.Last); lmsg = min (lmsg,gkey.Last); } /* * Start FeedUp for one group */ nntp_feed_group ( Wctxp,&frec,gkey.GrpName,lmsg,lExcList,PostingType); if ( lmsg == frec.Last ) continue; /* * Update Feed record in FeedDB */ NNTP_LOGT(Wctxp,LOGW,"Update FeedDB for %.*s,last ARTICLE #%u", Feed$_len,frec.Host_Grp,frec.Last); if ( !FeedDBput(&Wctxp->Feedrab,&frec) ) NNTP_LOGT(Wctxp,LOGE,"Update FeedDB."); } send(Wctxp->chan,QUIT,sizeof (QUIT)-1,0); NNTP_LOGT(Wctxp,LOGW,"All Group is Feeded."); return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_feed_group ( WorkerContext *Wctxp, FeedRec *frec, char *fGrp, int lmsg, char *ExcList, int PostingType ) { 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:"}; int Posted,Rejected; Posted = Rejected = 0; strncpy (lfGrp,fGrp,GrpName$_len); NNTP_LOGT(Wctxp,LOGI,"Start upload '%.*s' at ARTICLE #%u.", GrpName$_len,lfGrp,lmsg+1); while (1) { frec->Last = lmsg; lmsg++; /* * Get ARTICLE # in the buffer */ if ( !(szM = MsgDBget_byNum(&Wctxp->Msgrab,lfGrp, lmsg,Wctxp->MsgBuff,MSGBUFFSZ)) ) { NNTP_LOGT(Wctxp,LOGW,"'%s' ARTICLE #%u-Not Retrived.", lfGrp,lmsg); break; } Wctxp->MsgBuff[sizeof(MsgKey)+szM] = 0; NNTP_LOGT(Wctxp,LOGD,"ARTICLE #%u %.*s (%d bytes)-Retrived.", lmsg,MsgId$_len,mkeyp->MsgId,szM); /* * Extract 'Path:'-field for exclude list */ if ( NULL == (cp0 = strstr(&Wctxp->MsgBuff[sizeof(MsgKey)],FieldPath)) ) break; 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_LOGT(Wctxp,LOGD,"ARTICLE #%u %.*s-Skipped.", lmsg,MsgId$_len,mkeyp->MsgId); continue; } if ( PostingType ) {sz = sprintf(Wctxp->bufp,POST);} else {sz = sprintf(Wctxp->bufp,IHAVE,MsgId$_len,mkeyp->MsgId);} NNTP_LOGT(Wctxp,LOGD,"Send '%.*s'.",sz,Wctxp->bufp); if ( 0 > send (Wctxp->chan,Wctxp->bufp,sz,0) ) break; /* * Get response from feeder */ if ( 0 > (sz = nntp_cmd_get(Wctxp->chan,Wctxp->bufp,BUFPSZ)) ) break; NNTP_LOGT(Wctxp,LOGW,"Response to 'IHAVE' from Feeder '%.*s'.", sz,Wctxp->bufp); /* * Get status code & dispatch */ if (1 != sscanf(Wctxp->bufp,"%u",&rc) ) break; if ( (rc == 435) || (rc == 441) ) { Rejected++; continue; } if ( rc >= 400 ) break; /* * 335 or 340 - 'Ok' Send article to feeder host */ NNTP_LOGT(Wctxp,LOGD,"Send ARTICLE #%u %.*s.", lmsg,MsgId$_len,mkeyp->MsgId); if ( 0 >= send(Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)],szM,0) ) { NNTP_LOGT(Wctxp,LOGE,"Send ARTICLE #%u %.*s.", lmsg,MsgId$_len,mkeyp->MsgId); break; } if ( 0 >= (sz = nntp_cmd_get(Wctxp->chan,Wctxp->bufp,BUFPSZ)) ) return -1; NNTP_LOGT(Wctxp,LOGW,"Status after sending ARTICLE to Feed '%.*s'.", sz,Wctxp->bufp); /* * Get status code & check it */ if (1 != sscanf(Wctxp->bufp,"%u",&rc) ) break; if ( (rc == 235) || (rc == 240) ) { NNTP_LOGT(Wctxp,LOGW,"Send ARTICLE #%u %.*s.", lmsg,MsgId$_len,mkeyp->MsgId); Posted++; continue; } NNTP_LOGT(Wctxp,LOGE,"Send ARTICLE #%u %.*s.", lmsg,MsgId$_len,mkeyp->MsgId); } NNTP_LOGT(Wctxp,LOGI,"'%.*s' statistic:Posted %u,Rejected %u.", GrpName$_len,lfGrp,Posted,Rejected); 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; }