Newer
Older
/* js_file.c */
/* Synchronet JavaScript "File" Object */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2010 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. *
****************************************************************************/
#include "sbbs.h"
#include "md5.h"
#include "base64.h"
#include "uucode.h"
#include "yenc.h"
#include "ini_file.h"
#include "js_request.h"
#include "jsdate.h" /* Yes, I know this is a private header file */
char name[MAX_PATH+1];
char mode[4];
BOOL external; /* externally created, don't close */
BOOL debug;
BOOL rot13;
BOOL yencoded;
BOOL uuencoded;
BOOL b64encoded;
BOOL network_byte_order;
BOOL pipe; /* Opened with popen() use pclose() to close */
static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
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,"%04u 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,'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;
}
if(strchr(mode,'e'))
flags|=O_EXCL;
return(flags);
}
/* File Object Methods */
static JSBool
js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* mode="w+"; /* default mode */
BOOL shareable=FALSE;
int file;
JSString* str;
private_t* p;
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
if(p->fp!=NULL)
return(JS_TRUE);
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);
} 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);
}
SAFECOPY(p->mode,mode);
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[4];
SAFECOPY(fdomode,p->mode);
fdomode[strspn(fdomode,"abrwt+")]=0; /* MSVC10 fdopen() asserts when passed a mode with an unsupported char (e.g. 'e') */
if((p->fp=fdopen(file,fdomode))==NULL)
close(file);
}
}
if(p->fp!=NULL) {
*rval = JSVAL_TRUE;
dbprintf(FALSE, p, "opened: %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);
}
static JSBool
js_popen(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* mode="r+"; /* default mode */
uintN i;
jsint bufsize=2*1024;
JSString* str;
private_t* p;
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp!=NULL)
return(JS_TRUE);
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);
}
mode=JS_GetStringBytes(str);
}
else if(JSVAL_IS_NUMBER(argv[i])) { /* bufsize */
if(!JS_ValueToInt32(cx,argv[i],&bufsize))
return(JS_FALSE);
}
}
SAFECOPY(p->mode,mode);
rc=JS_SUSPENDREQUEST(cx);
p->fp=popen(p->name,p->mode);
if(p->fp!=NULL) {
p->pipe=TRUE;
*rval = 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);
}
static JSBool
js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
private_t* p;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
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");
p->fp=NULL;
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
char* uubuf;
int32 len;
int32 offset;
int32 uulen;
JSString* str;
private_t* p;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
if(p->fp==NULL)
return(JS_TRUE);
if(argc) {
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);
if(len<0)
len=0;
buf[len]=0;
if(p->etx) {
cp=strchr(buf,p->etx);
if(cp) *cp=0;
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);
*rval = STRING_TO_JSVAL(str);
rc=JS_SUSPENDREQUEST(cx);
dbprintf(FALSE, p, "read %u bytes",len);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
int32 len=512;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
if(p->fp==NULL)
return(JS_TRUE);
if(argc) {
if(!JS_ValueToInt32(cx,argv[0],&len))
return(JS_FALSE);
}
if((buf=alloca(len))==NULL)
rc=JS_SUSPENDREQUEST(cx);
if(fgets(buf,len,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(cp) *cp=0;
}
if(p->rot13)
rot13(buf);
JS_RESUMEREQUEST(cx, rc);
if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL) /* exception here Feb-12-2005 */
*rval = STRING_TO_JSVAL(js_str); /* _CrtDbgBreak from _heap_alloc_dbg */
} else {
JS_RESUMEREQUEST(cx, rc);
}
return(JS_TRUE);
}
static JSBool
js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
BYTE *b;
WORD *w;
DWORD *l;
size_t size=sizeof(DWORD);
private_t* p;
size_t count=1;
size_t retlen;
void *buffer=NULL;
JSObject* array;
jsval v;
*rval = INT_TO_JSVAL(-1);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
if(p->fp==NULL)
return(JS_TRUE);
if(argc) {
if(!JS_ValueToInt32(cx,argv[0],(int32*)&size))
return(JS_FALSE);
if(argc>1) {
if(!JS_ValueToInt32(cx,argv[1],(int32*)&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):
*rval = INT_TO_JSVAL(*b);
break;
case sizeof(WORD):
*rval = INT_TO_JSVAL(*w);
break;
case sizeof(DWORD):
JS_RESUMEREQUEST(cx, rc);
JS_NewNumberValue(cx,*l,rval);
rc=JS_SUSPENDREQUEST(cx);
}
}
}
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):
v = INT_TO_JSVAL(*(w++));
break;
case sizeof(DWORD):
JS_NewNumberValue(cx,*(l++),&v);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
*rval = OBJECT_TO_JSVAL(array);
end:
free(buffer);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsint len=0;
jsval line;
JSObject* array;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
if(p->fp==NULL)
return(JS_TRUE);
array = JS_NewArrayObject(cx, 0, NULL);
js_readln(cx, obj, argc, argv, &line);
if(line==JSVAL_NULL)
break;
if(!JS_SetElement(cx, array, len++, &line))
break;
*rval = OBJECT_TO_JSVAL(array);
static jsval get_value(JSContext *cx, char* value)
{
char* p;
BOOL f=FALSE;
jsval val;
if(value==NULL || *value==0)
return(JSVAL_VOID);
/* integer or float? */
for(p=value;*p;p++) {
if(*p=='.' && !f)
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
f=TRUE;
else if(!isdigit(*p))
break;
}
if(*p==0) {
JS_NewNumberValue(cx, f ? atof(value) : strtoul(value,NULL,10), &val);
return(val);
}
/* hexadecimal number? */
if(!strncmp(value,"0x",2)) {
for(p=value+2;*p;p++)
if(!isxdigit(*p))
break;
if(*p==0) {
JS_NewNumberValue(cx,strtoul(value,NULL,0),&val);
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 JSBool
js_iniGetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
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;
jsrefcount rc;
double dbl;
time_t tt;
char* cstr;
char* cstr2;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
if(dflt==JSVAL_VOID) { /* unspecified default value */
rc=JS_SUSPENDREQUEST(cx);
*rval=get_value(cx,iniReadString(p->fp,section,key,NULL,buf));
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
switch(JSVAL_TAG(dflt)) {
case JSVAL_BOOLEAN:
*rval = BOOLEAN_TO_JSVAL(
iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
break;
case JSVAL_DOUBLE:
rc=JS_SUSPENDREQUEST(cx);
dbl=iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt));
JS_RESUMEREQUEST(cx, rc);
JS_NewNumberValue(cx
break;
case JSVAL_OBJECT:
if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && js_DateIsValid(cx, dflt_obj)) {
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
if(date_obj!=NULL)
*rval = OBJECT_TO_JSVAL(date_obj);
break;
}
array = JS_NewArrayObject(cx, 0, NULL);
cstr=JS_GetStringBytes(JS_ValueToString(cx,dflt));
rc=JS_SUSPENDREQUEST(cx);
list=iniReadStringList(p->fp,section,key,",",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);
*rval = OBJECT_TO_JSVAL(array);
break;
default:
if(JSVAL_IS_NUMBER(dflt)) {
if(!JS_ValueToInt32(cx,dflt,&i))
return(JS_FALSE);
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
JS_NewNumberValue(cx,i,rval);
} else {
cstr=JS_GetStringBytes(JS_ValueToString(cx,dflt));
rc=JS_SUSPENDREQUEST(cx);
cstr2=iniReadString(p->fp,section,key,cstr,buf);
JS_RESUMEREQUEST(cx, rc);
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, cstr2));
}
break;
}
return(JS_TRUE);
}
static JSBool
js_iniSetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* key;
char* result=NULL;
int32 i;
jsval value=argv[2];
private_t* p;
str_list_t list;
JSObject* value_obj;
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
JS_RESUMEREQUEST(cx, rc);
if(value==JSVAL_VOID) { /* unspecified value */
rc=JS_SUSPENDREQUEST(cx);
result = iniSetString(&list,section,key,"",NULL);
JS_RESUMEREQUEST(cx, rc);
else {
switch(JSVAL_TAG(value)) {
case JSVAL_BOOLEAN:
result = iniSetBool(&list,section,key,JSVAL_TO_BOOLEAN(value),NULL);
break;
case JSVAL_DOUBLE:
result = iniSetFloat(&list,section,key,*JSVAL_TO_DOUBLE(value),NULL);
break;
default:
if(JSVAL_IS_NUMBER(value)) {
if(!JS_ValueToInt32(cx,value,&i))
return(JS_FALSE);
rc=JS_SUSPENDREQUEST(cx);
result = iniSetInteger(&list,section,key,i,NULL);
JS_RESUMEREQUEST(cx, rc);
} else {
if(JSVAL_IS_OBJECT(value)
&& (value_obj = JSVAL_TO_OBJECT(value))!=NULL
&& js_DateIsValid(cx, value_obj)) {
tt=(time_t)(js_DateGetMsecSinceEpoch(cx,value_obj)/1000.0);
rc=JS_SUSPENDREQUEST(cx);
result = iniSetDateTime(&list,section,key,/* include_time */TRUE, tt,NULL);
JS_RESUMEREQUEST(cx, rc);
} else {
cstr=JS_GetStringBytes(JS_ValueToString(cx,value));
rc=JS_SUSPENDREQUEST(cx);
result = iniSetString(&list,section,key, cstr,NULL);
JS_RESUMEREQUEST(cx, rc);
}
break;
}
}
rc=JS_SUSPENDREQUEST(cx);
if(result != NULL)
*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
strListFree(&list);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_iniRemoveKey(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* section=ROOT_SECTION;
char* key;
private_t* p;
str_list_t list;
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
if(iniRemoveKey(&list,section,key))
*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
strListFree(&list);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_iniRemoveSection(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* section=ROOT_SECTION;
private_t* p;
str_list_t list;
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
rc=JS_SUSPENDREQUEST(cx);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
if(iniRemoveSection(&list,section))
*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
strListFree(&list);
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
static JSBool
js_iniGetSections(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char** list;
jsint i;
jsval val;
JSObject* array;
private_t* p;
*rval = JSVAL_NULL;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argc)
prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
array = JS_NewArrayObject(cx, 0, NULL);
rc=JS_SUSPENDREQUEST(cx);
list = iniReadSectionList(p->fp,prefix);
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);
*rval = OBJECT_TO_JSVAL(array);
return(JS_TRUE);
}
static JSBool
js_iniGetKeys(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char** list;
jsint i;
jsval val;
JSObject* array;
private_t* p;
*rval = JSVAL_NULL;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
array = JS_NewArrayObject(cx, 0, NULL);
rc=JS_SUSPENDREQUEST(cx);
list = iniReadKeyList(p->fp,section);
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);
*rval = OBJECT_TO_JSVAL(array);
return(JS_TRUE);
}
static JSBool
js_iniGetObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsint i;
JSObject* object;
private_t* p;
named_string_t** list;
*rval = JSVAL_NULL;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(JS_FALSE);
}
if(p->fp==NULL)
return(JS_TRUE);
if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
object = JS_NewObject(cx, NULL, NULL, obj);
rc=JS_SUSPENDREQUEST(cx);
list = iniReadNamedStringList(p->fp,section);
JS_RESUMEREQUEST(cx, rc);
for(i=0;list && list[i];i++) {
JS_DefineProperty(cx, object, list[i]->name
,get_value(cx,list[i]->value)
,NULL,NULL,JSPROP_ENUMERATE);
}
rc=JS_SUSPENDREQUEST(cx);
iniFreeNamedStringList(list);
JS_RESUMEREQUEST(cx, rc);
*rval = OBJECT_TO_JSVAL(object);
return(JS_TRUE);
}
static JSBool
js_iniSetObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsint i;
JSObject* object;
JSIdArray* id_array;
jsval set_argv[3];
*rval = JSVAL_FALSE;
set_argv[0]=argv[0]; /* section */
if(!JSVAL_IS_OBJECT(argv[1]) || argv[1]==JSVAL_NULL)
return(JS_TRUE);
object = JSVAL_TO_OBJECT(argv[1]);
if((id_array=JS_Enumerate(cx,object))==NULL)
return(JS_TRUE);
for(i=0; i<id_array->length; i++) {
/* property */
JS_IdToValue(cx,id_array->vector[i],&set_argv[1]);
/* value */
JS_GetProperty(cx,object,JS_GetStringBytes(JSVAL_TO_STRING(set_argv[1])),&set_argv[2]);
if(!js_iniSetValue(cx,obj,3,set_argv,rval))
break;