/* pack_rep.cpp */ /* Synchronet QWK reply (REP) packet creation routine */ /* $Id$ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.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 * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * See the GNU General Public License for more details: gpl.txt or * * http://www.fsf.org/copyleft/gpl.html * * * * Anonymous FTP access to the most recent released source is available at * * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * * * * Anonymous CVS access to the development source and modification history * * is available at cvs.synchro.net:/cvsroot/sbbs, example: * * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * * (just hit return, no password is necessary) * * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * * * * For Synchronet coding style and modification guidelines, see * * http://www.synchro.net/source.html * * * * You are encouraged to submit any modifications (preferably in Unix diff * * format) via e-mail to mods@synchro.net * * * * Note: If this box doesn't appear square, then you need to fix your tabs. * ****************************************************************************/ #include "sbbs.h" #include "qwk.h" /****************************************************************************/ /* Creates an REP packet for upload to QWK hub 'hubnum'. */ /* Returns 1 if successful, 0 if not. */ /****************************************************************************/ bool sbbs_t::pack_rep(uint hubnum) { char str[MAX_PATH+1]; char tmp[MAX_PATH+1],tmp2[MAX_PATH+1]; char hubid_upper[LEN_QWKID+1]; char hubid_lower[LEN_QWKID+1]; int file,mode; uint i,j,k; long l,msgcnt,submsgs,packedmail,netfiles=0,deleted; int32_t posts; int32_t mailmsgs; ulong msgs; uint32_t last; post_t* post; mail_t* mail; FILE* rep; FILE* hdrs=NULL; DIR* dir; DIRENT* dirent; smbmsg_t msg; msgcnt=0L; delfiles(cfg.temp_dir,ALLFILES); SAFECOPY(hubid_upper,cfg.qhub[hubnum]->id); strupr(hubid_upper); SAFECOPY(hubid_lower,cfg.qhub[hubnum]->id); strlwr(hubid_lower); SAFEPRINTF2(str,"%s%s.REP",cfg.data_dir,hubid_upper); if(fexistcase(str)) { eprintf(LOG_INFO,"Updating %s", str); external(cmdstr(cfg.qhub[hubnum]->unpack,str,ALLFILES,NULL),EX_OFFLINE); } else eprintf(LOG_INFO,"Creating %s", str); /*************************************************/ /* Create SYSID.MSG, write header and leave open */ /*************************************************/ SAFEPRINTF2(str,"%s%s.MSG",cfg.temp_dir,hubid_upper); fexistcase(str); if((rep=fnopen(&file,str,O_CREAT|O_WRONLY|O_TRUNC))==NULL) { errormsg(WHERE,ERR_CREATE,str,O_CREAT|O_WRONLY|O_TRUNC); return(false); } if(filelength(file)<1) { /* New REP packet */ SAFEPRINTF2(str,"%-*s" ,QWK_BLOCK_LEN,hubid_upper); /* So write header */ fwrite(str,QWK_BLOCK_LEN,1,rep); } fseek(rep,0L,SEEK_END); /* Always includes HEADERS.DAT in .REP packets which are only for QWKnet hubs */ /* And *usually* a Synchronet system */ SAFEPRINTF(str,"%sHEADERS.DAT",cfg.temp_dir); fexistcase(str); if((hdrs=fopen(str,"a"))==NULL) errormsg(WHERE,ERR_CREATE,str,0); /*********************/ /* Pack new messages */ /*********************/ 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(rep); if(hdrs!=NULL) fclose(hdrs); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return(false); } /***********************/ /* Pack E-mail, if any */ /***********************/ qwkmail_last=0; mail=loadmail(&smb,&mailmsgs,0,MAIL_YOUR,0); packedmail=0; if(mailmsgs) { eprintf(LOG_INFO,"Packing NetMail for %s", cfg.qhub[hubnum]->id); for(l=0;l<mailmsgs;l++) { // bprintf("\b\b\b\b\b%-5lu",l+1); 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; SAFEPRINTF(str,"%s/",cfg.qhub[hubnum]->id); if(msg.to_net.type!=NET_QWK || (strcmp((char *)msg.to_net.addr,cfg.qhub[hubnum]->id) && strncmp((char *)msg.to_net.addr,str,strlen(str)))) { smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); continue; } msgtoqwk(&msg,rep,QM_TO_QNET|QM_REP|A_LEAVE,INVALID_SUB,0,hdrs); packedmail++; smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); YIELD(); /* yield */ } eprintf(LOG_INFO,"Packed %d NetMail messages",packedmail); } smb_close(&smb); /* Close the e-mail */ if(mailmsgs) free(mail); for(i=0;i<cfg.qhub[hubnum]->subs;i++) { j=cfg.qhub[hubnum]->sub[i]; /* j now equals the real sub num */ msgs=getlastmsg(j,&last,0); lncntr=0; /* defeat pause */ if(!msgs || last<=subscan[j].ptr) { if(subscan[j].ptr>last) { subscan[j].ptr=last; subscan[j].last=last; } eprintf(LOG_INFO,remove_ctrl_a(text[NScanStatusFmt],tmp) ,cfg.grp[cfg.sub[j]->grp]->sname ,cfg.sub[j]->lname,0L,msgs); continue; } SAFEPRINTF2(smb.file,"%s%s" ,cfg.sub[j]->data_dir,cfg.sub[j]->code); smb.retry_time=cfg.smb_retry_time; smb.subnum=j; if((k=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error); continue; } post=loadposts(&posts,j,subscan[j].ptr,LP_BYSELF|LP_OTHERS|LP_PRIVATE|LP_REP,NULL); eprintf(LOG_INFO,remove_ctrl_a(text[NScanStatusFmt],tmp) ,cfg.grp[cfg.sub[j]->grp]->sname ,cfg.sub[j]->lname,posts,msgs); if(!posts) { /* no new messages */ smb_close(&smb); continue; } subscan[j].ptr=last; /* set pointer */ eprintf(LOG_INFO,"%s",remove_ctrl_a(text[QWKPackingSubboard],tmp)); /* ptr to last msg */ submsgs=0; for(l=0;l<posts;l++) { // bprintf("\b\b\b\b\b%-5lu",l+1); memset(&msg,0,sizeof(msg)); msg.idx=post[l]; if(!loadmsg(&msg,post[l].number)) continue; if(msg.from_net.type && msg.from_net.type!=NET_QWK && !(cfg.sub[j]->misc&SUB_GATE)) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); continue; } if(!strnicmp(msg.subj,"NE:",3) || (msg.from_net.type==NET_QWK && route_circ((char *)msg.from_net.addr,cfg.qhub[hubnum]->id))) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); continue; } mode=cfg.qhub[hubnum]->mode[i]|QM_TO_QNET|QM_REP; if(mode&A_LEAVE) mode|=(QM_VIA|QM_TZ|QM_MSGID); if(msg.from_net.type!=NET_QWK) mode|=QM_TAGLINE; msgtoqwk(&msg,rep,mode,j,cfg.qhub[hubnum]->conf[i],hdrs); smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); msgcnt++; submsgs++; if(!(l%50)) YIELD(); /* yield */ } eprintf(LOG_INFO,remove_ctrl_a(text[QWKPackedSubboard],tmp),submsgs,msgcnt); free(post); smb_close(&smb); YIELD(); /* yield */ } if(hdrs!=NULL) fclose(hdrs); fclose(rep); /* close HUB_ID.MSG */ CRLF; /* Look for extra files to send out */ SAFEPRINTF2(str,"%sqnet/%s.out",cfg.data_dir,hubid_lower); dir=opendir(str); while(dir!=NULL && (dirent=readdir(dir))!=NULL) { SAFEPRINTF3(str,"%sqnet/%s.out/%s",cfg.data_dir,hubid_lower,dirent->d_name); if(isdir(str)) continue; SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,dirent->d_name); eprintf(LOG_INFO,remove_ctrl_a(text[RetrievingFile],tmp),str); if(!mv(str,tmp2,/* copy: */TRUE)) netfiles++; } if(dir!=NULL) closedir(dir); if(netfiles) CRLF; if(!msgcnt && !netfiles && !packedmail) { eprintf(LOG_INFO,remove_ctrl_a(text[QWKNoNewMessages],tmp)); return(true); // Changed from false Mar-11-2005 (needs to be true to save updated ptrs) } /*******************/ /* Compress Packet */ /*******************/ SAFEPRINTF2(str,"%s%s.REP",cfg.data_dir,hubid_upper); SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,ALLFILES); i=external(cmdstr(cfg.qhub[hubnum]->pack,str,tmp2,NULL) ,EX_OFFLINE|EX_WILDCARD); if(!fexistcase(str)) { eprintf(LOG_WARNING,"%s",remove_ctrl_a(text[QWKCompressionFailed],tmp)); if(i) errormsg(WHERE,ERR_EXEC,cmdstr(cfg.qhub[hubnum]->pack,str,tmp2,NULL),i); else lprintf(LOG_ERR, "Couldn't compress REP packet"); return(false); } SAFEPRINTF2(str,"%sqnet/%s.out/",cfg.data_dir,hubid_lower); delfiles(str,ALLFILES); if(packedmail) { /* Delete NetMail */ SAFEPRINTF(smb.file,"%smail",cfg.data_dir); smb.retry_time=cfg.smb_retry_time; smb.subnum=INVALID_SUB; if((i=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return(true); } mail=loadmail(&smb,&mailmsgs,0,MAIL_YOUR,0); if((i=smb_locksmbhdr(&smb))!=0) { /* Lock the base, so nobody */ if(mailmsgs) free(mail); smb_close(&smb); errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); /* messes with the index */ return(true); } if((i=smb_getstatus(&smb))!=0) { if(mailmsgs) free(mail); smb_close(&smb); errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); return(true); } deleted=0; /* Mark as READ and DELETE */ for(l=0;l<mailmsgs;l++) { if(mail[l].number>qwkmail_last) continue; memset(&msg,0,sizeof(msg)); /* !IMPORTANT: search by number (do not initialize msg.idx.offset) */ if(!loadmsg(&msg,mail[l].number)) continue; SAFEPRINTF(str,"%s/",cfg.qhub[hubnum]->id); if(msg.to_net.type!=NET_QWK || (strcmp((char *)msg.to_net.addr,cfg.qhub[hubnum]->id) && strncmp((char *)msg.to_net.addr,str,strlen(str)))) { smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); continue; } msg.hdr.attr|=MSG_DELETE; msg.idx.attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); else deleted++; smb_unlockmsghdr(&smb,&msg); smb_freemsgmem(&msg); } if(deleted && cfg.sys_misc&SM_DELEMAIL) delmail(0,MAIL_YOUR); smb_close(&smb); if(mailmsgs) free(mail); eprintf(LOG_INFO,"Deleted %d sent NetMail messages",deleted); } return(true); }