js_file.c 56.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* 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)		*
 *																			*
rswindell's avatar
rswindell committed
11
 * Copyright 2008 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 *																			*
 * 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"
39
40
#include "md5.h"
#include "base64.h"
41
#include "uucode.h"
42
#include "yenc.h"
43
#include "ini_file.h"
44
45
46

#ifdef JAVASCRIPT

47
48
#include "jsdate.h"	/* Yes, I know this is a private header file */

49
50
typedef struct
{
51
	FILE*	fp;
52
53
	char	name[MAX_PATH+1];
	char	mode[4];
54
	uchar	etx;
55
56
	BOOL	external;	/* externally created, don't close */
	BOOL	debug;
57
	BOOL	rot13;
58
	BOOL	yencoded;
59
	BOOL	uuencoded;
60
61
	BOOL	b64encoded;
	BOOL	network_byte_order;
62
	BOOL	pipe;		/* Opened with popen() use pclose() to close */
63
64
65

} private_t;

66
static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
67
68
69
70
71
72
73
74
75
76

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);
77
78
    vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
	sbuf[sizeof(sbuf)-1]=0;
79
80
    va_end(argptr);
	
81
	lprintf(LOG_DEBUG,"%04u File %s%s",p->fp ? fileno(p->fp) : 0,error ? "ERROR: ":"",sbuf);
82
83
}

84
85
86
87
88
89
90
91
/* 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;
92
93
	else
		flags|=O_TEXT;
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

	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;
	}

120
121
122
	if(strchr(mode,'e'))
		flags|=O_EXCL;

123
124
	return(flags);
}
125
126
127
128
129
130
131

/* File Object Methods */

static JSBool
js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		mode="w+";	/* default mode */
132
133
	BOOL		shareable=FALSE;
	int			file;
134
	uintN		i;
135
	jsint		bufsize=2*1024;
136
137
	JSString*	str;
	private_t*	p;
deuce's avatar
deuce committed
138
	jsrefcount	rc;
139

140
	*rval = JSVAL_FALSE;
141

142
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
143
		JS_ReportError(cx,getprivate_failure,WHERE);
144
		return(JS_FALSE);
145
	}
146
147
148

	if(p->fp!=NULL)  
		return(JS_TRUE);
149
150
151
152

	for(i=0;i<argc;i++) {
		if(JSVAL_IS_STRING(argv[i])) {	/* mode */
			if((str = JS_ValueToString(cx, argv[i]))==NULL) {
153
154
				JS_ReportError(cx,"Invalid mode specified: %s",str);
				return(JS_TRUE);
155
156
			}
			mode=JS_GetStringBytes(str);
157
158
		} else if(JSVAL_IS_BOOLEAN(argv[i]))	/* shareable */
			shareable=JSVAL_TO_BOOLEAN(argv[i]);
159
160
161
162
		else if(JSVAL_IS_NUMBER(argv[i])) {	/* bufsize */
			if(!JS_ValueToInt32(cx,argv[i],&bufsize))
				return(JS_FALSE);
		}
163
	}
164
	SAFECOPY(p->mode,mode);
165

deuce's avatar
deuce committed
166
	rc=JS_SuspendRequest(cx);
167
168
169
170
171
172
173
174
	if(shareable)
		p->fp=fopen(p->name,p->mode);
	else {
		if((file=nopen(p->name,fopenflags(p->mode)))!=-1) {
			if((p->fp=fdopen(file,p->mode))==NULL)
				close(file);
		}
	}
175
	if(p->fp!=NULL) {
176
		*rval = JSVAL_TRUE;
177
		dbprintf(FALSE, p, "opened: %s",p->name);
178
179
180
181
182
		if(!bufsize)
			setvbuf(p->fp,NULL,_IONBF,0);	/* no buffering */
		else
			setvbuf(p->fp,NULL,_IOFBF,bufsize);
	}
deuce's avatar
deuce committed
183
	JS_ResumeRequest(cx, rc);
184
185
186
187

	return(JS_TRUE);
}

188
189
190
191
192
193
194
195
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;
deuce's avatar
deuce committed
196
	jsrefcount	rc;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

	*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);

deuce's avatar
deuce committed
223
	rc=JS_SuspendRequest(cx);
224
225
226
227
228
229
230
231
232
233
	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);
	}
deuce's avatar
deuce committed
234
	JS_ResumeRequest(cx, rc);
235
236
237

	return(JS_TRUE);
}
238
239
240
241
242

static JSBool
js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	private_t*	p;
deuce's avatar
deuce committed
243
	jsrefcount	rc;
244

245
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
246
		JS_ReportError(cx,getprivate_failure,WHERE);
247
		return(JS_FALSE);
248
	}
249
250
251
252

	if(p->fp==NULL)
		return(JS_TRUE);

deuce's avatar
deuce committed
253
	rc=JS_SuspendRequest(cx);
254
255
256
257
258
259
#ifdef __unix__
	if(p->pipe)
		pclose(p->fp);
	else
#endif
		fclose(p->fp);
260
261
262
263

	dbprintf(FALSE, p, "closed");

	p->fp=NULL; 
deuce's avatar
deuce committed
264
	JS_ResumeRequest(cx, rc);
265
266
267
268
269

	return(JS_TRUE);
}

static JSBool
270
js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
271
272
{
	char*		cp;
273
	char*		buf;
274
	char*		uubuf;
275
276
	int32		len;
	int32		offset;
277
	int32		uulen;
278
279
	JSString*	str;
	private_t*	p;
deuce's avatar
deuce committed
280
	jsrefcount	rc;
281

282
283
	*rval = JSVAL_NULL;

284
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
285
		JS_ReportError(cx,getprivate_failure,WHERE);
286
		return(JS_FALSE);
287
	}
288

289
290
	if(p->fp==NULL)
		return(JS_TRUE);
291

292
293
294
295
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	} else {
deuce's avatar
deuce committed
296
		rc=JS_SuspendRequest(cx);
297
298
299
300
		len=filelength(fileno(p->fp));
		offset=ftell(p->fp);
		if(offset>0)
			len-=offset;
deuce's avatar
deuce committed
301
		JS_ResumeRequest(cx, rc);
302
303
304
	}
	if(len<0)
		len=512;
305

306
	if((buf=malloc(len+1))==NULL)
307
308
		return(JS_TRUE);

deuce's avatar
deuce committed
309
	rc=JS_SuspendRequest(cx);
310
311
312
313
314
315
316
317
	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; 
318
		len=strlen(buf);
319
320
	}

321
322
323
	if(p->rot13)
		rot13(buf);

324
	if(p->uuencoded || p->b64encoded || p->yencoded) {
325
		uulen=len*2;
deuce's avatar
deuce committed
326
		if((uubuf=malloc(uulen))==NULL) {
327
			free(buf);
deuce's avatar
deuce committed
328
			JS_ResumeRequest(cx, rc);
329
			return(JS_TRUE);
330
		}
331
332
		if(p->uuencoded)
			uulen=uuencode(uubuf,uulen,buf,len);
333
334
		else if(p->yencoded)
			uulen=yencode(uubuf,uulen,buf,len);
335
336
		else
			uulen=b64_encode(uubuf,uulen,buf,len);
337
		if(uulen>=0) {
338
			free(buf);
339
			buf=uubuf;
340
			len=uulen;
deuce's avatar
deuce committed
341
		}
342
343
		else
			free(uubuf);
344
	}
deuce's avatar
deuce committed
345
	JS_ResumeRequest(cx, rc);
346

347
	str = JS_NewStringCopyN(cx, buf, len);
348
	free(buf);
349

350
351
352
	if(str==NULL)
		return(JS_FALSE);

353
354
	*rval = STRING_TO_JSVAL(str);

deuce's avatar
deuce committed
355
	rc=JS_SuspendRequest(cx);
356
	dbprintf(FALSE, p, "read %u bytes",len);
deuce's avatar
deuce committed
357
	JS_ResumeRequest(cx, rc);
358
359
360
361
362
		
	return(JS_TRUE);
}

static JSBool
363
js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
364
{
365
366
	char*		cp;
	char*		buf;
367
	int32		len=512;
368
	JSString*	js_str;
369
	private_t*	p;
deuce's avatar
deuce committed
370
	jsrefcount	rc;
371

372
	*rval = JSVAL_NULL;
373

374
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
375
		JS_ReportError(cx,getprivate_failure,WHERE);
376
		return(JS_FALSE);
377
	}
378
379
380

	if(p->fp==NULL)
		return(JS_TRUE);
381
	
382
383
384
385
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	}
386

387
	if((buf=alloca(len))==NULL)
388
389
		return(JS_TRUE);

deuce's avatar
deuce committed
390
	rc=JS_SuspendRequest(cx);
391
	if(fgets(buf,len,p->fp)!=NULL) {
392
393
394
395
		len=strlen(buf);
		while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
			len--;
		buf[len]=0;
396
397
398
399
		if(p->etx) {
			cp=strchr(buf,p->etx);
			if(cp) *cp=0; 
		}
400
401
		if(p->rot13)
			rot13(buf);
deuce's avatar
deuce committed
402
		JS_ResumeRequest(cx, rc);
403
404
		if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL)	/* exception here Feb-12-2005 */
			*rval = STRING_TO_JSVAL(js_str);			/* _CrtDbgBreak from _heap_alloc_dbg */
deuce's avatar
deuce committed
405
		rc=JS_SuspendRequest(cx);
406
	}
deuce's avatar
deuce committed
407
	JS_ResumeRequest(cx, rc);
408
409
410
411
412

	return(JS_TRUE);
}

static JSBool
413
js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
414
{
415
416
417
	BYTE		*b;
	WORD		*w;
	DWORD		*l;
418
419
	size_t		size=sizeof(DWORD);
	private_t*	p;
420
421
422
	size_t		count=1;
	size_t		retlen;
	void		*buffer=NULL;
rswindell's avatar
rswindell committed
423
	size_t		i;
424
425
    JSObject*	array;
    jsval       v;
deuce's avatar
deuce committed
426
	jsrefcount	rc;
427

428
	*rval = INT_TO_JSVAL(-1);
429

430
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
431
		JS_ReportError(cx,getprivate_failure,WHERE);
432
		return(JS_FALSE);
433
	}
434
435
436
437

	if(p->fp==NULL)
		return(JS_TRUE);

438
439
440
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],(int32*)&size))
			return(JS_FALSE);
441
442
443
444
		if(argc>1) {
			if(!JS_ValueToInt32(cx,argv[1],(int32*)&count))
				return(JS_FALSE);
		}
445
	}
446

deuce's avatar
deuce committed
447
	rc=JS_SuspendRequest(cx);
448
449
450
	if(size != sizeof(BYTE) && size != sizeof(WORD) && size != sizeof(DWORD)) {
		/* unknown size */
		dbprintf(TRUE, p, "unsupported binary read size: %d",size);
deuce's avatar
deuce committed
451
		JS_ResumeRequest(cx, rc);
452
453
454
455
456
457
		return(JS_TRUE);
	}

	buffer=malloc(size*count);
	if(buffer==NULL) {
		dbprintf(TRUE, p, "malloc failure of %u bytes", size*count);
deuce's avatar
deuce committed
458
		JS_ResumeRequest(cx, rc);
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
		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):
deuce's avatar
deuce committed
475
					JS_ResumeRequest(cx, rc);
476
					JS_NewNumberValue(cx,*l,rval);
deuce's avatar
deuce committed
477
					rc=JS_SuspendRequest(cx);
478
					break;
479
			}
480
481
482
		}
	}
	else {
deuce's avatar
deuce committed
483
		JS_ResumeRequest(cx, rc);
484
485
486
487
488
489
490
491
492
493
494
495
496
    	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;
497
			}
deuce's avatar
deuce committed
498
499
        	if(!JS_SetElement(cx, array, i, &v)) {
				rc=JS_SuspendRequest(cx);
500
				goto end;
deuce's avatar
deuce committed
501
			}
502
503
		}
    	*rval = OBJECT_TO_JSVAL(array);
504
	}
505
506
507

end:
	free(buffer);
deuce's avatar
deuce committed
508
	JS_ResumeRequest(cx, rc);
509
510
511
512
	return(JS_TRUE);
}

static JSBool
513
js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
514
{
515
516
517
    jsint       len=0;
    jsval       line;
    JSObject*	array;
518
519
	private_t*	p;

520
521
	*rval = JSVAL_NULL;

522
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
523
		JS_ReportError(cx,getprivate_failure,WHERE);
524
		return(JS_FALSE);
525
	}
526

527
528
	if(p->fp==NULL)
		return(JS_TRUE);
529

530
    array = JS_NewArrayObject(cx, 0, NULL);
531

532
    while(!feof(p->fp)) {
533
		js_readln(cx, obj, argc, argv, &line);
534
535
		if(line==JSVAL_NULL)
			break;
536
537
        if(!JS_SetElement(cx, array, len++, &line))
			break;
538
	}
539
    *rval = OBJECT_TO_JSVAL(array);
540

541
542
    return(JS_TRUE);
}
543

544
545
546
547
548
549
550
551
552
553
554
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++) {
555
		if(*p=='.' && !f)
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
			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)));
}

584
static JSBool
585
js_iniGetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
586
{
rswindell's avatar
rswindell committed
587
	char*	section=ROOT_SECTION;
588
	char*	key;
589
	char**	list;
590
	char	buf[INI_MAX_VALUE_LEN];
591
592
	int32	i;
	jsval	val;
593
594
	jsval	dflt=argv[2];
	private_t*	p;
595
	JSObject*	array;
596
597
	JSObject*	dflt_obj;
	JSObject*	date_obj;
deuce's avatar
deuce committed
598
599
600
601
602
	jsrefcount	rc;
	double		dbl;
	time_t		tt;
	char*		cstr;
	char*		cstr2;
603
604
605
606
607
608

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

609
610
611
	if(p->fp==NULL)
		return(JS_TRUE);

612
613
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
614
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
615
616

	if(dflt==JSVAL_VOID) {	/* unspecified default value */
deuce's avatar
deuce committed
617
		rc=JS_SuspendRequest(cx);
618
		*rval=get_value(cx,iniReadString(p->fp,section,key,NULL,buf));
deuce's avatar
deuce committed
619
		JS_ResumeRequest(cx, rc);
620
621
622
		return(JS_TRUE);
	}

623
624
625
	switch(JSVAL_TAG(dflt)) {
		case JSVAL_BOOLEAN:
			*rval = BOOLEAN_TO_JSVAL(
626
				iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
627
628
			break;
		case JSVAL_DOUBLE:
deuce's avatar
deuce committed
629
630
631
			rc=JS_SuspendRequest(cx);
			dbl=iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt));
			JS_ResumeRequest(cx, rc);
632
			JS_NewNumberValue(cx
deuce's avatar
deuce committed
633
				,dbl,rval);
634
			break;
635
		case JSVAL_OBJECT:
636
			if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && js_DateIsValid(cx, dflt_obj)) {
deuce's avatar
deuce committed
637
				tt=(time_t)(js_DateGetMsecSinceEpoch(cx,dflt_obj)/1000.0);
deuce's avatar
deuce committed
638
639
640
641
				rc=JS_SuspendRequest(cx);
				dbl=iniReadDateTime(p->fp,section,key,tt);
				JS_ResumeRequest(cx, rc);
				date_obj = js_NewDateObjectMsec(cx, dbl);
642
643
644
645
				if(date_obj!=NULL)
					*rval = OBJECT_TO_JSVAL(date_obj);
				break;
			}
646
		    array = JS_NewArrayObject(cx, 0, NULL);
deuce's avatar
deuce committed
647
648
649
650
			cstr=JS_GetStringBytes(JS_ValueToString(cx,dflt));
			rc=JS_SuspendRequest(cx);
			list=iniReadStringList(p->fp,section,key,",",cstr);
			JS_ResumeRequest(cx, rc);
651
652
653
654
655
			for(i=0;list && list[i];i++) {
				val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
				if(!JS_SetElement(cx, array, i, &val))
					break;
			}
deuce's avatar
deuce committed
656
			rc=JS_SuspendRequest(cx);
657
			iniFreeStringList(list);
deuce's avatar
deuce committed
658
			JS_ResumeRequest(cx, rc);
659
660
			*rval = OBJECT_TO_JSVAL(array);
			break;
661
		default:
662
			if(JSVAL_IS_NUMBER(dflt)) {
663
664
				if(!JS_ValueToInt32(cx,dflt,&i))
					return(JS_FALSE);
deuce's avatar
deuce committed
665
666
667
668
669
670
671
672
673
674
675
				rc=JS_SuspendRequest(cx);
				i=iniReadInteger(p->fp,section,key,i);
				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));
			}
676
677
678
679
680
681
			break;
	}

	return(JS_TRUE);
}

682
683
684
static JSBool
js_iniSetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
rswindell's avatar
rswindell committed
685
	char*	section=ROOT_SECTION;
686
687
688
689
690
691
	char*	key;
	char*	result=NULL;
	int32	i;
	jsval	value=argv[2];
	private_t*	p;
	str_list_t	list;
692
	JSObject*	value_obj;
deuce's avatar
deuce committed
693
694
695
	jsrefcount	rc;
	char*		cstr;
	time_t		tt;
696
697
698
699
700
701
702
703

	*rval = JSVAL_FALSE;

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

704
705
706
	if(p->fp==NULL)
		return(JS_TRUE);

707
708
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
709
710
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));

deuce's avatar
deuce committed
711
712
713
	rc=JS_SuspendRequest(cx);
	if((list=iniReadFile(p->fp))==NULL) {
		JS_ResumeRequest(cx, rc);
714
		return(JS_TRUE);
deuce's avatar
deuce committed
715
716
	}
	JS_ResumeRequest(cx, rc);
717

deuce's avatar
deuce committed
718
719
	if(value==JSVAL_VOID) { 	/* unspecified value */
		rc=JS_SuspendRequest(cx);
720
		result = iniSetString(&list,section,key,"",NULL);
deuce's avatar
deuce committed
721
722
		JS_ResumeRequest(cx, rc);
	}
723
724
725
726
727
728
729
730
731
732
733
	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)) {
734
735
					if(!JS_ValueToInt32(cx,value,&i))
						return(JS_FALSE);
deuce's avatar
deuce committed
736
					rc=JS_SuspendRequest(cx);
737
					result = iniSetInteger(&list,section,key,i,NULL);
deuce's avatar
deuce committed
738
					JS_ResumeRequest(cx, rc);
739
740
741
742
				} else {
					if(JSVAL_IS_OBJECT(value) 
						&& (value_obj = JSVAL_TO_OBJECT(value))!=NULL
						&& js_DateIsValid(cx, value_obj)) {
deuce's avatar
deuce committed
743
744
745
746
747
748
749
750
751
752
						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);
					}
753
				}
754
755
756
757
				break;
		}
	}

deuce's avatar
deuce committed
758
	rc=JS_SuspendRequest(cx);
759
760
761
762
	if(result != NULL)
		*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));

	strListFree(&list);
deuce's avatar
deuce committed
763
	JS_ResumeRequest(cx, rc);
764
765
766
767

	return(JS_TRUE);
}

768
769
770
771
772
773
774
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;
deuce's avatar
deuce committed
775
	jsrefcount	rc;
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

	*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]));

deuce's avatar
deuce committed
791
792
793
	rc=JS_SuspendRequest(cx);
	if((list=iniReadFile(p->fp))==NULL) {
		JS_ResumeRequest(cx, rc);
794
		return(JS_TRUE);
deuce's avatar
deuce committed
795
	}
796
797
798
799
800

	if(iniRemoveKey(&list,section,key))
		*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));

	strListFree(&list);
deuce's avatar
deuce committed
801
	JS_ResumeRequest(cx, rc);
802
803
804
805
806
807
808
809
810
811

	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;
deuce's avatar
deuce committed
812
	jsrefcount	rc;
813
814
815
816
817
818
819
820
821
822
823
824
825
826

	*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]));

deuce's avatar
deuce committed
827
828
829
	rc=JS_SuspendRequest(cx);
	if((list=iniReadFile(p->fp))==NULL) {
		JS_ResumeRequest(cx, rc);
830
		return(JS_TRUE);
deuce's avatar
deuce committed
831
	}
832
833
834
835
836

	if(iniRemoveSection(&list,section))
		*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));

	strListFree(&list);
deuce's avatar
deuce committed
837
	JS_ResumeRequest(cx, rc);
838
839
840
841

	return(JS_TRUE);
}

842

843
844
845
static JSBool
js_iniGetSections(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
846
	char*		prefix=NULL;
847
848
849
850
851
	char**		list;
    jsint       i;
    jsval       val;
    JSObject*	array;
	private_t*	p;
deuce's avatar
deuce committed
852
	jsrefcount	rc;
853
854
855
856
857
858
859
860

	*rval = JSVAL_NULL;

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

861
862
863
	if(p->fp==NULL)
		return(JS_TRUE);

864
865
866
	if(argc)
		prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

867
868
    array = JS_NewArrayObject(cx, 0, NULL);

deuce's avatar
deuce committed
869
	rc=JS_SuspendRequest(cx);
870
	list = iniReadSectionList(p->fp,prefix);
deuce's avatar
deuce committed
871
	JS_ResumeRequest(cx, rc);
872
873
874
875
876
    for(i=0;list && list[i];i++) {
		val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
deuce's avatar
deuce committed
877
	rc=JS_SuspendRequest(cx);
878
	iniFreeStringList(list);
deuce's avatar
deuce committed
879
	JS_ResumeRequest(cx, rc);
880
881
882
883
884
885
886
887
888

    *rval = OBJECT_TO_JSVAL(array);

    return(JS_TRUE);
}

static JSBool
js_iniGetKeys(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
rswindell's avatar
rswindell committed
889
	char*		section=ROOT_SECTION;
890
891
892
893
894
	char**		list;
    jsint       i;
    jsval       val;
    JSObject*	array;
	private_t*	p;
deuce's avatar
deuce committed
895
	jsrefcount	rc;
896
897
898
899
900
901
902
903

	*rval = JSVAL_NULL;

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

904
905
906
	if(p->fp==NULL)
		return(JS_TRUE);

907
908
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
909
910
    array = JS_NewArrayObject(cx, 0, NULL);

deuce's avatar
deuce committed
911
	rc=JS_SuspendRequest(cx);
912
	list = iniReadKeyList(p->fp,section);
deuce's avatar
deuce committed
913
	JS_ResumeRequest(cx, rc);
914
915
916
917
918
    for(i=0;list && list[i];i++) {
		val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
deuce's avatar
deuce committed
919
	rc=JS_SuspendRequest(cx);
920
	iniFreeStringList(list);
deuce's avatar
deuce committed
921
	JS_ResumeRequest(cx, rc);
922
923
924
925
926
927
928
929
930

    *rval = OBJECT_TO_JSVAL(array);

    return(JS_TRUE);
}

static JSBool
js_iniGetObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
rswindell's avatar
rswindell committed
931
	char*		section=ROOT_SECTION;
932
933
934
    jsint       i;
    JSObject*	object;
	private_t*	p;
935
	named_string_t** list;
deuce's avatar
deuce committed
936
	jsrefcount	rc;
937
938
939
940
941
942
943
944

	*rval = JSVAL_NULL;

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

945
946
947
	if(p->fp==NULL)
		return(JS_TRUE);

948
949
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
950
951
    object = JS_NewObject(cx, NULL, NULL, obj);

deuce's avatar
deuce committed
952
	rc=JS_SuspendRequest(cx);
953
	list = iniReadNamedStringList(p->fp,section);
deuce's avatar
deuce committed
954
	JS_ResumeRequest(cx, rc);
955
    for(i=0;list && list[i];i++) {
956
		JS_DefineProperty(cx, object, list[i]->name
957
			,get_value(cx,list[i]->value)
958
959
960
			,NULL,NULL,JSPROP_ENUMERATE);

	}
deuce's avatar
deuce committed
961
	rc=JS_SuspendRequest(cx);
962
	iniFreeNamedStringList(list);
deuce's avatar
deuce committed
963
	JS_ResumeRequest(cx, rc);
964
965
966
967
968
969

    *rval = OBJECT_TO_JSVAL(object);

    return(JS_TRUE);
}

970
971
972
973
974
975
976
977
978
979
980
981
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 */

982
	if(!JSVAL_IS_OBJECT(argv[1]) || argv[1]==JSVAL_NULL)
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
		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;
	}

999
1000
	JS_DestroyIdArray(cx,id_array);

1001
1002
1003
1004
    return(JS_TRUE);
}


1005
1006
1007
1008
static JSBool
js_iniGetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		name="name";
1009
	char*		sec_name;
1010
1011
1012
1013
1014
1015
1016
1017
	char*		prefix=NULL;
	char**		sec_list;
    jsint       i,k;
    jsval       val;
    JSObject*	array;
    JSObject*	object;
	private_t*	p;
	named_string_t** key_list;
deuce's avatar
deuce committed
1018
	jsrefcount	rc;
1019
1020
1021
1022
1023
1024
1025
1026

	*rval = JSVAL_NULL;

	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

1027
1028
1029
	if(p->fp==NULL)
		return(JS_TRUE);

1030
1031
1032
1033
1034
1035
1036
1037
	if(argc)
		name=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

	if(argc>1)
		prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));

    array = JS_NewArrayObject(cx, 0, NULL);

deuce's avatar
deuce committed
1038
	rc=JS_SuspendRequest(cx);
1039
	sec_list = iniReadSectionList(p->fp,prefix);
deuce's avatar
deuce committed
1040
	JS_ResumeRequest(cx, rc);
1041
1042
1043
    for(i=0;sec_list && sec_list[i];i++) {
	    object = JS_NewObject(cx, NULL, NULL, obj);

1044
1045
1046
		sec_name=sec_list[i];
		if(prefix!=NULL)
			sec_name+=strlen(prefix);
1047
		JS_DefineProperty(cx, object, name
1048
			,STRING_TO_JSVAL(JS_NewStringCopyZ(cx,sec_name))
1049
1050
			,NULL,NULL,JSPROP_ENUMERATE);

deuce's avatar
deuce committed
1051
		rc=JS_SuspendRequest(cx);
1052
		key_list = iniReadNamedStringList(p->fp,sec_list[i]);
deuce's avatar
deuce committed
1053
		JS_ResumeRequest(cx, rc);
1054
1055
		for(k=0;key_list && key_list[k];k++)
			JS_DefineProperty(cx, object, key_list[k]->name
1056
				,get_value(cx,key_list[k]->value)
1057
				,NULL,NULL,JSPROP_ENUMERATE);
deuce's avatar
deuce committed
1058
		rc=JS_SuspendRequest(cx);
1059
		iniFreeNamedStringList(key_list);
deuce's avatar
deuce committed
1060
		JS_ResumeRequest(cx, rc);
1061
1062
1063
1064
1065

		val=OBJECT_TO_JSVAL(object);
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
deuce's avatar
deuce committed
1066
	rc=JS_SuspendRequest(cx);
1067
	iniFreeStringList(sec_list);
deuce's avatar
deuce committed
1068
	JS_ResumeRequest(cx, rc);
1069
1070
1071
1072
1073

    *rval = OBJECT_TO_JSVAL(array);

    return(JS_TRUE);
}
1074

1075