From c9f6aaa541e7ef93052e730083eae3f200035ec2 Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Thu, 21 Jul 2011 11:28:23 +0000 Subject: [PATCH] Complete QWKE support (using MultiMail for testing): Create and include in packet TOREADER.EXT if QWKEsupport is enabled (MultiMail keys of this file for QWKE support, so without, no QWKE features are enabled in MultiMail). Parse TODOOR.EXT if included in REP packets (for adding/dropping subs or setting/resetting pointers). Parse To:, From:, and Subject: QWKE kludge lines and use if/when appropriate (e.g. to defeat QWK 25-char header field limits). Create To:, From:, and Subject: QWKE kludge lines in QWK/REP packets when QWKE support is enabled and those fields exceed QWK limits (25 chars). Also, legacy SyncQNET kludge lines (@VIA, @TZ, etc.) may now exist in the top of the message body in any order. Note: current versions of MultiMail do not support "To" fields > 25 chars, even in QWKE mode (though I have a patch pending) and do not (yet) support Synchronet HEADERS.DAT file (rendering QWKE kludges unnecessary). These are major changes in the QWK/REP creation/parsing code, so testing (especially with QWKE-compliant offline readers) and bug reports are welcome! --- src/sbbs3/msgtoqwk.cpp | 46 +++++---- src/sbbs3/pack_qwk.cpp | 62 +++++++++++- src/sbbs3/qwk.h | 3 +- src/sbbs3/qwktomsg.cpp | 218 ++++++++++++++++++----------------------- src/sbbs3/sbbs.h | 3 +- src/sbbs3/un_rep.cpp | 119 ++++++++++++++++------ 6 files changed, 274 insertions(+), 177 deletions(-) diff --git a/src/sbbs3/msgtoqwk.cpp b/src/sbbs3/msgtoqwk.cpp index 7c2dfac981..48a2d37238 100644 --- a/src/sbbs3/msgtoqwk.cpp +++ b/src/sbbs3/msgtoqwk.cpp @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -167,27 +167,25 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum fprintf(qwk_fp,"%*s",QWK_BLOCK_LEN,""); /* Init header to space */ - if(msg->from_net.addr && (uint)subnum==INVALID_SUB) { - if(mode&QM_TO_QNET) - sprintf(from,"%.128s",msg->from); - else if(msg->from_net.type==NET_FIDO) + /* 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(strlen(from)>25) { - size+=fprintf(qwk_fp,"From: %.128s%c%c",from,QWK_NEWLINE,QWK_NEWLINE); - sprintf(from,"%.128s",msg->from); - } - } - else { - sprintf(from,"%.128s",msg->from); - if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) /* from user */ - SAFECOPY(from,text[Anonymous]); } - + 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)); @@ -209,16 +207,16 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); - if(strlen(to)>25) { - size+=fprintf(qwk_fp,"To: %.128s%c%c",to,QWK_NEWLINE,QWK_NEWLINE); - if(msg->to_net.type==NET_QWK) - SAFECOPY(to,"NETMAIL"); - else - sprintf(to,"%.128s",msg->to); - } } - else - sprintf(to,"%.128s",msg->to); + 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" diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp index e0acc22567..826844b40f 100644 --- a/src/sbbs3/pack_qwk.cpp +++ b/src/sbbs3/pack_qwk.cpp @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -205,6 +205,66 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack) } } + if(useron.qwk&QWK_EXT) { + /****************************/ + /* Create TOREADER.EXT file */ + /****************************/ + SAFEPRINTF(str,"%sTOREADER.EXT",cfg.temp_dir); + if((stream=fopen(str,"wb"))==NULL) { + errormsg(WHERE,ERR_OPEN,str,0); + return(false); + } + + fprintf(stream,"ALIAS %s\r\n", useron.alias); + + /* Double-checked with multimail (qwk.cc): */ + for(i=0;i<usrgrps;i++) + for(j=0;j<usrsubs[i];j++) { + fprintf(stream,"AREA %u " + ,cfg.sub[usrsub[i][j]]->qwkconf ? cfg.sub[usrsub[i][j]]->qwkconf : ((i+1)*1000)+j+1); + switch(subscan[usrsub[i][j]].cfg&(SUB_CFG_NSCAN|SUB_CFG_YSCAN)) { + case SUB_CFG_NSCAN|SUB_CFG_YSCAN: + fputc('p', stream); // p for personal messages + break; + case SUB_CFG_NSCAN: + fputc('a', stream); // a for all messages + break; + } + switch(cfg.sub[usrsub[i][j]]->misc&(SUB_PRIV|SUB_PONLY)) { + case SUB_PRIV|SUB_PONLY: + fputc('P', stream); // P if the area is private mail only + break; + case SUB_PRIV: + fputc('X', stream); // X if either private or public mail is allowed + break; + default: + fputc('O', stream); // O if the area is public mail only + break; + } + if(useron.qwk&QWK_BYSELF) + fputc('w', stream); // w if this area should include mail written by themselves + if(cfg.sub[usrsub[i][j]]->misc&SUB_FORCED) + fputc('F', stream); // F if this area is forced to be read + if(!chk_ar(cfg.sub[usrsub[i][j]]->post_ar,&useron,&client)) + fputc('R', stream); // R if the area is read-only (no posting at all allowed) + if(cfg.sub[usrsub[i][j]]->misc&SUB_QNET) + fputc('Q', stream); // I if the area is an internet area + if(cfg.sub[usrsub[i][j]]->misc&SUB_INET) + fputc('I', stream); // I if the area is an internet area + if(cfg.sub[usrsub[i][j]]->misc&SUB_FIDO) + fputc('E', stream); // E if the area is an echomail area + if((cfg.sub[usrsub[i][j]]->misc&(SUB_FIDO|SUB_INET|SUB_QNET))==0) + fputc('L', stream); // L if the area is a local message area + if((cfg.sub[usrsub[i][j]]->misc&SUB_NAME)==0) + fputc('H', stream); // H if the area is an handles only message area + if(cfg.sub[usrsub[i][j]]->misc&SUB_ANON) + fputc('A', stream); // A if the area allows messages 'from' any name (pick-an-alias) + + fprintf(stream,"\r\n"); + } + fclose(stream); + } + /****************************************************/ /* Create MESSAGES.DAT, write header and leave open */ /****************************************************/ diff --git a/src/sbbs3/qwk.h b/src/sbbs3/qwk.h index be53a75213..2da1486a87 100644 --- a/src/sbbs3/qwk.h +++ b/src/sbbs3/qwk.h @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -37,6 +37,7 @@ #define QWK_NEWLINE '\xe3' /* QWK line terminator */ #define QWK_BLOCK_LEN 128 +#define QWK_HFIELD_LEN 25 /* Header field (To/From/Subject) length */ /* QWK mode bits */ #define QM_TAGLINE (1<<5) /* Place tagline at end of qwk message */ diff --git a/src/sbbs3/qwktomsg.cpp b/src/sbbs3/qwktomsg.cpp index 255c43973b..e18a1118bb 100644 --- a/src/sbbs3/qwktomsg.cpp +++ b/src/sbbs3/qwktomsg.cpp @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -214,18 +214,18 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks { char* body; char* tail; - char* header; - char str[256],col=0,lastch=0,*p,qwkbuf[QWK_BLOCK_LEN+1]; + char* qwkbuf; + char str[256],col=0,lastch=0,*p; char from[128]; - uint i,k,lzh=0,skip=0; + uint i,k,lzh=0; long bodylen,taillen; bool header_cont=false; bool success=false; - ulong block; 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)) @@ -278,96 +278,102 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks /* Convert the QWK message text */ /********************************/ - if((header=(char *)calloc((blocks-1L)*QWK_BLOCK_LEN*2L,sizeof(char)))==NULL) { - errormsg(WHERE,ERR_ALLOC,"QWK msg header",(blocks-1L)*QWK_BLOCK_LEN*2L); + 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(header); + 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(header); + free(qwkbuf); free(body); 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; + 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; } - if(!taillen && qwkbuf[k]==' ' && col==3 && bodylen>=3 - && body[bodylen-3]=='-' && body[bodylen-2]=='-' - && body[bodylen-1]=='-') { + *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=4; - col++; - continue; + strcpy(tail,"---"); /* DO NOT USE SAFECOPY */ + taillen=3; } - 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,"---"); /* DO NOT USE SAFECOPY */ - taillen=3; - } - col=0; - if(taillen) { - tail[taillen++]=CR; - tail[taillen++]=LF; - } - else { - body[bodylen++]=CR; - body[bodylen++]=LF; - } - continue; + col=0; + if(taillen) { + tail[taillen++]=CR; + tail[taillen++]=LF; } - /* 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]!=1 && lastch!=1) - col++; - if(lastch==CTRL_A && !valid_ctrl_a_code(qwkbuf[k])) { - if(taillen) taillen--; - else bodylen--; - lastch=0; - continue; + else { + body[bodylen++]=CR; + body[bodylen++]=LF; } - lastch=qwkbuf[k]; - if(taillen) - tail[taillen++]=qwkbuf[k]; - else - body[bodylen++]=qwkbuf[k]; - } - } + 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]!=1 && lastch!=1) + 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) @@ -375,25 +381,17 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks while(taillen && tail[taillen-1]<=' ') taillen--; /* remove trailing garbage */ - skip=0; + /* Parse QWK Kludges (QWKE standard and SyncQNET legacy) here: */ if(useron.rest&FLAG('Q') || fromhub) { /* QWK Net */ - if(!strnicmp(header,"@VIA:",5)) { + if((p=iniGetString(kludges,ROOT_SECTION,"@VIA",NULL,NULL)) != NULL) { 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)) { bprintf("\r\nCircular message path: %s\r\n",p); SAFEPRINTF2(str,"Circular message path: %s from %s" ,p,fromhub ? cfg.qhub[fromhub-1]->id:useron.alias); errorlog(str); - free(header); + strListFree(&kludges); free(body); free(tail); return(false); @@ -424,63 +422,39 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks SAFECOPY(from,useron.alias); smb_hfield_str(msg,SENDER,from); } - - if(!strnicmp(header+skip,"@MSGID:",7)) { + if((p=iniGetString(kludges,ROOT_SECTION,"@MSGID",NULL,NULL)) != NULL) { 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 */ if(msg->id==NULL) smb_hfield_str(msg,RFC822MSGID,p); } - if(!strnicmp(header+skip,"@REPLY:",7)) { + if((p=iniGetString(kludges,ROOT_SECTION,"@REPLY",NULL,NULL)) != NULL) { 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 */ if(msg->reply_id==NULL) smb_hfield_str(msg,RFC822REPLYID,p); } - if(!strnicmp(header+skip,"@TZ:",4)) { + if((p=iniGetString(kludges,ROOT_SECTION,"@TZ",NULL,NULL)) != NULL) { 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 */ + if((p=iniGetString(kludges,ROOT_SECTION,"@REPLYTO",NULL,NULL)) != NULL) { if(msg->replyto==NULL) smb_hfield_str(msg,REPLYTO,p); } - free(header); + /* 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; diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index abb50f2196..1d5a92ee73 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -334,7 +334,7 @@ public: char temp_uler[31]; /* User who uploaded the files to temp dir */ char temp_file[41]; /* Origin of extracted temp files */ long temp_cdt; /* Credit value of file that was extracted */ - char autohang; /* Used for auto-hangup after transfer */ + bool autohang; /* Used for auto-hangup after transfer */ size_t logcol; /* Current column of log file */ uint criterrs; /* Critical error counter */ @@ -741,6 +741,7 @@ public: /* un_rep.cpp */ bool unpack_rep(char* repfile=NULL); + uint resolve_qwkconf(uint n); /* msgtoqwk.cpp */ ulong msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, int subnum, int conf, FILE* hdrs_dat); diff --git a/src/sbbs3/un_rep.cpp b/src/sbbs3/un_rep.cpp index e5fb8accc7..242f960792 100644 --- a/src/sbbs3/un_rep.cpp +++ b/src/sbbs3/un_rep.cpp @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -38,6 +38,40 @@ #include "sbbs.h" #include "qwk.h" +/****************************************************************************/ +/* Convert a QWK conference number into a sub-board offset */ +/* Return INVALID_SUB upon failure to convert */ +/****************************************************************************/ +uint sbbs_t::resolve_qwkconf(uint n) +{ + uint j,k; + + 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) + return INVALID_SUB; + } + + return usrsub[j][k]; +} + /****************************************************************************/ /* Unpacks .REP packet, 'repname' is the path and filename of the packet */ /****************************************************************************/ @@ -347,36 +381,15 @@ bool sbbs_t::unpack_rep(char* repfile) /**************************/ 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; - } + n=resolve_qwkconf(atol((char *)block+1)); /* conference number */ - 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); - SAFEPRINTF2(str,"%s: Invalid QWK conference number %lu",useron.alias,n); - logline(LOG_NOTICE,"P!",str); - continue; - } + if(n==INVALID_SUB) { + bprintf(text[QWKInvalidConferenceN],n); + SAFEPRINTF2(str,"%s: Invalid QWK conference number %lu",useron.alias,n); + logline(LOG_NOTICE,"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; @@ -536,6 +549,56 @@ bool sbbs_t::unpack_rep(char* repfile) smb_close(&smb); fclose(rep); + /* QWKE support */ + SAFEPRINTF(fname,"%sTODOOR.EXT",cfg.temp_dir); + if(fexistcase(fname)) { + useron.qwk|=QWK_EXT; + FILE* fp=fopen(fname,"r"); + char* p; + if(fp!=NULL) { + while(!feof(fp)) { + if(!fgets(str,sizeof(str)-1,fp)) + break; + if(strnicmp(str,"AREA ",5)==0) { + p=str+5; + SKIP_WHITESPACE(p); + if((n=resolve_qwkconf(atoi(p))) != INVALID_SUB) { + FIND_WHITESPACE(p); + SKIP_WHITESPACE(p); + if(strchr(p,'D')) + subscan[n].cfg&=~SUB_CFG_NSCAN; + else if(strchr(p,'a') || strchr(p,'g')) + subscan[n].cfg|=SUB_CFG_NSCAN; + else if(strchr(p,'p')) + subscan[n].cfg|=SUB_CFG_NSCAN|SUB_CFG_YSCAN; + } + continue; + } + if(strnicmp(str,"RESET ",6)==0) { + p=str+6; + SKIP_WHITESPACE(p); + if((n=resolve_qwkconf(atoi(p))) != INVALID_SUB) { + FIND_WHITESPACE(p); + SKIP_WHITESPACE(p); + /* If the [#ofmessages] is blank then the pointer should be set back to the start of the message base */ + if(*p==0) + subscan[n].ptr=0; + else { + /* otherwise it should be set back [#ofmessages] back from the end of the message base. */ + uint32_t last=0; + getlastmsg(n,&last,/* time_t* */NULL); + l=last-atol(p); + if(l<0) + l=0; + subscan[n].ptr=l; + } + } + } + } + fclose(fp); + } + } + if(useron.rest&FLAG('Q')) { /* QWK Net Node */ if(fexistcase(msg_fname)) remove(msg_fname); -- GitLab