Newer
Older
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(user->number == 0)
return 0;
if(user->rest&FLAG('G'))
return initmsgptrs(cfg, subscan, cfg->guest_msgscan_init, progress, cbdata);
/* New way: */
msgptrs_filename(cfg, user->number, path, sizeof path);
FILE* fp = fnopen(NULL, path, O_RDONLY|O_TEXT);
if (fp != NULL) {
str_list_t ini = iniReadFile(fp);
for(i = 0; i < cfg->total_subs; i++) {
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
str_list_t keys = iniGetSection(ini, cfg->sub[i]->code);
if(keys == NULL)
continue;
subscan[i].ptr = iniGetUInt32(keys, NULL, "ptr" , subscan[i].ptr);
subscan[i].last = iniGetUInt32(keys, NULL, "last" , subscan[i].last);
subscan[i].cfg = iniGetShortInt(keys, NULL, "cfg" , subscan[i].cfg);
subscan[i].cfg &= (SUB_CFG_NSCAN|SUB_CFG_SSCAN|SUB_CFG_YSCAN); // Sanitize the 'cfg' value
subscan[i].sav_ptr = subscan[i].ptr;
subscan[i].sav_last = subscan[i].last;
subscan[i].sav_cfg = subscan[i].cfg;
iniFreeStringList(keys);
iniRemoveSection(&ini, cfg->sub[i]->code);
}
iniFreeStringList(ini);
fclose(fp);
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
}
/* Old way: */
SAFEPRINTF2(path,"%suser/ptrs/%4.4u.ixb", cfg->data_dir, user->number);
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, progress, cbdata);
}
length=(long)filelength(file);
for(i=0;i<cfg->total_subs;i++) {
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
if(length>=(cfg->sub[i]->ptridx+1)*10L) {
fseek(stream,(long)cfg->sub[i]->ptridx*10L,SEEK_SET);
if(fread(&subscan[i].ptr,sizeof(subscan[i].ptr),1,stream) != 1)
break;
if(fread(&subscan[i].last,sizeof(subscan[i].last),1,stream) != 1)
break;
if(fread(&subscan[i].cfg,sizeof(subscan[i].cfg),1,stream) != 1)
break;
}
subscan[i].sav_ptr=subscan[i].ptr;
subscan[i].sav_last=subscan[i].last;
subscan[i].sav_cfg=subscan[i].cfg;
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
}
/****************************************************************************/
/* Writes to data/user/####.subs the msgptr array for the specified user */
/****************************************************************************/
bool putmsgptrs(scfg_t* cfg, user_t* user, subscan_t* subscan)
if (user->number==0 || (user->rest&FLAG('G'))) /* Guest */
return true;
msgptrs_filename(cfg, user->number, path, sizeof path);
FILE* fp = fnopen(NULL, path, O_RDWR|O_CREAT|O_TEXT);
if (fp == NULL)
return false;
bool result = putmsgptrs_fp(cfg, user, subscan, fp);
fclose(fp);
return result;
}
/****************************************************************************/
/* Writes to FILE* the msgptr array for the specified user */
/****************************************************************************/
bool putmsgptrs_fp(scfg_t* cfg, user_t* user, subscan_t* subscan, FILE* fp)
{

Rob Swindell
committed
int i;
time_t now = time(NULL);
if(user->number==0 || (user->rest&FLAG('G'))) /* Guest */
fixmsgptrs(cfg, subscan);
str_list_t new = strListInit();
str_list_t ini = iniReadFile(fp);
ini_style_t ini_style = { .key_prefix = "\t", .section_separator = "" };
for(i=0; i < cfg->total_subs; i++) {
str_list_t keys = iniGetSection(ini, cfg->sub[i]->code);
if(subscan[i].sav_ptr==subscan[i].ptr
&& subscan[i].sav_cfg==subscan[i].cfg
&& keys != NULL && *keys != NULL)
iniAppendSectionWithKeys(&new, cfg->sub[i]->code, keys, &ini_style);
else {
iniSetUInt32(&new, cfg->sub[i]->code, "ptr", subscan[i].ptr, &ini_style);
iniSetUInt32(&new, cfg->sub[i]->code, "last", subscan[i].last, &ini_style);
iniSetHexInt(&new, cfg->sub[i]->code, "cfg", subscan[i].cfg, &ini_style);
iniSetDateTime(&new, cfg->sub[i]->code, "updated", /* include_time: */true, now, &ini_style);
modified = true;
}
if(keys != NULL) {
iniRemoveSection(&ini, cfg->sub[i]->code);
iniFreeStringList(keys);
}
}
if(modified || strListCount(ini))
result = iniWriteFile(fp, new);
strListFree(&new);
iniFreeStringList(ini);
return result;
bool newmsgs(smb_t* smb, time_t t)
{
char index_fname[MAX_PATH + 1];
SAFEPRINTF(index_fname, "%s.sid", smb->file);
return fdate(index_fname) >= t;
}
/****************************************************************************/
/* Initialize new-msg-scan pointers (e.g. for new users) */
/* If 'days' is specified as 0, just set pointer to last message (faster) */
/****************************************************************************/
bool initmsgptrs(scfg_t* cfg, subscan_t* subscan, unsigned days, void (*progress)(void*, int, int), void* cbdata)

Rob Swindell
committed
int i;
smb_t smb;
idxrec_t idx;
time_t t = time(NULL) - (days * 24 * 60 * 60);
for(i=0;i<cfg->total_subs;i++) {
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
/* This value will be "fixed" (changed to the last msg) when saving */
subscan[i].ptr = ~0;
if(days == 0)
continue;
ZERO_VAR(smb);
SAFEPRINTF2(smb.file,"%s%s",cfg->sub[i]->data_dir,cfg->sub[i]->code);
if(!newmsgs(&smb, t))
continue;
smb.retry_time=cfg->smb_retry_time;
smb.subnum=i;
if(smb_open_index(&smb) != SMB_SUCCESS)
memset(&idx, 0, sizeof(idx));
smb_getlastidx(&smb, &idx);
subscan[i].ptr = idx.number;
if(idx.time >= t && smb_getmsgidx_by_time(&smb, &idx, t) >= SMB_SUCCESS)
subscan[i].ptr = idx.number - 1;
smb_close(&smb);
}
if(progress != NULL)
progress(cbdata, i, cfg->total_subs);
}
/****************************************************************************/
/* Insure message new-scan pointers are within the range of the msgs in */
/* the sub-board. */
/****************************************************************************/
bool fixmsgptrs(scfg_t* cfg, subscan_t* subscan)
{

Rob Swindell
committed
int i;
smb_t smb;
for(i=0;i<cfg->total_subs;i++) {
if(subscan[i].ptr == 0)
continue;
if(subscan[i].ptr < ~0 && subscan[i].sav_ptr == subscan[i].ptr)
continue;
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_index(&smb) != SMB_SUCCESS) {
subscan[i].ptr = 0;
continue;
}
idxrec_t idx;
memset(&idx, 0, sizeof(idx));
smb_getlastidx(&smb, &idx);
if(subscan[i].ptr > idx.number)
subscan[i].ptr = idx.number;
if(subscan[i].last > idx.number)
subscan[i].last = idx.number;
static char* sysop_available_semfile(scfg_t* scfg)
{
static char semfile[MAX_PATH+1];
SAFEPRINTF(semfile, "%ssysavail.chat", scfg->ctrl_dir);
return semfile;
}
bool sysop_available(scfg_t* scfg)
{
return fexist(sysop_available_semfile(scfg));
}
bool set_sysop_availability(scfg_t* scfg, bool available)
{
if(available)
return ftouch(sysop_available_semfile(scfg));
return remove(sysop_available_semfile(scfg)) == 0;
}
static char* sound_muted_semfile(scfg_t* scfg)
{
static char semfile[MAX_PATH+1];
SAFEPRINTF(semfile, "%ssound.mute", scfg->ctrl_dir);
return semfile;
}
{
return fexist(sound_muted_semfile(scfg));
}
bool set_sound_muted(scfg_t* scfg, bool muted)
{
if(muted)
return ftouch(sound_muted_semfile(scfg));
return remove(sound_muted_semfile(scfg)) == 0;
}
/************************************/
/* user .ini file get/set functions */
/************************************/
static FILE* user_ini_open(scfg_t* scfg, unsigned user_number, bool for_modify)
{
char path[MAX_PATH+1];
SAFEPRINTF2(path, "%suser/%04u.ini", scfg->data_dir, user_number);
return iniOpenFile(path, for_modify);
bool user_get_property(scfg_t* scfg, unsigned user_number, const char* section, const char* key, char* value, size_t maxlen)
{
FILE* fp;
char buf[INI_MAX_VALUE_LEN];
fp = user_ini_open(scfg, user_number, /* for_modify: */false);
if(fp == NULL)
char* result = iniReadValue(fp, section, key, NULL, buf);
if(result != NULL)
safe_snprintf(value, maxlen, "%s", result);
iniCloseFile(fp);
return result != NULL;
}
bool user_set_property(scfg_t* scfg, unsigned user_number, const char* section, const char* key, const char* value)
{
FILE* fp;
str_list_t ini;
fp = user_ini_open(scfg, user_number, /* for_modify: */true);
if(fp == NULL)
ini = iniReadFile(fp);
ini_style_t ini_style = { .key_prefix = "\t", .section_separator = "", .value_separator = " = " };
char* result = iniSetValue(&ini, section, key, value, &ini_style);
iniWriteFile(fp, ini);
iniFreeStringList(ini);
iniCloseFile(fp);
return result != NULL;
}
bool user_set_time_property(scfg_t* scfg, unsigned user_number, const char* section, const char* key, time_t value)
{
FILE* fp;
str_list_t ini;
fp = user_ini_open(scfg, user_number, /* for_modify: */true);
if(fp == NULL)
ini = iniReadFile(fp);
ini_style_t ini_style = { .key_prefix = "\t", .section_separator = "", .value_separator = " = " };
char* result = iniSetDateTime(&ini, section, key, /* include_time */true, value, &ini_style);
iniWriteFile(fp, ini);
iniFreeStringList(ini);
iniCloseFile(fp);
return result != NULL;
}
#endif /* !NO_SOCKET_SUPPORT */
/****************************************************************************/
/* Returns user number or 0 on failure or "user not found". */
/****************************************************************************/
int lookup_user(scfg_t* cfg, link_list_t* list, const char *inname)
{
if(inname == NULL || *inname == 0)
return 0;
if(list->first == NULL) {
user_t user;
int userdat = openuserdat(cfg, /* modify */false);
if(userdat < 0)
return 0;
for(user.number = 1; ;user.number++) {
if(fgetuserdat(cfg, &user, userdat) != 0)
break;
if(user.misc&DELETED)
continue;
listPushNodeData(list, &user, sizeof(user));
}
close(userdat);
}
for(list_node_t* node = listFirstNode(list); node != NULL; node = node->next) {
if(matchusername(cfg, ((user_t*)node->data)->alias, inname))
return ((user_t*)node->data)->number;
}
for(list_node_t* node = listFirstNode(list); node != NULL; node = node->next) {
if(matchusername(cfg, ((user_t*)node->data)->name, inname))
return ((user_t*)node->data)->number;
}
return 0;
}
/* Parse a virtual filebase path of the form "[/]lib[/dir][/filename]" (e.g. main/games/filename.ext) */
enum parsed_vpath parse_vpath(scfg_t* cfg, const char* vpath, user_t* user, client_t* client, bool include_upload_only
,int* lib, int* dir, char** filename)
char* tp;
char path[MAX_PATH+1];
*lib = -1;
*dir = -1;
SAFECOPY(path, vpath);
p=path;
if(*p=='/')
p++;
if(!strncmp(p,"./",2))
p+=2;
if(*p == '\0')
return PARSED_VPATH_ROOT;
tp=strchr(p,'/');
if(tp) *tp=0;
for(*lib = 0; *lib < cfg->total_libs; (*lib)++) {
if(!chk_ar(cfg,cfg->lib[*lib]->ar,user,client))
if(!stricmp(cfg->lib[*lib]->vdir,p))
if(*lib >= cfg->total_libs)
return PARSED_VPATH_NONE;
if(tp == NULL || *(tp + 1) == '\0')
return PARSED_VPATH_LIB;
tp=strchr(p,'/');
if(tp) {
*tp=0;
if(*(tp + 1) != '\0')
*filename = getfname(vpath);
}
for(*dir = 0; *dir < cfg->total_dirs; (*dir)++) {
if(cfg->dir[*dir]->lib != *lib)
if((!include_upload_only || (*dir != cfg->sysop_dir && *dir != cfg->upload_dir))
&& !chk_ar(cfg,cfg->dir[*dir]->ar,user,client))
if(!stricmp(cfg->dir[*dir]->vdir,p))
if(*dir >= cfg->total_dirs)
return PARSED_VPATH_NONE;
return *filename == NULL ? PARSED_VPATH_DIR : PARSED_VPATH_FULL;