js_file.c 50.6 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 2007 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
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);
}
232
233
234
235
236
237

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

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

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

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

	dbprintf(FALSE, p, "closed");

	p->fp=NULL; 

	return(JS_TRUE);
}

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

272
273
	*rval = JSVAL_NULL;

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

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

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

294
	if((buf=malloc(len+1))==NULL)
295
296
297
298
299
300
301
302
303
304
		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; 
305
		len=strlen(buf);
306
307
	}

308
309
310
	if(p->rot13)
		rot13(buf);

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

332
	str = JS_NewStringCopyN(cx, buf, len);
333
	free(buf);
334

335
336
337
	if(str==NULL)
		return(JS_FALSE);

338
339
340
	*rval = STRING_TO_JSVAL(str);

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

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

354
	*rval = JSVAL_NULL;
355

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

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

369
	if((buf=alloca(len))==NULL)
370
371
372
		return(JS_TRUE);

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

	return(JS_TRUE);
}

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

399
	*rval = INT_TO_JSVAL(-1);
400

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

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

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

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

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

446
447
	*rval = JSVAL_NULL;

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

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

456
    array = JS_NewArrayObject(cx, 0, NULL);
457

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

467
468
    return(JS_TRUE);
}
469

470
471
472
473
474
475
476
477
478
479
480
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++) {
481
		if(*p=='.' && !f)
482
483
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
			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)));
}

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

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

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

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

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

542
543
544
	switch(JSVAL_TAG(dflt)) {
		case JSVAL_BOOLEAN:
			*rval = BOOLEAN_TO_JSVAL(
545
				iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
546
547
548
			break;
		case JSVAL_DOUBLE:
			JS_NewNumberValue(cx
549
				,iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt)),rval);
550
			break;
551
		case JSVAL_OBJECT:
552
			if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && js_DateIsValid(cx, dflt_obj)) {
553
554
555
556
557
558
559
560
				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;
			}
561
		    array = JS_NewArrayObject(cx, 0, NULL);
562
			list=iniReadStringList(p->fp,section,key,",",JS_GetStringBytes(JS_ValueToString(cx,dflt)));
563
564
565
566
567
568
569
570
			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;
571
		default:
572
			if(JSVAL_IS_NUMBER(dflt)) {
573
574
				if(!JS_ValueToInt32(cx,dflt,&i))
					return(JS_FALSE);
575
				JS_NewNumberValue(cx,iniReadInteger(p->fp,section,key,i),rval);
576
577
578
			} else
				*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx
					,iniReadString(p->fp,section,key,JS_GetStringBytes(JS_ValueToString(cx,dflt)),buf)));
579
580
581
582
583
584
			break;
	}

	return(JS_TRUE);
}

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

	*rval = JSVAL_FALSE;

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

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

607
608
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
	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)) {
627
628
					if(!JS_ValueToInt32(cx,value,&i))
						return(JS_FALSE);
629
					result = iniSetInteger(&list,section,key,i,NULL);
630
631
632
633
634
635
636
637
638
639
				} 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);
				}
640
641
642
643
644
645
646
647
648
649
650
651
				break;
		}
	}

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

	strListFree(&list);

	return(JS_TRUE);
}

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

716

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

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

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

740
741
    array = JS_NewArrayObject(cx, 0, NULL);

742
	list = iniReadSectionList(p->fp,prefix);
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
    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
758
	char*		section=ROOT_SECTION;
759
760
761
762
763
764
765
766
767
768
769
770
771
	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);
	}

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

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

779
	list = iniReadKeyList(p->fp,section);
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
    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
795
	char*		section=ROOT_SECTION;
796
797
798
    jsint       i;
    JSObject*	object;
	private_t*	p;
799
	named_string_t** list;
800
801
802
803
804
805
806
807

	*rval = JSVAL_NULL;

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

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

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

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

	}
822
	iniFreeNamedStringList(list);
823
824
825
826
827
828

    *rval = OBJECT_TO_JSVAL(object);

    return(JS_TRUE);
}

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

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

858
859
	JS_DestroyIdArray(cx,id_array);

860
861
862
863
    return(JS_TRUE);
}


864
865
866
867
static JSBool
js_iniGetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		name="name";
868
	char*		sec_name;
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
	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);
	}

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

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

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

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

907
		key_list = iniReadNamedStringList(p->fp,sec_list[i]);
908
909
		for(k=0;key_list && key_list[k];k++)
			JS_DefineProperty(cx, object, key_list[k]->name
910
				,get_value(cx,key_list[k]->value)
911
912
913
914
915
916
917
918
919
920
921
922
923
				,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);
}
924

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

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

975
	*rval = JSVAL_FALSE;
976

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

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

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

989
	if((p->uuencoded || p->b64encoded || p->yencoded)
990
		&& len && (uubuf=malloc(len))!=NULL) {
991
992
		if(p->uuencoded)
			len=uudecode(uubuf,len,cp,len);
993
994
		else if(p->yencoded)
			len=ydecode(uubuf,len,cp,len);
995
996
		else
			len=b64_decode(uubuf,len,cp,len);
997
998
		if(len<0) {
			free(uubuf);
999
			return(JS_TRUE);
1000
		}
1001
1002
1003
		cp=uubuf;
	}

1004
1005
1006
	if(p->rot13)
		rot13(cp);

1007
	tlen=len;
1008
	if(argc>1) {
1009
1010
		if(!JS_ValueToInt32(cx,argv[1],(int32*)&tlen)) {
			FREE_AND_NULL(uubuf);
1011
			return(JS_FALSE);
1012
		}
1013
1014
1015
		if(len>tlen)
			len=tlen;
	}
1016
1017

	if(fwrite(cp,1,len,p->fp)==(size_t)len) {
1018
1019
		if(tlen>len) {
			len=tlen-len;
1020
1021
1022
			if((cp=malloc(len))==NULL) {
				FREE_AND_NULL(uubuf);
				dbprintf(TRUE, p, "malloc failure of %u bytes", len);
1023
1024
1025
1026
				return(JS_TRUE);
			}
			memset(cp,p->etx,len);
			fwrite(cp,1,len,p->fp);
1027
			free(cp);
1028
1029
		}
		dbprintf(FALSE, p, "wrote %u bytes",tlen);
1030
		*rval = JSVAL_TRUE;
1031
1032
	} else 
		dbprintf(TRUE, p, "write of %u bytes failed",len);
1033
1034

	FREE_AND_NULL(uubuf);
1035
1036
1037
1038
1039
		
	return(JS_TRUE);
}

static JSBool
1040
js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1041
{
1042
1043
1044
1045
	char*		cp="";
	JSString*	str;
	private_t*	p;

1046
	*rval = JSVAL_FALSE;
1047

1048
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1049
		JS_ReportError(cx,getprivate_failure,WHERE);
1050
		return(JS_FALSE);
1051
	}
1052
1053
1054
1055
1056

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

	if(argc) {
1057
1058
		if((str = JS_ValueToString(cx, argv[0]))==NULL) {
			JS_ReportError(cx,"JS_ValueToString failed");
1059
			return(JS_FALSE);
1060
		}
1061
1062
1063
		cp = JS_GetStringBytes(str);
	}

1064
1065
1066
	if(p->rot13)
		rot13(cp);

1067
	if(fprintf(p->fp,"%s\n",cp)!=0)
1068
		*rval = JSVAL_TRUE;
1069

1070
1071
	return(JS_TRUE);
}
1072

1073
static JSBool
1074
js_writebin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1075
{
1076
1077
1078
	BYTE		b;
	WORD		w;
	DWORD		l;
1079
	int32		val=0;
1080
	size_t		wr=0;
1081
	size_t		size=sizeof(DWORD);
1082
1083
	private_t*	p;

1084
	*rval = JSVAL_FALSE;
1085

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

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

1094
1095
1096
1097
1098
1099
	if(!JS_ValueToInt32(cx,argv[0],&val))
		return(JS_FALSE);
	if(argc>1) {
		if(!JS_ValueToInt32(cx,argv[1],(int32*)&size))
			return(JS_FALSE);
	}
1100

1101
1102
	switch(size) {
		case sizeof(BYTE):
1103
			b = (BYTE)val;
1104
			wr=fwrite(&b,1,size,p->fp);
1105
1106
			break;
		case sizeof(WORD):
1107
			w = (WORD)val;
1108
1109
			if(p->network_byte_order)
				w=htons(w);
1110
			wr=fwrite(&w,1,size,p->fp);
1111
1112
			break;
		case sizeof(DWORD):
1113
			l = val;
1114
1115
			if(p->network_byte_order)
				l=htonl(l);
1116
1117
1118
1119
1120
			wr=fwrite(&l,1,size,p->fp);
			break;
		default:	
			/* unknown size */
			dbprintf(TRUE, p, "unsupported binary write size: %d",size);
1121
1122
			break;
	}
1123
	if(wr==size)
1124
		*rval = JSVAL_TRUE;
1125
		
1126
1127
1128
	return(JS_TRUE);
}

1129
1130
1131
1132
1133
1134
1135
1136
1137
static JSBool
js_writeall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsuint      i;
    jsuint      limit;
    JSObject*	array;
    jsval       elemval;
	private_t*	p;

1138
	*rval = JSVAL_FALSE;
1139

1140
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1141
		JS_ReportError(cx,getprivate_failure,WHERE);
1142
		return(JS_FALSE);
1143
	}
1144
1145
1146
1147

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

1148
	if(!JSVAL_IS_OBJECT(argv[0]))
1149
1150
1151
1152
		return(JS_TRUE);

    array = JSVAL_TO_OBJECT(argv[0]);

1153
1154
1155
    if(!JS_IsArrayObject(cx, array))
		return(JS_TRUE);

1156
1157
    if(!JS_GetArrayLength(cx, array, &limit))
		return(JS_FALSE);
1158

1159
    *rval = JSVAL_TRUE;
1160

1161
1162
1163
1164
    for(i=0;i<limit;i++) {
        if(!JS_GetElement(cx, array, i, &elemval))
			break;