js_file.c 50.7 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)		*
 *																			*
11
 * Copyright 2006 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
138
	JSString*	str;
	private_t*	p;

139
	*rval = JSVAL_FALSE;
140

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

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

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

165
166
167
168
169
170
171
172
	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);
		}
	}
173
	if(p->fp!=NULL) {
174
		*rval = JSVAL_TRUE;
175
		dbprintf(FALSE, p, "opened: %s",p->name);
176
177
178
179
180
		if(!bufsize)
			setvbuf(p->fp,NULL,_IONBF,0);	/* no buffering */
		else
			setvbuf(p->fp,NULL,_IOFBF,bufsize);
	}
181
182
183
184

	return(JS_TRUE);
}

185
186
187
188
189
190
191
192
193
194
195
196
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
223
224
225
226
227
228
229
230
231
232
233
#ifdef __unix__
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;

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

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

	return(JS_TRUE);
}
#endif
234
235
236
237
238
239

static JSBool
js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	private_t*	p;

240
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
241
		JS_ReportError(cx,getprivate_failure,WHERE);
242
		return(JS_FALSE);
243
	}
244
245
246
247

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

248
249
250
251
252
253
#ifdef __unix__
	if(p->pipe)
		pclose(p->fp);
	else
#endif
		fclose(p->fp);
254
255
256
257
258
259
260
261
262

	dbprintf(FALSE, p, "closed");

	p->fp=NULL; 

	return(JS_TRUE);
}

static JSBool
263
js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
264
265
{
	char*		cp;
266
	char*		buf;
267
	char*		uubuf;
268
269
	int32		len;
	int32		offset;
270
	int32		uulen;
271
272
273
	JSString*	str;
	private_t*	p;

274
275
	*rval = JSVAL_NULL;

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

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

284
285
286
287
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	} else {
288
289
290
291
292
293
294
		len=filelength(fileno(p->fp));
		offset=ftell(p->fp);
		if(offset>0)
			len-=offset;
	}
	if(len<0)
		len=512;
295

296
	if((buf=malloc(len+1))==NULL)
297
298
299
300
301
302
303
304
305
306
		return(JS_TRUE);

	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; 
307
		len=strlen(buf);
308
309
	}

310
311
312
	if(p->rot13)
		rot13(buf);

313
	if(p->uuencoded || p->b64encoded || p->yencoded) {
314
		uulen=len*2;
deuce's avatar
deuce committed
315
		if((uubuf=malloc(uulen))==NULL) {
316
			free(buf);
317
			return(JS_TRUE);
318
		}
319
320
		if(p->uuencoded)
			uulen=uuencode(uubuf,uulen,buf,len);
321
322
		else if(p->yencoded)
			uulen=yencode(uubuf,uulen,buf,len);
323
324
		else
			uulen=b64_encode(uubuf,uulen,buf,len);
325
		if(uulen>=0) {
326
			free(buf);
327
			buf=uubuf;
328
			len=uulen;
deuce's avatar
deuce committed
329
		}
330
331
		else
			free(uubuf);
332
333
	}

334
	str = JS_NewStringCopyN(cx, buf, len);
335
	free(buf);
336

337
338
339
	if(str==NULL)
		return(JS_FALSE);

340
341
342
	*rval = STRING_TO_JSVAL(str);

	dbprintf(FALSE, p, "read %u bytes",len);
343
344
345
346
347
		
	return(JS_TRUE);
}

static JSBool
348
js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
349
{
350
351
	char*		cp;
	char*		buf;
352
	int32		len=512;
353
	JSString*	js_str;
354
355
	private_t*	p;

356
	*rval = JSVAL_NULL;
357

358
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
359
		JS_ReportError(cx,getprivate_failure,WHERE);
360
		return(JS_FALSE);
361
	}
362
363
364

	if(p->fp==NULL)
		return(JS_TRUE);
365
	
366
367
368
369
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	}
370

371
	if((buf=alloca(len))==NULL)
372
373
374
		return(JS_TRUE);

	if(fgets(buf,len,p->fp)!=NULL) {
375
376
377
378
		len=strlen(buf);
		while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
			len--;
		buf[len]=0;
379
380
381
382
		if(p->etx) {
			cp=strchr(buf,p->etx);
			if(cp) *cp=0; 
		}
383
384
		if(p->rot13)
			rot13(buf);
385
386
		if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL)	/* exception here Feb-12-2005 */
			*rval = STRING_TO_JSVAL(js_str);			/* _CrtDbgBreak from _heap_alloc_dbg */
387
388
389
390
391
392
	}

	return(JS_TRUE);
}

static JSBool
393
js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
394
395
396
397
398
399
400
{
	BYTE		b;
	WORD		w;
	DWORD		l;
	size_t		size=sizeof(DWORD);
	private_t*	p;

401
	*rval = INT_TO_JSVAL(-1);
402

403
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
404
		JS_ReportError(cx,getprivate_failure,WHERE);
405
		return(JS_FALSE);
406
	}
407
408
409
410

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

411
412
413
414
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],(int32*)&size))
			return(JS_FALSE);
	}
415
416
417

	switch(size) {
		case sizeof(BYTE):
418
419
			if(fread(&b,1,size,p->fp)==size)
				*rval = INT_TO_JSVAL(b);
420
421
			break;
		case sizeof(WORD):
422
423
424
			if(fread(&w,1,size,p->fp)==size) {
				if(p->network_byte_order)
					w=ntohs(w);
425
				*rval = INT_TO_JSVAL(w);
426
			}
427
428
			break;
		case sizeof(DWORD):
429
430
431
			if(fread(&l,1,size,p->fp)==size) {
				if(p->network_byte_order)
					l=ntohl(l);
432
				JS_NewNumberValue(cx,l,rval);
433
			}
434
435
436
437
438
439
440
			break;
	}
		
	return(JS_TRUE);
}

static JSBool
441
js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
442
{
443
444
445
    jsint       len=0;
    jsval       line;
    JSObject*	array;
446
447
	private_t*	p;

448
449
	*rval = JSVAL_NULL;

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

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

458
    array = JS_NewArrayObject(cx, 0, NULL);
459

460
    while(!feof(p->fp)) {
461
		js_readln(cx, obj, argc, argv, &line);
462
463
		if(line==JSVAL_NULL)
			break;
464
465
        if(!JS_SetElement(cx, array, len++, &line))
			break;
466
	}
467
    *rval = OBJECT_TO_JSVAL(array);
468

469
470
    return(JS_TRUE);
}
471

472
473
474
475
476
477
478
479
480
481
482
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++) {
483
		if(*p=='.' && !f)
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
			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)));
}

512
static JSBool
513
js_iniGetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
514
{
rswindell's avatar
rswindell committed
515
	char*	section=ROOT_SECTION;
516
	char*	key;
517
	char**	list;
518
	char	buf[INI_MAX_VALUE_LEN];
519
520
	int32	i;
	jsval	val;
521
522
	jsval	dflt=argv[2];
	private_t*	p;
523
	JSObject*	array;
524
525
	JSObject*	dflt_obj;
	JSObject*	date_obj;
526
527
528
529
530
531

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

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

535
536
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
537
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
538
539

	if(dflt==JSVAL_VOID) {	/* unspecified default value */
540
		*rval=get_value(cx,iniReadString(p->fp,section,key,NULL,buf));
541
542
543
		return(JS_TRUE);
	}

544
545
546
	switch(JSVAL_TAG(dflt)) {
		case JSVAL_BOOLEAN:
			*rval = BOOLEAN_TO_JSVAL(
547
				iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
548
549
550
			break;
		case JSVAL_DOUBLE:
			JS_NewNumberValue(cx
551
				,iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt)),rval);
552
			break;
553
		case JSVAL_OBJECT:
554
			if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && js_DateIsValid(cx, dflt_obj)) {
555
556
557
558
559
560
561
562
				date_obj = js_NewDateObjectMsec(cx
					,(jsdouble)iniReadDateTime(p->fp,section,key
						,(time_t)(js_DateGetMsecSinceEpoch(cx,dflt_obj)/1000.0))
					*1000.0);
				if(date_obj!=NULL)
					*rval = OBJECT_TO_JSVAL(date_obj);
				break;
			}
563
		    array = JS_NewArrayObject(cx, 0, NULL);
564
			list=iniReadStringList(p->fp,section,key,",",JS_GetStringBytes(JS_ValueToString(cx,dflt)));
565
566
567
568
569
570
571
572
			for(i=0;list && list[i];i++) {
				val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
				if(!JS_SetElement(cx, array, i, &val))
					break;
			}
			iniFreeStringList(list);
			*rval = OBJECT_TO_JSVAL(array);
			break;
573
		default:
574
			if(JSVAL_IS_NUMBER(dflt)) {
575
576
				if(!JS_ValueToInt32(cx,dflt,&i))
					return(JS_FALSE);
577
				JS_NewNumberValue(cx,iniReadInteger(p->fp,section,key,i),rval);
578
579
580
			} else
				*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx
					,iniReadString(p->fp,section,key,JS_GetStringBytes(JS_ValueToString(cx,dflt)),buf)));
581
582
583
584
585
586
			break;
	}

	return(JS_TRUE);
}

587
588
589
static JSBool
js_iniSetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
rswindell's avatar
rswindell committed
590
	char*	section=ROOT_SECTION;
591
592
593
594
595
596
	char*	key;
	char*	result=NULL;
	int32	i;
	jsval	value=argv[2];
	private_t*	p;
	str_list_t	list;
597
	JSObject*	value_obj;
598
599
600
601
602
603
604
605

	*rval = JSVAL_FALSE;

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

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

609
610
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));

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

	if(value==JSVAL_VOID) 	/* unspecified value */
		result = iniSetString(&list,section,key,"",NULL);
	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)) {
629
630
					if(!JS_ValueToInt32(cx,value,&i))
						return(JS_FALSE);
631
					result = iniSetInteger(&list,section,key,i,NULL);
632
633
634
635
636
637
638
639
640
641
				} else {
					if(JSVAL_IS_OBJECT(value) 
						&& (value_obj = JSVAL_TO_OBJECT(value))!=NULL
						&& js_DateIsValid(cx, value_obj)) {
						result = iniSetDateTime(&list,section,key,/* include_time */TRUE
									,(time_t)(js_DateGetMsecSinceEpoch(cx,value_obj)/1000.0),NULL);
					} else
						result = iniSetString(&list,section,key
									,JS_GetStringBytes(JS_ValueToString(cx,value)),NULL);
				}
642
643
644
645
646
647
648
649
650
651
652
653
				break;
		}
	}

	if(result != NULL)
		*rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));

	strListFree(&list);

	return(JS_TRUE);
}

654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
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]));

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

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

	strListFree(&list);

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

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

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

	strListFree(&list);

	return(JS_TRUE);
}

718

719
720
721
static JSBool
js_iniGetSections(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
722
	char*		prefix=NULL;
723
724
725
726
727
728
729
730
731
732
733
734
735
	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);
	}

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

739
740
741
	if(argc)
		prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

742
743
    array = JS_NewArrayObject(cx, 0, NULL);

744
	list = iniReadSectionList(p->fp,prefix);
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
    for(i=0;list && list[i];i++) {
		val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
	iniFreeStringList(list);

    *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
760
	char*		section=ROOT_SECTION;
761
762
763
764
765
766
767
768
769
770
771
772
773
	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);
	}

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

777
778
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
779
780
    array = JS_NewArrayObject(cx, 0, NULL);

781
	list = iniReadKeyList(p->fp,section);
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
    for(i=0;list && list[i];i++) {
		val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
	iniFreeStringList(list);

    *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
797
	char*		section=ROOT_SECTION;
798
799
800
    jsint       i;
    JSObject*	object;
	private_t*	p;
801
	named_string_t** list;
802
803
804
805
806
807
808
809

	*rval = JSVAL_NULL;

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

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

813
814
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
815
816
    object = JS_NewObject(cx, NULL, NULL, obj);

817
	list = iniReadNamedStringList(p->fp,section);
818
    for(i=0;list && list[i];i++) {
819
		JS_DefineProperty(cx, object, list[i]->name
820
			,get_value(cx,list[i]->value)
821
822
823
			,NULL,NULL,JSPROP_ENUMERATE);

	}
824
	iniFreeNamedStringList(list);
825
826
827
828
829
830

    *rval = OBJECT_TO_JSVAL(object);

    return(JS_TRUE);
}

831
832
833
834
835
836
837
838
839
840
841
842
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 */

843
	if(!JSVAL_IS_OBJECT(argv[1]) || argv[1]==JSVAL_NULL)
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
		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;
	}

860
861
	JS_DestroyIdArray(cx,id_array);

862
863
864
865
    return(JS_TRUE);
}


866
867
868
869
static JSBool
js_iniGetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		name="name";
870
	char*		sec_name;
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
	char*		prefix=NULL;
	char**		sec_list;
    jsint       i,k;
    jsval       val;
    JSObject*	array;
    JSObject*	object;
	private_t*	p;
	named_string_t** key_list;

	*rval = JSVAL_NULL;

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

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

890
891
892
893
894
895
896
897
	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);

898
	sec_list = iniReadSectionList(p->fp,prefix);
899
900
901
    for(i=0;sec_list && sec_list[i];i++) {
	    object = JS_NewObject(cx, NULL, NULL, obj);

902
903
904
		sec_name=sec_list[i];
		if(prefix!=NULL)
			sec_name+=strlen(prefix);
905
		JS_DefineProperty(cx, object, name
906
			,STRING_TO_JSVAL(JS_NewStringCopyZ(cx,sec_name))
907
908
			,NULL,NULL,JSPROP_ENUMERATE);

909
		key_list = iniReadNamedStringList(p->fp,sec_list[i]);
910
911
		for(k=0;key_list && key_list[k];k++)
			JS_DefineProperty(cx, object, key_list[k]->name
912
				,get_value(cx,key_list[k]->value)
913
914
915
916
917
918
919
920
921
922
923
924
925
				,NULL,NULL,JSPROP_ENUMERATE);
		iniFreeNamedStringList(key_list);

		val=OBJECT_TO_JSVAL(object);
        if(!JS_SetElement(cx, array, i, &val))
			break;
	}
	iniFreeStringList(sec_list);

    *rval = OBJECT_TO_JSVAL(array);

    return(JS_TRUE);
}
926

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
static JSBool
js_iniSetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		name="name";
    jsuint      i;
    jsuint      count;
    JSObject*	array;
	jsval		set_argv[2];

	*rval = JSVAL_FALSE;

	if(!JSVAL_IS_OBJECT(argv[0]))
		return(JS_TRUE);

    array = JSVAL_TO_OBJECT(argv[0]);

	if(!JS_IsArrayObject(cx, array))
		return(JS_TRUE);

    if(!JS_GetArrayLength(cx, array, &count))
		return(JS_TRUE);

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

	/* enumerate the array */
	for(i=0; i<count; i++)  {
        if(!JS_GetElement(cx, array, i, &set_argv[1]))
			break;
		if(!JSVAL_IS_OBJECT(set_argv[1]))	/* must be an array of objects */
			break;
		if(!JS_GetProperty(cx, JSVAL_TO_OBJECT(set_argv[1]), name, &set_argv[0]))
			continue;
		if(!js_iniSetObject(cx, obj, 2, set_argv, rval))
			break;
	}

    return(JS_TRUE);
}

967
968
969
970
static JSBool
js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		cp;
971
972
973
	char*		uubuf=NULL;
	int			len;	/* string length */
	int			tlen;	/* total length to write (may be greater than len) */
974
	JSString*	str;
975
	private_t*	p;
976

977
	*rval = JSVAL_FALSE;
978

979
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
980
		JS_ReportError(cx,getprivate_failure,WHERE);
981
		return(JS_FALSE);
982
	}
983
984
985
986

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

987
988
989
	str = JS_ValueToString(cx, argv[0]);
	cp	= JS_GetStringBytes(str);
	len	= JS_GetStringLength(str);
990

991
	if((p->uuencoded || p->b64encoded || p->yencoded)
992
		&& len && (uubuf=malloc(len))!=NULL) {
993
994
		if(p->uuencoded)
			len=uudecode(uubuf,len,cp,len);
995
996
		else if(p->yencoded)
			len=ydecode(uubuf,len,cp,len);
997
998
		else
			len=b64_decode(uubuf,len,cp,len);
999
1000
		if(len<0) {
			free(uubuf);
For faster browsing, not all history is shown. View entire blame