/* Copyright (c) 1996, Ruslan R. Laishev (@RRL) */ #include "nntp.h" #include "nntp_log.h" #include "nntp_lib.h" char MODE_READER[] = "MODE READER\r\n"; char GROUP [] = "GROUP %.*s\r\n"; char ARTICLE[] = "ARTICLE %u\r\n"; char QUIT[] = "QUIT\r\n"; int nntp_suck_group ( WorkerContext *Wctxp, SuckRec *srec ); /* *-------------------------------------------------------------------------------- */ int nntp_suck ( WorkerContext *Wctxp, char *GrpList, char *IP ) { GrpKey gkey; SuckRec srec; int flag = 0; int rc; unsigned long int nmsg,fmsg,lmsg; char lGrpList [ 1024 ]; char lIP [ 17 ]; int sz; strcpy (lGrpList,GrpList); strcpy (lIP,IP); /* For Dump INN and other *ix... send MODE READER */ if ( 0 > nntp_cmd_get (Wctxp->chan,&Wctxp->bufp[0],sizeof(Wctxp->bufp)) ) return -1; if ( 0 > send(Wctxp->chan,MODE_READER,sizeof (MODE_READER)-1,0) ) return -1; if ( 0 > nntp_cmd_get (Wctxp->chan,&Wctxp->bufp[0],sizeof(Wctxp->bufp)) ) return -1; /* */ while ( GrpDBget_seq (&Wctxp->Grprab,&gkey,flag++) ) { nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Group '%.*s'-Check.", Wctxp->chan,GrpName$_len,gkey.GrpName)); gkey.GrpName[GrpName$_len] = 0; /* if ( (!gkey.SuckFlag) || (!match_in_list (lGrpList,&gkey.GrpName[0])) ) */ if ( !match_in_list (lGrpList,&gkey.GrpName[0]) ) { nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Group '%.*s'-Skip.", Wctxp->chan,GrpName$_len,gkey.GrpName)); continue; } nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Group '%.*s'-Cached.", Wctxp->chan,GrpName$_len,gkey.GrpName)); sz = sprintf(&Wctxp->bufp[0],GROUP,GrpName$_len,gkey.GrpName); if ( 0 > send (Wctxp->chan,&Wctxp->bufp[0],sz,0) ) return -1; nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Request info-%.*s.", Wctxp->chan,GrpName$_len,gkey.GrpName)); if ( 0 > (sz = nntp_cmd_get (Wctxp->chan,&Wctxp->bufp[0],sizeof(Wctxp->bufp))) ) { nntp_log(loge,(stdout,"[Th:Suck,Ch:%d]Request info-%.*s-Error.", Wctxp->chan,GrpName$_len,gkey.GrpName)); return -1; } nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]recv '%.*s'", Wctxp->chan,sz,&Wctxp->bufp[0])); sscanf(&Wctxp->bufp[0],"%u %u %u %u",&rc,&nmsg,&fmsg,&lmsg); if ( rc != 211) continue; /* */ sprintf(&srec.Host_Grp,"%s,%.*s",lIP,GrpName$_len,gkey.GrpName); if ( SuckDBget(&Wctxp->Suckrab,&srec) ) { nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]SuckDB:last #%u article.", Wctxp->chan,srec.Last)); if ( lmsg <= srec.Last) { nntp_log(logw,(stdout,"[Th:Suck,Ch:%d]Group '%.*s'-Up-to-Date.", Wctxp->chan,GrpName$_len,gkey.GrpName)); continue; } fmsg = max (fmsg,srec.Last); } /* */ srec.Last = fmsg; nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Start downloading at #%u article.", Wctxp->chan,srec.Last)); nntp_suck_group ( Wctxp,&srec); /* */ nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Update SuckDB-%.*s,%u", Wctxp->chan,Suck$_len,srec.Host_Grp,srec.Last)); if ( !SuckDBput(&Wctxp->Suckrab,&srec) ) nntp_log(loge,(stdout,"[Th:Suck,Ch:%d]Update SuckDB-Error.", Wctxp->chan)); /* */ } send(Wctxp->chan,MODE_READER,sizeof (MODE_READER)-1,0); nntp_log(logw,(stdout,"[Th:Suck,Ch:%d]All Group is Up-to-Date.", Wctxp->chan)); } /* *-------------------------------------------------------------------------------- */ int nntp_suck_group ( WorkerContext *Wctxp, SuckRec *srec ) { unsigned long rc,cmsg; int sz; char *cp0,*cp1; cmsg = srec->Last; while (1) { sz = sprintf(&Wctxp->bufp[0],ARTICLE,cmsg); if ( 0 > send (Wctxp->chan,&Wctxp->bufp[0],sz,0) ) return -1; if ( 0 > (sz = nntp_cmd_get(Wctxp->chan,&Wctxp->bufp[0],sizeof(Wctxp->bufp))) ) return -1; nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Response from Suck '%.*s'.", Wctxp->chan,sz-2,&Wctxp->bufp[0])); if ( 2 != sscanf(&Wctxp->bufp[0],"%u %u",&rc,&cmsg) ) return -1; if ( rc == 423 ) return 0; if ( rc != 220 ) goto next; /* From nntp_ihave with small corrections. */ if ( NULL == (cp0 = strchr(Wctxp->bufp,'<')) ) goto next; if ( NULL == (cp1 = strchr(cp0,'>')) ) goto next; if ( (cp1 - cp0) > MsgId$_len ) goto next; *(++cp1) = 0; nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Article %.*s-Check.", Wctxp->chan,MsgId$_len,cp0)); if (!MsgDBfind_byId(&Wctxp->Msgrab,cp0,cp1-cp0) ) { nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Article %.*s-Duplicate.", Wctxp->chan,MsgId$_len,cp0)); nntp_txt_get (Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)], Msg_MaxRec-sizeof(MsgKey)-1); goto next; } nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]Article %.*s-Suck.", Wctxp->chan,MsgId$_len,cp0)); sz = nntp_txt_get (Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)], Msg_MaxRec-sizeof(MsgKey)-1); if ( sz <= 0 ) { nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]#%u article size is too big-Skip.", Wctxp->chan,srec->Last)); goto next; } if ( nntp_msg_to_db (Wctxp,sz) ) nntp_log(logd,(stdout,"[Th:Suck,Ch:%d]#%u article-Retrieved.", Wctxp->chan,srec->Last)); /* */ next: srec->Last = cmsg; cmsg++; } return 0; }