void showstatus(void) { int i; i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); smb_unlocksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } printf("last_msg =%"PRIu32"\n" "total_msgs =%"PRIu32"\n" "header_offset =%"PRIu32"\n" "max_crcs =%"PRIu32"\n" "max_msgs =%"PRIu32"\n" "max_age =%u\n" "attr =%04Xh\n" ,smb.status.last_msg ,smb.status.total_msgs ,smb.status.header_offset ,smb.status.max_crcs ,smb.status.max_msgs ,smb.status.max_age ,smb.status.attr ); }
int fixsmb(char* sub) { char* p; char* text; char c; int i,w; ulong l,length,size,n; smbmsg_t msg; memset(&smb,0,sizeof(smb)); SAFECOPY(smb.file,sub); if((p=getfext(smb.file))!=NULL && stricmp(p,".shd")==0) *p=0; /* Chop off .shd extension, if supplied on command-line */ printf("Opening %s\n",smb.file); if((i=smb_open(&smb))!=0) { printf("smb_open returned %d: %s\n",i,smb.last_error); exit(1); } if((i=smb_lock(&smb))!=0) { printf("smb_lock returned %d: %s\n",i,smb.last_error); exit(1); } if((i=smb_locksmbhdr(&smb))!=0) { smb_close(&smb); printf("smb_locksmbhdr returned %d: %s\n",i,smb.last_error); exit(1); } if((i=smb_getstatus(&smb))!=0) { smb_unlocksmbhdr(&smb); smb_close(&smb); printf("smb_getstatus returned %d: %s\n",i,smb.last_error); exit(1); } if(!(smb.status.attr&SMB_HYPERALLOC)) { if((i=smb_open_ha(&smb))!=0) { smb_close(&smb); printf("smb_open_ha returned %d: %s\n",i,smb.last_error); exit(1); } if((i=smb_open_da(&smb))!=0) { smb_close(&smb); printf("smb_open_da returned %d: %s\n",i,smb.last_error); exit(1); } rewind(smb.sha_fp); chsize(fileno(smb.sha_fp),0L); /* Truncate the header allocation file */ rewind(smb.sda_fp); chsize(fileno(smb.sda_fp),0L); /* Truncate the data allocation file */ } rewind(smb.sid_fp); chsize(fileno(smb.sid_fp),0L); /* Truncate the index */ if(!(smb.status.attr&SMB_HYPERALLOC)) { length=filelength(fileno(smb.sdt_fp)); w=0; for(l=0;l<length;l+=SDT_BLOCK_LEN) /* Init .SDA file to NULL */ fwrite(&w,2,1,smb.sda_fp); length=filelength(fileno(smb.shd_fp)); c=0; for(l=0;l<length;l+=SHD_BLOCK_LEN) /* Init .SHD file to NULL */ fwrite(&c,1,1,smb.sha_fp); } else length=filelength(fileno(smb.shd_fp)); n=0; /* messsage offset */ for(l=smb.status.header_offset;l<length;l+=size) { size=SHD_BLOCK_LEN; printf("\r%2lu%% ",(long)(100.0/((float)length/l))); msg.idx.offset=l; if((i=smb_lockmsghdr(&smb,&msg))!=0) { printf("\n(%06lX) smb_lockmsghdr returned %d:\n%s\n",l,i,smb.last_error); continue; } i=smb_getmsghdr(&smb,&msg); smb_unlockmsghdr(&smb,&msg); if(i!=0) { printf("\n(%06lX) smb_getmsghdr returned %d:\n%s\n",l,i,smb.last_error); continue; } size=smb_hdrblocks(smb_getmsghdrlen(&msg))*SHD_BLOCK_LEN; printf("#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from); /* Create hash record */ if(msg.hdr.attr&MSG_DELETE) text=NULL; else text=smb_getmsgtxt(&smb,&msg,GETMSGTXT_BODY_ONLY); i=smb_hashmsg(&smb,&msg,text,TRUE /* update */); if(i!=SMB_SUCCESS) printf("!ERROR %d hashing message\n", i); if(text!=NULL) free(text); /* Index the header */ if(msg.hdr.attr&MSG_DELETE) printf("Not indexing deleted message\n"); else if(msg.hdr.number==0) printf("Not indexing invalid message number (0)!\n"); else { msg.offset=n; if(renumber) msg.hdr.number=n+1; if(msg.hdr.netattr&MSG_INTRANSIT) { printf("Removing 'in transit' attribute\n"); msg.hdr.netattr&=~MSG_INTRANSIT; } if((i=smb_putmsg(&smb,&msg))!=0) { printf("\nsmb_putmsg returned %d: %s\n",i,smb.last_error); continue; } n++; } if(!(smb.status.attr&SMB_HYPERALLOC)) { /**************************/ /* Allocate header blocks */ /**************************/ fseek(smb.sha_fp,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET); if(msg.hdr.attr&MSG_DELETE) c=0; /* mark as free */ else c=1; /* or allocated */ for(i=0;i<(int)(size/SHD_BLOCK_LEN);i++) fputc(c,smb.sha_fp); /************************/ /* Allocate data blocks */ /************************/ if(!(msg.hdr.attr&MSG_DELETE)) smb_incmsg_dfields(&smb,&msg,1); } smb_freemsgmem(&msg); } printf("\r%79s\r100%%\n",""); smb.status.total_msgs=n; if(renumber) smb.status.last_msg=n; else sort_index(&smb); printf("Saving message base status (%lu total messages).\n",n); if((i=smb_putstatus(&smb))!=0) printf("\nsmb_putstatus returned %d: %s\n",i,smb.last_error); smb_unlocksmbhdr(&smb); printf("Closing message base.\n"); smb_close(&smb); unlock_msgbase(); printf("Done.\n"); return(0); }
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 msgcnt,submsgs,packedmail,netfiles=0,deleted; uint32_t u; uint32_t posts; uint32_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(u=0;u<mailmsgs;u++) { // bprintf("\b\b\b\b\b%-5lu",u+1); memset(&msg,0,sizeof(msg)); msg.idx=mail[u]; if(msg.idx.number>qwkmail_last) qwkmail_last=msg.idx.number; if(!loadmsg(&msg,mail[u].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(u=0;u<posts;u++) { // bprintf("\b\b\b\b\b%-5lu",u+1); memset(&msg,0,sizeof(msg)); msg.idx=post[u]; if(!loadmsg(&msg,post[u].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(!(u%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(u=0;u<mailmsgs;u++) { if(mail[u].number>qwkmail_last) continue; memset(&msg,0,sizeof(msg)); /* !IMPORTANT: search by number (do not initialize msg.idx.offset) */ if(!loadmsg(&msg,mail[u].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); }
extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, client_t* client, const char* server, char* msgbuf) { char pid[128]; char msg_id[256]; ushort xlat=XLAT_NONE; int i; int storage=SMB_SELFPACK; long dupechk_hashes=SMB_HASH_SOURCE_DUPE; if(msg==NULL) return(SMB_FAILURE); if(!SMB_IS_OPEN(smb)) { if(smb->subnum==INVALID_SUB) sprintf(smb->file,"%smail",cfg->data_dir); else sprintf(smb->file,"%s%s",cfg->sub[smb->subnum]->data_dir,cfg->sub[smb->subnum]->code); smb->retry_time=cfg->smb_retry_time; if((i=smb_open(smb))!=SMB_SUCCESS) return(i); } /* Lock the msgbase early to preserve our message number (used in MSG-IDs) */ if(!smb->locked && smb_locksmbhdr(smb)!=SMB_SUCCESS) return(SMB_ERR_LOCK); if(filelength(fileno(smb->shd_fp))>0 && (i=smb_getstatus(smb))!=SMB_SUCCESS) { if(smb->locked) smb_unlocksmbhdr(smb); return(i); } if(smb->subnum==INVALID_SUB) { /* e-mail */ /* exception here during recycle: sbbs.dll!savemsg(scfg_t * cfg, smb_t * smb, smbmsg_t * msg, client_t * client, char * msgbuf) Line 473 + 0xf bytes C++ sbbs.dll!js_save_msg(JSContext * cx, JSObject * obj, unsigned int argc, long * argv, long * rval) Line 1519 + 0x25 bytes C js32.dll!js_Invoke(JSContext * cx, unsigned int argc, unsigned int flags) Line 1375 + 0x17 bytes C js32.dll!js_Interpret(JSContext * cx, unsigned char * pc, long * result) Line 3944 + 0xf bytes C js32.dll!js_Execute(JSContext * cx, JSObject * chain, JSObject * script, JSStackFrame * down, unsigned int flags, long * result) Line 1633 + 0x13 bytes C js32.dll!JS_ExecuteScript(JSContext * cx, JSObject * obj, JSObject * script, long * rval) Line 4188 + 0x19 bytes C sbbs.dll!sbbs_t::js_execfile(const char * cmd, const char * startup_dir) Line 686 + 0x27 bytes C++ sbbs.dll!sbbs_t::external(const char * cmdline, long mode, const char * startup_dir) Line 413 + 0x1e bytes C++ sbbs.dll!event_thread(void * arg) Line 2745 + 0x71 bytes C++ apparently the event_thread is sharing an scfg_t* with another thread! */ smb->status.max_crcs=cfg->mail_maxcrcs; smb->status.max_age=cfg->mail_maxage; smb->status.max_msgs=0; /* unlimited */ smb->status.attr=SMB_EMAIL; if(cfg->sys_misc&SM_FASTMAIL) storage=SMB_FASTALLOC; /* duplicate message-IDs must be allowed in mail database */ dupechk_hashes&=~(1<<SMB_HASH_SOURCE_MSG_ID); } else { /* sub-board */ smb->status.max_crcs=cfg->sub[smb->subnum]->maxcrcs; smb->status.max_msgs=cfg->sub[smb->subnum]->maxmsgs; smb->status.max_age=cfg->sub[smb->subnum]->maxage; smb->status.attr=0; if(cfg->sub[smb->subnum]->misc&SUB_HYPER) storage = smb->status.attr = SMB_HYPERALLOC; else if(cfg->sub[smb->subnum]->misc&SUB_FAST) storage = SMB_FASTALLOC; if(cfg->sub[smb->subnum]->misc&SUB_LZH) xlat=XLAT_LZH; /* enforce anonymous/private posts only */ if(cfg->sub[smb->subnum]->misc&SUB_PONLY) msg->hdr.attr|=MSG_PRIVATE; if(cfg->sub[smb->subnum]->misc&SUB_AONLY) msg->hdr.attr|=MSG_ANONYMOUS; } if(msg->hdr.when_imported.time==0) { msg->hdr.when_imported.time=time32(NULL); msg->hdr.when_imported.zone=sys_timezone(cfg); } if(msg->hdr.when_written.time==0) /* Uninitialized */ msg->hdr.when_written = msg->hdr.when_imported; msg->hdr.number=smb->status.last_msg+1; /* needed for MSG-ID generation */ if(smb->status.max_crcs==0) /* no CRC checking means no body text dupe checking */ dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY); if(client!=NULL) msg_client_hfields(msg,client); if(server!=NULL) smb_hfield_str(msg,SENDERSERVER,server); /* Generate RFC-822 Message-id */ if(msg->id==NULL) { get_msgid(cfg,smb->subnum,msg,msg_id,sizeof(msg_id)); smb_hfield_str(msg,RFC822MSGID,msg_id); } /* Generate FidoNet MSGID (for FidoNet sub-boards) */ if(smb->subnum!=INVALID_SUB && cfg->sub[smb->subnum]->misc&SUB_FIDO && msg->ftn_msgid==NULL) { ftn_msgid(cfg->sub[smb->subnum],msg,msg_id,sizeof(msg_id)); smb_hfield_str(msg,FIDOMSGID,msg_id); } /* Generate FidoNet Program Identifier */ if(msg->ftn_pid==NULL) smb_hfield_str(msg,FIDOPID,msg_program_id(pid)); if((i=smb_addmsg(smb,msg,storage,dupechk_hashes,xlat,(uchar*)msgbuf,NULL))==SMB_SUCCESS && msg->to!=NULL /* no recipient means no header created at this stage */) signal_sub_sem(cfg,smb->subnum); return(i); }
bool sbbs_t::postmsg(uint subnum, smbmsg_t *remsg, long wm_mode) { char str[256],title[LEN_TITLE+1],top[256]; char msg_id[256]; char touser[64]; char from[64]; char pid[128]; char* editor=NULL; char* msgbuf=NULL; uint16_t xlat; ushort msgattr; int i,storage; long dupechk_hashes; long length; FILE* fp; smbmsg_t msg; uint reason; if(remsg) { sprintf(title,"%.*s",LEN_TITLE,remsg->subj); if(remsg->hdr.attr&MSG_ANONYMOUS) SAFECOPY(from,text[Anonymous]); else SAFECOPY(from,remsg->from); // If user posted this message, reply to the original recipient again if((remsg->from_ext!=NULL && atoi(remsg->from_ext)==useron.number) || stricmp(useron.alias,remsg->from)==0 || stricmp(useron.name,remsg->from)==0) SAFECOPY(touser,remsg->to); else SAFECOPY(touser,from); msgattr=(ushort)(remsg->hdr.attr&MSG_PRIVATE); sprintf(top,text[RegardingByToOn],title,from,remsg->to ,timestr(remsg->hdr.when_written.time) ,smb_zonestr(remsg->hdr.when_written.zone,NULL)); } else { title[0]=0; touser[0]=0; top[0]=0; msgattr=0; } /* Security checks */ if(!can_user_post(&cfg,subnum,&useron,&client,&reason)) { bputs(text[reason]); return false; } bprintf(text[Posting],cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname); action=NODE_PMSG; nodesync(); if(!(msgattr&MSG_PRIVATE) && (cfg.sub[subnum]->misc&SUB_PONLY || (cfg.sub[subnum]->misc&SUB_PRIV && !noyes(text[PrivatePostQ])))) msgattr|=MSG_PRIVATE; if(sys_status&SS_ABORT) return(false); if( #if 0 /* we *do* support internet posts to specific people July-11-2002 */ !(cfg.sub[subnum]->misc&SUB_INET) && // Prompt for TO: user #endif (cfg.sub[subnum]->misc&SUB_TOUSER || msgattr&MSG_PRIVATE || touser[0])) { if(!touser[0] && !(msgattr&MSG_PRIVATE)) SAFECOPY(touser,"All"); bputs(text[PostTo]); i=LEN_ALIAS; if(cfg.sub[subnum]->misc&SUB_QNET) i=25; if(cfg.sub[subnum]->misc&SUB_FIDO) i=FIDO_NAME_LEN-1; if(cfg.sub[subnum]->misc&(SUB_PNET|SUB_INET)) i=60; getstr(touser,i,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL); if(stricmp(touser,"ALL") && !(cfg.sub[subnum]->misc&(SUB_PNET|SUB_FIDO|SUB_QNET|SUB_INET|SUB_ANON))) { if(cfg.sub[subnum]->misc&SUB_NAME) { if(!userdatdupe(useron.number,U_NAME,LEN_NAME,touser)) { bputs(text[UnknownUser]); return(false); } } else { if((i=finduser(touser))==0) return(false); username(&cfg,i,touser); } } if(sys_status&SS_ABORT) return(false); } if(!touser[0]) SAFECOPY(touser,"All"); // Default to ALL if(!stricmp(touser,"SYSOP") && !SYSOP) // Change SYSOP to user #1 username(&cfg,1,touser); if(msgattr&MSG_PRIVATE && !stricmp(touser,"ALL")) { bputs(text[NoToUser]); return(false); } if(msgattr&MSG_PRIVATE) wm_mode|=WM_PRIVATE; if(cfg.sub[subnum]->misc&SUB_AONLY || (cfg.sub[subnum]->misc&SUB_ANON && useron.exempt&FLAG('A') && !noyes(text[AnonymousQ]))) msgattr|=MSG_ANONYMOUS; if(cfg.sub[subnum]->mod_ar[0] && chk_ar(cfg.sub[subnum]->mod_ar,&useron,&client)) msgattr|=MSG_MODERATED; if(cfg.sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum)) msgattr|=MSG_PERMANENT; if(msgattr&MSG_PRIVATE) bputs(text[PostingPrivately]); if(msgattr&MSG_ANONYMOUS) bputs(text[PostingAnonymously]); if(cfg.sub[subnum]->misc&SUB_NAME) bputs(text[UsingRealName]); msg_tmp_fname(useron.xedit, str, sizeof(str)); if(!writemsg(str,top,title,wm_mode,subnum,touser,&editor) || (length=(long)flength(str))<1) { /* Bugfix Aug-20-2003: Reject negative length */ bputs(text[Aborted]); return(false); } bputs(text[WritingIndx]); if((i=smb_stack(&smb,SMB_STACK_PUSH))!=SMB_SUCCESS) { errormsg(WHERE,ERR_OPEN,cfg.sub[subnum]->code,i,smb.last_error); return(false); } smb.subnum=subnum; if((i=msgbase_open(&cfg,&smb,&storage,&dupechk_hashes,&xlat))!=SMB_SUCCESS) { errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); smb_stack(&smb,SMB_STACK_POP); return(false); } if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) { smb_close(&smb); errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); smb_stack(&smb,SMB_STACK_POP); return(false); } if((i=smb_getstatus(&smb))!=SMB_SUCCESS) { smb_close(&smb); errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); smb_stack(&smb,SMB_STACK_POP); return(false); } if((msgbuf=(char*)calloc(length+1,sizeof(char))) == NULL) { smb_close(&smb); errormsg(WHERE,ERR_ALLOC,"msgbuf",length+1); smb_stack(&smb,SMB_STACK_POP); return(false); } if((fp=fopen(str,"rb"))==NULL) { free(msgbuf); smb_close(&smb); errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY); smb_stack(&smb,SMB_STACK_POP); return(false); } i=fread(msgbuf,1,length,fp); fclose(fp); if(i != length) { free(msgbuf); smb_close(&smb); errormsg(WHERE,ERR_READ,str,length); smb_stack(&smb,SMB_STACK_POP); return(false); } truncsp(msgbuf); /* ToDo: split body/tail */ memset(&msg,0,sizeof(msg)); msg.hdr.attr=msgattr; msg.hdr.when_written.time=msg.hdr.when_imported.time=time32(NULL); msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg); msg.hdr.number=smb.status.last_msg+1; /* this *should* be the new message number */ if(remsg) { msg.hdr.thread_back=remsg->hdr.number; /* needed for threading backward */ if((msg.hdr.thread_id=remsg->hdr.thread_id) == 0) msg.hdr.thread_id=remsg->hdr.number; /* Add RFC-822 Reply-ID (generate if necessary) */ if(remsg->id!=NULL) smb_hfield_str(&msg,RFC822REPLYID,remsg->id); /* Add FidoNet Reply if original message has FidoNet MSGID */ if(remsg->ftn_msgid!=NULL) smb_hfield_str(&msg,FIDOREPLYID,remsg->ftn_msgid); if((i=smb_updatethread(&smb, remsg, smb.status.last_msg+1))!=SMB_SUCCESS) errormsg(WHERE,"updating thread",smb.file,i,smb.last_error); } smb_hfield_str(&msg,RECIPIENT,touser); SAFECOPY(str,cfg.sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias); smb_hfield_str(&msg,SENDER,str); sprintf(str,"%u",useron.number); smb_hfield_str(&msg,SENDEREXT,str); /* Security logging */ msg_client_hfields(&msg,&client); smb_hfield_str(&msg,SENDERSERVER,startup->host_name); smb_hfield_str(&msg,SUBJECT,title); /* Generate default (RFC822) message-id (always) */ get_msgid(&cfg,subnum,&msg,msg_id,sizeof(msg_id)); smb_hfield_str(&msg,RFC822MSGID,msg_id); /* Generate FTN (FTS-9) MSGID */ if(cfg.sub[subnum]->misc&SUB_FIDO) { ftn_msgid(cfg.sub[subnum],&msg,msg_id,sizeof(msg_id)); smb_hfield_str(&msg,FIDOMSGID,msg_id); } /* Generate FidoNet Program Identifier */ smb_hfield_str(&msg,FIDOPID,msg_program_id(pid)); if(editor!=NULL) smb_hfield_str(&msg,SMB_EDITOR,editor); i=smb_addmsg(&smb,&msg,storage,dupechk_hashes,xlat,(uchar*)msgbuf,NULL); free(msgbuf); if(i==SMB_DUPE_MSG) { attr(cfg.color[clr_err]); bprintf(text[CantPostMsg], smb.last_error); } else if(i!=SMB_SUCCESS) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); smb_freemsgmem(&msg); if(i!=SMB_SUCCESS) return(false); logon_posts++; user_posted_msg(&cfg, &useron, 1); bprintf(text[Posted],cfg.grp[cfg.sub[subnum]->grp]->sname ,cfg.sub[subnum]->lname); sprintf(str,"%s posted on %s %s" ,useron.alias,cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->lname); logline("P+",str); signal_sub_sem(&cfg,subnum); user_event(EVENT_POST); return(true); }
void sbbs_t::readmail(uint usernumber, int which) { char str[256],str2[256],str3[256],done=0,domsg=1 ,*p,*tp,*sp,ch; char tmp[512]; int i,j; int error; int mismatches=0,act; long length,l,lm_mode; ulong last; bool replied; file_t fd; mail_t *mail; smbmsg_t msg; if(which==MAIL_SENT && useron.rest&FLAG('K')) { bputs(text[R_ReadSentMail]); return; } msg.total_hfields=0; /* init to NULL, cause not allocated yet */ fd.dir=cfg.total_dirs+1; /* temp dir for file attachments */ if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) { errormsg(WHERE,ERR_OPEN,"MAIL",i); return; } sprintf(smb.file,"%smail",cfg.data_dir); smb.retry_time=cfg.smb_retry_time; smb.subnum=INVALID_SUB; if((i=smb_open(&smb))!=0) { smb_stack(&smb,SMB_STACK_POP); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return; } if(cfg.sys_misc&SM_SYSVDELM && (SYSOP || cfg.sys_misc&SM_USRVDELM)) lm_mode=LM_INCDEL; else lm_mode=0; mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); if(!smb.msgs) { if(which==MAIL_SENT) bputs(text[NoMailSent]); else if(which==MAIL_ALL) bputs(text[NoMailOnSystem]); else bputs(text[NoMailWaiting]); smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); return; } last=smb.status.last_msg; if(which==MAIL_SENT) act=NODE_RSML; else if(which==MAIL_ALL) act=NODE_SYSP; else act=NODE_RMAL; action=act; if(smb.msgs>1 && which!=MAIL_ALL) { if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else bputs(text[MailWaitingLstHdr]); for(smb.curmsg=0;smb.curmsg<smb.msgs && !msgabort();smb.curmsg++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[smb.curmsg].offset; if(!loadmsg(&msg,mail[smb.curmsg].number)) continue; smb_unlockmsghdr(&smb,&msg); bprintf(text[MailWaitingLstFmt],smb.curmsg+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } ASYNC; if(!(sys_status&SS_ABORT)) { bprintf(text[StartWithN],1L); if((long)(smb.curmsg=getnum(smb.msgs))>0) smb.curmsg--; else if((long)smb.curmsg==-1) { free(mail); smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); return; } } sys_status&=~SS_ABORT; } else { smb.curmsg=0; if(which==MAIL_ALL) domsg=0; } if(which==MAIL_SENT) { sprintf(str,"%s read sent mail",useron.alias); logline("E",str); } else if(which==MAIL_ALL) { sprintf(str,"%s read all mail",useron.alias); logline("S+",str); } else { sprintf(str,"%s read mail",useron.alias); logline("E",str); } if(useron.misc&RIP) { strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); } while(online && !done) { action=act; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[smb.curmsg].offset; msg.idx.number=mail[smb.curmsg].number; msg.idx.to=mail[smb.curmsg].to; msg.idx.from=mail[smb.curmsg].from; msg.idx.subj=mail[smb.curmsg].subj; if((i=smb_locksmbhdr(&smb))!=0) { errormsg(WHERE,ERR_LOCK,smb.file,i); break; } if((i=smb_getstatus(&smb))!=0) { smb_unlocksmbhdr(&smb); errormsg(WHERE,ERR_READ,smb.file,i); break; } smb_unlocksmbhdr(&smb); if(smb.status.last_msg!=last) { /* New messages */ last=smb.status.last_msg; free(mail); mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); /* So re-load */ if(!smb.msgs) break; for(smb.curmsg=0;smb.curmsg<smb.msgs;smb.curmsg++) if(mail[smb.curmsg].number==msg.idx.number) break; if(smb.curmsg>=smb.msgs) smb.curmsg=(smb.msgs-1); continue; } if(!loadmsg(&msg,mail[smb.curmsg].number)) { /* Message header gone */ if(mismatches>5) { /* We can't do this too many times in a row */ errormsg(WHERE,ERR_CHK,"message number",mail[smb.curmsg].number); break; } free(mail); mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); if(!smb.msgs) break; if(smb.curmsg>(smb.msgs-1)) smb.curmsg=(smb.msgs-1); mismatches++; continue; } smb_unlockmsghdr(&smb,&msg); msg.idx.attr=msg.hdr.attr; mismatches=0; if(domsg && !(sys_status&SS_ABORT)) { show_msg(&msg ,msg.from_ext && msg.idx.from==1 && !msg.from_net.type ? 0:P_NOATCODES); if(msg.hdr.auxattr&MSG_FILEATTACH) { /* Attached file */ smb_getmsgidx(&smb,&msg); strcpy(str,msg.subj); /* filenames in title */ // strupr(str); tp=str; while(online) { p=strchr(tp,' '); if(p) *p=0; sp=strrchr(tp,'/'); /* sp is slash pointer */ if(!sp) sp=strrchr(tp,'\\'); if(sp) tp=sp+1; padfname(tp,fd.name); sprintf(str2,"%sfile/%04u.in/%s" /* str2 is path/fname */ ,cfg.data_dir,msg.idx.to,tp); length=flength(str2); if(length<1) bputs(text[FileNotFound]); else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP && length/(long)cur_cps>(time_t)timeleft) bputs(text[NotEnoughTimeToDl]); else { sprintf(str3,text[DownloadAttachedFileQ] ,tp,ultoac(length,tmp)); if(length>0L && yesno(str3)) { #if 0 /* no such thing as local logon */ if(online==ON_LOCAL) { bputs(text[EnterPath]); if(getstr(str3,60,K_LINE)) { backslashcolon(str3); sprintf(tmp,"%s%s",str3,tp); if(!mv(str2,tmp,which!=MAIL_YOUR)) { logon_dlb+=length; logon_dls++; useron.dls=(ushort)adjustuserrec(&cfg,useron.number ,U_DLS,5,1); useron.dlb=adjustuserrec(&cfg,useron.number ,U_DLB,10,length); bprintf(text[FileNBytesSent] ,fd.name,ultoac(length,tmp)); } } } else #endif { /* Remote User */ xfer_prot_menu(XFER_DOWNLOAD); mnemonics(text[ProtocolOrQuit]); strcpy(str3,"Q"); for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron)) { sprintf(tmp,"%c",cfg.prot[i]->mnemonic); strcat(str3,tmp); } ch=(char)getkeys(str3,0); for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic && chk_ar(cfg.prot[i]->ar,&useron)) break; if(i<cfg.total_prots) { error=protocol(cfg.prot[i],XFER_DOWNLOAD,str2,nulstr,false); if(checkprotresult(cfg.prot[i],error,&fd)) { if(which==MAIL_YOUR) remove(str2); logon_dlb+=length; /* Update stats */ logon_dls++; useron.dls=(ushort)adjustuserrec(&cfg,useron.number ,U_DLS,5,1); useron.dlb=adjustuserrec(&cfg,useron.number ,U_DLB,10,length); bprintf(text[FileNBytesSent] ,fd.name,ultoac(length,tmp)); sprintf(str3 ,"%s downloaded attached file: %s" ,useron.alias ,fd.name); logline("D-",str3); } autohangup(); } } } } if(!p) break; tp=p+1; while(*tp==' ') tp++; } sprintf(str,"%sfile/%04u.in",cfg.data_dir,usernumber); rmdir(str); } if(which==MAIL_YOUR && !(msg.hdr.attr&MSG_READ)) { mail[smb.curmsg].attr|=MSG_READ; if(thisnode.status==NODE_INUSE) telluser(&msg); if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; /* Search by number */ if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_READ; msg.idx.attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } if(!msg.total_hfields) { /* unsuccessful reload */ domsg=0; continue; } } } else domsg=1; if(useron.misc&WIP) { strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); } ASYNC; if(which==MAIL_SENT) bprintf(text[ReadingSentMail],smb.curmsg+1,smb.msgs); else if(which==MAIL_ALL) bprintf(text[ReadingAllMail],smb.curmsg+1,smb.msgs); else bprintf(text[ReadingMail],smb.curmsg+1,smb.msgs); sprintf(str,"ADFLNQRT?<>[]{}-+"); if(SYSOP) strcat(str,"CUSPH"); if(which!=MAIL_YOUR) strcat(str,"E"); l=getkeys(str,smb.msgs); if(l&0x80000000L) { if(l==-1) /* ctrl-c */ break; smb.curmsg=(l&~0x80000000L)-1; continue; } switch(l) { case 'A': /* Auto-reply to last piece */ case 'R': if(l==(cfg.sys_misc&SM_RA_EMU ? 'A' : 'R')) /* re-read last message */ break; if(which==MAIL_SENT) break; if((msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP) { bputs(text[CantReplyToAnonMsg]); break; } quotemsg(&msg,1); if(msg.from_net.addr==NULL) SAFECOPY(str,msg.from); else if(msg.from_net.type==NET_FIDO) /* FidoNet type */ SAFEPRINTF2(str,"%s@%s",msg.from ,smb_faddrtoa((faddr_t *)msg.from_net.addr,tmp)); else if(msg.from_net.type==NET_INTERNET) { if(msg.replyto_net.type==NET_INTERNET) SAFECOPY(str,(char *)msg.replyto_net.addr); else SAFECOPY(str,(char *)msg.from_net.addr); } else SAFEPRINTF2(str,"%s@%s",msg.from,(char*)msg.from_net.addr); SAFECOPY(str2,str); bputs(text[Email]); if(!getstr(str,64,K_EDIT|K_AUTODEL)) break; msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); if(!stricmp(str2,str)) /* Reply to sender */ sprintf(str2,text[Regarding],msg.subj); else /* Reply to other */ sprintf(str2,text[RegardingByOn],msg.subj,msg.from ,timestr((time_t *)&msg.hdr.when_written.time)); p=strrchr(str,'@'); if(p) { /* name @addr */ replied=netmail(str,msg.subj,WM_QUOTE); sprintf(str2,text[DeleteMailQ],msg.from); } else { if(!msg.from_net.type && !stricmp(str,msg.from)) replied=email(msg.idx.from,str2,msg.subj,WM_EMAIL|WM_QUOTE); else if(!stricmp(str,"SYSOP")) replied=email(1,str2,msg.subj,WM_EMAIL|WM_QUOTE); else if((i=finduser(str))!=0) replied=email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE); else replied=false; sprintf(str2,text[DeleteMailQ],msg.from); } if(replied==true && !(msg.hdr.attr&MSG_REPLIED)) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_REPLIED; msg.idx.attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } } if(msg.hdr.attr&MSG_DELETE || !yesno(str2)) { if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; } /* Case 'D': must follow! */ case 'D': /* Delete last piece (toggle) */ if(msg.hdr.attr&MSG_PERMANENT) { bputs("\r\nPermanent message.\r\n"); domsg=0; break; } if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr^=MSG_DELETE; msg.idx.attr=msg.hdr.attr; // mail[smb.curmsg].attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; case 'F': /* Forward last piece */ domsg=0; bputs(text[ForwardMailTo]); if(!getstr(str,LEN_ALIAS,cfg.uq&UQ_NOUPRLWR ? K_NONE:K_UPRLWR)) break; i=finduser(str); if(!i) break; domsg=1; if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; smb_getmsgidx(&smb,&msg); forwardmail(&msg,i); if(msg.hdr.attr&MSG_PERMANENT) break; sprintf(str2,text[DeleteMailQ],msg.from); if(!yesno(str2)) break; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_DELETE; msg.idx.attr=msg.hdr.attr; // mail[smb.curmsg].attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } break; case 'H': domsg=0; msghdr(&msg); break; case 'L': /* List mail */ domsg=0; bprintf(text[StartWithN],(long)smb.curmsg+1); if((i=getnum(smb.msgs))>0) i--; else if(i==-1) break; else i=smb.curmsg; if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else if(which==MAIL_ALL) bputs(text[MailOnSystemLstHdr]); else bputs(text[MailWaitingLstHdr]); for(;i<smb.msgs && !msgabort();i++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[i].offset; if(!loadmsg(&msg,mail[i].number)) continue; smb_unlockmsghdr(&smb,&msg); if(which==MAIL_ALL) bprintf(text[MailOnSystemLstFmt] ,i+1,msg.from,msg.to ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); else bprintf(text[MailWaitingLstFmt],i+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } break; case 'Q': done=1; break; case 'C': /* Change attributes of last piece */ i=chmsgattr(msg.hdr.attr); if(msg.hdr.attr==i) break; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr=msg.idx.attr=(ushort)i; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } break; case '>': for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].subj==msg.idx.subj) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '<': /* Search Title backward */ for(i=smb.curmsg-1;i>-1;i--) if(mail[i].subj==msg.idx.subj) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case '}': /* Search Author forward */ strcpy(str,msg.from); for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].from==msg.idx.from) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case 'N': /* Got to next un-read message */ for(i=smb.curmsg+1;i<smb.msgs;i++) if(!(mail[i].attr&MSG_READ)) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '{': /* Search Author backward */ strcpy(str,msg.from); for(i=smb.curmsg-1;i>-1;i--) if(mail[i].from==msg.idx.from) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case ']': /* Search To User forward */ strcpy(str,msg.to); for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].to==msg.idx.to) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '[': /* Search To User backward */ strcpy(str,msg.to); for(i=smb.curmsg-1;i>-1;i--) if(mail[i].to==msg.idx.to) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case 0: case '+': if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; case '-': if(smb.curmsg>0) smb.curmsg--; break; case 'S': domsg=0; /* if(!yesno(text[SaveMsgToFile])) break; */ bputs(text[FileToWriteTo]); if(getstr(str,40,K_LINE)) msgtotxt(&msg,str,1,1); break; case 'E': editmsg(&msg,INVALID_SUB); break; case 'T': domsg=0; i=smb.curmsg; if(i) i++; j=i+10; if(j>smb.msgs) j=smb.msgs; if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else if(which==MAIL_ALL) bputs(text[MailOnSystemLstHdr]); else bputs(text[MailWaitingLstHdr]); for(;i<j;i++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[i].offset; if(!loadmsg(&msg,mail[i].number)) continue; smb_unlockmsghdr(&smb,&msg); if(which==MAIL_ALL) bprintf(text[MailOnSystemLstFmt] ,i+1,msg.from,msg.to ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); else bprintf(text[MailWaitingLstFmt],i+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } smb.curmsg=(i-1); break; case 'U': /* user edit */ msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); useredit(which==MAIL_SENT ? msg.idx.to : msg.idx.from); break; case 'P': /* Purge author and all mail to/from */ if(noyes(text[AreYouSureQ])) break; msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); purgeuser(msg.idx.from); if(smb.curmsg<smb.msgs-1) smb.curmsg++; break; case '?': strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); if(SYSOP && which==MAIL_SENT) menu("syssmail"); else if(SYSOP && which==MAIL_YOUR) menu("sysmailr"); /* Sysop Mail Read */ domsg=0; break; } } if(msg.total_hfields) smb_freemsgmem(&msg); if(smb.msgs) free(mail); /***************************************/ /* Delete messages marked for deletion */ /***************************************/ if(cfg.sys_misc&SM_DELEMAIL) { if((i=smb_locksmbhdr(&smb))!=0) /* Lock the base, so nobody */ errormsg(WHERE,ERR_LOCK,smb.file,i); /* messes with the index */ else delmail(usernumber,which); } smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); }
void maint(void) { int i; ulong l,m,n,f,flagged=0; time_t now; smbmsg_t msg; idxrec_t *idx; printf("Maintaining %s\r\n",smb.file); now=time(NULL); i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } if(smb_open_hash(&smb) == SMB_SUCCESS) { ulong max_hashes=0; printf("Maintaining %s hash file\r\n", smb.file); if((smb.status.attr&(SMB_EMAIL|SMB_NOHASH)) == 0) { max_hashes = smb.status.max_msgs; if(smb.status.max_crcs > max_hashes) max_hashes = smb.status.max_crcs; } if(!max_hashes) { CHSIZE_FP(smb.hash_fp,0); } else if(filelength(fileno(smb.hash_fp)) > (long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))) { if(fseek(smb.hash_fp, -((long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))), SEEK_END) == 0) { hash_t* hashes = malloc(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t)); if(hashes != NULL) { if(fread(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp) == max_hashes * SMB_HASH_SOURCE_TYPES) { CHSIZE_FP(smb.hash_fp,0); rewind(smb.hash_fp); fwrite(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp); } free(hashes); } } } smb_close_hash(&smb); } if(!smb.status.total_msgs) { smb_unlocksmbhdr(&smb); printf("Empty\n"); return; } printf("Loading index...\n"); if((idx=(idxrec_t *)malloc(sizeof(idxrec_t)*smb.status.total_msgs)) ==NULL) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!Error allocating %u bytes of memory\n" ,beep,sizeof(idxrec_t)*smb.status.total_msgs); return; } fseek(smb.sid_fp,0L,SEEK_SET); for(l=0;l<smb.status.total_msgs;l++) { printf("%lu of %"PRIu32"\r" ,l+1,smb.status.total_msgs); if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp)) break; } printf("\nDone.\n\n"); printf("Scanning for pre-flagged messages...\n"); for(m=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&MSG_DELETE) flagged++; } printf("\r100%% (%lu pre-flagged for deletion)\n",flagged); if(smb.status.max_age) { printf("Scanning for messages more than %u days old...\n" ,smb.status.max_age); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L) >smb.status.max_age) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } /* mark for deletion */ printf("\r100%% (%lu flagged for deletion due to age)\n",f); } printf("Scanning for read messages to be killed...\n"); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } printf("\r100%% (%lu flagged for deletion due to read status)\n",f); if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) { printf("Flagging excess messages for deletion...\n"); for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) { if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs); flagged++; idx[m].attr|=MSG_DELETE; } /* mark for deletion */ printf("\nDone.\n\n"); } if(!flagged) { /* No messages to delete */ free(idx); smb_unlocksmbhdr(&smb); return; } if(!(mode&NOANALYSIS)) { printf("Freeing allocated header and data blocks for deleted messages...\n"); if(!(smb.status.attr&SMB_HYPERALLOC)) { i=smb_open_da(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } i=smb_open_ha(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } } for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) { printf("%lu of %lu\r",++n,flagged); msg.idx=idx[m]; msg.hdr.number=msg.idx.number; if((i=smb_getmsgidx(&smb,&msg))!=0) { fprintf(errfp,"\n%s!smb_getmsgidx returned %d: %s\n" ,beep,i,smb.last_error); continue; } i=smb_lockmsghdr(&smb,&msg); if(i) { fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } if((i=smb_getmsghdr(&smb,&msg))!=0) { smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */ if((i=smb_putmsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_putmsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_unlockmsghdr(&smb,&msg); if((i=smb_freemsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); fprintf(errfp,"\n%s!smb_freemsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_freemsgmem(&msg); } } if(!(smb.status.attr&SMB_HYPERALLOC)) { smb_close_ha(&smb); smb_close_da(&smb); } printf("\nDone.\n\n"); } printf("Re-writing index...\n"); rewind(smb.sid_fp); CHSIZE_FP(smb.sid_fp,0); for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) continue; printf("%lu of %lu\r",++n,l-flagged); fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); } printf("\nDone.\n\n"); fflush(smb.sid_fp); free(idx); smb.status.total_msgs-=flagged; smb_putstatus(&smb); smb_unlocksmbhdr(&smb); }
void config(void) { char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128]; int i; i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); smb_unlocksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } printf("Header offset =%-5"PRIu32" New value (CR=No Change): " ,smb.status.header_offset); gets(header_offset); printf("Max msgs =%-5"PRIu32" New value (CR=No Change): " ,smb.status.max_msgs); gets(max_msgs); printf("Max crcs =%-5"PRIu32" New value (CR=No Change): " ,smb.status.max_crcs); gets(max_crcs); printf("Max age =%-5u New value (CR=No Change): " ,smb.status.max_age); gets(max_age); printf("Attributes =%-5u New value (CR=No Change): " ,smb.status.attr); gets(attr); i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); if(i) { fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); smb_unlocksmbhdr(&smb); return; } if(isdigit(max_msgs[0])) smb.status.max_msgs=atol(max_msgs); if(isdigit(max_crcs[0])) smb.status.max_crcs=atol(max_crcs); if(isdigit(max_age[0])) smb.status.max_age=atoi(max_age); if(isdigit(header_offset[0])) smb.status.header_offset=atol(header_offset); if(isdigit(attr[0])) smb.status.attr=atoi(attr); i=smb_putstatus(&smb); smb_unlocksmbhdr(&smb); if(i) fprintf(errfp,"\n%s!smb_putstatus returned %d: %s\n" ,beep,i,smb.last_error); }
int sbbs_t::delmail(uint usernumber, int which) { ulong i,l; time_t now; idxrec_t *idxbuf; smbmsg_t msg; now=time(NULL); if((i=smb_getstatus(&smb))!=0) { errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); return(2); } if(!smb.status.total_msgs) return(0); if((idxbuf=(idxrec_t *)malloc(smb.status.total_msgs*sizeof(idxrec_t)))==NULL) { errormsg(WHERE,ERR_ALLOC,smb.file,smb.status.total_msgs*sizeof(idxrec_t)); return(-1); } if((i=smb_open_da(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); free(idxbuf); return(i); } if((i=smb_open_ha(&smb))!=0) { smb_close_da(&smb); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); free(idxbuf); return(i); } smb_rewind(smb.sid_fp); for(l=0;l<smb.status.total_msgs;) { if(smb_fread(&smb,&msg.idx,sizeof(idxrec_t),smb.sid_fp)!=sizeof(idxrec_t)) break; if(!(msg.idx.attr&MSG_PERMANENT) && ((which==MAIL_SENT && usernumber==msg.idx.from) || (which==MAIL_YOUR && usernumber==msg.idx.to) || (which==MAIL_ANY && (usernumber==msg.idx.to || usernumber==msg.idx.from)) || which==MAIL_ALL)) { if(smb.status.max_age && (now<0?0:(uintmax_t)now)>msg.idx.time && (now-msg.idx.time)/(24L*60L*60L)>smb.status.max_age) msg.idx.attr|=MSG_DELETE; else if(msg.idx.attr&MSG_KILLREAD && msg.idx.attr&MSG_READ) msg.idx.attr|=MSG_DELETE; if(msg.idx.attr&MSG_DELETE) { /* Don't need to lock message because base is locked */ if((i=smb_getmsghdr(&smb,&msg))!=0) errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); else { if(msg.hdr.attr!=msg.idx.attr) { msg.hdr.attr=msg.idx.attr; if((i=smb_putmsghdr(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); } if((i=smb_freemsg(&smb,&msg))!=0) errormsg(WHERE,ERR_REMOVE,smb.file,i,smb.last_error); if(msg.hdr.auxattr&MSG_FILEATTACH) delfattach(&cfg,&msg); smb_freemsgmem(&msg); } continue; } } idxbuf[l]=msg.idx; l++; } smb_rewind(smb.sid_fp); smb_fsetlength(smb.sid_fp,0); for(i=0;i<l;i++) smb_fwrite(&smb,&idxbuf[i],sizeof(idxrec_t),smb.sid_fp); free(idxbuf); smb.status.total_msgs=l; smb_putstatus(&smb); smb_fflush(smb.sid_fp); smb_close_ha(&smb); smb_close_da(&smb); return(0); }
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); }