--- sbbs/src/sbbs3/js_user.c 2018/04/24 16:41:23 1.1.1.1 +++ sbbs/src/sbbs3/js_user.c 2018/04/24 16:43:34 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet JavaScript "User" Object */ -/* $Id: js_user.c,v 1.1.1.1 2018/04/24 16:41:23 root Exp $ */ +/* $Id: js_user.c,v 1.1.1.2 2018/04/24 16:43:34 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2010 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 * @@ -36,6 +36,7 @@ ****************************************************************************/ #include "sbbs.h" +#include "js_request.h" #ifdef JAVASCRIPT @@ -45,9 +46,11 @@ static const char* getprivate_failure = typedef struct { - user_t user; - BOOL cached; - scfg_t* cfg; + user_t* user; + user_t storage; + BOOL cached; + scfg_t* cfg; + client_t* client; } private_t; @@ -124,12 +127,13 @@ enum { ,USER_PROP_POSTSPERDAY ,USER_PROP_FREECDTPERDAY ,USER_PROP_CACHED + ,USER_PROP_IS_SYSOP }; static void js_getuserdat(private_t* p) { if(!p->cached) { - if(getuserdat(p->cfg,&p->user)==0) + if(getuserdat(p->cfg,p->user)==0) p->cached=TRUE; } } @@ -143,243 +147,251 @@ static JSBool js_user_get(JSContext *cx, jsint tiny; JSString* js_str; private_t* p; + jsrefcount rc; - if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { - JS_ReportError(cx,getprivate_failure,WHERE); - return(JS_FALSE); - } + if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_TRUE); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); tiny = JSVAL_TO_INT(id); switch(tiny) { case USER_PROP_NUMBER: - val=p->user.number; + val=p->user->number; break; case USER_PROP_ALIAS: - s=p->user.alias; + s=p->user->alias; break; case USER_PROP_NAME: - s=p->user.name; + s=p->user->name; break; case USER_PROP_HANDLE: - s=p->user.handle; + s=p->user->handle; break; case USER_PROP_NOTE: - s=p->user.note; + s=p->user->note; break; case USER_PROP_COMP: - s=p->user.comp; + s=p->user->comp; break; case USER_PROP_COMMENT: - s=p->user.comment; + s=p->user->comment; break; case USER_PROP_NETMAIL: - s=p->user.netmail; + s=p->user->netmail; break; case USER_PROP_EMAIL: s=usermailaddr(p->cfg, tmp - ,p->cfg->inetmail_misc&NMAIL_ALIAS ? p->user.alias : p->user.name); + ,p->cfg->inetmail_misc&NMAIL_ALIAS ? p->user->alias : p->user->name); break; case USER_PROP_ADDRESS: - s=p->user.address; + s=p->user->address; break; case USER_PROP_LOCATION: - s=p->user.location; + s=p->user->location; break; case USER_PROP_ZIPCODE: - s=p->user.zipcode; + s=p->user->zipcode; break; case USER_PROP_PASS: - s=p->user.pass; + s=p->user->pass; break; case USER_PROP_PHONE: - s=p->user.phone; + s=p->user->phone; break; case USER_PROP_BIRTH: - s=p->user.birth; + s=p->user->birth; break; case USER_PROP_AGE: - val=getage(p->cfg,p->user.birth); + val=getage(p->cfg,p->user->birth); break; case USER_PROP_MODEM: - s=p->user.modem; + s=p->user->modem; break; case USER_PROP_LASTON: - val=p->user.laston; + val=p->user->laston; break; case USER_PROP_FIRSTON: - val=p->user.firston; + val=p->user->firston; break; case USER_PROP_EXPIRE: - val=p->user.expire; + val=p->user->expire; break; case USER_PROP_PWMOD: - val=p->user.pwmod; + val=p->user->pwmod; break; case USER_PROP_LOGONS: - val=p->user.logons; + val=p->user->logons; break; case USER_PROP_LTODAY: - val=p->user.ltoday; + val=p->user->ltoday; break; case USER_PROP_TIMEON: - val=p->user.timeon; + val=p->user->timeon; break; case USER_PROP_TEXTRA: - val=p->user.textra; + val=p->user->textra; break; case USER_PROP_TTODAY: - val=p->user.ttoday; + val=p->user->ttoday; break; case USER_PROP_TLAST: - val=p->user.tlast; + val=p->user->tlast; break; case USER_PROP_POSTS: - val=p->user.posts; + val=p->user->posts; break; case USER_PROP_EMAILS: - val=p->user.emails; + val=p->user->emails; break; case USER_PROP_FBACKS: - val=p->user.fbacks; + val=p->user->fbacks; break; case USER_PROP_ETODAY: - val=p->user.etoday; + val=p->user->etoday; break; case USER_PROP_PTODAY: - val=p->user.ptoday; + val=p->user->ptoday; break; case USER_PROP_ULB: - val=p->user.ulb; + val=p->user->ulb; break; case USER_PROP_ULS: - val=p->user.uls; + val=p->user->uls; break; case USER_PROP_DLB: - val=p->user.dlb; + val=p->user->dlb; break; case USER_PROP_DLS: - val=p->user.dls; + val=p->user->dls; break; case USER_PROP_CDT: - val=p->user.cdt; + val=p->user->cdt; break; case USER_PROP_MIN: - val=p->user.min; + val=p->user->min; break; case USER_PROP_LEVEL: - val=p->user.level; + val=p->user->level; break; case USER_PROP_FLAGS1: - val=p->user.flags1; + val=p->user->flags1; break; case USER_PROP_FLAGS2: - val=p->user.flags2; + val=p->user->flags2; break; case USER_PROP_FLAGS3: - val=p->user.flags3; + val=p->user->flags3; break; case USER_PROP_FLAGS4: - val=p->user.flags4; + val=p->user->flags4; break; case USER_PROP_EXEMPT: - val=p->user.exempt; + val=p->user->exempt; break; case USER_PROP_REST: - val=p->user.rest; + val=p->user->rest; break; case USER_PROP_ROWS: - val=p->user.rows; + val=p->user->rows; break; case USER_PROP_SEX: - sprintf(tmp,"%c",p->user.sex); + sprintf(tmp,"%c",p->user->sex); s=tmp; break; case USER_PROP_MISC: - val=p->user.misc; + val=p->user->misc; break; case USER_PROP_LEECH: - val=p->user.leech; + val=p->user->leech; break; case USER_PROP_CURSUB: - s=p->user.cursub; + s=p->user->cursub; break; case USER_PROP_CURDIR: - s=p->user.curdir; + s=p->user->curdir; break; case USER_PROP_CURXTRN: - s=p->user.curxtrn; + s=p->user->curxtrn; break; case USER_PROP_FREECDT: - val=p->user.freecdt; + val=p->user->freecdt; break; case USER_PROP_XEDIT: - if(p->user.xedit>0 && p->user.xedit<=p->cfg->total_xedits) - s=p->cfg->xedit[p->user.xedit-1]->code; + if(p->user->xedit>0 && p->user->xedit<=p->cfg->total_xedits) + s=p->cfg->xedit[p->user->xedit-1]->code; else s=""; /* internal editor */ break; case USER_PROP_SHELL: - s=p->cfg->shell[p->user.shell]->code; + s=p->cfg->shell[p->user->shell]->code; break; case USER_PROP_QWK: - val=p->user.qwk; + val=p->user->qwk; break; case USER_PROP_TMPEXT: - s=p->user.tmpext; + s=p->user->tmpext; break; case USER_PROP_CHAT: - val=p->user.chat; + val=p->user->chat; break; case USER_PROP_NS_TIME: - val=p->user.ns_time; + val=p->user->ns_time; break; case USER_PROP_PROT: - sprintf(tmp,"%c",p->user.prot); + sprintf(tmp,"%c",p->user->prot); s=tmp; break; case USER_PROP_LOGONTIME: - val=p->user.logontime; + val=p->user->logontime; break; case USER_PROP_TIMEPERCALL: - val=p->cfg->level_timepercall[p->user.level]; + val=p->cfg->level_timepercall[p->user->level]; break; case USER_PROP_TIMEPERDAY: - val=p->cfg->level_timeperday[p->user.level]; + val=p->cfg->level_timeperday[p->user->level]; break; case USER_PROP_CALLSPERDAY: - val=p->cfg->level_callsperday[p->user.level]; + val=p->cfg->level_callsperday[p->user->level]; break; case USER_PROP_LINESPERMSG: - val=p->cfg->level_linespermsg[p->user.level]; + val=p->cfg->level_linespermsg[p->user->level]; break; case USER_PROP_POSTSPERDAY: - val=p->cfg->level_postsperday[p->user.level]; + val=p->cfg->level_postsperday[p->user->level]; break; case USER_PROP_EMAILPERDAY: - val=p->cfg->level_emailperday[p->user.level]; + val=p->cfg->level_emailperday[p->user->level]; break; case USER_PROP_FREECDTPERDAY: - val=p->cfg->level_freecdtperday[p->user.level]; + val=p->cfg->level_freecdtperday[p->user->level]; break; case USER_PROP_MAIL_WAITING: - val=getmail(p->cfg,p->user.number,/* sent? */FALSE); + val=getmail(p->cfg,p->user->number,/* sent? */FALSE); break; case USER_PROP_MAIL_PENDING: - val=getmail(p->cfg,p->user.number,/* sent? */TRUE); + val=getmail(p->cfg,p->user->number,/* sent? */TRUE); break; case USER_PROP_CACHED: *vp = BOOLEAN_TO_JSVAL(p->cached); + JS_RESUMEREQUEST(cx, rc); + return(JS_TRUE); /* intentional early return */ + + case USER_PROP_IS_SYSOP: + *vp = BOOLEAN_TO_JSVAL(p->user->level >= SYSOP_LEVEL); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); /* intentional early return */ default: /* This must not set vp in order for child objects to work (stats and security) */ + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } + JS_RESUMEREQUEST(cx, rc); if(s!=NULL) { if((js_str=JS_NewStringCopyZ(cx, s))==NULL) return(JS_FALSE); @@ -400,11 +412,10 @@ static JSBool js_user_set(JSContext *cx, JSString* js_str; private_t* p; int32 usernumber; + jsrefcount rc; - if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { - JS_ReportError(cx,getprivate_failure,WHERE); - return(JS_FALSE); - } + if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_TRUE); if((js_str=JS_ValueToString(cx,*vp))==NULL) return(JS_FALSE); @@ -414,166 +425,225 @@ static JSBool js_user_set(JSContext *cx, tiny = JSVAL_TO_INT(id); + rc=JS_SUSPENDREQUEST(cx); switch(tiny) { case USER_PROP_NUMBER: + JS_RESUMEREQUEST(cx, rc); JS_ValueToInt32(cx, *vp, &usernumber); - if(usernumber!=p->user.number) - p->user.number=(ushort)usernumber; + rc=JS_SUSPENDREQUEST(cx); + if(usernumber!=p->user->number) { + p->user->number=(ushort)usernumber; + p->cached=FALSE; + } break; case USER_PROP_ALIAS: + SAFECOPY(p->user->alias,str); /* update USER.DAT */ - putuserrec(p->cfg,p->user.number,U_ALIAS,LEN_ALIAS,str); + putuserrec(p->cfg,p->user->number,U_ALIAS,LEN_ALIAS,str); /* update NAME.DAT */ - getuserrec(p->cfg,p->user.number,U_MISC,8,tmp); + getuserrec(p->cfg,p->user->number,U_MISC,8,tmp); usermisc=ahtoul(tmp); if(!(usermisc&DELETED)) - putusername(p->cfg,p->user.number,str); + putusername(p->cfg,p->user->number,str); break; case USER_PROP_NAME: - putuserrec(p->cfg,p->user.number,U_NAME,LEN_NAME,str); + SAFECOPY(p->user->name,str); + putuserrec(p->cfg,p->user->number,U_NAME,LEN_NAME,str); break; case USER_PROP_HANDLE: - putuserrec(p->cfg,p->user.number,U_HANDLE,LEN_HANDLE,str); + SAFECOPY(p->user->handle,str); + putuserrec(p->cfg,p->user->number,U_HANDLE,LEN_HANDLE,str); break; case USER_PROP_NOTE: - putuserrec(p->cfg,p->user.number,U_NOTE,LEN_NOTE,str); + SAFECOPY(p->user->note,str); + putuserrec(p->cfg,p->user->number,U_NOTE,LEN_NOTE,str); break; - case USER_PROP_COMP: - putuserrec(p->cfg,p->user.number,U_COMP,LEN_COMP,str); + case USER_PROP_COMP: + SAFECOPY(p->user->comp,str); + putuserrec(p->cfg,p->user->number,U_COMP,LEN_COMP,str); break; case USER_PROP_COMMENT: - putuserrec(p->cfg,p->user.number,U_COMMENT,LEN_COMMENT,str); + SAFECOPY(p->user->comment,str); + putuserrec(p->cfg,p->user->number,U_COMMENT,LEN_COMMENT,str); break; case USER_PROP_NETMAIL: - putuserrec(p->cfg,p->user.number,U_NETMAIL,LEN_NETMAIL,str); + SAFECOPY(p->user->netmail,str); + putuserrec(p->cfg,p->user->number,U_NETMAIL,LEN_NETMAIL,str); break; case USER_PROP_ADDRESS: - putuserrec(p->cfg,p->user.number,U_ADDRESS,LEN_ADDRESS,str); + SAFECOPY(p->user->address,str); + putuserrec(p->cfg,p->user->number,U_ADDRESS,LEN_ADDRESS,str); break; case USER_PROP_LOCATION: - putuserrec(p->cfg,p->user.number,U_LOCATION,LEN_LOCATION,str); + SAFECOPY(p->user->location,str); + putuserrec(p->cfg,p->user->number,U_LOCATION,LEN_LOCATION,str); break; case USER_PROP_ZIPCODE: - putuserrec(p->cfg,p->user.number,U_ZIPCODE,LEN_ZIPCODE,str); + SAFECOPY(p->user->zipcode,str); + putuserrec(p->cfg,p->user->number,U_ZIPCODE,LEN_ZIPCODE,str); break; case USER_PROP_PHONE: - putuserrec(p->cfg,p->user.number,U_PHONE,LEN_PHONE,str); + SAFECOPY(p->user->phone,str); + putuserrec(p->cfg,p->user->number,U_PHONE,LEN_PHONE,str); break; case USER_PROP_BIRTH: - putuserrec(p->cfg,p->user.number,U_BIRTH,LEN_BIRTH,str); + SAFECOPY(p->user->birth,str); + putuserrec(p->cfg,p->user->number,U_BIRTH,LEN_BIRTH,str); break; case USER_PROP_MODEM: - putuserrec(p->cfg,p->user.number,U_MODEM,LEN_MODEM,str); + SAFECOPY(p->user->modem,str); + putuserrec(p->cfg,p->user->number,U_MODEM,LEN_MODEM,str); break; - case USER_PROP_ROWS: - putuserrec(p->cfg,p->user.number,U_ROWS,0,str); /* base 10 */ + case USER_PROP_ROWS: + p->user->rows=atoi(str); + putuserrec(p->cfg,p->user->number,U_ROWS,0,str); /* base 10 */ break; case USER_PROP_SEX: - putuserrec(p->cfg,p->user.number,U_SEX,0,strupr(str)); /* single char */ + p->user->sex=toupper(str[0]); + putuserrec(p->cfg,p->user->number,U_SEX,0,strupr(str)); /* single char */ break; case USER_PROP_CURSUB: - putuserrec(p->cfg,p->user.number,U_CURSUB,0,strupr(str)); + SAFECOPY(p->user->cursub,str); + putuserrec(p->cfg,p->user->number,U_CURSUB,0,str); break; case USER_PROP_CURDIR: - putuserrec(p->cfg,p->user.number,U_CURDIR,0,strupr(str)); + SAFECOPY(p->user->curdir,str); + putuserrec(p->cfg,p->user->number,U_CURDIR,0,str); break; case USER_PROP_CURXTRN: - putuserrec(p->cfg,p->user.number,U_CURXTRN,0,strupr(str)); + SAFECOPY(p->user->curxtrn,str); + putuserrec(p->cfg,p->user->number,U_CURXTRN,0,str); break; case USER_PROP_XEDIT: - putuserrec(p->cfg,p->user.number,U_XEDIT,0,strupr(str)); + putuserrec(p->cfg,p->user->number,U_XEDIT,0,str); break; case USER_PROP_SHELL: - putuserrec(p->cfg,p->user.number,U_COMP,0,strupr(str)); + putuserrec(p->cfg,p->user->number,U_SHELL,0,str); break; case USER_PROP_MISC: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_MISC,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_MISC,0,ultoa(p->user->misc=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_QWK: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_QWK,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_QWK,0,ultoa(p->user->qwk=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_CHAT: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_CHAT,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_CHAT,0,ultoa(p->user->chat=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_TMPEXT: - putuserrec(p->cfg,p->user.number,U_TMPEXT,0,str); + SAFECOPY(p->user->tmpext,str); + putuserrec(p->cfg,p->user->number,U_TMPEXT,0,str); break; case USER_PROP_NS_TIME: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_NS_TIME,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_NS_TIME,0,ultoa(p->user->ns_time=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_PROT: - putuserrec(p->cfg,p->user.number,U_PROT,0,strupr(str)); /* single char */ + p->user->prot=toupper(str[0]); + putuserrec(p->cfg,p->user->number,U_PROT,0,strupr(str)); /* single char */ break; case USER_PROP_LOGONTIME: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_LOGONTIME,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_LOGONTIME,0,ultoa(p->user->logontime=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; /* security properties*/ case USER_PROP_PASS: - putuserrec(p->cfg,p->user.number,U_PASS,LEN_PASS,strupr(str)); + SAFECOPY(p->user->pass,str); + putuserrec(p->cfg,p->user->number,U_PASS,LEN_PASS,strupr(str)); break; case USER_PROP_PWMOD: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_PWMOD,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_PWMOD,0,ultoa(p->user->pwmod=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_LEVEL: - putuserrec(p->cfg,p->user.number,U_LEVEL,0,str); + p->user->level=atoi(str); + putuserrec(p->cfg,p->user->number,U_LEVEL,0,str); break; case USER_PROP_FLAGS1: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_FLAGS1,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_FLAGS1,0,ultoa(p->user->flags1=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_FLAGS2: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_FLAGS2,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_FLAGS2,0,ultoa(p->user->flags2=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_FLAGS3: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_FLAGS3,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_FLAGS3,0,ultoa(p->user->flags3=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_FLAGS4: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_FLAGS4,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_FLAGS4,0,ultoa(p->user->flags4=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_EXEMPT: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_EXEMPT,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_EXEMPT,0,ultoa(p->user->exempt=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_REST: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_REST,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_REST,0,ultoa(p->user->rest=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_CDT: - putuserrec(p->cfg,p->user.number,U_CDT,0,str); + p->user->cdt=strtoul(str,NULL,0); + putuserrec(p->cfg,p->user->number,U_CDT,0,str); break; case USER_PROP_FREECDT: - putuserrec(p->cfg,p->user.number,U_FREECDT,0,str); + p->user->freecdt=strtoul(str,NULL,0); + putuserrec(p->cfg,p->user->number,U_FREECDT,0,str); break; case USER_PROP_MIN: - putuserrec(p->cfg,p->user.number,U_MIN,0,str); + p->user->min=strtoul(str,NULL,0); + putuserrec(p->cfg,p->user->number,U_MIN,0,str); break; case USER_PROP_TEXTRA: - putuserrec(p->cfg,p->user.number,U_TEXTRA,0,str); + p->user->textra=(ushort)strtoul(str,NULL,0); + putuserrec(p->cfg,p->user->number,U_TEXTRA,0,str); break; case USER_PROP_EXPIRE: + JS_RESUMEREQUEST(cx, rc); if(JS_ValueToInt32(cx,*vp,&val)) - putuserrec(p->cfg,p->user.number,U_EXPIRE,0,ultoa(val,tmp,16)); + putuserrec(p->cfg,p->user->number,U_EXPIRE,0,ultoa(p->user->expire=val,tmp,16)); + rc=JS_SUSPENDREQUEST(cx); break; case USER_PROP_CACHED: JS_ValueToBoolean(cx, *vp, &p->cached); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); /* intentional early return */ } - p->cached=FALSE; - + if(!(p->user->rest&FLAG('G'))) + p->cached=FALSE; + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } @@ -617,6 +687,7 @@ static jsSyncPropertySpec js_user_proper { "download_protocol" ,USER_PROP_PROT ,USER_PROP_FLAGS, 310}, { "logontime" ,USER_PROP_LOGONTIME ,USER_PROP_FLAGS, 310}, { "cached" ,USER_PROP_CACHED ,USER_PROP_FLAGS, 314}, + { "is_sysop" ,USER_PROP_IS_SYSOP ,JSPROP_ENUMERATE|JSPROP_READONLY, 315}, {0} }; @@ -644,11 +715,11 @@ static char* user_prop_desc[] = { ,"AKA connection" ,"terminal rows (lines)" ,"gender type" - ,"current message sub-board" - ,"current file directory" - ,"current external program being run" - ,"external message editor" - ,"command shell" + ,"current/last message sub-board (internal code)" + ,"current/last file directory (internal code)" + ,"current/last external program (internal code) run" + ,"external message editor (internal code) or blank if none" + ,"command shell (internal code)" ,"settings bitfield - see USER_* in sbbsdefs.js for bit definitions" ,"QWK packet settings bitfield - see QWK_* in sbbsdefs.js for bit definitions" ,"chat settings bitfield - see CHAT_* in sbbsdefs.js for bit definitions" @@ -657,6 +728,7 @@ static char* user_prop_desc[] = { ,"file transfer protocol (command key)" ,"logon time (time_t format)" ,"record is currently cached in memory" + ,"user has a System Operator's security level" ,NULL }; #endif @@ -769,8 +841,8 @@ static jsSyncPropertySpec js_user_stats_ #ifdef BUILD_JSDOCS static char* user_stats_prop_desc[] = { - "date of previous logon" - ,"date of first logon" + "date of previous logon (time_t format)" + ,"date of first logon (time_t format)" ,"total number of logons" ,"total logons today" ,"total time used (in minutes)" @@ -812,6 +884,7 @@ js_chk_ar(JSContext *cx, JSObject *obj, uchar* ar; JSString* js_str; private_t* p; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -819,14 +892,16 @@ js_chk_ar(JSContext *cx, JSObject *obj, if((js_str=JS_ValueToString(cx, argv[0]))==NULL) return JS_FALSE; + rc=JS_SUSPENDREQUEST(cx); ar = arstr(NULL,JS_GetStringBytes(js_str),p->cfg); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(chk_ar(p->cfg,ar,&p->user)); + *rval = BOOLEAN_TO_JSVAL(chk_ar(p->cfg,ar,p->user,p->client)); if(ar!=NULL && ar!=nular) free(ar); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -836,6 +911,7 @@ js_posted_msg(JSContext *cx, JSObject *o { private_t* p; int32 count=1; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -843,9 +919,11 @@ js_posted_msg(JSContext *cx, JSObject *o if(argc) JS_ValueToInt32(cx, argv[0], &count); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_posted_msg(p->cfg, &p->user, count)); + *rval = BOOLEAN_TO_JSVAL(user_posted_msg(p->cfg, p->user, count)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -856,6 +934,7 @@ js_sent_email(JSContext *cx, JSObject *o private_t* p; int32 count=1; BOOL feedback=FALSE; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -865,9 +944,11 @@ js_sent_email(JSContext *cx, JSObject *o if(argc>1) JS_ValueToBoolean(cx, argv[1], &feedback); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_sent_email(p->cfg, &p->user, count, feedback)); + *rval = BOOLEAN_TO_JSVAL(user_sent_email(p->cfg, p->user, count, feedback)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -878,6 +959,7 @@ js_downloaded_file(JSContext *cx, JSObje private_t* p; int32 files=1; int32 bytes=0; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -887,9 +969,11 @@ js_downloaded_file(JSContext *cx, JSObje if(argc>1) JS_ValueToInt32(cx, argv[1], &files); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_downloaded(p->cfg, &p->user, files, bytes)); + *rval = BOOLEAN_TO_JSVAL(user_downloaded(p->cfg, p->user, files, bytes)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -900,6 +984,7 @@ js_uploaded_file(JSContext *cx, JSObject private_t* p; int32 files=1; int32 bytes=0; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -909,9 +994,11 @@ js_uploaded_file(JSContext *cx, JSObject if(argc>1) JS_ValueToInt32(cx, argv[1], &files); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_uploaded(p->cfg, &p->user, files, bytes)); + *rval = BOOLEAN_TO_JSVAL(user_uploaded(p->cfg, p->user, files, bytes)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -921,6 +1008,7 @@ js_adjust_credits(JSContext *cx, JSObjec { private_t* p; int32 count=0; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -928,9 +1016,11 @@ js_adjust_credits(JSContext *cx, JSObjec if(argc) JS_ValueToInt32(cx, argv[0], &count); + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_adjust_credits(p->cfg, &p->user, count)); + *rval = BOOLEAN_TO_JSVAL(user_adjust_credits(p->cfg, p->user, count)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } @@ -940,6 +1030,7 @@ js_adjust_minutes(JSContext *cx, JSObjec { private_t* p; int32 count=0; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) return JS_FALSE; @@ -947,13 +1038,38 @@ js_adjust_minutes(JSContext *cx, JSObjec if(argc) JS_ValueToInt32(cx, argv[0], &count); + rc=JS_SUSPENDREQUEST(cx); + js_getuserdat(p); + + *rval = BOOLEAN_TO_JSVAL(user_adjust_minutes(p->cfg, p->user, count)); + JS_RESUMEREQUEST(cx, rc); + + return JS_TRUE; +} + +static JSBool +js_get_time_left(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + private_t* p; + int32 start_time=0; + jsrefcount rc; + + if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) + return JS_FALSE; + + if(argc) + JS_ValueToInt32(cx, argv[0], &start_time); + + rc=JS_SUSPENDREQUEST(cx); js_getuserdat(p); - *rval = BOOLEAN_TO_JSVAL(user_adjust_minutes(p->cfg, &p->user, count)); + *rval = INT_TO_JSVAL(gettimeleft(p->cfg, p->user, (time_t)start_time)); + JS_RESUMEREQUEST(cx, rc); return JS_TRUE; } + static jsSyncMethodSpec js_user_functions[] = { {"compare_ars", js_chk_ar, 1, JSTYPE_BOOLEAN, JSDOCSTR("string ars") ,JSDOCSTR("Verify user meets access requirements string") @@ -982,22 +1098,60 @@ static jsSyncMethodSpec js_user_function {"downloaded_file", js_downloaded_file, 1, JSTYPE_BOOLEAN, JSDOCSTR("[bytes] [,files]") ,JSDOCSTR("Adjust user's files/bytes-downloaded statistics") ,314 - }, + }, + {"get_time_left", js_get_time_left, 1, JSTYPE_NUMBER, JSDOCSTR("start_time") + ,JSDOCSTR("Returns the user's available remaining time online, in seconds,
" + "based on the passed start_time value (in time_t format)
" + "Note: this method does not account for pending forced timed events") + ,31401 + }, {0} }; -static JSClass js_user_class = { - "User" /* name */ - ,JSCLASS_HAS_PRIVATE /* flags */ - ,JS_PropertyStub /* addProperty */ - ,JS_PropertyStub /* delProperty */ - ,js_user_get /* getProperty */ - ,js_user_set /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ - ,JS_ConvertStub /* convert */ - ,js_user_finalize /* finalize */ -}; +static JSBool js_user_stats_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char* name=NULL; + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + return(js_SyncResolve(cx, obj, name, js_user_stats_properties, NULL, NULL, 0)); +} + +static JSBool js_user_stats_enumerate(JSContext *cx, JSObject *obj) +{ + return(js_user_stats_resolve(cx, obj, JSVAL_NULL)); +} + +static JSBool js_user_security_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char* name=NULL; + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + return(js_SyncResolve(cx, obj, name, js_user_security_properties, NULL, NULL, 0)); +} + +static JSBool js_user_security_enumerate(JSContext *cx, JSObject *obj) +{ + return(js_user_security_resolve(cx, obj, JSVAL_NULL)); +} + +static JSBool js_user_limits_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char* name=NULL; + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + return(js_SyncResolve(cx, obj, name, js_user_limits_properties, NULL, NULL, 0)); +} + +static JSBool js_user_limits_enumerate(JSContext *cx, JSObject *obj) +{ + return(js_user_limits_resolve(cx, obj, JSVAL_NULL)); +} static JSClass js_user_stats_class = { "UserStats" /* name */ @@ -1006,8 +1160,8 @@ static JSClass js_user_stats_class = { ,JS_PropertyStub /* delProperty */ ,js_user_get /* getProperty */ ,js_user_set /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ + ,js_user_stats_enumerate /* enumerate */ + ,js_user_stats_resolve /* resolve */ ,JS_ConvertStub /* convert */ ,JS_FinalizeStub /* finalize */ }; @@ -1019,8 +1173,8 @@ static JSClass js_user_security_class = ,JS_PropertyStub /* delProperty */ ,js_user_get /* getProperty */ ,js_user_set /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ + ,js_user_security_enumerate /* enumerate */ + ,js_user_security_resolve /* resolve */ ,JS_ConvertStub /* convert */ ,JS_FinalizeStub /* finalize */ }; @@ -1032,12 +1186,88 @@ static JSClass js_user_limits_class = { ,JS_PropertyStub /* delProperty */ ,js_user_get /* getProperty */ ,js_user_set /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ + ,js_user_limits_enumerate /* enumerate */ + ,js_user_limits_resolve /* resolve */ ,JS_ConvertStub /* convert */ ,JS_FinalizeStub /* finalize */ }; +static JSBool js_user_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char* name=NULL; + JSObject* newobj; + private_t* p; + + if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_TRUE); + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + if(name==NULL || strcmp(name, "stats")==0) { + /* user.stats */ + if((newobj=JS_DefineObject(cx, obj, "stats" + ,&js_user_stats_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) + return(JS_FALSE); + JS_SetPrivate(cx, newobj, p); +#ifdef BUILD_JSDOCS + js_DescribeSyncObject(cx,newobj,"User statistics (all READ ONLY)",310); + js_CreateArrayOfStrings(cx, newobj, "_property_desc_list", user_stats_prop_desc, JSPROP_READONLY); +#endif + if(name) + return(JS_TRUE); + + } + + if(name==NULL || strcmp(name, "security")==0) { + /* user.security */ + if((newobj=JS_DefineObject(cx, obj, "security" + ,&js_user_security_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) + return(JS_FALSE); + JS_SetPrivate(cx, newobj, p); +#ifdef BUILD_JSDOCS + js_DescribeSyncObject(cx,newobj,"User limitations based on security level (all READ ONLY)",311); + js_CreateArrayOfStrings(cx, newobj, "_property_desc_list", user_limits_prop_desc, JSPROP_READONLY); +#endif + if(name) + return(JS_TRUE); + } + + if(name==NULL || strcmp(name, "limits")==0) { + /* user.limits */ + if((newobj=JS_DefineObject(cx, obj, "limits" + ,&js_user_limits_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) + return(JS_FALSE); + JS_SetPrivate(cx, newobj, p); +#ifdef BUILD_JSDOCS + js_DescribeSyncObject(cx,newobj,"User security settings",310); + js_CreateArrayOfStrings(cx, newobj, "_property_desc_list", user_security_prop_desc, JSPROP_READONLY); +#endif + if(name) + return(JS_TRUE); + } + + return(js_SyncResolve(cx, obj, name, js_user_properties, js_user_functions, NULL, 0)); +} + +static JSBool js_user_enumerate(JSContext *cx, JSObject *obj) +{ + return(js_user_resolve(cx, obj, JSVAL_NULL)); +} + +static JSClass js_user_class = { + "User" /* name */ + ,JSCLASS_HAS_PRIVATE /* flags */ + ,JS_PropertyStub /* addProperty */ + ,JS_PropertyStub /* delProperty */ + ,js_user_get /* getProperty */ + ,js_user_set /* setProperty */ + ,js_user_enumerate /* enumerate */ + ,js_user_resolve /* resolve */ + ,JS_ConvertStub /* convert */ + ,js_user_finalize /* finalize */ +}; + /* User Constructor (creates instance of user class) */ static JSBool @@ -1047,9 +1277,6 @@ js_user_constructor(JSContext *cx, JSObj int32 val=0; user_t user; private_t* p; - JSObject* statsobj; - JSObject* securityobj; - JSObject* limitsobj; JS_ValueToInt32(cx,argv[0],&val); user.number=(ushort)val; @@ -1058,52 +1285,17 @@ js_user_constructor(JSContext *cx, JSObj return(JS_FALSE); } - /* user.stats */ - if((statsobj=JS_DefineObject(cx, obj, "stats" - ,&js_user_stats_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) - return(JS_FALSE); - - if(!js_DefineSyncProperties(cx, statsobj, js_user_stats_properties)) - return(JS_FALSE); - - /* user.security */ - if((securityobj=JS_DefineObject(cx, obj, "security" - ,&js_user_security_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) - return(JS_FALSE); - - if(!js_DefineSyncProperties(cx, securityobj, js_user_security_properties)) - return(JS_FALSE); - - /* user.limits */ - if((limitsobj=JS_DefineObject(cx, obj, "limits" - ,&js_user_limits_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) - return(JS_FALSE); - - if(!js_DefineSyncProperties(cx, limitsobj, js_user_limits_properties)) - return(JS_FALSE); - - /* other user properties */ - if(!js_DefineSyncProperties(cx, obj, js_user_properties)) - return(JS_FALSE); - if((p=(private_t*)malloc(sizeof(private_t)))==NULL) return(JS_FALSE); + memset(p,0,sizeof(private_t)); + p->cfg = scfg; - p->user = user; + p->storage = user; + p->user = &p->storage; p->cached = (user.number==0 ? FALSE : TRUE); - JS_SetPrivate(cx, obj, p); /* Must do this before calling js_DefineSyncMethods() */ - - if(!js_DefineSyncMethods(cx, obj, js_user_functions, FALSE)) { - JS_SetPrivate(cx, obj, NULL); - free(p); - return(JS_FALSE); - } - - JS_SetPrivate(cx, statsobj, p); - JS_SetPrivate(cx, securityobj, p); - JS_SetPrivate(cx, limitsobj, p); + JS_SetPrivate(cx, obj, p); return(JS_TRUE); } @@ -1125,12 +1317,9 @@ JSObject* DLLCALL js_CreateUserClass(JSC } JSObject* DLLCALL js_CreateUserObject(JSContext* cx, JSObject* parent, scfg_t* cfg, char* name - , uint usernumber) + ,user_t* user, client_t* client, BOOL global_user) { JSObject* userobj; - JSObject* statsobj; - JSObject* limitsobj; - JSObject* securityobj; private_t* p; jsval val; @@ -1148,17 +1337,20 @@ JSObject* DLLCALL js_CreateUserObject(JS if((p=(private_t*)malloc(sizeof(private_t)))==NULL) return(NULL); + memset(p,0,sizeof(private_t)); + p->cfg = cfg; - p->user.number = usernumber; + p->client = client; p->cached = FALSE; + p->user = &p->storage; + if(user!=NULL) { + p->storage = *user; + if(global_user) + p->user = user; + } JS_SetPrivate(cx, userobj, p); - if(!js_DefineSyncProperties(cx, userobj, js_user_properties)) { - free(p); - return(NULL); - } - #ifdef BUILD_JSDOCS js_DescribeSyncObject(cx,userobj ,"Instance of User class, representing current user online" @@ -1169,72 +1361,6 @@ JSObject* DLLCALL js_CreateUserObject(JS ,"_property_desc_list", user_prop_desc, JSPROP_READONLY); #endif - js_DefineSyncMethods(cx, userobj, js_user_functions, FALSE); - - /* user.stats */ - statsobj = JS_DefineObject(cx, userobj, "stats" - ,&js_user_stats_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY); - - if(statsobj==NULL) { - free(p); - return(NULL); - } - - JS_SetPrivate(cx, statsobj, p); - - if(!js_DefineSyncProperties(cx, statsobj, js_user_stats_properties)) { - free(p); - return(NULL); - } - -#ifdef BUILD_JSDOCS - js_DescribeSyncObject(cx,statsobj,"User statistics (all READ ONLY)",310); - js_CreateArrayOfStrings(cx, statsobj, "_property_desc_list", user_stats_prop_desc, JSPROP_READONLY); -#endif - - /* user.limits */ - limitsobj = JS_DefineObject(cx, userobj, "limits" - ,&js_user_limits_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY); - - if(limitsobj==NULL) { - free(p); - return(NULL); - } - - JS_SetPrivate(cx, limitsobj, p); - - if(!js_DefineSyncProperties(cx, limitsobj, js_user_limits_properties)) { - free(p); - return(NULL); - } - -#ifdef BUILD_JSDOCS - js_DescribeSyncObject(cx,limitsobj,"User limitations based on security level (all READ ONLY)",311); - js_CreateArrayOfStrings(cx, limitsobj, "_property_desc_list", user_limits_prop_desc, JSPROP_READONLY); -#endif - - - /* user.security */ - securityobj = JS_DefineObject(cx, userobj, "security" - ,&js_user_security_class, NULL, JSPROP_ENUMERATE|JSPROP_READONLY); - - if(securityobj==NULL) { - free(p); - return(NULL); - } - - JS_SetPrivate(cx, securityobj, p); - - if(!js_DefineSyncProperties(cx, securityobj, js_user_security_properties)) { - free(p); - return(NULL); - } - -#ifdef BUILD_JSDOCS - js_DescribeSyncObject(cx,securityobj,"User security settings",310); - js_CreateArrayOfStrings(cx, securityobj, "_property_desc_list", user_security_prop_desc, JSPROP_READONLY); -#endif - return(userobj); } @@ -1242,16 +1368,16 @@ JSObject* DLLCALL js_CreateUserObject(JS /* Creates all the user-specific objects: user, msg_area, file_area */ /****************************************************************************/ JSBool DLLCALL -js_CreateUserObjects(JSContext* cx, JSObject* parent, scfg_t* cfg, user_t* user +js_CreateUserObjects(JSContext* cx, JSObject* parent, scfg_t* cfg, user_t* user, client_t* client ,char* html_index_file, subscan_t* subscan) { - if(js_CreateUserObject(cx,parent,cfg,"user",user==NULL ? 0 : user->number)==NULL) + if(js_CreateUserObject(cx,parent,cfg,"user",user,client,/* global_user */TRUE)==NULL) return(JS_FALSE); - if(js_CreateFileAreaObject(cx,parent,cfg,user,html_index_file)==NULL) + if(js_CreateFileAreaObject(cx,parent,cfg,user,client,html_index_file)==NULL) return(JS_FALSE); - if(js_CreateMsgAreaObject(cx,parent,cfg,user,subscan)==NULL) + if(js_CreateMsgAreaObject(cx,parent,cfg,user,client,subscan)==NULL) return(JS_FALSE); - if(js_CreateXtrnAreaObject(cx,parent,cfg,user)==NULL) + if(js_CreateXtrnAreaObject(cx,parent,cfg,user,client)==NULL) return(JS_FALSE); return(JS_TRUE);