diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c index 0141db44d48d44094356b57ea68425f438cc011c..17007a701adc205aaf9879b12e71b06b2e225487 100644 --- a/src/sbbs3/websrvr.c +++ b/src/sbbs3/websrvr.c @@ -3049,6 +3049,16 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) fprintf(session->req.fp,"!JavaScript %s%s%s: %s",warning,file,line,message); } +static void js_writebuf(http_session_t *session, char *buf, size_t buflen) +{ + if(session->req.sent_headers) { + if(session->req.method!=HTTP_HEAD && session->req.method!=HTTP_OPTIONS) + writebuf(session,buf,buflen); + } + else + fwrite(buf,1,buflen,session->req.fp); +} + static JSBool js_writefunc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, BOOL writeln) { @@ -3089,18 +3099,9 @@ js_writefunc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, continue; if(JS_GetStringLength(str)<1 && !writeln) continue; - if(session->req.sent_headers) { - if(session->req.method!=HTTP_HEAD && session->req.method!=HTTP_OPTIONS) { - writebuf(session,JS_GetStringBytes(str), JS_GetStringLength(str)); - if(writeln) - writebuf(session, newline, 2); - } - } - else { - fwrite(JS_GetStringBytes(str),1,JS_GetStringLength(str),session->req.fp); - if(writeln) - fwrite(newline,1,2,session->req.fp); - } + js_writebuf(session,JS_GetStringBytes(str), JS_GetStringLength(str)); + if(writeln) + js_writebuf(session, newline, 2); } if(str==NULL) @@ -3248,6 +3249,191 @@ js_login(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) 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; + + 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, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + JSString* js_str; + char *filename; + char *template; + FILE *tfile; + size_t len; + 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((filename=js_ValueToStringBytes(cx, argv[0]))==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); + } + + if((template=(char *)malloc(len))==NULL) { + 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)) + 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)) + return(JS_FALSE); + } + } + } + + session->req.prev_write=TRUE; + js_write_template_part(cx, obj, template, len, NULL); + + free(template); + 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 */