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