bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack) { char str[MAX_PATH+1],ch,*p; 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 ,files,submsgs,msgs,netfiles=0,preqwk=0; ulong subs_scanned=0; float f; /* Sparky is responsible */ time_t start; node_t node; mail_t *mail; post_t *post; glob_t g; FILE *stream,*qwk,*personal,*ndx; DIR* dir; DIRENT* dirent; struct tm tm; smbmsg_t msg; ex=EX_OUTL|EX_OUTR; /* Need sh for wildcard expansion */ if(prepack) ex|=EX_OFFLINE; delfiles(cfg.temp_dir,ALLFILES); sprintf(str,"%sfile/%04u.qwk",cfg.data_dir,useron.number); if(fexistcase(str)) { for(k=0;k<cfg.total_fextrs;k++) if(!stricmp(cfg.fextr[k]->ext,useron.tmpext) && chk_ar(cfg.fextr[k]->ar,&useron)) break; if(k>=cfg.total_fextrs) k=0; p=cmdstr(cfg.fextr[k]->cmd,str,ALLFILES,NULL); if((i=external(p,ex))==0) preqwk=1; else errormsg(WHERE,ERR_EXEC,p,i); } if(useron.rest&FLAG('Q') && useron.qwk&QWK_RETCTLA) useron.qwk|=(QWK_NOINDEX|QWK_NOCTRL|QWK_VIA|QWK_TZ|QWK_MSGID); if(useron.qwk&QWK_EXPCTLA) mode=A_EXPAND; else if(useron.qwk&QWK_RETCTLA) mode=A_LEAVE; else mode=0; if(useron.qwk&QWK_TZ) mode|=QM_TZ; if(useron.qwk&QWK_VIA) mode|=QM_VIA; if(useron.qwk&QWK_MSGID) mode|=QM_MSGID; (*msgcnt)=0L; if(/* !prepack && */ !(useron.qwk&QWK_NOCTRL)) { /***************************/ /* Create CONTROL.DAT file */ /***************************/ sprintf(str,"%sCONTROL.DAT",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_OPEN,str,0); return(false); } now=time(NULL); if(localtime_r(&now,&tm)==NULL) return(false); fprintf(stream,"%s\r\n%s\r\n%s\r\n%s, Sysop\r\n0000,%s\r\n" "%02u-%02u-%u,%02u:%02u:%02u\r\n" ,cfg.sys_name ,cfg.sys_location ,cfg.node_phone ,cfg.sys_op ,cfg.sys_id ,tm.tm_mon+1,tm.tm_mday,tm.tm_year+1900 ,tm.tm_hour,tm.tm_min,tm.tm_sec); k=0; for(i=0;i<usrgrps;i++) for(j=0;j<usrsubs[i];j++) k++; /* k is how many subs */ fprintf(stream,"%s\r\n\r\n0\r\n0\r\n%u\r\n",useron.alias,k); fprintf(stream,"0\r\nE-mail\r\n"); /* first conference is e-mail */ char confname[256]; for(i=0;i<usrgrps;i++) for(j=0;j<usrsubs[i];j++) { if(useron.qwk&QWK_EXT) /* 255 char max */ sprintf(confname,"%s %s" ,cfg.grp[cfg.sub[usrsub[i][j]]->grp]->sname ,cfg.sub[usrsub[i][j]]->lname); else /* 10 char max */ strcpy(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); } fprintf(stream,"HELLO\r\nBBSNEWS\r\nGOODBYE\r\n"); fclose(stream); /***********************/ /* Create DOOR.ID File */ /***********************/ sprintf(str,"%sDOOR.ID",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_OPEN,str,0); return(false); } p="CONTROLTYPE = "; fprintf(stream,"DOOR = %.10s\r\nVERSION = %s%c\r\n" "SYSTEM = %s\r\n" "CONTROLNAME = SBBS\r\n" "%sADD\r\n" "%sDROP\r\n" "%sYOURS\r\n" "%sRESET\r\n" "%sRESETALL\r\n" "%sFILES\r\n" "%sATTACH\r\n" "%sOWN\r\n" "%smail\r\n" "%sDELMAIL\r\n" "%sCTRL-A\r\n" "%sFREQ\r\n" "%sNDX\r\n" "%sTZ\r\n" "%sVIA\r\n" "%sCONTROL\r\n" "MIXEDCASE = YES\r\n" ,VERSION_NOTICE ,VERSION,REVISION ,VERSION_NOTICE ,p,p,p,p ,p,p,p,p ,p,p,p,p ,p,p,p,p ); fclose(stream); if(useron.rest&FLAG('Q')) { /***********************/ /* Create NETFLAGS.DAT */ /***********************/ sprintf(str,"%sNETFLAGS.DAT",cfg.temp_dir); if((stream=fopen(str,"wb"))==NULL) { errormsg(WHERE,ERR_CREATE,str,0); return(false); } ch=1; /* Net enabled */ if(usrgrps) for(i=0;i<(usrgrps*1000)+usrsubs[usrgrps-1];i++) fputc(ch,stream); fclose(stream); } } /****************************************************/ /* Create MESSAGES.DAT, write header and leave open */ /****************************************************/ sprintf(str,"%sMESSAGES.DAT",cfg.temp_dir); if(fexistcase(str)) fmode="r+b"; else fmode="w+b"; if((qwk=fopen(str,fmode))==NULL) { errormsg(WHERE,ERR_OPEN,str,0); return(false); } l=filelength(fileno(qwk)); if(l<1) { fprintf(qwk,"%-128.128s","Produced by " VERSION_NOTICE " " COPYRIGHT_NOTICE); msgndx=1; } else { msgndx=l/QWK_BLOCK_LEN; fseek(qwk,0,SEEK_END); } sprintf(str,"%sNEWFILES.DAT",cfg.temp_dir); remove(str); if(!(useron.rest&FLAG('T')) && useron.qwk&QWK_FILES) files=create_filelist("NEWFILES.DAT",FL_ULTIME); else files=0; start=time(NULL); if(useron.rest&FLAG('Q')) useron.qwk|=(QWK_EMAIL|QWK_ALLMAIL|QWK_DELMAIL); if(!(useron.qwk&QWK_NOINDEX)) { sprintf(str,"%sPERSONAL.NDX",cfg.temp_dir); if((personal=fopen(str,"ab"))==NULL) { fclose(qwk); errormsg(WHERE,ERR_OPEN,str,0); return(false); } } else personal=NULL; if(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL) /* && !prepack */) { sprintf(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(personal) fclose(personal); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return(false); } /***********************/ /* Pack E-mail, if any */ /***********************/ qwkmail_last=0; mail=loadmail(&smb,&mailmsgs,useron.number,0,useron.qwk&QWK_ALLMAIL ? 0 : LM_UNREAD); if(mailmsgs && !(sys_status&SS_ABORT)) { bputs(text[QWKPackingEmail]); if(!(useron.qwk&QWK_NOINDEX)) { sprintf(str,"%s000.NDX",cfg.temp_dir); if((ndx=fopen(str,"ab"))==NULL) { fclose(qwk); if(personal) fclose(personal); smb_close(&smb); errormsg(WHERE,ERR_OPEN,str,0); free(mail); return(false); } } else ndx=NULL; if(useron.rest&FLAG('Q')) mode|=QM_TO_QNET; else mode&=~QM_TO_QNET; for(l=0;l<mailmsgs;l++) { bprintf("\b\b\b\b\b\b\b\b\b\b\b\b%4lu of %-4lu" ,l+1,mailmsgs); memset(&msg,0,sizeof(msg)); msg.idx=mail[l]; if(msg.idx.number>qwkmail_last) qwkmail_last=msg.idx.number; if(!loadmsg(&msg,mail[l].number)) continue; if(msg.hdr.auxattr&MSG_FILEATTACH && useron.qwk&QWK_ATTACH) { sprintf(str,"%sfile/%04u.in/%s" ,cfg.data_dir,useron.number,msg.subj); sprintf(tmp,"%s%s",cfg.temp_dir,msg.subj); if(fexistcase(str) && !fexistcase(tmp)) mv(str,tmp,1); } size=msgtoqwk(&msg,qwk,mode,INVALID_SUB,0); smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); if(ndx) { msgndx++; f=ltomsbin(msgndx); /* Record number */ ch=0; /* Sub number, not used */ if(personal) { fwrite(&f,4,1,personal); fwrite(&ch,1,1,personal); } fwrite(&f,4,1,ndx); fwrite(&ch,1,1,ndx); msgndx+=size/QWK_BLOCK_LEN; } YIELD(); /* yield */ } bprintf(text[QWKPackedEmail],mailmsgs); if(ndx) fclose(ndx); } smb_close(&smb); /* Close the e-mail */ if(mailmsgs) free(mail); } /*********************/ /* Pack new messages */ /*********************/ for(i=0;i<usrgrps;i++) { for(j=0;j<usrsubs[i] && !msgabort();j++) { 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)) continue; lncntr=0; /* defeat pause */ if(useron.rest&FLAG('Q') && !(cfg.sub[usrsub[i][j]]->misc&SUB_QNET)) continue; /* QWK Net Node and not QWK networked, so skip */ subs_scanned++; msgs=getlastmsg(usrsub[i][j],&lastmsg,0); if(!msgs || lastmsg<=subscan[usrsub[i][j]].ptr) { /* no msgs */ if(subscan[usrsub[i][j]].ptr>lastmsg) { /* corrupted ptr */ outchar('*'); subscan[usrsub[i][j]].ptr=lastmsg; /* so fix automatically */ subscan[usrsub[i][j]].last=lastmsg; } bprintf(text[NScanStatusFmt] ,cfg.grp[cfg.sub[usrsub[i][j]]->grp]->sname ,cfg.sub[usrsub[i][j]]->lname,0L,msgs); continue; } sprintf(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]; if((k=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error); continue; } k=0; if(useron.qwk&QWK_BYSELF) k|=LP_BYSELF; if(useron.rest&FLAG('Q') || !(subscan[usrsub[i][j]].cfg&SUB_CFG_YSCAN)) k|=LP_OTHERS; post=loadposts(&posts,usrsub[i][j],subscan[usrsub[i][j]].ptr,k); bprintf(text[NScanStatusFmt] ,cfg.grp[cfg.sub[usrsub[i][j]]->grp]->sname ,cfg.sub[usrsub[i][j]]->lname,posts,msgs); if(!posts) { /* no new messages */ smb_close(&smb); continue; } bputs(text[QWKPackingSubboard]); submsgs=0; conf=cfg.sub[usrsub[i][j]]->qwkconf; if(!conf) conf=((i+1)*1000)+j+1; if(!(useron.qwk&QWK_NOINDEX)) { sprintf(str,"%s%u.NDX",cfg.temp_dir,conf); if((ndx=fopen(str,"ab"))==NULL) { fclose(qwk); if(personal) fclose(personal); smb_close(&smb); errormsg(WHERE,ERR_OPEN,str,0); free(post); return(false); } } else ndx=NULL; for(l=0;l<posts && !msgabort();l++) { bprintf("\b\b\b\b\b%-5lu",l+1); subscan[usrsub[i][j]].ptr=post[l].number; /* set ptr */ subscan[usrsub[i][j]].last=post[l].number; /* set last read */ memset(&msg,0,sizeof(msg)); msg.idx=post[l]; if(!loadmsg(&msg,post[l].number)) continue; if(useron.rest&FLAG('Q')) { if(msg.from_net.type && msg.from_net.type!=NET_QWK && !(cfg.sub[usrsub[i][j]]->misc&SUB_GATE)) { /* From other */ smb_freemsgmem(&msg); /* net, don't gate */ smb_unlockmsghdr(&smb,&msg); continue; } mode|=(QM_TO_QNET|QM_TAGLINE); if(msg.from_net.type==NET_QWK) { mode&=~QM_TAGLINE; if(route_circ((char *)msg.from_net.addr,useron.alias) || !strnicmp(msg.subj,"NE:",3)) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); continue; } } } else mode&=~(QM_TAGLINE|QM_TO_QNET); size=msgtoqwk(&msg,qwk,mode,usrsub[i][j],conf); smb_unlockmsghdr(&smb,&msg); if(ndx) { msgndx++; f=ltomsbin(msgndx); /* Record number */ ch=0; /* Sub number, not used */ if(personal && (!stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name))) { fwrite(&f,4,1,personal); fwrite(&ch,1,1,personal); } fwrite(&f,4,1,ndx); fwrite(&ch,1,1,ndx); msgndx+=size/QWK_BLOCK_LEN; } smb_freemsgmem(&msg); (*msgcnt)++; submsgs++; if(cfg.max_qwkmsgs && !(useron.exempt&FLAG('O')) && (*msgcnt)>=cfg.max_qwkmsgs) { bputs(text[QWKmsgLimitReached]); break; } if(!(l%50)) YIELD(); /* yield */ } if(!(sys_status&SS_ABORT)) bprintf(text[QWKPackedSubboard],submsgs,(*msgcnt)); if(ndx) { fclose(ndx); sprintf(str,"%s%u.NDX",cfg.temp_dir,conf); if(!flength(str)) remove(str); } smb_close(&smb); free(post); if(l<posts) break; YIELD(); /* yield */ } } if(j<usrsubs[i]) /* if sub aborted, abort all */ break; } if(online==ON_LOCAL) /* event */ eprintf(LOG_INFO,"%s scanned %lu sub-boards for new messages" ,useron.alias,subs_scanned); else lprintf(LOG_INFO,"Node %d %s scanned %lu sub-boards for new messages" ,cfg.node_num,useron.alias,subs_scanned); if((*msgcnt)+mailmsgs && time(NULL)-start) { bprintf("\r\n\r\n\1n\1hPacked %lu messages (%lu bytes) in %lu seconds " "(%lu messages/second)." ,(*msgcnt)+mailmsgs ,ftell(qwk) ,time(NULL)-start ,((*msgcnt)+mailmsgs)/(time(NULL)-start)); sprintf(str,"Packed %lu messages (%lu bytes) in %lu seconds (%lu msgs/sec)" ,(*msgcnt)+mailmsgs ,ftell(qwk) ,(ulong)(time(NULL)-start) ,((*msgcnt)+mailmsgs)/(time(NULL)-start)); if(online==ON_LOCAL) /* event */ eprintf(LOG_INFO,"%s",str); else lprintf(LOG_INFO,"%s",str); } fclose(qwk); /* close MESSAGE.DAT */ if(personal) { fclose(personal); /* close PERSONAL.NDX */ sprintf(str,"%sPERSONAL.NDX",cfg.temp_dir); if(!flength(str)) remove(str); } CRLF; if(!prepack && (sys_status&SS_ABORT || !online)) 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); 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); if(isdir(str)) continue; sprintf(tmp2,"%s%s",cfg.temp_dir,dirent->d_name); lncntr=0; /* Default 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)) netfiles++; } if(dir!=NULL) closedir(dir); if(netfiles) CRLF; } if(batdn_total) { for(i=0,totalcdt=0;i<batdn_total;i++) if(!is_download_free(&cfg,batdn_dir[i],&useron)) totalcdt+=batdn_cdt[i]; if(totalcdt>useron.cdt+useron.freecdt) { bprintf(text[YouOnlyHaveNCredits] ,ultoac(useron.cdt+useron.freecdt,tmp)); } else { for(i=0,totaltime=0;i<batdn_total;i++) { if(!(cfg.dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps) totaltime+=batdn_size[i]/(ulong)cur_cps; } if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) bputs(text[NotEnoughTimeToDl]); else { for(i=0;i<batdn_total;i++) { lncntr=0; unpadfname(batdn_name[i],tmp); sprintf(tmp2,"%s%s",cfg.temp_dir,tmp); if(!fexistcase(tmp2)) { seqwait(cfg.dir[batdn_dir[i]]->seqdev); bprintf(text[RetrievingFile],tmp); sprintf(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); thisnode.aux=0xfe; putnodedat(cfg.node_num,&thisnode); CRLF; } } } } } if(!(*msgcnt) && !mailmsgs && !files && !netfiles && !batdn_total && (prepack || !preqwk)) { bputs(text[QWKNoNewMessages]); return(false); } if(!(useron.rest&FLAG('Q'))) { /* Don't include in network */ /***********************/ /* packets */ /* Copy QWK Text files */ /***********************/ sprintf(str,"%sQWK/HELLO",cfg.text_dir); if(fexistcase(str)) { sprintf(tmp2,"%sHELLO",cfg.temp_dir); mv(str,tmp2,1); } sprintf(str,"%sQWK/BBSNEWS",cfg.text_dir); if(fexistcase(str)) { sprintf(tmp2,"%sBBSNEWS",cfg.temp_dir); mv(str,tmp2,1); } sprintf(str,"%sQWK/GOODBYE",cfg.text_dir); if(fexistcase(str)) { sprintf(tmp2,"%sGOODBYE",cfg.temp_dir); mv(str,tmp2,1); } sprintf(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); } } globfree(&g); } if(prepack) { for(i=1;i<=cfg.sys_nodes;i++) { getnodedat(i,&node,0); if((node.status==NODE_INUSE || node.status==NODE_QUIET || node.status==NODE_LOGON) && node.useron==useron.number) break; } if(i<=cfg.sys_nodes) /* Don't pre-pack with user online */ return(false); } /*******************/ /* Compress Packet */ /*******************/ sprintf(tmp2,"%s%s",cfg.temp_dir,ALLFILES); i=external(cmdstr(temp_cmd(),packet,tmp2,NULL) ,ex|EX_WILDCARD); if(!fexist(packet)) { bputs(text[QWKCompressionFailed]); 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]); return(false); } if(useron.rest&FLAG('Q')) { sprintf(str,"%s.qwk",cfg.sys_id); dir=opendir(cfg.temp_dir); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { if(!stricmp(str,dirent->d_name)) /* QWK packet */ continue; sprintf(tmp,"%s%s",cfg.temp_dir,dirent->d_name); if(!isdir(tmp)) remove(tmp); } if(dir!=NULL) closedir(dir); } return(true); }
bool sbbs_t::netmail(const char *into, const char *title, long mode) { char str[256],subj[128],to[256],fname[128],*buf,*p,ch; char tmp[512]; int file,fido,x,cc_found,cc_sent; uint i; long length,l; faddr_t addr; fmsghdr_t hdr; struct tm tm; if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) { bputs(text[TooManyEmailsToday]); return(false); } SAFECOPY(subj,title); strcpy(to,into); lookup_netuser(to); p=strrchr(to,'@'); /* Find '@' in name@addr */ if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { mode&=~WM_FILE; qnetmail(to,title,mode|WM_NETMAIL); return(false); } if(!cfg.total_faddrs || p==NULL || !strchr(p+1,'/')) { if(!p && cfg.dflt_faddr.zone) addr=cfg.dflt_faddr; else if(cfg.inetmail_misc&NMAIL_ALLOW) { if(mode&WM_FILE && !SYSOP && !(cfg.inetmail_misc&NMAIL_FILE)) mode&=~WM_FILE; return(inetmail(into,title,mode|WM_NETMAIL)); } else if(cfg.dflt_faddr.zone) addr=cfg.dflt_faddr; else { bputs(text[InvalidNetMailAddr]); return(false); } } else { addr=atofaddr(&cfg,p+1); /* Get fido address */ *p=0; /* Chop off address */ } if(mode&WM_FILE && !SYSOP && !(cfg.netmail_misc&NMAIL_FILE)) mode&=~WM_FILE; if((!SYSOP && !(cfg.netmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M') || !cfg.total_faddrs) { bputs(text[NoNetMailAllowed]); return(false); } truncsp(to); /* Truncate off space */ memset(&hdr,0,sizeof(hdr)); /* Initialize header to null */ strcpy(hdr.from,cfg.netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name); SAFECOPY(hdr.to,to); /* Look-up in nodelist? */ if(cfg.netmail_cost && !(useron.exempt&FLAG('S'))) { if(useron.cdt+useron.freecdt<cfg.netmail_cost) { bputs(text[NotEnoughCredits]); return(false); } sprintf(str,text[NetMailCostContinueQ],cfg.netmail_cost); if(noyes(str)) return(false); } now=time(NULL); if(localtime_r(&now,&tm)!=NULL) sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u" ,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year) ,tm.tm_hour,tm.tm_min,tm.tm_sec); hdr.destzone =addr.zone; hdr.destnet =addr.net; hdr.destnode =addr.node; hdr.destpoint =addr.point; for(i=0;i<cfg.total_faddrs;i++) if(addr.zone==cfg.faddr[i].zone && addr.net==cfg.faddr[i].net) break; if(i==cfg.total_faddrs) { for(i=0;i<cfg.total_faddrs;i++) if(addr.zone==cfg.faddr[i].zone) break; } if(i==cfg.total_faddrs) i=0; hdr.origzone =cfg.faddr[i].zone; hdr.orignet =cfg.faddr[i].net; hdr.orignode =cfg.faddr[i].node; hdr.origpoint =cfg.faddr[i].point; smb_faddrtoa(&cfg.faddr[i],str); bprintf(text[NetMailing],hdr.to,smb_faddrtoa(&addr,tmp),hdr.from,str); hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE); if(cfg.netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH; if(cfg.netmail_misc&NMAIL_HOLD) hdr.attr|=FIDO_HOLD; if(cfg.netmail_misc&NMAIL_KILL) hdr.attr|=FIDO_KILLSENT; if(mode&WM_FILE) hdr.attr|=FIDO_FILE; sprintf(str,"%sNETMAIL.MSG", cfg.node_dir); remove(str); /* Just incase it's already there */ // mode&=~WM_FILE; if(!writemsg(str,nulstr,subj,WM_NETMAIL|mode,INVALID_SUB,into)) { bputs(text[Aborted]); return(false); } if(mode&WM_FILE) { strcpy(fname,subj); sprintf(str,"%sfile/%04u.out", cfg.data_dir, useron.number); MKDIR(str); strcpy(tmp, cfg.data_dir); if(tmp[0]=='.') /* Relative path */ sprintf(tmp,"%s%s", cfg.node_dir, cfg.data_dir); sprintf(str,"%sfile/%04u.out/%s",tmp,useron.number,fname); strcpy(subj,str); if(fexistcase(str)) { bputs(text[FileAlreadyThere]); return(false); } { /* Remote */ xfer_prot_menu(XFER_UPLOAD); mnemonics(text[ProtocolOrQuit]); strcpy(str,"Q"); for(x=0;x<cfg.total_prots;x++) if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) { sprintf(tmp,"%c",cfg.prot[x]->mnemonic); strcat(str,tmp); } ch=(char)getkeys(str,0); if(ch=='Q' || sys_status&SS_ABORT) { bputs(text[Aborted]); return(false); } for(x=0;x<cfg.total_prots;x++) if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch && chk_ar(cfg.prot[x]->ar,&useron,&client)) break; if(x<cfg.total_prots) /* This should be always */ protocol(cfg.prot[x],XFER_UPLOAD,subj,nulstr,true); } sprintf(tmp,"%s%s",cfg.temp_dir,title); if(!fexistcase(subj) && fexistcase(tmp)) mv(tmp,subj,0); l=(long)flength(subj); if(l>0) bprintf(text[FileNBytesReceived],fname,ultoac(l,tmp)); else { bprintf(text[FileNotReceived],fname); return(false); } } p=subj; if((SYSOP || useron.exempt&FLAG('F')) && !strnicmp(p,"CR:",3)) { /* Crash over-ride by sysop */ p+=3; /* skip CR: */ if(*p==' ') p++; /* skip extra space if it exists */ hdr.attr|=FIDO_CRASH; } if((SYSOP || useron.exempt&FLAG('F')) && !strnicmp(p,"FR:",3)) { /* File request */ p+=3; /* skip FR: */ if(*p==' ') p++; hdr.attr|=FIDO_FREQ; } if((SYSOP || useron.exempt&FLAG('F')) && !strnicmp(p,"RR:",3)) { /* Return receipt request */ p+=3; /* skip RR: */ if(*p==' ') p++; hdr.attr|=FIDO_RRREQ; } if((SYSOP || useron.exempt&FLAG('F')) && !strnicmp(p,"FA:",3)) { /* File Attachment */ p+=3; /* skip FA: */ if(*p==' ') p++; hdr.attr|=FIDO_FILE; } SAFECOPY(hdr.subj,p); sprintf(str,"%sNETMAIL.MSG", cfg.node_dir); if((file=nopen(str,O_RDONLY))==-1) { errormsg(WHERE,ERR_OPEN,str,O_RDONLY); return(false); } length=(long)filelength(file); if((buf=(char *)malloc(length))==NULL) { close(file); errormsg(WHERE,ERR_ALLOC,str,length); return(false); } read(file,buf,length); close(file); md(cfg.netmail_dir); cc_sent=0; while(1) { for(i=1;i;i++) { sprintf(str,"%s%u.msg", cfg.netmail_dir,i); if(!fexistcase(str)) break; } if(!i) { bputs(text[TooManyEmailsToday]); return(false); } if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) { errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL); return(false); } write(fido,&hdr,sizeof(hdr)); pt_zone_kludge(hdr,fido); if(cfg.netmail_misc&NMAIL_DIRECT) { SAFECOPY(str,"\1FLAGS DIR\r\n"); write(fido,str,strlen(str)); } if(mode&WM_FILE) { SAFECOPY(str,"\1FLAGS KFS\r\n"); write(fido,str,strlen(str)); } if(cc_sent) { SAFEPRINTF(str,"* Originally to: %s\r\n\r\n",into); write(fido,str,strlen(str)); } l=0L; while(l<length) { if(buf[l]==CTRL_A) { /* Ctrl-A, so skip it and the next char */ l++; if(l>=length || toupper(buf[l])=='Z') /* EOF */ break; if((ch=ctrl_a_to_ascii_char(buf[l])) != 0) write(fido,&ch,1); } else if(buf[l]!=LF) { if((uchar)buf[l]==0x8d) /* r0dent i converted to normal i */ buf[l]='i'; write(fido,buf+l,1); } l++; } l=0; write(fido,&l,1); /* Null terminator */ close(fido); useron.emails++; logon_emails++; putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10)); useron.etoday++; putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10)); if(!(useron.exempt&FLAG('S'))) subtract_cdt(&cfg,&useron,cfg.netmail_cost); if(mode&WM_FILE) sprintf(str,"%s sent NetMail file attachment to %s (%s)" ,useron.alias ,hdr.to,smb_faddrtoa(&addr,tmp)); else sprintf(str,"%s sent NetMail to %s (%s)" ,useron.alias ,hdr.to,smb_faddrtoa(&addr,tmp)); logline("EN",str); cc_found=0; for(l=0;l<length && cc_found<=cc_sent;l++) if(l+3<length && !strnicmp(buf+l,"CC:",3)) { cc_found++; l+=2; } else { while(l<length && *(buf+l)!=LF) l++; } if(!cc_found) break; while(l<length && *(buf+l)==' ') l++; for(i=0;l<length && *(buf+l)!=LF && i<128;i++,l++) str[i]=buf[l]; if(!i) break; str[i]=0; p=strrchr(str,'@'); if(p) { addr=atofaddr(&cfg,p+1); *p=0; SAFECOPY(hdr.to,str); } else { atofaddr(&cfg,str); strcpy(hdr.to,"Sysop"); } hdr.destzone =addr.zone; hdr.destnet =addr.net; hdr.destnode =addr.node; hdr.destpoint =addr.point; cc_sent++; } if(cfg.netmail_sem[0]) /* update semaphore file */ ftouch(cmdstr(cfg.netmail_sem,nulstr,nulstr,NULL)); free(buf); return(true); }
bool sbbs_t::unpack_rep(char* repfile) { char str[MAX_PATH+1],fname[MAX_PATH+1] ,*AttemptedToUploadREPpacket="Attempted to upload REP packet"; char tmp[512]; char from[26]; char to[26]; char inbox[MAX_PATH+1]; char block[QWK_BLOCK_LEN]; int file; uint i,j,k,lastsub=INVALID_SUB; long l,size,misc; ulong n; ulong ex; node_t node; FILE* rep; DIR* dir; DIRENT* dirent; BOOL twit_list; sprintf(fname,"%stwitlist.cfg",cfg.ctrl_dir); twit_list=fexist(fname); if(repfile!=NULL) strcpy(str,repfile); else sprintf(str,"%s%s.rep",cfg.temp_dir,cfg.sys_id); if(!fexistcase(str)) { bputs(text[QWKReplyNotReceived]); logline("U!",AttemptedToUploadREPpacket); logline(nulstr,"REP file not received"); return(false); } for(k=0;k<cfg.total_fextrs;k++) if(!stricmp(cfg.fextr[k]->ext,useron.tmpext) && chk_ar(cfg.fextr[k]->ar,&useron)) break; if(k>=cfg.total_fextrs) k=0; ex=EX_OUTL|EX_OUTR; if(online!=ON_REMOTE) ex|=EX_OFFLINE; i=external(cmdstr(cfg.fextr[k]->cmd,str,ALLFILES,NULL),ex); if(i) { bputs(text[QWKExtractionFailed]); logline("U!",AttemptedToUploadREPpacket); logline(nulstr,"Extraction failed"); return(false); } sprintf(str,"%s%s.msg",cfg.temp_dir,cfg.sys_id); if(!fexistcase(str)) { bputs(text[QWKReplyNotReceived]); logline("U!",AttemptedToUploadREPpacket); logline(nulstr,"MSG file not received"); return(false); } if((rep=fnopen(&file,str,O_RDONLY))==NULL) { errormsg(WHERE,ERR_OPEN,str,O_RDONLY); return(false); } size=filelength(file); fread(block,QWK_BLOCK_LEN,1,rep); if(strnicmp((char *)block,cfg.sys_id,strlen(cfg.sys_id))) { fclose(rep); bputs(text[QWKReplyNotReceived]); logline("U!",AttemptedToUploadREPpacket); logline(nulstr,"Incorrect BBSID"); return(false); } logline("U+","Uploaded REP packet"); /********************/ /* Process messages */ /********************/ bputs(text[QWKUnpacking]); for(l=QWK_BLOCK_LEN;l<size;l+=i*QWK_BLOCK_LEN) { if(terminated) { bprintf("!Terminated"); break; } lncntr=0; /* defeat pause */ if(fseek(rep,l,SEEK_SET)!=0) { sprintf(str,"%s.msg", cfg.sys_id); errormsg(WHERE,ERR_SEEK,str,l); break; } if(fread(block,1,QWK_BLOCK_LEN,rep)!=QWK_BLOCK_LEN) { sprintf(str,"%s.msg", cfg.sys_id); errormsg(WHERE,ERR_READ,str,ftell(rep)); break; } sprintf(tmp,"%.6s",block+116); i=atoi(tmp); /* i = number of blocks */ if(i<2) { sprintf(str,"%s.msg blocks (read '%s' at offset %ld)", cfg.sys_id, tmp, l); errormsg(WHERE,ERR_CHK,str,i); i=1; continue; } if(atoi(block+1)==0) { /**********/ if(useron.rest&FLAG('E')) { /* E-mail */ bputs(text[R_Email]); /**********/ continue; } sprintf(str,"%25.25s",block+21); truncsp(str); if(!stricmp(str,"NETMAIL")) { /* QWK to FidoNet NetMail */ qwktonetmail(rep,block,NULL,0); continue; } if(strchr(str,'@')) { qwktonetmail(rep,block,str,0); continue; } if(!stricmp(str,"SBBS")) { /* to SBBS, config stuff */ qwkcfgline(block+71,INVALID_SUB); continue; } if(useron.etoday>=cfg.level_emailperday[useron.level] && !(useron.rest&FLAG('Q'))) { bputs(text[TooManyEmailsToday]); continue; } j=atoi(str); if(j && j>lastuser(&cfg)) j=0; if(!j) j=matchuser(&cfg,str,TRUE /* sysop_alias */); if(!j) { bputs(text[UnknownUser]); continue; } if(j==1 && useron.rest&FLAG('S')) { bprintf(text[R_Feedback],cfg.sys_op); continue; } getuserrec(&cfg,j,U_MISC,8,str); misc=ahtoul(str); if(misc&NETMAIL && cfg.sys_misc&SM_FWDTONET) { getuserrec(&cfg,j,U_NETMAIL,LEN_NETMAIL,str); qwktonetmail(rep,block,str,0); continue; } sprintf(smb.file,"%smail",cfg.data_dir); smb.retry_time=cfg.smb_retry_time; if(lastsub!=INVALID_SUB) { smb_close(&smb); lastsub=INVALID_SUB; } smb.subnum=INVALID_SUB; if((k=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error); continue; } if(!filelength(fileno(smb.shd_fp))) { smb.status.max_crcs=cfg.mail_maxcrcs; smb.status.max_msgs=0; smb.status.max_age=cfg.mail_maxage; smb.status.attr=SMB_EMAIL; if((k=smb_create(&smb))!=0) { smb_close(&smb); errormsg(WHERE,ERR_CREATE,smb.file,k); continue; } } if((k=smb_locksmbhdr(&smb))!=0) { smb_close(&smb); errormsg(WHERE,ERR_LOCK,smb.file,k); continue; } if((k=smb_getstatus(&smb))!=0) { smb_close(&smb); errormsg(WHERE,ERR_READ,smb.file,k); continue; } smb_unlocksmbhdr(&smb); if(!qwktomsg(rep,block,0,INVALID_SUB,j)) { smb_close(&smb); continue; } smb_close(&smb); if(j==1) { useron.fbacks++; logon_fbacks++; putuserrec(&cfg,useron.number,U_FBACKS,5 ,ultoa(useron.fbacks,tmp,10)); } else { useron.emails++; logon_emails++; putuserrec(&cfg,useron.number,U_EMAILS,5 ,ultoa(useron.emails,tmp,10)); } useron.etoday++; putuserrec(&cfg,useron.number,U_ETODAY,5 ,ultoa(useron.etoday,tmp,10)); bprintf(text[Emailed],username(&cfg,j,tmp),j); sprintf(str,"%s sent e-mail to %s #%d" ,useron.alias,username(&cfg,j,tmp),j); logline("E+",str); if(useron.rest&FLAG('Q')) { sprintf(tmp,"%-25.25s",block+46); truncsp(tmp); } else strcpy(tmp,useron.alias); for(k=1;k<=cfg.sys_nodes;k++) { /* Tell user, if online */ getnodedat(k,&node,0); if(node.useron==j && !(node.misc&NODE_POFF) && (node.status==NODE_INUSE || node.status==NODE_QUIET)) { sprintf(str,text[EmailNodeMsg] ,cfg.node_num,tmp); putnmsg(&cfg,k,str); break; } } if(k>cfg.sys_nodes) { sprintf(str,text[UserSentYouMail],tmp); putsmsg(&cfg,j,str); } } /* end of email */ /**************************/ else { /* message on a sub-board */ /**************************/ n=atol((char *)block+1); /* conference number */ for(j=0;j<usrgrps;j++) { for(k=0;k<usrsubs[j];k++) if(cfg.sub[usrsub[j][k]]->qwkconf==n) break; if(k<usrsubs[j]) break; } if(j>=usrgrps) { if(n<1000) { /* version 1 method, start at 101 */ j=n/100; k=n-(j*100); } else { /* version 2 method, start at 1001 */ j=n/1000; k=n-(j*1000); } j--; /* j is group */ k--; /* k is sub */ if(j>=usrgrps || k>=usrsubs[j] || cfg.sub[usrsub[j][k]]->qwkconf) { bprintf(text[QWKInvalidConferenceN],n); sprintf(str,"%s: Invalid conference number %lu",useron.alias,n); logline("P!",str); continue; } } n=usrsub[j][k]; /* if posting, add to new-scan config for QWKnet nodes automatically */ if(useron.rest&FLAG('Q')) subscan[n].cfg|=SUB_CFG_NSCAN; sprintf(str,"%-25.25s","SBBS"); if(!strnicmp((char *)block+21,str,25)) { /* to SBBS, config stuff */ qwkcfgline((char *)block+71,n); continue; } if(!SYSOP && cfg.sub[n]->misc&SUB_QNET) { /* QWK Netted */ sprintf(str,"%-25.25s","DROP"); /* Drop from new-scan? */ if(!strnicmp((char *)block+71,str,25)) /* don't allow post */ continue; sprintf(str,"%-25.25s","ADD"); /* Add to new-scan? */ if(!strnicmp((char *)block+71,str,25)) /* don't allow post */ continue; } if(useron.rest&FLAG('Q') && !(cfg.sub[n]->misc&SUB_QNET)) { bputs(text[CantPostOnSub]); logline("P!","Attempted to post on non-QWKnet sub"); continue; } if(useron.rest&FLAG('P')) { bputs(text[R_Post]); logline("P!","Post attempted"); continue; } if(useron.ptoday>=cfg.level_postsperday[useron.level] && !(useron.rest&FLAG('Q'))) { bputs(text[TooManyPostsToday]); continue; } if(useron.rest&FLAG('N') && cfg.sub[n]->misc&(SUB_FIDO|SUB_PNET|SUB_QNET|SUB_INET)) { bputs(text[CantPostOnSub]); logline("P!","Networked post attempted"); continue; } if(!chk_ar(cfg.sub[n]->post_ar,&useron)) { bputs(text[CantPostOnSub]); logline("P!","Post attempted"); continue; } if((block[0]=='*' || block[0]=='+') && !(cfg.sub[n]->misc&SUB_PRIV)) { bputs(text[PrivatePostsNotAllowed]); logline("P!","Private post attempt"); continue; } if(block[0]=='*' || block[0]=='+' /* Private post */ || cfg.sub[n]->misc&SUB_PONLY) { sprintf(str,"%-25.25s",nulstr); sprintf(tmp,"%-25.25s","ALL"); if(!strnicmp((char *)block+21,str,25) || !strnicmp((char *)block+21,tmp,25)) { /* to blank */ bputs(text[NoToUser]); /* or all */ continue; } } if(!SYSOP && !(useron.rest&FLAG('Q'))) { sprintf(str,"%-25.25s","SYSOP"); if(!strnicmp((char *)block+21,str,25)) { sprintf(str,"%-25.25s",username(&cfg,1,tmp)); memcpy((char *)block+21,str,25); /* change from sysop */ } /* to user name */ } /* TWIT FILTER */ if(twit_list) { sprintf(fname,"%stwitlist.cfg",cfg.ctrl_dir); sprintf(from,"%25.25s",block+46); /* From user */ truncsp(from); sprintf(to,"%25.25s",block+21); /* To user */ truncsp(to); if(findstr(from,fname) || findstr(to,fname)) { sprintf(str,"Filtering post from %s to %s on %s %s" ,from ,to ,cfg.grp[cfg.sub[n]->grp]->sname,cfg.sub[n]->lname); logline("P!",str); continue; } } if(n!=lastsub) { if(lastsub!=INVALID_SUB) smb_close(&smb); lastsub=INVALID_SUB; sprintf(smb.file,"%s%s",cfg.sub[n]->data_dir,cfg.sub[n]->code); smb.retry_time=cfg.smb_retry_time; smb.subnum=n; if((j=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,j,smb.last_error); continue; } if(!filelength(fileno(smb.shd_fp))) { smb.status.max_crcs=cfg.sub[n]->maxcrcs; smb.status.max_msgs=cfg.sub[n]->maxmsgs; smb.status.max_age=cfg.sub[n]->maxage; smb.status.attr=cfg.sub[n]->misc&SUB_HYPER ? SMB_HYPERALLOC:0; if((j=smb_create(&smb))!=0) { smb_close(&smb); lastsub=INVALID_SUB; errormsg(WHERE,ERR_CREATE,smb.file,j); continue; } } if((j=smb_locksmbhdr(&smb))!=0) { smb_close(&smb); lastsub=INVALID_SUB; errormsg(WHERE,ERR_LOCK,smb.file,j); continue; } if((j=smb_getstatus(&smb))!=0) { smb_close(&smb); lastsub=INVALID_SUB; errormsg(WHERE,ERR_READ,smb.file,j); continue; } smb_unlocksmbhdr(&smb); lastsub=n; } if(!qwktomsg(rep,block,0,n,0)) continue; logon_posts++; user_posted_msg(&cfg, &useron, 1); bprintf(text[Posted],cfg.grp[cfg.sub[n]->grp]->sname ,cfg.sub[n]->lname); sprintf(str,"%s posted on %s %s" ,useron.alias,cfg.grp[cfg.sub[n]->grp]->sname,cfg.sub[n]->lname); signal_sub_sem(&cfg,n); logline("P+",str); if(!(useron.rest&FLAG('Q'))) user_event(EVENT_POST); } /* end of public message */ } update_qwkroute(NULL); /* Write ROUTE.DAT */ if(lastsub!=INVALID_SUB) smb_close(&smb); fclose(rep); if(useron.rest&FLAG('Q')) { /* QWK Net Node */ sprintf(str,"%s%s.msg",cfg.temp_dir,cfg.sys_id); if(fexistcase(str)) remove(str); sprintf(str,"%s%s.rep",cfg.temp_dir,cfg.sys_id); if(fexistcase(str)) remove(str); sprintf(str,"%sATTXREF.DAT",cfg.temp_dir); if(fexistcase(str)) remove(str); dir=opendir(cfg.temp_dir); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { /* Extra files */ // Move files sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name); if(isdir(str)) continue; // Create directory if necessary sprintf(inbox,"%sqnet/%s.in",cfg.data_dir,useron.alias); MKDIR(inbox); sprintf(fname,"%s/%s",inbox,dirent->d_name); mv(str,fname,1); sprintf(str,text[ReceivedFileViaQWK],dirent->d_name,useron.alias); putsmsg(&cfg,1,str); } if(dir!=NULL) closedir(dir); sprintf(str,"%sqnet-rep.now",cfg.data_dir); ftouch(str); } bputs(text[QWKUnpacked]); CRLF; /**********************************************/ /* Hang-up now if that's what the user wanted */ /**********************************************/ autohangup(); return(true); }