Newer
Older
session->js_query = JS_DefineObject(cx, session->js_request, "query", NULL
, NULL, JSPROP_ENUMERATE|JSPROP_READONLY);
/* Return existing object if it's already been created */
if(JS_GetProperty(cx,session->js_request,"header",&val) && val!=JSVAL_VOID) {
session->js_header = JSVAL_TO_OBJECT(val);
JS_ClearScope(cx,session->js_header);
session->js_header = JS_DefineObject(cx, session->js_request, "header", NULL
, NULL, JSPROP_ENUMERATE|JSPROP_READONLY);
/* Return existing object if it's already been created */
if(JS_GetProperty(cx,session->js_request,"cookie",&val) && val!=JSVAL_VOID) {
session->js_cookie = JSVAL_TO_OBJECT(val);
JS_ClearScope(cx,session->js_cookie);
}
else
session->js_cookie = JS_DefineObject(cx, session->js_request, "cookie", NULL
, NULL, JSPROP_ENUMERATE|JSPROP_READONLY);
static void
js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
char line[64];
char file[MAX_PATH+1];
char* warning;
http_session_t* session;
int log_level;
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return;
if(report==NULL) {
lprintf(LOG_ERR,"%04d !JavaScript: %s", session->socket, message);
if(session->req.fp!=NULL)
fprintf(session->req.fp,"!JavaScript: %s", message);
return;
}
if(report->filename)
SAFEPRINTF(file," %s",report->filename);
else
file[0]=0;
if(report->lineno)
SAFEPRINTF(line," line %u",report->lineno);
else
line[0]=0;
if(JSREPORT_IS_WARNING(report->flags)) {
if(JSREPORT_IS_STRICT(report->flags))
warning="strict warning";
else
warning="warning";
log_level=LOG_WARNING;
} else {
log_level=LOG_ERR;
warning="";
lprintf(log_level,"%04d !JavaScript %s%s%s: %s, Request: %s"
,session->socket,warning,file,line,message, session->req.request_line);
if(session->req.fp!=NULL)
fprintf(session->req.fp,"!JavaScript %s%s%s: %s",warning,file,line,message);
}
static void js_writebuf(http_session_t *session, const char *buf, size_t buflen)
{
if(session->req.sent_headers) {
writebuf(session,buf,buflen);
}
else
fwrite(buf,1,buflen,session->req.fp);
}
static JSBool
js_writefunc(JSContext *cx, uintN argc, jsval *arglist, BOOL writeln)
uintN i;
JSString* str=NULL;
http_session_t* session;
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
if(session->req.fp==NULL) {
return(JS_FALSE);
if((!session->req.prev_write) && (!session->req.sent_headers)) {
if(session->http_ver>=HTTP_1_1 && session->req.keep_alive) {
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
return(JS_FALSE);
JS_RESUMEREQUEST(cx, rc);
else {
/* "Fast Mode" requested? */
jsval val;
JSObject* reply;
JS_GetProperty(cx, session->js_glob, "http_reply", &val);
reply=JSVAL_TO_OBJECT(val);
JS_GetProperty(cx, reply, "fast", &val);
if(JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
session->req.keep_alive=FALSE;
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
return(JS_FALSE);
JS_RESUMEREQUEST(cx, rc);
}
}
}
session->req.prev_write=TRUE;
for(i=0; i<argc; i++) {
if((str=JS_ValueToString(cx, argv[i]))==NULL)
continue;
JSSTRING_TO_RASTRING(cx, str, cstr, &cstr_sz, &len);
HANDLE_PENDING(cx, cstr);
rc=JS_SUSPENDREQUEST(cx);
if(writeln)
js_writebuf(session, newline, 2);
JS_RESUMEREQUEST(cx, rc);
}
if(str==NULL)
else
return(JS_TRUE);
}
static JSBool
js_write(JSContext *cx, uintN argc, jsval *arglist)
return(JS_TRUE);
}
static JSBool
js_writeln(JSContext *cx, uintN argc, jsval *arglist)
return(JS_TRUE);
}
js_set_cookie(JSContext *cx, uintN argc, jsval *arglist)
jsval *argv=JS_ARGV(cx, arglist);
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
if(argc<2)
return(JS_FALSE);
header=header_buf;
HANDLE_PENDING(cx, p);
if(!p)
return(JS_FALSE);
header+=sprintf(header,"Set-Cookie: %s=",p);
FREE_AND_NULL(p);
HANDLE_PENDING(cx, p);
if(!p)
return(JS_FALSE);
header+=sprintf(header,"%s",p);
if(!JS_ValueToInt32(cx,argv[2],&i))
return JS_FALSE;
header += strftime(header,50,"; expires=%a, %d-%b-%Y %H:%M:%S GMT",&tm);
}
if(argc>3) {
JSVALUE_TO_MSTRING(cx, argv[3], p, NULL);
if(p!=NULL && *p) {
JSVALUE_TO_MSTRING(cx, argv[4], p, NULL);
if(p!=NULL && *p) {
header += sprintf(header,"; secure");
}
strListPush(&session->req.dynamic_heads,header_buf);
return(JS_TRUE);
}
static JSBool
js_log(JSContext *cx, uintN argc, jsval *arglist)
jsval *argv=JS_ARGV(cx, arglist);
char str[512];
uintN i=0;
int32 level=LOG_INFO;
http_session_t* session;
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
if(startup==NULL || startup->lputs==NULL)
return(JS_FALSE);
if(argc > 1 && JSVAL_IS_NUMBER(argv[i])) {
if(!JS_ValueToInt32(cx,argv[i++],&level))
return JS_FALSE;
}
str[0]=0;
for(;i<argc && strlen(str)<(sizeof(str)/2);i++) {
char* tp=strchr(str, 0);
JSVALUE_TO_STRBUF(cx, argv[i], tp, sizeof(str)/2, NULL);
strcat(str," ");
}
rc=JS_SUSPENDREQUEST(cx);
lprintf(level,"%04d %s",session->socket,str);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, str)));
return(JS_TRUE);
}
static JSBool
js_login(JSContext *cx, uintN argc, jsval *arglist)
jsval *argv=JS_ARGV(cx, arglist);
char* p;
JSBool inc_logons=JS_FALSE;
user_t user;
http_session_t* session;
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(JS_FALSE));
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
/* User name */
JSVALUE_TO_ASTRING(cx, argv[0], p, (LEN_ALIAS > LEN_NAME) ? LEN_ALIAS+2 : LEN_NAME+2, NULL);
if(p==NULL)
return(JS_FALSE);
rc=JS_SUSPENDREQUEST(cx);
memset(&user,0,sizeof(user));
if(isdigit((uchar)*p))
user.number=atoi(p);
else if(*p)
user.number=matchuser(&scfg,p,FALSE);
if(getuserdat(&scfg,&user)!=0) {
lprintf(LOG_NOTICE,"%04d !USER NOT FOUND: '%s'"
,session->socket,p);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
if(user.misc&(DELETED|INACTIVE)) {
lprintf(LOG_WARNING,"%04d !DELETED OR INACTIVE USER #%d: %s"
,session->socket,user.number,p);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
JS_RESUMEREQUEST(cx, rc);
/* Password */
if(user.pass[0]) {
JSVALUE_TO_ASTRING(cx, argv[1], p, LEN_PASS+2, NULL);
if(p==NULL)
return(JS_FALSE);
if(stricmp(user.pass,p)) { /* Wrong password */
rc=JS_SUSPENDREQUEST(cx);

rswindell
committed
lprintf(LOG_WARNING,"%04d !INVALID PASSWORD ATTEMPT FOR USER: '%s'"
,session->socket,user.alias);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
}
if(argc>2)
JS_ValueToBoolean(cx,argv[2],&inc_logons);
rc=JS_SUSPENDREQUEST(cx);
if(inc_logons) {
user.logons++;
user.ltoday++;
}
http_logon(session, &user);
JS_RESUMEREQUEST(cx, rc);
/* user-specific objects */
if(!js_CreateUserObjects(session->js_cx, session->js_glob, &scfg, &session->user, &session->client
,NULL /* ftp index file */, session->subscan /* subscan */)) {
lprintf(LOG_ERR,"%04d !JavaScript ERROR creating user objects",session->socket);
send_error(session,__LINE__,"500 Error initializing JavaScript User Objects");
return(FALSE);
}
JS_SET_RVAL(cx, arglist,BOOLEAN_TO_JSVAL(JS_TRUE));
return(JS_TRUE);
}
#if 0
static char *find_next_pair(char *buffer, size_t buflen, char find)
{
char *p;
char *search;
char *end;
size_t buflen2;
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
end=buffer+buflen;
search=buffer;
buflen2=buflen;
for(;search<end;) {
p=memchr(search, chars[i], buflen2);
/* Can't even find one... there's definatly no pair */
if(p==NULL)
return(NULL);
if(*(p+1)==find)
return(p);
/* Next search pos is at the char after the match */
search=p+1;
buflen2=end-search;
}
}
static void js_write_escaped(JSContext *cx, JSObject *obj, char *pos, size_t len, char *name_end, char *repeat_section)
{
char *name=pos+2;
}
enum {
T_AT
,T_PERCENT
,T_CARET
,T_LT
};
static int js_write_template_part(JSContext *cx, JSObject *obj, char *template, size_t len, char *repeat_section)
{
size_t len2;
char *pos;
char *end;
char *p;
char *p2;
char *send_end;
int no_more[4];
char *next[4];
int i,j;
char chars[5]="@%^<";
end=template+len;
pos=template;
memset(&next,0,sizeof(next));
memset(&no_more,0,sizeof(no_more));
while(pos<end) {
send_end=NULL;
/* Find next seperator */
for(i=0; i<4; i++) {
if(!no_more[i]) {
if(next[i] < pos)
next[i]=NULL;
if(next[i] == NULL) {
if((next[i]=find_next_pair(pos, len, chars[i]))==NULL) {
no_more[i]=TRUE;
continue;
}
}
if(!send_end || next[i] < send_end)
send_end=next[i];
}
}
if(send_end==NULL) {
/* Nothing else matched... we're good now! */
js_writebuf(session, pos, len);
pos=end;
len=0;
continue;
}
if(send_end > pos) {
i=send_end-pos;
js_writebuf(session, pos, i);
pos+=i;
len-=i;
}
/*
* At this point, pos points to a matched introducer.
* If it's not a repeat section, we can just output it here.
*/
if(*pos != '<') {
/*
* If there is no corresponding terminator to this introdcer,
* force it to be output unchanged.
*/
if((p=find_next_pair(pos, len, *pos))==NULL) {
no_more[strchr(chars,*pos)-char]=TRUE;
continue;
}
js_write_escaped(cx, obj, pos, len, p, repeat_section);
continue;
}
/*
* Pos is the start of a repeat section now... this is where things
* start to get tricky. Set up RepeatObj object, then call self
* once for each repeat.
*/
}
}
static JSBool
js_write_template(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
JSString* js_str;
char *filename;
char *template;
FILE *tfile;
size_t len;
http_session_t* session;
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
if(session->req.fp==NULL)
return(JS_FALSE);
JSVALUE_TO_MSTRING(cx, argv[0], filename, NULL);
return(JS_FALSE);
if(!fexist(filename)) {
JS_ReportError(cx, "Template file %s does not exist.", filename);
return(JS_FALSE);
}
len=flength(filename);
if((tfile=fopen(filename,"r"))==NULL) {
JS_ReportError(cx, "Unable to open template %s for read.", filename);
return(JS_FALSE);
}
JS_ReportError(cx, "Unable to allocate %u bytes for template.", len);
return(JS_FALSE);
}
if(fread(template, 1, len, tfile) != len) {
fclose(tfile);
JS_ReportError(cx, "Unable to read %u bytes from template %s.", len, filename);
return(JS_FALSE);
}
fclose(tfile);
if((!session->req.prev_write) && (!session->req.sent_headers)) {
if(session->http_ver>=HTTP_1_1 && session->req.keep_alive) {
if(!ssjs_send_headers(session,TRUE)) {
free(template);
return(JS_FALSE);
}
else {
/* "Fast Mode" requested? */
jsval val;
JSObject* reply;
JS_GetProperty(cx, session->js_glob, "http_reply", &val);
reply=JSVAL_TO_OBJECT(val);
JS_GetProperty(cx, reply, "fast", &val);
if(JSVAL_IS_BOOLEAN(val) && JSVAL_TO_BOOLEAN(val)) {
session->req.keep_alive=FALSE;
if(!ssjs_send_headers(session,FALSE)) {
free(template);
return(JS_FALSE);
}
}
}
session->req.prev_write=TRUE;
js_write_template_part(cx, obj, template, len, NULL);
return(JS_TRUE);
}
#endif
static JSFunctionSpec js_global_functions[] = {
{"write", js_write, 1}, /* write to HTML file */
{"writeln", js_writeln, 1}, /* write line to HTML file */
{"print", js_writeln, 1}, /* write line to HTML file (alias) */
{"log", js_log, 0}, /* Log a string */
{"login", js_login, 2}, /* log in as a different user */
{"set_cookie", js_set_cookie, 2}, /* Set a cookie */
{0}
};
static JSBool
js_OperationCallback(JSContext *cx)
JSBool ret;
http_session_t* session;
JS_SetOperationCallback(cx, NULL);
if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL) {
JS_SetOperationCallback(cx, js_OperationCallback);
return(JS_FALSE);
ret=js_CommonOperationCallback(cx,&session->js_callback);
JS_SetOperationCallback(cx, js_OperationCallback);
static JSContext*
js_initcx(http_session_t *session)
{
JSContext* js_cx;
lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)"
,session->socket,startup->js.cx_stack);
if((js_cx = JS_NewContext(session->js_runtime, startup->js.cx_stack))==NULL)
return(NULL);
JS_BEGINREQUEST(js_cx);
lprintf(LOG_DEBUG,"%04d JavaScript: Context created",session->socket);
JS_SetErrorReporter(js_cx, js_ErrorReporter);
JS_SetOperationCallback(js_cx, js_OperationCallback);
lprintf(LOG_DEBUG,"%04d JavaScript: Creating Global Objects and Classes",session->socket);
if(!js_CreateCommonObjects(js_cx, &scfg, NULL
,NULL /* global */
,uptime /* system */
,startup->host_name /* system */
,SOCKLIB_DESC /* system */
,&session->js_callback /* js */
,&session->client /* client */
,session->socket /* client */
,session->tls_sess /* client */
,&js_server_props /* server */
,&session->js_glob
)
|| !JS_DefineFunctions(js_cx, session->js_glob, js_global_functions)) {
JS_RemoveObjectRoot(js_cx, &session->js_glob);
JS_ENDREQUEST(js_cx);
JS_DestroyContext(js_cx);
return(NULL);
}
return(js_cx);
}
static BOOL js_setup_cx(http_session_t* session)
if(session->js_runtime == NULL) {
lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes"
,session->socket,startup->js.max_bytes);
if((session->js_runtime=jsrt_GetNew(startup->js.max_bytes, 5000, __FILE__, __LINE__))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR creating JavaScript runtime",session->socket);
return(FALSE);
}
}
if(session->js_cx==NULL) { /* Context not yet created, create it now */
/* js_initcx() begins a context */
if(((session->js_cx=js_initcx(session))==NULL)) {
lprintf(LOG_ERR,"%04d !ERROR initializing JavaScript context",session->socket);
return(FALSE);
}
argv=JS_NewArrayObject(session->js_cx, 0, NULL);
JS_DefineProperty(session->js_cx, session->js_glob, "argv", OBJECT_TO_JSVAL(argv)
,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
JS_DefineProperty(session->js_cx, session->js_glob, "argc", INT_TO_JSVAL(0)
,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
JS_DefineProperty(session->js_cx, session->js_glob, "web_root_dir",
STRING_TO_JSVAL(JS_NewStringCopyZ(session->js_cx, root_dir))
,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
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);
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);
JS_ENDREQUEST(session->js_cx);
return(FALSE);
}
JS_SetContextPrivate(session->js_cx, session);
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);
JS_ENDREQUEST(session->js_cx);
return(TRUE);
}
static BOOL ssjs_send_headers(http_session_t* session,int chunked)
jsval val;
JSObject* reply;
JSIdArray* heads;
JSObject* headers;
int i, h;
char str[MAX_REQUEST_LINE+1];
char *p=NULL,*p2=NULL;
size_t p_sz=0, p2_sz=0;
JS_BEGINREQUEST(session->js_cx);
JS_GetProperty(session->js_cx,session->js_glob,"http_reply",&val);
reply = JSVAL_TO_OBJECT(val);
JS_GetProperty(session->js_cx,reply,"status",&val);
JSVALUE_TO_STRBUF(session->js_cx, val, session->req.status, sizeof(session->req.status), NULL);
JS_GetProperty(session->js_cx,reply,"header",&val);
headers = JSVAL_TO_OBJECT(val);
heads=JS_Enumerate(session->js_cx,headers);
if(heads != NULL) {
for(i=0;i<heads->length;i++) {
JS_IdToValue(session->js_cx,heads->vector[i],&val);
JSVALUE_TO_RASTRING(session->js_cx, val, p, &p_sz, NULL);
if(p==NULL) {
if(p)
free(p);
if(p2)
free(p2);
return FALSE;
}
JS_GetProperty(session->js_cx,headers,p,&val);
JSVALUE_TO_RASTRING(session->js_cx, val, p2, &p2_sz, NULL);
if(JS_IsExceptionPending(session->js_cx)) {
if(p)
free(p);
if(p2)
free(p2);
return FALSE;
}
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
h = get_header_type(p);
switch(h) {
case HEAD_LOCATION:
if (*p2 == '/') {
unescape(p2);
SAFECOPY(session->req.virtual_path,p2);
session->req.send_location=MOVED_STAT;
}
else {
SAFECOPY(session->req.virtual_path,p2);
session->req.send_location=MOVED_TEMP;
}
if (atoi(session->req.status) == 200)
SAFECOPY(session->req.status, error_302);
break;
case HEAD_LENGTH:
case HEAD_TRANSFER_ENCODING:
/* If either of these are manually set, point
* the gun at the script writers foot for them */
chunked = false;
session->req.manual_length = TRUE;
default:
safe_snprintf(str,sizeof(str),"%s: %s",p,p2);
strListPush(&session->req.dynamic_heads,str);
}
if(p)
free(p);
if(p2)
free(p2);
JS_ClearScope(session->js_cx, headers);
JS_ENDREQUEST(session->js_cx);
return(send_headers(session,session->req.status,chunked));
}
static BOOL exec_ssjs(http_session_t* session, char* script) {
JSObject* js_script;
jsval rval;
char path[MAX_PATH+1];
BOOL retval=TRUE;
long double start;
/* External JavaScript handler? */
if(script == session->req.physical_path && session->req.xjs_handler[0])
script = session->req.xjs_handler;
sprintf(path,"%sSBBS_SSJS.%u.%u.html",temp_dir,getpid(),session->socket);
if((session->req.fp=fopen(path,"wb"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d opening/creating %s", session->socket, errno, path);
return(FALSE);
}
if(session->req.cleanup_file[CLEANUP_SSJS_TMP_FILE]) {
if(!(startup->options&WEB_OPT_DEBUG_SSJS))
remove(session->req.cleanup_file[CLEANUP_SSJS_TMP_FILE]);
free(session->req.cleanup_file[CLEANUP_SSJS_TMP_FILE]);
}
/* FREE()d in close_request() */
session->req.cleanup_file[CLEANUP_SSJS_TMP_FILE]=strdup(path);
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(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);
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_property(session, "post_data", session->req.post_data, session->req.post_len, /* writeable: */false);
js_parse_query(session,session->req.post_data);
}
do {
/* RUN SCRIPT */
JS_ClearPendingException(session->js_cx);
session->js_callback.counter=0;
lprintf(LOG_DEBUG,"%04d JavaScript: Compiling script: %s",session->socket,script);
if((js_script=JS_CompileFile(session->js_cx, session->js_glob
,script))==NULL) {
lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)"
,session->socket,script);
JS_RemoveObjectRoot(session->js_cx, &session->js_glob);
JS_ENDREQUEST(session->js_cx);
return(FALSE);
}
lprintf(LOG_DEBUG,"%04d JavaScript: Executing script: %s",session->socket,script);
start=xp_timer();
js_PrepareToExecute(session->js_cx, session->js_glob, script, /* startup_dir */NULL, session->js_glob);
JS_ExecuteScript(session->js_cx, session->js_glob, js_script, &rval);
js_EvalOnExit(session->js_cx, session->js_glob, &session->js_callback);
JS_RemoveObjectRoot(session->js_cx, &session->js_glob);
lprintf(LOG_DEBUG,"%04d JavaScript: Done executing script: %s (%.2Lf seconds)"
,session->socket,script,xp_timer()-start);
} while(0);
SAFECOPY(session->req.physical_path, path);
if(session->req.fp!=NULL) {
fclose(session->req.fp);
session->req.fp=NULL;
}
/* Read http_reply object */
retval=ssjs_send_headers(session,FALSE);
/* Free up temporary resources here */
session->req.dynamic=IS_SSJS;
JS_ENDREQUEST(session->js_cx);
return(retval);
}
static void respond(http_session_t * session)
{
if(session->req.method==HTTP_OPTIONS)
send_headers(session,session->req.status,FALSE);
if(session->req.dynamic==IS_FASTCGI) {
if(!exec_fastcgi(session)) {
send_error(session,__LINE__,error_500);
return;
}
session->req.finished=TRUE;
return;
}
if(session->req.dynamic==IS_CGI) {
if(!exec_cgi(session)) {
send_error(session,__LINE__,error_500);
return;
}
session->req.finished=TRUE;
if(session->req.dynamic==IS_SSJS) { /* Server-Side JavaScript */
if(!exec_ssjs(session,session->req.physical_path)) {
send_error(session,__LINE__,error_500);
return;
}
sprintf(session->req.physical_path
,"%sSBBS_SSJS.%u.%u.html",temp_dir,getpid(),session->socket);
}
else {
session->req.mime_type=get_mime_type(strrchr(session->req.physical_path,'.'));
send_headers(session,session->req.status,FALSE);
lprintf(LOG_INFO,"%04d Sending file: %s (%"PRIuOFF" bytes)"
,session->socket, session->req.physical_path, flength(session->req.physical_path));
snt=sock_sendfile(session,session->req.physical_path,session->req.range_start,session->req.range_end);
if(session->req.ld!=NULL) {
if(snt<0)
snt=0;
session->req.ld->size=snt;
}
lprintf(LOG_INFO,"%04d Sent file: %s (%d bytes)"
,session->socket, session->req.physical_path, snt);
session->req.finished=TRUE;
BOOL post_to_file(http_session_t *session, FILE*fp, size_t ch_len)
{
char buf[20*1024];
size_t k;
int bytes_read;
for(k=0; k<ch_len;) {
bytes_read=recvbufsocket(session,buf,(ch_len-k)>sizeof(buf)?sizeof(buf):(ch_len-k));
if(!bytes_read) {
send_error(session,__LINE__,error_500);
fclose(fp);
return(FALSE);
}
if(fwrite(buf, bytes_read, 1, fp)!=1) {
send_error(session,__LINE__,error_500);
fclose(fp);
return(FALSE);
}
k+=bytes_read;
session->req.post_len+=bytes_read;
}
return TRUE;
}
FILE *open_post_file(http_session_t *session)
{
char path[MAX_PATH+1];
FILE *fp;
// Create temporary file for post data.
SAFEPRINTF3(path,"%sSBBS_POST.%u.%u.data",temp_dir,getpid(),session->socket);
if((fp=fopen(path,"wb"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d opening/creating %s", session->socket, errno, path);
return fp;
}
if(session->req.cleanup_file[CLEANUP_POST_DATA]) {
remove(session->req.cleanup_file[CLEANUP_POST_DATA]);
free(session->req.cleanup_file[CLEANUP_POST_DATA]);
}
/* remove()d in close_request() */
session->req.cleanup_file[CLEANUP_POST_DATA]=strdup(path);
if(session->req.post_data != NULL) {
if(fwrite(session->req.post_data, session->req.post_len, 1, fp)!=1) {
lprintf(LOG_ERR,"%04d !ERROR writeing to %s", session->socket, path);
fclose(fp);
return(FALSE);
}
FREE_AND_NULL(session->req.post_data);
}
return fp;
}
int read_post_data(http_session_t * session)
{
FILE *fp=NULL;
if(session->req.dynamic!=IS_CGI && (session->req.post_len || session->req.read_chunked)) {
if(session->req.read_chunked) {
char *p;
size_t ch_len=0;
int bytes_read=0;
char ch_lstr[12];
session->req.post_len=0;
while(1) {
/* Read chunk length */
if(sockreadline(session,ch_lstr,sizeof(ch_lstr)-1)>0) {
ch_len=strtol(ch_lstr,NULL,16);
}
else {
send_error(session,__LINE__,error_500);
if(fp) fclose(fp);
return(FALSE);
}
if(ch_len==0)
break;
/* Check size */
s += ch_len;
if(s > MAX_POST_LEN) {
if(s > SIZE_MAX) {
send_error(session,__LINE__,"413 Request entity too large");