Commit 65a68990 authored by rswindell's avatar rswindell
Browse files

New long-sought feature:

Sysop can set the number of days-worth of new messages that new users will
see in their first new-message scan (the default is 0, no new messages).
This does lengthen the amount of time that the first "Loading message pointers"
is displayed (it has to go and open all the message bases), but at least new
users are no longer bombarded with thousands of very old messages when they
answer "Yes" to the "Scan for New Messages" prompt. This setting is in
SCFG->System->New User Values->Days of New Messages. Set it to some really
high number (maximum of 9999) if you want the old behavior.
parent 140a364e
......@@ -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 2011 Rob Swindell - http://www.synchro.net/copyright.html *
* Copyright 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 *
......@@ -51,111 +51,11 @@ void sbbs_t::getmsgptrs()
bputs(text[LoadedMsgPtrs]);
}
extern "C" BOOL DLLCALL getmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan)
{
char str[256];
uint i;
int file;
long length;
FILE* stream;
/* Initialize to configured defaults */
for(i=0;i<cfg->total_subs;i++) {
subscan[i].ptr=subscan[i].sav_ptr=0;
subscan[i].last=subscan[i].sav_last=0;
subscan[i].cfg=0xff;
if(!(cfg->sub[i]->misc&SUB_NSDEF))
subscan[i].cfg&=~SUB_CFG_NSCAN;
if(!(cfg->sub[i]->misc&SUB_SSDEF))
subscan[i].cfg&=~SUB_CFG_SSCAN;
subscan[i].sav_cfg=subscan[i].cfg;
}
if(!usernumber)
return(FALSE);
sprintf(str,"%suser/ptrs/%4.4u.ixb", cfg->data_dir,usernumber);
if((stream=fnopen(&file,str,O_RDONLY))==NULL)
return(TRUE);
length=(long)filelength(file);
for(i=0;i<cfg->total_subs;i++) {
if(length>=(cfg->sub[i]->ptridx+1)*10L) {
fseek(stream,(long)cfg->sub[i]->ptridx*10L,SEEK_SET);
fread(&subscan[i].ptr,sizeof(subscan[i].ptr),1,stream);
fread(&subscan[i].last,sizeof(subscan[i].last),1,stream);
fread(&subscan[i].cfg,sizeof(subscan[i].cfg),1,stream);
}
subscan[i].sav_ptr=subscan[i].ptr;
subscan[i].sav_last=subscan[i].last;
subscan[i].sav_cfg=subscan[i].cfg;
}
fclose(stream);
return(TRUE);
}
void sbbs_t::putmsgptrs()
{
::putmsgptrs(&cfg,useron.number,subscan);
}
/****************************************************************************/
/* Writes to DATA\USER\PTRS\xxxx.DAB the msgptr array for the current user */
/* Called from functions main and newuser */
/****************************************************************************/
extern "C" BOOL DLLCALL putmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan)
{
char str[256];
ushort idx;
uint16_t scancfg;
uint i,j;
int file;
ulong length;
uint32_t l=0L;
if(!usernumber)
return(FALSE);
sprintf(str,"%suser/ptrs/%4.4u.ixb", cfg->data_dir,usernumber);
if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
return(FALSE);
}
length=(ulong)filelength(file);
for(i=0;i<cfg->total_subs;i++) {
if(subscan[i].sav_ptr==subscan[i].ptr
&& subscan[i].sav_last==subscan[i].last
&& length>=((cfg->sub[i]->ptridx+1)*10UL)
&& subscan[i].sav_cfg==subscan[i].cfg)
continue;
while(filelength(file)<(long)(cfg->sub[i]->ptridx)*10) {
lseek(file,0L,SEEK_END);
idx=(ushort)(tell(file)/10);
for(j=0;j<cfg->total_subs;j++)
if(cfg->sub[j]->ptridx==idx)
break;
write(file,&l,sizeof(l));
write(file,&l,sizeof(l));
scancfg=0xff;
if(j<cfg->total_subs) {
if(!(cfg->sub[j]->misc&SUB_NSDEF))
scancfg&=~SUB_CFG_NSCAN;
if(!(cfg->sub[j]->misc&SUB_SSDEF))
scancfg&=~SUB_CFG_SSCAN;
} else /* default to scan OFF for unknown sub */
scancfg&=~(SUB_CFG_NSCAN|SUB_CFG_SSCAN);
write(file,&scancfg,sizeof(scancfg));
}
lseek(file,(long)((long)(cfg->sub[i]->ptridx)*10),SEEK_SET);
write(file,&(subscan[i].ptr),sizeof(subscan[i].ptr));
write(file,&(subscan[i].last),sizeof(subscan[i].last));
write(file,&(subscan[i].cfg),sizeof(subscan[i].cfg));
}
close(file);
if(!flength(str)) /* Don't leave 0 byte files */
remove(str);
return(TRUE);
}
/****************************************************************************/
/* Checks for a duplicate user field starting at user record offset */
/* 'offset', reading in 'datlen' chars, comparing to 'str' for each user */
......@@ -172,5 +72,3 @@ uint sbbs_t::userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
bputs(text[SearchedForDupes]);
return(i);
}
......@@ -80,7 +80,7 @@ int sbbs_t::loadmsg(smbmsg_t *msg, ulong number)
return(0);
}
if((i=smb_getmsghdr(&smb,msg))!=SMB_SUCCESS) {
sprintf(str,"(%06"PRIX32") #%"PRIu32"/%lu %s",msg->idx.offset,msg->idx.number
SAFEPRINTF4(str,"(%06"PRIX32") #%"PRIu32"/%lu %s",msg->idx.offset,msg->idx.number
,number,smb.file);
smb_unlockmsghdr(&smb,msg);
errormsg(WHERE,ERR_READ,str,i,smb.last_error);
......@@ -129,7 +129,7 @@ void sbbs_t::show_msghdr(smbmsg_t* msg)
else
CRLF;
sprintf(str,"%smenu/msghdr.*", cfg.text_dir);
SAFEPRINTF(str,"%smenu/msghdr.*", cfg.text_dir);
if(fexist(str)) {
menu("msghdr");
return;
......@@ -237,69 +237,25 @@ void sbbs_t::msgtotxt(smbmsg_t* msg, char *str, int header, int tails)
/****************************************************************************/
ulong sbbs_t::getmsgnum(uint subnum, time_t t)
{
int i;
ulong l,total,bot,top;
smbmsg_t msg;
int i;
smb_t smb;
idxrec_t idx;
if(!t)
return(0);
sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
ZERO_VAR(smb);
SAFEPRINTF2(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
smb.retry_time=cfg.smb_retry_time;
smb.subnum=subnum;
if((i=smb_open(&smb))!=0) {
if((i=smb_open(&smb)) != SMB_SUCCESS) {
errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
return(0);
}
smb_getmsgidx_by_time(&smb, &idx, t);
total=(long)filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
if(!total) { /* Empty base */
smb_close(&smb);
return(0);
}
if((i=smb_locksmbhdr(&smb))!=0) {
smb_close(&smb);
errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
return(0);
}
if((i=smb_getlastidx(&smb,&msg.idx))!=0) {
smb_close(&smb);
errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error);
return(0);
}
if((time_t)msg.idx.time<=t) {
smb_close(&smb);
return(msg.idx.number);
}
bot=0;
top=total;
l=total/2; /* Start at middle index */
clearerr(smb.sid_fp);
while(1) {
fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET);
if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
break;
if(bot==top-1)
break;
if((time_t)msg.idx.time>t) {
top=l;
l=bot+((top-bot)/2);
continue;
}
if((time_t)msg.idx.time<t) {
bot=l;
l=top-((top-bot)/2);
continue;
}
break;
}
smb_close(&smb);
return(msg.idx.number);
return idx.number;
}
/****************************************************************************/
......@@ -307,11 +263,13 @@ ulong sbbs_t::getmsgnum(uint subnum, time_t t)
/****************************************************************************/
time_t sbbs_t::getmsgtime(uint subnum, ulong ptr)
{
int i;
smbmsg_t msg;
idxrec_t lastidx;
int i;
smb_t smb;
smbmsg_t msg;
idxrec_t lastidx;
sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
ZERO_VAR(smb);
SAFEPRINTF2(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
smb.retry_time=cfg.smb_retry_time;
smb.subnum=subnum;
if((i=smb_open(&smb))!=0) {
......@@ -382,6 +340,7 @@ ulong sbbs_t::getlastmsg(uint subnum, uint32_t *ptr, time_t *t)
{
int i;
ulong total;
smb_t smb;
idxrec_t idx;
if(ptr)
......@@ -391,7 +350,8 @@ ulong sbbs_t::getlastmsg(uint subnum, uint32_t *ptr, time_t *t)
if(subnum>=cfg.total_subs)
return(0);
sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
ZERO_VAR(smb);
SAFEPRINTF2(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
smb.retry_time=cfg.smb_retry_time;
smb.subnum=subnum;
if((i=smb_open(&smb))!=0) {
......
......@@ -1100,10 +1100,6 @@ extern "C" {
/* data.cpp */
DLLEXPORT time_t DLLCALL getnextevent(scfg_t* cfg, event_t* event);
/* data_ovl.cpp */
DLLEXPORT BOOL DLLCALL getmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan);
DLLEXPORT BOOL DLLCALL putmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan);
/* sockopt.c */
DLLEXPORT int DLLCALL set_socket_options(scfg_t* cfg, SOCKET sock, const char* section
,char* error, size_t errlen);
......
......@@ -866,6 +866,7 @@ while(1) {
else
strcpy(str,"None");
sprintf(opt[i++],"%-27.27s%s","Download Protocol",str);
sprintf(opt[i++],"%-27.27s%hu","Days of New Messages", cfg.new_msgscan_init);
strcpy(opt[i++],"Default Toggles...");
strcpy(opt[i++],"Question Toggles...");
opt[i][0]=0;
......@@ -1049,6 +1050,21 @@ while(1) {
cfg.new_prot=' ';
break;
case 13:
uifc.helpbuf=
"`New User Days of New Messages:`\n"
"\n"
"This option allows you to set the number of days worth of messages\n"
"which will be included in the new user's first `new message scan`.\n"
"\n"
"The value `0` means there will be `no` new messages for the new user.\n"
;
sprintf(str,"%hu",cfg.new_msgscan_init);
uifc.input(WIN_SAV|WIN_MID,0,0
,"Days of New Messages for New User's first new message scan"
,str,4,K_EDIT|K_NUMBER);
cfg.new_msgscan_init=atoi(str);
break;
case 14:
uifc.helpbuf=
"`New User Default Toggle Options:`\n"
"\n"
......@@ -1147,7 +1163,7 @@ while(1) {
}
}
break;
case 14:
case 15:
uifc.helpbuf=
"`New User Question Toggle Options:`\n"
"\n"
......
......@@ -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 2015 Rob Swindell - http://www.synchro.net/copyright.html *
* Copyright 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 *
......@@ -498,6 +498,7 @@ typedef struct
uint32_t new_misc; /* New User Miscellaneous Defaults */
uint16_t new_expire; /* Expiration days for new user */
uchar new_prot; /* New User Default Download Protocol */
uint16_t new_msgscan_init; /* Uew User new-scan pointers initialized to msgs this old (in days) */
char val_level[10]; /* Validation User Main Level */
uint32_t val_flags1[10]; /* Validation User Flags from set #1*/
uint32_t val_flags2[10]; /* Validation User Flags from set #2*/
......
......@@ -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 2015 Rob Swindell - http://www.synchro.net/copyright.html *
* Copyright 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 *
......@@ -276,7 +276,8 @@ BOOL read_main_cfg(scfg_t* cfg, char* error)
if(cfg->new_prot<' ')
cfg->new_prot=' ';
get_int(cfg->new_install,instream);
for(i=0;i<7;i++)
get_int(cfg->new_msgscan_init,instream);
for(i=0;i<6;i++)
get_int(n,instream);
/*************************/
......
......@@ -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 2015 Rob Swindell - http://www.synchro.net/copyright.html *
* Copyright 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 *
......@@ -351,8 +351,9 @@ BOOL DLLCALL write_main_cfg(scfg_t* cfg, int backup_level)
put_int(cfg->new_misc,stream);
put_int(cfg->new_prot,stream);
put_int(cfg->new_install,stream);
put_int(cfg->new_msgscan_init, stream);
n=0;
for(i=0;i<7;i++)
for(i=0;i<6;i++)
put_int(n,stream);
put_int(cfg->expired_level,stream);
......
......@@ -2835,3 +2835,136 @@ ulong DLLCALL loginFailure(link_list_t* list, const union xp_sockaddr* addr, con
return count;
}
/****************************************************************************/
/* Message-new-scan pointer functions (moved from data_ovl.cpp): */
/****************************************************************************/
BOOL DLLCALL getmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan)
{
char path[MAX_PATH+1];
uint i;
int file;
long length;
FILE* stream;
/* Initialize to configured defaults */
for(i=0;i<cfg->total_subs;i++) {
subscan[i].ptr=subscan[i].sav_ptr=0;
subscan[i].last=subscan[i].sav_last=0;
subscan[i].cfg=0xff;
if(!(cfg->sub[i]->misc&SUB_NSDEF))
subscan[i].cfg&=~SUB_CFG_NSCAN;
if(!(cfg->sub[i]->misc&SUB_SSDEF))
subscan[i].cfg&=~SUB_CFG_SSCAN;
subscan[i].sav_cfg=subscan[i].cfg;
}
if(!usernumber)
return(FALSE);
SAFEPRINTF2(path,"%suser/ptrs/%4.4u.ixb", cfg->data_dir, usernumber);
if((stream=fnopen(&file,path,O_RDONLY))==NULL) {
if(fexist(path))
return(FALSE); /* file exists, but couldn't be opened? */
return initmsgptrs(cfg, subscan, cfg->new_msgscan_init);
}
length=(long)filelength(file);
for(i=0;i<cfg->total_subs;i++) {
if(length>=(cfg->sub[i]->ptridx+1)*10L) {
fseek(stream,(long)cfg->sub[i]->ptridx*10L,SEEK_SET);
fread(&subscan[i].ptr,sizeof(subscan[i].ptr),1,stream);
fread(&subscan[i].last,sizeof(subscan[i].last),1,stream);
fread(&subscan[i].cfg,sizeof(subscan[i].cfg),1,stream);
}
subscan[i].sav_ptr=subscan[i].ptr;
subscan[i].sav_last=subscan[i].last;
subscan[i].sav_cfg=subscan[i].cfg;
}
fclose(stream);
return(TRUE);
}
/****************************************************************************/
/* Writes to DATA\USER\PTRS\xxxx.DAB the msgptr array for the current user */
/* Called from functions main and newuser */
/****************************************************************************/
BOOL DLLCALL putmsgptrs(scfg_t* cfg, uint usernumber, subscan_t* subscan)
{
char path[MAX_PATH+1];
ushort idx;
uint16_t scancfg;
uint i,j;
int file;
ulong length;
uint32_t l=0L;
if(!usernumber)
return(FALSE);
SAFEPRINTF2(path,"%suser/ptrs/%4.4u.ixb", cfg->data_dir, usernumber);
if((file=nopen(path,O_WRONLY|O_CREAT))==-1) {
return(FALSE);
}
length=(ulong)filelength(file);
for(i=0;i<cfg->total_subs;i++) {
if(subscan[i].sav_ptr==subscan[i].ptr
&& subscan[i].sav_last==subscan[i].last
&& length>=((cfg->sub[i]->ptridx+1)*10UL)
&& subscan[i].sav_cfg==subscan[i].cfg)
continue;
while(filelength(file)<(long)(cfg->sub[i]->ptridx)*10) {
lseek(file,0L,SEEK_END);
idx=(ushort)(tell(file)/10);
for(j=0;j<cfg->total_subs;j++)
if(cfg->sub[j]->ptridx==idx)
break;
write(file,&l,sizeof(l));
write(file,&l,sizeof(l));
scancfg=0xff;
if(j<cfg->total_subs) {
if(!(cfg->sub[j]->misc&SUB_NSDEF))
scancfg&=~SUB_CFG_NSCAN;
if(!(cfg->sub[j]->misc&SUB_SSDEF))
scancfg&=~SUB_CFG_SSCAN;
} else /* default to scan OFF for unknown sub */
scancfg&=~(SUB_CFG_NSCAN|SUB_CFG_SSCAN);
write(file,&scancfg,sizeof(scancfg));
}
lseek(file,(long)((long)(cfg->sub[i]->ptridx)*10),SEEK_SET);
write(file,&(subscan[i].ptr),sizeof(subscan[i].ptr));
write(file,&(subscan[i].last),sizeof(subscan[i].last));
write(file,&(subscan[i].cfg),sizeof(subscan[i].cfg));
}
close(file);
if(!flength(path)) /* Don't leave 0 byte files */
remove(path);
return(TRUE);
}
/****************************************************************************/
/* Initialize new-msg-scan pointers (e.g. for new users) */
/* If 'days' is specified as 0, just set pointer to last message (faster) */
/****************************************************************************/
BOOL DLLCALL initmsgptrs(scfg_t* cfg, subscan_t* subscan, unsigned days)
{
uint i;
smb_t smb;
idxrec_t idx;
time_t t = time(NULL) - (days * 24 * 60 * 60);
for(i=0;i<cfg->total_subs;i++) {
ZERO_VAR(smb);
SAFEPRINTF2(smb.file,"%s%s",cfg->sub[i]->data_dir,cfg->sub[i]->code);
smb.retry_time=cfg->smb_retry_time;
smb.subnum=i;
if(smb_open(&smb) != SMB_SUCCESS)
continue;
if(days == 0)
subscan[i].sav_ptr = subscan[i].ptr = smb.status.last_msg;
else if(smb_getmsgidx_by_time(&smb, &idx, t) == SMB_SUCCESS)
subscan[i].sav_ptr = subscan[i].ptr = idx.number;
smb_close(&smb);
}
return TRUE;
}
......@@ -121,6 +121,12 @@ DLLEXPORT BOOL DLLCALL is_download_free(scfg_t* cfg, uint dirnum, user_t* user,
DLLEXPORT BOOL DLLCALL filter_ip(scfg_t* cfg, const char* prot, const char* reason, const char* host
,const char* ip_addr, const char* username, const char* fname);
/* New-message-scan pointer functions: */
DLLEXPORT BOOL DLLCALL getmsgptrs(scfg_t*, uint usernumber, subscan_t*);
DLLEXPORT BOOL DLLCALL putmsgptrs(scfg_t*, uint usernumber, subscan_t*);
DLLEXPORT BOOL DLLCALL initmsgptrs(scfg_t*, subscan_t*, unsigned days);
/* New atomic numeric user field adjustment functions: */
DLLEXPORT BOOL DLLCALL user_posted_msg(scfg_t* cfg, user_t* user, int count);
DLLEXPORT BOOL DLLCALL user_sent_email(scfg_t* cfg, user_t* user, int count, BOOL feedback);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment