js_global.c 97.09 KiB
/* js_global.c */
/* Synchronet JavaScript "global" object properties/methods for all servers */
/* $Id$ */
/****************************************************************************
* @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 *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
*
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#define JS_THREADSAFE /* needed for JS_SetContextThread */
#include "sbbs.h"
#include "md5.h"
#include "base64.h"
#include "htmlansi.h"
#include "ini_file.h"
#include "js_rtpool.h"
/* SpiderMonkey: */
#include <jsfun.h>
#define MAX_ANSI_SEQ 16
#define MAX_ANSI_PARAMS 8
#ifdef JAVASCRIPT
typedef struct {
scfg_t *cfg;
jsSyncMethodSpec *methods;
} private_t;
/* Global Object Properites */
enum {
GLOB_PROP_ERRNO
,GLOB_PROP_ERRNO_STR
,GLOB_PROP_SOCKET_ERRNO
};
static JSBool js_system_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
jsint tiny;
JSString* js_str;
tiny = JSVAL_TO_INT(id);
switch(tiny) {
case GLOB_PROP_SOCKET_ERRNO:
JS_NewNumberValue(cx,ERROR_VALUE,vp);
break;
case GLOB_PROP_ERRNO:
JS_NewNumberValue(cx,errno,vp);
break;
case GLOB_PROP_ERRNO_STR:
if((js_str=JS_NewStringCopyZ(cx, strerror(errno)))==NULL)
return(JS_FALSE);
*vp = STRING_TO_JSVAL(js_str);
break;
}
return(JS_TRUE);
}
#define GLOBOBJ_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED
static jsSyncPropertySpec js_global_properties[] = {
/* name, tinyid, flags, ver */
{ "errno" ,GLOB_PROP_ERRNO ,GLOBOBJ_FLAGS, 310 },
{ "errno_str" ,GLOB_PROP_ERRNO_STR ,GLOBOBJ_FLAGS, 310 },
{ "socket_errno" ,GLOB_PROP_SOCKET_ERRNO ,GLOBOBJ_FLAGS, 310 },
{0}
};
typedef struct {
JSRuntime* runtime;
JSContext* cx;
JSContext* parent_cx;
JSObject* obj;
JSScript* script;
msg_queue_t* msg_queue;
js_branch_t branch;
JSErrorReporter error_reporter;
JSNative log;
} background_data_t;
static void background_thread(void* arg)
{
background_data_t* bg = (background_data_t*)arg;
jsval result=JSVAL_VOID;
jsval exit_code;
msgQueueAttach(bg->msg_queue);
JS_SetContextThread(bg->cx);
if(!JS_ExecuteScript(bg->cx, bg->obj, bg->script, &result)
&& JS_GetProperty(bg->cx, bg->obj, "exit_code", &exit_code))
result=exit_code;
js_EvalOnExit(bg->cx, bg->obj, &bg->branch);
js_enqueue_value(bg->cx, bg->msg_queue, result, NULL);
JS_DestroyScript(bg->cx, bg->script);
JS_DestroyContext(bg->cx);
jsrt_Release(bg->runtime);
free(bg);
}
static void
js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
background_data_t* bg;
if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
return;
/* Use parent's context private data */
JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
/* Call parent's error reporter */
bg->error_reporter(cx, message, report);
/* Restore our context private data */
JS_SetContextPrivate(cx, bg);
}
static JSBool js_BranchCallback(JSContext *cx, JSScript* script)
{
background_data_t* bg;
if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
return(JS_FALSE);
if(bg->parent_cx!=NULL && !JS_IsRunning(bg->parent_cx)) /* die when parent dies */
return(JS_FALSE);
return js_CommonBranchCallback(cx,&bg->branch);
}
static JSBool
js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSBool retval;
background_data_t* bg;
if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
return JS_FALSE;
/* Use parent's context private data */
JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
/* Call parent's log() function */
retval = bg->log(cx, obj, argc, argv, rval);
/* Restore our context private data */
JS_SetContextPrivate(cx, bg);
return retval;
}
/* Create a new value in the new context with a value from the original context */
/* Note: objects (including arrays) not currently supported */
static jsval* js_CopyValue(JSContext* cx, jsval val, JSContext* new_cx, jsval* rval)
{
*rval = JSVAL_VOID;
if(cx==new_cx
|| JSVAL_IS_BOOLEAN(val)
|| JSVAL_IS_NULL(val)
|| JSVAL_IS_VOID(val)
|| JSVAL_IS_INT(val))
*rval = val;
else if(JSVAL_IS_NUMBER(val)) {
jsdouble d;
if(JS_ValueToNumber(cx,val,&d))
JS_NewNumberValue(new_cx,d,rval);
}
else {
JSString* str;
size_t len;
char* p;
if((p=js_ValueToStringBytes(cx,val,&len)) != NULL
&& (str=JS_NewStringCopyN(new_cx,p,len)) != NULL)
*rval=STRING_TO_JSVAL(str);
}
return rval;
}
static JSBool
js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char path[MAX_PATH+1];
uintN i;
uintN argn=0;
const char* filename;
JSScript* script;
private_t* p;
jsval val;
JSObject* js_argv;
JSObject* exec_obj;
JSContext* exec_cx=cx;
JSBool success;
JSBool background=JS_FALSE;
background_data_t* bg;
jsrefcount rc;
*rval=JSVAL_VOID;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL)
return(JS_FALSE);
exec_obj=JS_GetScopeChain(cx);
if(JSVAL_IS_BOOLEAN(argv[argn]))
background=JSVAL_TO_BOOLEAN(argv[argn++]);
if(background) {
if((bg=(background_data_t*)malloc(sizeof(background_data_t)))==NULL)
return(JS_FALSE);
memset(bg,0,sizeof(background_data_t));
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;
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));
bg->branch.terminated=NULL; /* could be bad pointer at any time */
bg->branch.counter=0;
bg->branch.gc_attempts=0;
if((bg->runtime = jsrt_GetNew(JAVASCRIPT_MAX_BYTES, 1000))==NULL)
return(JS_FALSE);
if((bg->cx = JS_NewContext(bg->runtime, JAVASCRIPT_CONTEXT_STACK))==NULL)
return(JS_FALSE);
if((bg->obj=js_CreateCommonObjects(bg->cx
,p->cfg /* common config */
,NULL /* node-specific config */
,NULL /* additional global methods */
,0 /* uptime */
,"" /* hostname */
,"" /* socklib_desc */
,&bg->branch /* js */
,NULL /* client */
,INVALID_SOCKET /* client_socket */
,NULL /* server props */
))==NULL)
return(JS_FALSE);
bg->msg_queue = msgQueueInit(NULL,MSG_QUEUE_BIDIR);
js_CreateQueueObject(bg->cx, bg->obj, "parent_queue", bg->msg_queue);
/* Save parent's error reporter (for later use by our error reporter) */
bg->error_reporter=JS_SetErrorReporter(cx,NULL);
JS_SetErrorReporter(cx,bg->error_reporter);
JS_SetErrorReporter(bg->cx,js_ErrorReporter);
/* Set our branch callback (which calls the generic branch callback) */
JS_SetContextPrivate(bg->cx, bg);
JS_SetBranchCallback(bg->cx, js_BranchCallback);
/* Save parent's 'log' function (for later use by our log function) */
if(JS_GetProperty(cx, obj, "log", &val)) {
JSFunction* func;
if((func=JS_ValueToFunction(cx, val))!=NULL && !(func->flags&JSFUN_INTERPRETED)) {
bg->log=func->u.n.native;
JS_DefineFunction(bg->cx, bg->obj
,"log", js_log, func->nargs, func->flags);
}
}
exec_cx = bg->cx;
exec_obj = bg->obj;
} else if(JSVAL_IS_OBJECT(argv[argn])) {
JSObject* tmp_obj=JSVAL_TO_OBJECT(argv[argn++]);
if(!JS_ObjectIsFunction(cx,tmp_obj)) /* Scope specified */
exec_obj=tmp_obj;
}
if(argn==argc) {
JS_ReportError(cx,"no filename specified");
return(JS_FALSE);
}
if((filename=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
return(JS_FALSE);
if(argc>argn || background) {
if((js_argv=JS_NewArrayObject(exec_cx, 0, NULL)) == NULL)
return(JS_FALSE);
JS_DefineProperty(exec_cx, exec_obj, "argv", OBJECT_TO_JSVAL(js_argv)
,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
for(i=argn; i<argc; i++)
JS_SetElement(exec_cx, js_argv, i-argn, js_CopyValue(cx,argv[i],exec_cx,&val));
JS_DefineProperty(exec_cx, exec_obj, "argc", INT_TO_JSVAL(argc-argn)
,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
}
rc=JS_SuspendRequest(cx);
errno = 0;
if(isfullpath(filename))
strcpy(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);
}
JS_ResumeRequest(cx, rc);
JS_ClearPendingException(exec_cx);
if((script=JS_CompileFile(exec_cx, exec_obj, path))==NULL)
return(JS_FALSE);
if(background) {
bg->script = script;
*rval = OBJECT_TO_JSVAL(js_CreateQueueObject(cx, obj, NULL, bg->msg_queue));
success = _beginthread(background_thread,0,bg)!=-1;
} else {
success = JS_ExecuteScript(exec_cx, exec_obj, script, rval);
JS_DestroyScript(exec_cx, script);
}
return(success);
}
static JSBool
js_format(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
JSString* str;
if((p=js_sprintf(cx, 0, argc, argv))==NULL) {
JS_ReportError(cx,"js_sprintf failed");
return(JS_FALSE);
}
str = JS_NewStringCopyZ(cx, p);
js_sprintf_free(p);
if(str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(str);
return(JS_TRUE);
}
static JSBool
js_yield(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
BOOL forced=TRUE;
jsrefcount rc;
if(argc)
JS_ValueToBoolean(cx, argv[0], &forced);
rc=JS_SuspendRequest(cx);
if(forced) {
YIELD();
} else {
MAYBE_YIELD();
}
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_mswait(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 val=1;
clock_t start=msclock();
jsrefcount rc;
if(argc)
JS_ValueToInt32(cx,argv[0],&val);
rc=JS_SuspendRequest(cx);
mswait(val);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,msclock()-start,rval);
return(JS_TRUE);
}
static JSBool
js_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 val=100;
if(argc)
JS_ValueToInt32(cx,argv[0],&val);
JS_NewNumberValue(cx,sbbs_random(val),rval);
return(JS_TRUE);
}
static JSBool
js_time(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JS_NewNumberValue(cx,time(NULL),rval);
return(JS_TRUE);
}
static JSBool
js_beep(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 freq=500;
int32 dur=500;
jsrefcount rc;
if(argc)
JS_ValueToInt32(cx,argv[0],&freq);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&dur);
rc=JS_SuspendRequest(cx);
sbbs_beep(freq,dur);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_exit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
if(argc)
JS_DefineProperty(cx, obj, "exit_code", argv[0]
,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
return(JS_FALSE);
}
static JSBool
js_crc16(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
size_t len;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = INT_TO_JSVAL(crc16(p,len));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_crc32(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
size_t len;
uint32_t cs;
jsrefcount rc;
rc=JS_SuspendRequest(cx);
JS_ResumeRequest(cx, rc);
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
return(JS_FALSE);
cs=crc32(p,len);
rc=JS_SuspendRequest(cx);
JS_NewNumberValue(cx,cs,rval);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_chksum(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
ulong sum=0;
char* p;
size_t len;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
while(len--) sum+=*(p++);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,sum,rval);
return(JS_TRUE);
}
static JSBool
js_ascii(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char str[2];
int32 i=0;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if(JSVAL_IS_STRING(argv[0])) { /* string to ascii-int */
if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
return(JS_FALSE);
*rval=INT_TO_JSVAL(*p);
return(JS_TRUE);
}
/* ascii-int to str */
JS_ValueToInt32(cx,argv[0],&i);
str[0]=(uchar)i;
str[1]=0;
if((js_str = JS_NewStringCopyZ(cx, str))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_ctrl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char ch;
char* p;
char str[2];
int32 i=0;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if(JSVAL_IS_STRING(argv[0])) {
if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
return(JS_FALSE);
ch=*p;
} else {
JS_ValueToInt32(cx,argv[0],&i);
ch=(char)i;
}
str[0]=toupper(ch)&~0x40;
str[1]=0;
if((js_str = JS_NewStringCopyZ(cx, str))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_ascii_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* buf;
JSString* str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((buf=strdup(p))==NULL)
return(JS_FALSE);
ascii_str(buf);
str = JS_NewStringCopyZ(cx, buf);
free(buf);
if(str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(str);
return(JS_TRUE);
}
static JSBool
js_strip_ctrl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* buf;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((buf=strdup(p))==NULL)
return(JS_FALSE);
strip_ctrl(buf);
js_str = JS_NewStringCopyZ(cx, buf);
free(buf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_strip_exascii(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* buf;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((buf=strdup(p))==NULL)
return(JS_FALSE);
strip_exascii(buf);
js_str = JS_NewStringCopyZ(cx, buf);
free(buf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_lfexpand(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
ulong i,j;
char* inbuf;
char* outbuf;
JSString* str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((outbuf=(char*)malloc((strlen(inbuf)*2)+1))==NULL)
return(JS_FALSE);
for(i=j=0;inbuf[i];i++) {
if(inbuf[i]=='\n' && (!i || inbuf[i-1]!='\r'))
outbuf[j++]='\r';
outbuf[j++]=inbuf[i];
}
outbuf[j]=0;
str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
if(str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(str);
return(JS_TRUE);
}
static int get_prefix(char *text, int *bytes, int *len, int maxlen)
{
int tmp_prefix_bytes,tmp_prefix_len;
int expect;
int depth;
*bytes=0;
*len=0;
tmp_prefix_bytes=0;
tmp_prefix_len=0;
depth=0;
expect=1;
if(text[0]!=' ')
expect=2;
while(expect) {
tmp_prefix_bytes++;
/* Skip CTRL-A codes */
while(text[tmp_prefix_bytes-1]=='\x01') {
tmp_prefix_bytes++;
if(text[tmp_prefix_bytes-1]=='\x01')
break;
tmp_prefix_bytes++;
}
tmp_prefix_len++;
if(text[tmp_prefix_bytes-1]==0 || text[tmp_prefix_bytes-1]=='\n' || text[tmp_prefix_bytes-1]=='\r')
break;
switch(expect) {
case 1: /* At start of possible quote (Next char should be space) */
if(text[tmp_prefix_bytes-1]!=' ')
expect=0;
else
expect++;
break;
case 2: /* At start of nick (next char should be alphanum or '>') */
case 3: /* At second nick initial (next char should be alphanum or '>') */
case 4: /* At third nick initial (next char should be alphanum or '>') */
if(text[tmp_prefix_bytes-1]==' ' || text[tmp_prefix_bytes-1]==0)
expect=0;
else
if(text[tmp_prefix_bytes-1]=='>')
expect=6;
else
expect++;
break;
case 5: /* After three regular chars, next HAS to be a '>') */
if(text[tmp_prefix_bytes-1]!='>')
expect=0;
else
expect++;
break;
case 6: /* At '>' next char must be a space */
if(text[tmp_prefix_bytes-1]!=' ')
expect=0;
else {
expect=1;
*len=tmp_prefix_len;
*bytes=tmp_prefix_bytes;
depth++;
/* Some editors don't put double spaces in between */
if(text[tmp_prefix_bytes]!=' ')
expect++;
}
break;
default:
expect=0;
break;
}
}
if(*bytes >= maxlen) {
lprintf(LOG_CRIT, "Prefix bytes %u is larger than buffer (%u) here: %*.*s",*bytes,maxlen,maxlen,maxlen,text);
*bytes=maxlen-1;
}
return(depth);
}
static void outbuf_append(char **outbuf, char **outp, char *append, int len, int *outlen)
{
char *p;
/* Terminate outbuf */
**outp=0;
/* Check if there's room */
if(*outp - *outbuf + len < *outlen) {
memcpy(*outp, append, len);
*outp+=len;
return;
}
/* Not enough room, double the size. */
*outlen *= 2;
p=realloc(*outbuf, *outlen);
if(p==NULL) {
/* Can't do it. */
*outlen/=2;
return;
}
/* Set outp for new buffer */
*outp=p+(*outp - *outbuf);
*outbuf=p;
memcpy(*outp, append, len);
*outp+=len;
return;
}
static int compare_prefix(char *old_prefix, int old_prefix_bytes, char *new_prefix, int new_prefix_bytes)
{
int i;
if(new_prefix_bytes != old_prefix_bytes) {
if(new_prefix_bytes < old_prefix_bytes) {
if(memcmp(old_prefix, new_prefix, new_prefix_bytes)!=0)
return(-1);
for(i=new_prefix_bytes; i<old_prefix_bytes; i++) {
if(!isspace(old_prefix[i]))
return(-1);
}
}
else {
if(memcmp(old_prefix, new_prefix, old_prefix_bytes)!=0)
return(-1);
for(i=old_prefix_bytes; i<new_prefix_bytes; i++) {
if(!isspace(new_prefix[i]))
return(-1);
}
}
return(0);
}
if(memcmp(old_prefix,new_prefix,new_prefix_bytes)!=0)
return(-1);
return(0);
}
static JSBool
js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 l,len=79;
int32 oldlen=79;
int32 crcount=0;
JSBool handle_quotes=JS_TRUE;
long i,k,t;
int ocol=1;
int icol=1;
uchar* inbuf;
char* outbuf;
char* outp;
char* linebuf;
char* prefix=NULL;
int prefix_len=0;
int prefix_bytes=0;
int quote_count=0;
int old_prefix_bytes=0;
int outbuf_size=0;
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
outbuf_size=strlen(inbuf)*3+1;
if((outbuf=(char*)malloc(outbuf_size))==NULL)
return(JS_FALSE);
outp=outbuf;
if(argc>1)
JS_ValueToInt32(cx,argv[1],&len);
if(argc>2)
JS_ValueToInt32(cx,argv[2],&oldlen);
if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
handle_quotes=JSVAL_TO_BOOLEAN(argv[3]);
if((linebuf=(char*)malloc((len*2)+2))==NULL) /* room for ^A codes ToDo: This isn't actually "enough" room */
return(JS_FALSE);
if(handle_quotes) {
if((prefix=(char *)malloc((len*2)+2))==NULL) { /* room for ^A codes ToDo: This isn't actually "enough" room */
free(linebuf);
return(JS_FALSE);
}
prefix[0]=0;
}
rc=JS_SuspendRequest(cx);
outbuf[0]=0;
/* Get prefix from the first line (ouch) */
l=0;
i=0;
if(handle_quotes && (quote_count=get_prefix(inbuf, &prefix_bytes, &prefix_len, len*2+2))!=0) {
i+=prefix_bytes;
if(prefix_len>len/3*2) {
/* This prefix is insane (more than 2/3rds of the new width) hack it down to size */
/* Since we're hacking it, we will always end up with a hardcr on this line. */
/* ToDo: Something prettier would be nice. */
sprintf(prefix," %d> ",quote_count);
prefix_len=strlen(prefix);
prefix_bytes=strlen(prefix);
}
else {
memcpy(prefix,inbuf,prefix_bytes);
/* Terminate prefix */
prefix[prefix_bytes]=0;
}
memcpy(linebuf,prefix,prefix_bytes);
l=prefix_bytes;
ocol=prefix_len+1;
icol=prefix_len+1;
old_prefix_bytes=prefix_bytes;
}
for(; inbuf[i]; i++) {
if(l>=len*2+2) {
l-=4;
linebuf[l]=0;
lprintf(LOG_CRIT, "Word wrap line buffer exceeded... munging line %s",linebuf);
}
switch(inbuf[i]) {
case '\r':
crcount++;
break;
case '\n':
if(handle_quotes && (quote_count=get_prefix(inbuf+i+1, &prefix_bytes, &prefix_len, len*2+2))!=0) {
/* Move the input pointer offset to the last char of the prefix */
i+=prefix_bytes;
}
if(!inbuf[i+1]) { /* EOF */
linebuf[l++]='\r';
linebuf[l++]='\n';
outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
l=0;
ocol=1;
}
/* If there's a new prefix, it is a hardcr */
else if(compare_prefix(prefix, old_prefix_bytes, inbuf+i+1-prefix_bytes, prefix_bytes)!=0) {
if(prefix_len>len/3*2) {
/* This prefix is insane (more than 2/3rds of the new width) hack it down to size */
/* Since we're hacking it, we will always end up with a hardcr on this line. */
/* ToDo: Something prettier would be nice. */
sprintf(prefix," %d> ",quote_count);
prefix_len=strlen(prefix);
prefix_bytes=strlen(prefix);
}
else {
memcpy(prefix,inbuf+i+1-prefix_bytes,prefix_bytes);
/* Terminate prefix */
prefix[prefix_bytes]=0;
}
linebuf[l++]='\r';
linebuf[l++]='\n';
outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
memcpy(linebuf,prefix,prefix_bytes);
l=prefix_bytes;
ocol=prefix_len+1;
old_prefix_bytes=prefix_bytes;
}
else if(isspace(inbuf[i+1]) && inbuf[i+1] != '\n' && inbuf[i+1] != '\r') { /* Next line starts with whitespace. This is a "hard" CR. */
linebuf[l++]='\r';
linebuf[l++]='\n';
outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
l=prefix_bytes;
ocol=prefix_len+1;
}
else {
if(icol < oldlen) { /* If this line is overly long, It's impossible for the next word to fit */
/* k will equal the length of the first word on the next line */
for(k=0; inbuf[i+1+k] && (!isspace(inbuf[i+1+k])); k++);
if(icol+k+1 < oldlen) { /* The next word would have fit but isn't here. Must be a hard CR */
linebuf[l++]='\r';
linebuf[l++]='\n';
outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
if(prefix)
memcpy(linebuf,prefix,prefix_bytes);
l=prefix_bytes;
ocol=prefix_len+1;
}
else { /* Not a hard CR... add space if needed */
if(l<1 || !isspace(linebuf[l-1])) {
linebuf[l++]=' ';
ocol++;
}
}
}
else { /* Not a hard CR... add space if needed */
if(l<1 || !isspace(linebuf[l-1])) {
linebuf[l++]=' ';
ocol++;
}
}
}
icol=prefix_len+1;
break;
case '\x1f': /* Delete... meaningless... strip. */
break;
case '\b': /* Backspace... handle if possible, but don't go crazy. */
if(l>0) {
if(l>1 && linebuf[l-2]=='\x01') {
if(linebuf[l-1]=='\x01') {
ocol--;
icol--;
}
l-=2;
}
else {
l--;
ocol--;
icol--;
}
}
break;
case '\t': /* TAB */
linebuf[l++]=inbuf[i];
/* Can't ever wrap on whitespace remember. */
icol++;
ocol++;
while(ocol%8)
ocol++;
while(icol%8)
icol++;
break;
case '\x01': /* CTRL-A */
linebuf[l++]=inbuf[i++];
if(inbuf[i]!='\x01') {
linebuf[l++]=inbuf[i];
break;
}
default:
linebuf[l++]=inbuf[i];
ocol++;
icol++;
if(ocol>len && !isspace(inbuf[i])) { /* Need to wrap here */
/* Find the start of the last word */
k=l; /* Original next char */
l--; /* Move back to the last char */
while((!isspace(linebuf[l])) && l>0) /* Move back to the last non-space char */
l--;
if(l==0) { /* Couldn't wrap... must chop. */
l=k;
while(l>1 && linebuf[l-2]=='\x01' && linebuf[l-1]!='\x01')
l-=2;
if(l>0 && linebuf[l-1]=='\x01')
l--;
if(l>0)
l--;
}
t=l+1; /* Store start position of next line */
/* Move to start of whitespace */
while(l>0 && isspace(linebuf[l]))
l--;
outbuf_append(&outbuf, &outp, linebuf, l+1, &outbuf_size);
outbuf_append(&outbuf, &outp, "\r\n", 2, &outbuf_size);
/* Move trailing words to start of buffer. */
l=prefix_bytes;
if(k-t>0) /* k-1 is the last char position. t is the start of the next line position */
memmove(linebuf+l, linebuf+t, k-t);
l+=k-t;
/* Find new ocol */
for(ocol=prefix_len+1,t=prefix_bytes; t<l; t++) {
switch(linebuf[t]) {
case '\x01': /* CTRL-A */
t++;
if(linebuf[t]!='\x01')
break;
/* Fall-through */
default:
ocol++;
}
}
}
}
}
/* Trailing bits. */
if(l) {
linebuf[l++]='\r';
linebuf[l++]='\n';
outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
}
*outp=0;
/* If there were no CRs in the input, strip all CRs */
if(!crcount) {
for(inbuf=outbuf; *inbuf; inbuf++) {
if(*inbuf=='\r')
memmove(inbuf, inbuf+1, strlen(inbuf));
}
}
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
free(linebuf);
if(prefix)
free(prefix);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_quote_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 len=79;
int i,l,clen;
uchar* inbuf;
char* outbuf;
char* linebuf;
char* prefix=" > ";
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&len);
if(argc>2)
prefix=js_ValueToStringBytes(cx, argv[2], NULL);
if((outbuf=(char*)malloc((strlen(inbuf)*strlen(prefix))+1))==NULL)
return(JS_FALSE);
len-=strlen(prefix);
if(len<=0)
return(JS_FALSE);
if((linebuf=(char*)alloca(len*2+2))==NULL) /* (Hopefully) Room for ^A codes. ToDo */
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
outbuf[0]=0;
clen=0;
for(i=l=0;inbuf[i];i++) {
if(l==0) /* Do not use clen here since if the line starts with ^A, could stay at zero */
strcat(outbuf,prefix);
if(clen<len || inbuf[i]=='\n' || inbuf[i]=='\r')
linebuf[l++]=inbuf[i];
if(inbuf[i]=='\x01') { /* Handle CTRL-A */
linebuf[l++]=inbuf[++i];
if(inbuf[i]=='\x01')
clen++;
}
else
clen++;
/* ToDo: Handle TABs etc. */
if(inbuf[i]=='\n') {
strncat(outbuf,linebuf,l);
l=0;
clen=0;
}
}
if(l) /* remainder */
strncat(outbuf,linebuf,l);
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_netaddr_type(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
*rval = INT_TO_JSVAL(smb_netaddr_type(str));
return(JS_TRUE);
}
static JSBool
js_rot13(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* str;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((p=strdup(str))==NULL)
return(JS_FALSE);
js_str = JS_NewStringCopyZ(cx, rot13(p));
free(p);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
/* This table is used to convert between IBM ex-ASCII and HTML character entities */
/* Much of this table supplied by Deuce (thanks!) */
static struct {
int value;
char* name;
} exasctbl[128] = {
/* HTML val,name ASCII description */
{ 199 ,"Ccedil" }, /* 128 C, cedilla */
{ 252 ,"uuml" }, /* 129 u, umlaut */
{ 233 ,"eacute" }, /* 130 e, acute accent */
{ 226 ,"acirc" }, /* 131 a, circumflex accent */
{ 228 ,"auml" }, /* 132 a, umlaut */
{ 224 ,"agrave" }, /* 133 a, grave accent */
{ 229 ,"aring" }, /* 134 a, ring */
{ 231 ,"ccedil" }, /* 135 c, cedilla */
{ 234 ,"ecirc" }, /* 136 e, circumflex accent */
{ 235 ,"euml" }, /* 137 e, umlaut */
{ 232 ,"egrave" }, /* 138 e, grave accent */
{ 239 ,"iuml" }, /* 139 i, umlaut */
{ 238 ,"icirc" }, /* 140 i, circumflex accent */
{ 236 ,"igrave" }, /* 141 i, grave accent */
{ 196 ,"Auml" }, /* 142 A, umlaut */
{ 197 ,"Aring" }, /* 143 A, ring */
{ 201 ,"Eacute" }, /* 144 E, acute accent */
{ 230 ,"aelig" }, /* 145 ae ligature */
{ 198 ,"AElig" }, /* 146 AE ligature */
{ 244 ,"ocirc" }, /* 147 o, circumflex accent */
{ 246 ,"ouml" }, /* 148 o, umlaut */
{ 242 ,"ograve" }, /* 149 o, grave accent */
{ 251 ,"ucirc" }, /* 150 u, circumflex accent */
{ 249 ,"ugrave" }, /* 151 u, grave accent */
{ 255 ,"yuml" }, /* 152 y, umlaut */
{ 214 ,"Ouml" }, /* 153 O, umlaut */
{ 220 ,"Uuml" }, /* 154 U, umlaut */
{ 162 ,"cent" }, /* 155 Cent sign */
{ 163 ,"pound" }, /* 156 Pound sign */
{ 165 ,"yen" }, /* 157 Yen sign */
{ 8359 ,NULL }, /* 158 Pt (unicode) */
{ 402 ,NULL }, /* 402 Florin (non-standard alsi 159?) */
{ 225 ,"aacute" }, /* 160 a, acute accent */
{ 237 ,"iacute" }, /* 161 i, acute accent */
{ 243 ,"oacute" }, /* 162 o, acute accent */
{ 250 ,"uacute" }, /* 163 u, acute accent */
{ 241 ,"ntilde" }, /* 164 n, tilde */
{ 209 ,"Ntilde" }, /* 165 N, tilde */
{ 170 ,"ordf" }, /* 166 Feminine ordinal */
{ 186 ,"ordm" }, /* 167 Masculine ordinal */
{ 191 ,"iquest" }, /* 168 Inverted question mark */
{ 8976 ,NULL }, /* 169 Inverse "Not sign" (unicode) */
{ 172 ,"not" }, /* 170 Not sign */
{ 189 ,"frac12" }, /* 171 Fraction one-half */
{ 188 ,"frac14" }, /* 172 Fraction one-fourth */
{ 161 ,"iexcl" }, /* 173 Inverted exclamation point */
{ 171 ,"laquo" }, /* 174 Left angle quote */
{ 187 ,"raquo" }, /* 175 Right angle quote */
{ 9617 ,NULL }, /* 176 drawing symbol (unicode) */
{ 9618 ,NULL }, /* 177 drawing symbol (unicode) */
{ 9619 ,NULL }, /* 178 drawing symbol (unicode) */
{ 9474 ,NULL }, /* 179 drawing symbol (unicode) */
{ 9508 ,NULL }, /* 180 drawing symbol (unicode) */
{ 9569 ,NULL }, /* 181 drawing symbol (unicode) */
{ 9570 ,NULL }, /* 182 drawing symbol (unicode) */
{ 9558 ,NULL }, /* 183 drawing symbol (unicode) */
{ 9557 ,NULL }, /* 184 drawing symbol (unicode) */
{ 9571 ,NULL }, /* 185 drawing symbol (unicode) */
{ 9553 ,NULL }, /* 186 drawing symbol (unicode) */
{ 9559 ,NULL }, /* 187 drawing symbol (unicode) */
{ 9565 ,NULL }, /* 188 drawing symbol (unicode) */
{ 9564 ,NULL }, /* 189 drawing symbol (unicode) */
{ 9563 ,NULL }, /* 190 drawing symbol (unicode) */
{ 9488 ,NULL }, /* 191 drawing symbol (unicode) */
{ 9492 ,NULL }, /* 192 drawing symbol (unicode) */
{ 9524 ,NULL }, /* 193 drawing symbol (unicode) */
{ 9516 ,NULL }, /* 194 drawing symbol (unicode) */
{ 9500 ,NULL }, /* 195 drawing symbol (unicode) */
{ 9472 ,NULL }, /* 196 drawing symbol (unicode) */
{ 9532 ,NULL }, /* 197 drawing symbol (unicode) */
{ 9566 ,NULL }, /* 198 drawing symbol (unicode) */
{ 9567 ,NULL }, /* 199 drawing symbol (unicode) */
{ 9562 ,NULL }, /* 200 drawing symbol (unicode) */
{ 9556 ,NULL }, /* 201 drawing symbol (unicode) */
{ 9577 ,NULL }, /* 202 drawing symbol (unicode) */
{ 9574 ,NULL }, /* 203 drawing symbol (unicode) */
{ 9568 ,NULL }, /* 204 drawing symbol (unicode) */
{ 9552 ,NULL }, /* 205 drawing symbol (unicode) */
{ 9580 ,NULL }, /* 206 drawing symbol (unicode) */
{ 9575 ,NULL }, /* 207 drawing symbol (unicode) */
{ 9576 ,NULL }, /* 208 drawing symbol (unicode) */
{ 9572 ,NULL }, /* 209 drawing symbol (unicode) */
{ 9573 ,NULL }, /* 210 drawing symbol (unicode) */
{ 9561 ,NULL }, /* 211 drawing symbol (unicode) */
{ 9560 ,NULL }, /* 212 drawing symbol (unicode) */
{ 9554 ,NULL }, /* 213 drawing symbol (unicode) */
{ 9555 ,NULL }, /* 214 drawing symbol (unicode) */
{ 9579 ,NULL }, /* 215 drawing symbol (unicode) */
{ 9578 ,NULL }, /* 216 drawing symbol (unicode) */
{ 9496 ,NULL }, /* 217 drawing symbol (unicode) */
{ 9484 ,NULL }, /* 218 drawing symbol (unicode) */
{ 9608 ,NULL }, /* 219 drawing symbol (unicode) */
{ 9604 ,NULL }, /* 220 drawing symbol (unicode) */
{ 9612 ,NULL }, /* 221 drawing symbol (unicode) */
{ 9616 ,NULL }, /* 222 drawing symbol (unicode) */
{ 9600 ,NULL }, /* 223 drawing symbol (unicode) */
{ 945 ,NULL }, /* 224 alpha symbol */
{ 223 ,"szlig" }, /* 225 sz ligature (beta symbol) */
{ 915 ,NULL }, /* 226 omega symbol */
{ 960 ,NULL }, /* 227 pi symbol*/
{ 931 ,NULL }, /* 228 epsilon symbol */
{ 963 ,NULL }, /* 229 o with stick */
{ 181 ,"micro" }, /* 230 Micro sign (Greek mu) */
{ 964 ,NULL }, /* 231 greek char? */
{ 934 ,NULL }, /* 232 greek char? */
{ 920 ,NULL }, /* 233 greek char? */
{ 937 ,NULL }, /* 234 greek char? */
{ 948 ,NULL }, /* 235 greek char? */
{ 8734 ,NULL }, /* 236 infinity symbol (unicode) */
{ 966 ,"oslash" }, /* 237 Greek Phi */
{ 949 ,NULL }, /* 238 rounded E */
{ 8745 ,NULL }, /* 239 unside down U (unicode) */
{ 8801 ,NULL }, /* 240 drawing symbol (unicode) */
{ 177 ,"plusmn" }, /* 241 Plus or minus */
{ 8805 ,NULL }, /* 242 drawing symbol (unicode) */
{ 8804 ,NULL }, /* 243 drawing symbol (unicode) */
{ 8992 ,NULL }, /* 244 drawing symbol (unicode) */
{ 8993 ,NULL }, /* 245 drawing symbol (unicode) */
{ 247 ,"divide" }, /* 246 Division sign */
{ 8776 ,NULL }, /* 247 two squiggles (unicode) */
{ 176 ,"deg" }, /* 248 Degree sign */
{ 8729 ,NULL }, /* 249 drawing symbol (unicode) */
{ 183 ,"middot" }, /* 250 Middle dot */
{ 8730 ,NULL }, /* 251 check mark (unicode) */
{ 8319 ,NULL }, /* 252 superscript n (unicode) */
{ 178 ,"sup2" }, /* 253 superscript 2 */
{ 9632 ,NULL }, /* 254 drawing symbol (unicode) */
{ 160 ,"nbsp" } /* 255 non-breaking space */
};
static struct {
int value;
char* name;
} lowasctbl[32] = {
{ 160 ,"nbsp" }, /* NULL non-breaking space */
{ 9786 ,NULL }, /* white smiling face */
{ 9787 ,NULL }, /* black smiling face */
{ 9829 ,"hearts" }, /* black heart suit */
{ 9830 ,"diams" }, /* black diamond suit */
{ 9827 ,"clubs" }, /* black club suit */
{ 9824 ,"spades" }, /* black spade suit */
{ 8226 ,"bull" }, /* bullet */
{ 9688 ,NULL }, /* inverse bullet */
{ 9702 ,NULL }, /* white bullet */
{ 9689 ,NULL }, /* inverse white circle */
{ 9794 ,NULL }, /* male sign */
{ 9792 ,NULL }, /* female sign */
{ 9834 ,NULL }, /* eighth note */
{ 9835 ,NULL }, /* beamed eighth notes */
{ 9788 ,NULL }, /* white sun with rays */
{ 9654 ,NULL }, /* black right-pointing triangle */
{ 9664 ,NULL }, /* black left-pointing triangle */
{ 8597 ,NULL }, /* up down arrow */
{ 8252 ,NULL }, /* double exclamation mark */
{ 182 ,"para" }, /* pilcrow sign */
{ 167 ,"sect" }, /* section sign */
{ 9644 ,NULL }, /* black rectangle */
{ 8616 ,NULL }, /* up down arrow with base */
{ 8593 ,"uarr" }, /* upwards arrow */
{ 8595 ,"darr" }, /* downwards arrow */
{ 8594 ,"rarr" }, /* rightwards arrow */
{ 8592 ,"larr" }, /* leftwards arrow */
{ 8985 ,NULL }, /* turned not sign */
{ 8596 ,"harr" }, /* left right arrow */
{ 9650 ,NULL }, /* black up-pointing triangle */
{ 9660 ,NULL } /* black down-pointing triangle */
};
static JSBool
js_html_encode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int ch;
ulong i,j;
uchar* inbuf;
uchar* tmpbuf;
uchar* outbuf;
uchar* param;
char* lastparam;
JSBool exascii=JS_TRUE;
JSBool wsp=JS_TRUE;
JSBool ansi=JS_TRUE;
JSBool ctrl_a=JS_TRUE;
JSString* js_str;
int32 fg=7;
int32 bg=0;
JSBool blink=FALSE;
JSBool bold=FALSE;
int esccount=0;
char ansi_seq[MAX_ANSI_SEQ+1];
int ansi_param[MAX_ANSI_PARAMS];
int k,l;
ulong savepos=0;
int32 hpos=0;
int32 currrow=0;
int savehpos=0;
int savevpos=0;
int32 wraphpos=-2;
int32 wrapvpos=-2;
int32 wrappos=0;
BOOL extchar=FALSE;
ulong obsize;
int32 lastcolor=7;
char tmp1[128];
struct tm tm;
time_t now;
BOOL nodisplay=FALSE;
private_t* p;
uchar attr_stack[64]; /* Saved attributes (stack) */
int attr_sp=0; /* Attribute stack pointer */
ulong clear_screen=0;
JSObject* stateobj=NULL;
jsval val;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) /* Will this work? Ask DM */
return(JS_FALSE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
exascii=JSVAL_TO_BOOLEAN(argv[1]);
if(argc>2 && JSVAL_IS_BOOLEAN(argv[2]))
wsp=JSVAL_TO_BOOLEAN(argv[2]);
if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
ansi=JSVAL_TO_BOOLEAN(argv[3]);
if(argc>4 && JSVAL_IS_BOOLEAN(argv[4]))
{
ctrl_a=JSVAL_TO_BOOLEAN(argv[4]);
if(ctrl_a)
ansi=ctrl_a;
}
if(argc>5 && JSVAL_IS_OBJECT(argv[5])) {
stateobj=JSVAL_TO_OBJECT(argv[5]);
JS_GetProperty(cx,stateobj,"fg",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &fg);
JS_GetProperty(cx,stateobj,"bg",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &bg);
JS_GetProperty(cx,stateobj,"lastcolor",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &lastcolor);
JS_GetProperty(cx,stateobj,"blink",&val);
if(JSVAL_IS_BOOLEAN(val))
fg=JS_ValueToBoolean(cx, val, &blink);
JS_GetProperty(cx,stateobj,"bold",&val);
if(JSVAL_IS_BOOLEAN(val))
fg=JS_ValueToBoolean(cx, val, &bold);
JS_GetProperty(cx,stateobj,"hpos",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &hpos);
JS_GetProperty(cx,stateobj,"currrow",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &currrow);
JS_GetProperty(cx,stateobj,"wraphpos",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &wraphpos);
JS_GetProperty(cx,stateobj,"wrapvpos",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &wrapvpos);
JS_GetProperty(cx,stateobj,"wrappos",&val);
if(JSVAL_IS_NUMBER(val))
fg=JS_ValueToInt32(cx, val, &wrappos);
}
if((tmpbuf=(char*)malloc((strlen(inbuf)*10)+1))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
for(i=j=0;inbuf[i];i++) {
switch(inbuf[i]) {
case TAB:
case LF:
case CR:
if(wsp)
j+=sprintf(tmpbuf+j,"&#%u;",inbuf[i]);
else
tmpbuf[j++]=inbuf[i];
break;
case '"':
j+=sprintf(tmpbuf+j,""");
break;
case '&':
j+=sprintf(tmpbuf+j,"&");
break;
case '<':
j+=sprintf(tmpbuf+j,"<");
break;
case '>':
j+=sprintf(tmpbuf+j,">");
break;
case '\b':
j--;
break;
default:
if(inbuf[i]&0x80) {
if(exascii) {
ch=inbuf[i]^0x80;
if(exasctbl[ch].name!=NULL)
j+=sprintf(tmpbuf+j,"&%s;",exasctbl[ch].name);
else
j+=sprintf(tmpbuf+j,"&#%u;",exasctbl[ch].value);
} else
tmpbuf[j++]=inbuf[i];
}
else if(inbuf[i]>=' ' && inbuf[i]<DEL)
tmpbuf[j++]=inbuf[i];
#if 0 /* ASCII 127 - Not displayed? */
else if(inbuf[i]==DEL && exascii)
j+=sprintf(tmpbuf+j,"⌂",exasctbl[ch].value);
#endif
else if(inbuf[i]<' ') /* unknown control chars */
{
if(ansi && inbuf[i]==ESC)
{
esccount++;
tmpbuf[j++]=inbuf[i];
}
else if(ctrl_a && inbuf[i]==1)
{
esccount++;
tmpbuf[j++]=inbuf[i];
tmpbuf[j++]=inbuf[++i];
}
else if(exascii) {
ch=inbuf[i];
if(lowasctbl[ch].name!=NULL)
j+=sprintf(tmpbuf+j,"&%s;",lowasctbl[ch].name);
else
j+=sprintf(tmpbuf+j,"&#%u;",lowasctbl[ch].value);
} else
j+=sprintf(tmpbuf+j,"&#%u;",inbuf[i]);
}
break;
}
}
tmpbuf[j]=0;
if(ansi)
{
obsize=(strlen(tmpbuf)+(esccount+1)*MAX_COLOR_STRING)+1;
if(obsize<2048)
obsize=2048;
if((outbuf=(uchar*)malloc(obsize))==NULL)
{
free(tmpbuf);
rc=JS_SuspendRequest(cx);
return(JS_FALSE);
}
j=sprintf(outbuf,"<span style=\"%s\">",htmlansi[7]);
clear_screen=j;
for(i=0;tmpbuf[i];i++) {
if(j>(obsize/2)) /* Completely arbitrary here... must be carefull with this eventually ToDo */
{
obsize+=(obsize/2);
if((param=realloc(outbuf,obsize))==NULL)
{
free(tmpbuf);
free(outbuf);
rc=JS_SuspendRequest(cx);
return(JS_FALSE);
}
outbuf=param;
}
if(tmpbuf[i]==ESC && tmpbuf[i+1]=='[')
{
if(nodisplay)
continue;
k=0;
memset(&ansi_param,0xff,sizeof(int)*MAX_ANSI_PARAMS);
strncpy(ansi_seq, tmpbuf+i+2, MAX_ANSI_SEQ);
ansi_seq[MAX_ANSI_SEQ]=0;
for(lastparam=ansi_seq;*lastparam;lastparam++)
{
if(isalpha(*lastparam))
{
*(++lastparam)=0;
break;
}
}
k=0;
param=ansi_seq;
if(*param=='?') /* This is to fix ESC[?7 whatever that is */
param++;
if(isdigit(*param))
ansi_param[k++]=atoi(ansi_seq);
while(isspace(*param) || isdigit(*param))
param++;
lastparam=param;
while((param=strchr(param,';'))!=NULL)
{
param++;
ansi_param[k++]=atoi(param);
while(isspace(*param) || isdigit(*param))
param++;
lastparam=param;
}
switch(*lastparam)
{
case 'm': /* Colour */
for(k=0;ansi_param[k]>=0;k++)
{
switch(ansi_param[k])
{
case 0:
fg=7;
bg=0;
blink=FALSE;
bold=FALSE;
break;
case 1:
bold=TRUE;
break;
case 2:
bold=FALSE;
break;
case 5:
blink=TRUE;
break;
case 6:
blink=TRUE;
break;
case 7:
l=fg;
fg=bg;
bg=l;
break;
case 8:
fg=bg;
blink=FALSE;
bold=FALSE;
break;
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
fg=ansi_param[k]-30;
break;
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
bg=ansi_param[k]-40;
break;
}
}
break;
case 'C': /* Move right */
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
l=ansi_param[0]>0?ansi_param[0]:1;
if(wrappos==0 && wrapvpos==currrow) {
/* j+=sprintf(outbuf+j,"<!-- \r\nC after A l=%d hpos=%d -->",l,hpos); */
l=l-hpos;
wrapvpos=-2; /* Prevent additional move right */
}
if(l>81-hpos)
l=81-hpos;
for(k=0; k<l; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
hpos++;
}
break;
case 's': /* Save position */
savepos=j;
savehpos=hpos;
savevpos=currrow;
break;
case 'u': /* Restore saved position */
j=savepos;
hpos=savehpos;
currrow=savevpos;
break;
case 'H': /* Move */
k=ansi_param[0];
if(k<=0)
k=1;
k--;
l=ansi_param[1];
if(l<=0)
l=1;
l--;
while(k>currrow)
{
hpos=0;
currrow++;
outbuf[j++]='\r';
outbuf[j++]='\n';
}
if(l>hpos)
{
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
while(l>hpos)
{
j+=sprintf(outbuf+j,"%s"," ");
hpos++;
}
}
break;
case 'B': /* Move down */
l=ansi_param[0];
if(l<=0)
l=1;
for(k=0; k < l; k++)
{
currrow++;
outbuf[j++]='\r';
outbuf[j++]='\n';
}
if(hpos!=0 && tmpbuf[i+1]!=CR)
{
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
for(k=0; k<hpos ; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
}
break;
}
break;
case 'A': /* Move up */
l=wrappos;
if(j > (ulong)wrappos && hpos==0 && currrow==wrapvpos+1 && ansi_param[0]<=1) {
hpos=wraphpos;
currrow=wrapvpos;
j=wrappos;
wrappos=0; /* Prevent additional move up */
}
break;
case 'J': /* Clear */
if(ansi_param[0]==2) {
j=clear_screen;
hpos=0;
currrow=0;
wraphpos=-2;
wrapvpos=-2;
wrappos=0;
}
break;
}
i+=(int)(lastparam-ansi_seq)+2;
}
else if(ctrl_a && tmpbuf[i]==1) /* CTRL-A codes */
{
/* j+=sprintf(outbuf+j,"<!-- CTRL-A-%c (%u) -->",tmpbuf[i+1],tmpbuf[i+1]); */
if(nodisplay && tmpbuf[i+1] != ')')
continue;
if(tmpbuf[i+1]>0x7f)
{
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
l=tmpbuf[i+1]-0x7f;
if(l>81-hpos)
l=81-hpos;
for(k=0; k<l; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
hpos++;
}
}
else switch(toupper(tmpbuf[i+1]))
{
case 'K':
fg=0;
break;
case 'R':
fg=1;
break;
case 'G':
fg=2;
break;
case 'Y':
fg=3;
break;
case 'B':
fg=4;
break;
case 'M':
fg=5;
break;
case 'C':
fg=6;
break;
case 'W':
fg=7;
break;
case '0':
bg=0;
break;
case '1':
bg=1;
break;
case '2':
bg=2;
break;
case '3':
bg=3;
break;
case '4':
bg=4;
break;
case '5':
bg=5;
break;
case '6':
bg=6;
break;
case '7':
bg=7;
break;
case 'H':
bold=TRUE;
break;
case 'I':
blink=TRUE;
break;
case '+':
if(attr_sp<(int)sizeof(attr_stack))
attr_stack[attr_sp++]=(blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | (int)fg;
break;
case '-':
if(attr_sp>0)
{
blink=(attr_stack[--attr_sp]&(1<<7))?TRUE:FALSE;
bg=(attr_stack[attr_sp] >> 4) & 7;
blink=(attr_stack[attr_sp]&(1<<3))?TRUE:FALSE;
fg=attr_stack[attr_sp] & 7;
}
else if(bold || blink || bg)
{
bold=FALSE;
blink=FALSE;
fg=7;
bg=0;
}
break;
case '_':
if(blink || bg)
{
bold=FALSE;
blink=FALSE;
fg=7;
bg=0;
}
break;
case 'N':
bold=FALSE;
blink=FALSE;
fg=7;
bg=0;
break;
case 'P':
case 'Q':
case ',':
case ';':
case '.':
case 'S':
case '>':
case '<':
break;
case '!': /* This needs to be fixed! (Somehow) */
case '@':
case '#':
case '$':
case '%':
case '^':
case '&':
case '*':
case '(':
nodisplay=TRUE;
break;
case ')':
nodisplay=FALSE;
break;
case 'D':
now=time(NULL);
j+=sprintf(outbuf+j,"%s",unixtodstr(p->cfg,now,tmp1));
break;
case 'T':
now=time(NULL);
localtime_r(&now,&tm);
j+=sprintf(outbuf+j,"%02d:%02d %s"
,tm.tm_hour==0 ? 12
: tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
break;
case 'L':
currrow=0;
hpos=0;
outbuf[j++]='\r';
outbuf[j++]='\n';
break;
case ']':
currrow++;
if(hpos!=0 && tmpbuf[i+2]!=CR && !(tmpbuf[i+2]==1 && tmpbuf[i+3]=='['))
{
outbuf[j++]='\r';
outbuf[j++]='\n';
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
for(k=0; k<hpos ; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
}
break;
}
outbuf[j++]='\n';
break;
case '[':
outbuf[j++]='\r';
hpos=0;
break;
case 'Z':
outbuf[j++]=0;
break;
case 'A':
default:
if(exascii) {
ch=tmpbuf[i];
if(lowasctbl[ch].name!=NULL)
j+=sprintf(outbuf+j,"&%s;",lowasctbl[ch].name);
else
j+=sprintf(outbuf+j,"&#%u;",lowasctbl[ch].value);
} else
j+=sprintf(outbuf+j,"&#%u;",inbuf[i]);
i--;
}
i++;
}
else
{
if(nodisplay)
continue;
switch(tmpbuf[i])
{
case TAB: /* This assumes that tabs do NOT use the current background. */
l=hpos%8;
if(l==0)
l=8;
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
for(k=0; k<l ; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
hpos++;
}
break;
case LF:
wrapvpos=currrow;
if((ulong)wrappos<j-3)
wrappos=j;
currrow++;
if(hpos!=0 && tmpbuf[i+1]!=CR)
{
outbuf[j++]='\r';
outbuf[j++]='\n';
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
lastcolor=0;
for(k=0; k<hpos ; k++)
{
j+=sprintf(outbuf+j,"%s"," ");
}
break;
}
case CR:
if(wraphpos==-2 || hpos!=0)
wraphpos=hpos;
if((ulong)wrappos<j-3)
wrappos=j;
outbuf[j++]=tmpbuf[i];
hpos=0;
break;
default:
if(lastcolor != ((blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | fg))
{
lastcolor=(blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | fg;
j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[lastcolor],HTML_COLOR_SUFFIX);
}
outbuf[j++]=tmpbuf[i];
if(tmpbuf[i]=='&')
extchar=TRUE;
if(tmpbuf[i]==';')
extchar=FALSE;
if(!extchar)
hpos++;
/* ToDo: Fix hard-coded terminal window width (80) */
if(hpos>=80 && tmpbuf[i+1] != '\r' && tmpbuf[i+1] != '\n' && tmpbuf[i+1] != ESC)
{
wrapvpos=-2;
wraphpos=-2;
wrappos=0;
hpos=0;
currrow++;
outbuf[j++]='\r';
outbuf[j++]='\n';
}
}
}
}
strcpy(outbuf+j,"</span>");
rc=JS_SuspendRequest(cx);
js_str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
}
else {
rc=JS_SuspendRequest(cx);
js_str = JS_NewStringCopyZ(cx, tmpbuf);
}
free(tmpbuf); /* assertion here, Feb-20-2006 */
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
if(stateobj!=NULL) {
JS_DefineProperty(cx, stateobj, "fg", INT_TO_JSVAL(fg)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "bg", INT_TO_JSVAL(bg)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "lastcolor", INT_TO_JSVAL(lastcolor)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "blink", BOOLEAN_TO_JSVAL(blink)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "bold", BOOLEAN_TO_JSVAL(bold)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "hpos", INT_TO_JSVAL(hpos)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "currrow", INT_TO_JSVAL(currrow)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "wraphpos", INT_TO_JSVAL(wraphpos)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "wrapvpos", INT_TO_JSVAL(wrapvpos)
,NULL,NULL,JSPROP_ENUMERATE);
JS_DefineProperty(cx, stateobj, "wrappos", INT_TO_JSVAL(wrappos)
,NULL,NULL,JSPROP_ENUMERATE);
}
return(JS_TRUE);
}
static JSBool
js_html_decode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int ch;
int val;
ulong i,j;
uchar* inbuf;
uchar* outbuf;
char token[16];
size_t t;
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((outbuf=(char*)malloc(strlen(inbuf)+1))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
for(i=j=0;inbuf[i];i++) {
if(inbuf[i]!='&') {
outbuf[j++]=inbuf[i];
continue;
}
for(i++,t=0; inbuf[i]!=0 && inbuf[i]!=';' && t<sizeof(token)-1; i++, t++)
token[t]=inbuf[i];
if(inbuf[i]==0)
break;
token[t]=0;
/* First search the ex-ascii table for a name match */
for(ch=0;ch<128;ch++)
if(exasctbl[ch].name!=NULL && strcmp(token,exasctbl[ch].name)==0)
break;
if(ch<128) {
outbuf[j++]=ch|0x80;
continue;
}
if(token[0]=='#') { /* numeric constant */
val=atoi(token+1);
/* search ex-ascii table for a value match */
for(ch=0;ch<128;ch++)
if(exasctbl[ch].value==val)
break;
if(ch<128) {
outbuf[j++]=ch|0x80;
continue;
}
if((val>=' ' && val<=0xff) || val=='\r' || val=='\n' || val=='\t') {
outbuf[j++]=val;
continue;
}
}
if(strcmp(token,"quot")==0) {
outbuf[j++]='"';
continue;
}
if(strcmp(token,"amp")==0) {
outbuf[j++]='&';
continue;
}
if(strcmp(token,"lt")==0) {
outbuf[j++]='<';
continue;
}
if(strcmp(token,"gt")==0) {
outbuf[j++]='>';
continue;
}
if(strcmp(token,"curren")==0) {
outbuf[j++]=CTRL_O;
continue;
}
if(strcmp(token,"para")==0) {
outbuf[j++]=CTRL_T;
continue;
}
if(strcmp(token,"sect")==0) {
outbuf[j++]=CTRL_U;
continue;
}
/* Unknown character entity, leave intact */
j+=sprintf(outbuf+j,"&%s;",token);
}
outbuf[j]=0;
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_b64_encode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int res;
size_t len;
size_t inbuf_len;
uchar* inbuf;
uchar* outbuf;
JSString* js_str;
jsrefcount rc;
*rval = JSVAL_NULL;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], &inbuf_len))==NULL)
return(JS_FALSE);
len=(inbuf_len*10)+1;
if((outbuf=(char*)malloc(len))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
res=b64_encode(outbuf,len,inbuf,inbuf_len);
JS_ResumeRequest(cx, rc);
if(res<1) {
free(outbuf);
return(JS_TRUE);
}
js_str = JS_NewStringCopyZ(cx, outbuf);
free(outbuf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_b64_decode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int res;
size_t len;
uchar* inbuf;
uchar* outbuf;
JSString* js_str;
jsrefcount rc;
*rval = JSVAL_NULL;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
len=strlen(inbuf)+1;
if((outbuf=(char*)malloc(len))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
res=b64_decode(outbuf,len,inbuf,strlen(inbuf));
JS_ResumeRequest(cx, rc);
if(res<1) {
free(outbuf);
return(JS_TRUE);
}
js_str = JS_NewStringCopyN(cx, outbuf, res);
free(outbuf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_md5_calc(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
{
BYTE digest[MD5_DIGEST_SIZE];
JSBool hex=JS_FALSE;
size_t inbuf_len;
char* inbuf;
char outbuf[64];
JSString* js_str;
jsrefcount rc;
*rval = JSVAL_NULL;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((inbuf=js_ValueToStringBytes(cx, argv[0], &inbuf_len))==NULL)
return(JS_FALSE);
if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
hex=JSVAL_TO_BOOLEAN(argv[1]);
rc=JS_SuspendRequest(cx);
MD5_calc(digest,inbuf,inbuf_len);
if(hex)
MD5_hex(outbuf,digest);
else
b64_encode(outbuf,sizeof(outbuf),digest,sizeof(digest));
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, outbuf);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_skipsp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
js_str = JS_NewStringCopyZ(cx, skipsp(str));
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_truncsp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* str;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((p=strdup(str))==NULL)
return(JS_FALSE);
truncsp(p);
js_str = JS_NewStringCopyZ(cx, p);
free(p);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_truncstr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char* str;
char* set;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((set=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
return(JS_FALSE);
if((p=strdup(str))==NULL)
return(JS_FALSE);
truncstr(p,set);
js_str = JS_NewStringCopyZ(cx, p);
free(p);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_backslash(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char path[MAX_PATH+1];
char* str;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
SAFECOPY(path,str);
backslash(path);
if((js_str = JS_NewStringCopyZ(cx, path))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_fullpath(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char path[MAX_PATH+1];
char* str;
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
SAFECOPY(path,str);
rc=JS_SuspendRequest(cx);
_fullpath(path, str, sizeof(path));
JS_ResumeRequest(cx, rc);
if((js_str = JS_NewStringCopyZ(cx, path))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_getfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
js_str = JS_NewStringCopyZ(cx, getfname(str));
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_getfext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
char* p;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((p=getfext(str))==NULL)
return(JS_TRUE);
js_str = JS_NewStringCopyZ(cx, p);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_getfcase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
char path[MAX_PATH+1];
JSString* js_str;
jsrefcount rc;
rc=JS_SuspendRequest(cx);
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
SAFECOPY(path,str);
rc=JS_SuspendRequest(cx);
if(fexistcase(path)) {
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, path);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
}
else
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_dosfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* str;
char path[MAX_PATH+1];
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
#if defined(_WIN32)
if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
if(GetShortPathName(str,path,sizeof(path))) {
JS_ResumeRequest(cx, rc);
js_str = JS_NewStringCopyZ(cx, path);
if(js_str==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
}
else
JS_ResumeRequest(cx, rc);
#else /* No non-Windows equivalent */
*rval = argv[0];
#endif
return(JS_TRUE);
}
static JSBool
js_cfgfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* path;
char* fname;
char result[MAX_PATH+1];
char* cstr;
jsrefcount rc;
rc=JS_SuspendRequest(cx);
JS_ResumeRequest(cx, rc);
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((path=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if((fname=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
cstr = iniFileName(result,sizeof(result),path,fname);
JS_ResumeRequest(cx, rc);
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,cstr));
return(JS_TRUE);
}
static JSBool
js_fexist(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(fexist(p));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_removecase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(removecase(p)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(remove(p)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_rename(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* oldname;
char* newname;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
if((oldname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_TRUE);
if((newname=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
return(JS_TRUE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(rename(oldname,newname)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_fcopy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* src;
char* dest;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
if((src=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_TRUE);
if((dest=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
return(JS_TRUE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(fcopy(src,dest));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_fcompare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* fn1;
char* fn2;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
if((fn1=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_TRUE);
if((fn2=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
return(JS_TRUE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(fcompare(fn1,fn2));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_backup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* fname;
int32 level=5;
BOOL ren=FALSE;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_TRUE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&level);
if(argc>2)
JS_ValueToBoolean(cx,argv[2],&ren);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(backup(fname,level,ren));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_isdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(isdir(p));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_fattr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
int attr;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
attr=getfattr(p);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,attr,rval);
return(JS_TRUE);
}
static JSBool
js_fdate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
time_t fd;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
fd=fdate(p);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,fd,rval);
return(JS_TRUE);
}
static JSBool
js_utime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* fname;
int32 actime;
int32 modtime;
struct utimbuf ut;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = JSVAL_FALSE;
if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
/* use current time as default */
ut.actime = ut.modtime = time(NULL);
if(argc>1) {
actime=modtime=ut.actime;
JS_ValueToInt32(cx,argv[1],&actime);
JS_ValueToInt32(cx,argv[2],&modtime);
ut.actime=actime;
ut.modtime=modtime;
}
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(utime(fname,&ut)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_flength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
long fl;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
fl=flength(p);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,fl,rval);
return(JS_TRUE);
}
static JSBool
js_ftouch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* fname;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(ftouch(fname));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_fmutex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* fname;
char* text=NULL;
int32 max_age=0;
uintN argn=0;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((fname=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
return(JS_FALSE);
if(argc > argn && JSVAL_IS_STRING(argv[argn]))
text=js_ValueToStringBytes(cx, argv[argn++], NULL);
if(argc > argn && JSVAL_IS_NUMBER(argv[argn]))
JS_ValueToInt32(cx, argv[argn++], &max_age);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(fmutex(fname,text,max_age));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_sound(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(!argc) { /* Stop playing sound */
#ifdef _WIN32
PlaySound(NULL,NULL,0);
#endif
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
return(JS_TRUE);
}
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
#ifdef _WIN32
*rval = BOOLEAN_TO_JSVAL(PlaySound(p, NULL, SND_ASYNC|SND_FILENAME));
#else
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
#endif
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_directory(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int i;
int32 flags=GLOB_MARK;
char* p;
glob_t g;
JSObject* array;
JSString* js_str;
jsint len=0;
jsval val;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
*rval = JSVAL_NULL;
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&flags);
if((array = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
glob(p,flags,NULL,&g);
JS_ResumeRequest(cx, rc);
for(i=0;i<(int)g.gl_pathc;i++) {
if((js_str=JS_NewStringCopyZ(cx,g.gl_pathv[i]))==NULL)
break;
val=STRING_TO_JSVAL(js_str);
if(!JS_SetElement(cx, array, len++, &val))
break;
}
rc=JS_SuspendRequest(cx);
globfree(&g);
JS_ResumeRequest(cx, rc);
*rval = OBJECT_TO_JSVAL(array);
return(JS_TRUE);
}
static JSBool
js_wildmatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
BOOL case_sensitive=FALSE;
BOOL path=FALSE;
char* fname;
char* spec="*";
uintN argn=0;
jsrefcount rc;
if(JSVAL_IS_BOOLEAN(argv[argn]))
JS_ValueToBoolean(cx, argv[argn++], &case_sensitive);
if((fname=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
return(JS_FALSE);
if(argn<argc && argv[argn]!=JSVAL_VOID)
if((spec=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
return(JS_FALSE);
if(argn<argc && argv[argn]!=JSVAL_VOID)
JS_ValueToBoolean(cx, argv[argn++], &path);
rc=JS_SuspendRequest(cx);
if(case_sensitive)
*rval = BOOLEAN_TO_JSVAL(wildmatch(fname, spec, path));
else
*rval = BOOLEAN_TO_JSVAL(wildmatchi(fname, spec, path));
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_freediskspace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 unit=0;
char* p;
ulong fd;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&unit);
rc=JS_SuspendRequest(cx);
fd=getfreediskspace(p,unit);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,fd,rval);
return(JS_TRUE);
}
static JSBool
js_disksize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
int32 unit=0;
char* p;
ulong ds;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&unit);
rc=JS_SuspendRequest(cx);
ds=getdisksize(p,unit);
JS_ResumeRequest(cx, rc);
JS_NewNumberValue(cx,ds,rval);
return(JS_TRUE);
}
static JSBool
js_socket_select(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSObject* inarray=NULL;
JSObject* rarray;
BOOL poll_for_write=FALSE;
fd_set socket_set;
fd_set* rd_set=NULL;
fd_set* wr_set=NULL;
uintN argn;
SOCKET sock;
SOCKET maxsock=0;
struct timeval tv = {0, 0};
jsuint i;
jsuint limit;
SOCKET* index;
jsval val;
int len=0;
jsrefcount rc;
*rval = JSVAL_NULL;
for(argn=0;argn<argc;argn++) {
if(JSVAL_IS_BOOLEAN(argv[argn]))
poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
else if(JSVAL_IS_OBJECT(argv[argn]))
inarray = JSVAL_TO_OBJECT(argv[argn]);
else if(JSVAL_IS_NUMBER(argv[argn]))
js_timeval(cx,argv[argn],&tv);
}
if(inarray==NULL || !JS_IsArrayObject(cx, inarray))
return(JS_TRUE); /* This not a fatal error */
if(!JS_GetArrayLength(cx, inarray, &limit))
return(JS_TRUE);
/* Return array */
if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
if((index=(SOCKET *)alloca(sizeof(SOCKET)*limit))==NULL)
return(JS_FALSE);
FD_ZERO(&socket_set);
if(poll_for_write)
wr_set=&socket_set;
else
rd_set=&socket_set;
for(i=0;i<limit;i++) {
if(!JS_GetElement(cx, inarray, i, &val))
break;
sock=js_socket(cx,val);
index[i]=sock;
if(sock!=INVALID_SOCKET) {
FD_SET(sock,&socket_set);
if(sock>maxsock)
maxsock=sock;
}
}
rc=JS_SuspendRequest(cx);
if(select(maxsock+1,rd_set,wr_set,NULL,&tv) >= 0) {
for(i=0;i<limit;i++) {
if(index[i]!=INVALID_SOCKET && FD_ISSET(index[i],&socket_set)) {
val=INT_TO_JSVAL(i);
JS_ResumeRequest(cx, rc);
if(!JS_SetElement(cx, rarray, len++, &val)) {
rc=JS_SuspendRequest(cx);
break;
}
rc=JS_SuspendRequest(cx);
}
}
*rval = OBJECT_TO_JSVAL(rarray);
}
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(MKDIR(p)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_mkpath(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(mkpath(p)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_rmdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
*rval = BOOLEAN_TO_JSVAL(rmdir(p)==0);
JS_ResumeRequest(cx, rc);
return(JS_TRUE);
}
static JSBool
js_strftime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char str[128];
char* fmt;
int32 i=time(NULL);
time_t t;
struct tm tm;
JSString* js_str;
jsrefcount rc;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((fmt=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
if(argc>1)
JS_ValueToInt32(cx,argv[1],&i);
rc=JS_SuspendRequest(cx);
strcpy(str,"-Invalid time-");
t=i;
if(localtime_r(&t,&tm)==NULL)
memset(&tm,0,sizeof(tm));
strftime(str,sizeof(str),fmt,&tm);
JS_ResumeRequest(cx, rc);
if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static JSBool
js_resolve_ip(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct in_addr addr;
JSString* str;
char* p;
jsrefcount rc;
*rval = JSVAL_NULL;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
if((addr.s_addr=resolve_ip(p))==INADDR_NONE)
return(JS_TRUE);
JS_ResumeRequest(cx, rc);
if((str=JS_NewStringCopyZ(cx, inet_ntoa(addr)))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(str);
return(JS_TRUE);
}
static JSBool
js_resolve_host(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct in_addr addr;
HOSTENT* h;
char* p;
jsrefcount rc;
*rval = JSVAL_NULL;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
addr.s_addr=inet_addr(p);
h=gethostbyaddr((char *)&addr,sizeof(addr),AF_INET);
JS_ResumeRequest(cx, rc);
if(h!=NULL && h->h_name!=NULL)
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,h->h_name));
return(JS_TRUE);
}
extern link_list_t named_queues; /* js_queue.c */
static JSBool
js_list_named_queues(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSObject* array;
jsint len=0;
jsval val;
list_node_t* node;
msg_queue_t* q;
jsrefcount rc;
if((array = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
rc=JS_SuspendRequest(cx);
for(node=listFirstNode(&named_queues);node!=NULL;node=listNextNode(node)) {
if((q=listNodeData(node))==NULL)
continue;
JS_ResumeRequest(cx, rc);
val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,q->name));
if(!JS_SetElement(cx, array, len++, &val)) {
rc=JS_SuspendRequest(cx);
break;
}
rc=JS_SuspendRequest(cx);
}
JS_ResumeRequest(cx, rc);
*rval = OBJECT_TO_JSVAL(array);
return(JS_TRUE);
}
static JSBool
js_flags_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* p;
char str[64];
jsdouble d;
JSString* js_str;
if(JSVAL_IS_VOID(argv[0]))
return(JS_TRUE);
if(JSVAL_IS_STRING(argv[0])) { /* string to long */
if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
return(JS_FALSE);
JS_NewNumberValue(cx,aftol(p),rval);
return(JS_TRUE);
}
/* number to string */
JS_ValueToNumber(cx,argv[0],&d);
if((js_str = JS_NewStringCopyZ(cx, ltoaf((long)d,str)))==NULL)
return(JS_FALSE);
*rval = STRING_TO_JSVAL(js_str);
return(JS_TRUE);
}
static jsSyncMethodSpec js_global_functions[] = {
{"exit", js_exit, 0, JSTYPE_VOID, "[exit_code]"
,JSDOCSTR("stop script execution, "
"optionally setting the global property <tt>exit_code</tt> to the specified numeric value")
,311
},
{"load", js_load, 1, JSTYPE_UNDEF
,JSDOCSTR("[<i>bool</i> background or <i>object</i> scope,] <i>string</i> filename [,args]")
,JSDOCSTR("load and execute a JavaScript module (<i>filename</i>), "
"optionally specifying a target <i>scope</i> object (default: <i>this</i>) "
"and a list of arguments to pass to the module (as <i>argv</i>). "
"Returns the result (last executed statement) of the executed script "
"or a newly created <i>Queue</i> object if <i>background</i> is <i>true</i>).<br><br>"
"<b>Background</b> (added in v3.12):<br>"
"If <i>background</i> is <i>true</i>, the loaded script runs in the background "
"(in a child thread) but may communicate with the parent "
"script/thread by reading from and/or writing to the <i>parent_queue</i> "
"(an automatically created <i>Queue</i> object). "
"The result (last executed statement) of the executed script "
"(or the optional <i>exit_code</i> passed to the <i>exit()/<i> function) "
"will be automatically written to the <i>parent_queue</i> "
"which may be read later by the parent script (using <i>load_result.read()</i>, for example).")
,312
},
{"sleep", js_mswait, 0, JSTYPE_ALIAS },
{"mswait", js_mswait, 0, JSTYPE_NUMBER, JSDOCSTR("[milliseconds=<tt>1</tt>]")
,JSDOCSTR("millisecond wait/sleep routine (AKA sleep), returns number of elapsed clock ticks (in v3.13)")
,313
},
{"yield", js_yield, 0, JSTYPE_VOID, JSDOCSTR("[forced=<tt>true</tt>]")
,JSDOCSTR("release current thread time-slice, "
"a <i>forced</i> yield will yield to all other pending tasks (lowering CPU utilization), "
"a non-<i>forced</i> yield will yield only to pending tasks of equal or higher priority. "
"<i>forced</i> defaults to <i>true</i>")
,311
},
{"random", js_random, 1, JSTYPE_NUMBER, JSDOCSTR("max_number=<tt>100</tt>")
,JSDOCSTR("return random integer between <tt>0</tt> and <i>max_number</i>-1")
,310
},
{"time", js_time, 0, JSTYPE_NUMBER, ""
,JSDOCSTR("return current time and date in Unix (time_t) format "
"(number of seconds since Jan-01-1970)")
,310
},
{"beep", js_beep, 0, JSTYPE_VOID, JSDOCSTR("[frequency=<tt>500</tt>] [,duration=<tt>500</tt>]")
,JSDOCSTR("produce a tone on the local speaker at specified frequency for specified duration (in milliseconds)")
,310
},
{"sound", js_sound, 0, JSTYPE_BOOLEAN, JSDOCSTR("[filename]")
,JSDOCSTR("play a waveform (.wav) sound file (currently, on Windows platforms only)")
,310
},
{"ctrl", js_ctrl, 1, JSTYPE_STRING, JSDOCSTR("number or string")
,JSDOCSTR("return ASCII control character representing character passed - Example: <tt>ctrl('C') returns '\3'</tt>")
,311
},
{"ascii", js_ascii, 1, JSTYPE_UNDEF, JSDOCSTR("[string text] or [number value]")
,JSDOCSTR("convert single character to numeric ASCII value or vice-versa (returns number OR string)")
,310
},
{"ascii_str", js_ascii_str, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("convert extended-ASCII in text string to plain ASCII, returns modified string")
,310
},
{"strip_ctrl", js_strip_ctrl, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("strip control characters from string, returns modified string")
,310
},
{"strip_exascii", js_strip_exascii, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("strip extended-ASCII characters from string, returns modified string")
,310
},
{"skipsp", js_skipsp, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("skip (trim) white-space characters off <b>beginning</b> of string, returns modified string")
,315
},
{"truncsp", js_truncsp, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("truncate (trim) white-space characters off <b>end</b> of string, returns modified string")
,310
},
{"truncstr", js_truncstr, 2, JSTYPE_STRING, JSDOCSTR("text, charset")
,JSDOCSTR("truncate (trim) string at first char in <i>charset</i>, returns modified string")
,310
},
{"lfexpand", js_lfexpand, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("expand line-feeds (LF) to carriage-return/line-feeds (CRLF), returns modified string")
,310
},
{"wildmatch", js_wildmatch, 2, JSTYPE_BOOLEAN, JSDOCSTR("[case_sensitive=<tt>false</tt>,] string [,pattern=<tt>'*'</tt>] [,path=<tt>false</tt>]")
,JSDOCSTR("returns <tt>true</tt> if the <i>string</i> matches the wildcard <i>pattern</i> (wildcards supported are '*' and '?'), "
"if <i>path</i> is <tt>true</tt>, '*' will not match path delimeter characters (e.g. '/')")
,314
},
{"backslash", js_backslash, 1, JSTYPE_STRING, JSDOCSTR("path")
,JSDOCSTR("returns directory path with trailing (platform-specific) path delimeter "
"(i.e. \"slash\" or \"backslash\")")
,312
},
{"fullpath", js_fullpath, 1, JSTYPE_STRING, JSDOCSTR("path")
,JSDOCSTR("Creates an absolute or full path name for the specified relative path name.")
,315
},
{"file_getname", js_getfname, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
,JSDOCSTR("returns filename portion of passed path string")
,311
},
{"file_getext", js_getfext, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
,JSDOCSTR("returns file extension portion of passed path/filename string (including '.') "
"or <i>undefined</i> if no extension is found")
,311
},
{"file_getcase", js_getfcase, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
,JSDOCSTR("returns correct case of filename (long version of filename on Windows) "
"or <i>undefined</i> if the file doesn't exist")
,311
},
{"file_cfgname", js_cfgfname, 2, JSTYPE_STRING, JSDOCSTR("path, filename")
,JSDOCSTR("returns completed configuration filename from supplied <i>path</i> and <i>filename</i>, "
"optionally including the local hostname (e.g. <tt>path/file.<i>host</i>.<i>domain</i>.ext</tt> "
"or <tt>path/file.<i>host</i>.ext</tt>) if such a variation of the filename exists")
,312
},
{"file_getdosname", js_dosfname, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
,JSDOCSTR("returns DOS-compatible (Micros~1 shortened) version of specified <i>path/filename</i>"
"(on Windows only)<br>"
"returns unmodified <i>path/filename</i> on other platforms")
,315
},
{"file_exists", js_fexist, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
,JSDOCSTR("verify a file's existence")
,310
},
{"file_remove", js_remove, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
,JSDOCSTR("delete a file")
,310
},
{"file_removecase", js_removecase, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
,JSDOCSTR("delete files case insensitively")
,314
},
{"file_rename", js_rename, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/oldname, path/newname")
,JSDOCSTR("rename a file, possibly moving it to another directory in the process")
,311
},
{"file_copy", js_fcopy, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/source, path/destination")
,JSDOCSTR("copy a file from one directory or filename to another")
,311
},
{"file_backup", js_backup, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,level=<tt>5</tt>] [,rename=<tt>false</tt>]")
,JSDOCSTR("backup the specified <i>filename</i> as <tt>filename.<i>number</i>.extension</tt> "
"where <i>number</i> is the backup number 0 through <i>level</i>-1 "
"(default backup <i>level</i> is 5), "
"if <i>rename</i> is <i>true</i>, the original file is renamed instead of copied "
"(default is <i>false</i>)")
,311
},
{"file_isdir", js_isdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
,JSDOCSTR("check if specified <i>filename</i> is a directory")
,310
},
{"file_attrib", js_fattr, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
,JSDOCSTR("get a file's permissions/attributes")
,310
},
{"file_date", js_fdate, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
,JSDOCSTR("get a file's last modified date/time (in time_t format)")
,310
},
{"file_size", js_flength, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
,JSDOCSTR("get a file's length (in bytes)")
,310
},
{"file_utime", js_utime, 3, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,access_time=<i>current</i>] [,mod_time=<i>current</i>]")
,JSDOCSTR("change a file's last accessed and modification date/time (in time_t format), "
"or change to current time")
,311
},
{"file_touch", js_ftouch, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
,JSDOCSTR("updates a file's last modification date/time to current time, "
"creating an empty file if it doesn't already exist")
,311
},
{"file_mutex", js_fmutex, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,text=<i>local_hostname</i>] [,max_age=<tt>0</tt>]")
,JSDOCSTR("attempts to create an mutual-exclusion (e.g. lock) file, "
"optionally with the contents of <i>text</i>. "
"If a non-zero <i>max_age</i> (supported in v3.13b+) is specified "
"and the lock file exists, but is older than this value (in seconds), "
"it is presumed stale and removed/over-written")
,312
},
{"file_compare", js_fcompare, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/file1, path/file2")
,JSDOCSTR("compare 2 files, returning <i>true</i> if they are identical, <i>false</i> otherwise")
,314
},
{"directory", js_directory, 1, JSTYPE_ARRAY, JSDOCSTR("path/pattern [,flags=<tt>GLOB_MARK</tt>]")
,JSDOCSTR("returns an array of directory entries, "
"<i>pattern</i> is the path and filename or wildcards to search for (e.g. '/subdir/*.txt'), "
"<i>flags</i> is a bitfield of optional <tt>glob</tt> flags (default is <tt>GLOB_MARK</tt>)")
,310
},
{"dir_freespace", js_freediskspace, 2, JSTYPE_NUMBER, JSDOCSTR("directory [,unit_size=<tt>1</tt>]")
,JSDOCSTR("returns the amount of available disk space in the specified <i>directory</i> "
"using the specified <i>unit_size</i> in bytes (default: 1), "
"specify a <i>unit_size</i> of <tt>1024</tt> to return the available space in <i>kilobytes</i>.")
,311
},
{"disk_size", js_disksize, 2, JSTYPE_NUMBER, JSDOCSTR("directory [,unit_size=<tt>1</tt>]")
,JSDOCSTR("returns the total disk size of the specified <i>directory</i> "
"using the specified <i>unit_size</i> in bytes (default: 1), "
"specify a <i>unit_size</i> of <tt>1024</tt> to return the total disk size in <i>kilobytes</i>.")
,314
},
{"socket_select", js_socket_select, 0, JSTYPE_ARRAY, JSDOCSTR("[array of socket objects or descriptors] [,timeout=<tt>0</tt>] [,write=<tt>false</tt>]")
,JSDOCSTR("checks an array of socket objects or descriptors for read or write ability (default is <i>read</i>), "
"default timeout value is 0.0 seconds (immediate timeout), "
"returns an array of 0-based index values into the socket array, representing the sockets that were ready for reading or writing, or <i>null</i> on error")
,311
},
{"mkdir", js_mkdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/directory")
,JSDOCSTR("make a directory")
,310
},
{"mkpath", js_mkpath, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/directory")
,JSDOCSTR("make a path to a directory (creating all necessary sub-directories)")
,315
},
{"rmdir", js_rmdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/directory")
,JSDOCSTR("remove a directory")
,310
},
{"strftime", js_strftime, 1, JSTYPE_STRING, JSDOCSTR("format [,time=<i>current</i>]")
,JSDOCSTR("return a formatted time string (ala C strftime)")
,310
},
{"format", js_format, 1, JSTYPE_STRING, JSDOCSTR("format [,args]")
,JSDOCSTR("return a formatted string (ala the standard C <tt>sprintf</tt> function)")
,310
},
{"html_encode", js_html_encode, 1, JSTYPE_STRING, JSDOCSTR("text [,ex_ascii=<tt>true</tt>] [,white_space=<tt>true</tt>] [,ansi=<tt>true</tt>] [,ctrl_a=<tt>true</tt>] [, state (object)]")
,JSDOCSTR("return an HTML-encoded text string (using standard HTML character entities), "
"escaping IBM extended-ASCII, white-space characters, ANSI codes, and CTRL-A codes by default."
"Optionally storing the current ANSI state in <i>state</i> object")
,311
},
{"html_decode", js_html_decode, 1, JSTYPE_STRING, JSDOCSTR("html")
,JSDOCSTR("return a decoded HTML-encoded text string")
,311
},
{"word_wrap", js_word_wrap, 1, JSTYPE_STRING, JSDOCSTR("text [,line_length=<tt>79</tt> [, orig_line_length=<tt>79</tt> [, handle_quotes=<tt>true</tt>]]]]")
,JSDOCSTR("returns a word-wrapped version of the text string argument optionally handing quotes magically, "
"<i>line_length</i> defaults to <i>79</i> <i>orig_line_length</i> defaults to <i>79</i> "
"and <i>handle_quotes</i> defaults to <i>true</i>")
,311
},
{"quote_msg", js_quote_msg, 1, JSTYPE_STRING, JSDOCSTR("text [,line_length=<tt>79</tt>] [,prefix=<tt>\" > \"</tt>]")
,JSDOCSTR("returns a quoted version of the message text string argument, <i>line_length</i> defaults to <i>79</i>, "
"<i>prefix</i> defaults to <tt>\" > \"</tt>")
,311
},
{"rot13_translate", js_rot13, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("returns ROT13-translated version of text string (will encode or decode text)")
,311
},
{"base64_encode", js_b64_encode, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("returns base64-encoded version of text string or <i>null</i> on error")
,311
},
{"base64_decode", js_b64_decode, 1, JSTYPE_STRING, JSDOCSTR("text")
,JSDOCSTR("returns base64-decoded text string or <i>null</i> on error")
,311
},
{"crc16_calc", js_crc16, 1, JSTYPE_NUMBER, JSDOCSTR("text")
,JSDOCSTR("calculate and return 16-bit CRC of text string")
,311
},
{"crc32_calc", js_crc32, 1, JSTYPE_NUMBER, JSDOCSTR("text")
,JSDOCSTR("calculate and return 32-bit CRC of text string")
,311
},
{"chksum_calc", js_chksum, 1, JSTYPE_NUMBER, JSDOCSTR("text")
,JSDOCSTR("calculate and return 32-bit checksum of text string")
,311
},
{"md5_calc", js_md5_calc, 1, JSTYPE_STRING, JSDOCSTR("text [,hex=<tt>false</tt>]")
,JSDOCSTR("calculate and return 128-bit MD5 digest of text string, result encoded in base64 (default) or hexadecimal")
,311
},
{"gethostbyname", js_resolve_ip, 1, JSTYPE_ALIAS },
{"resolve_ip", js_resolve_ip, 1, JSTYPE_STRING, JSDOCSTR("hostname")
,JSDOCSTR("resolve IP address of specified hostname (AKA gethostbyname)")
,311
},
{"gethostbyaddr", js_resolve_host, 1, JSTYPE_ALIAS },
{"resolve_host", js_resolve_host, 1, JSTYPE_STRING, JSDOCSTR("ip_address")
,JSDOCSTR("resolve hostname of specified IP address (AKA gethostbyaddr)")
,311
},
{"netaddr_type", js_netaddr_type, 1, JSTYPE_NUMBER, JSDOCSTR("email_address")
,JSDOCSTR("returns the proper message <i>net_type</i> for the specified <i>email_address</i>, "
"(e.g. <tt>NET_INTERNET</tt> for Internet e-mail or <tt>NET_NONE</tt> for local e-mail)")
,312
},
{"list_named_queues",js_list_named_queues,0,JSTYPE_ARRAY, JSDOCSTR("")
,JSDOCSTR("returns an array of <i>named queues</i> (created with the <i>Queue</i> constructor)")
,312
},
{"flags_str", js_flags_str, 1, JSTYPE_UNDEF, JSDOCSTR("[string] or [number]")
,JSDOCSTR("convert a string of security flags (letters) into their numeric value or vice-versa "
"(returns number OR string) - (added in v3.13)")
,313
},
{0}
};
static jsConstIntSpec js_global_const_ints[] = {
/* Numeric error constants from errno.h (platform-dependant) */
{"EPERM" ,EPERM },
{"ENOENT" ,ENOENT },
{"ESRCH" ,ESRCH },
{"EIO" ,EIO },
{"ENXIO" ,ENXIO },
{"E2BIG" ,E2BIG },
{"ENOEXEC" ,ENOEXEC },
{"EBADF" ,EBADF },
{"ECHILD" ,ECHILD },
{"EAGAIN" ,EAGAIN },
{"ENOMEM" ,ENOMEM },
{"EACCES" ,EACCES },
{"EFAULT" ,EFAULT },
{"EBUSY" ,EBUSY },
{"EEXIST" ,EEXIST },
{"EXDEV" ,EXDEV },
{"ENODEV" ,ENODEV },
{"ENOTDIR" ,ENOTDIR },
{"EISDIR" ,EISDIR },
{"EINVAL" ,EINVAL },
{"ENFILE" ,ENFILE },
{"EMFILE" ,EMFILE },
{"ENOTTY" ,ENOTTY },
{"EFBIG" ,EFBIG },
{"ENOSPC" ,ENOSPC },
{"ESPIPE" ,ESPIPE },
{"EROFS" ,EROFS },
{"EMLINK" ,EMLINK },
{"EPIPE" ,EPIPE },
{"EDOM" ,EDOM },
{"ERANGE" ,ERANGE },
{"EDEADLOCK" ,EDEADLOCK },
{"ENAMETOOLONG" ,ENAMETOOLONG },
{"ENOTEMPTY" ,ENOTEMPTY },
/* Socket errors */
{"EINTR" ,EINTR },
{"ENOTSOCK" ,ENOTSOCK },
{"EMSGSIZE" ,EMSGSIZE },
{"EWOULDBLOCK" ,EWOULDBLOCK },
{"EPROTOTYPE" ,EPROTOTYPE },
{"ENOPROTOOPT" ,ENOPROTOOPT },
{"EPROTONOSUPPORT" ,EPROTONOSUPPORT},
{"ESOCKTNOSUPPORT" ,ESOCKTNOSUPPORT},
{"EOPNOTSUPP" ,EOPNOTSUPP },
{"EPFNOSUPPORT" ,EPFNOSUPPORT },
{"EAFNOSUPPORT" ,EAFNOSUPPORT },
{"EADDRINUSE" ,EADDRINUSE },
{"EADDRNOTAVAIL" ,EADDRNOTAVAIL },
{"ECONNABORTED" ,ECONNABORTED },
{"ECONNRESET" ,ECONNRESET },
{"ENOBUFS" ,ENOBUFS },
{"EISCONN" ,EISCONN },
{"ENOTCONN" ,ENOTCONN },
{"ESHUTDOWN" ,ESHUTDOWN },
{"ETIMEDOUT" ,ETIMEDOUT },
{"ECONNREFUSED" ,ECONNREFUSED },
{"EINPROGRESS" ,EINPROGRESS },
/* Log priority values from syslog.h/sbbsdefs.h (possibly platform-dependant) */
{"LOG_EMERG" ,LOG_EMERG },
{"LOG_ALERT" ,LOG_ALERT },
{"LOG_CRIT" ,LOG_CRIT },
{"LOG_ERR" ,LOG_ERR },
{"LOG_ERROR" ,LOG_ERR },
{"LOG_WARNING" ,LOG_WARNING },
{"LOG_NOTICE" ,LOG_NOTICE },
{"LOG_INFO" ,LOG_INFO },
{"LOG_DEBUG" ,LOG_DEBUG },
/* Other useful constants */
{"INVALID_SOCKET" ,INVALID_SOCKET },
/* Terminator (Governor Arnold) */
{0}
};
static void js_global_finalize(JSContext *cx, JSObject *obj)
{
private_t* p;
p=(private_t*)JS_GetPrivate(cx,obj);
if(p!=NULL)
free(p);
p=NULL;
JS_SetPrivate(cx,obj,p);
}
static JSBool js_global_resolve(JSContext *cx, JSObject *obj, jsval id)
{
char* name=NULL;
private_t* p;
JSBool ret=JS_TRUE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL)
return(JS_FALSE);
if(id != JSVAL_NULL)
name=JS_GetStringBytes(JSVAL_TO_STRING(id));
if(p->methods) {
if(js_SyncResolve(cx, obj, name, NULL, p->methods, NULL, 0)==JS_FALSE)
ret=JS_FALSE;
}
if(js_SyncResolve(cx, obj, name, js_global_properties, js_global_functions, js_global_const_ints, 0)==JS_FALSE)
ret=JS_FALSE;
return(ret);
}
static JSBool js_global_enumerate(JSContext *cx, JSObject *obj)
{
return(js_global_resolve(cx, obj, JSVAL_NULL));
}
static JSClass js_global_class = {
"Global" /* name */
,JSCLASS_HAS_PRIVATE /* flags */
,JS_PropertyStub /* addProperty */
,JS_PropertyStub /* delProperty */
,js_system_get /* getProperty */
,JS_PropertyStub /* setProperty */
,js_global_enumerate /* enumerate */
,js_global_resolve /* resolve */
,JS_ConvertStub /* convert */
,js_global_finalize /* finalize */
};
JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods)
{
JSObject* glob;
private_t* p;
if((p = (private_t*)malloc(sizeof(private_t)))==NULL)
return(NULL);
p->cfg = cfg;
p->methods = methods;
if((glob = JS_NewObject(cx, &js_global_class, NULL, NULL)) ==NULL)
return(NULL);
if(!JS_SetPrivate(cx, glob, p)) /* Store a pointer to scfg_t and the new methods */
return(NULL);
if (!JS_InitStandardClasses(cx, glob))
return(NULL);
#ifdef BUILD_JSDOCS
js_DescribeSyncObject(cx,glob
,"Top-level functions and properties (common to all servers and services)",310);
#endif
return(glob);
}
JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx
,scfg_t* cfg /* common */
,scfg_t* node_cfg /* node-specific */
,jsSyncMethodSpec* methods /* global */
,time_t uptime /* system */
,char* host_name /* system */
,char* socklib_desc /* system */
,js_branch_t* branch /* js */
,client_t* client /* client */
,SOCKET client_socket /* client */
,js_server_props_t* props /* server */
)
{
JSObject* js_glob;
if(node_cfg==NULL)
node_cfg=cfg;
/* Global Object */
if((js_glob=js_CreateGlobalObject(js_cx, cfg, methods))==NULL)
return(NULL);
/* System Object */
if(js_CreateSystemObject(js_cx, js_glob, node_cfg, uptime, host_name, socklib_desc)==NULL)
return(NULL);
/* Internal JS Object */
if(branch!=NULL
&& js_CreateInternalJsObject(js_cx, js_glob, branch)==NULL)
return(NULL);
/* Client Object */
if(client!=NULL
&& js_CreateClientObject(js_cx, js_glob, "client", client, client_socket)==NULL)
return(NULL);
/* Server */
if(props!=NULL
&& js_CreateServerObject(js_cx, js_glob, props)==NULL)
return(NULL);
/* Socket Class */
if(js_CreateSocketClass(js_cx, js_glob)==NULL)
return(NULL);
/* Queue Class */
if(js_CreateQueueClass(js_cx, js_glob)==NULL)
return(NULL);
/* MsgBase Class */
if(js_CreateMsgBaseClass(js_cx, js_glob, cfg)==NULL)
return(NULL);
/* File Class */
if(js_CreateFileClass(js_cx, js_glob)==NULL)
return(NULL);
/* User class */
if(js_CreateUserClass(js_cx, js_glob, cfg)==NULL)
return(NULL);
/* Area Objects */
if(!js_CreateUserObjects(js_cx, js_glob, cfg, NULL, NULL, NULL))
return(NULL);
return(js_glob);
}
#endif /* JAVSCRIPT */