Newer
Older
/* Synchronet JavaScript "File" Object */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 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 *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#include "md5.h"
#include "base64.h"
#include "uucode.h"
#include "yenc.h"
#include "ini_file.h"
#include <stdbool.h>
#if !defined(__unix__)
#include <conio.h> /* for kbhit() */
#endif
#include "js_request.h"
char name[MAX_PATH+1];
char mode[4];
BOOL rot13;
BOOL yencoded;
BOOL uuencoded;
BOOL b64encoded;
BOOL network_byte_order;
BOOL pipe; /* Opened with popen() use pclose() to close */
ini_style_t ini_style;
} private_t;
static void dbprintf(BOOL error, private_t* p, char* fmt, ...)
{
va_list argptr;
char sbuf[1024];
if(p==NULL || (!p->debug && !error))
return;
va_start(argptr,fmt);
vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
sbuf[sizeof(sbuf)-1]=0;
lprintf(LOG_DEBUG,"%04d File %s%s",p->fp ? fileno(p->fp) : 0,error ? "ERROR: ":"",sbuf);
/* Converts fopen() style 'mode' string into open() style 'flags' integer */
static int fopenflags(char *mode)
{
int flags=0;
if(strchr(mode,'b'))
flags|=O_BINARY;
if(strchr(mode,'x'))
flags|=O_EXCL;
if(strchr(mode,'w')) {
flags|=O_CREAT|O_TRUNC;
if(strchr(mode,'+'))
flags|=O_RDWR;
else
flags|=O_WRONLY;
return(flags);
}
if(strchr(mode,'a')) {
flags|=O_CREAT|O_APPEND;
if(strchr(mode,'+'))
flags|=O_RDWR;
else
flags|=O_WRONLY;
return(flags);
}
if(strchr(mode,'r')) {
if(strchr(mode,'+'))
flags|=O_RDWR;
else
flags|=O_RDONLY;
}
return(flags);
}
/* File Object Methods */
extern JSClass js_file_class;
js_open(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
BOOL shareable=FALSE;
int file = -1;
JSString* str;
private_t* p;
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
SAFECOPY(p->mode,"w+"); /* default mode */
for(i=0;i<argc;i++) {
if(JSVAL_IS_STRING(argv[i])) { /* mode */
if((str = JS_ValueToString(cx, argv[i]))==NULL) {
JS_ReportError(cx,"Invalid mode specified: %s",str);
return(JS_TRUE);
JSSTRING_TO_STRBUF(cx, str, p->mode, sizeof(p->mode), NULL);
}
else if(JSVAL_IS_BOOLEAN(argv[i])) /* shareable */
shareable=JSVAL_TO_BOOLEAN(argv[i]);
else if(JSVAL_IS_NUMBER(argv[i])) { /* bufsize */
if(!JS_ValueToInt32(cx,argv[i],&bufsize))
return(JS_FALSE);
}
rc=JS_SUSPENDREQUEST(cx);
if(shareable)
p->fp=fopen(p->name,p->mode);
else {
if((file=nopen(p->name,fopenflags(p->mode)))!=-1) {
char *fdomode=strdup(p->mode);
char *e=fdomode;
if(fdomode && e) {
/* Remove deprecated (never-worked, non-standard) 'e'xclusive mode char (and warn): */
for(e=strchr(fdomode, 'e'); e ; e=strchr(e, 'e')) {
JS_ReportWarning(cx, "Deprecated file open mode: 'e'");
memmove(e, e+1, strlen(e));
}
/* Remove (C11 standard) 'x'clusive mode char to avoid MSVC assertion: */
for(e=strchr(fdomode, 'x'); e ; e=strchr(e, 'x'))
memmove(e, e+1, strlen(e));
if((p->fp=fdopen(file,fdomode)) == NULL) {
JS_ReportWarning(cx, "fdopen(%s, %s) ERROR %d: %s", p->name, fdomode, errno, strerror(errno));
}
}
free(fdomode);
}
}
if(p->fp!=NULL) {
JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
dbprintf(FALSE, p, "opened: %s",p->name);
if(!bufsize)
setvbuf(p->fp,NULL,_IONBF,0); /* no buffering */
else {
#ifdef _WIN32
if(bufsize < 2)
bufsize = 2;
#endif
setvbuf(p->fp,NULL,_IOFBF,bufsize);
}
} else if(file >= 0)
close(file);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_popen(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
uintN i;
jsint bufsize=2*1024;
JSString* str;
private_t* p;
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
return(JS_FALSE);
}
return(JS_TRUE);
SAFECOPY(p->mode,"r+"); /* default mode */
for(i=0;i<argc;i++) {
if(JSVAL_IS_STRING(argv[i])) { /* mode */
if((str = JS_ValueToString(cx, argv[i]))==NULL) {
JS_ReportError(cx,"Invalid mode specified: %s",str);
return(JS_TRUE);
}
JSSTRING_TO_STRBUF(cx, str, p->mode, sizeof(p->mode), NULL);
}
else if(JSVAL_IS_NUMBER(argv[i])) { /* bufsize */
if(!JS_ValueToInt32(cx,argv[i],&bufsize))
return(JS_FALSE);
}
}
rc=JS_SUSPENDREQUEST(cx);
p->fp=popen(p->name,p->mode);
if(p->fp!=NULL) {
p->pipe=TRUE;
JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
dbprintf(FALSE, p, "popened: %s",p->name);
if(!bufsize)
setvbuf(p->fp,NULL,_IONBF,0); /* no buffering */
else
setvbuf(p->fp,NULL,_IOFBF,bufsize);
}
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
js_close(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if(p->fp==NULL)
return(JS_TRUE);
rc=JS_SUSPENDREQUEST(cx);
#ifdef __unix__
if(p->pipe)
pclose(p->fp);
else
#endif
fclose(p->fp);
dbprintf(FALSE, p, "closed: %s", p->name);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_raw_pollin(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
private_t* p;
jsrefcount rc;
int32 timeout = -1;
#ifdef __unix__
fd_set rd;
struct timeval tv = {0, 0};
#endif
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argc && !JSVAL_NULL_OR_VOID(argv[0])) {
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
if(!JS_ValueToInt32(cx,argv[0],&timeout))
return(JS_FALSE);
}
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(FALSE));
rc=JS_SUSPENDREQUEST(cx);
#ifdef __unix__
if (timeout >= 0) {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout%1000)*1000;
}
FD_ZERO(&rd);
FD_SET(fileno(p->fp), &rd);
if (select(fileno(p->fp)+1, &rd, NULL, NULL, timeout < 0 ? NULL : &tv) == 1)
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(TRUE));
#else
while(timeout) {
if (isatty(fileno(p->fp))) {
if (kbhit()) {
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(TRUE));
rc=JS_SUSPENDREQUEST(cx);
break;
}
SLEEP(1);
if (timeout > 0)
timeout--;
}
else {
if (!eof(fileno(p->fp))) {
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(TRUE));
rc=JS_SUSPENDREQUEST(cx);
break;
}
SLEEP(1);
if (timeout > 0)
timeout--;
}
}
#endif
JS_RESUMEREQUEST(cx, rc);
return JS_TRUE;
}
static JSBool
js_raw_read(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
char* buf;
int32 len;
JSString* str;
private_t* p;
jsrefcount rc;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argc && !JSVAL_NULL_OR_VOID(argv[0])) {
if(!JS_ValueToInt32(cx,argv[0],&len))
return(JS_FALSE);
} else
len = 1;
if(len<0)
len=1;
if((buf=malloc(len))==NULL)
return(JS_TRUE);
rc=JS_SUSPENDREQUEST(cx);
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
// https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_05.html#tag_02_05_01
/* For the first handle, the first applicable condition below applies. After the actions
* required below are taken, if the handle is still open, the application can close it.
* If it is a file descriptor, no action is required.
* If the only further action to be performed on any handle to this open file descriptor
* is to close it, no action need be taken.
* If it is a stream which is unbuffered, no action need be taken.
* If it is a stream which is line buffered, and the last byte written to the stream was a
* <newline> (that is, as if a: putc('\n') was the most recent operation on that stream),
* no action need be taken.
* If it is a stream which is open for writing or appending (but not also open for reading),
* the application shall either perform an fflush(), or the stream shall be closed.
* If the stream is open for reading and it is at the end of the file ( feof() is true), no
* action need be taken.
* If the stream is open with a mode that allows reading and the underlying open file
* description refers to a device that is capable of seeking, the application shall
* either perform an fflush(), or the stream shall be closed.
* Otherwise, the result is undefined.
* For the second handle:
* If any previous active handle has been used by a function that explicitly changed the file
* offset, except as required above for the first handle, the application shall perform an
* lseek() or fseek() (as appropriate to the type of handle) to an appropriate location.
*/
/*
* Since we don't want to overcomplicate this, it basically boils down to:
* Call fflush() on the stream, lseek() on the descriptor, diddle the descriptor, then fseek() the
* stream.
*
* The only option bit is the fflush() on the stream, but it never hurts and is sometimes
* required by POSIX.
*/
fflush(p->fp);
pos = ftell(p->fp);
fd = fileno(p->fp);
lseek(fd, pos, SEEK_SET);
len = read(fileno(p->fp),buf,len);
fseek(p->fp, pos + (len >= 0 ? len : 0), SEEK_SET);
dbprintf(FALSE, p, "read %u raw bytes",len);
len=0;
JS_RESUMEREQUEST(cx, rc);
str = JS_NewStringCopyN(cx, buf, len);
free(buf);
if(str==NULL)
return(JS_FALSE);
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
return(JS_TRUE);
}
js_read(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
char* uubuf;
int32 len;
int32 offset;
int32 uulen;
JSString* str;
private_t* p;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
if(p->fp==NULL)
return(JS_TRUE);
if(argc && !JSVAL_NULL_OR_VOID(argv[0])) {
if(!JS_ValueToInt32(cx,argv[0],&len))
return(JS_FALSE);
} else {
rc=JS_SUSPENDREQUEST(cx);
len=(long)filelength(fileno(p->fp));
offset=(long)ftell(p->fp);
if(offset>0)
len-=offset;
JS_RESUMEREQUEST(cx, rc);
}
if(len<0)
len=512;
if((buf=malloc(len+1))==NULL)
rc=JS_SUSPENDREQUEST(cx);
len = fread(buf,1,len,p->fp);
dbprintf(FALSE, p, "read %u bytes",len);
len=0;
buf[len]=0;
if(p->etx) {
cp=strchr(buf,p->etx);
len=strlen(buf);
if(p->rot13)
rot13(buf);
if(p->uuencoded || p->b64encoded || p->yencoded) {
uulen=len*2;
free(buf);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
if(p->uuencoded)
uulen=uuencode(uubuf,uulen,buf,len);
else if(p->yencoded)
uulen=yencode(uubuf,uulen,buf,len);
else
uulen=b64_encode(uubuf,uulen,buf,len);
if(uulen>=0) {
free(buf);
buf=uubuf;
len=uulen;
else
free(uubuf);
JS_RESUMEREQUEST(cx, rc);
str = JS_NewStringCopyN(cx, buf, len);
free(buf);
if(str==NULL)
return(JS_FALSE);
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
return(JS_TRUE);
}
static JSBool
js_readln(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
int32 len=512;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
if(p->fp==NULL)
return(JS_TRUE);
if(argc && !JSVAL_NULL_OR_VOID(argv[0])) {
if(!JS_ValueToInt32(cx,argv[0],&len))
return(JS_FALSE);
}
if((buf=malloc(len + 1))==NULL)
rc=JS_SUSPENDREQUEST(cx);
if(fgets(buf,len + 1,p->fp)!=NULL) {
len=strlen(buf);
while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
len--;
buf[len]=0;
if(p->etx) {
cp=strchr(buf,p->etx);
if(p->rot13)
rot13(buf);
JS_RESUMEREQUEST(cx, rc);
if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL) /* exception here Feb-12-2005 */
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
} else {
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_readbin(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
BYTE *b;
WORD *w;
DWORD *l;
int32 size=sizeof(DWORD);
int32 count=1;
size_t retlen;
void *buffer=NULL;
JSObject* array;
jsval v;
JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(-1));
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
if(p->fp==NULL)
return(JS_TRUE);
if(argc && !JSVAL_NULL_OR_VOID(argv[0])) {
if(!JS_ValueToInt32(cx,argv[0],&size))
return(JS_FALSE);
if(argc>1 && !JSVAL_NULL_OR_VOID(argv[1])) {
if(!JS_ValueToInt32(cx,argv[1],&count))
return(JS_FALSE);
}
}
rc=JS_SUSPENDREQUEST(cx);
if(size != sizeof(BYTE) && size != sizeof(WORD) && size != sizeof(DWORD)) {
/* unknown size */
dbprintf(TRUE, p, "unsupported binary read size: %d",size);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
buffer=malloc(size*count);
if(buffer==NULL) {
dbprintf(TRUE, p, "malloc failure of %u bytes", size*count);
JS_RESUMEREQUEST(cx, rc);
return(JS_FALSE);
}
b=buffer;
w=buffer;
l=buffer;
retlen=fread(buffer, size, count, p->fp);
if(count==1) {
if(retlen==1) {
switch(size) {
case sizeof(BYTE):
JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(*b));
break;
case sizeof(WORD):
if (p->network_byte_order)
*w = BE_SHORT(*w);
else
*w = LE_SHORT(*w);
JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(*w));
break;
case sizeof(DWORD):
if (p->network_byte_order)
*l = BE_LONG(*l);
else
*l = LE_LONG(*l);
JS_SET_RVAL(cx, arglist, UINT_TO_JSVAL(*l));
}
}
}
else {
JS_RESUMEREQUEST(cx, rc);
array = JS_NewArrayObject(cx, 0, NULL);
for(i=0; i<retlen; i++) {
switch(size) {
case sizeof(BYTE):
v = INT_TO_JSVAL(*(b++));
break;
case sizeof(WORD):
if (p->network_byte_order)
*w = BE_SHORT(*w);
else
*w = LE_SHORT(*w);
v = INT_TO_JSVAL(*(w++));
break;
case sizeof(DWORD):
if (p->network_byte_order)
*l = BE_LONG(*l);
else
*l = LE_LONG(*l);
v=UINT_TO_JSVAL(*(l++));
}
rc=JS_SUSPENDREQUEST(cx);
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
end:
free(buffer);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_readall(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsint len=0;
JSObject* array;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
if(p->fp==NULL)
return(JS_TRUE);
array = JS_NewArrayObject(cx, 0, NULL);
js_readln(cx, argc, arglist);
if(JS_RVAL(cx, arglist)==JSVAL_NULL)
if(!JS_SetElement(cx, array, len++, &JS_RVAL(cx, arglist)))
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
static jsval get_value(JSContext *cx, char* value, bool blanks)
{
char* p;
BOOL f=FALSE;
jsval val;
if(value==NULL || (*value==0 && !blanks))
return(JSVAL_VOID);
/* integer or float? */
for(p=value;*p;p++) {
if(*p=='.' && !f)
f=TRUE;
else if(!IS_DIGIT(*p))
break;
}
if(p!=value && *p==0) {
if(f)
val=DOUBLE_TO_JSVAL(atof(value));
else
val=DOUBLE_TO_JSVAL((double)strtoul(value,NULL,10));
return(val);
}
/* hexadecimal number? */
if(!strncmp(value,"0x",2)) {
for(p=value+2;*p;p++)
break;
val=DOUBLE_TO_JSVAL((double)strtoul(value,NULL,0));
return(val);
}
}
/* Boolean? */
if(!stricmp(value,"true"))
return(JSVAL_TRUE);
if(!stricmp(value,"false"))
return(JSVAL_FALSE);
/* String */
return(STRING_TO_JSVAL(JS_NewStringCopyZ(cx,value)));
}
static double js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
{
jsval rval;
if(!JS_CallFunctionName(cx, obj, "getTime", 0, NULL, &rval)) {
static JSBool
js_iniGetValue(JSContext *cx, uintN argc, jsval *arglist)
{
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
char* key;
char** list;
char buf[INI_MAX_VALUE_LEN];
int32 i;
jsval val;
jsval dflt=argv[2];
private_t* p;
JSObject* array;
JSObject* dflt_obj;
JSObject* date_obj;
char* cstr=NULL;
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
return(JS_FALSE);
}
if(argc && argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
JSVALUE_TO_MSTRING(cx, argv[0], section, NULL);
JSVALUE_TO_MSTRING(cx, argv[1], key, NULL);
if(JS_IsExceptionPending(cx)) {
FREE_AND_NULL(section);
FREE_AND_NULL(key);
/*
* Although section can be NULL (ie: root), a NULL key will cause a
* segfault.
*/
if(key==NULL) {
JS_ReportError(cx, "Invalid NULL key specified");
FREE_AND_NULL(section);
str_list_t ini = iniReadFile(p->fp);
if(argc < 3 || dflt==JSVAL_VOID) { /* unspecified default value */
rc=JS_SUSPENDREQUEST(cx);
cstr=iniGetString(ini,section,key,NULL,buf);
FREE_AND_NULL(section);
FREE_AND_NULL(key);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, get_value(cx, cstr, /* blanks */false));
return(JS_TRUE);
}
if(JSVAL_IS_BOOLEAN(dflt)) {
JS_SET_RVAL(cx,arglist,BOOLEAN_TO_JSVAL(
iniGetBool(ini,section,key,JSVAL_TO_BOOLEAN(dflt))));
}
else if(JSVAL_IS_OBJECT(dflt)) {
if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && (strcmp("Date",JS_GetClass(cx, dflt_obj)->name)==0)) {
tt=(time_t)(js_DateGetMsecSinceEpoch(cx,dflt_obj)/1000.0);
rc=JS_SUSPENDREQUEST(cx);
dbl=(double)iniGetDateTime(ini,section,key,tt);
JS_RESUMEREQUEST(cx, rc);
date_obj = JS_NewDateObjectMsec(cx, dbl);
if(date_obj!=NULL) {
array = JS_NewArrayObject(cx, 0, NULL);
cstr=NULL;
JSVALUE_TO_MSTRING(cx, dflt, cstr, NULL);
if(JS_IsExceptionPending(cx)) {
FREE_AND_NULL(cstr);
FREE_AND_NULL(section);
FREE_AND_NULL(key);
rc=JS_SUSPENDREQUEST(cx);
list=iniGetStringList(ini,section,key,",",cstr);
FREE_AND_NULL(cstr);
JS_RESUMEREQUEST(cx, rc);
for(i=0;list && list[i];i++) {
val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
if(!JS_SetElement(cx, array, i, &val))
break;
}
rc=JS_SUSPENDREQUEST(cx);
iniFreeStringList(list);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
}
}
else if(JSVAL_IS_DOUBLE(dflt)) {
rc=JS_SUSPENDREQUEST(cx);
dbl=iniGetFloat(ini,section,key,JSVAL_TO_DOUBLE(dflt));
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL(dbl));
}
else if(JSVAL_IS_NUMBER(dflt)) {
if(!JS_ValueToInt32(cx,dflt,&i)) {
FREE_AND_NULL(section);
FREE_AND_NULL(key);
i=iniGetInteger(ini,section,key,i);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist,INT_TO_JSVAL(i));
} else {
cstr=NULL;
JSVALUE_TO_MSTRING(cx, dflt, cstr, NULL);
if(JS_IsExceptionPending(cx)) {
FREE_AND_NULL(cstr);
FREE_AND_NULL(section);
FREE_AND_NULL(key);
cstr2=iniGetString(ini,section,key,cstr,buf);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, cstr2)));
}
FREE_AND_NULL(section);
FREE_AND_NULL(key);
return(JS_TRUE);
}
js_iniSetValue_internal(JSContext *cx, JSObject *obj, uintN argc, jsval* argv, str_list_t* list)
char* result=NULL;
int32 i;
jsval value=argv[2];
private_t* p;
JSObject* value_obj;
if((p=(private_t*)js_GetClassPrivate(cx, obj, &js_file_class))==NULL) {
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argc && argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
JSVALUE_TO_MSTRING(cx, argv[0], section, NULL);
JSVALUE_TO_MSTRING(cx, argv[1], key, NULL);
if(JS_IsExceptionPending(cx)) {
FREE_AND_NULL(section);
FREE_AND_NULL(key);
if(value==JSVAL_VOID) { /* unspecified value */
rc=JS_SUSPENDREQUEST(cx);
result = iniSetString(list,section,key,"",&p->ini_style);
JS_RESUMEREQUEST(cx, rc);
result = iniSetBool(list,section,key,JSVAL_TO_BOOLEAN(value),&p->ini_style);
result = iniSetFloat(list,section,key,JSVAL_TO_DOUBLE(value),&p->ini_style);
if(!JS_ValueToInt32(cx,value,&i)) {
FREE_AND_NULL(section);
FREE_AND_NULL(key);
result = iniSetInteger(list,section,key,i,&p->ini_style);
} else if(JSVAL_IS_OBJECT(value)
&& (value_obj = JSVAL_TO_OBJECT(value))!=NULL
&& (strcmp("Date",JS_GetClass(cx, value_obj)->name)==0)) {
tt=(time_t)(js_DateGetMsecSinceEpoch(cx,value_obj)/1000.0);
rc=JS_SUSPENDREQUEST(cx);
result = iniSetDateTime(list,section,key,/* include_time */TRUE, tt, &p->ini_style);
cstr=NULL;
JSVALUE_TO_MSTRING(cx, value, cstr, NULL);
if(JS_IsExceptionPending(cx)) {
FREE_AND_NULL(cstr);
FREE_AND_NULL(section);
FREE_AND_NULL(key);
result = iniSetString(list,section,key, cstr, &p->ini_style);
FREE_AND_NULL(cstr);
FREE_AND_NULL(section);
FREE_AND_NULL(key);
return(result != NULL);