js_file.c 31 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
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
/* js_file.c */

/* Synchronet JavaScript "File" Object */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2001 Rob Swindell - http://www.synchro.net/copyright.html		*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"
39
40
#include "md5.h"
#include "base64.h"
41
#include "uucode.h"
42
#include "ini_file.h"
43
44
45
46
47

#ifdef JAVASCRIPT

typedef struct
{
48
	FILE*	fp;
49
50
	char	name[MAX_PATH+1];
	char	mode[4];
51
	uchar	etx;
52
53
	BOOL	external;	/* externally created, don't close */
	BOOL	debug;
54
	BOOL	rot13;
55
	BOOL	uuencoded;
56
57
	BOOL	b64encoded;
	BOOL	network_byte_order;
58
59
60

} private_t;

61
static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
62
63
64
65
66
67
68
69
70
71

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

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

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

	return(flags);
}
117
118
119
120
121
122
123

/* File Object Methods */

static JSBool
js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		mode="w+";	/* default mode */
124
125
	BOOL		shareable=FALSE;
	int			file;
126
	uintN		i;
127
	jsint		bufsize=2*1024;
128
129
130
	JSString*	str;
	private_t*	p;

131
	*rval = JSVAL_FALSE;
132

133
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
134
		JS_ReportError(cx,getprivate_failure,WHERE);
135
		return(JS_FALSE);
136
	}
137
138
139

	if(p->fp!=NULL)  
		return(JS_TRUE);
140
141
142
143

	for(i=0;i<argc;i++) {
		if(JSVAL_IS_STRING(argv[i])) {	/* mode */
			if((str = JS_ValueToString(cx, argv[i]))==NULL) {
144
145
				JS_ReportError(cx,"Invalid mode specified: %s",str);
				return(JS_TRUE);
146
147
			}
			mode=JS_GetStringBytes(str);
148
149
150
		} else if(JSVAL_IS_BOOLEAN(argv[i]))	/* shareable */
			shareable=JSVAL_TO_BOOLEAN(argv[i]);
		else	/* bufsize */
151
			JS_ValueToInt32(cx,argv[i],&bufsize);
152
	}
153
	SAFECOPY(p->mode,mode);
154

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

	return(JS_TRUE);
}


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

181
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
182
		JS_ReportError(cx,getprivate_failure,WHERE);
183
		return(JS_FALSE);
184
	}
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

	*rval = JSVAL_VOID;

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

	fclose(p->fp);

	dbprintf(FALSE, p, "closed");

	p->fp=NULL; 

	return(JS_TRUE);
}

static JSBool
201
js_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
202
203
{
	char*		cp;
204
	char*		buf;
205
	char*		uubuf;
206
207
	int32		len;
	int32		offset;
208
	int32		uulen;
209
210
211
	JSString*	str;
	private_t*	p;

212
213
	*rval = JSVAL_NULL;

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

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

222
	if(argc)
223
		JS_ValueToInt32(cx,argv[0],&len);
224
225
226
227
228
229
230
231
	else {
		len=filelength(fileno(p->fp));
		offset=ftell(p->fp);
		if(offset>0)
			len-=offset;
	}
	if(len<0)
		len=512;
232

233
234
235
236
237
238
239
240
241
242
243
244
245
	if((buf=malloc(len+1))==NULL)
		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; 
	}

246
247
248
	if(p->rot13)
		rot13(buf);

249
	if(p->uuencoded || p->b64encoded) {
250
251
252
		uulen=len*2;
		if((uubuf=malloc(uulen))==NULL)
			return(JS_TRUE);
253
254
255
256
		if(p->uuencoded)
			uulen=uuencode(uubuf,uulen,buf,len);
		else
			uulen=b64_encode(uubuf,uulen,buf,len);
257
258
259
260
261
262
263
		if(uulen>=0) {
			free(buf);
			buf=uubuf;
		} else
			free(uubuf);
	}

264
265
266
267
	str = JS_NewStringCopyZ(cx, buf);

	free(buf);

268
269
270
	if(str==NULL)
		return(JS_FALSE);

271
272
273
	*rval = STRING_TO_JSVAL(str);

	dbprintf(FALSE, p, "read %u bytes",len);
274
275
276
277
278
		
	return(JS_TRUE);
}

static JSBool
279
js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
280
{
281
282
	char*		cp;
	char*		buf;
283
	int32		len=512;
284
	JSString*	js_str;
285
286
	private_t*	p;

287
	*rval = JSVAL_NULL;
288

289
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
290
		JS_ReportError(cx,getprivate_failure,WHERE);
291
		return(JS_FALSE);
292
	}
293
294
295

	if(p->fp==NULL)
		return(JS_TRUE);
296
297
	
	if(argc)
298
		JS_ValueToInt32(cx,argv[0],&len);
299

300
301
302
303
	if((buf=malloc(len))==NULL)
		return(JS_TRUE);

	if(fgets(buf,len,p->fp)!=NULL) {
304
305
306
307
		len=strlen(buf);
		while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
			len--;
		buf[len]=0;
308
309
310
311
		if(p->etx) {
			cp=strchr(buf,p->etx);
			if(cp) *cp=0; 
		}
312
313
		if(p->rot13)
			rot13(buf);
314
315
		if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL)
			*rval = STRING_TO_JSVAL(js_str);
316
317
	}

318
319
	free(buf);

320
321
322
323
	return(JS_TRUE);
}

static JSBool
324
js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
325
326
327
328
329
330
331
{
	BYTE		b;
	WORD		w;
	DWORD		l;
	size_t		size=sizeof(DWORD);
	private_t*	p;

332
	*rval = INT_TO_JSVAL(-1);
333

334
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
335
		JS_ReportError(cx,getprivate_failure,WHERE);
336
		return(JS_FALSE);
337
	}
338
339
340
341

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

342
	if(argc) 
343
		JS_ValueToInt32(cx,argv[0],(int32*)&size);
344
345
346

	switch(size) {
		case sizeof(BYTE):
347
348
			if(fread(&b,1,size,p->fp)==size)
				*rval = INT_TO_JSVAL(b);
349
350
			break;
		case sizeof(WORD):
351
352
353
			if(fread(&w,1,size,p->fp)==size) {
				if(p->network_byte_order)
					w=ntohs(w);
354
				*rval = INT_TO_JSVAL(w);
355
			}
356
357
			break;
		case sizeof(DWORD):
358
359
360
			if(fread(&l,1,size,p->fp)==size) {
				if(p->network_byte_order)
					l=ntohl(l);
361
				JS_NewNumberValue(cx,l,rval);
362
			}
363
364
365
366
367
368
369
			break;
	}
		
	return(JS_TRUE);
}

static JSBool
370
js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
371
{
372
373
374
    jsint       len=0;
    jsval       line;
    JSObject*	array;
375
376
	private_t*	p;

377
378
	*rval = JSVAL_NULL;

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

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

387
    array = JS_NewArrayObject(cx, 0, NULL);
388

389
390
391
392
    while(!feof(p->fp)) {
		js_readln(cx, obj, 0, NULL, &line); 
		if(line==JSVAL_NULL)
			break;
393
394
        if(!JS_SetElement(cx, array, len++, &line))
			break;
395
	}
396
    *rval = OBJECT_TO_JSVAL(array);
397

398
399
    return(JS_TRUE);
}
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
static JSBool
js_ini_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*	section;
	char*	key;
	jsval	dflt=argv[2];
	private_t*	p;

	*rval = JSVAL_NULL;

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

	section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
	key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
	switch(JSVAL_TAG(dflt)) {
		case JSVAL_STRING:
			*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,
				iniReadString(p->fp,section,key
					,JS_GetStringBytes(JS_ValueToString(cx,dflt)))));
			break;
		case JSVAL_BOOLEAN:
			*rval = BOOLEAN_TO_JSVAL(
				iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
			break;
		case JSVAL_DOUBLE:
			JS_NewNumberValue(cx
				,iniReadFloat(p->fp,section,key,*JSVAL_TO_DOUBLE(dflt)),rval);
			break;
		default:
			if(JSVAL_IS_INT(dflt)) {
				*rval = INT_TO_JSVAL(
					iniReadInteger(p->fp,section,key,JSVAL_TO_INT(dflt)));
				break;
			}
			break;
	}

	return(JS_TRUE);
}

444
445
446
447
static JSBool
js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		cp;
448
449
450
	char*		uubuf=NULL;
	int			len;	/* string length */
	int			tlen;	/* total length to write (may be greater than len) */
451
	private_t*	p;
452

453
	*rval = JSVAL_FALSE;
454

455
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
456
		JS_ReportError(cx,getprivate_failure,WHERE);
457
		return(JS_FALSE);
458
	}
459
460
461
462

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

463
464
465
	cp=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
	len=strlen(cp);

466
467
468
469
470
471
	if((p->uuencoded || p->b64encoded)
		&& len && (uubuf=malloc(len))!=NULL) {
		if(p->uuencoded)
			len=uudecode(uubuf,len,cp,len);
		else
			len=b64_decode(uubuf,len,cp,len);
472
473
474
475
476
477
478
		if(len<0) {
			free(uubuf);
			return(JS_TRUE);
		}
		cp=uubuf;
	}

479
480
481
	if(p->rot13)
		rot13(cp);

482
	tlen=len;
483
	if(argc>1) {
484
		JS_ValueToInt32(cx,argv[1],(int32*)&tlen);
485
486
487
		if(len>tlen)
			len=tlen;
	}
488
489

	if(fwrite(cp,1,len,p->fp)==(size_t)len) {
490
491
492
493
494
495
496
497
498
499
500
		if(tlen>len) {
			len=tlen-len;
			if((cp=malloc(len))==NULL) {
				dbprintf(TRUE, p, "malloc failure of %u bytes", len);
				return(JS_TRUE);
			}
			memset(cp,p->etx,len);
			fwrite(cp,1,len,p->fp);
			free(cp);
		}
		dbprintf(FALSE, p, "wrote %u bytes",tlen);
501
		*rval = JSVAL_TRUE;
502
503
	} else 
		dbprintf(TRUE, p, "write of %u bytes failed",len);
504
		
505
506
507
	if(uubuf!=NULL)
		free(uubuf);

508
509
510
511
	return(JS_TRUE);
}

static JSBool
512
js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
513
{
514
515
516
517
	char*		cp="";
	JSString*	str;
	private_t*	p;

518
	*rval = JSVAL_FALSE;
519

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

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

	if(argc) {
529
530
		if((str = JS_ValueToString(cx, argv[0]))==NULL) {
			JS_ReportError(cx,"JS_ValueToString failed");
531
			return(JS_FALSE);
532
		}
533
534
535
		cp = JS_GetStringBytes(str);
	}

536
537
538
	if(p->rot13)
		rot13(cp);

539
	if(fprintf(p->fp,"%s\n",cp)!=0)
540
		*rval = JSVAL_TRUE;
541

542
543
	return(JS_TRUE);
}
544

545
static JSBool
546
js_writebin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
547
{
548
549
550
	BYTE		b;
	WORD		w;
	DWORD		l;
551
	int32		val=0;
552
	size_t		wr=0;
553
	size_t		size=sizeof(DWORD);
554
555
	private_t*	p;

556
	*rval = JSVAL_FALSE;
557

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

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

566
	JS_ValueToInt32(cx,argv[0],&val);
567
	if(argc>1) 
568
		JS_ValueToInt32(cx,argv[1],(int32*)&size);
569

570
571
	switch(size) {
		case sizeof(BYTE):
572
			b = (BYTE)val;
573
			wr=fwrite(&b,1,size,p->fp);
574
575
			break;
		case sizeof(WORD):
576
			w = (WORD)val;
577
578
			if(p->network_byte_order)
				w=htons(w);
579
			wr=fwrite(&w,1,size,p->fp);
580
581
			break;
		case sizeof(DWORD):
582
			l = val;
583
584
			if(p->network_byte_order)
				l=htonl(l);
585
586
587
588
589
			wr=fwrite(&l,1,size,p->fp);
			break;
		default:	
			/* unknown size */
			dbprintf(TRUE, p, "unsupported binary write size: %d",size);
590
591
			break;
	}
592
	if(wr==size)
593
		*rval = JSVAL_TRUE;
594
		
595
596
597
	return(JS_TRUE);
}

598
599
600
601
602
603
604
605
606
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;

607
	*rval = JSVAL_FALSE;
608

609
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
610
		JS_ReportError(cx,getprivate_failure,WHERE);
611
		return(JS_FALSE);
612
	}
613
614
615
616

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

617
	if(!JSVAL_IS_OBJECT(argv[0]))
618
619
620
621
		return(JS_TRUE);

    array = JSVAL_TO_OBJECT(argv[0]);

622
623
624
    if(!JS_IsArrayObject(cx, array))
		return(JS_TRUE);

625
626
    if(!JS_GetArrayLength(cx, array, &limit))
		return(JS_FALSE);
627

628
    *rval = JSVAL_TRUE;
629

630
631
632
633
    for(i=0;i<limit;i++) {
        if(!JS_GetElement(cx, array, i, &elemval))
			break;
        js_writeln(cx, obj, 1, &elemval, rval);
634
		if(*rval!=JSVAL_TRUE)
635
			break;
636
637
638
639
640
    }

    return(JS_TRUE);
}

641
static JSBool
642
js_lock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
643
{
644
645
	int32		offset=0;
	int32		len=0;
646
647
	private_t*	p;

648
	*rval = JSVAL_FALSE;
649

650
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
651
		JS_ReportError(cx,getprivate_failure,WHERE);
652
		return(JS_FALSE);
653
	}
654
655
656
657

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

658
659
660
661
662
663
664
665
666
667
668
669
	/* offset */
	if(argc)
		JS_ValueToInt32(cx,argv[0],&offset);

	/* length */
	if(argc>1)
		JS_ValueToInt32(cx,argv[1],&len);

	if(len==0)
		len=filelength(fileno(p->fp))-offset;

	if(lock(fileno(p->fp),offset,len)==0)
670
		*rval = JSVAL_TRUE;
671

672
673
	return(JS_TRUE);
}
674

675
static JSBool
676
js_unlock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
677
{
678
679
	int32		offset=0;
	int32		len=0;
680
681
	private_t*	p;

682
	*rval = JSVAL_FALSE;
683

684
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
685
		JS_ReportError(cx,getprivate_failure,WHERE);
686
		return(JS_FALSE);
687
	}
688
689
690
691

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

692
693
694
695
696
697
698
699
700
701
702
	/* offset */
	if(argc)
		JS_ValueToInt32(cx,argv[0],&offset);

	/* length */
	if(argc>1)
		JS_ValueToInt32(cx,argv[1],&len);

	if(len==0)
		len=filelength(fileno(p->fp))-offset;

703
	if(unlock(fileno(p->fp),offset,len)==0)
704
		*rval = JSVAL_TRUE;
705

706
707
708
	return(JS_TRUE);
}

709
710
711
712
713
static JSBool
js_delete(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	private_t*	p;

714
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
715
		JS_ReportError(cx,getprivate_failure,WHERE);
716
		return(JS_FALSE);
717
	}
718
719
720
721
722
723
724
725
726
727

	if(p->fp!=NULL) {	/* close it if it's open */
		fclose(p->fp);
		p->fp=NULL;
	}

	*rval = BOOLEAN_TO_JSVAL(remove(p->name)==0);

	return(JS_TRUE);
}
728
729
730
731
732
733

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

734
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
735
		JS_ReportError(cx,getprivate_failure,WHERE);
736
		return(JS_FALSE);
737
	}
738
739

	if(p->fp==NULL)
740
		*rval = JSVAL_FALSE;
741
742
743
744
745
746
747
748
749
750
751
	else 
		*rval = BOOLEAN_TO_JSVAL(fflush(p->fp)==0);

	return(JS_TRUE);
}

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

752
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
753
		JS_ReportError(cx,getprivate_failure,WHERE);
754
		return(JS_FALSE);
755
	}
756
757

	if(p->fp==NULL)
758
		*rval = JSVAL_FALSE;
759
760
	else  {
		clearerr(p->fp);
761
		*rval = JSVAL_TRUE;
762
763
764
765
766
	}

	return(JS_TRUE);
}

767
768
769
770
771
772
773
774
775
776
static JSBool
js_fprintf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char*		cp;
    uintN		i;
	JSString *	fmt;
    JSString *	str;
	va_list		arglist[64];
	private_t*	p;

777
	*rval = JSVAL_FALSE;
778

779
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
780
		JS_ReportError(cx,getprivate_failure,WHERE);
781
		return(JS_FALSE);
782
	}
783
784
785
786

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

787
788
	if((fmt=JS_ValueToString(cx, argv[0]))==NULL) {
		JS_ReportError(cx,"JS_ValueToString failed");
789
		return(JS_FALSE);
790
	}
791
792
793
794
795

	memset(arglist,0,sizeof(arglist));	/* Initialize arglist to NULLs */

    for (i = 1; i < argc && i<sizeof(arglist)/sizeof(arglist[0]); i++) {
		if(JSVAL_IS_STRING(argv[i])) {
796
797
			if((str=JS_ValueToString(cx, argv[i]))==NULL) {
				JS_ReportError(cx,"JS_ValueToString failed");
798
			    return(JS_FALSE);
799
			}
800
801
802
803
804
805
806
807
808
809
			arglist[i-1]=JS_GetStringBytes(str);	/* exception here July-29-2002 */
		}
		else if(JSVAL_IS_DOUBLE(argv[i]))
			arglist[i-1]=(char*)(unsigned long)*JSVAL_TO_DOUBLE(argv[i]);
		else if(JSVAL_IS_INT(argv[i]) || JSVAL_IS_BOOLEAN(argv[i]))
			arglist[i-1]=(char *)JSVAL_TO_INT(argv[i]);
		else
			arglist[i-1]=NULL;
	}

810
811
	if((cp=JS_vsmprintf(JS_GetStringBytes(fmt),(char*)arglist))==NULL) {
		JS_ReportError(cx,"JS_vsmprintf failed");
812
		return(JS_FALSE);
813
	}
814
815
816
817
818
819
820

	*rval = INT_TO_JSVAL(fwrite(cp,1,strlen(cp),p->fp));
	JS_smprintf_free(cp);
	
    return(JS_TRUE);
}

821
822
823
824

/* File Object Properites */
enum {
	 FILE_PROP_NAME		
825
826
	,FILE_PROP_MODE
	,FILE_PROP_ETX
827
828
829
830
831
832
833
834
835
836
	,FILE_PROP_EXISTS	
	,FILE_PROP_DATE		
	,FILE_PROP_IS_OPEN	
	,FILE_PROP_EOF		
	,FILE_PROP_ERROR	
	,FILE_PROP_DESCRIPTOR
	,FILE_PROP_DEBUG	
	,FILE_PROP_POSITION	
	,FILE_PROP_LENGTH	
	,FILE_PROP_ATTRIBUTES
837
	,FILE_PROP_UUENCODED
838
	,FILE_PROP_B64ENCODED
839
	,FILE_PROP_ROT13
840
	,FILE_PROP_NETWORK_ORDER
841
842
843
844
845
	/* dynamically calculated */
	,FILE_PROP_CHKSUM
	,FILE_PROP_CRC16
	,FILE_PROP_CRC32
	,FILE_PROP_MD5_HEX
846
	,FILE_PROP_MD5_B64
847
848
};

rswindell's avatar
rswindell committed
849

850
851
852
853
854
static JSBool js_file_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    jsint       tiny;
	private_t*	p;

855
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
856
		JS_ReportError(cx,getprivate_failure,WHERE);
857
		return(JS_FALSE);
858
	}
859
860
861
862
863
864
865

    tiny = JSVAL_TO_INT(id);

	dbprintf(FALSE, p, "setting property %d",tiny);

	switch(tiny) {
		case FILE_PROP_DEBUG:
866
			JS_ValueToBoolean(cx,*vp,&(p->debug));
867
			break;
868
		case FILE_PROP_UUENCODED:
869
870
871
872
873
			JS_ValueToBoolean(cx,*vp,&(p->uuencoded));
			break;
		case FILE_PROP_B64ENCODED:
			JS_ValueToBoolean(cx,*vp,&(p->b64encoded));
			break;
874
875
876
		case FILE_PROP_ROT13:
			JS_ValueToBoolean(cx,*vp,&(p->rot13));
			break;
877
878
		case FILE_PROP_NETWORK_ORDER:
			JS_ValueToBoolean(cx,*vp,&(p->network_byte_order));
879
			break;
880
881
882
883
884
885
886
887
888
889
890
		case FILE_PROP_POSITION:
			if(p->fp!=NULL)
				fseek(p->fp,JSVAL_TO_INT(*vp),SEEK_SET);
			break;
		case FILE_PROP_LENGTH:
			if(p->fp!=NULL)
				chsize(fileno(p->fp),JSVAL_TO_INT(*vp));
			break;
		case FILE_PROP_ATTRIBUTES:
			CHMOD(p->name,JSVAL_TO_INT(*vp));
			break;
891
892
893
		case FILE_PROP_ETX:
			p->etx = (uchar)JSVAL_TO_INT(*vp);
			break;
894
895
896
897
898
899
900
	}

	return(JS_TRUE);
}

static JSBool js_file_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
901
902
903
904
905
906
	BYTE*		buf;
	long		l;
	long		len;
	long		offset;
	ulong		sum;
	BYTE		digest[MD5_DIGEST_SIZE];
907
    jsint       tiny;
908
	JSString*	js_str=NULL;
909
910
	private_t*	p;

911
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
912
		JS_ReportError(cx,getprivate_failure,WHERE);
913
		return(JS_FALSE);
914
	}
915
916
917
918
919
920
921
922
923

    tiny = JSVAL_TO_INT(id);

#if 0 /* just too much */
	dbprintf(FALSE, sock, "getting property %d",tiny);
#endif

	switch(tiny) {
		case FILE_PROP_NAME:
924
925
926
			if((js_str=JS_NewStringCopyZ(cx, p->name))==NULL)
				return(JS_FALSE);
			*vp = STRING_TO_JSVAL(js_str);
927
928
			break;
		case FILE_PROP_MODE:
929
930
931
			if((js_str=JS_NewStringCopyZ(cx, p->mode))==NULL)
				return(JS_FALSE);
			*vp = STRING_TO_JSVAL(js_str);
932
933
934
			break;
		case FILE_PROP_EXISTS:
			if(p->fp)	/* open? */
935
				*vp = JSVAL_TRUE;
936
937
938
939
			else
				*vp = BOOLEAN_TO_JSVAL(fexist(p->name));
			break;
		case FILE_PROP_DATE:
940
			JS_NewNumberValue(cx,fdate(p->name),vp);
941
942
943
944
945
			break;
		case FILE_PROP_IS_OPEN:
			*vp = BOOLEAN_TO_JSVAL(p->fp!=NULL);
			break;
		case FILE_PROP_EOF:
946
947
948
			if(p->fp)
				*vp = BOOLEAN_TO_JSVAL(feof(p->fp)!=0);
			else
949
				*vp = JSVAL_TRUE;
950
951
			break;
		case FILE_PROP_ERROR:
952
953
954
			if(p->fp)
				*vp = INT_TO_JSVAL(ferror(p->fp));
			else
955
				*vp = INT_TO_JSVAL(errno);
956
957
			break;
		case FILE_PROP_POSITION:
958
			if(p->fp)
959
				JS_NewNumberValue(cx,ftell(p->fp),vp);
960
961
			else
				*vp = INT_TO_JSVAL(-1);
962
963
964
			break;
		case FILE_PROP_LENGTH:
			if(p->fp)	/* open? */
965
				JS_NewNumberValue(cx,filelength(fileno(p->fp)),vp);
966
			else
967
				JS_NewNumberValue(cx,flength(p->name),vp);
968
969
			break;
		case FILE_PROP_ATTRIBUTES:
970
			JS_NewNumberValue(cx,getfattr(p->name),vp);
971
972
			break;
		case FILE_PROP_DEBUG:
973
974
975
976
			*vp = BOOLEAN_TO_JSVAL(p->debug);
			break;
		case FILE_PROP_UUENCODED:
			*vp = BOOLEAN_TO_JSVAL(p->uuencoded);
977
			break;
978
979
980
		case FILE_PROP_B64ENCODED:
			*vp = BOOLEAN_TO_JSVAL(p->b64encoded);
			break;
981
982
983
		case FILE_PROP_ROT13:
			*vp = BOOLEAN_TO_JSVAL(p->rot13);
			break;
984
985
986
		case FILE_PROP_NETWORK_ORDER:
			*vp = BOOLEAN_TO_JSVAL(p->network_byte_order);
			break;
987
		case FILE_PROP_DESCRIPTOR:
988
989
990
991
			if(p->fp)
				*vp = INT_TO_JSVAL(fileno(p->fp));
			else
				*vp = INT_TO_JSVAL(-1);
992
			break;
993
994
995
		case FILE_PROP_ETX:
			*vp = INT_TO_JSVAL(p->etx);
			break;
996
997
998
		case FILE_PROP_CHKSUM:
		case FILE_PROP_CRC16:
		case FILE_PROP_CRC32:
999
1000
1001
1002
			*vp = JSVAL_ZERO;
			if(p->fp==NULL)
				break;
			/* fall-through */
1003
		case FILE_PROP_MD5_HEX:
1004
		case FILE_PROP_MD5_B64:
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
			*vp = JSVAL_VOID;
			if(p->fp==NULL)
				break;
			offset=ftell(p->fp);			/* save current file position */
			fseek(p->fp,0,SEEK_SET);
			len=filelength(fileno(p->fp));
			if(len<1)
				break;
			if((buf=malloc(len*2))==NULL)
				break;
			len=fread(buf,sizeof(BYTE),len,p->fp);
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
			if(len>0) 
				switch(tiny) {
					case FILE_PROP_CHKSUM:
						for(sum=l=0;l<len;l++)
							sum+=buf[l];
						JS_NewNumberValue(cx,sum,vp);
						break;
					case FILE_PROP_CRC16:
						JS_NewNumberValue(cx,crc16(buf,len),vp);
						break;
					case FILE_PROP_CRC32:
						JS_NewNumberValue(cx,crc32(buf,len),vp);
						break;
					case FILE_PROP_MD5_HEX:
						MD5_calc(digest,buf,len);
						MD5_hex(buf,digest);
						js_str=JS_NewStringCopyZ(cx, buf);
						break;
					case FILE_PROP_MD5_B64:
						MD5_calc(digest,buf,len);
						b64_encode(buf,len*2,digest,sizeof(digest));
						js_str=JS_NewStringCopyZ(cx, buf);
						break;
				}
1040
1041
1042
1043
1044
			free(buf);
			fseek(p->fp,offset,SEEK_SET);	/* restore saved file position */
			if(js_str!=NULL)
				*vp = STRING_TO_JSVAL(js_str);
			break;
1045
1046
	}

1047
	return(JS_TRUE);
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
}

#define FILE_PROP_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY

static struct JSPropertySpec js_file_properties[] = {
/*		 name				,tinyid					,flags,				getter,	setter	*/
	{	"name"				,FILE_PROP_NAME			,FILE_PROP_FLAGS,	NULL,NULL},
	{	"mode"				,FILE_PROP_MODE			,FILE_PROP_FLAGS,	NULL,NULL},
	{	"exists"			,FILE_PROP_EXISTS		,FILE_PROP_FLAGS,	NULL,NULL},
	{	"date"				,FILE_PROP_DATE			,FILE_PROP_FLAGS,	NULL,NULL},
	{	"is_open"			,FILE_PROP_IS_OPEN		,FILE_PROP_FLAGS,	NULL,NULL},
	{	"eof"				,FILE_PROP_EOF			,FILE_PROP_FLAGS,	NULL,NULL},
	{	"error"				,FILE_PROP_ERROR		,FILE_PROP_FLAGS,	NULL,NULL},
	{	"descriptor"		,FILE_PROP_DESCRIPTOR	,FILE_PROP_FLAGS,	NULL,NULL},
	/* writeable */
1063
	{	"etx"				,FILE_PROP_ETX			,JSPROP_ENUMERATE,  NULL,NULL},
1064
1065
1066
1067
	{	"debug"				,FILE_PROP_DEBUG		,JSPROP_ENUMERATE,	NULL,NULL},
	{	"position"			,FILE_PROP_POSITION		,JSPROP_ENUMERATE,	NULL,NULL},
	{	"length"			,FILE_PROP_LENGTH		,JSPROP_ENUMERATE,	NULL,NULL},
	{	"attributes"		,FILE_PROP_ATTRIBUTES	,JSPROP_ENUMERATE,	NULL,NULL},
1068
	{	"network_byte_order",FILE_PROP_NETWORK_ORDER,JSPROP_ENUMERATE,	NULL,NULL},
1069
	{	"rot13"				,FILE_PROP_ROT13		,JSPROP_ENUMERATE,	NULL,NULL},
1070
1071
	{	"uue"				,FILE_PROP_UUENCODED	,JSPROP_ENUMERATE,	NULL,NULL},
	{	"base64"			,FILE_PROP_B64ENCODED	,JSPROP_ENUMERATE,	NULL,NULL},
1072
1073
1074
	/* dynamically calculated */
	{	"crc16"				,FILE_PROP_CRC16		,FILE_PROP_FLAGS,	NULL,NULL},
	{	"crc32"				,FILE_PROP_CRC32		,FILE_PROP_FLAGS,	NULL,NULL},
1075
	{	"chksum"			,FILE_PROP_CHKSUM		,FILE_PROP_FLAGS,	NULL,NULL},
1076
	{	"md5_hex"			,FILE_PROP_MD5_HEX		,FILE_PROP_FLAGS,	NULL,NULL},
1077
	{	"md5_base64"		,FILE_PROP_MD5_B64		,FILE_PROP_FLAGS,	NULL,NULL},
1078
1079
1080