|
|
1.1 root 1: /* js_file.c */
2:
3: /* Synchronet JavaScript "File" Object */
4:
5: /* $Id: js_file.c,v 1.99 2006/07/21 04:26:17 deuce Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "md5.h"
40: #include "base64.h"
41: #include "uucode.h"
42: #include "yenc.h"
43: #include "ini_file.h"
44:
45: #ifdef JAVASCRIPT
46:
47: #include "jsdate.h" /* Yes, I know this is a private header file */
48:
49: typedef struct
50: {
51: FILE* fp;
52: char name[MAX_PATH+1];
53: char mode[4];
54: uchar etx;
55: BOOL external; /* externally created, don't close */
56: BOOL debug;
57: BOOL rot13;
58: BOOL yencoded;
59: BOOL uuencoded;
60: BOOL b64encoded;
61: BOOL network_byte_order;
62:
63: } private_t;
64:
65: static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
66:
67: static void dbprintf(BOOL error, private_t* p, char* fmt, ...)
68: {
69: va_list argptr;
70: char sbuf[1024];
71:
72: if(p==NULL || (!p->debug && !error))
73: return;
74:
75: va_start(argptr,fmt);
76: vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
77: sbuf[sizeof(sbuf)-1]=0;
78: va_end(argptr);
79:
80: lprintf(LOG_DEBUG,"%04u File %s%s",p->fp ? fileno(p->fp) : 0,error ? "ERROR: ":"",sbuf);
81: }
82:
83: /* Converts fopen() style 'mode' string into open() style 'flags' integer */
84:
85: static int fopenflags(char *mode)
86: {
87: int flags=0;
88:
89: if(strchr(mode,'b'))
90: flags|=O_BINARY;
91: else
92: flags|=O_TEXT;
93:
94: if(strchr(mode,'w')) {
95: flags|=O_CREAT|O_TRUNC;
96: if(strchr(mode,'+'))
97: flags|=O_RDWR;
98: else
99: flags|=O_WRONLY;
100: return(flags);
101: }
102:
103: if(strchr(mode,'a')) {
104: flags|=O_CREAT|O_APPEND;
105: if(strchr(mode,'+'))
106: flags|=O_RDWR;
107: else
108: flags|=O_WRONLY;
109: return(flags);
110: }
111:
112: if(strchr(mode,'r')) {
113: if(strchr(mode,'+'))
114: flags|=O_RDWR;
115: else
116: flags|=O_RDONLY;
117: }
118:
119: if(strchr(mode,'e'))
120: flags|=O_EXCL;
121:
122: return(flags);
123: }
124:
125: /* File Object Methods */
126:
127: static JSBool
128: js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
129: {
130: char* mode="w+"; /* default mode */
131: BOOL shareable=FALSE;
132: int file;
133: uintN i;
134: jsint bufsize=2*1024;
135: JSString* str;
136: private_t* p;
137:
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: if(p->fp!=NULL)
146: return(JS_TRUE);
147:
148: for(i=0;i<argc;i++) {
149: if(JSVAL_IS_STRING(argv[i])) { /* mode */
150: if((str = JS_ValueToString(cx, argv[i]))==NULL) {
151: JS_ReportError(cx,"Invalid mode specified: %s",str);
152: return(JS_TRUE);
153: }
154: mode=JS_GetStringBytes(str);
155: } else if(JSVAL_IS_BOOLEAN(argv[i])) /* shareable */
156: shareable=JSVAL_TO_BOOLEAN(argv[i]);
157: else if(JSVAL_IS_NUMBER(argv[i])) { /* bufsize */
158: if(!JS_ValueToInt32(cx,argv[i],&bufsize))
159: return(JS_FALSE);
160: }
161: }
162: SAFECOPY(p->mode,mode);
163:
164: if(shareable)
165: p->fp=fopen(p->name,p->mode);
166: else {
167: if((file=nopen(p->name,fopenflags(p->mode)))!=-1) {
168: if((p->fp=fdopen(file,p->mode))==NULL)
169: close(file);
170: }
171: }
172: if(p->fp!=NULL) {
173: *rval = JSVAL_TRUE;
174: dbprintf(FALSE, p, "opened: %s",p->name);
175: if(!bufsize)
176: setvbuf(p->fp,NULL,_IONBF,0); /* no buffering */
177: else
178: setvbuf(p->fp,NULL,_IOFBF,bufsize);
179: }
180:
181: return(JS_TRUE);
182: }
183:
184:
185: static JSBool
186: js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
187: {
188: private_t* p;
189:
190: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
191: JS_ReportError(cx,getprivate_failure,WHERE);
192: return(JS_FALSE);
193: }
194:
195: if(p->fp==NULL)
196: return(JS_TRUE);
197:
198: fclose(p->fp);
199:
200: dbprintf(FALSE, p, "closed");
201:
202: p->fp=NULL;
203:
204: return(JS_TRUE);
205: }
206:
207: 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: int32 len;
214: int32 offset;
215: int32 uulen;
216: JSString* str;
217: private_t* p;
218:
219: *rval = JSVAL_NULL;
220:
221: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
222: JS_ReportError(cx,getprivate_failure,WHERE);
223: return(JS_FALSE);
224: }
225:
226: if(p->fp==NULL)
227: return(JS_TRUE);
228:
229: if(argc) {
230: if(!JS_ValueToInt32(cx,argv[0],&len))
231: return(JS_FALSE);
232: } else {
233: len=filelength(fileno(p->fp));
234: offset=ftell(p->fp);
235: if(offset>0)
236: len-=offset;
237: }
238: if(len<0)
239: len=512;
240:
241: if((buf=malloc(len+1))==NULL)
242: return(JS_TRUE);
243:
244: len = fread(buf,1,len,p->fp);
245: if(len<0)
246: len=0;
247: buf[len]=0;
248:
249: if(p->etx) {
250: cp=strchr(buf,p->etx);
251: if(cp) *cp=0;
252: len=strlen(buf);
253: }
254:
255: if(p->rot13)
256: rot13(buf);
257:
258: if(p->uuencoded || p->b64encoded || p->yencoded) {
259: uulen=len*2;
260: if((uubuf=malloc(uulen))==NULL) {
261: free(buf);
262: return(JS_TRUE);
263: }
264: if(p->uuencoded)
265: uulen=uuencode(uubuf,uulen,buf,len);
266: else if(p->yencoded)
267: uulen=yencode(uubuf,uulen,buf,len);
268: else
269: uulen=b64_encode(uubuf,uulen,buf,len);
270: if(uulen>=0) {
271: free(buf);
272: buf=uubuf;
273: len=uulen;
274: }
275: else
276: free(uubuf);
277: }
278:
279: str = JS_NewStringCopyN(cx, buf, len);
280: free(buf);
281:
282: if(str==NULL)
283: return(JS_FALSE);
284:
285: *rval = STRING_TO_JSVAL(str);
286:
287: dbprintf(FALSE, p, "read %u bytes",len);
288:
289: return(JS_TRUE);
290: }
291:
292: static JSBool
293: js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
294: {
295: char* cp;
296: char* buf;
297: int32 len=512;
298: JSString* js_str;
299: private_t* p;
300:
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: if(p->fp==NULL)
309: return(JS_TRUE);
310:
311: if(argc) {
312: if(!JS_ValueToInt32(cx,argv[0],&len))
313: return(JS_FALSE);
314: }
315:
316: if((buf=alloca(len))==NULL)
317: return(JS_TRUE);
318:
319: if(fgets(buf,len,p->fp)!=NULL) {
320: len=strlen(buf);
321: while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n'))
322: len--;
323: buf[len]=0;
324: if(p->etx) {
325: cp=strchr(buf,p->etx);
326: if(cp) *cp=0;
327: }
328: if(p->rot13)
329: rot13(buf);
330: if((js_str=JS_NewStringCopyZ(cx,buf))!=NULL) /* exception here Feb-12-2005 */
331: *rval = STRING_TO_JSVAL(js_str); /* _CrtDbgBreak from _heap_alloc_dbg */
332: }
333:
334: return(JS_TRUE);
335: }
336:
337: static JSBool
338: js_readbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
339: {
340: BYTE b;
341: WORD w;
342: DWORD l;
343: size_t size=sizeof(DWORD);
344: private_t* p;
345:
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: if(p->fp==NULL)
354: return(JS_TRUE);
355:
356: if(argc) {
357: if(!JS_ValueToInt32(cx,argv[0],(int32*)&size))
358: return(JS_FALSE);
359: }
360:
361: switch(size) {
362: case sizeof(BYTE):
363: if(fread(&b,1,size,p->fp)==size)
364: *rval = INT_TO_JSVAL(b);
365: break;
366: case sizeof(WORD):
367: if(fread(&w,1,size,p->fp)==size) {
368: if(p->network_byte_order)
369: w=ntohs(w);
370: *rval = INT_TO_JSVAL(w);
371: }
372: break;
373: case sizeof(DWORD):
374: if(fread(&l,1,size,p->fp)==size) {
375: if(p->network_byte_order)
376: l=ntohl(l);
377: JS_NewNumberValue(cx,l,rval);
378: }
379: break;
380: }
381:
382: return(JS_TRUE);
383: }
384:
385: static JSBool
386: js_readall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
387: {
388: jsint len=0;
389: jsval line;
390: JSObject* array;
391: private_t* p;
392:
393: *rval = JSVAL_NULL;
394:
395: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
396: JS_ReportError(cx,getprivate_failure,WHERE);
397: return(JS_FALSE);
398: }
399:
400: if(p->fp==NULL)
401: 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: if(line==JSVAL_NULL)
408: break;
409: if(!JS_SetElement(cx, array, len++, &line))
410: break;
411: }
412: *rval = OBJECT_TO_JSVAL(array);
413:
414: return(JS_TRUE);
415: }
416:
417: static jsval get_value(JSContext *cx, char* value)
418: {
419: char* p;
420: BOOL f=FALSE;
421: jsval val;
422:
423: if(value==NULL || *value==0)
424: return(JSVAL_VOID);
425:
426: /* integer or float? */
427: for(p=value;*p;p++) {
428: if(*p=='.' && !f)
429: f=TRUE;
430: else if(!isdigit(*p))
431: break;
432: }
433: if(*p==0) {
434: JS_NewNumberValue(cx, f ? atof(value) : strtoul(value,NULL,10), &val);
435: return(val);
436: }
437: /* hexadecimal number? */
438: if(!strncmp(value,"0x",2)) {
439: for(p=value+2;*p;p++)
440: if(!isxdigit(*p))
441: break;
442: if(*p==0) {
443: JS_NewNumberValue(cx,strtoul(value,NULL,0),&val);
444: return(val);
445: }
446: }
447: /* Boolean? */
448: if(!stricmp(value,"true"))
449: return(JSVAL_TRUE);
450: if(!stricmp(value,"false"))
451: return(JSVAL_FALSE);
452:
453: /* String */
454: return(STRING_TO_JSVAL(JS_NewStringCopyZ(cx,value)));
455: }
456:
457: static JSBool
458: js_iniGetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
459: {
460: char* section=ROOT_SECTION;
461: char* key;
462: char** list;
463: char buf[INI_MAX_VALUE_LEN];
464: int32 i;
465: jsval val;
466: jsval dflt=argv[2];
467: private_t* p;
468: JSObject* array;
469: JSObject* dflt_obj;
470: JSObject* date_obj;
471:
472: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
473: JS_ReportError(cx,getprivate_failure,WHERE);
474: return(JS_FALSE);
475: }
476:
477: if(p->fp==NULL)
478: return(JS_TRUE);
479:
480: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
481: 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: return(JS_TRUE);
487: }
488:
489: switch(JSVAL_TAG(dflt)) {
490: case JSVAL_BOOLEAN:
491: *rval = BOOLEAN_TO_JSVAL(
492: iniReadBool(p->fp,section,key,JSVAL_TO_BOOLEAN(dflt)));
493: break;
494: case JSVAL_DOUBLE:
495: 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: date_obj = js_NewDateObjectMsec(cx
501: ,(jsdouble)iniReadDateTime(p->fp,section,key
502: ,(time_t)(js_DateGetMsecSinceEpoch(cx,dflt_obj)/1000.0))
503: *1000.0);
504: if(date_obj!=NULL)
505: *rval = OBJECT_TO_JSVAL(date_obj);
506: break;
507: }
508: array = JS_NewArrayObject(cx, 0, NULL);
509: list=iniReadStringList(p->fp,section,key,",",JS_GetStringBytes(JS_ValueToString(cx,dflt)));
510: for(i=0;list && list[i];i++) {
511: val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
512: if(!JS_SetElement(cx, array, i, &val))
513: break;
514: }
515: iniFreeStringList(list);
516: *rval = OBJECT_TO_JSVAL(array);
517: break;
518: default:
519: if(JSVAL_IS_NUMBER(dflt)) {
520: if(!JS_ValueToInt32(cx,dflt,&i))
521: return(JS_FALSE);
522: JS_NewNumberValue(cx,iniReadInteger(p->fp,section,key,i),rval);
523: } else
524: *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx
525: ,iniReadString(p->fp,section,key,JS_GetStringBytes(JS_ValueToString(cx,dflt)),buf)));
526: break;
527: }
528:
529: return(JS_TRUE);
530: }
531:
532: static JSBool
533: js_iniSetValue(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
534: {
535: char* section=ROOT_SECTION;
536: char* key;
537: char* result=NULL;
538: int32 i;
539: jsval value=argv[2];
540: private_t* p;
541: str_list_t list;
542: JSObject* value_obj;
543:
544: *rval = JSVAL_FALSE;
545:
546: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
547: JS_ReportError(cx,getprivate_failure,WHERE);
548: return(JS_FALSE);
549: }
550:
551: if(p->fp==NULL)
552: return(JS_TRUE);
553:
554: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
555: section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
556: key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
557:
558: if((list=iniReadFile(p->fp))==NULL)
559: return(JS_TRUE);
560:
561: if(value==JSVAL_VOID) /* unspecified value */
562: result = iniSetString(&list,section,key,"",NULL);
563: else {
564:
565: switch(JSVAL_TAG(value)) {
566: case JSVAL_BOOLEAN:
567: result = iniSetBool(&list,section,key,JSVAL_TO_BOOLEAN(value),NULL);
568: break;
569: case JSVAL_DOUBLE:
570: result = iniSetFloat(&list,section,key,*JSVAL_TO_DOUBLE(value),NULL);
571: break;
572: default:
573: if(JSVAL_IS_NUMBER(value)) {
574: if(!JS_ValueToInt32(cx,value,&i))
575: return(JS_FALSE);
576: result = iniSetInteger(&list,section,key,i,NULL);
577: } else {
578: if(JSVAL_IS_OBJECT(value)
579: && (value_obj = JSVAL_TO_OBJECT(value))!=NULL
580: && js_DateIsValid(cx, value_obj)) {
581: result = iniSetDateTime(&list,section,key,/* include_time */TRUE
582: ,(time_t)(js_DateGetMsecSinceEpoch(cx,value_obj)/1000.0),NULL);
583: } else
584: result = iniSetString(&list,section,key
585: ,JS_GetStringBytes(JS_ValueToString(cx,value)),NULL);
586: }
587: break;
588: }
589: }
590:
591: if(result != NULL)
592: *rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
593:
594: strListFree(&list);
595:
596: return(JS_TRUE);
597: }
598:
599: static JSBool
600: js_iniRemoveKey(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
601: {
602: char* section=ROOT_SECTION;
603: char* key;
604: private_t* p;
605: str_list_t list;
606:
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: if(p->fp==NULL)
615: return(JS_TRUE);
616:
617: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
618: section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
619: key=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
620:
621: if((list=iniReadFile(p->fp))==NULL)
622: return(JS_TRUE);
623:
624: if(iniRemoveKey(&list,section,key))
625: *rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
626:
627: strListFree(&list);
628:
629: return(JS_TRUE);
630: }
631:
632: static JSBool
633: js_iniRemoveSection(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
634: {
635: char* section=ROOT_SECTION;
636: private_t* p;
637: str_list_t list;
638:
639: *rval = JSVAL_FALSE;
640:
641: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
642: JS_ReportError(cx,getprivate_failure,WHERE);
643: return(JS_FALSE);
644: }
645:
646: if(p->fp==NULL)
647: return(JS_TRUE);
648:
649: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
650: section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
651:
652: if((list=iniReadFile(p->fp))==NULL)
653: return(JS_TRUE);
654:
655: if(iniRemoveSection(&list,section))
656: *rval = BOOLEAN_TO_JSVAL(iniWriteFile(p->fp,list));
657:
658: strListFree(&list);
659:
660: return(JS_TRUE);
661: }
662:
663:
664: static JSBool
665: js_iniGetSections(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
666: {
667: char* prefix=NULL;
668: char** list;
669: jsint i;
670: jsval val;
671: JSObject* array;
672: private_t* p;
673:
674: *rval = JSVAL_NULL;
675:
676: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
677: JS_ReportError(cx,getprivate_failure,WHERE);
678: return(JS_FALSE);
679: }
680:
681: if(p->fp==NULL)
682: return(JS_TRUE);
683:
684: if(argc)
685: prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
686:
687: array = JS_NewArrayObject(cx, 0, NULL);
688:
689: list = iniReadSectionList(p->fp,prefix);
690: for(i=0;list && list[i];i++) {
691: val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
692: if(!JS_SetElement(cx, array, i, &val))
693: break;
694: }
695: iniFreeStringList(list);
696:
697: *rval = OBJECT_TO_JSVAL(array);
698:
699: return(JS_TRUE);
700: }
701:
702: static JSBool
703: js_iniGetKeys(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
704: {
705: char* section=ROOT_SECTION;
706: char** list;
707: jsint i;
708: jsval val;
709: JSObject* array;
710: private_t* p;
711:
712: *rval = JSVAL_NULL;
713:
714: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
715: JS_ReportError(cx,getprivate_failure,WHERE);
716: return(JS_FALSE);
717: }
718:
719: if(p->fp==NULL)
720: return(JS_TRUE);
721:
722: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
723: section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
724: array = JS_NewArrayObject(cx, 0, NULL);
725:
726: list = iniReadKeyList(p->fp,section);
727: for(i=0;list && list[i];i++) {
728: val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,list[i]));
729: if(!JS_SetElement(cx, array, i, &val))
730: break;
731: }
732: iniFreeStringList(list);
733:
734: *rval = OBJECT_TO_JSVAL(array);
735:
736: return(JS_TRUE);
737: }
738:
739: static JSBool
740: js_iniGetObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
741: {
742: char* section=ROOT_SECTION;
743: jsint i;
744: JSObject* object;
745: private_t* p;
746: named_string_t** list;
747:
748: *rval = JSVAL_NULL;
749:
750: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
751: JS_ReportError(cx,getprivate_failure,WHERE);
752: return(JS_FALSE);
753: }
754:
755: if(p->fp==NULL)
756: return(JS_TRUE);
757:
758: if(argv[0]!=JSVAL_VOID && argv[0]!=JSVAL_NULL)
759: section=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
760: object = JS_NewObject(cx, NULL, NULL, obj);
761:
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: ,NULL,NULL,JSPROP_ENUMERATE);
767:
768: }
769: iniFreeNamedStringList(list);
770:
771: *rval = OBJECT_TO_JSVAL(object);
772:
773: return(JS_TRUE);
774: }
775:
776: static JSBool
777: js_iniSetObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
778: {
779: jsint i;
780: JSObject* object;
781: JSIdArray* id_array;
782: jsval set_argv[3];
783:
784: *rval = JSVAL_FALSE;
785:
786: set_argv[0]=argv[0]; /* section */
787:
788: if(!JSVAL_IS_OBJECT(argv[1]) || argv[1]==JSVAL_NULL)
789: return(JS_TRUE);
790:
791: object = JSVAL_TO_OBJECT(argv[1]);
792:
793: if((id_array=JS_Enumerate(cx,object))==NULL)
794: return(JS_TRUE);
795:
796: for(i=0; i<id_array->length; i++) {
797: /* property */
798: JS_IdToValue(cx,id_array->vector[i],&set_argv[1]);
799: /* value */
800: JS_GetProperty(cx,object,JS_GetStringBytes(JSVAL_TO_STRING(set_argv[1])),&set_argv[2]);
801: if(!js_iniSetValue(cx,obj,3,set_argv,rval))
802: break;
803: }
804:
805: JS_DestroyIdArray(cx,id_array);
806:
807: return(JS_TRUE);
808: }
809:
810:
811: static JSBool
812: js_iniGetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
813: {
814: char* name="name";
815: char* sec_name;
816: char* prefix=NULL;
817: char** sec_list;
818: jsint i,k;
819: jsval val;
820: JSObject* array;
821: JSObject* object;
822: private_t* p;
823: named_string_t** key_list;
824:
825: *rval = JSVAL_NULL;
826:
827: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
828: JS_ReportError(cx,getprivate_failure,WHERE);
829: return(JS_FALSE);
830: }
831:
832: if(p->fp==NULL)
833: return(JS_TRUE);
834:
835: if(argc)
836: name=JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
837:
838: if(argc>1)
839: prefix=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
840:
841: array = JS_NewArrayObject(cx, 0, NULL);
842:
843: sec_list = iniReadSectionList(p->fp,prefix);
844: for(i=0;sec_list && sec_list[i];i++) {
845: object = JS_NewObject(cx, NULL, NULL, obj);
846:
847: sec_name=sec_list[i];
848: if(prefix!=NULL)
849: sec_name+=strlen(prefix);
850: JS_DefineProperty(cx, object, name
851: ,STRING_TO_JSVAL(JS_NewStringCopyZ(cx,sec_name))
852: ,NULL,NULL,JSPROP_ENUMERATE);
853:
854: key_list = iniReadNamedStringList(p->fp,sec_list[i]);
855: for(k=0;key_list && key_list[k];k++)
856: JS_DefineProperty(cx, object, key_list[k]->name
857: ,get_value(cx,key_list[k]->value)
858: ,NULL,NULL,JSPROP_ENUMERATE);
859: iniFreeNamedStringList(key_list);
860:
861: val=OBJECT_TO_JSVAL(object);
862: if(!JS_SetElement(cx, array, i, &val))
863: break;
864: }
865: iniFreeStringList(sec_list);
866:
867: *rval = OBJECT_TO_JSVAL(array);
868:
869: return(JS_TRUE);
870: }
871:
872: static JSBool
873: js_iniSetAllObjects(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
874: {
875: char* name="name";
876: jsuint i;
877: jsuint count;
878: JSObject* array;
879: jsval set_argv[2];
880:
881: *rval = JSVAL_FALSE;
882:
883: if(!JSVAL_IS_OBJECT(argv[0]))
884: return(JS_TRUE);
885:
886: array = JSVAL_TO_OBJECT(argv[0]);
887:
888: if(!JS_IsArrayObject(cx, array))
889: return(JS_TRUE);
890:
891: if(!JS_GetArrayLength(cx, array, &count))
892: return(JS_TRUE);
893:
894: if(argc>1)
895: name=JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
896:
897: /* enumerate the array */
898: for(i=0; i<count; i++) {
899: if(!JS_GetElement(cx, array, i, &set_argv[1]))
900: break;
901: if(!JSVAL_IS_OBJECT(set_argv[1])) /* must be an array of objects */
902: break;
903: if(!JS_GetProperty(cx, JSVAL_TO_OBJECT(set_argv[1]), name, &set_argv[0]))
904: continue;
905: if(!js_iniSetObject(cx, obj, 2, set_argv, rval))
906: break;
907: }
908:
909: return(JS_TRUE);
910: }
911:
912: static JSBool
913: js_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
914: {
915: char* cp;
916: char* uubuf=NULL;
917: int len; /* string length */
918: 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: if(p->fp==NULL)
930: return(JS_TRUE);
931:
932: str = JS_ValueToString(cx, argv[0]);
933: cp = JS_GetStringBytes(str);
934: len = JS_GetStringLength(str);
935:
936: if((p->uuencoded || p->b64encoded || p->yencoded)
937: && len && (uubuf=malloc(len))!=NULL) {
938: if(p->uuencoded)
939: len=uudecode(uubuf,len,cp,len);
940: else if(p->yencoded)
941: len=ydecode(uubuf,len,cp,len);
942: else
943: len=b64_decode(uubuf,len,cp,len);
944: if(len<0) {
945: free(uubuf);
946: return(JS_TRUE);
947: }
948: cp=uubuf;
949: }
950:
951: if(p->rot13)
952: rot13(cp);
953:
954: tlen=len;
955: if(argc>1) {
956: if(!JS_ValueToInt32(cx,argv[1],(int32*)&tlen)) {
957: FREE_AND_NULL(uubuf);
958: return(JS_FALSE);
959: }
960: if(len>tlen)
961: len=tlen;
962: }
963:
964: if(fwrite(cp,1,len,p->fp)==(size_t)len) {
965: if(tlen>len) {
966: len=tlen-len;
967: if((cp=malloc(len))==NULL) {
968: FREE_AND_NULL(uubuf);
969: dbprintf(TRUE, p, "malloc failure of %u bytes", len);
970: return(JS_TRUE);
971: }
972: memset(cp,p->etx,len);
973: fwrite(cp,1,len,p->fp);
974: free(cp);
975: }
976: dbprintf(FALSE, p, "wrote %u bytes",tlen);
977: *rval = JSVAL_TRUE;
978: } else
979: dbprintf(TRUE, p, "write of %u bytes failed",len);
980:
981: FREE_AND_NULL(uubuf);
982:
983: return(JS_TRUE);
984: }
985:
986: static JSBool
987: js_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
988: {
989: char* cp="";
990: JSString* str;
991: private_t* p;
992:
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: if(p->fp==NULL)
1001: return(JS_TRUE);
1002:
1003: if(argc) {
1004: if((str = JS_ValueToString(cx, argv[0]))==NULL) {
1005: JS_ReportError(cx,"JS_ValueToString failed");
1006: return(JS_FALSE);
1007: }
1008: cp = JS_GetStringBytes(str);
1009: }
1010:
1011: if(p->rot13)
1012: rot13(cp);
1013:
1014: if(fprintf(p->fp,"%s\n",cp)!=0)
1015: *rval = JSVAL_TRUE;
1016:
1017: return(JS_TRUE);
1018: }
1019:
1020: static JSBool
1021: js_writebin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1022: {
1023: BYTE b;
1024: WORD w;
1025: DWORD l;
1026: int32 val=0;
1027: size_t wr=0;
1028: size_t size=sizeof(DWORD);
1029: private_t* p;
1030:
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: if(p->fp==NULL)
1039: return(JS_TRUE);
1040:
1041: if(!JS_ValueToInt32(cx,argv[0],&val))
1042: return(JS_FALSE);
1043: if(argc>1) {
1044: if(!JS_ValueToInt32(cx,argv[1],(int32*)&size))
1045: return(JS_FALSE);
1046: }
1047:
1048: switch(size) {
1049: case sizeof(BYTE):
1050: b = (BYTE)val;
1051: wr=fwrite(&b,1,size,p->fp);
1052: break;
1053: case sizeof(WORD):
1054: w = (WORD)val;
1055: if(p->network_byte_order)
1056: w=htons(w);
1057: wr=fwrite(&w,1,size,p->fp);
1058: break;
1059: case sizeof(DWORD):
1060: l = val;
1061: if(p->network_byte_order)
1062: l=htonl(l);
1063: wr=fwrite(&l,1,size,p->fp);
1064: break;
1065: default:
1066: /* unknown size */
1067: dbprintf(TRUE, p, "unsupported binary write size: %d",size);
1068: break;
1069: }
1070: if(wr==size)
1071: *rval = JSVAL_TRUE;
1072:
1073: return(JS_TRUE);
1074: }
1075:
1076: static JSBool
1077: js_writeall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1078: {
1079: jsuint i;
1080: jsuint limit;
1081: JSObject* array;
1082: jsval elemval;
1083: private_t* p;
1084:
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: if(p->fp==NULL)
1093: return(JS_TRUE);
1094:
1095: if(!JSVAL_IS_OBJECT(argv[0]))
1096: return(JS_TRUE);
1097:
1098: array = JSVAL_TO_OBJECT(argv[0]);
1099:
1100: if(!JS_IsArrayObject(cx, array))
1101: return(JS_TRUE);
1102:
1103: if(!JS_GetArrayLength(cx, array, &limit))
1104: return(JS_FALSE);
1105:
1106: *rval = JSVAL_TRUE;
1107:
1108: for(i=0;i<limit;i++) {
1109: if(!JS_GetElement(cx, array, i, &elemval))
1110: break;
1111: js_writeln(cx, obj, 1, &elemval, rval);
1112: if(*rval!=JSVAL_TRUE)
1113: break;
1114: }
1115:
1116: return(JS_TRUE);
1117: }
1118:
1119: static JSBool
1120: js_lock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1121: {
1122: int32 offset=0;
1123: int32 len=0;
1124: private_t* p;
1125:
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);
1131: }
1132:
1133: if(p->fp==NULL)
1134: return(JS_TRUE);
1135:
1136: /* offset */
1137: if(argc) {
1138: if(!JS_ValueToInt32(cx,argv[0],&offset))
1139: return(JS_FALSE);
1140: }
1141:
1142: /* length */
1143: if(argc>1) {
1144: if(!JS_ValueToInt32(cx,argv[1],&len))
1145: return(JS_FALSE);
1146: }
1147:
1148: if(len==0)
1149: len=filelength(fileno(p->fp))-offset;
1150:
1151: if(lock(fileno(p->fp),offset,len)==0)
1152: *rval = JSVAL_TRUE;
1153:
1154: return(JS_TRUE);
1155: }
1156:
1157: static JSBool
1158: js_unlock(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1159: {
1160: int32 offset=0;
1161: int32 len=0;
1162: private_t* p;
1163:
1164: *rval = JSVAL_FALSE;
1165:
1166: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1167: JS_ReportError(cx,getprivate_failure,WHERE);
1168: return(JS_FALSE);
1169: }
1170:
1171: if(p->fp==NULL)
1172: return(JS_TRUE);
1173:
1174: /* offset */
1175: if(argc) {
1176: if(!JS_ValueToInt32(cx,argv[0],&offset))
1177: return(JS_FALSE);
1178: }
1179:
1180: /* length */
1181: if(argc>1) {
1182: if(!JS_ValueToInt32(cx,argv[1],&len))
1183: return(JS_FALSE);
1184: }
1185:
1186: if(len==0)
1187: len=filelength(fileno(p->fp))-offset;
1188:
1189: if(unlock(fileno(p->fp),offset,len)==0)
1190: *rval = JSVAL_TRUE;
1191:
1192: return(JS_TRUE);
1193: }
1194:
1195: static JSBool
1196: js_delete(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1197: {
1198: private_t* p;
1199:
1200: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1201: JS_ReportError(cx,getprivate_failure,WHERE);
1202: return(JS_FALSE);
1203: }
1204:
1205: if(p->fp!=NULL) { /* close it if it's open */
1206: fclose(p->fp);
1207: p->fp=NULL;
1208: }
1209:
1210: *rval = BOOLEAN_TO_JSVAL(remove(p->name)==0);
1211:
1212: return(JS_TRUE);
1213: }
1214:
1215: static JSBool
1216: js_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1217: {
1218: private_t* p;
1219:
1220: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1221: JS_ReportError(cx,getprivate_failure,WHERE);
1222: return(JS_FALSE);
1223: }
1224:
1225: if(p->fp==NULL)
1226: *rval = JSVAL_FALSE;
1227: else
1228: *rval = BOOLEAN_TO_JSVAL(fflush(p->fp)==0);
1229:
1230: return(JS_TRUE);
1231: }
1232:
1233: static JSBool
1234: js_rewind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1235: {
1236: private_t* p;
1237:
1238: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1239: JS_ReportError(cx,getprivate_failure,WHERE);
1240: return(JS_FALSE);
1241: }
1242:
1243: if(p->fp==NULL)
1244: *rval = JSVAL_FALSE;
1245: else {
1246: *rval = JSVAL_TRUE;
1247: rewind(p->fp);
1248: }
1249:
1250: return(JS_TRUE);
1251: }
1252:
1253: static JSBool
1254: js_truncate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1255: {
1256: private_t* p;
1257: int32 len=0;
1258:
1259: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1260: JS_ReportError(cx,getprivate_failure,WHERE);
1261: return(JS_FALSE);
1262: }
1263:
1264: if(argc) {
1265: if(!JS_ValueToInt32(cx,argv[0],&len))
1266: return(JS_FALSE);
1267: }
1268:
1269: *rval = JSVAL_FALSE;
1270: if(p->fp!=NULL && chsize(fileno(p->fp),len)==0) {
1271: fseek(p->fp,len,SEEK_SET);
1272: *rval = JSVAL_TRUE;
1273: }
1274:
1275: return(JS_TRUE);
1276: }
1277:
1278: static JSBool
1279: js_clear_error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1280: {
1281: private_t* p;
1282:
1283: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1284: JS_ReportError(cx,getprivate_failure,WHERE);
1285: return(JS_FALSE);
1286: }
1287:
1288: if(p->fp==NULL)
1289: *rval = JSVAL_FALSE;
1290: else {
1291: clearerr(p->fp);
1292: *rval = JSVAL_TRUE;
1293: }
1294:
1295: return(JS_TRUE);
1296: }
1297:
1298: static JSBool
1299: js_fprintf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1300: {
1301: char* cp;
1302: private_t* p;
1303:
1304: *rval = JSVAL_FALSE;
1305:
1306: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1307: JS_ReportError(cx,getprivate_failure,WHERE);
1308: return(JS_FALSE);
1309: }
1310:
1311: if(p->fp==NULL)
1312: return(JS_TRUE);
1313:
1314: if((cp=js_sprintf(cx, 0, argc, argv))==NULL) {
1315: JS_ReportError(cx,"js_sprintf failed");
1316: return(JS_FALSE);
1317: }
1318:
1319: *rval = INT_TO_JSVAL(fwrite(cp,1,strlen(cp),p->fp));
1320: js_sprintf_free(cp);
1321:
1322: return(JS_TRUE);
1323: }
1324:
1325:
1326: /* File Object Properites */
1327: enum {
1328: FILE_PROP_NAME
1329: ,FILE_PROP_MODE
1330: ,FILE_PROP_ETX
1331: ,FILE_PROP_EXISTS
1332: ,FILE_PROP_DATE
1333: ,FILE_PROP_IS_OPEN
1334: ,FILE_PROP_EOF
1335: ,FILE_PROP_ERROR
1336: ,FILE_PROP_DESCRIPTOR
1337: ,FILE_PROP_DEBUG
1338: ,FILE_PROP_POSITION
1339: ,FILE_PROP_LENGTH
1340: ,FILE_PROP_ATTRIBUTES
1341: ,FILE_PROP_YENCODED
1342: ,FILE_PROP_UUENCODED
1343: ,FILE_PROP_B64ENCODED
1344: ,FILE_PROP_ROT13
1345: ,FILE_PROP_NETWORK_ORDER
1346: /* dynamically calculated */
1347: ,FILE_PROP_CHKSUM
1348: ,FILE_PROP_CRC16
1349: ,FILE_PROP_CRC32
1350: ,FILE_PROP_MD5_HEX
1351: ,FILE_PROP_MD5_B64
1352: };
1353:
1354:
1355: static JSBool js_file_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
1356: {
1357: int32 i=0;
1358: jsint tiny;
1359: private_t* p;
1360:
1361: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1362: JS_ReportError(cx,getprivate_failure,WHERE);
1363: return(JS_FALSE);
1364: }
1365:
1366: tiny = JSVAL_TO_INT(id);
1367:
1368: dbprintf(FALSE, p, "setting property %d",tiny);
1369:
1370: switch(tiny) {
1371: case FILE_PROP_DEBUG:
1372: JS_ValueToBoolean(cx,*vp,&(p->debug));
1373: break;
1374: case FILE_PROP_YENCODED:
1375: JS_ValueToBoolean(cx,*vp,&(p->yencoded));
1376: break;
1377: case FILE_PROP_UUENCODED:
1378: JS_ValueToBoolean(cx,*vp,&(p->uuencoded));
1379: break;
1380: case FILE_PROP_B64ENCODED:
1381: JS_ValueToBoolean(cx,*vp,&(p->b64encoded));
1382: break;
1383: case FILE_PROP_ROT13:
1384: JS_ValueToBoolean(cx,*vp,&(p->rot13));
1385: break;
1386: case FILE_PROP_NETWORK_ORDER:
1387: JS_ValueToBoolean(cx,*vp,&(p->network_byte_order));
1388: break;
1389: case FILE_PROP_POSITION:
1390: if(p->fp!=NULL) {
1391: if(!JS_ValueToInt32(cx,*vp,&i))
1392: return(JS_FALSE);
1393: fseek(p->fp,i,SEEK_SET);
1394: }
1395: break;
1396: case FILE_PROP_DATE:
1397: if(!JS_ValueToInt32(cx,*vp,&i))
1398: return(JS_FALSE);
1399: setfdate(p->name,i);
1400: break;
1401: case FILE_PROP_LENGTH:
1402: if(p->fp!=NULL) {
1403: if(!JS_ValueToInt32(cx,*vp,&i))
1404: return(JS_FALSE);
1405: chsize(fileno(p->fp),i);
1406: }
1407: break;
1408: case FILE_PROP_ATTRIBUTES:
1409: if(!JS_ValueToInt32(cx,*vp,&i))
1410: return(JS_FALSE);
1411: CHMOD(p->name,i);
1412: break;
1413: case FILE_PROP_ETX:
1414: if(!JS_ValueToInt32(cx,*vp,&i))
1415: return(JS_FALSE);
1416: p->etx = (uchar)i;
1417: break;
1418: }
1419:
1420: return(JS_TRUE);
1421: }
1422:
1423: static JSBool js_file_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
1424: {
1425: char str[128];
1426: size_t i;
1427: size_t rd;
1428: long offset;
1429: ulong sum=0;
1430: ushort c16=0;
1431: ulong c32=~0;
1432: MD5 md5_ctx;
1433: BYTE block[4096];
1434: BYTE digest[MD5_DIGEST_SIZE];
1435: jsint tiny;
1436: JSString* js_str=NULL;
1437: private_t* p;
1438:
1439: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
1440: JS_ReportError(cx,getprivate_failure,WHERE);
1441: return(JS_FALSE);
1442: }
1443:
1444: tiny = JSVAL_TO_INT(id);
1445:
1446: #if 0 /* just too much */
1447: dbprintf(FALSE, sock, "getting property %d",tiny);
1448: #endif
1449:
1450: switch(tiny) {
1451: case FILE_PROP_NAME:
1452: if((js_str=JS_NewStringCopyZ(cx, p->name))==NULL)
1453: return(JS_FALSE);
1454: *vp = STRING_TO_JSVAL(js_str);
1455: break;
1456: case FILE_PROP_MODE:
1457: if((js_str=JS_NewStringCopyZ(cx, p->mode))==NULL)
1458: return(JS_FALSE);
1459: *vp = STRING_TO_JSVAL(js_str);
1460: break;
1461: case FILE_PROP_EXISTS:
1462: if(p->fp) /* open? */
1463: *vp = JSVAL_TRUE;
1464: else
1465: *vp = BOOLEAN_TO_JSVAL(fexistcase(p->name));
1466: break;
1467: case FILE_PROP_DATE:
1468: JS_NewNumberValue(cx,fdate(p->name),vp);
1469: break;
1470: case FILE_PROP_IS_OPEN:
1471: *vp = BOOLEAN_TO_JSVAL(p->fp!=NULL);
1472: break;
1473: case FILE_PROP_EOF:
1474: if(p->fp)
1475: *vp = BOOLEAN_TO_JSVAL(feof(p->fp)!=0);
1476: else
1477: *vp = JSVAL_TRUE;
1478: break;
1479: case FILE_PROP_ERROR:
1480: if(p->fp)
1481: *vp = INT_TO_JSVAL(ferror(p->fp));
1482: else
1483: *vp = INT_TO_JSVAL(errno);
1484: break;
1485: case FILE_PROP_POSITION:
1486: if(p->fp)
1487: JS_NewNumberValue(cx,ftell(p->fp),vp);
1488: else
1489: *vp = INT_TO_JSVAL(-1);
1490: break;
1491: case FILE_PROP_LENGTH:
1492: if(p->fp) /* open? */
1493: JS_NewNumberValue(cx,filelength(fileno(p->fp)),vp);
1494: else
1495: JS_NewNumberValue(cx,flength(p->name),vp);
1496: break;
1497: case FILE_PROP_ATTRIBUTES:
1498: JS_NewNumberValue(cx,getfattr(p->name),vp);
1499: break;
1500: case FILE_PROP_DEBUG:
1501: *vp = BOOLEAN_TO_JSVAL(p->debug);
1502: break;
1503: case FILE_PROP_YENCODED:
1504: *vp = BOOLEAN_TO_JSVAL(p->yencoded);
1505: break;
1506: case FILE_PROP_UUENCODED:
1507: *vp = BOOLEAN_TO_JSVAL(p->uuencoded);
1508: break;
1509: case FILE_PROP_B64ENCODED:
1510: *vp = BOOLEAN_TO_JSVAL(p->b64encoded);
1511: break;
1512: case FILE_PROP_ROT13:
1513: *vp = BOOLEAN_TO_JSVAL(p->rot13);
1514: break;
1515: case FILE_PROP_NETWORK_ORDER:
1516: *vp = BOOLEAN_TO_JSVAL(p->network_byte_order);
1517: break;
1518: case FILE_PROP_DESCRIPTOR:
1519: if(p->fp)
1520: *vp = INT_TO_JSVAL(fileno(p->fp));
1521: else
1522: *vp = INT_TO_JSVAL(-1);
1523: break;
1524: case FILE_PROP_ETX:
1525: *vp = INT_TO_JSVAL(p->etx);
1526: break;
1527: case FILE_PROP_CHKSUM:
1528: case FILE_PROP_CRC16:
1529: case FILE_PROP_CRC32:
1530: *vp = JSVAL_ZERO;
1531: if(p->fp==NULL)
1532: break;
1533: /* fall-through */
1534: case FILE_PROP_MD5_HEX:
1535: case FILE_PROP_MD5_B64:
1536: *vp = JSVAL_VOID;
1537: if(p->fp==NULL)
1538: break;
1539: offset=ftell(p->fp); /* save current file position */
1540: fseek(p->fp,0,SEEK_SET);
1541:
1542: /* Initialization */
1543: switch(tiny) {
1544: case FILE_PROP_MD5_HEX:
1545: case FILE_PROP_MD5_B64:
1546: MD5_open(&md5_ctx);
1547: break;
1548: }
1549:
1550: /* calculate */
1551: while(!feof(p->fp)) {
1552: if((rd=fread(block,1,sizeof(block),p->fp))<1)
1553: break;
1554: switch(tiny) {
1555: case FILE_PROP_CHKSUM:
1556: for(i=0;i<rd;i++)
1557: sum+=block[i];
1558: break;
1559: case FILE_PROP_CRC16:
1560: for(i=0;i<rd;i++)
1561: c16=ucrc16(block[i],c16);
1562: break;
1563: case FILE_PROP_CRC32:
1564: for(i=0;i<rd;i++)
1565: c32=ucrc32(block[i],c32);
1566: break;
1567: case FILE_PROP_MD5_HEX:
1568: case FILE_PROP_MD5_B64:
1569: MD5_digest(&md5_ctx,block,rd);
1570: break;
1571: }
1572: }
1573:
1574: /* finalize */
1575: switch(tiny) {
1576: case FILE_PROP_CHKSUM:
1577: JS_NewNumberValue(cx,sum,vp);
1578: break;
1579: case FILE_PROP_CRC16:
1580: if(!JS_NewNumberValue(cx,c16,vp))
1581: *vp=JSVAL_ZERO;
1582: break;
1583: case FILE_PROP_CRC32:
1584: if(!JS_NewNumberValue(cx,~c32,vp))
1585: *vp=JSVAL_ZERO;
1586: break;
1587: case FILE_PROP_MD5_HEX:
1588: case FILE_PROP_MD5_B64:
1589: MD5_close(&md5_ctx,digest);
1590: if(tiny==FILE_PROP_MD5_HEX)
1591: MD5_hex(str,digest);
1592: else
1593: b64_encode(str,sizeof(str)-1,digest,sizeof(digest));
1594: js_str=JS_NewStringCopyZ(cx, str);
1595: break;
1596: }
1597: fseek(p->fp,offset,SEEK_SET); /* restore saved file position */
1598: if(js_str!=NULL)
1599: *vp = STRING_TO_JSVAL(js_str);
1600: break;
1601: }
1602:
1603: return(JS_TRUE);
1604: }
1605:
1606: #define FILE_PROP_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY
1607:
1608: static jsSyncPropertySpec js_file_properties[] = {
1609: /* name ,tinyid ,flags, ver */
1610: { "name" ,FILE_PROP_NAME ,FILE_PROP_FLAGS, 310},
1611: { "mode" ,FILE_PROP_MODE ,FILE_PROP_FLAGS, 310},
1612: { "exists" ,FILE_PROP_EXISTS ,FILE_PROP_FLAGS, 310},
1613: { "is_open" ,FILE_PROP_IS_OPEN ,FILE_PROP_FLAGS, 310},
1614: { "eof" ,FILE_PROP_EOF ,FILE_PROP_FLAGS, 310},
1615: { "error" ,FILE_PROP_ERROR ,FILE_PROP_FLAGS, 310},
1616: { "descriptor" ,FILE_PROP_DESCRIPTOR ,FILE_PROP_FLAGS, 310},
1617: /* writeable */
1618: { "etx" ,FILE_PROP_ETX ,JSPROP_ENUMERATE, 310},
1619: { "debug" ,FILE_PROP_DEBUG ,JSPROP_ENUMERATE, 310},
1620: { "position" ,FILE_PROP_POSITION ,JSPROP_ENUMERATE, 310},
1621: { "date" ,FILE_PROP_DATE ,JSPROP_ENUMERATE, 311},
1622: { "length" ,FILE_PROP_LENGTH ,JSPROP_ENUMERATE, 310},
1623: { "attributes" ,FILE_PROP_ATTRIBUTES ,JSPROP_ENUMERATE, 310},
1624: { "network_byte_order",FILE_PROP_NETWORK_ORDER,JSPROP_ENUMERATE, 311},
1625: { "rot13" ,FILE_PROP_ROT13 ,JSPROP_ENUMERATE, 311},
1626: { "uue" ,FILE_PROP_UUENCODED ,JSPROP_ENUMERATE, 311},
1627: { "yenc" ,FILE_PROP_YENCODED ,JSPROP_ENUMERATE, 311},
1628: { "base64" ,FILE_PROP_B64ENCODED ,JSPROP_ENUMERATE, 311},
1629: /* dynamically calculated */
1630: { "crc16" ,FILE_PROP_CRC16 ,FILE_PROP_FLAGS, 311},
1631: { "crc32" ,FILE_PROP_CRC32 ,FILE_PROP_FLAGS, 311},
1632: { "chksum" ,FILE_PROP_CHKSUM ,FILE_PROP_FLAGS, 311},
1633: { "md5_hex" ,FILE_PROP_MD5_HEX ,FILE_PROP_FLAGS, 311},
1634: { "md5_base64" ,FILE_PROP_MD5_B64 ,FILE_PROP_FLAGS, 311},
1635: {0}
1636: };
1637:
1638: #ifdef BUILD_JSDOCS
1639: static char* file_prop_desc[] = {
1640: "filename specified in constructor - <small>READ ONLY</small>"
1641: ,"mode string specified in <i>open</i> call - <small>READ ONLY</small>"
1642: ,"<i>true</i> if the file exists - <small>READ ONLY</small>"
1643: ,"<i>true</i> if the file has been opened successfully - <small>READ ONLY</small>"
1644: ,"<i>true</i> if the current file position is at the <i>end of file</i> - <small>READ ONLY</small>"
1645: ,"the last occurred error value (use clear_error to clear) - <small>READ ONLY</small>"
1646: ,"the open file descriptor (advanced use only) - <small>READ ONLY</small>"
1647: ,"end-of-text character (advanced use only), if non-zero used by <i>read</i>, <i>readln</i>, and <i>write</i>"
1648: ,"set to <i>true</i> to enable debug log output"
1649: ,"the current file position (offset in bytes), change value to seek within file"
1650: ,"last modified date/time (in time_t format)"
1651: ,"the current length of the file (in bytes)"
1652: ,"file mode/attributes"
1653: ,"set to <i>true</i> if binary data is to be written and read in Network Byte Order (big end first)"
1654: ,"set to <i>true</i> to enable automatic ROT13 translatation of text"
1655: ,"set to <i>true</i> to enable automatic Unix-to-Unix encode and decode on <tt>read</tt> and <tt>write</tt> calls"
1656: ,"set to <i>true</i> to enable automatic yEnc encode and decode on <tt>read</tt> and <tt>write</tt> calls"
1657: ,"set to <i>true</i> to enable automatic Base64 encode and decode on <tt>read</tt> and <tt>write</tt> calls"
1658: ,"calculated 16-bit CRC of file contents - <small>READ ONLY</small>"
1659: ,"calculated 32-bit CRC of file contents - <small>READ ONLY</small>"
1660: ,"calculated 32-bit checksum of file contents - <small>READ ONLY</small>"
1661: ,"calculated 128-bit MD5 digest of file contents as hexadecimal string - <small>READ ONLY</small>"
1662: ,"calculated 128-bit MD5 digest of file contents as base64-encoded string - <small>READ ONLY</small>"
1663: ,NULL
1664: };
1665: #endif
1666:
1667:
1668: static jsSyncMethodSpec js_file_functions[] = {
1669: {"open", js_open, 1, JSTYPE_BOOLEAN, JSDOCSTR("[mode=<tt>\"w+\"</tt>] [,shareable=<tt>false</tt>] [,buffer_length]")
1670: ,JSDOCSTR("open file, <i>shareable</i> defaults to <i>false</i>, <i>buffer_length</i> defaults to 2048 bytes, "
1671: "mode (default: <tt>'w+'</tt>) specifies the type of access requested for the file, as follows:<br>"
1672: "<tt>r </tt> open for reading; if the file does not exist or cannot be found, the open call fails<br>"
1673: "<tt>w </tt> open an empty file for writing; if the given file exists, its contents are destroyed<br>"
1674: "<tt>a </tt> open for writing at the end of the file (appending); creates the file first if it doesn�t exist<br>"
1675: "<tt>r+</tt> open for both reading and writing (the file must exist)<br>"
1676: "<tt>w+</tt> open an empty file for both reading and writing; if the given file exists, its contents are destroyed<br>"
1677: "<tt>a+</tt> open for reading and appending<br>"
1678: "<tt>b </tt> open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed (e.g. <tt>r+b</tt>)<br>"
1679: "<tt>e </tt> open a <i>non-shareable</i> file (that must not already exist) for <i>exclusive</i> access <i>(introduced in v3.12)</i><br>"
1680: "<br><b>Note:</b> When using the <tt>iniSet</tt> methods to modify a <tt>.ini</tt> file, "
1681: "the file must be opened for both reading and writing.<br>"
1682: "<br><b>Note:</b> To open an existing or create a new file for both reading and writing, "
1683: "use the <i>file_exists</i> function like so:<br>"
1684: "<tt>file.open(file_exists(file.name) ? 'r+':'w+');</tt>"
1685: )
1686: ,310
1687: },
1688: {"close", js_close, 0, JSTYPE_VOID, JSDOCSTR("")
1689: ,JSDOCSTR("close file")
1690: ,310
1691: },
1692: {"remove", js_delete, 0, JSTYPE_BOOLEAN, JSDOCSTR("")
1693: ,JSDOCSTR("remove the file from the disk")
1694: ,310
1695: },
1696: {"clearError", js_clear_error, 0, JSTYPE_ALIAS },
1697: {"clear_error", js_clear_error, 0, JSTYPE_BOOLEAN, JSDOCSTR("")
1698: ,JSDOCSTR("clears the current error value (AKA clearError)")
1699: ,310
1700: },
1701: {"flush", js_flush, 0, JSTYPE_BOOLEAN, JSDOCSTR("")
1702: ,JSDOCSTR("flush/commit buffers to disk")
1703: ,310
1704: },
1705: {"rewind", js_rewind, 0, JSTYPE_BOOLEAN, JSDOCSTR("")
1706: ,JSDOCSTR("repositions the file pointer (<i>position</i>) to the beginning of a file "
1707: "and clears error and end-of-file indicators")
1708: ,311
1709: },
1710: {"truncate", js_truncate, 0, JSTYPE_BOOLEAN, JSDOCSTR("[length=<tt>0</tt>]")
1711: ,JSDOCSTR("changes the file <i>length</i> (default: 0) and repositions the file pointer "
1712: "(<i>position</i>) to the new end-of-file")
1713: ,314
1714: },
1715: {"lock", js_lock, 2, JSTYPE_BOOLEAN, JSDOCSTR("[offset=<tt>0</tt>] [,length=<i>file_length</i>-<i>offset</i>]")
1716: ,JSDOCSTR("lock file record for exclusive access (file must be opened <i>shareable</i>)")
1717: ,310
1718: },
1719: {"unlock", js_unlock, 2, JSTYPE_BOOLEAN, JSDOCSTR("[offset=<tt>0</tt>] [,length=<i>file_length</i>-<i>offset</i>]")
1720: ,JSDOCSTR("unlock file record for exclusive access")
1721: ,310
1722: },
1723: {"read", js_read, 0, JSTYPE_STRING, JSDOCSTR("[maxlen=<i>file_length</i>-<i>file_position</i>]")
1724: ,JSDOCSTR("read a string from file (optionally unix-to-unix or base64 decoding in the process), "
1725: "<i>maxlen</i> defaults to the current length of the file minus the current file position")
1726: ,310
1727: },
1728: {"readln", js_readln, 0, JSTYPE_STRING, JSDOCSTR("[maxlen=<tt>512</tt>]")
1729: ,JSDOCSTR("read a line-feed terminated string, <i>maxlen</i> defaults to 512 characters")
1730: ,310
1731: },
1732: {"readBin", js_readbin, 0, JSTYPE_NUMBER, JSDOCSTR("[bytes=<tt>4</tt>]")
1733: ,JSDOCSTR("read a binary integer from the file, default number of <i>bytes</i> is 4 (32-bits)")
1734: ,310
1735: },
1736: {"readAll", js_readall, 0, JSTYPE_ARRAY, JSDOCSTR("[maxlen=<tt>512</tt>]")
1737: ,JSDOCSTR("read all lines into an array of strings, <i>maxlen</i> defaults to 512 characters")
1738: ,310
1739: },
1740: {"write", js_write, 1, JSTYPE_BOOLEAN, JSDOCSTR("text [,length=<i>text_length</i>]")
1741: ,JSDOCSTR("write a string to the file (optionally unix-to-unix or base64 decoding in the process)")
1742: ,310
1743: },
1744: {"writeln", js_writeln, 0, JSTYPE_BOOLEAN, JSDOCSTR("[text]")
1745: ,JSDOCSTR("write a line-feed terminated string to the file")
1746: ,310
1747: },
1748: {"writeBin", js_writebin, 1, JSTYPE_BOOLEAN, JSDOCSTR("value [,bytes=<tt>4</tt>]")
1749: ,JSDOCSTR("write a binary integer to the file, default number of <i>bytes</i> is 4 (32-bits)")
1750: ,310
1751: },
1752: {"writeAll", js_writeall, 0, JSTYPE_BOOLEAN, JSDOCSTR("array lines")
1753: ,JSDOCSTR("write an array of strings to file")
1754: ,310
1755: },
1756: {"printf", js_fprintf, 0, JSTYPE_NUMBER, JSDOCSTR("format [,args]")
1757: ,JSDOCSTR("write a formatted string to the file (ala fprintf) - "
1758: "<small>CAUTION: for experienced C programmers ONLY</small>")
1759: ,310
1760: },
1761: {"iniGetSections", js_iniGetSections, 0, JSTYPE_ARRAY, JSDOCSTR("[prefix=<i>none</i>]")
1762: ,JSDOCSTR("parse all section names from a <tt>.ini</tt> file (format = '<tt>[section]</tt>') "
1763: "and return the section names as an <i>array of strings</i>, "
1764: "optionally, only those section names that begin with the specified <i>prefix</i>")
1765: ,311
1766: },
1767: {"iniGetKeys", js_iniGetKeys, 1, JSTYPE_ARRAY, JSDOCSTR("[section=<i>root</i>]")
1768: ,JSDOCSTR("parse all key names from the specified <i>section</i> in a <tt>.ini</tt> file "
1769: "and return the key names as an <i>array of strings</i>. "
1770: "if <i>section</i> is undefined, returns key names from the <i>root</i> section")
1771: ,311
1772: },
1773: {"iniGetValue", js_iniGetValue, 3, JSTYPE_UNDEF, JSDOCSTR("section, key [,default=<i>none</i>]")
1774: ,JSDOCSTR("parse a key from a <tt>.ini</tt> file and return its value (format = '<tt>key = value</tt>'). "
1775: "returns the specified <i>default</i> value if the key or value is missing or invalid. "
1776: "to parse a key from the <i>root</i> section, pass <i>null</i> for <i>section</i>. "
1777: "will return a <i>bool</i>, <i>number</i>, <i>string</i>, or an <i>array of strings</i> "
1778: "determined by the type of <i>default</i> value specified")
1779: ,311
1780: },
1781: {"iniSetValue", js_iniSetValue, 3, JSTYPE_BOOLEAN, JSDOCSTR("section, key, [value=<i>none</i>]")
1782: ,JSDOCSTR("set the specified <i>key</i> to the specified <i>value</i> in the specified <i>section</i> "
1783: "of a <tt>.ini</tt> file. "
1784: "to set a key in the <i>root</i> section, pass <i>null</i> for <i>section</i>. ")
1785: ,312
1786: },
1787: {"iniGetObject", js_iniGetObject, 1, JSTYPE_OBJECT, JSDOCSTR("[section=<i>root</i>]")
1788: ,JSDOCSTR("parse an entire section from a .ini file "
1789: "and return all of its keys and values as properties of an object. "
1790: "if <i>section</i> is undefined, returns key and values from the <i>root</i> section")
1791: ,311
1792: },
1793: {"iniSetObject", js_iniSetObject, 2, JSTYPE_BOOLEAN, JSDOCSTR("section, object")
1794: ,JSDOCSTR("write all the properties of the specified <i>object</i> as separate <tt>key=value</tt> pairs "
1795: "in the specified <i>section</i> of a <tt>.ini</tt> file. "
1796: "to write an object in the <i>root</i> section, pass <i>null</i> for <i>section</i>. ")
1797: ,312
1798: },
1799: {"iniGetAllObjects",js_iniGetAllObjects,1, JSTYPE_ARRAY, JSDOCSTR("[name_property] [,prefix=<i>none</i>]")
1800: ,JSDOCSTR("parse all sections from a .ini file and return all (non-<i>root</i>) sections "
1801: "in an array of objects with each section's keys as properties of each object. "
1802: "<i>name_property</i> is the name of the property to create to contain the section's name "
1803: "(default is <tt>\"name\"</tt>), "
1804: "the optional <i>prefix</i> has the same use as in the <tt>iniGetSections</tt> method, "
1805: "if a <i>prefix</i> is specified, it is removed from each section's name" )
1806: ,311
1807: },
1808: {"iniSetAllObjects",js_iniSetAllObjects,1, JSTYPE_ARRAY, JSDOCSTR("object array [,name_property=<tt>\"name\"</tt>]")
1809: ,JSDOCSTR("write an array of objects to a .ini file, each object in its own section named "
1810: "after the object's <i>name_property</i> (default: <tt>name</tt>)")
1811: ,312
1812: },
1813: {"iniRemoveKey", js_iniRemoveKey, 2, JSTYPE_BOOLEAN, JSDOCSTR("section, key")
1814: ,JSDOCSTR("remove specified <i>key</i> from specified <i>section</i> in <tt>.ini</tt> file.")
1815: ,314
1816: },
1817: {"iniRemoveSection",js_iniRemoveSection,1, JSTYPE_BOOLEAN, JSDOCSTR("section")
1818: ,JSDOCSTR("remove specified <i>section</i> from <tt>.ini</tt> file.")
1819: ,314
1820: },
1821: {0}
1822: };
1823:
1824: /* File Destructor */
1825:
1826: static void js_finalize_file(JSContext *cx, JSObject *obj)
1827: {
1828: private_t* p;
1829:
1830: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL)
1831: return;
1832:
1833: if(p->external==JS_FALSE && p->fp!=NULL)
1834: fclose(p->fp);
1835:
1836: dbprintf(FALSE, p, "closed: %s",p->name);
1837:
1838: free(p);
1839:
1840: JS_SetPrivate(cx, obj, NULL);
1841: }
1842:
1843: static JSClass js_file_class = {
1844: "File" /* name */
1845: ,JSCLASS_HAS_PRIVATE /* flags */
1846: ,JS_PropertyStub /* addProperty */
1847: ,JS_PropertyStub /* delProperty */
1848: ,js_file_get /* getProperty */
1849: ,js_file_set /* setProperty */
1850: ,JS_EnumerateStub /* enumerate */
1851: ,JS_ResolveStub /* resolve */
1852: ,JS_ConvertStub /* convert */
1853: ,js_finalize_file /* finalize */
1854: };
1855:
1856: /* File Constructor (creates file descriptor) */
1857:
1858: static JSBool
1859: js_file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1860: {
1861: JSString* str;
1862: private_t* p;
1863:
1864: if((str = JS_ValueToString(cx, argv[0]))==NULL) {
1865: JS_ReportError(cx,"No filename specified");
1866: return(JS_FALSE);
1867: }
1868:
1869: *rval = JSVAL_VOID;
1870:
1871: if((p=(private_t*)calloc(1,sizeof(private_t)))==NULL) {
1872: JS_ReportError(cx,"calloc failed");
1873: return(JS_FALSE);
1874: }
1875:
1876: SAFECOPY(p->name,JS_GetStringBytes(str));
1877:
1878: if(!JS_SetPrivate(cx, obj, p)) {
1879: dbprintf(TRUE, p, "JS_SetPrivate failed");
1880: return(JS_FALSE);
1881: }
1882:
1883: if(!js_DefineSyncProperties(cx, obj, js_file_properties)) {
1884: dbprintf(TRUE, p, "js_DefineSyncProperties failed");
1885: return(JS_FALSE);
1886: }
1887:
1888: if(!js_DefineSyncMethods(cx, obj, js_file_functions, FALSE)) {
1889: dbprintf(TRUE, p, "js_DefineSyncMethods failed");
1890: return(JS_FALSE);
1891: }
1892:
1893: #ifdef BUILD_JSDOCS
1894: js_DescribeSyncObject(cx,obj,"Class used for opening, creating, reading, or writing files on the local file system<p>"
1895: "Special features include:</h2><ol type=disc>"
1896: "<li>Exclusive-access files (default) or shared files<ol type=circle>"
1897: "<li>optional record-locking"
1898: "<li>buffered or non-buffered I/O"
1899: "</ol>"
1900: "<li>Support for binary files<ol type=circle>"
1901: "<li>native or network byte order (endian)"
1902: "<li>automatic Unix-to-Unix (<i>UUE</i>), yEncode (<i>yEnc</i>) or Base64 encoding/decoding"
1903: "</ol>"
1904: "<li>Support for ASCII text files<ol type=circle>"
1905: "<li>supports line-based I/O<ol type=square>"
1906: "<li>entire file may be read or written as an array of strings"
1907: "<li>individual lines may be read or written one line at a time"
1908: "</ol>"
1909: "<li>supports fixed-length records<ol type=square>"
1910: "<li>optional end-of-text (<i>etx</i>) character for automatic record padding/termination"
1911: "<li>Synchronet <tt>.dat</tt> files use an <i>etx</i> value of 3 (Ctrl-C)"
1912: "</ol>"
1913: "<li>supports <tt>.ini</tt> formated configuration files<ol type=square>"
1914: "<li>concept and support of <i>root</i> ini sections added in v3.12"
1915: "</ol>"
1916: "<li>optional ROT13 encoding/translation"
1917: "</ol>"
1918: "<li>Dynamically-calculated industry standard checksums (e.g. CRC-16, CRC-32, MD5)"
1919: "</ol>"
1920: ,310
1921: );
1922: js_DescribeSyncConstructor(cx,obj,"To create a new File object: <tt>var f = new File(<i>filename</i>)</tt>");
1923: js_CreateArrayOfStrings(cx, obj, "_property_desc_list", file_prop_desc, JSPROP_READONLY);
1924: #endif
1925:
1926: dbprintf(FALSE, p, "object constructed");
1927: return(JS_TRUE);
1928: }
1929:
1930: JSObject* DLLCALL js_CreateFileClass(JSContext* cx, JSObject* parent)
1931: {
1932: JSObject* sockobj;
1933:
1934: sockobj = JS_InitClass(cx, parent, NULL
1935: ,&js_file_class
1936: ,js_file_constructor
1937: ,1 /* number of constructor args */
1938: ,NULL /* props, set in constructor */
1939: ,NULL /* funcs, set in constructor */
1940: ,NULL,NULL);
1941:
1942: return(sockobj);
1943: }
1944:
1945: JSObject* DLLCALL js_CreateFileObject(JSContext* cx, JSObject* parent, char *name, FILE* fp)
1946: {
1947: JSObject* obj;
1948: private_t* p;
1949:
1950: obj = JS_DefineObject(cx, parent, name, &js_file_class, NULL
1951: ,JSPROP_ENUMERATE|JSPROP_READONLY);
1952:
1953: if(obj==NULL)
1954: return(NULL);
1955:
1956: if(!js_DefineSyncProperties(cx, obj, js_file_properties))
1957: return(NULL);
1958:
1959: if (!js_DefineSyncMethods(cx, obj, js_file_functions, FALSE))
1960: return(NULL);
1961:
1962: if((p=(private_t*)calloc(1,sizeof(private_t)))==NULL)
1963: return(NULL);
1964:
1965: p->fp=fp;
1966: p->debug=JS_FALSE;
1967: p->external=JS_TRUE;
1968:
1969: if(!JS_SetPrivate(cx, obj, p)) {
1970: dbprintf(TRUE, p, "JS_SetPrivate failed");
1971: return(NULL);
1972: }
1973:
1974: dbprintf(FALSE, p, "object created");
1975:
1976: return(obj);
1977: }
1978:
1979:
1980: #endif /* JAVSCRIPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.