diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c index 14463dec16524838dcf7684b3be86131eca5fb89..20113bf7817c4c4ccc40a95591b7b070e969d46b 100644 --- a/src/sbbs3/websrvr.c +++ b/src/sbbs3/websrvr.c @@ -262,6 +262,7 @@ typedef struct { time_t logon_time; char username[LEN_NAME+1]; int last_js_user_num; + char redir_req[MAX_REQUEST_LINE+1]; /* JavaScript parameters */ JSRuntime* js_runtime; @@ -399,6 +400,7 @@ static char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; static char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; static void respond(http_session_t * session); +static BOOL js_setup_cx(http_session_t* session); static BOOL js_setup(http_session_t* session); static char *find_last_slash(char *str); static BOOL check_extra_path(http_session_t * session); @@ -2258,6 +2260,20 @@ static void js_add_cookieval(http_session_t * session, char *key, char *value) JS_SetElement(session->js_cx, keyarray, alen, &val); } +static void js_add_request_prop_writeable(http_session_t * session, char *key, char *value) +{ + JSString* js_str; + + if(session->js_cx==NULL || session->js_request==NULL) + return; + if(key==NULL || value==NULL) + return; + if((js_str=JS_NewStringCopyZ(session->js_cx, value))==NULL) + return; + JS_DefineProperty(session->js_cx, session->js_request, key, STRING_TO_JSVAL(js_str) + ,NULL,NULL,JSPROP_ENUMERATE); +} + static void js_add_request_prop(http_session_t * session, char *key, char *value) { JSString* js_str; @@ -3197,9 +3213,80 @@ static BOOL check_extra_path(http_session_t * session) return(FALSE); } +static BOOL exec_js_rewrite(http_session_t* session, char* script) { + jsval rval; + jsval val; + BOOL retval=TRUE; + char redir_req[MAX_REQUEST_LINE+1]; + + if(!js_setup_cx(session)) { + lprintf(LOG_ERR,"%04d !ERROR setting up JavaScript support for rewrite", session->socket); + return FALSE; + } + + JS_BEGINREQUEST(session->js_cx); + js_add_request_prop(session,"real_path",session->req.physical_path); + js_add_request_prop(session,"virtual_path",session->req.virtual_path); + js_add_request_prop(session,"ars",session->req.ars); + js_add_request_prop_writeable(session,"request_string",session->req.request_line); + js_add_request_prop(session,"host",session->req.host); + js_add_request_prop(session,"vhost",session->req.vhost); + js_add_request_prop(session,"http_ver",http_vers[session->http_ver]); + js_add_request_prop(session,"remote_ip",session->host_ip); + js_add_request_prop(session,"remote_host",session->host_name); + if(session->req.query_str[0]) { + js_add_request_prop(session,"query_string",session->req.query_str); + js_parse_query(session,session->req.query_str); + } + if(session->req.post_data && session->req.post_data[0]) { + if(session->req.post_len <= MAX_POST_LEN) { + js_add_request_prop(session,"post_data",session->req.post_data); + js_parse_query(session,session->req.post_data); + } + } + parse_js_headers(session); + + do { + /* RUN SCRIPT */ + JS_ClearPendingException(session->js_cx); + + session->js_callback.counter=0; + + lprintf(LOG_DEBUG,"%04d JavaScript: Compiling rewrite", session->socket); + if(!JS_EvaluateScript(session->js_cx, session->js_glob, script, strlen(script), "Redirection", 1, &rval)) { + lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile rewrite (%s)" + ,session->socket,script); + JS_ReportPendingException(session->js_cx); + JS_RemoveObjectRoot(session->js_cx, &session->js_glob); + JS_ENDREQUEST(session->js_cx); + return(FALSE); + } + JS_ReportPendingException(session->js_cx); + js_EvalOnExit(session->js_cx, session->js_glob, &session->js_callback); + JS_ReportPendingException(session->js_cx); + if (JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval)) { + session->req.send_location = MOVED_STAT; + JS_GetProperty(session->js_cx,session->js_request,"request_string",&val); + JSVALUE_TO_STRBUF(session->js_cx, val, redir_req, sizeof(redir_req), NULL); + safe_snprintf(session->redir_req,sizeof(session->redir_req),"%s %s%s%s",methods[session->req.method] + ,redir_req,session->http_ver<HTTP_1_0?"":" ",http_vers[session->http_ver]); + lprintf(LOG_DEBUG, "%04d Rewrite returned TRUE (%s)", session->socket, session->redir_req); + } + else + lprintf(LOG_DEBUG, "%04d Rewrite returned FALSE", session->socket); + JS_RemoveObjectRoot(session->js_cx, &session->js_glob); + } while(0); + + JS_ENDREQUEST(session->js_cx); + + return(retval); +} + static void read_webctrl_section(FILE *file, char *section, http_session_t *session, BOOL *recheck_dynamic) { - char str[MAX_PATH+1]; + int i; + char str[MAX_PATH+1]; + named_string_t **values; if(iniReadString(file, section, "AccessRequirements", session->req.ars,str)==str) SAFECOPY(session->req.ars,str); @@ -3237,6 +3324,12 @@ static void read_webctrl_section(FILE *file, char *section, http_session_t *sess session->req.fastcgi_socket=strdup(str); *recheck_dynamic=TRUE; } + values = iniReadNamedStringList(file, section); + for (i=0; values && values[i]; i++) { + if (strnicmp(values[i]->name, "Rewrite", 7)==0) + exec_js_rewrite(session, values[i]->value); + } + iniFreeNamedStringList(values); } static BOOL check_request(http_session_t * session) @@ -5440,7 +5533,7 @@ js_initcx(http_session_t *session) return(js_cx); } -static BOOL js_setup(http_session_t* session) +static BOOL js_setup_cx(http_session_t* session) { JSObject* argv; @@ -5473,11 +5566,11 @@ static BOOL js_setup(http_session_t* session) JS_DefineProperty(session->js_cx, session->js_glob, "web_error_dir", STRING_TO_JSVAL(JS_NewStringCopyZ(session->js_cx, session->req.error_dir?session->req.error_dir:error_dir)) ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE); - + JS_ENDREQUEST(session->js_cx); } else JS_BEGINREQUEST(session->js_cx); - + lprintf(LOG_DEBUG,"%04d JavaScript: Initializing HttpRequest object",session->socket); if(js_CreateHttpRequestObject(session->js_cx, session->js_glob, session)==NULL) { lprintf(LOG_ERR,"%04d !ERROR initializing JavaScript HttpRequest object",session->socket); @@ -5485,6 +5578,14 @@ static BOOL js_setup(http_session_t* session) return(FALSE); } + return TRUE; +} + +static BOOL js_setup(http_session_t* session) +{ + if(!js_setup_cx(session)) + return FALSE; + lprintf(LOG_DEBUG,"%04d JavaScript: Initializing HttpReply object",session->socket); if(js_CreateHttpReplyObject(session->js_cx, session->js_glob, session)==NULL) { lprintf(LOG_ERR,"%04d !ERROR initializing JavaScript HttpReply object",session->socket); @@ -5493,7 +5594,6 @@ static BOOL js_setup(http_session_t* session) } JS_SetContextPrivate(session->js_cx, session); - JS_ENDREQUEST(session->js_cx); return(TRUE); } @@ -6005,7 +6105,6 @@ static int close_session_no_rb(http_session_t *session) void http_session_thread(void* arg) { SOCKET socket; - char redir_req[MAX_REQUEST_LINE+1]; char *redirp; http_session_t session; int loop_count; @@ -6209,6 +6308,8 @@ void http_session_thread(void* arg) } if(get_req(&session,redirp)) { + if (redirp) + redirp[0]=0; if(init_error) { send_error(&session, __LINE__, error_500); } @@ -6220,10 +6321,12 @@ void http_session_thread(void* arg) respond(&session); } else { - safe_snprintf(redir_req,sizeof(redir_req),"%s %s%s%s",methods[session.req.method] - ,session.req.virtual_path,session.http_ver<HTTP_1_0?"":" ",http_vers[session.http_ver]); - lprintf(LOG_DEBUG,"%04d Internal Redirect to: %s",socket,redir_req); - redirp=redir_req; + if (!session.redir_req[0]) { + safe_snprintf(session.redir_req,sizeof(session.redir_req),"%s %s%s%s",methods[session.req.method] + ,session.req.virtual_path,session.http_ver<HTTP_1_0?"":" ",http_vers[session.http_ver]); + } + lprintf(LOG_DEBUG,"%04d Internal Redirect to: %s",socket,session.redir_req); + redirp=session.redir_req; } } }