Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit c9f6aaa5 authored by rswindell's avatar rswindell

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!
parent 77a2cda0
......@@ -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"
......
......@@ -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 */
/****************************************************/
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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);
......
......@@ -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)) {