--- sbbs/src/sbbs3/pack_qwk.cpp 2018/04/24 16:41:23 1.1.1.1 +++ sbbs/src/sbbs3/pack_qwk.cpp 2018/04/24 16:42:34 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet pack QWK packet routine */ -/* $Id: pack_qwk.cpp,v 1.1.1.1 2018/04/24 16:41:23 root Exp $ */ +/* $Id: pack_qwk.cpp,v 1.1.1.2 2018/04/24 16:42:34 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -43,16 +43,17 @@ /****************************************************************************/ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack) { - char str[MAX_PATH+1],ch,*p; + char str[MAX_PATH+1],ch; char tmp[MAX_PATH+1],tmp2[MAX_PATH+1]; char* fname; - char* fmode; int mode; uint i,j,k,conf; - long l,size,msgndx,posts,ex; - long mailmsgs=0; - ulong totalcdt,totaltime,lastmsg + long l,size,msgndx,ex; + int32_t posts; + int32_t mailmsgs=0; + ulong totalcdt,totaltime ,files,submsgs,msgs,netfiles=0,preqwk=0; + uint32_t lastmsg; ulong subs_scanned=0; float f; /* Sparky is responsible */ time_t start; @@ -61,21 +62,24 @@ bool sbbs_t::pack_qwk(char *packet, ulon post_t *post; glob_t g; FILE *stream,*qwk,*personal,*ndx; + FILE* hdrs=NULL; DIR* dir; DIRENT* dirent; struct tm tm; smbmsg_t msg; + const char* p; + const char* fmode; - ex=EX_OUTL|EX_OUTR; /* Need sh for wildcard expansion */ + ex=EX_STDOUT; if(prepack) ex|=EX_OFFLINE; delfiles(cfg.temp_dir,ALLFILES); - sprintf(str,"%sfile/%04u.qwk",cfg.data_dir,useron.number); + SAFEPRINTF2(str,"%sfile/%04u.qwk",cfg.data_dir,useron.number); if(fexistcase(str)) { for(k=0;kext,useron.tmpext) - && chk_ar(cfg.fextr[k]->ar,&useron)) + && chk_ar(cfg.fextr[k]->ar,&useron,&client)) break; if(k>=cfg.total_fextrs) k=0; @@ -106,7 +110,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon /***************************/ /* Create CONTROL.DAT file */ /***************************/ - sprintf(str,"%sCONTROL.DAT",cfg.temp_dir); + SAFEPRINTF(str,"%sCONTROL.DAT",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_OPEN,str,0); return(false); @@ -135,11 +139,11 @@ bool sbbs_t::pack_qwk(char *packet, ulon for(i=0;igrp]->sname ,cfg.sub[usrsub[i][j]]->lname); else /* 10 char max */ - strcpy(confname,cfg.sub[usrsub[i][j]]->qwkname); + SAFECOPY(confname,cfg.sub[usrsub[i][j]]->qwkname); fprintf(stream,"%u\r\n%s\r\n" ,cfg.sub[usrsub[i][j]]->qwkconf ? cfg.sub[usrsub[i][j]]->qwkconf : ((i+1)*1000)+j+1,confname); @@ -149,7 +153,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon /***********************/ /* Create DOOR.ID File */ /***********************/ - sprintf(str,"%sDOOR.ID",cfg.temp_dir); + SAFEPRINTF(str,"%sDOOR.ID",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_OPEN,str,0); return(false); @@ -166,7 +170,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon "%sFILES\r\n" "%sATTACH\r\n" "%sOWN\r\n" - "%smail\r\n" + "%sMAIL\r\n" "%sDELMAIL\r\n" "%sCTRL-A\r\n" "%sFREQ\r\n" @@ -188,7 +192,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon /***********************/ /* Create NETFLAGS.DAT */ /***********************/ - sprintf(str,"%sNETFLAGS.DAT",cfg.temp_dir); + SAFEPRINTF(str,"%sNETFLAGS.DAT",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_CREATE,str,0); return(false); @@ -201,10 +205,70 @@ bool sbbs_t::pack_qwk(char *packet, ulon } } + if(useron.qwk&QWK_EXT) { + /****************************/ + /* Create TOREADER.EXT file */ + /****************************/ + SAFEPRINTF(str,"%sTOREADER.EXT",cfg.temp_dir); + if((stream=fopen(str,"wb"))==NULL) { + errormsg(WHERE,ERR_OPEN,str,0); + return(false); + } + + fprintf(stream,"ALIAS %s\r\n", useron.alias); + + /* Double-checked with multimail (qwk.cc): */ + for(i=0;iqwkconf ? cfg.sub[usrsub[i][j]]->qwkconf : ((i+1)*1000)+j+1); + switch(subscan[usrsub[i][j]].cfg&(SUB_CFG_NSCAN|SUB_CFG_YSCAN)) { + case SUB_CFG_NSCAN|SUB_CFG_YSCAN: + fputc('p', stream); // p for personal messages + break; + case SUB_CFG_NSCAN: + fputc('a', stream); // a for all messages + break; + } + switch(cfg.sub[usrsub[i][j]]->misc&(SUB_PRIV|SUB_PONLY)) { + case SUB_PRIV|SUB_PONLY: + fputc('P', stream); // P if the area is private mail only + break; + case SUB_PRIV: + fputc('X', stream); // X if either private or public mail is allowed + break; + default: + fputc('O', stream); // O if the area is public mail only + break; + } + if(useron.qwk&QWK_BYSELF) + fputc('w', stream); // w if this area should include mail written by themselves + if(cfg.sub[usrsub[i][j]]->misc&SUB_FORCED) + fputc('F', stream); // F if this area is forced to be read + if(!chk_ar(cfg.sub[usrsub[i][j]]->post_ar,&useron,&client)) + fputc('R', stream); // R if the area is read-only (no posting at all allowed) + if(cfg.sub[usrsub[i][j]]->misc&SUB_QNET) + fputc('Q', stream); // I if the area is an internet area + if(cfg.sub[usrsub[i][j]]->misc&SUB_INET) + fputc('I', stream); // I if the area is an internet area + if(cfg.sub[usrsub[i][j]]->misc&SUB_FIDO) + fputc('E', stream); // E if the area is an echomail area + if((cfg.sub[usrsub[i][j]]->misc&(SUB_FIDO|SUB_INET|SUB_QNET))==0) + fputc('L', stream); // L if the area is a local message area + if((cfg.sub[usrsub[i][j]]->misc&SUB_NAME)==0) + fputc('H', stream); // H if the area is an handles only message area + if(cfg.sub[usrsub[i][j]]->misc&SUB_ANON) + fputc('A', stream); // A if the area allows messages 'from' any name (pick-an-alias) + + fprintf(stream,"\r\n"); + } + fclose(stream); + } + /****************************************************/ /* Create MESSAGES.DAT, write header and leave open */ /****************************************************/ - sprintf(str,"%sMESSAGES.DAT",cfg.temp_dir); + SAFEPRINTF(str,"%sMESSAGES.DAT",cfg.temp_dir); if(fexistcase(str)) fmode="r+b"; else @@ -213,7 +277,15 @@ bool sbbs_t::pack_qwk(char *packet, ulon errormsg(WHERE,ERR_OPEN,str,0); return(false); } - l=filelength(fileno(qwk)); + if(useron.qwk&QWK_HEADERS) { + SAFEPRINTF(str,"%sHEADERS.DAT",cfg.temp_dir); + if((hdrs=fopen(str,"a"))==NULL) { + fclose(qwk); + errormsg(WHERE,ERR_OPEN,str,0); + return(false); + } + } + l=(long)filelength(fileno(qwk)); if(l<1) { fprintf(qwk,"%-128.128s","Produced by " VERSION_NOTICE " " COPYRIGHT_NOTICE); msgndx=1; @@ -221,7 +293,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon msgndx=l/QWK_BLOCK_LEN; fseek(qwk,0,SEEK_END); } - sprintf(str,"%sNEWFILES.DAT",cfg.temp_dir); + SAFEPRINTF(str,"%sNEWFILES.DAT",cfg.temp_dir); remove(str); if(!(useron.rest&FLAG('T')) && useron.qwk&QWK_FILES) files=create_filelist("NEWFILES.DAT",FL_ULTIME); @@ -234,9 +306,11 @@ bool sbbs_t::pack_qwk(char *packet, ulon useron.qwk|=(QWK_EMAIL|QWK_ALLMAIL|QWK_DELMAIL); if(!(useron.qwk&QWK_NOINDEX)) { - sprintf(str,"%sPERSONAL.NDX",cfg.temp_dir); + SAFEPRINTF(str,"%sPERSONAL.NDX",cfg.temp_dir); if((personal=fopen(str,"ab"))==NULL) { fclose(qwk); + if(hdrs!=NULL) + fclose(hdrs); errormsg(WHERE,ERR_OPEN,str,0); return(false); } @@ -245,11 +319,13 @@ bool sbbs_t::pack_qwk(char *packet, ulon personal=NULL; if(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL) /* && !prepack */) { - sprintf(smb.file,"%smail",cfg.data_dir); + SAFEPRINTF(smb.file,"%smail",cfg.data_dir); smb.retry_time=cfg.smb_retry_time; smb.subnum=INVALID_SUB; if((i=smb_open(&smb))!=0) { fclose(qwk); + if(hdrs!=NULL) + fclose(hdrs); if(personal) fclose(personal); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); @@ -262,12 +338,14 @@ bool sbbs_t::pack_qwk(char *packet, ulon qwkmail_last=0; mail=loadmail(&smb,&mailmsgs,useron.number,0,useron.qwk&QWK_ALLMAIL ? 0 : LM_UNREAD); - if(mailmsgs && !(sys_status&SS_ABORT)) { + if(mailmsgs && (online==ON_LOCAL || !(sys_status&SS_ABORT))) { bputs(text[QWKPackingEmail]); if(!(useron.qwk&QWK_NOINDEX)) { - sprintf(str,"%s000.NDX",cfg.temp_dir); + SAFEPRINTF(str,"%s000.NDX",cfg.temp_dir); if((ndx=fopen(str,"ab"))==NULL) { fclose(qwk); + if(hdrs!=NULL) + fclose(hdrs); if(personal) fclose(personal); smb_close(&smb); @@ -296,14 +374,14 @@ bool sbbs_t::pack_qwk(char *packet, ulon continue; if(msg.hdr.auxattr&MSG_FILEATTACH && useron.qwk&QWK_ATTACH) { - sprintf(str,"%sfile/%04u.in/%s" + SAFEPRINTF3(str,"%sfile/%04u.in/%s" ,cfg.data_dir,useron.number,msg.subj); - sprintf(tmp,"%s%s",cfg.temp_dir,msg.subj); + SAFEPRINTF2(tmp,"%s%s",cfg.temp_dir,msg.subj); if(fexistcase(str) && !fexistcase(tmp)) - mv(str,tmp,1); + mv(str,tmp,/* copy: */TRUE); } - size=msgtoqwk(&msg,qwk,mode,INVALID_SUB,0); + size=msgtoqwk(&msg,qwk,mode,INVALID_SUB,0,hdrs); smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); if(ndx) { @@ -337,7 +415,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon if(subscan[usrsub[i][j]].cfg&SUB_CFG_NSCAN || (!(useron.rest&FLAG('Q')) && cfg.sub[usrsub[i][j]]->misc&SUB_FORCED)) { - if(!chk_ar(cfg.sub[usrsub[i][j]]->read_ar,&useron)) + if(!chk_ar(cfg.sub[usrsub[i][j]]->read_ar,&useron,&client)) continue; lncntr=0; /* defeat pause */ if(useron.rest&FLAG('Q') && !(cfg.sub[usrsub[i][j]]->misc&SUB_QNET)) @@ -357,7 +435,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon continue; } - sprintf(smb.file,"%s%s" + SAFEPRINTF2(smb.file,"%s%s" ,cfg.sub[usrsub[i][j]]->data_dir,cfg.sub[usrsub[i][j]]->code); smb.retry_time=cfg.smb_retry_time; smb.subnum=usrsub[i][j]; @@ -387,9 +465,11 @@ bool sbbs_t::pack_qwk(char *packet, ulon conf=((i+1)*1000)+j+1; if(!(useron.qwk&QWK_NOINDEX)) { - sprintf(str,"%s%u.NDX",cfg.temp_dir,conf); + SAFEPRINTF2(str,"%s%u.NDX",cfg.temp_dir,conf); if((ndx=fopen(str,"ab"))==NULL) { fclose(qwk); + if(hdrs!=NULL) + fclose(hdrs); if(personal) fclose(personal); smb_close(&smb); @@ -433,7 +513,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon else mode&=~(QM_TAGLINE|QM_TO_QNET); - size=msgtoqwk(&msg,qwk,mode,usrsub[i][j],conf); + size=msgtoqwk(&msg,qwk,mode,usrsub[i][j],conf,hdrs); smb_unlockmsghdr(&smb,&msg); if(ndx) { @@ -466,7 +546,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon bprintf(text[QWKPackedSubboard],submsgs,(*msgcnt)); if(ndx) { fclose(ndx); - sprintf(str,"%s%u.NDX",cfg.temp_dir,conf); + SAFEPRINTF2(str,"%s%u.NDX",cfg.temp_dir,conf); if(!flength(str)) remove(str); } @@ -495,7 +575,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon ,ftell(qwk) ,time(NULL)-start ,((*msgcnt)+mailmsgs)/(time(NULL)-start)); - sprintf(str,"Packed %lu messages (%lu bytes) in %lu seconds (%lu msgs/sec)" + SAFEPRINTF4(str,"Packed %lu messages (%lu bytes) in %lu seconds (%lu msgs/sec)" ,(*msgcnt)+mailmsgs ,ftell(qwk) ,(ulong)(time(NULL)-start) @@ -507,32 +587,39 @@ bool sbbs_t::pack_qwk(char *packet, ulon } fclose(qwk); /* close MESSAGE.DAT */ + if(hdrs!=NULL) + fclose(hdrs); /* close HEADERS.DAT */ if(personal) { fclose(personal); /* close PERSONAL.NDX */ - sprintf(str,"%sPERSONAL.NDX",cfg.temp_dir); + SAFEPRINTF(str,"%sPERSONAL.NDX",cfg.temp_dir); if(!flength(str)) remove(str); } CRLF; - if(!prepack && (sys_status&SS_ABORT || !online)) + if(!prepack && online!=ON_LOCAL && ((sys_status&SS_ABORT) || !online)) { + bputs(text[Aborted]); return(false); + } if(/*!prepack && */ useron.rest&FLAG('Q')) { /* If QWK Net node, check for files */ - sprintf(str,"%sqnet/%s.out/",cfg.data_dir,useron.alias); + char id[LEN_QWKID+1]; + SAFECOPY(id,useron.alias); + strlwr(id); + SAFEPRINTF2(str,"%sqnet/%s.out/",cfg.data_dir,id); dir=opendir(str); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { /* Move files into temp dir */ - sprintf(str,"%sqnet/%s.out/%s",cfg.data_dir,useron.alias,dirent->d_name); + SAFEPRINTF3(str,"%sqnet/%s.out/%s",cfg.data_dir,id,dirent->d_name); if(isdir(str)) continue; - sprintf(tmp2,"%s%s",cfg.temp_dir,dirent->d_name); - lncntr=0; /* Default pause */ + SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,dirent->d_name); + lncntr=0; /* Defeat pause */ if(online==ON_LOCAL) eprintf(LOG_INFO,"Including %s in packet",str); else lprintf(LOG_INFO,"Including %s in packet",str); bprintf(text[RetrievingFile],str); - if(!mv(str,tmp2,1)) + if(!mv(str,tmp2,/* copy: */TRUE)) netfiles++; } if(dir!=NULL) @@ -543,7 +630,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon if(batdn_total) { for(i=0,totalcdt=0;iuseron.cdt+useron.freecdt) { bprintf(text[YouOnlyHaveNCredits] @@ -560,17 +647,17 @@ bool sbbs_t::pack_qwk(char *packet, ulon for(i=0;iseqdev); bprintf(text[RetrievingFile],tmp); - sprintf(str,"%s%s" + SAFEPRINTF2(str,"%s%s" ,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths ? cfg.altpath[batdn_alt[i]-1] : cfg.dir[batdn_dir[i]]->path ,tmp); - mv(str,tmp2,1); /* copy the file to temp dir */ - getnodedat(cfg.node_num,&thisnode,1); + mv(str,tmp2,/* copy: */TRUE); /* copy the file to temp dir */ + getnodedat(cfg.node_num,&thisnode,/* copy: */TRUE); thisnode.aux=0xfe; putnodedat(cfg.node_num,&thisnode); CRLF; @@ -590,30 +677,30 @@ bool sbbs_t::pack_qwk(char *packet, ulon /***********************/ /* packets */ /* Copy QWK Text files */ /***********************/ - sprintf(str,"%sQWK/HELLO",cfg.text_dir); + SAFEPRINTF(str,"%sQWK/HELLO",cfg.text_dir); if(fexistcase(str)) { - sprintf(tmp2,"%sHELLO",cfg.temp_dir); - mv(str,tmp2,1); + SAFEPRINTF(tmp2,"%sHELLO",cfg.temp_dir); + mv(str,tmp2,/* copy: */TRUE); } - sprintf(str,"%sQWK/BBSNEWS",cfg.text_dir); + SAFEPRINTF(str,"%sQWK/BBSNEWS",cfg.text_dir); if(fexistcase(str)) { - sprintf(tmp2,"%sBBSNEWS",cfg.temp_dir); - mv(str,tmp2,1); + SAFEPRINTF(tmp2,"%sBBSNEWS",cfg.temp_dir); + mv(str,tmp2,/* copy: */TRUE); } - sprintf(str,"%sQWK/GOODBYE",cfg.text_dir); + SAFEPRINTF(str,"%sQWK/GOODBYE",cfg.text_dir); if(fexistcase(str)) { - sprintf(tmp2,"%sGOODBYE",cfg.temp_dir); - mv(str,tmp2,1); + SAFEPRINTF(tmp2,"%sGOODBYE",cfg.temp_dir); + mv(str,tmp2,/* copy: */TRUE); } - sprintf(str,"%sQWK/BLT-*",cfg.text_dir); + SAFEPRINTF(str,"%sQWK/BLT-*",cfg.text_dir); glob(str,0,NULL,&g); for(i=0;i<(uint)g.gl_pathc;i++) { /* Copy BLT-*.* files */ fname=getfname(g.gl_pathv[i]); padfname(fname,str); if(isdigit(str[4]) && isdigit(str[9])) { - sprintf(str,"%sQWK/%s",cfg.text_dir,fname); - sprintf(tmp2,"%s%s",cfg.temp_dir,fname); - mv(str,tmp2,1); + SAFEPRINTF2(str,"%sQWK/%s",cfg.text_dir,fname); + SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,fname); + mv(str,tmp2,/* copy: */TRUE); } } globfree(&g); @@ -633,7 +720,7 @@ bool sbbs_t::pack_qwk(char *packet, ulon /*******************/ /* Compress Packet */ /*******************/ - sprintf(tmp2,"%s%s",cfg.temp_dir,ALLFILES); + SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,ALLFILES); i=external(cmdstr(temp_cmd(),packet,tmp2,NULL) ,ex|EX_WILDCARD); if(!fexist(packet)) { @@ -641,35 +728,16 @@ bool sbbs_t::pack_qwk(char *packet, ulon if(i) errormsg(WHERE,ERR_EXEC,cmdstr(temp_cmd(),packet,tmp2,NULL),i); else - errorlog("Couldn't compress QWK packet"); - return(false); - } - - if(prepack) /* Early return if pre-packing */ - return(true); - - l=flength(packet); - sprintf(str,"%s.qwk",cfg.sys_id); - bprintf(text[FiFilename],str); - bprintf(text[FiFileSize],ultoac(l,tmp)); - if(l>0L && cur_cps) - i=l/(ulong)cur_cps; - else - i=0; - bprintf(text[FiTransferTime],sectostr(i,tmp)); - CRLF; - if(!(useron.exempt&FLAG('T')) && i>timeleft) { - bputs(text[NotEnoughTimeToDl]); + lprintf(LOG_ERR, "Couldn't compress QWK packet"); return(false); } - if(useron.rest&FLAG('Q')) { - sprintf(str,"%s.qwk",cfg.sys_id); + if(!prepack && useron.rest&FLAG('Q')) { dir=opendir(cfg.temp_dir); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { - if(!stricmp(str,dirent->d_name)) /* QWK packet */ + if(!stricmp(getfname(packet),dirent->d_name)) /* QWK packet */ continue; - sprintf(tmp,"%s%s",cfg.temp_dir,dirent->d_name); + SAFEPRINTF2(tmp,"%s%s",cfg.temp_dir,dirent->d_name); if(!isdir(tmp)) remove(tmp); }