bool sbbs_t::answer() { char str[MAX_PATH+1],str2[MAX_PATH+1],c; char tmp[(MAX_PATH > CRYPT_MAX_TEXTSIZE ? MAX_PATH:CRYPT_MAX_TEXTSIZE)+1]; char tmpname[CRYPT_MAX_TEXTSIZE+1]; char path[MAX_PATH+1]; int i,l,in; struct tm tm; useron.number=0; answertime=logontime=starttime=now=time(NULL); /* Caller ID is IP address */ SAFECOPY(cid,client_ipaddr); memset(&tm,0,sizeof(tm)); localtime_r(&now,&tm); safe_snprintf(str,sizeof(str),"%s %s %s %02d %u Node %3u" ,hhmmtostr(&cfg,&tm,str2) ,wday[tm.tm_wday] ,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900,cfg.node_num); logline("@ ",str); safe_snprintf(str,sizeof(str),"%s %s [%s]", connection, client_name, cid); logline("@+:",str); if(client_ident[0]) { safe_snprintf(str,sizeof(str),"Identity: %s",client_ident); logline("@*",str); } online=ON_REMOTE; if(sys_status&SS_RLOGIN) { if(incom(1000)==0) { for(i=0;i<(int)sizeof(str)-1;i++) { in=incom(1000); if(in==0 || in==NOINP) break; str[i]=in; } str[i]=0; for(i=0;i<(int)sizeof(str2)-1;i++) { in=incom(1000); if(in==0 || in==NOINP) break; str2[i]=in; } str2[i]=0; for(i=0;i<(int)sizeof(terminal)-1;i++) { in=incom(1000); if(in==0 || in==NOINP) break; terminal[i]=in; } terminal[i]=0; lprintf(LOG_DEBUG,"Node %d RLogin: '******' / '%.*s' / '%s'" ,cfg.node_num ,LEN_ALIAS*2,str ,LEN_ALIAS*2,str2 ,terminal); SAFECOPY(rlogin_term, terminal); SAFECOPY(rlogin_name, str2); SAFECOPY(rlogin_pass, str); /* Truncate terminal speed (e.g. "/57600") from terminal-type string (but keep full terminal type/speed string in rlogin_term): */ truncstr(terminal,"/"); useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name); if(useron.number) { getuserdat(&cfg,&useron); useron.misc&=~TERM_FLAGS; SAFEPRINTF(path,"%srlogin.cfg",cfg.ctrl_dir); if(!findstr(client.addr,path)) { SAFECOPY(tmp, rlogin_pass); for(i=0;i<3;i++) { if(stricmp(tmp,useron.pass)) { badlogin(useron.alias, tmp); rioctl(IOFI); /* flush input buffer */ bputs(text[InvalidLogon]); if(cfg.sys_misc&SM_ECHO_PW) safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt: '%s'" ,0,useron.alias,tmp); else safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt" ,0,useron.alias); logline(LOG_NOTICE,"+!",str); bputs(text[PasswordPrompt]); console|=CON_R_ECHOX; getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB); console&=~(CON_R_ECHOX|CON_L_ECHOX); } else { if(REALSYSOP) { rioctl(IOFI); /* flush input buffer */ if(!chksyspass()) bputs(text[InvalidLogon]); else { i=0; break; } } else break; } } if(i) { if(stricmp(tmp,useron.pass)) { badlogin(useron.alias, tmp); bputs(text[InvalidLogon]); if(cfg.sys_misc&SM_ECHO_PW) safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt: '%s'" ,0,useron.alias,tmp); else safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt" ,0,useron.alias); logline(LOG_NOTICE,"+!",str); } lprintf(LOG_WARNING,"Node %d !CLIENT IP NOT LISTED in %s" ,cfg.node_num,path); useron.number=0; hangup(); } } } else lprintf(LOG_INFO,"Node %d RLogin: Unknown user: %s",cfg.node_num,rlogin_name); } if(rlogin_name[0]==0) { lprintf(LOG_NOTICE,"Node %d !RLogin: No user name received",cfg.node_num); sys_status&=~SS_RLOGIN; } } if(!(telnet_mode&TELNET_MODE_OFF)) { /* Disable Telnet Terminal Echo */ request_telnet_opt(TELNET_WILL,TELNET_ECHO); /* Will suppress Go Ahead */ request_telnet_opt(TELNET_WILL,TELNET_SUP_GA); /* Retrieve terminal type and speed from telnet client --RS */ request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE); request_telnet_opt(TELNET_DO,TELNET_TERM_SPEED); request_telnet_opt(TELNET_DO,TELNET_SEND_LOCATION); request_telnet_opt(TELNET_DO,TELNET_NEGOTIATE_WINDOW_SIZE); request_telnet_opt(TELNET_DO,TELNET_NEW_ENVIRON); } #ifdef USE_CRYPTLIB if(sys_status&SS_SSH) { pthread_mutex_lock(&ssh_mutex); cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, tmpname, &i); tmpname[i]=0; SAFECOPY(rlogin_name, tmpname); cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, tmp, &i); tmp[i]=0; SAFECOPY(rlogin_pass, tmp); pthread_mutex_unlock(&ssh_mutex); lprintf(LOG_DEBUG,"Node %d SSH login: '******'" ,cfg.node_num, tmpname); useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, tmpname); if(useron.number) { getuserdat(&cfg,&useron); useron.misc&=~TERM_FLAGS; for(i=0;i<3;i++) { if(stricmp(tmp,useron.pass)) { badlogin(useron.alias, tmp); rioctl(IOFI); /* flush input buffer */ bputs(text[InvalidLogon]); if(cfg.sys_misc&SM_ECHO_PW) safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt: '%s'" ,0,useron.alias,tmp); else safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt" ,0,useron.alias); /* crash here Sept-12-2010 str 0x06b3fc4c "(0000) Guest FAILED Password attempt: '*****@*****.**'" and Oct-6-2010 str 0x070ffc4c "(0000) Woot903 FAILED Password attempt: 'p67890pppsdsjhsdfhhfhnhnfhfhfdhjksdjkfdskw3902391=`'" char [261] */ logline(LOG_NOTICE,"+!",str); bputs(text[PasswordPrompt]); console|=CON_R_ECHOX; getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB); console&=~(CON_R_ECHOX|CON_L_ECHOX); } else { if(REALSYSOP) { rioctl(IOFI); /* flush input buffer */ if(!chksyspass()) bputs(text[InvalidLogon]); else { i=0; break; } } else break; } } if(i) { if(stricmp(tmp,useron.pass)) { badlogin(useron.alias, tmp); bputs(text[InvalidLogon]); if(cfg.sys_misc&SM_ECHO_PW) safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt: '%s'" ,0,useron.alias,tmp); else safe_snprintf(str,sizeof(str),"(%04u) %-25s FAILED Password attempt" ,0,useron.alias); logline(LOG_NOTICE,"+!",str); } useron.number=0; hangup(); } } else lprintf(LOG_INFO,"Node %d SSH: Unknown user: %s",cfg.node_num,rlogin_name); } #endif /* Detect terminal type */ mswait(200); rioctl(IOFI); /* flush input buffer */ putcom( "\r\n" /* locate cursor at column 1 */ "\x1b[s" /* save cursor position (necessary for HyperTerm auto-ANSI) */ "\x1b[255B" /* locate cursor as far down as possible */ "\x1b[255C" /* locate cursor as far right as possible */ "\b_" /* need a printable at this location to actually move cursor */ "\x1b[6n" /* Get cursor position */ "\x1b[u" /* restore cursor position */ "\x1b[!_" /* RIP? */ "\x1b[30;40m\xc2\x9f""Zuul.connection.write('\\x1b""Are you the gatekeeper?')\xc2\x9c" /* ZuulTerm? */ "\x1b[0m_" /* "Normal" colors */ "\x1b[2J" /* clear screen */ "\x1b[H" /* home cursor */ "\xC" /* clear screen (in case not ANSI) */ "\r" /* Move cursor left (in case previous char printed) */ ); i=l=0; tos=1; lncntr=0; safe_snprintf(str, sizeof(str), "%s %s", VERSION_NOTICE, COPYRIGHT_NOTICE); strip_ctrl(str, str); center(str); while(i++<50 && l<(int)sizeof(str)-1) { /* wait up to 5 seconds for response */ c=incom(100)&0x7f; if(c==0) continue; i=0; if(l==0 && c!=ESC) // response must begin with escape char continue; str[l++]=c; if(c=='R') { /* break immediately if ANSI response */ mswait(500); break; } } while((c=(incom(100)&0x7f))!=0 && l<(int)sizeof(str)-1) str[l++]=c; str[l]=0; if(l) { c_escape_str(str,tmp,sizeof(tmp),TRUE); lprintf(LOG_DEBUG,"Node %d received terminal auto-detection response: '%s'" ,cfg.node_num,tmp); if(str[0]==ESC && str[1]=='[' && str[l-1]=='R') { int x,y; if(terminal[0]==0) SAFECOPY(terminal,"ANSI"); autoterm|=(ANSI|COLOR); if(sscanf(str+2,"%u;%u",&y,&x)==2) { lprintf(LOG_DEBUG,"Node %d received ANSI cursor position report: %ux%u" ,cfg.node_num, x, y); /* Sanity check the coordinates in the response: */ if(x>=40 && x<=255) cols=x; if(y>=10 && y<=255) rows=y; } } truncsp(str); if(strstr(str,"RIPSCRIP")) { if(terminal[0]==0) SAFECOPY(terminal,"RIP"); logline("@R",strstr(str,"RIPSCRIP")); autoterm|=(RIP|COLOR|ANSI); } else if(strstr(str,"Are you the gatekeeper?")) { if(terminal[0]==0) SAFECOPY(terminal,"HTML"); logline("@H",strstr(str,"Are you the gatekeeper?")); autoterm|=HTML; } } else if(terminal[0]==0) SAFECOPY(terminal,"DUMB"); rioctl(IOFI); /* flush left-over or late response chars */ if(!autoterm && str[0]) { c_escape_str(str,tmp,sizeof(tmp),TRUE); lprintf(LOG_NOTICE,"Node %d terminal auto-detection failed, response: '%s'" ,cfg.node_num, tmp); } /* AutoLogon via IP or Caller ID here */ if(!useron.number && !(sys_status&SS_RLOGIN) && (startup->options&BBS_OPT_AUTO_LOGON) && cid[0]) { useron.number=userdatdupe(0, U_NOTE, LEN_NOTE, cid); if(useron.number) { getuserdat(&cfg, &useron); if(!(useron.misc&AUTOLOGON) || !(useron.exempt&FLAG('V'))) useron.number=0; } } if(!online) return(false); if(stricmp(terminal,"sexpots")==0) { /* dial-up connection (via SexPOTS) */ SAFEPRINTF2(str,"%s connection detected at %lu bps", terminal, cur_rate); logline("@S",str); node_connection = (ushort)cur_rate; SAFEPRINTF(connection,"%lu",cur_rate); SAFECOPY(cid,"Unknown"); SAFECOPY(client_name,"Unknown"); if(telnet_location[0]) { /* Caller-ID info provided */ SAFEPRINTF(str, "CID: %s", telnet_location); logline("@*",str); SAFECOPY(cid,telnet_location); truncstr(cid," "); /* Only include phone number in CID */ char* p=telnet_location; FIND_WHITESPACE(p); SKIP_WHITESPACE(p); if(*p) { SAFECOPY(client_name,p); /* CID name, if provided (maybe 'P' or 'O' if private or out-of-area) */ } } SAFECOPY(client.addr,cid); SAFECOPY(client.host,client_name); client_on(client_socket,&client,TRUE /* update */); } else { if(telnet_location[0]) { /* Telnet Location info provided */ SAFEPRINTF(str, "Telnet Location: %s", telnet_location); logline("@*",str); } } useron.misc&=~TERM_FLAGS; useron.misc|=autoterm; SAFECOPY(useron.comp,client_name); if(!useron.number && rlogin_name[0]!=0 && !(cfg.sys_misc&SM_CLOSED) && !matchuser(&cfg, rlogin_name, /* Sysop alias: */FALSE)) { lprintf(LOG_INFO,"Node %d UNKNOWN %s-specified USERNAME: %s, starting new user signup",cfg.node_num,client.protocol,rlogin_name); bprintf("%s: %s\r\n", text[UNKNOWN_USER], rlogin_name); newuser(); } if(!useron.number) { /* manual/regular logon */ /* Display ANSWER screen */ rioctl(IOSM|PAUSE); sys_status|=SS_PAUSEON; SAFEPRINTF(str,"%sanswer",cfg.text_dir); SAFEPRINTF(path,"%s.rip",str); if((autoterm&RIP) && fexistcase(path)) printfile(path,P_NOABORT); else { SAFEPRINTF(path,"%s.html",str); if((autoterm&HTML) && fexistcase(path)) printfile(path,P_NOABORT); else { SAFEPRINTF(path,"%s.ans",str); if((autoterm&ANSI) && fexistcase(path)) printfile(path,P_NOABORT); else { SAFEPRINTF(path,"%s.asc",str); if(fexistcase(path)) printfile(path, P_NOABORT); } } } sys_status&=~SS_PAUSEON; exec_bin(cfg.login_mod,&main_csi); } else /* auto logon here */ if(logon()==false) return(false); if(!useron.number) hangup(); /* Save the IP to the user's note */ if(cid[0]) { SAFECOPY(useron.note,cid); putuserrec(&cfg,useron.number,U_NOTE,LEN_NOTE,useron.note); } /* Save host name to the user's computer description */ if(client_name[0]) { SAFECOPY(useron.comp,client_name); putuserrec(&cfg,useron.number,U_COMP,LEN_COMP,useron.comp); } if(!online) return(false); if(!(sys_status&SS_USERON)) { errormsg(WHERE,ERR_CHK,"User not logged on",0); hangup(); return(false); } if(useron.pass[0]) loginSuccess(startup->login_attempt_list, &client_addr); return(true); }
bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks ,char fromhub, uint subnum ,uint touser, smbmsg_t* msg) { char* body; char* tail; char* qwkbuf; char str[256],col=0,lastch=0,*p; char from[128]; uint i,k; long bodylen,taillen; bool success=false; uint16_t net_type; ushort xlat=XLAT_NONE; int storage=SMB_SELFPACK; long dupechk_hashes=SMB_HASH_SOURCE_DUPE; str_list_t kludges; if(subnum!=INVALID_SUB && (hdrblk[0]=='*' || hdrblk[0]=='+' || cfg.sub[subnum]->misc&SUB_PONLY)) msg->hdr.attr|=MSG_PRIVATE; if(subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_AONLY) msg->hdr.attr|=MSG_ANONYMOUS; if(subnum==INVALID_SUB && cfg.sys_misc&SM_DELREADM) msg->hdr.attr|=MSG_KILLREAD; if((fromhub || useron.rest&FLAG('Q')) && (hdrblk[0]=='*' || hdrblk[0]=='-' || hdrblk[0]=='`')) msg->hdr.attr|=MSG_READ; if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->mod_ar[0] && chk_ar(cfg.sub[subnum]->mod_ar,&useron,&client)) msg->hdr.attr|=MSG_MODERATED; if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum)) msg->hdr.attr|=MSG_PERMANENT; if(!(useron.rest&FLAG('Q')) && !fromhub && msg->hdr.when_written.zone==0) msg->hdr.when_written.zone=sys_timezone(&cfg); msg->hdr.when_imported.time=time32(NULL); msg->hdr.when_imported.zone=sys_timezone(&cfg); hdrblk[116]=0; // don't include number of blocks in "re: msg number" if(!(useron.rest&FLAG('Q')) && !fromhub) msg->hdr.thread_back=atol((char *)hdrblk+108); if(subnum==INVALID_SUB) { /* E-mail */ 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); sprintf(str,"%u",touser); smb_hfield_str(msg,RECIPIENTEXT,str); } else { if(cfg.sub[subnum]->misc&SUB_HYPER) storage = SMB_HYPERALLOC; else if(cfg.sub[subnum]->misc&SUB_FAST) storage = SMB_FASTALLOC; if(cfg.sub[subnum]->misc&SUB_LZH) xlat=XLAT_LZH; } /********************************/ /* Convert the QWK message text */ /********************************/ if((qwkbuf=(char *)malloc((blocks-1)*QWK_BLOCK_LEN))==NULL) { errormsg(WHERE,ERR_ALLOC,"QWK msg buf",(blocks-1)*QWK_BLOCK_LEN); return(false); } if(fread(qwkbuf,QWK_BLOCK_LEN,blocks-1,qwk_fp) != blocks-1) { free(qwkbuf); errormsg(WHERE,ERR_READ,"QWK msg blocks",(blocks-1)*QWK_BLOCK_LEN); } bodylen=0; if((body=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) { free(qwkbuf); errormsg(WHERE,ERR_ALLOC,"QWK msg body",(blocks-1L)*QWK_BLOCK_LEN*2L); return(false); } taillen=0; if((tail=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) { free(qwkbuf); free(body); errormsg(WHERE,ERR_ALLOC,"QWK msg tail",(blocks-1L)*QWK_BLOCK_LEN*2L); return(false); } kludges=strListInit(); for(k=0;k<(blocks-1)*QWK_BLOCK_LEN;k++) { if(qwkbuf[k]==0) continue; if(bodylen==0 && (qwkbuf[k]=='@' || (((useron.qwk&QWK_EXT) || subnum==INVALID_SUB) && (strnicmp(qwkbuf+k,"To:",3)==0 || strnicmp(qwkbuf+k,"From:",5)==0 || strnicmp(qwkbuf+k,"Subject:",8)==0)))) { if((p=strchr(qwkbuf+k, QWK_NEWLINE))==NULL) { body[bodylen++]=qwkbuf[k]; continue; } *p=0; /* Converts QWK_NEWLINE to NUL */ strListPush(&kludges, qwkbuf+k); k+=strlen(qwkbuf+k); continue; } if(!taillen && qwkbuf[k]==' ' && col==3 && bodylen>=3 && body[bodylen-3]=='-' && body[bodylen-2]=='-' && body[bodylen-1]=='-') { bodylen-=3; strcpy(tail,"--- "); /* DO NOT USE SAFECOPY */ taillen=4; col++; continue; } if(qwkbuf[k]==QWK_NEWLINE) { /* expand QWK_NEWLINE to crlf */ if(!bodylen && !taillen) /* Ignore blank lines at top of message */ continue; if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-' && body[bodylen-2]=='-' && body[bodylen-1]=='-') { bodylen-=3; strcpy(tail,"---"); /* DO NOT USE SAFECOPY */ taillen=3; } col=0; if(taillen) { tail[taillen++]=CR; tail[taillen++]=LF; } else { body[bodylen++]=CR; body[bodylen++]=LF; } continue; } /* beep restrict */ if(!fromhub && qwkbuf[k]==BEL && useron.rest&FLAG('B')) continue; /* ANSI restriction */ if(!fromhub && (qwkbuf[k]==CTRL_A || qwkbuf[k]==ESC) && useron.rest&FLAG('A')) continue; if(qwkbuf[k]!=CTRL_A && lastch!=CTRL_A) col++; if(lastch==CTRL_A && !valid_ctrl_a_code(qwkbuf[k])) { if(taillen) taillen--; else bodylen--; lastch=0; continue; } lastch=qwkbuf[k]; if(taillen) tail[taillen++]=qwkbuf[k]; else body[bodylen++]=qwkbuf[k]; } free(qwkbuf); while(bodylen && body[bodylen-1]==' ') bodylen--; /* remove trailing spaces */ if(bodylen>=2 && body[bodylen-2]==CR && body[bodylen-1]==LF) bodylen-=2; while(taillen && tail[taillen-1]<=' ') taillen--; /* remove trailing garbage */ /* Parse QWK Kludges (QWKE standard and SyncQNET legacy) here: */ if(useron.rest&FLAG('Q') || fromhub) { /* QWK Net */ if((p=iniGetString(kludges,ROOT_SECTION,"@VIA",NULL,NULL)) != NULL) { if(!fromhub) set_qwk_flag(QWK_VIA); if(route_circ(p,cfg.sys_id)) { bprintf("\r\nCircular message path: %s\r\n",p); lprintf(LOG_ERR,"Circular message path: %s from %s" ,p,fromhub ? cfg.qhub[fromhub-1]->id:useron.alias); strListFree(&kludges); free(body); free(tail); return(false); } SAFEPRINTF2(str,"%s/%s" ,fromhub ? cfg.qhub[fromhub-1]->id : useron.alias,p); strupr(str); update_qwkroute(str); } else { if(fromhub) SAFECOPY(str,cfg.qhub[fromhub-1]->id); else SAFECOPY(str,useron.alias); } /* From network type & address: */ strupr(str); net_type=NET_QWK; smb_hfield_netaddr(msg, SENDERNETADDR, str, &net_type); smb_hfield_bin(msg,SENDERNETTYPE,net_type); } else { sprintf(str,"%u",useron.number); smb_hfield_str(msg,SENDEREXT,str); if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_NAME) SAFECOPY(from,useron.name); else SAFECOPY(from,useron.alias); smb_hfield_str(msg,SENDER,from); } if((p=iniGetString(kludges,ROOT_SECTION,"@MSGID",NULL,NULL)) != NULL) { if(!fromhub) set_qwk_flag(QWK_MSGID); truncstr(p," "); /* Truncate at first space char */ if(msg->id==NULL) smb_hfield_str(msg,RFC822MSGID,p); } if((p=iniGetString(kludges,ROOT_SECTION,"@REPLY",NULL,NULL)) != NULL) { if(!fromhub) set_qwk_flag(QWK_MSGID); truncstr(p," "); /* Truncate at first space char */ if(msg->reply_id==NULL) smb_hfield_str(msg,RFC822REPLYID,p); } if((p=iniGetString(kludges,ROOT_SECTION,"@TZ",NULL,NULL)) != NULL) { if(!fromhub) set_qwk_flag(QWK_TZ); msg->hdr.when_written.zone=(short)ahtoul(p); } if((p=iniGetString(kludges,ROOT_SECTION,"@REPLYTO",NULL,NULL)) != NULL) { if(msg->replyto==NULL) smb_hfield_str(msg,REPLYTO,p); } /* QWKE standard: */ if((p=iniGetString(kludges,ROOT_SECTION,"Subject",NULL,NULL)) != NULL) smb_hfield_replace_str(msg,SUBJECT,p); if((p=iniGetString(kludges,ROOT_SECTION,"To",NULL,NULL)) != NULL) smb_hfield_replace_str(msg,RECIPIENT,p); if((useron.rest&FLAG('Q')) && (p=iniGetString(kludges,ROOT_SECTION,"From",NULL,NULL)) != NULL) smb_hfield_replace_str(msg,SENDER,p); strListFree(&kludges); /* smb_addmsg requires ASCIIZ strings */ body[bodylen]=0; tail[taillen]=0; if(online==ON_REMOTE) bputs(text[WritingIndx]); if(smb.status.max_crcs==0) /* no CRC checking means no body text dupe checking */ dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY); if((i=smb_addmsg(&smb,msg,storage,dupechk_hashes,xlat,(uchar*)body,(uchar*)tail))==SMB_SUCCESS) success=true; else if(i==SMB_DUPE_MSG) { bprintf("\r\n!%s\r\n",smb.last_error); if(!fromhub) { if(subnum==INVALID_SUB) { SAFEPRINTF2(str,"%s duplicate e-mail attempt (%s)",useron.alias,smb.last_error); logline(LOG_NOTICE,"E!",str); } else { SAFEPRINTF4(str,"%s duplicate message attempt in %s %s (%s)" ,useron.alias ,cfg.grp[cfg.sub[subnum]->grp]->sname ,cfg.sub[subnum]->lname ,smb.last_error); logline(LOG_NOTICE,"P!",str); } } } else errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); free(body); free(tail); return(success); }
void msgs_cfg() { static int dflt,msgs_dflt,bar; char str[256],str2[256],done=0; char* p; char* tp; char tmp[128]; char tmp_code[32]; int j,k,q,s; int i,file,ptridx,n; unsigned total_subs; long ported; sub_t tmpsub; static grp_t savgrp; FILE* stream; while(1) { for(i=0;i<cfg.total_grps && i<MAX_OPTS;i++) sprintf(opt[i],"%-25s",cfg.grp[i]->lname); opt[i][0]=0; j=WIN_ORG|WIN_ACT|WIN_CHE; if(cfg.total_grps) j|=WIN_DEL|WIN_DELACT|WIN_GET; if(cfg.total_grps<MAX_OPTS) j|=WIN_INS|WIN_INSACT|WIN_XTR; if(savgrp.sname[0]) j|=WIN_PUT; uifc.helpbuf= "`Message Groups:`\n" "\n" "This is a listing of message groups for your BBS. Message groups are\n" "used to logically separate your message `sub-boards` into groups. Every\n" "sub-board belongs to a message group. You must have at least one message\n" "group and one sub-board configured.\n" "\n" "One popular use for message groups is to separate local sub-boards and\n" "networked sub-boards. One might have a `Local` message group that contains\n" "non-networked sub-boards of various topics and also have a `FidoNet`\n" "message group that contains sub-boards that are echoed across FidoNet.\n" "Some sysops separate sub-boards into more specific areas such as `Main`,\n" "`Technical`, or `Adult`. If you have many sub-boards that have a common\n" "subject denominator, you may want to have a separate message group for\n" "those sub-boards for a more organized message structure.\n" ; i=uifc.list(j,0,0,45,&msgs_dflt,&bar,"Message Groups",opt); if(i==-1) { j=save_changes(WIN_MID); if(j==-1) continue; if(!j) { write_msgs_cfg(&cfg,backup_level); refresh_cfg(&cfg); } return; } if((i&MSK_ON)==MSK_INS) { i&=MSK_OFF; uifc.helpbuf= "`Group Long Name:`\n" "\n" "This is a description of the message group which is displayed when a\n" "user of the system uses the `/*` command from the main menu.\n" ; strcpy(str,"Main"); if(uifc.input(WIN_MID|WIN_SAV,0,0,"Group Long Name",str,LEN_GLNAME ,K_EDIT)<1) continue; uifc.helpbuf= "`Group Short Name:`\n" "\n" "This is a short description of the message group which is used for the\n" "main menu and reading message prompts.\n" ; sprintf(str2,"%.*s",LEN_GSNAME,str); if(uifc.input(WIN_MID,0,0,"Group Short Name",str2,LEN_GSNAME,K_EDIT)<1) continue; if((cfg.grp=(grp_t **)realloc(cfg.grp,sizeof(grp_t *)*(cfg.total_grps+1)))==NULL) { errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_grps+1); cfg.total_grps=0; bail(1); continue; } if(cfg.total_grps) { /* was cfg.total_subs (?) */ for(j=cfg.total_grps;j>i;j--) /* insert above */ cfg.grp[j]=cfg.grp[j-1]; for(j=0;j<cfg.total_subs;j++) /* move sub group numbers */ if(cfg.sub[j]->grp>=i) cfg.sub[j]->grp++; } if((cfg.grp[i]=(grp_t *)malloc(sizeof(grp_t)))==NULL) { errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(grp_t)); continue; } memset((grp_t *)cfg.grp[i],0,sizeof(grp_t)); strcpy(cfg.grp[i]->lname,str); strcpy(cfg.grp[i]->sname,str2); cfg.total_grps++; uifc.changes=1; continue; } if((i&MSK_ON)==MSK_DEL) { i&=MSK_OFF; uifc.helpbuf= "`Delete All Data in Group:`\n" "\n" "If you wish to delete the messages in all the sub-boards in this group,\n" "select `Yes`.\n" ; j=1; strcpy(opt[0],"Yes"); strcpy(opt[1],"No"); opt[2][0]=0; j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Delete All Data in Group",opt); if(j==-1) continue; if(j==0) for(j=0;j<cfg.total_subs;j++) if(cfg.sub[j]->grp==i) { sprintf(str,"%s%s.s*" ,cfg.grp[cfg.sub[j]->grp]->code_prefix ,cfg.sub[j]->code_suffix); strlwr(str); if(!cfg.sub[j]->data_dir[0]) sprintf(tmp,"%ssubs/",cfg.data_dir); else strcpy(tmp,cfg.sub[j]->data_dir); delfiles(tmp,str); clearptrs(j); } free(cfg.grp[i]); for(j=0;j<cfg.total_subs;) { if(cfg.sub[j]->grp==i) { /* delete subs of this group */ free(cfg.sub[j]); cfg.total_subs--; k=j; while(k<cfg.total_subs) { /* move all subs down */ cfg.sub[k]=cfg.sub[k+1]; for(q=0;q<cfg.total_qhubs;q++) for(s=0;s<cfg.qhub[q]->subs;s++) if(cfg.qhub[q]->sub[s]==k) cfg.qhub[q]->sub[s]--; k++; } } else j++; } for(j=0;j<cfg.total_subs;j++) /* move sub group numbers down */ if(cfg.sub[j]->grp>i) cfg.sub[j]->grp--; cfg.total_grps--; while(i<cfg.total_grps) { cfg.grp[i]=cfg.grp[i+1]; i++; } uifc.changes=1; continue; } if((i&MSK_ON)==MSK_GET) { i&=MSK_OFF; savgrp=*cfg.grp[i]; continue; } if((i&MSK_ON)==MSK_PUT) { i&=MSK_OFF; *cfg.grp[i]=savgrp; uifc.changes=1; continue; } done=0; while(!done) { j=0; sprintf(opt[j++],"%-27.27s%s","Long Name",cfg.grp[i]->lname); sprintf(opt[j++],"%-27.27s%s","Short Name",cfg.grp[i]->sname); sprintf(opt[j++],"%-27.27s%s","Internal Code Prefix",cfg.grp[i]->code_prefix); sprintf(opt[j++],"%-27.27s%.40s","Access Requirements" ,cfg.grp[i]->arstr); strcpy(opt[j++],"Clone Options"); strcpy(opt[j++],"Export Areas..."); strcpy(opt[j++],"Import Areas..."); strcpy(opt[j++],"Message Sub-boards..."); opt[j][0]=0; sprintf(str,"%s Group",cfg.grp[i]->sname); uifc.helpbuf= "`Message Group Configuration:`\n" "\n" "This menu allows you to configure the security requirements for access\n" "to this message group. You can also add, delete, and configure the\n" "sub-boards of this group by selecting the `Messages Sub-boards...` option.\n" ; switch(uifc.list(WIN_ACT,6,4,60,&dflt,0,str,opt)) { case -1: done=1; break; case 0: uifc.helpbuf= "`Group Long Name:`\n" "\n" "This is a description of the message group which is displayed when a\n" "user of the system uses the `/*` command from the main menu.\n" ; strcpy(str,cfg.grp[i]->lname); /* save incase setting to null */ if(!uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Listings" ,cfg.grp[i]->lname,LEN_GLNAME,K_EDIT)) strcpy(cfg.grp[i]->lname,str); break; case 1: uifc.helpbuf= "`Group Short Name:`\n" "\n" "This is a short description of the message group which is used for\n" "main menu and reading messages prompts.\n" ; uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Prompts" ,cfg.grp[i]->sname,LEN_GSNAME,K_EDIT); break; case 2: uifc.helpbuf= "`Internal Code Prefix:`\n" "\n" "This is an `optional` code prefix used to help generate unique internal\n" "codes for the sub-boards in this message group. If this option\n" "is used, sub-board internal codes will be constructed from this prefix\n" "and the specified code suffix for each sub-board.\n" ; uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code Prefix" ,cfg.grp[i]->code_prefix,LEN_CODE,K_EDIT|K_UPPER); break; case 3: sprintf(str,"%s Group",cfg.grp[i]->sname); getar(str,cfg.grp[i]->arstr); break; case 4: /* Clone Options */ j=0; strcpy(opt[0],"Yes"); strcpy(opt[1],"No"); opt[2][0]=0; uifc.helpbuf= "`Clone Sub-board Options:`\n" "\n" "If you want to clone the options of the first sub-board of this group\n" "into all sub-boards of this group, select `Yes`.\n" "\n" "The options cloned are posting requirements, reading requirements,\n" "operator requirments, moderated user requirments, toggle options,\n" "network options (including EchoMail origin line, EchoMail address,\n" "and QWK Network tagline), maximum number of messages, maximum number\n" "of CRCs, maximum age of messages, storage method, and data directory.\n" ; j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0 ,"Clone Options of First Sub-board into All of Group",opt); if(j==0) { k=-1; for(j=0;j<cfg.total_subs;j++) if(cfg.sub[j]->grp==i) { if(k==-1) k=j; else { uifc.changes=1; cfg.sub[j]->misc=(cfg.sub[k]->misc|SUB_HDRMOD); strcpy(cfg.sub[j]->post_arstr,cfg.sub[k]->post_arstr); strcpy(cfg.sub[j]->read_arstr,cfg.sub[k]->read_arstr); strcpy(cfg.sub[j]->op_arstr,cfg.sub[k]->op_arstr); strcpy(cfg.sub[j]->mod_arstr,cfg.sub[k]->mod_arstr); strcpy(cfg.sub[j]->origline,cfg.sub[k]->origline); strcpy(cfg.sub[j]->tagline,cfg.sub[k]->tagline); strcpy(cfg.sub[j]->data_dir,cfg.sub[k]->data_dir); strcpy(cfg.sub[j]->post_sem,cfg.sub[k]->post_sem); cfg.sub[j]->maxmsgs=cfg.sub[k]->maxmsgs; cfg.sub[j]->maxcrcs=cfg.sub[k]->maxcrcs; cfg.sub[j]->maxage=cfg.sub[k]->maxage; cfg.sub[j]->faddr=cfg.sub[k]->faddr; } } } break; case 5: k=0; ported=0; q=uifc.changes; strcpy(opt[k++],"SUBS.TXT (Synchronet)"); strcpy(opt[k++],"AREAS.BBS (MSG)"); strcpy(opt[k++],"AREAS.BBS (SBBSecho)"); strcpy(opt[k++],"FIDONET.NA (Fido)"); opt[k][0]=0; uifc.helpbuf= "`Export Area File Format:`\n" "\n" "This menu allows you to choose the format of the area file you wish to\n" "export the current message group into.\n" ; k=0; k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0 ,"Export Area File Format",opt); if(k==-1) break; if(k==0) sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir); else if(k==1) sprintf(str,"AREAS.BBS"); else if(k==2) sprintf(str,"%sAREAS.BBS",cfg.data_dir); else if(k==3) sprintf(str,"FIDONET.NA"); if(k && k<3) if(uifc.input(WIN_MID|WIN_SAV,0,0,"Uplinks" ,str2,sizeof(str2)-1,0)<=0) { uifc.changes=q; break; } if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename" ,str,sizeof(str)-1,K_EDIT)<=0) { uifc.changes=q; break; } if(fexist(str)) { strcpy(opt[0],"Overwrite"); strcpy(opt[1],"Append"); opt[2][0]=0; j=0; j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0 ,"File Exists",opt); if(j==-1) break; if(j==0) j=O_WRONLY|O_TRUNC; else j=O_WRONLY|O_APPEND; } else j=O_WRONLY|O_CREAT; if((stream=fnopen(&file,str,j))==NULL) { sprintf(str,"Open Failure: %d (%s)" ,errno,strerror(errno)); uifc.msg(str); uifc.changes=q; break; } uifc.pop("Exporting Areas..."); for(j=0;j<cfg.total_subs;j++) { if(cfg.sub[j]->grp!=i) continue; ported++; if(k==1) { /* AREAS.BBS *.MSG */ sprintf(str,"%s%s%s/" ,cfg.echomail_dir ,cfg.grp[cfg.sub[j]->grp]->code_prefix ,cfg.sub[j]->code_suffix); fprintf(stream,"%-30s %-20s %s\r\n" ,str,stou(cfg.sub[j]->sname),str2); continue; } if(k==2) { /* AREAS.BBS SBBSecho */ fprintf(stream,"%s%-30s %-20s %s\r\n" ,cfg.grp[cfg.sub[j]->grp]->code_prefix ,cfg.sub[j]->code_suffix ,stou(cfg.sub[j]->sname) ,str2); continue; } if(k==3) { /* FIDONET.NA */ fprintf(stream,"%-20s %s\r\n" ,stou(cfg.sub[j]->sname),cfg.sub[j]->lname); continue; } fprintf(stream,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n" "%s\r\n%s\r\n%s\r\n" ,cfg.sub[j]->lname ,cfg.sub[j]->sname ,cfg.sub[j]->qwkname ,cfg.sub[j]->code_suffix ,cfg.sub[j]->data_dir ,cfg.sub[j]->arstr ,cfg.sub[j]->read_arstr ,cfg.sub[j]->post_arstr ,cfg.sub[j]->op_arstr ); fprintf(stream,"%"PRIX32"\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n" ,cfg.sub[j]->misc ,cfg.sub[j]->tagline ,cfg.sub[j]->origline ,cfg.sub[j]->post_sem ,cfg.sub[j]->newsgroup ,smb_faddrtoa(&cfg.sub[j]->faddr,tmp) ); fprintf(stream,"%"PRIu32"\r\n%"PRIu32"\r\n%u\r\n%u\r\n%s\r\n" ,cfg.sub[j]->maxmsgs ,cfg.sub[j]->maxcrcs ,cfg.sub[j]->maxage ,cfg.sub[j]->ptridx ,cfg.sub[j]->mod_arstr ); fprintf(stream,"***END-OF-SUB***\r\n\r\n"); } fclose(stream); uifc.pop(0); sprintf(str,"%lu Message Areas Exported Successfully",ported); uifc.msg(str); uifc.changes=q; break; case 6: ported=0; k=0; strcpy(opt[k++],"SUBS.TXT (Synchronet)"); strcpy(opt[k++],"AREAS.BBS (Generic)"); strcpy(opt[k++],"AREAS.BBS (SBBSecho)"); strcpy(opt[k++],"FIDONET.NA (Fido)"); opt[k][0]=0; uifc.helpbuf= "`Import Area File Format:`\n" "\n" "This menu allows you to choose the format of the area file you wish to\n" "import into the current message group.\n" ; k=0; k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0 ,"Import Area File Format",opt); if(k==-1) break; if(k==0) sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir); else if(k==1) sprintf(str,"AREAS.BBS"); else if(k==2) sprintf(str,"%sAREAS.BBS",cfg.data_dir); else if(k==3) sprintf(str,"FIDONET.NA"); if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename" ,str,sizeof(str)-1,K_EDIT)<=0) break; if((stream=fnopen(&file,str,O_RDONLY))==NULL) { uifc.msg("Open Failure"); break; } uifc.pop("Importing Areas..."); total_subs = cfg.total_subs; /* Save original number of subs */ ptridx = 0; while(!feof(stream)) { if(!fgets(str,sizeof(str),stream)) break; truncsp(str); if(!str[0]) continue; if(k) { p=str; while(*p && *p<=' ') p++; if(!*p || *p==';') continue; memset(&tmpsub,0,sizeof(sub_t)); tmpsub.misc|= (SUB_FIDO|SUB_NAME|SUB_TOUSER|SUB_QUOTE|SUB_HYPER); if(k==1) { /* AREAS.BBS Generic/*.MSG */ p=str; SKIP_WHITESPACE(p); /* Find path */ FIND_WHITESPACE(p); /* Skip path */ SKIP_WHITESPACE(p); /* Find tag */ truncstr(p," \t"); /* Truncate tag */ SAFECOPY(tmp_code,p); /* Copy tag to internal code */ SAFECOPY(tmpsub.lname,utos(p)); SAFECOPY(tmpsub.sname,tmpsub.lname); SAFECOPY(tmpsub.qwkname,tmpsub.qwkname); } else if(k==2) { /* AREAS.BBS SBBSecho */ p=str; SKIP_WHITESPACE(p); /* Find internal code */ tp=p; FIND_WHITESPACE(tp); *tp=0; /* Truncate internal code */ SAFECOPY(tmp_code,p); /* Copy internal code suffix */ p=tp+1; SKIP_WHITESPACE(p); /* Find echo tag */ truncstr(p," \t"); /* Truncate tag */ SAFECOPY(tmpsub.lname,utos(p)); SAFECOPY(tmpsub.sname,tmpsub.lname); SAFECOPY(tmpsub.qwkname,tmpsub.sname); } else if(k==3) { /* FIDONET.NA */ p=str; SKIP_WHITESPACE(p); /* Find echo tag */ tp=p; FIND_WHITESPACE(tp); /* Find end of tag */ *tp=0; /* Truncate echo tag */ SAFECOPY(tmp_code,p); /* Copy tag to internal code suffix */ SAFECOPY(tmpsub.sname,utos(p)); /* ... to short name, converting underscores to spaces */ SAFECOPY(tmpsub.qwkname,tmpsub.sname); /* ... to QWK name .... */ p=tp+1; SKIP_WHITESPACE(p); /* Find description */ SAFECOPY(tmpsub.lname,p); /* Copy description to long name */ } } else { memset(&tmpsub,0,sizeof(sub_t)); tmpsub.grp=i; sprintf(tmpsub.lname,"%.*s",LEN_SLNAME,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.qwkname,"%.*s",10,str); if(!fgets(str,128,stream)) break; truncsp(str); SAFECOPY(tmp_code,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.data_dir,"%.*s",LEN_DIR,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.arstr,"%.*s",LEN_ARSTR,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.read_arstr,"%.*s",LEN_ARSTR,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.post_arstr,"%.*s",LEN_ARSTR,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.op_arstr,"%.*s",LEN_ARSTR,str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.misc=ahtoul(str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.tagline,"%.*s",80,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.origline,"%.*s",50,str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.post_sem,"%.*s",LEN_DIR,str); if(!fgets(str,128,stream)) break; truncsp(str); SAFECOPY(tmpsub.newsgroup,str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.faddr=atofaddr(str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.maxmsgs=atol(str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.maxcrcs=atol(str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.maxage=atoi(str); if(!fgets(str,128,stream)) break; truncsp(str); tmpsub.ptridx=atoi(str); if(!fgets(str,128,stream)) break; truncsp(str); sprintf(tmpsub.mod_arstr,"%.*s",LEN_ARSTR,str); while(!feof(stream) && strcmp(str,"***END-OF-SUB***")) { if(!fgets(str,128,stream)) break; truncsp(str); } } SAFECOPY(tmpsub.code_suffix, prep_code(tmp_code,cfg.grp[i]->code_prefix)); truncsp(tmpsub.sname); truncsp(tmpsub.lname); truncsp(tmpsub.qwkname); if(tmpsub.code_suffix[0]==0 || tmpsub.sname[0]==0 || tmpsub.lname[0]==0 || tmpsub.qwkname[0]==0) continue; for(j=0;j<total_subs;j++) { if(cfg.sub[j]->grp!=i) continue; if(!stricmp(cfg.sub[j]->code_suffix,tmpsub.code_suffix)) break; } if(j==total_subs) { j=cfg.total_subs; if((cfg.sub=(sub_t **)realloc(cfg.sub ,sizeof(sub_t *)*(cfg.total_subs+1)))==NULL) { errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_subs+1); cfg.total_subs=0; bail(1); break; } if((cfg.sub[j]=(sub_t *)malloc(sizeof(sub_t))) ==NULL) { errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(sub_t)); break; } memset(cfg.sub[j],0,sizeof(sub_t)); } if(!k) { n=cfg.sub[j]->ptridx; /* save original ptridx */ memcpy(cfg.sub[j],&tmpsub,sizeof(sub_t)); cfg.sub[j]->ptridx=n; /* restore original ptridx */ } else { cfg.sub[j]->grp=i; if(cfg.total_faddrs) cfg.sub[j]->faddr=cfg.faddr[0]; strcpy(cfg.sub[j]->code_suffix,tmpsub.code_suffix); strcpy(cfg.sub[j]->sname,tmpsub.sname); strcpy(cfg.sub[j]->lname,tmpsub.lname); strcpy(cfg.sub[j]->qwkname,tmpsub.qwkname); strcpy(cfg.sub[j]->data_dir,tmpsub.data_dir); if(j==cfg.total_subs) cfg.sub[j]->maxmsgs=1000; } if(j==cfg.total_subs) { /* adding new sub-board */ for(;ptridx<USHRT_MAX;ptridx++) { for(n=0;n<total_subs;n++) if(cfg.sub[n]->ptridx==ptridx) break; if(n==total_subs) break; } cfg.sub[j]->ptridx=ptridx; /* use new ptridx */ cfg.sub[j]->misc=tmpsub.misc; cfg.total_subs++; ptridx++; /* don't use the same ptridx for next sub */ } uifc.changes=1; ported++; } fclose(stream); uifc.pop(0); sprintf(str,"%lu Message Areas Imported Successfully",ported); uifc.msg(str); break; case 7: sub_cfg(i); break; } } } }
ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, uint subnum , int conf, FILE* hdrs) { char str[512],from[512],to[512],ch=0,tear=0,tearwatch=0,*buf,*p; char asc; char msgid[256]; char tmp[512]; long l,size=0,offset; int i; ushort hfield_type; struct tm tm; smbmsg_t remsg; time_t tt; offset=(long)ftell(qwk_fp); if(hdrs!=NULL) { fprintf(hdrs,"[%lx]\n",offset); /* Message-IDs */ fprintf(hdrs,"Message-ID: %s\n",get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid))); if(msg->reply_id!=NULL) fprintf(hdrs,"In-Reply-To: %s\n",msg->reply_id); /* Time/Date/Zone info */ fprintf(hdrs,"WhenWritten: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( time_to_xpDateTime(msg->hdr.when_written.time,smb_tzutc(msg->hdr.when_written.zone)) ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,msg->hdr.when_written.zone ); fprintf(hdrs,"WhenImported: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( time_to_xpDateTime(msg->hdr.when_imported.time,smb_tzutc(msg->hdr.when_imported.zone)) ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,msg->hdr.when_imported.zone ); fprintf(hdrs,"WhenExported: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( xpDateTime_now() ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,sys_timezone(&cfg) ); fprintf(hdrs,"ExportedFrom: %s %s %"PRIu32"\n" ,cfg.sys_id ,subnum==INVALID_SUB ? "mail":cfg.sub[subnum]->code ,msg->hdr.number ); /* SENDER */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDER),msg->from); if(msg->from_net.type) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDERNETADDR),smb_netaddrstr(&msg->from_net,tmp)); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERIPADDR,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERHOSTNAME,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERPROTOCOL,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if(msg->from_org!=NULL) fprintf(hdrs,"Organization: %s\n",msg->from_org); else if(msg->from_net.type==NET_NONE) fprintf(hdrs,"Organization: %s\n",cfg.sys_name); /* Reply-To */ if((p=(char*)smb_get_hfield(msg,RFC822REPLYTO,NULL))==NULL) { if(msg->replyto_net.type==NET_INTERNET) p=(char*)msg->replyto_net.addr; else if(msg->replyto!=NULL) p=msg->replyto; } if(p!=NULL) fprintf(hdrs,"Reply-To: %s\n",p); /* use original RFC822 header field */ /* SUBJECT */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SUBJECT),msg->subj); /* RECIPIENT */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENT),msg->to); if(msg->to_net.type) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENTNETADDR),smb_netaddrstr(&msg->to_net,tmp)); /* FidoNet */ if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOAREA,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOSEENBY,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPATH,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOMSGID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOREPLYID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOFLAGS,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOTID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* Synchronet */ if((p=(char*)smb_get_hfield(msg,hfield_type=SMB_EDITOR,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* USENET */ if((p=(char*)smb_get_hfield(msg,hfield_type=USENETPATH,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=USENETNEWSGROUPS,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* RFC822 header fields: */ for(i=0;i<msg->total_hfields;i++) if(msg->hfield[i].type==RFC822HEADER) fprintf(hdrs,"%s\n",truncsp_lines((char*)msg->hfield_dat[i])); /* Blank line: */ fprintf(hdrs,"\n"); } fprintf(qwk_fp,"%*s",QWK_BLOCK_LEN,""); /* Init header to space */ /* QWKE compatible kludges */ SAFECOPY(from,msg->from); if(msg->from_net.addr && (uint)subnum==INVALID_SUB && !(mode&QM_TO_QNET)) { if(msg->from_net.type==NET_FIDO) sprintf(from,"%.128s@%.128s" ,msg->from,smb_faddrtoa((faddr_t *)msg->from_net.addr,tmp)); else if(msg->from_net.type==NET_INTERNET || strchr((char*)msg->from_net.addr,'@')!=NULL) sprintf(from,"%.128s",(char*)msg->from_net.addr); else sprintf(from,"%.128s@%.128s",msg->from,(char*)msg->from_net.addr); } if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) SAFECOPY(from,text[Anonymous]); else if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(from) > QWK_HFIELD_LEN) { size+=fprintf(qwk_fp,"From: %.128s%c", from, QWK_NEWLINE); SAFECOPY(from,msg->from); } SAFECOPY(to,msg->to); if(msg->to_net.addr && (uint)subnum==INVALID_SUB) { if(msg->to_net.type==NET_FIDO) sprintf(to,"%.128s@%s",msg->to,smb_faddrtoa((faddr_t *)msg->to_net.addr,tmp)); else if(msg->to_net.type==NET_INTERNET) sprintf(to,"%.128s",(char*)msg->to_net.addr); else if(msg->to_net.type==NET_QWK) { if(mode&QM_TO_QNET) { p=strchr((char *)msg->to_net.addr,'/'); if(p) { /* Another hop */ p++; SAFECOPY(to,"NETMAIL"); size+=fprintf(qwk_fp,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE); } else sprintf(to,"%.128s",msg->to); } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); } if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(to) > QWK_HFIELD_LEN) { size+=fprintf(qwk_fp,"To: %.128s%c", to, QWK_NEWLINE); if(msg->to_net.type==NET_QWK) SAFECOPY(to,"NETMAIL"); else SAFECOPY(to,msg->to); } if((useron.qwk&QWK_EXT) && strlen(msg->subj) > QWK_HFIELD_LEN) size+=fprintf(qwk_fp,"Subject: %.128s%c", msg->subj, QWK_NEWLINE); if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded) size+=fprintf(qwk_fp,"@VIA: %s%c" ,(char*)msg->from_net.addr,QWK_NEWLINE); if(mode&QM_MSGID && (uint)subnum!=INVALID_SUB) { size+=fprintf(qwk_fp,"@MSGID: %s%c" ,get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid)),QWK_NEWLINE); if(msg->reply_id) { SAFECOPY(tmp,msg->reply_id); truncstr(tmp," "); size+=fprintf(qwk_fp,"@REPLY: %s%c" ,tmp,QWK_NEWLINE); } else if(msg->hdr.thread_back) { memset(&remsg,0,sizeof(remsg)); remsg.hdr.number=msg->hdr.thread_back; if(smb_getmsgidx(&smb, &remsg)) size+=fprintf(qwk_fp,"@REPLY: <%s>%c",smb.last_error,QWK_NEWLINE); else size+=fprintf(qwk_fp,"@REPLY: %s%c" ,get_msgid(&cfg,subnum,&remsg,msgid,sizeof(msgid)) ,QWK_NEWLINE); } } if(msg->hdr.when_written.zone && mode&QM_TZ) size+=fprintf(qwk_fp,"@TZ: %04hx%c",msg->hdr.when_written.zone,QWK_NEWLINE); if(msg->replyto!=NULL && mode&QM_REPLYTO) size+=fprintf(qwk_fp,"@REPLYTO: %s%c" ,msg->replyto,QWK_NEWLINE); p=0; for(i=0;i<msg->total_hfields;i++) { if(msg->hfield[i].type==SENDER) p=(char *)msg->hfield_dat[i]; if(msg->hfield[i].type==FORWARDED && p) { size+=fprintf(qwk_fp,"Forwarded from %s on %s%c",p ,timestr(*(time32_t *)msg->hfield_dat[i]) ,QWK_NEWLINE); } } buf=smb_getmsgtxt(&smb,msg,GETMSGTXT_ALL); if(!buf) return(0); for(l=0;buf[l];l++) { ch=buf[l]; if(ch=='\n') { if(tear) tear++; /* Count LFs after tearline */ if(tear>3) /* more than two LFs after the tear */ tear=0; if(tearwatch==4) { /* watch for LF---LF */ tear=1; tearwatch=0; } else if(!tearwatch) tearwatch=1; else tearwatch=0; if(l && buf[l-1]=='\r') /* Replace CRLF with funky char */ ch=QWK_NEWLINE; /* but leave sole LF (soft-NL) alone */ fputc(ch,qwk_fp); size++; continue; } if(ch=='\r') { /* Ignore CRs */ if(tearwatch<4) /* LF---CRLF is okay */ tearwatch=0; /* LF-CR- is not okay */ continue; } if(ch==' ' && tearwatch==4) { /* watch for "LF--- " */ tear=1; tearwatch=0; } if(ch=='-') { /* watch for "LF---" */ if(l==0 || (tearwatch && tearwatch<4)) tearwatch++; else tearwatch=0; } else tearwatch=0; if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_ASCII) { if(ch<' ' && ch!=1) ch='.'; else if((uchar)ch>0x7f) ch=exascii_to_ascii_char(ch); } if(ch==QWK_NEWLINE) /* funky char */ ch='*'; if(ch==CTRL_A) { ch=buf[++l]; if(ch==0 || toupper(ch)=='Z') /* EOF */ break; if((asc=ctrl_a_to_ascii_char(ch)) != 0) { fputc(asc,qwk_fp); size++; continue; } if(mode&A_EXPAND) { str[0]=0; switch(toupper(ch)) { case 'W': SAFECOPY(str,ansi(LIGHTGRAY)); break; case 'K': SAFECOPY(str,ansi(BLACK)); break; case 'H': SAFECOPY(str,ansi(HIGH)); break; case 'I': SAFECOPY(str,ansi(BLINK)); break; case '-': case '_': case 'N': /* Normal */ SAFECOPY(str,ansi(ANSI_NORMAL)); break; case 'R': SAFECOPY(str,ansi(RED)); break; case 'G': SAFECOPY(str,ansi(GREEN)); break; case 'B': SAFECOPY(str,ansi(BLUE)); break; case 'C': SAFECOPY(str,ansi(CYAN)); break; case 'M': SAFECOPY(str,ansi(MAGENTA)); break; case 'Y': /* Yellow */ SAFECOPY(str,ansi(BROWN)); break; case '0': SAFECOPY(str,ansi(BG_BLACK)); break; case '1': SAFECOPY(str,ansi(BG_RED)); break; case '2': SAFECOPY(str,ansi(BG_GREEN)); break; case '3': SAFECOPY(str,ansi(BG_BROWN)); break; case '4': SAFECOPY(str,ansi(BG_BLUE)); break; case '5': SAFECOPY(str,ansi(BG_MAGENTA)); break; case '6': SAFECOPY(str,ansi(BG_CYAN)); break; case '7': SAFECOPY(str,ansi(BG_LIGHTGRAY)); break; } if(str[0]) size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); continue; } /* End Expand */ if(mode&A_LEAVE && valid_ctrl_a_code(ch)) { fputc(CTRL_A,qwk_fp); fputc(ch,qwk_fp); size+=2L; } continue; } /* End of Ctrl-A shit */ fputc(ch,qwk_fp); size++; } free(buf); if(ch!=QWK_NEWLINE) { fputc(QWK_NEWLINE,qwk_fp); /* make sure it ends in CRLF */ size++; } if(mode&QM_TAGLINE && !(cfg.sub[subnum]->misc&SUB_NOTAG)) { if(!tear) /* no tear line */ SAFEPRINTF(str,"\1n---%c",QWK_NEWLINE); /* so add one */ else SAFECOPY(str,"\1n"); if(cfg.sub[subnum]->misc&SUB_ASCII) ch='*'; else ch='þ'; safe_snprintf(tmp,sizeof(tmp)," %c \1g%.10s\1n %c %.127s%c" ,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,QWK_NEWLINE); strcat(str,tmp); if(!(mode&A_LEAVE)) remove_ctrl_a(str,str); size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); } while(size%QWK_BLOCK_LEN) { /* Pad with spaces */ size++; fputc(' ',qwk_fp); } tt=msg->hdr.when_written.time; if(localtime_r(&tt,&tm)==NULL) memset(&tm,0,sizeof(tm)); safe_snprintf(tmp,sizeof(tmp),"%02u-%02u-%02u%02u:%02u" ,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year) ,tm.tm_hour,tm.tm_min); if(msg->hdr.attr&MSG_PRIVATE) { if(msg->hdr.attr&MSG_READ) ch='*'; /* private, read */ else ch='+'; /* private, unread */ } else { if(msg->hdr.attr&MSG_READ) ch='-'; /* public, read */ else ch=' '; /* public, unread */ } safe_snprintf(str,sizeof(str),"%c%-7lu%-13.13s%-25.25s" "%-25.25s%-25.25s%12s%-8lu%-6lu\xe1%c%c%c%c%c" ,ch /* message status flag */ ,mode&QM_REP ? (ulong)conf /* conference or */ : msg->hdr.number&MAX_MSGNUM /* message number */ ,tmp /* date and time */ ,to /* To: */ ,from /* From: */ ,msg->subj /* Subject */ ,nulstr /* Password */ ,msg->hdr.thread_back&MAX_MSGNUM /* Message Re: Number */ ,(size/QWK_BLOCK_LEN)+1 /* Number of blocks */ ,(char)conf&0xff /* Conference number lo byte */ ,(ushort)conf>>8 /* hi byte */ ,' ' /* not used */ ,' ' /* not used */ ,useron.rest&FLAG('Q') ? '*' : ' ' /* Net tag line */ ); fseek(qwk_fp,offset,SEEK_SET); fwrite(str,QWK_BLOCK_LEN,1,qwk_fp); fseek(qwk_fp,size,SEEK_CUR); return(size); }
bool sbbs_t::qwktomsg(FILE *qwk_fp, char *hdrblk, char fromhub, uint subnum , uint touser) { char* body; char* tail; char* header; char str[256],col=0,lastch=0,*p,qwkbuf[QWK_BLOCK_LEN+1]; uint i,j,k,lzh=0,skip=0; long bodylen,taillen; bool header_cont=false; bool success=false; ulong block,blocks; smbmsg_t msg; struct tm tm; ushort xlat=XLAT_NONE; int storage=SMB_SELFPACK; long dupechk_hashes=SMB_HASH_SOURCE_ALL; memset(&msg,0,sizeof(smbmsg_t)); /* Initialize message header */ msg.hdr.version=smb_ver(); blocks=atol(hdrblk+116); if(blocks<2) { errormsg(WHERE,ERR_CHK,"QWK packet header blocks",blocks); return(false); } if(subnum!=INVALID_SUB && (hdrblk[0]=='*' || hdrblk[0]=='+' || cfg.sub[subnum]->misc&SUB_PONLY)) msg.hdr.attr|=MSG_PRIVATE; if(subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_AONLY) msg.hdr.attr|=MSG_ANONYMOUS; if(subnum==INVALID_SUB && cfg.sys_misc&SM_DELREADM) msg.hdr.attr|=MSG_KILLREAD; if((fromhub || useron.rest&FLAG('Q')) && (hdrblk[0]=='*' || hdrblk[0]=='-' || hdrblk[0]=='`')) msg.hdr.attr|=MSG_READ; if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->mod_ar[0] && chk_ar(cfg.sub[subnum]->mod_ar,&useron)) msg.hdr.attr|=MSG_MODERATED; if(subnum!=INVALID_SUB && !fromhub && cfg.sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum)) msg.hdr.attr|=MSG_PERMANENT; memset(&tm,0,sizeof(tm)); tm.tm_mon = ((hdrblk[8]&0xf)*10)+(hdrblk[9]&0xf); if(tm.tm_mon>0) tm.tm_mon--; /* zero based */ tm.tm_mday=((hdrblk[11]&0xf)*10)+(hdrblk[12]&0xf); tm.tm_year=((hdrblk[14]&0xf)*10)+(hdrblk[15]&0xf); if(tm.tm_year<Y2K_2DIGIT_WINDOW) tm.tm_year+=100; tm.tm_hour=((hdrblk[16]&0xf)*10)+(hdrblk[17]&0xf); tm.tm_min=((hdrblk[19]&0xf)*10)+(hdrblk[20]&0xf); tm.tm_sec=0; tm.tm_isdst=-1; /* Do not adjust for DST */ msg.hdr.when_written.time=mktime(&tm); if(!(useron.rest&FLAG('Q')) && !fromhub) msg.hdr.when_written.zone=sys_timezone(&cfg); msg.hdr.when_imported.time=time(NULL); msg.hdr.when_imported.zone=sys_timezone(&cfg); hdrblk[116]=0; // don't include number of blocks in "re: msg number" if(!(useron.rest&FLAG('Q')) && !fromhub) msg.hdr.thread_back=atol((char *)hdrblk+108); if(subnum==INVALID_SUB) { /* E-mail */ 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); username(&cfg,touser,str); smb_hfield_str(&msg,RECIPIENT,str); sprintf(str,"%u",touser); smb_hfield_str(&msg,RECIPIENTEXT,str); } else { if(cfg.sub[subnum]->misc&SUB_HYPER) storage = SMB_HYPERALLOC; else if(cfg.sub[subnum]->misc&SUB_FAST) storage = SMB_FASTALLOC; if(cfg.sub[subnum]->misc&SUB_LZH) xlat=XLAT_LZH; sprintf(str,"%25.25s",(char *)hdrblk+21); /* To user */ truncsp(str); smb_hfield_str(&msg,RECIPIENT,str); if(cfg.sub[subnum]->misc&SUB_LZH) xlat=XLAT_LZH; } sprintf(str,"%25.25s",hdrblk+71); /* Subject */ truncsp(str); smb_hfield_str(&msg,SUBJECT,str); /********************************/ /* Convert the QWK message text */ /********************************/ if((header=(char *)calloc((blocks-1L)*QWK_BLOCK_LEN*2L,sizeof(char)))==NULL) { smb_freemsgmem(&msg); errormsg(WHERE,ERR_ALLOC,"QWK msg header",(blocks-1L)*QWK_BLOCK_LEN*2L); return(false); } bodylen=0; if((body=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) { free(header); smb_freemsgmem(&msg); errormsg(WHERE,ERR_ALLOC,"QWK msg body",(blocks-1L)*QWK_BLOCK_LEN*2L); return(false); } taillen=0; if((tail=(char *)malloc((blocks-1L)*QWK_BLOCK_LEN*2L))==NULL) { free(header); free(body); smb_freemsgmem(&msg); errormsg(WHERE,ERR_ALLOC,"QWK msg tail",(blocks-1L)*QWK_BLOCK_LEN*2L); return(false); } memset(qwkbuf,0,sizeof(qwkbuf)); for(block=1;block<blocks;block++) { if(!fread(qwkbuf,1,QWK_BLOCK_LEN,qwk_fp)) break; for(k=0;k<QWK_BLOCK_LEN;k++) { if(qwkbuf[k]==0) continue; if(bodylen==0 && (qwkbuf[k]=='@' || header_cont)) { if((p=strchr(qwkbuf+k, QWK_NEWLINE))!=NULL) *p=0; strcat(header, qwkbuf+k); strcat(header, "\n"); if(p==NULL) { header_cont=true; break; } k+=strlen(qwkbuf+k); header_cont=false; continue; } if(!taillen && qwkbuf[k]==' ' && col==3 && bodylen>=3 && body[bodylen-3]=='-' && body[bodylen-2]=='-' && body[bodylen-1]=='-') { bodylen-=3; strcpy(tail,"--- "); taillen=4; col++; continue; } if(qwkbuf[k]==QWK_NEWLINE) { /* expand QWK_NEWLINE to crlf */ if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-' && body[bodylen-2]=='-' && body[bodylen-1]=='-') { bodylen-=3; strcpy(tail,"---"); taillen=3; } col=0; if(taillen) { tail[taillen++]=CR; tail[taillen++]=LF; } else { body[bodylen++]=CR; body[bodylen++]=LF; } continue; } /* beep restrict */ if(!fromhub && qwkbuf[k]==BEL && useron.rest&FLAG('B')) continue; /* ANSI restriction */ if(!fromhub && (qwkbuf[k]==1 || qwkbuf[k]==ESC) && useron.rest&FLAG('A')) continue; if(qwkbuf[k]!=1 && lastch!=1) col++; if(lastch==CTRL_A && !validattr(qwkbuf[k])) { if(taillen) taillen--; else bodylen--; lastch=0; continue; } lastch=qwkbuf[k]; if(taillen) tail[taillen++]=qwkbuf[k]; else body[bodylen++]=qwkbuf[k]; } } while(bodylen && body[bodylen-1]==' ') bodylen--; /* remove trailing spaces */ if(bodylen>=2 && body[bodylen-2]==CR && body[bodylen-1]==LF) bodylen-=2; while(taillen && tail[taillen-1]<=' ') taillen--; /* remove trailing garbage */ skip=0; if(useron.rest&FLAG('Q') || fromhub) { /* QWK Net */ if(!strnicmp(header,"@VIA:",5)) { if(!fromhub) set_qwk_flag(QWK_VIA); p=strchr(header, '\n'); if(p) { *p=0; skip=strlen(header)+1; } truncsp(header); p=header+5; /* Skip "@VIA:" */ while(*p && *p<=' ') p++; /* Skip any spaces */ if(route_circ(p,cfg.sys_id)) { free(header); free(body); free(tail); smb_freemsgmem(&msg); bprintf("\r\nCircular message path: %s\r\n",p); sprintf(str,"Circular message path: %s from %s" ,p,fromhub ? cfg.qhub[fromhub-1]->id:useron.alias); errorlog(str); return(false); } sprintf(str,"%s/%s" ,fromhub ? cfg.qhub[fromhub-1]->id : useron.alias,p); strupr(str); update_qwkroute(str); } else { if(fromhub) strcpy(str,cfg.qhub[fromhub-1]->id); else strcpy(str,useron.alias); } strupr(str); j=NET_QWK; smb_hfield(&msg,SENDERNETTYPE,2,&j); smb_hfield_str(&msg,SENDERNETADDR,str); sprintf(str,"%25.25s",hdrblk+46); /* From user */ truncsp(str); } else { sprintf(str,"%u",useron.number); smb_hfield_str(&msg,SENDEREXT,str); if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_NAME) strcpy(str,useron.name); else strcpy(str,useron.alias); } smb_hfield_str(&msg,SENDER,str); if(!strnicmp(header+skip,"@MSGID:",7)) { if(!fromhub) set_qwk_flag(QWK_MSGID); p=strchr(header+skip, '\n'); i=skip; if(p) { *p=0; skip+=strlen(header+i)+1; } p=header+i+7; /* Skip "@MSGID:" */ while(*p && *p<=' ') p++; /* Skip any spaces */ truncstr(p," "); /* Truncate at first space char */ smb_hfield_str(&msg,RFC822MSGID,p); } if(!strnicmp(header+skip,"@REPLY:",7)) { if(!fromhub) set_qwk_flag(QWK_MSGID); p=strchr(header+skip, '\n'); i=skip; if(p) { *p=0; skip+=strlen(header+i)+1; } p=header+i+7; /* Skip "@REPLY:" */ while(*p && *p<=' ') p++; /* Skip any spaces */ truncstr(p," "); /* Truncate at first space char */ smb_hfield_str(&msg,RFC822REPLYID,p); } if(!strnicmp(header+skip,"@TZ:",4)) { if(!fromhub) set_qwk_flag(QWK_TZ); p=strchr(header+skip, '\n'); i=skip; if(p) { *p=0; skip+=strlen(header+i)+1; } p=header+i+4; /* Skip "@TZ:" */ while(*p && *p<=' ') p++; /* Skip any spaces */ msg.hdr.when_written.zone=(short)ahtoul(p); } if(!strnicmp(header+skip,"@REPLYTO:",9)) { p=strchr(header+skip, '\n'); i=skip; if(p) { *p=0; skip+=strlen(header+i)+1; } p=header+i+9; /* Skip "@REPLYTO:" */ while(*p && *p<=' ') p++; /* Skip any spaces */ smb_hfield_str(&msg,REPLYTO,p); } free(header); /* smb_addmsg required ASCIIZ strings */ body[bodylen]=0; tail[taillen]=0; if(online==ON_REMOTE) bputs(text[WritingIndx]); if(smb.status.max_crcs==0) /* no CRC checking means no body text dupe checking */ dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY); if((i=smb_addmsg(&smb,&msg,storage,dupechk_hashes,xlat,(uchar*)body,(uchar*)tail))==SMB_SUCCESS) success=true; else if(i==SMB_DUPE_MSG) { bprintf("\r\n!%s\r\n",smb.last_error); if(!fromhub) { if(subnum==INVALID_SUB) { sprintf(str,"%s duplicate e-mail attempt (%s)",useron.alias,smb.last_error); logline("E!",str); } else { sprintf(str,"%s duplicate message attempt in %s %s (%s)" ,useron.alias ,cfg.grp[cfg.sub[subnum]->grp]->sname ,cfg.sub[subnum]->lname ,smb.last_error); logline("P!",str); } } } else errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); smb_freemsgmem(&msg); free(body); free(tail); return(success); }