js_file.c 49 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
63
64

} private_t;

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

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

83
84
85
86
87
88
89
90
/* 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;
91
92
	else
		flags|=O_TEXT;
93
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

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

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

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

/* File Object Methods */

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

138
	*rval = JSVAL_FALSE;
139

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

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

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

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

	return(JS_TRUE);
}


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

190
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
191
		JS_ReportError(cx,getprivate_failure,WHERE);
192
		return(JS_FALSE);
193
	}
194
195
196
197
198
199
200
201
202
203
204
205
206
207

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

	fclose(p->fp);

	dbprintf(FALSE, p, "closed");

	p->fp=NULL; 

	return(JS_TRUE);
}

static JSBool
208
js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
209
210
{
	char*		cp;
211
	char*		buf;
212
	char*		uubuf;
213
214
	int32		len;
	int32		offset;
215
	int32		uulen;
216
217
218
	JSString*	str;
	private_t*	p;

219
220
	*rval = JSVAL_NULL;

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

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

229
230
231
232
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	} else {
233
234
235
236
237
238
239
		len=filelength(fileno(p->fp));
		offset=ftell(p->fp);
		if(offset>0)
			len-=offset;
	}
	if(len<0)
		len=512;
240

241
	if((buf=malloc(len+1))==NULL)
242
243
244
245
246
247
248
249
250
251
		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; 
252
		len=strlen(buf);
253
254
	}

255
256
257
	if(p->rot13)
		rot13(buf);

258
	if(p->uuencoded || p->b64encoded || p->yencoded) {
259
		uulen=len*2;
deuce's avatar
deuce committed
260
		if((uubuf=malloc(uulen))==NULL) {
261
			free(buf);
262
			return(JS_TRUE);
263
		}
264
265
		if(p->uuencoded)
			uulen=uuencode(uubuf,uulen,buf,len);
266
267
		else if(p->yencoded)
			uulen=yencode(uubuf,uulen,buf,len);
268
269
		else
			uulen=b64_encode(uubuf,uulen,buf,len);
270
		if(uulen>=0) {
271
			free(buf);
272
			buf=uubuf;
273
			len=uulen;
deuce's avatar
deuce committed
274
		}
275
276
		else
			free(uubuf);
277
278
	}

279
	str = JS_NewStringCopyN(cx, buf, len);
280
	free(buf);
281

282
283
284
	if(str==NULL)
		return(JS_FALSE);

285
286
287
	*rval = STRING_TO_JSVAL(str);

	dbprintf(FALSE, p, "read %u bytes",len);
288
289
290
291
292
		
	return(JS_TRUE);
}

static JSBool
293
js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
294
{
295
296
	char*		cp;
	char*		buf;
297
	int32		len=512;
298
	JSString*	js_str;
299
300
	private_t*	p;

301
	*rval = JSVAL_NULL;
302

303
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
304
		JS_ReportError(cx,getprivate_failure,WHERE);
305
		return(JS_FALSE);
306
	}
307
308
309

	if(p->fp==NULL)
		return(JS_TRUE);
310
	
311
312
313
314
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],&len))
			return(JS_FALSE);
	}
315

316
	if((buf=alloca(len))==NULL)
317
318
319
		return(JS_TRUE);

	if(fgets(buf,len,p->fp)!=NULL) {
320
321
322
323
		len=strlen(buf);
		while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
			len--;
		buf[len]=0;
324
325
326
327
		if(p->etx) {
			cp=strchr(buf,p->etx);
			if(cp) *cp=0; 
		}
328
329
		if(p->rot13)
			rot13(buf);
330
331
		if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL)	/* exception here Feb-12-2005 */
			*rval = STRING_TO_JSVAL(js_str);			/* _CrtDbgBreak from _heap_alloc_dbg */
332
333
334
335
336
337
	}

	return(JS_TRUE);
}

static JSBool
338
js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
339
340
341
342
343
344
345
{
	BYTE		b;
	WORD		w;
	DWORD		l;
	size_t		size=sizeof(DWORD);
	private_t*	p;

346
	*rval = INT_TO_JSVAL(-1);
347

348
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
349
		JS_ReportError(cx,getprivate_failure,WHERE);
350
		return(JS_FALSE);
351
	}
352
353
354
355

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

356
357
358
359
	if(argc) {
		if(!JS_ValueToInt32(cx,argv[0],(int32*)&size))
			return(JS_FALSE);
	}
360
361
362

	switch(size) {
		case sizeof(BYTE):
363
364
			if(fread(&b,1,size,p->fp)==size)
				*rval = INT_TO_JSVAL(b);
365
366
			break;
		case sizeof(WORD):
367
368
369
			if(fread(&w,1,size,p->fp)==size) {
				if(p->network_byte_order)
					w=ntohs(w);
370
				*rval = INT_TO_JSVAL(w);
371
			}
372
373
			break;
		case sizeof(DWORD):
374
375
376
			if(fread(&l,1,size,p->fp)==size) {
				if(p->network_byte_order)
					l=ntohl(l);
377
				JS_NewNumberValue(cx,l,rval);
378
			}
379
380
381
382
383
384
385
			break;
	}
		
	return(JS_TRUE);
}

static JSBool
386
js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
387
{
388
389
390
    jsint       len=0;
    jsval       line;
    JSObject*	array;
391
392
	private_t*	p;

393
394
	*rval = JSVAL_NULL;

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

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

403
    array = JS_NewArrayObject(cx, 0, NULL);
404

405
    while(!feof(p->fp)) {
406
		js_readln(cx, obj, argc, argv, &line);
407
408
		if(line==JSVAL_NULL)
			break;
409
410
        if(!JS_SetElement(cx, array, len++, &line))
			break;
411
	}
412
    *rval = OBJECT_TO_JSVAL(array);
413

414
415
    return(JS_TRUE);
}
416

417
418
419
420
421
422
423
424
425
426
427
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++) {
428
		if(*p=='.' && !f)
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
			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)));
}

457
static JSBool
458
js_iniGetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
459
{
rswindell's avatar
rswindell committed
460
	char*	section=ROOT_SECTION;
461
	char*	key;
462
	char**	list;
463
	char	buf[INI_MAX_VALUE_LEN];
464
465
	int32	i;
	jsval	val;
466
467
	jsval	dflt=argv[2];
	private_t*	p;
468
	JSObject*	array;
469
470
	JSObject*	dflt_obj;
	JSObject*	date_obj;
471
472
473
474
475
476

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

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

480
481
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
482
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
483
484

	if(dflt==JSVAL_VOID) {	/* unspecified default value */
485
		*rval=get_value(cx,iniReadString(p->fp,section,key,NULL,buf));
486
487
488
		return(JS_TRUE);
	}

489
490
491
	switch(JSVAL_TAG(dflt)) {
		case JSVAL_BOOLEAN:
			*rval = BOOLEAN_TO_JSVAL(
492
				iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
493
494
495
			break;
		case JSVAL_DOUBLE:
			JS_NewNumberValue(cx
496
				,iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt)),rval);
497
			break;
498
		case JSVAL_OBJECT:
499
			if((dflt_obj = JSVAL_TO_OBJECT(dflt))!=NULL && js_DateIsValid(cx, dflt_obj)) {
500
501
502
503
504
505
506
507
				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;
			}
508
		    array = JS_NewArrayObject(cx, 0, NULL);
509
			list=iniReadStringList(p->fp,section,key,",",JS_GetStringBytes(JS_ValueToString(cx,dflt)));
510
511
512
513
514
515
516
517
			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;
518
		default:
519
			if(JSVAL_IS_NUMBER(dflt)) {
520
521
				if(!JS_ValueToInt32(cx,dflt,&i))
					return(JS_FALSE);
522
				JS_NewNumberValue(cx,iniReadInteger(p->fp,section,key,i),rval);
523
524
525
			} else
				*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx
					,iniReadString(p->fp,section,key,JS_GetStringBytes(JS_ValueToString(cx,dflt)),buf)));
526
527
528
529
530
531
			break;
	}

	return(JS_TRUE);
}

532
533
534
static JSBool
js_iniSetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
rswindell's avatar
rswindell committed
535
	char*	section=ROOT_SECTION;
536
537
538
539
540
541
	char*	key;
	char*	result=NULL;
	int32	i;
	jsval	value=argv[2];
	private_t*	p;
	str_list_t	list;
542
	JSObject*	value_obj;
543
544
545
546
547
548
549
550

	*rval = JSVAL_FALSE;

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

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

554
555
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
	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)) {
574
575
					if(!JS_ValueToInt32(cx,value,&i))
						return(JS_FALSE);
576
					result = iniSetInteger(&list,section,key,i,NULL);
577
578
579
580
581
582
583
584
585
586
				} 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);
				}
587
588
589
590
591
592
593
594
595
596
597
598
				break;
		}
	}

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

	strListFree(&list);

	return(JS_TRUE);
}

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
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);
}

663

664
665
666
static JSBool
js_iniGetSections(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
667
	char*		prefix=NULL;
668
669
670
671
672
673
674
675
676
677
678
679
680
	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);
	}

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

684
685
686
	if(argc)
		prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

687
688
    array = JS_NewArrayObject(cx, 0, NULL);

689
	list = iniReadSectionList(p->fp,prefix);
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
    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
705
	char*		section=ROOT_SECTION;
706
707
708
709
710
711
712
713
714
715
716
717
718
	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);
	}

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

722
723
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
724
725
    array = JS_NewArrayObject(cx, 0, NULL);

726
	list = iniReadKeyList(p->fp,section);
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
    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
742
	char*		section=ROOT_SECTION;
743
744
745
    jsint       i;
    JSObject*	object;
	private_t*	p;
746
	named_string_t** list;
747
748
749
750
751
752
753
754

	*rval = JSVAL_NULL;

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

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

758
759
	if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
		section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
760
761
    object = JS_NewObject(cx, NULL, NULL, obj);

762
	list = iniReadNamedStringList(p->fp,section);
763
    for(i=0;list && list[i];i++) {
764
		JS_DefineProperty(cx, object, list[i]->name
765
			,get_value(cx,list[i]->value)
766
767
768
			,NULL,NULL,JSPROP_ENUMERATE);

	}
769
	iniFreeNamedStringList(list);
770
771
772
773
774
775

    *rval = OBJECT_TO_JSVAL(object);

    return(JS_TRUE);
}

776
777
778
779
780
781
782
783
784
785
786
787
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 */

788
	if(!JSVAL_IS_OBJECT(argv[1]) || argv[1]==JSVAL_NULL)
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
		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;
	}

805
806
	JS_DestroyIdArray(cx,id_array);

807
808
809
810
    return(JS_TRUE);
}


811
812
813
814
static JSBool
js_iniGetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		name="name";
815
	char*		sec_name;
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
	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);
	}

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

835
836
837
838
839
840
841
842
	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);

843
	sec_list = iniReadSectionList(p->fp,prefix);
844
845
846
    for(i=0;sec_list && sec_list[i];i++) {
	    object = JS_NewObject(cx, NULL, NULL, obj);

847
848
849
		sec_name=sec_list[i];
		if(prefix!=NULL)
			sec_name+=strlen(prefix);
850
		JS_DefineProperty(cx, object, name
851
			,STRING_TO_JSVAL(JS_NewStringCopyZ(cx,sec_name))
852
853
			,NULL,NULL,JSPROP_ENUMERATE);

854
		key_list = iniReadNamedStringList(p->fp,sec_list[i]);
855
856
		for(k=0;key_list && key_list[k];k++)
			JS_DefineProperty(cx, object, key_list[k]->name
857
				,get_value(cx,key_list[k]->value)
858
859
860
861
862
863
864
865
866
867
868
869
870
				,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);
}
871

872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
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);
}

912
913
914
915
static JSBool
js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		cp;
916
917
918
	char*		uubuf=NULL;
	int			len;	/* string length */
	int			tlen;	/* total length to write (may be greater than len) */
919
	JSString*	str;
920
	private_t*	p;
921

922
	*rval = JSVAL_FALSE;
923

924
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
925
		JS_ReportError(cx,getprivate_failure,WHERE);
926
		return(JS_FALSE);
927
	}
928
929
930
931

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

932
933
934
	str = JS_ValueToString(cx, argv[0]);
	cp	= JS_GetStringBytes(str);
	len	= JS_GetStringLength(str);
935

936
	if((p->uuencoded || p->b64encoded || p->yencoded)
937
		&& len && (uubuf=malloc(len))!=NULL) {
938
939
		if(p->uuencoded)
			len=uudecode(uubuf,len,cp,len);
940
941
		else if(p->yencoded)
			len=ydecode(uubuf,len,cp,len);
942
943
		else
			len=b64_decode(uubuf,len,cp,len);
944
945
		if(len<0) {
			free(uubuf);
946
			return(JS_TRUE);
947
		}
948
949
950
		cp=uubuf;
	}

951
952
953
	if(p->rot13)
		rot13(cp);

954
	tlen=len;
955
	if(argc>1) {
956
957
		if(!JS_ValueToInt32(cx,argv[1],(int32*)&tlen)) {
			FREE_AND_NULL(uubuf);
958
			return(JS_FALSE);
959
		}
960
961
962
		if(len>tlen)
			len=tlen;
	}
963
964

	if(fwrite(cp,1,len,p->fp)==(size_t)len) {
965
966
		if(tlen>len) {
			len=tlen-len;
967
968
969
			if((cp=malloc(len))==NULL) {
				FREE_AND_NULL(uubuf);
				dbprintf(TRUE, p, "malloc failure of %u bytes", len);
970
971
972
973
				return(JS_TRUE);
			}
			memset(cp,p->etx,len);
			fwrite(cp,1,len,p->fp);
974
			free(cp);
975
976
		}
		dbprintf(FALSE, p, "wrote %u bytes",tlen);
977
		*rval = JSVAL_TRUE;
978
979
	} else 
		dbprintf(TRUE, p, "write of %u bytes failed",len);
980
981

	FREE_AND_NULL(uubuf);
982
983
984
985
986
		
	return(JS_TRUE);
}

static JSBool
987
js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
988
{
989
990
991
992
	char*		cp="";
	JSString*	str;
	private_t*	p;

993
	*rval = JSVAL_FALSE;
994

995
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
996
		JS_ReportError(cx,getprivate_failure,WHERE);
997
		return(JS_FALSE);
998
	}
999
1000
1001
1002
1003

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

	if(argc) {
1004
1005
		if((str = JS_ValueToString(cx, argv[0]))==NULL) {
			JS_ReportError(cx,"JS_ValueToString failed");
1006
			return(JS_FALSE);
1007
		}
1008
1009
1010
		cp = JS_GetStringBytes(str);
	}

1011
1012
1013
	if(p->rot13)
		rot13(cp);

1014
	if(fprintf(p->fp,"%s\n",cp)!=0)
1015
		*rval = JSVAL_TRUE;
1016

1017
1018
	return(JS_TRUE);
}
1019

1020
static JSBool
1021
js_writebin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1022
{
1023
1024
1025
	BYTE		b;
	WORD		w;
	DWORD		l;
1026
	int32		val=0;
1027
	size_t		wr=0;
1028
	size_t		size=sizeof(DWORD);
1029
1030
	private_t*	p;

1031
	*rval = JSVAL_FALSE;
1032

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

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

1041
1042
1043
1044
1045
1046
	if(!JS_ValueToInt32(cx,argv[0],&val))
		return(JS_FALSE);
	if(argc>1) {
		if(!JS_ValueToInt32(cx,argv[1],(int32*)&size))
			return(JS_FALSE);
	}
1047

1048
1049
	switch(size) {
		case sizeof(BYTE):
1050
			b = (BYTE)val;
1051
			wr=fwrite(&b,1,size,p->fp);
1052
1053
			break;
		case sizeof(WORD):
1054
			w = (WORD)val;
1055
1056
			if(p->network_byte_order)
				w=htons(w);
1057
			wr=fwrite(&w,1,size,p->fp);
1058
1059
			break;
		case sizeof(DWORD):
1060
			l = val;
1061
1062
			if(p->network_byte_order)
				l=htonl(l);
1063
1064
1065
1066
1067
			wr=fwrite(&l,1,size,p->fp);
			break;
		default:	
			/* unknown size */
			dbprintf(TRUE, p, "unsupported binary write size: %d",size);
1068
1069
			break;
	}
1070
	if(wr==size)
1071
		*rval = JSVAL_TRUE;
1072
		
1073
1074
1075
	return(JS_TRUE);
}

1076
1077
1078
1079
1080
1081
1082
1083
1084
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;

1085
	*rval = JSVAL_FALSE;
1086

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

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

1095
	if(!JSVAL_IS_OBJECT(argv[0]))
1096
1097
1098
1099
		return(JS_TRUE);

    array = JSVAL_TO_OBJECT(argv[0]);

1100
1101
1102
    if(!JS_IsArrayObject(cx, array))
		return(JS_TRUE);

1103
1104
    if(!JS_GetArrayLength(cx, array, &limit))
		return(JS_FALSE);
1105

1106
    *rval = JSVAL_TRUE;
1107

1108
1109
1110
1111
    for(i=0;i<limit;i++) {
        if(!JS_GetElement(cx, array, i, &elemval))
			break;
        js_writeln(cx, obj, 1, &elemval, rval);
1112
		if(*rval!=JSVAL_TRUE)
1113
			break;
1114
1115
1116
1117
1118
    }

    return(JS_TRUE);
}

1119
static JSBool
1120
js_lock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1121
{
1122
1123
	int32		offset=0;
	int32		len=0;
1124
1125
	private_t*	p;

1126
	*rval = JSVAL_FALSE;
1127

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