/* Copyright (c) 1996, Ruslan R. Laishev (@RRL) */ #include #include "nntp.h" #include "nntp_commands.h" #include "nntp_rms.h" #include "nntp_log.h" #include "nntp_lib.h" static NNTP_cmd_t NNTP_cmd[] = { {"help", nntp_help,"Help"}, {"quit", nntp_quit,"Quit"}, {"arti", nntp_arti,"Article [MessageID | Number]"}, {"head", nntp_head,"Head [MessageID | Number]"}, {"body", nntp_body,"Body [MessageID | Number]"}, {"stat", nntp_stat,"Stat [MessageID | Number]"}, {"post", nntp_post,"Post"}, {"ihav", nntp_ihav,"Ihave MessageID"}, {"list", nntp_list,"List"}, {"grou", nntp_grou,"Group newsgroupname"}, {"newg", nntp_newg,"NewGroups date time [GMT] []"}, {"slav", nntp_slav,"Slave"}, {"xove", nntp_xove,"Xover [First - Last]"}, {"last", nntp_last,"Last"}, {"next", nntp_next,"Next"}, {"newn", nntp_newn,"NewNews date time [GMT] []"}, /* "auth", nntp_auth,"Authinfo user pass" */ {NULL, NULL, "UnRecognized"} }; /* *-------------------------------------------------------------------------------- */ int nntp_cmd_get (int chan,char *bufp,int bufl) { int sz; int pos; pos = 0; do { if ( 0 > (sz = recv(chan,bufp+pos,1, 0)) ) { nntp_log(loge,(stdout,"[Ch:%d]nntp_cmd_get:%s", chan,strerror(errno))); return -1; } pos += sz; if ( (pos > 1) ) if ( (*(bufp+pos-2) == 13) && (*(bufp+pos-1) == 10) ) break; } while (pos <= bufl); *(bufp+pos) = '\0'; return pos; } /* *-------------------------------------------------------------------------------- */ int nntp_txt_get (int chan,char *bufp,int bufl) { int sz,pos,flag; char *cp; pos = flag = 0; bufl--; /*@RRL ? Whot need do with big messages ? */ while (1) { do { if ( 0 > (sz = recv(chan,bufp+pos,bufl-pos, 0)) ) { nntp_log(loge,(stdout,"[Ch:%d]nntp_txt_get:%s", chan,strerror(errno))); return -1; } pos += sz; *(bufp+pos) = '\0'; if (pos >= 5) { if ( strstr(bufp,"\r\n.\r\n") ) return ( (flag == 0)?pos:-1); } } while (pos < bufl); /* For getting rest of big messages. */ memmove(bufp,bufp+(pos/2),1+(pos/2)); pos /= 2; flag++; } return 0; } /* *-------------------------------------------------------------------------------- */ void *nntp_cmd_parse (WorkerContext *Wctxp) { NNTP_cmd_t *cmdp; cmdp = &NNTP_cmd[0]; do { if ( !strincmp(cmdp->cmd,Wctxp->bufp,4) ) break; cmdp++; } while (cmdp->cmd != NULL); nntp_log(logd,(stdout,"[Th:%d,Ch:%d]NNTP cmd '%s'->%s", Wctxp->indx,Wctxp->chan, cmdp->hlp, &Wctxp->bufp[0])); return (void *) cmdp->nntp_fun; } /* *-------------------------------------------------------------------------------- */ char LIST_OF_CMD[] = "100 list of legal commands follows\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_help (WorkerContext *Wctxp) { NNTP_cmd_t *t = &NNTP_cmd[0]; char *cp= &Wctxp->MsgBuff[0]; long status; send(Wctxp->chan,LIST_OF_CMD,sizeof(LIST_OF_CMD)-1,0); while(t->cmd) { sprintf(cp,"->%s\r\n",t->hlp); cp += strlen(cp); t++; } send(Wctxp->chan,&Wctxp->MsgBuff[0],cp-(&Wctxp->MsgBuff[0]),0); send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); return 0; } /* *-------------------------------------------------------------------------------- */ char GOODBYE[] = "205 closing connection - goodbye !\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_quit (WorkerContext *Wctxp) { send(Wctxp->chan,GOODBYE,sizeof(GOODBYE)-1,0); return -1; } /* *-------------------------------------------------------------------------------- */ char SLAVE_RESP[] = "202 slave status noted\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_slav (WorkerContext *Wctxp) { send(Wctxp->chan,SLAVE_RESP,sizeof(SLAVE_RESP)-1,0); return 0; } /* *-------------------------------------------------------------------------------- */ char NO_GRP_SEL[] = "412 no newsgroup has been selected\r\n"; char ARTI_FOLLOW[] = "220 %.*s Article text follows\r\n"; char ARTI_N_FOLW[] = "220 %u %.*s article retrived-head follows\r\n"; char HEAD_FOLLOW[] = "221 %.*s Article text follows\r\n"; char HEAD_N_FOLW[] = "221 %u %.*s article retrived-head follows\r\n"; char BODY_FOLLOW[] = "222 %.*s Article text follows\r\n"; char BODY_N_FOLW[] = "222 %u %.*s article retrived-head follows\r\n"; char STAT_FOLLOW[] = "223 %.*s Article retrived-id follows\r\n%.*s\r\n"; char STAT_N_FOLW[] = "223 %u %.*s article retrived-id follows\r\n%.*s\r\n"; char NO_ART_SEL[] = "420 no current article has been slected\r\n"; char NO_SUCH_ARTS[] = "421 no such next article in this group\r\n"; char NO_SUCH_ARTP[] = "422 no such previous article in this group\r\n"; char NO_SUCH_ARTN[] = "423 no such article number in this group\r\n"; char NO_SUCH_ART[] = "430 no such article found\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_arti (WorkerContext *Wctxp) { char *cp0,*cp1; int sz,n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if( cp0 = strchr(Wctxp->bufp,'<') ) { /*Get by Message ID */ if ( cp1 = strchr(Wctxp->bufp,'>') ) if ( (cp1 - cp0) > MsgId$_len ) return 0; *(++cp1) = 0; Wctxp->MsgNumf = 0; if ( sz = MsgDBget_byId(&Wctxp->Msgrab,cp0, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,ARTI_FOLLOW,MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); send(Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)],sz,0); } else { send(Wctxp->chan,NO_SUCH_ART,sizeof(NO_SUCH_ART)-1,0); } return 0; } /*Get by Message number */ if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } n = Wctxp->MsgNum; if( cp0 = strchr(Wctxp->bufp,' ') ) if ( atoi(cp0) ) n = atoi(cp0); if ( sz = MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,ARTI_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); send(Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)],sz,0); Wctxp->MsgNum = n; Wctxp->MsgNumf= 1; } else { send(Wctxp->chan,NO_SUCH_ARTN,sizeof(NO_SUCH_ARTN)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_head (WorkerContext *Wctxp) { char *cp0,*cp1; int sz,n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if( cp0 = strchr(Wctxp->bufp,'<') ) { /*Get by Message ID */ if ( cp1 = strchr(Wctxp->bufp,'>') ) if ( (cp1 - cp0) > MsgId$_len ) return 0; *(++cp1) = 0; Wctxp->MsgNumf= 0; if ( sz = MsgDBget_byId(&Wctxp->Msgrab,cp0, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,HEAD_FOLLOW, MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); cp0 = &Wctxp->MsgBuff[sizeof(MsgKey)]; sz = strstr(cp0,"\r\n\r\n") - cp0; sz += 2; send(Wctxp->chan,cp0,sz,0); send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); } else { send(Wctxp->chan,NO_SUCH_ART,sizeof(NO_SUCH_ART)-1,0); } return 0; } /*Get by Message number */ if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } n = Wctxp->MsgNum; if( cp0 = strchr(Wctxp->bufp,' ') ) if ( atoi(cp0) ) n = atoi(cp0); if ( sz = MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,HEAD_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); cp0 = &Wctxp->MsgBuff[sizeof(MsgKey)]; sz = strstr(cp0,"\r\n\r\n") - cp0; sz += 2; send(Wctxp->chan,cp0,sz,0); send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); Wctxp->MsgNum = n; Wctxp->MsgNumf= 1; } else { send(Wctxp->chan,NO_SUCH_ARTN,sizeof(NO_SUCH_ARTN)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_body (WorkerContext *Wctxp) { char *cp0,*cp1; int sz,n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if( cp0 = strchr(Wctxp->bufp,'<') ) { /*Get by Message ID */ if ( cp1 = strchr(Wctxp->bufp,'>') ) if ( (cp1 - cp0) > MsgId$_len ) return 0; *(++cp1) = 0; Wctxp->MsgNumf= 0; if ( sz = MsgDBget_byId(&Wctxp->Msgrab,cp0, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,BODY_FOLLOW, MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); cp0 = &Wctxp->MsgBuff[sizeof(MsgKey)]; cp0 = 4+strstr(cp0,"\r\n\r\n"); sz -= (cp0-&Wctxp->MsgBuff[sizeof(MsgKey)]); send(Wctxp->chan,cp0,sz,0); } else { send(Wctxp->chan,NO_SUCH_ART,sizeof(NO_SUCH_ART)-1,0); } return 0; } /*Get by Message number */ if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } n = Wctxp->MsgNum; if( cp0 = strchr(Wctxp->bufp,' ') ) if ( atoi(cp0) ) n = atoi(cp0); if ( sz = MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,BODY_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); cp0 = &Wctxp->MsgBuff[sizeof(MsgKey)]; cp0 = 4+strstr(cp0,"\r\n\r\n"); sz -= (cp0-&Wctxp->MsgBuff[sizeof(MsgKey)]); send(Wctxp->chan,cp0,sz,0); Wctxp->MsgNumf= 1; Wctxp->MsgNum = n; } else { send(Wctxp->chan,NO_SUCH_ARTN,sizeof(NO_SUCH_ARTN)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_stat (WorkerContext *Wctxp) { char *cp0,*cp1; int sz,n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if( cp0 = strchr(Wctxp->bufp,'<') ) { /*Get by Message ID */ if ( cp1 = strchr(Wctxp->bufp,'>') ) if ( (cp1 - cp0) > MsgId$_len ) return 0; *(++cp1) = 0; Wctxp->MsgNumf= 0; if ( MsgDBget_byId(&Wctxp->Msgrab,cp0, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,STAT_FOLLOW, MsgId$_len, &mkeyp->MsgId[0], MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); } else { send(Wctxp->chan,NO_SUCH_ART,sizeof(NO_SUCH_ART)-1,0); } return 0; } /*Get by Message number */ if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } n = Wctxp->MsgNum; if( cp0 = strchr(Wctxp->bufp,' ') ) if ( atoi(cp0) ) n = atoi(cp0); if ( MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,STAT_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0], MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); Wctxp->MsgNumf= 1; Wctxp->MsgNum = n; } else { send(Wctxp->chan,NO_SUCH_ARTN,sizeof(NO_SUCH_ARTN)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ char SEND_TO_POST[] = "340 send article to be posted.End-.\r\n"; char NO_VALD_SIZE[] = "441 length article not valid\r\n"; char POST_FAIL[] = "442 posting failed\r\n"; char POST_OK[] = "240 article posting ok\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_post (WorkerContext *Wctxp) { int sz; send(Wctxp->chan,SEND_TO_POST,sizeof(SEND_TO_POST)-1,0); sz = nntp_txt_get (Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)], Msg_MaxRec-sizeof(MsgKey)-1); if (sz <= 0) { send(Wctxp->chan,NO_VALD_SIZE,sizeof(NO_VALD_SIZE)-1,0); return 0; } if ( nntp_msg_to_db (Wctxp,sz) ) sprintf(Wctxp->bufp,POST_FAIL); else sprintf(Wctxp->bufp,POST_OK); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); return 0; } /* *-------------------------------------------------------------------------------- */ char FieldFrom [ ] = {"From:"}; char FieldDate [ ] = {"Date:"}; char FieldNewsg [ ] = {"Newsgroups:"}; char FieldSubj [ ] = {"Subject:"}; char FieldMID [ ] = {"Message-ID:"}; char FieldPath [ ] = {"Path:"}; /* *-------------------------------------------------------------------------------- */ int nntp_msg_to_db (WorkerContext *Wctxp,int sz) { int nntp_msg_hdr_valid (WorkerContext *,int); MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; char *msgp = (char *) &Wctxp->MsgBuff[sizeof(MsgKey)]; char *cp0,*cp1; if ( 0 > (sz = nntp_msg_hdr_valid (Wctxp,sz)) ) return -1; memset(mkeyp,0,sizeof(MsgKey)); /* Extract Message-ID field */ if ( NULL == (cp0 = strstr(msgp,FieldMID)) ) return -1; cp0 += sizeof(FieldMID); cp1 = strpbrk(cp0,"\r\t"); if ( (cp1-cp0) > MsgId$_len ) return -1; strncpy(mkeyp->MsgId,cp0,cp1-cp0); /* Extract Date: field */ /* if ( NULL == (cp0 = strstr(msgp,FieldDate)) ) return -1; cp0 += sizeof(FieldDate); cp1 = strpbrk(cp0,"\r\t"); if ( (cp1-cp0) > MsgId$_len ) return -1; strncpy(Wctxp->bufp,cp0,cp1-cp0); Wctxp->bufp[cp1-cp0] = 0; */ time(&mkeyp->Date); /* = cvt_rfc_to_vms (Wctxp->bufp); */ /* Extract NewsGroups: field */ if ( NULL == (cp0 = strstr(msgp,FieldNewsg)) ) return -1; cp0 += sizeof(FieldNewsg); cp1 = strpbrk(cp0,"\r\t"); if ( (cp1-cp0) > (sizeof(Wctxp->bufp) - 1) ) return -1; strncpy(Wctxp->bufp,cp0,cp1-cp0); Wctxp->bufp[cp1-cp0] = 0; /* Field MsgKey.Date,MsgKey.Id is filled */ Wctxp->MsgNumf= 0; for (cp0=Wctxp->bufp,cp0=strtok(Wctxp->bufp," ,"); cp0 != NULL; cp0=strtok(NULL," ,")) { if ( strlen (cp0) > GrpName$_len ) continue; if ( !match_in_list (nntp_conf.GrpME,cp0) ) continue; if ( DBins (&Wctxp->Grprab,&Wctxp->Msgrab,cp0,mkeyp->Date, &Wctxp->MsgBuff[0],sz) ) nntp_log(logd,(stdout,"[Th:%d,Ch:%d]Error insert to DB.%.*s\n", Wctxp->indx,Wctxp->chan, MsgId$_len,&Wctxp->MsgBuff[sizeof(MsgKey)])); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_msg_hdr_valid (WorkerContext *Wctxp,int sz) { char *msgp = (char *) &Wctxp->MsgBuff[sizeof(MsgKey)]; char *cp0,*cp1; char buf [ 256 ]; time_t t; int sz0; if ( NULL == strstr (msgp,FieldFrom) ) return -1; if ( NULL == strstr (msgp,FieldSubj) ) return -1; if ( NULL == strstr (msgp,FieldMID) ) return -1; if ( NULL == strstr (msgp,FieldNewsg) ) return -1; /* Check and validate Date field */ if ( NULL == (cp0 = strstr(msgp,FieldDate)) ) { time(&t); sprintf(buf,"Date: %s\r\n",cvt_vms_to_rfc(t,&buf[128], nntp_conf.LocalTZ)); sz0 = strlen(buf); if ( (sz0+sz) > sizeof(Wctxp->MsgBuff) ) return -1; memmove(msgp+sz0,msgp,sz); memcpy (msgp,buf,sz0); sz += sz0; } /* Check and validate Path field */ if ( NULL == (cp0 = strstr(msgp,FieldPath)) ) { sz0 = sprintf(buf,"Path: %s\r\n",nntp_conf.LocalHost); if ( (sz0+sz) > sizeof(Wctxp->MsgBuff) ) return -1; memmove(msgp+sz0,msgp,sz); memcpy (msgp,buf,sz0); return (sz+sz0); } cp0 += sizeof(FieldPath); sz0 = sprintf(buf,"%s!",nntp_conf.LocalHost); /*@RRL? */ if ( (sz0+sz) > sizeof(Wctxp->MsgBuff) ) return -1; memmove(cp0+sz0,cp0,sz); memcpy (cp0,buf,sz0); return (sz+sz0); } /* *-------------------------------------------------------------------------------- */ char LIST_GRP[] = "215 list of newsgroups follows\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_list (WorkerContext *Wctxp) { char *cp = &Wctxp->MsgBuff[0]; int flag = 0; int sz0 = 0,sz1 = 0; GrpKey *gk = (GrpKey *) &Wctxp->bufp[0]; send(Wctxp->chan,LIST_GRP,sizeof(LIST_GRP)-1,0); while( GrpDBget_seq(&Wctxp->Grprab,(char *) gk,flag++) ) { sprintf(cp,"%.*s %d %d %c\r\n", GrpName$_len, gk->GrpName, gk->Last, gk->First, gk->PostFlag); sz0 = strlen(cp); cp += sz0; sz1 += sz0; if ( sz1 > (sizeof(Wctxp->MsgBuff[0]) - 256) ) { send(Wctxp->chan,Wctxp->MsgBuff,sz1,0); cp = &Wctxp->MsgBuff[0]; sz0 = sz1 = 0; } } send(Wctxp->chan,Wctxp->MsgBuff,sz1,0); send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); return 0; } /* *-------------------------------------------------------------------------------- */ char ALRDY_SEEN[] = "435 Already seen that one,where you been\r\n"; char NEWS_TO_ME[] = "335 News to me!End-..\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_ihav (WorkerContext *Wctxp) { int sz; char *cp0,*cp1; if ( NULL == (cp0 = strchr(Wctxp->bufp,'<')) ) return 0; if ( NULL == (cp1 = strchr(cp0,'>')) ) return 0; if ( (cp1 - cp0) > MsgId$_len ) return 0; *(++cp1) = 0; Wctxp->MsgNumf= 0; if (!MsgDBfind_byId(&Wctxp->Msgrab,cp0,cp1-cp0) ) { send(Wctxp->chan,ALRDY_SEEN,sizeof(ALRDY_SEEN)-1,0); return 0; } send(Wctxp->chan,NEWS_TO_ME,sizeof(NEWS_TO_ME)-1,0); sz = nntp_txt_get (Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)], Msg_MaxRec-sizeof(MsgKey)-1); if ( sz <= 0 ) { send(Wctxp->chan,NO_VALD_SIZE,sizeof(NO_VALD_SIZE)-1,0); return 0; } nntp_log(logd,(stdout,"[Th:%d,Ch:%d]Message to post follows\n%s", Wctxp->indx,Wctxp->chan,&Wctxp->MsgBuff[sizeof(MsgKey)])); if ( nntp_msg_to_db (Wctxp,sz) ) sprintf(Wctxp->bufp,POST_FAIL); else sprintf(Wctxp->bufp,POST_OK); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); return 0; } /* *-------------------------------------------------------------------------------- */ char NO_SUCH_GRP[] = "411 no such news group\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_grou (WorkerContext *Wctxp) { char *cp = &Wctxp->bufp[0]; int sz = 0; GrpKey *gk = (GrpKey *) &Wctxp->MsgBuff[0]; if ( 2 == (sscanf (cp,"%s %s",cp,cp)) ) { nntp_log(logd,(stdout,"[Th:%d,Ch:%d]Groups:%s", Wctxp->indx,Wctxp->chan,cp)); if ( sz = GrpDBget (&Wctxp->Grprab,cp, (char *) gk) ) { sprintf(cp,"211 0%d 0%d 0%d %.*s group selected\r\n", (gk->Last-gk->First)+1, gk->First, gk->Last, GrpName$_len, gk->GrpName); strncpy(&Wctxp->Grp[0],gk->GrpName,GrpName$_len); Wctxp->MsgNum = gk->First; Wctxp->MsgNumf= 0; } else sprintf(cp,NO_SUCH_GRP); } else sprintf(cp,NO_SUCH_GRP); send(Wctxp->chan,cp,strlen(cp),0); return 0; } /* *-------------------------------------------------------------------------------- */ char NEW_GRP[] = "231 list of newsgroups since %s follows\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_newg (WorkerContext *Wctxp) { char *cp = &Wctxp->bufp[0]; char *cp0= &Wctxp->MsgBuff[0]; int sz0,sz1,flag = 0; time_t t; GrpKey *gk = (GrpKey *) &Wctxp->bufp[0]; if ( cp = strchr (cp,' ') ) { if ( t = cvt_nntp_to_vms(cp) ) { *(strchr(cp,'\r')) = 0; sprintf(cp0,NEW_GRP,cp); send(Wctxp->chan,cp0,strlen(cp0),0); cp = &Wctxp->MsgBuff[0]; sz0 = sz1 = 0; while(GrpDBget_seq(&Wctxp->Grprab, (char *) gk,flag++) ) { if (t > gk->DateCr) continue; sprintf(cp,"%.*s %d %d %c\r\n", GrpName$_len, gk->GrpName, gk->Last, gk->First, gk->PostFlag); sz0 = strlen(cp); cp += sz0; sz1 += sz0; if ( sz1 > (sizeof(Wctxp->MsgBuff[0]) - 256) ) { send(Wctxp->chan,Wctxp->MsgBuff,sz1,0); cp = &Wctxp->MsgBuff[0]; sz0 = sz1 = 0; } } }; } send(Wctxp->chan,Wctxp->MsgBuff,sz1,0); send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); return 0; } /* *-------------------------------------------------------------------------------- */ char DATA_FOLLOWS[] = "224 data follows\r\n"; char XOVER_DATA[] = "%s\t%.*s\t%.*s\t%s\t%.*\r\n"; /* *-------------------------------------------------------------------------------- */ /* Extract the headers, remove tab and nl's, the headers we want are: artid|subject|From|Date|Message-Id */ /* *-------------------------------------------------------------------------------- */ int nntp_xove (WorkerContext *Wctxp) { char *cp0,*cp1,*cp2; unsigned sz,from = 0,to = 0,i; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; GrpKey *gkeyp = (GrpKey *) &Wctxp->MsgBuff[0]; char lkey [MsgGrp$_len]; char buf [ 128 ]; if ( 0 > GrpDBget(&Wctxp->Grprab,&Wctxp->Grp[0],(char *) gkeyp)) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } from = to = gkeyp->First; if ( cp0 = strchr(&Wctxp->bufp[0],' ') ) { cp0++; from = atoi(cp0); if ( cp0 = strchr(cp0,'-') ) { cp0++; to = atoi(cp0); } } from = max (from,gkeyp->First); to = min (to ,gkeyp->Last); send(Wctxp->chan,DATA_FOLLOWS,sizeof(DATA_FOLLOWS)-1,0); lkey[0] = 0; for (i = from; i <= to; i++) { if (0 > (sz = MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],i, &Wctxp->MsgBuff[0], sizeof(Wctxp->MsgBuff))) ) break; Wctxp->MsgBuff[sz+sizeof(MsgKey)] = 0; /*Article Number */ sz = sprintf(&Wctxp->bufp[0],"%lu \t",i); /*Article 'Subj' Field */ sz += sprintf(&Wctxp->bufp[sz],"%s\t", strtok_val (&Wctxp->MsgBuff[sizeof(MsgKey)],&buf[0], FieldSubj, "\r\t\n", 64)); /*Article 'From' Field */ sz += sprintf(&Wctxp->bufp[sz],"%s\t", strtok_val (&Wctxp->MsgBuff[sizeof(MsgKey)],&buf[0], FieldFrom, "\r\t\n", 64)); /*Article 'Date' Field */ sz += sprintf(&Wctxp->bufp[sz],"%s\t", strtok_val (&Wctxp->MsgBuff[sizeof(MsgKey)],&buf[0], FieldDate, "\r\t\n", 64)); /*Article 'Msg-ID' Field */ sz += sprintf(&Wctxp->bufp[sz],"%.*s\t\t\t\t\r\n", MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,sz,0); } send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_last (WorkerContext *Wctxp) { int n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } if ( !Wctxp->MsgNum ) { send(Wctxp->chan,NO_ART_SEL,sizeof(NO_ART_SEL)-1,0); return 0; } n = Wctxp->MsgNum; n--; Wctxp->MsgNumf= 0; if ( MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,STAT_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0], MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); Wctxp->MsgNum = n; } else { send(Wctxp->chan,NO_SUCH_ARTP,sizeof(NO_SUCH_ARTP)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ int nntp_next (WorkerContext *Wctxp) { int n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; if ( !Wctxp->Grp[0] ) { send(Wctxp->chan,NO_GRP_SEL,sizeof(NO_GRP_SEL)-1,0); return 0; } if ( !Wctxp->MsgNum ) { send(Wctxp->chan,NO_ART_SEL,sizeof(NO_ART_SEL)-1,0); return 0; } n = Wctxp->MsgNum; n++; Wctxp->MsgNumf= 0; if ( MsgDBget_byNum(&Wctxp->Msgrab,&Wctxp->Grp[0],n, &Wctxp->MsgBuff[0],sizeof(Wctxp->MsgBuff)) ) { sprintf(Wctxp->bufp,STAT_N_FOLW, n, MsgId$_len, &mkeyp->MsgId[0], MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); Wctxp->MsgNum = n; } else { send(Wctxp->chan,NO_SUCH_ARTS,sizeof(NO_SUCH_ARTS)-1,0); } return 0; } /* *-------------------------------------------------------------------------------- */ char NEW_NEWS[] = "230 list of news since %s follows\r\n"; /* *-------------------------------------------------------------------------------- */ int nntp_newn (WorkerContext *Wctxp) { int n; MsgKey *mkeyp = (MsgKey *) &Wctxp->MsgBuff[0]; GrpKey gk; char *lp = &Wctxp->bufp[0],*cp; time_t t; int flag_g; char MsgId [ MsgId$_len + 3 ]; char lkey [MsgGrp$_len]; if ( NULL == (lp = strchr (lp,' ')) ) return 0; n = strspn (lp," "); lp += n; if ( NULL == (cp = strchr (lp,' ')) ) return 0; *cp = 0; cp++; if ( !(t = cvt_nntp_to_vms(cp)) ) return 0; sprintf((char *) mkeyp,NEW_NEWS,cp); send(Wctxp->chan,(char *) mkeyp ,strlen((char *) mkeyp),0); flag_g = 0; while( GrpDBget_seq(&Wctxp->Grprab,(char *) &gk,flag_g++) ) { printf("\ngk.Grp = %s",gk.GrpName); if ( match_in_list (lp,&gk.GrpName[0]) ) { lkey [0] = 0; while( 0 < MsgDBget_byRange(&Wctxp->Msgrab, &gk.GrpName[0], gk.First, gk.Last, (char *) mkeyp, sizeof(MsgKey)+1, &lkey[0]) ) { if ( t <= mkeyp->Date ) { sprintf(&MsgId[0],"%.*s\r\n",MsgId$_len, &mkeyp->MsgId[0]); send(Wctxp->chan,MsgId,strlen(MsgId),0); } } } } send(Wctxp->chan,NNTP_EOT,sizeof(NNTP_EOT)-1,0); return 0; }