diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index 754365661f8ea52c5edd61bc2b445a986f020973..59b7aeac8ac6a8728000035d15f3b1df27eeb8a9 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -503,7 +503,7 @@ js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp) do { lprintf(LOG_DEBUG,"%04d JavaScript: Initializing Global object",sock); - if((js_glob=js_CreateGlobalObject(js_cx, &scfg, NULL))==NULL) + if((js_glob=js_CreateGlobalObject(js_cx, &scfg, NULL, &startup->js))==NULL) break; if (!JS_DefineFunctions(js_cx, js_glob, js_global_functions)) diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c index fc2f4ce35ac571a8d0ec29d75a78134d7e80ae7c..3768fba127b58b14caa05adc31ab92319d9e4a68 100644 --- a/src/sbbs3/js_global.c +++ b/src/sbbs3/js_global.c @@ -55,8 +55,9 @@ #ifdef JAVASCRIPT typedef struct { - scfg_t *cfg; - jsSyncMethodSpec *methods; + scfg_t* cfg; + jsSyncMethodSpec* methods; + js_startup_t* startup; } private_t; /* Global Object Properites */ @@ -253,11 +254,13 @@ js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) bg->parent_cx = cx; /* Setup default values for branch settings */ - bg->branch.limit=JAVASCRIPT_BRANCH_LIMIT; - bg->branch.gc_interval=JAVASCRIPT_GC_INTERVAL; - bg->branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL; + bg->branch.limit=p->startup->branch_limit; + bg->branch.gc_interval=p->startup->gc_interval; + bg->branch.yield_interval=p->startup->yield_interval; +#if 0 if(JS_GetProperty(cx, obj,"js",&val)) /* copy branch settings from parent */ memcpy(&bg->branch,JS_GetPrivate(cx,JSVAL_TO_OBJECT(val)),sizeof(bg->branch)); +#endif bg->branch.terminated=NULL; /* could be bad pointer at any time */ bg->branch.counter=0; bg->branch.gc_attempts=0; @@ -277,6 +280,7 @@ js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ,"" /* hostname */ ,"" /* socklib_desc */ ,&bg->branch /* js */ + ,p->startup /* js */ ,NULL /* client */ ,INVALID_SOCKET /* client_socket */ ,NULL /* server props */ @@ -340,11 +344,45 @@ js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) rc=JS_SUSPENDREQUEST(cx); errno = 0; if(isfullpath(filename)) - strcpy(path,filename); + SAFECOPY(path,filename); else { - sprintf(path,"%s%s",p->cfg->mods_dir,filename); - if(p->cfg->mods_dir[0]==0 || !fexistcase(path)) - sprintf(path,"%s%s",p->cfg->exec_dir,filename); + path[0]=0; + if(JS_GetProperty(cx, obj, "js", &val)) { + JSObject* js = JSVAL_TO_OBJECT(val); + if(JS_GetProperty(cx, js, JAVASCRIPT_LOAD_PATH_LIST, &val) && JSVAL_IS_OBJECT(val)) { + JSObject* list = JSVAL_TO_OBJECT(val); + jsuint i; + char prefix[MAX_PATH+1]; + for(i=0;path[0]==0;i++) { + if(!JS_GetElement(cx, list, i, &val) || val==JSVAL_VOID) + break; + if(!JSVAL_IS_STRING(val)) + continue; + SAFECOPY(prefix,js_ValueToStringBytes(cx, val, NULL)); + if(prefix[0]==0) + continue; + backslash(prefix); + if(isfullpath(prefix)) { + SAFEPRINTF2(path,"%s%s",prefix,filename); + if(!fexistcase(path)) + path[0]=0; + } else { + /* relative path */ + SAFEPRINTF3(path,"%s%s%s",p->cfg->mods_dir,prefix,filename); + if(p->cfg->mods_dir[0]==0 || !fexistcase(path)) { + SAFEPRINTF3(path,"%s%s%s",p->cfg->exec_dir,prefix,filename); + if(!fexistcase(path)) + path[0]=0; + } + } + } + } + } + if(path[0]==0) { + SAFEPRINTF2(path,"%s%s",p->cfg->mods_dir,filename); + if(p->cfg->mods_dir[0]==0 || !fexistcase(path)) + SAFEPRINTF2(path,"%s%s",p->cfg->exec_dir,filename); + } } JS_RESUMEREQUEST(cx, rc); @@ -3433,7 +3471,7 @@ static JSClass js_global_class = { ,js_global_finalize /* finalize */ }; -JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods) +JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t* startup) { JSObject* glob; private_t* p; @@ -3443,6 +3481,7 @@ JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethod p->cfg = cfg; p->methods = methods; + p->startup = startup; if((glob = JS_NewObject(cx, &js_global_class, NULL, NULL)) ==NULL) return(NULL); @@ -3469,6 +3508,7 @@ JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx ,char* host_name /* system */ ,char* socklib_desc /* system */ ,js_branch_t* branch /* js */ + ,js_startup_t* js_startup /* js */ ,client_t* client /* client */ ,SOCKET client_socket /* client */ ,js_server_props_t* props /* server */ @@ -3480,7 +3520,7 @@ JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx node_cfg=cfg; /* Global Object */ - if((js_glob=js_CreateGlobalObject(js_cx, cfg, methods))==NULL) + if((js_glob=js_CreateGlobalObject(js_cx, cfg, methods, js_startup))==NULL) return(NULL); /* System Object */ @@ -3489,7 +3529,7 @@ JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx /* Internal JS Object */ if(branch!=NULL - && js_CreateInternalJsObject(js_cx, js_glob, branch)==NULL) + && js_CreateInternalJsObject(js_cx, js_glob, branch, js_startup)==NULL) return(NULL); /* Client Object */ diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c index 510d42d143d8971c28767681e4d9fcdd0a9138b2..160ac41065885725c8a1831909422f77aa71b963 100644 --- a/src/sbbs3/js_internal.c +++ b/src/sbbs3/js_internal.c @@ -441,7 +441,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_branch_t* branch) branch->auto_terminate = auto_terminate; } -JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_branch_t* branch) +JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_branch_t* branch, js_startup_t* startup) { JSObject* obj; @@ -452,6 +452,30 @@ JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_ if(!JS_SetPrivate(cx, obj, branch)) /* Store a pointer to js_branch_t */ return(NULL); + if(startup!=NULL) { + JSObject* load_path_list; + jsval val; + + if((load_path_list=JS_NewArrayObject(cx, 0, NULL))==NULL) + return(NULL); + val=OBJECT_TO_JSVAL(load_path_list); + if(!JS_SetProperty(cx, obj, JAVASCRIPT_LOAD_PATH_LIST, &val)) + return(NULL); + + if(startup->load_path!=NULL) { + JSString* js_str; + unsigned i; + + for(i=0; startup->load_path[i]!=NULL; i++) { + if((js_str=JS_NewStringCopyZ(cx, startup->load_path[i]))==NULL) + return(NULL); + val=STRING_TO_JSVAL(js_str); + if(!JS_SetElement(cx, load_path_list, i, &val)) + return(NULL); + } + } + } + #ifdef BUILD_JSDOCS js_DescribeSyncObject(cx,obj,"JavaScript execution and garbage collection control object",311); js_CreateArrayOfStrings(cx, obj, "_property_desc_list", prop_desc, JSPROP_READONLY); diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c index ed90e1cba00f1605be57f6ab787dc4da3c668a9b..5d5c7bcbfa4aabab7f5b0a3519cdba2defbe1bfd 100644 --- a/src/sbbs3/jsexec.c +++ b/src/sbbs3/jsexec.c @@ -67,6 +67,7 @@ char revision[16]; char compiler[32]; char* host_name=NULL; char host_name_buf[128]; +char* load_path_list=JAVASCRIPT_LOAD_PATH; BOOL pause_on_exit=FALSE; BOOL pause_on_error=FALSE; BOOL terminated=FALSE; @@ -116,6 +117,7 @@ void usage(FILE* fp) "\t-u<mask> set file creation permissions mask (in octal)\n" "\t-L<level> set log level (default=%u)\n" "\t-E<level> set error log level threshold (default=%d)\n" + "\t-i<path_list> set load() comma-sep search path list (default=\"%s\")\n" "\t-f use non-buffered stream for console messages\n" "\t-a append instead of overwriting message output files\n" "\t-e<filename> send error messages to file in addition to stderr\n" @@ -135,6 +137,7 @@ void usage(FILE* fp) ,JAVASCRIPT_GC_INTERVAL ,DEFAULT_LOG_LEVEL ,DEFAULT_ERR_LOG_LVL + ,load_path_list ,_PATH_DEVNULL ,_PATH_DEVNULL ); @@ -612,6 +615,11 @@ static BOOL js_CreateEnvObject(JSContext* cx, JSObject* glob, char** env) static BOOL js_init(char** environ) { + js_startup_t startup; + + memset(&startup,0,sizeof(startup)); + startup.load_path=strListSplit(NULL, load_path_list, ","); + fprintf(statfp,"%s\n",(char *)JS_GetImplementationVersion()); fprintf(statfp,"JavaScript: Creating runtime: %lu bytes\n" @@ -636,7 +644,7 @@ static BOOL js_init(char** environ) /* Global Object */ if((js_glob=js_CreateCommonObjects(js_cx, &scfg, NULL, js_global_functions ,time(NULL), host_name, SOCKLIB_DESC /* system */ - ,&branch /* js */ + ,&branch,&startup /* js */ ,NULL,INVALID_SOCKET /* client */ ,NULL /* server */ ))==NULL) { @@ -970,6 +978,10 @@ int main(int argc, char **argv, char** environ) if(*p==0) p=argv[++argn]; SAFECOPY(scfg.ctrl_dir,p); break; + case 'i': + if(*p==0) p=argv[++argn]; + load_path_list=p; + break; case 'v': banner(statfp); fprintf(statfp,"%s\n",(char *)JS_GetImplementationVersion()); diff --git a/src/sbbs3/mailsrvr.h b/src/sbbs3/mailsrvr.h index c34a3c735447453983313c1cf82b8b400d334883..7a3c6adba365466a982db4d8b068887e79cf84e7 100644 --- a/src/sbbs3/mailsrvr.h +++ b/src/sbbs3/mailsrvr.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 2008 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2009 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 * @@ -138,7 +138,7 @@ static struct init_field mail_init_fields[] = { #define MAIL_OPT_DNSBL_BADUSER (1<<17) /* Refuse mail (bad user name) */ #define MAIL_OPT_DNSBL_CHKRECVHDRS (1<<18) /* Check all Recieved: from addresses */ #define MAIL_OPT_DNSBL_THROTTLE (1<<19) /* Throttle receive from blacklisted servers */ -#define MAIL_OPT_DNSBL_DEBUG (1<<20) /* Debug DNSBL activity */ +#define MAIL_OPT_DNSBL_SPAMHASH (1<<20) /* Store hashes of ignored or tagged messages in spam.hash */ #define MAIL_OPT_SMTP_AUTH_VIA_IP (1<<21) /* Allow SMTP authentication via IP */ #define MAIL_OPT_SEND_INTRANSIT (1<<22) /* Send mail, even if already "in transit" */ #define MAIL_OPT_RELAY_AUTH_PLAIN (1<<23) @@ -177,7 +177,7 @@ static ini_bitdesc_t mail_options[] = { { MAIL_OPT_DNSBL_BADUSER ,"DNSBL_BADUSER" }, { MAIL_OPT_DNSBL_CHKRECVHDRS ,"DNSBL_CHKRECVHDRS" }, { MAIL_OPT_DNSBL_THROTTLE ,"DNSBL_THROTTLE" }, - { MAIL_OPT_DNSBL_DEBUG ,"DNSBL_DEBUG" }, + { MAIL_OPT_DNSBL_SPAMHASH ,"DNSBL_SPAMHASH" }, { MAIL_OPT_SEND_INTRANSIT ,"SEND_INTRANSIT" }, { MAIL_OPT_RELAY_AUTH_PLAIN ,"RELAY_AUTH_PLAIN" }, { MAIL_OPT_RELAY_AUTH_LOGIN ,"RELAY_AUTH_LOGIN" }, diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index bfac9ffcd069d9f4a9ea8942185d01db5514d227..af3836226506aca51206a93d45ba5813af50aec4 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -1066,6 +1066,7 @@ bool sbbs_t::js_init(ulong* stack_frame) if((js_glob=js_CreateCommonObjects(js_cx, &scfg, &cfg, js_global_functions ,uptime, startup->host_name, SOCKLIB_DESC /* system */ ,&js_branch /* js */ + ,&startup->js ,&client, client_socket /* client */ ,&js_server_props /* server */ ))==NULL) diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index dddba8f81c531ed5e343f0fbfa4c2b65f948f32e..0007b9b97f0db91f84b531732b377b12f2703bb8 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -119,8 +119,8 @@ extern int thread_suid_broken; /* NPTL is no longer broken */ /***********************/ /* Synchronet-specific */ /***********************/ +#include "startup.h" #ifdef __cplusplus - #include "startup.h" #include "threadwrap.h" /* pthread_mutex_t */ #endif @@ -1001,7 +1001,7 @@ extern "C" { ,js_server_props_t* props); /* js_global.c */ - DLLEXPORT JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods); + DLLEXPORT JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*); DLLEXPORT JSObject* DLLCALL js_CreateCommonObjects(JSContext* cx ,scfg_t* cfg /* common */ ,scfg_t* node_cfg /* node-specific */ @@ -1009,14 +1009,15 @@ extern "C" { ,time_t uptime /* system */ ,char* host_name /* system */ ,char* socklib_desc /* system */ - ,js_branch_t* js_branch /* js */ + ,js_branch_t* /* js */ + ,js_startup_t* /* js */ ,client_t* client /* client */ ,SOCKET client_socket /* client */ ,js_server_props_t* props /* server */ ); /* js_internal.c */ - DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_branch_t* branch); + DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_branch_t*, js_startup_t*); DLLEXPORT JSBool DLLCALL js_CommonBranchCallback(JSContext*, js_branch_t*); DLLEXPORT void DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_branch_t*); diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c index c48d54f159e10a433b58ad3b6a5eeaf9c5a002f5..3841fc27f1ad38ccc7306301ecc17867d30a2199 100644 --- a/src/sbbs3/sbbs_ini.c +++ b/src/sbbs3/sbbs_ini.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 2008 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2009 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 * @@ -65,6 +65,7 @@ static const char* strJavaScriptThreadStack ="JavaScriptThreadStack"; static const char* strJavaScriptBranchLimit ="JavaScriptBranchLimit"; static const char* strJavaScriptGcInterval ="JavaScriptGcInterval"; static const char* strJavaScriptYieldInterval ="JavaScriptYieldInterval"; +static const char* strJavaScriptLoadPath ="JavaScriptLoadPath"; static const char* strSemFileCheckFrequency ="SemFileCheckFrequency"; #define DEFAULT_LOG_LEVEL LOG_DEBUG @@ -125,6 +126,8 @@ void sbbs_get_js_settings( ,js_startup_t* js ,js_startup_t* defaults) { + str_list_t load_path; + js->max_bytes = iniGetInteger(list,section,strJavaScriptMaxBytes ,defaults->max_bytes); js->cx_stack = iniGetInteger(list,section,strJavaScriptContextStack ,defaults->cx_stack); js->thread_stack = iniGetInteger(list,section,strJavaScriptThreadStack ,defaults->thread_stack); @@ -132,6 +135,11 @@ void sbbs_get_js_settings( js->gc_interval = iniGetInteger(list,section,strJavaScriptGcInterval ,defaults->gc_interval); js->yield_interval = iniGetInteger(list,section,strJavaScriptYieldInterval ,defaults->yield_interval); + iniFreeStringList(js->load_path); + if((load_path = iniGetStringList(list, section,strJavaScriptLoadPath,",",NULL)) == NULL) + load_path = defaults->load_path; + js->load_path = load_path; + sbbs_fix_js_settings(js); } @@ -229,6 +237,7 @@ static void get_ini_globals(str_list_t list, global_startup_t* global) global->js.branch_limit = JAVASCRIPT_BRANCH_LIMIT; global->js.gc_interval = JAVASCRIPT_GC_INTERVAL; global->js.yield_interval = JAVASCRIPT_YIELD_INTERVAL; + global->js.load_path = strListSplit(NULL, JAVASCRIPT_LOAD_PATH, ","); /* Read .ini values here */ sbbs_get_js_settings(list, section, &global->js, &global->js); diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h index e02e2bcdac8b7ed8c41df9f6bd7e61b55bb88d8f..62a79ca5e1c276a43f50fe80690f3f25283dd230 100644 --- a/src/sbbs3/sbbsdefs.h +++ b/src/sbbs3/sbbsdefs.h @@ -76,6 +76,8 @@ #define JAVASCRIPT_BRANCH_LIMIT 99999999 #define JAVASCRIPT_YIELD_INTERVAL 10000 #define JAVASCRIPT_GC_INTERVAL 100 +#define JAVASCRIPT_LOAD_PATH "load" +#define JAVASCRIPT_LOAD_PATH_LIST "load_path_list" typedef struct { ulong counter; @@ -391,6 +393,7 @@ typedef enum { /* Values for xtrn_t.event */ #define XTRN_SH (1<<18) /* Use command shell to execute */ #define XTRN_PAUSE (1<<19) /* Force a screen pause on exit */ #define XTRN_NOECHO (1<<20) /* Don't echo stdin to stdout */ +#define QUOTEWRAP (1<<21) /* Word-wrap the quoted text */ /* Bits in cfg.xtrn_misc */ #define XTRN_NO_MUTEX (1<<0) /* Do not use exec_mutex for FOSSIL VXD */ diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index 7f687191180d5b109e639bd02b5655031bc5dd59..9e4813f284e4b72a2ada68e91ba81841b9b8ddc8 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -846,14 +846,14 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, JS_SetContextPrivate(js_cx, service_client); - if((js_glob=js_CreateGlobalObject(js_cx, &scfg, NULL))==NULL) + if((js_glob=js_CreateGlobalObject(js_cx, &scfg, NULL, &service_client->service->js))==NULL) break; if (!JS_DefineFunctions(js_cx, js_glob, js_global_functions)) break; /* Internal JS Object */ - if(js_CreateInternalJsObject(js_cx, js_glob, &service_client->branch)==NULL) + if(js_CreateInternalJsObject(js_cx, js_glob, &service_client->branch, &service_client->service->js)==NULL) break; /* Client Object */ diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h index ee618972c99116df8300bc2a9b93065ae6e33a94..a191e1764caf577d8d646e0c92cd41a8f34eeb76 100644 --- a/src/sbbs3/startup.h +++ b/src/sbbs3/startup.h @@ -52,6 +52,7 @@ typedef struct { ulong branch_limit; /* maximum number of branches (for infinite loop detection) */ ulong gc_interval; /* number of branches between garbage collection attempts */ ulong yield_interval; /* number of branches between time-slice yields */ + str_list_t load_path; /* additional directories to search for load()ed scripts */ } js_startup_t; typedef struct { diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c index d6ec9ada14d93f7a4a602b43975e096b5956b606..88f762e232dbd50073963c451adde86f568df7e3 100644 --- a/src/sbbs3/websrvr.c +++ b/src/sbbs3/websrvr.c @@ -3663,7 +3663,7 @@ static BOOL exec_cgi(http_session_t *session) /* Check socket for received POST Data */ if(!socket_check(session->socket, &rd, NULL, /* timeout: */0)) { - lprintf(LOG_WARNING,"%04d CGI Socket disconected", session->socket); + lprintf(LOG_WARNING,"%04d CGI Socket disconnected", session->socket); break; } if(rd) { @@ -4452,6 +4452,7 @@ js_initcx(http_session_t *session) ,startup->host_name /* system */ ,SOCKLIB_DESC /* system */ ,&session->js_branch /* js */ + ,&startup->js /* js */ ,&session->client /* client */ ,session->socket /* client */ ,&js_server_props /* server */