|
|
1.1 root 1: /* js_global.c */
2:
3: /* Synchronet JavaScript "global" object properties/methods for all servers */
4:
5: /* $Id: js_global.c,v 1.210 2006/12/27 09:19:26 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 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: #define JS_THREADSAFE /* needed for JS_SetContextThread */
39:
40: #include "sbbs.h"
41: #include "md5.h"
42: #include "base64.h"
43: #include "htmlansi.h"
44: #include "ini_file.h"
45:
46: /* SpiderMonkey: */
47: #include <jsfun.h>
48:
49: #define MAX_ANSI_SEQ 16
50: #define MAX_ANSI_PARAMS 8
51:
52: #ifdef JAVASCRIPT
53:
54: /* Global Object Properites */
55: enum {
56: GLOB_PROP_ERRNO
57: ,GLOB_PROP_ERRNO_STR
58: ,GLOB_PROP_SOCKET_ERRNO
59: };
60:
61: static JSBool js_system_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
62: {
63: jsint tiny;
64: JSString* js_str;
65:
66: tiny = JSVAL_TO_INT(id);
67:
68: switch(tiny) {
69: case GLOB_PROP_SOCKET_ERRNO:
70: JS_NewNumberValue(cx,ERROR_VALUE,vp);
71: break;
72: case GLOB_PROP_ERRNO:
73: JS_NewNumberValue(cx,errno,vp);
74: break;
75: case GLOB_PROP_ERRNO_STR:
76: if((js_str=JS_NewStringCopyZ(cx, strerror(errno)))==NULL)
77: return(JS_FALSE);
78: *vp = STRING_TO_JSVAL(js_str);
79: break;
80: }
81: return(JS_TRUE);
82: }
83:
84: #define GLOBOBJ_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED
85:
86: static struct JSPropertySpec js_global_properties[] = {
87: /* name, tinyid, flags */
88:
89: { "errno" ,GLOB_PROP_ERRNO ,GLOBOBJ_FLAGS },
90: { "errno_str" ,GLOB_PROP_ERRNO_STR ,GLOBOBJ_FLAGS },
91: { "socket_errno" ,GLOB_PROP_SOCKET_ERRNO ,GLOBOBJ_FLAGS },
92: {0}
93: };
94:
95: typedef struct {
96: JSRuntime* runtime;
97: JSContext* cx;
98: JSContext* parent_cx;
99: JSObject* obj;
100: JSScript* script;
101: msg_queue_t* msg_queue;
102: js_branch_t branch;
103: JSErrorReporter error_reporter;
104: JSNative log;
105: } background_data_t;
106:
107: static void background_thread(void* arg)
108: {
109: background_data_t* bg = (background_data_t*)arg;
110: jsval result=JSVAL_VOID;
111: jsval exit_code;
112:
113: msgQueueAttach(bg->msg_queue);
114: JS_SetContextThread(bg->cx);
115: if(!JS_ExecuteScript(bg->cx, bg->obj, bg->script, &result)
116: && JS_GetProperty(bg->cx, bg->obj, "exit_code", &exit_code))
117: result=exit_code;
118: js_EvalOnExit(bg->cx, bg->obj, &bg->branch);
119: js_enqueue_value(bg->cx, bg->msg_queue, result, NULL);
120: JS_DestroyScript(bg->cx, bg->script);
121: JS_DestroyContext(bg->cx);
122: JS_DestroyRuntime(bg->runtime);
123: free(bg);
124: }
125:
126: static void
127: js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
128: {
129: background_data_t* bg;
130:
131: if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
132: return;
133:
134: /* Use parent's context private data */
135: JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
136:
137: /* Call parent's error reporter */
138: bg->error_reporter(cx, message, report);
139:
140: /* Restore our context private data */
141: JS_SetContextPrivate(cx, bg);
142: }
143:
144: static JSBool js_BranchCallback(JSContext *cx, JSScript* script)
145: {
146: background_data_t* bg;
147:
148: if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
149: return(JS_FALSE);
150:
151: if(bg->parent_cx!=NULL && !JS_IsRunning(bg->parent_cx)) /* die when parent dies */
152: return(JS_FALSE);
153:
154: return js_CommonBranchCallback(cx,&bg->branch);
155: }
156:
157: static JSBool
158: js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
159: {
160: JSBool retval;
161: background_data_t* bg;
162:
163: if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
164: return JS_FALSE;
165:
166: /* Use parent's context private data */
167: JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
168:
169: /* Call parent's log() function */
170: retval = bg->log(cx, obj, argc, argv, rval);
171:
172: /* Restore our context private data */
173: JS_SetContextPrivate(cx, bg);
174:
175: return retval;
176: }
177:
178: /* Create a new value in the new context with a value from the original context */
179: /* Note: objects (including arrays) not currently supported */
180: static jsval* js_CopyValue(JSContext* cx, jsval val, JSContext* new_cx, jsval* rval)
181: {
182: *rval = JSVAL_VOID;
183:
184: if(cx==new_cx
185: || JSVAL_IS_BOOLEAN(val)
186: || JSVAL_IS_NULL(val)
187: || JSVAL_IS_VOID(val)
188: || JSVAL_IS_INT(val))
189: *rval = val;
190: else if(JSVAL_IS_NUMBER(val)) {
191: jsdouble d;
192: if(JS_ValueToNumber(cx,val,&d))
193: JS_NewNumberValue(new_cx,d,rval);
194: }
195: else {
196: JSString* str;
197: size_t len;
198: char* p;
199:
200: if((p=js_ValueToStringBytes(cx,val,&len)) != NULL
201: && (str=JS_NewStringCopyN(new_cx,p,len)) != NULL)
202: *rval=STRING_TO_JSVAL(str);
203: }
204:
205: return rval;
206: }
207:
208: static JSBool
209: js_load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
210: {
211: char path[MAX_PATH+1];
212: uintN i;
213: uintN argn=0;
214: const char* filename;
215: JSScript* script;
216: scfg_t* cfg;
217: jsval val;
218: JSObject* js_argv;
219: JSObject* exec_obj;
220: JSContext* exec_cx=cx;
221: JSBool success;
222: JSBool background=JS_FALSE;
223: background_data_t* bg;
224:
225: *rval=JSVAL_VOID;
226:
227: if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL)
228: return(JS_FALSE);
229:
230: exec_obj=JS_GetScopeChain(cx);
231:
232: if(JSVAL_IS_BOOLEAN(argv[argn]))
233: background=JSVAL_TO_BOOLEAN(argv[argn++]);
234:
235: if(background) {
236:
237: if((bg=(background_data_t*)malloc(sizeof(background_data_t)))==NULL)
238: return(JS_FALSE);
239: memset(bg,0,sizeof(background_data_t));
240:
241: bg->parent_cx = cx;
242:
243: /* Setup default values for branch settings */
244: bg->branch.limit=JAVASCRIPT_BRANCH_LIMIT;
245: bg->branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
246: bg->branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
247: if(JS_GetProperty(cx, obj,"js",&val)) /* copy branch settings from parent */
248: memcpy(&bg->branch,JS_GetPrivate(cx,JSVAL_TO_OBJECT(val)),sizeof(bg->branch));
249: bg->branch.terminated=NULL; /* could be bad pointer at any time */
250: bg->branch.counter=0;
251: bg->branch.gc_attempts=0;
252:
253: if((bg->runtime = JS_NewRuntime(JAVASCRIPT_MAX_BYTES))==NULL)
254: return(JS_FALSE);
255:
256: if((bg->cx = JS_NewContext(bg->runtime, JAVASCRIPT_CONTEXT_STACK))==NULL)
257: return(JS_FALSE);
258:
259: if((bg->obj=js_CreateCommonObjects(bg->cx
260: ,cfg /* common config */
261: ,NULL /* node-specific config */
262: ,NULL /* additional global methods */
263: ,0 /* uptime */
264: ,"" /* hostname */
265: ,"" /* socklib_desc */
266: ,&bg->branch /* js */
267: ,NULL /* client */
268: ,INVALID_SOCKET /* client_socket */
269: ,NULL /* server props */
270: ))==NULL)
271: return(JS_FALSE);
272:
273: bg->msg_queue = msgQueueInit(NULL,MSG_QUEUE_BIDIR);
274:
275: js_CreateQueueObject(bg->cx, bg->obj, "parent_queue", bg->msg_queue);
276:
277: /* Save parent's error reporter (for later use by our error reporter) */
278: bg->error_reporter=JS_SetErrorReporter(cx,NULL);
279: JS_SetErrorReporter(cx,bg->error_reporter);
280: JS_SetErrorReporter(bg->cx,js_ErrorReporter);
281:
282: /* Set our branch callback (which calls the generic branch callback) */
283: JS_SetContextPrivate(bg->cx, bg);
284: JS_SetBranchCallback(bg->cx, js_BranchCallback);
285:
286: /* Save parent's 'log' function (for later use by our log function) */
287: if(JS_GetProperty(cx, obj, "log", &val)) {
288: JSFunction* func;
289: if((func=JS_ValueToFunction(cx, val))!=NULL && !func->interpreted) {
290: bg->log=func->u.native;
291: JS_DefineFunction(bg->cx, bg->obj
292: ,"log", js_log, func->nargs, func->flags);
293: }
294: }
295:
296: exec_cx = bg->cx;
297: exec_obj = bg->obj;
298:
299: } else if(JSVAL_IS_OBJECT(argv[argn])) {
300: JSObject* tmp_obj=JSVAL_TO_OBJECT(argv[argn++]);
301: if(!JS_ObjectIsFunction(cx,tmp_obj)) /* Scope specified */
302: exec_obj=tmp_obj;
303: }
304:
305: if(argn==argc) {
306: JS_ReportError(cx,"no filename specified");
307: return(JS_FALSE);
308: }
309: if((filename=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
310: return(JS_FALSE);
311:
312: if(argc>argn || background) {
313:
314: if((js_argv=JS_NewArrayObject(exec_cx, 0, NULL)) == NULL)
315: return(JS_FALSE);
316:
317: JS_DefineProperty(exec_cx, exec_obj, "argv", OBJECT_TO_JSVAL(js_argv)
318: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
319:
320: for(i=argn; i<argc; i++)
321: JS_SetElement(exec_cx, js_argv, i-argn, js_CopyValue(cx,argv[i],exec_cx,&val));
322:
323: JS_DefineProperty(exec_cx, exec_obj, "argc", INT_TO_JSVAL(argc-argn)
324: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
325: }
326:
327: errno = 0;
328: if(isfullpath(filename))
329: strcpy(path,filename);
330: else {
331: sprintf(path,"%s%s",cfg->mods_dir,filename);
332: if(cfg->mods_dir[0]==0 || !fexistcase(path))
333: sprintf(path,"%s%s",cfg->exec_dir,filename);
334: }
335:
336: JS_ClearPendingException(exec_cx);
337:
338: if((script=JS_CompileFile(exec_cx, exec_obj, path))==NULL)
339: return(JS_FALSE);
340:
341: if(background) {
342:
343: bg->script = script;
344: *rval = OBJECT_TO_JSVAL(js_CreateQueueObject(cx, obj, NULL, bg->msg_queue));
345: success = _beginthread(background_thread,0,bg)!=-1;
346:
347: } else {
348:
349: success = JS_ExecuteScript(exec_cx, exec_obj, script, rval);
350: JS_DestroyScript(exec_cx, script);
351: }
352:
353: return(success);
354: }
355:
356: static JSBool
357: js_format(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
358: {
359: char* p;
360: JSString* str;
361:
362: if((p=js_sprintf(cx, 0, argc, argv))==NULL) {
363: JS_ReportError(cx,"js_sprintf failed");
364: return(JS_FALSE);
365: }
366:
367: str = JS_NewStringCopyZ(cx, p);
368: js_sprintf_free(p);
369:
370: if(str==NULL)
371: return(JS_FALSE);
372:
373: *rval = STRING_TO_JSVAL(str);
374: return(JS_TRUE);
375: }
376:
377: static JSBool
378: js_yield(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
379: {
380: BOOL forced=TRUE;
381:
382: if(argc)
383: JS_ValueToBoolean(cx, argv[0], &forced);
384: if(forced) {
385: YIELD();
386: } else {
387: MAYBE_YIELD();
388: }
389:
390: return(JS_TRUE);
391: }
392:
393: static JSBool
394: js_mswait(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
395: {
396: int32 val=1;
397: clock_t start=msclock();
398:
399: if(argc)
400: JS_ValueToInt32(cx,argv[0],&val);
401: mswait(val);
402:
403: JS_NewNumberValue(cx,msclock()-start,rval);
404:
405: return(JS_TRUE);
406: }
407:
408: static JSBool
409: js_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
410: {
411: int32 val=100;
412:
413: if(argc)
414: JS_ValueToInt32(cx,argv[0],&val);
415:
416: JS_NewNumberValue(cx,sbbs_random(val),rval);
417: return(JS_TRUE);
418: }
419:
420: static JSBool
421: js_time(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
422: {
423: JS_NewNumberValue(cx,time(NULL),rval);
424: return(JS_TRUE);
425: }
426:
427:
428: static JSBool
429: js_beep(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
430: {
431: int32 freq=500;
432: int32 dur=500;
433:
434: if(argc)
435: JS_ValueToInt32(cx,argv[0],&freq);
436: if(argc>1)
437: JS_ValueToInt32(cx,argv[1],&dur);
438:
439: sbbs_beep(freq,dur);
440: return(JS_TRUE);
441: }
442:
443: static JSBool
444: js_exit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
445: {
446: if(argc)
447: JS_DefineProperty(cx, obj, "exit_code", argv[0]
448: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
449:
450: return(JS_FALSE);
451: }
452:
453: static JSBool
454: js_crc16(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
455: {
456: char* p;
457: size_t len;
458:
459: if(JSVAL_IS_VOID(argv[0]))
460: return(JS_TRUE);
461:
462: if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
463: return(JS_FALSE);
464:
465: *rval = INT_TO_JSVAL(crc16(p,len));
466: return(JS_TRUE);
467: }
468:
469: static JSBool
470: js_crc32(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
471: {
472: char* p;
473: size_t len;
474:
475: if(JSVAL_IS_VOID(argv[0]))
476: return(JS_TRUE);
477:
478: if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
479: return(JS_FALSE);
480:
481: JS_NewNumberValue(cx,crc32(p,len),rval);
482: return(JS_TRUE);
483: }
484:
485: static JSBool
486: js_chksum(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
487: {
488: ulong sum=0;
489: char* p;
490: size_t len;
491:
492: if(JSVAL_IS_VOID(argv[0]))
493: return(JS_TRUE);
494:
495: if((p=js_ValueToStringBytes(cx, argv[0], &len))==NULL)
496: return(JS_FALSE);
497:
498: while(len--) sum+=*(p++);
499:
500: JS_NewNumberValue(cx,sum,rval);
501: return(JS_TRUE);
502: }
503:
504: static JSBool
505: js_ascii(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
506: {
507: char* p;
508: char str[2];
509: int32 i=0;
510: JSString* js_str;
511:
512: if(JSVAL_IS_VOID(argv[0]))
513: return(JS_TRUE);
514:
515: if(JSVAL_IS_STRING(argv[0])) { /* string to ascii-int */
516:
517: if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
518: return(JS_FALSE);
519:
520: *rval=INT_TO_JSVAL(*p);
521: return(JS_TRUE);
522: }
523:
524: /* ascii-int to str */
525: JS_ValueToInt32(cx,argv[0],&i);
526: str[0]=(uchar)i;
527: str[1]=0;
528:
529: if((js_str = JS_NewStringCopyZ(cx, str))==NULL)
530: return(JS_FALSE);
531:
532: *rval = STRING_TO_JSVAL(js_str);
533: return(JS_TRUE);
534: }
535:
536: static JSBool
537: js_ctrl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
538: {
539: char ch;
540: char* p;
541: char str[2];
542: int32 i=0;
543: JSString* js_str;
544:
545: if(JSVAL_IS_VOID(argv[0]))
546: return(JS_TRUE);
547:
548: if(JSVAL_IS_STRING(argv[0])) {
549:
550: if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
551: return(JS_FALSE);
552: ch=*p;
553: } else {
554: JS_ValueToInt32(cx,argv[0],&i);
555: ch=(char)i;
556: }
557:
558: str[0]=toupper(ch)&~0x40;
559: str[1]=0;
560:
561: if((js_str = JS_NewStringCopyZ(cx, str))==NULL)
562: return(JS_FALSE);
563:
564: *rval = STRING_TO_JSVAL(js_str);
565: return(JS_TRUE);
566: }
567:
568: static JSBool
569: js_ascii_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
570: {
571: char* p;
572: char* buf;
573: JSString* str;
574:
575: if(JSVAL_IS_VOID(argv[0]))
576: return(JS_TRUE);
577:
578: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
579: return(JS_FALSE);
580:
581: if((buf=strdup(p))==NULL)
582: return(JS_FALSE);
583:
584: ascii_str(buf);
585:
586: str = JS_NewStringCopyZ(cx, buf);
587: free(buf);
588: if(str==NULL)
589: return(JS_FALSE);
590:
591: *rval = STRING_TO_JSVAL(str);
592: return(JS_TRUE);
593: }
594:
595:
596: static JSBool
597: js_strip_ctrl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
598: {
599: char* p;
600: char* buf;
601: JSString* js_str;
602:
603: if(JSVAL_IS_VOID(argv[0]))
604: return(JS_TRUE);
605:
606: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
607: return(JS_FALSE);
608:
609: if((buf=strdup(p))==NULL)
610: return(JS_FALSE);
611:
612: strip_ctrl(buf);
613:
614: js_str = JS_NewStringCopyZ(cx, buf);
615: free(buf);
616: if(js_str==NULL)
617: return(JS_FALSE);
618:
619: *rval = STRING_TO_JSVAL(js_str);
620: return(JS_TRUE);
621: }
622:
623: static JSBool
624: js_strip_exascii(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
625: {
626: char* p;
627: char* buf;
628: JSString* js_str;
629:
630: if(JSVAL_IS_VOID(argv[0]))
631: return(JS_TRUE);
632:
633: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
634: return(JS_FALSE);
635:
636: if((buf=strdup(p))==NULL)
637: return(JS_FALSE);
638:
639: strip_exascii(buf);
640:
641: js_str = JS_NewStringCopyZ(cx, buf);
642: free(buf);
643: if(js_str==NULL)
644: return(JS_FALSE);
645:
646: *rval = STRING_TO_JSVAL(js_str);
647: return(JS_TRUE);
648: }
649:
650: static JSBool
651: js_lfexpand(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
652: {
653: ulong i,j;
654: char* inbuf;
655: char* outbuf;
656: JSString* str;
657:
658: if(JSVAL_IS_VOID(argv[0]))
659: return(JS_TRUE);
660:
661: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
662: return(JS_FALSE);
663:
664: if((outbuf=(char*)malloc((strlen(inbuf)*2)+1))==NULL)
665: return(JS_FALSE);
666:
667: for(i=j=0;inbuf[i];i++) {
668: if(inbuf[i]=='\n' && (!i || inbuf[i-1]!='\r'))
669: outbuf[j++]='\r';
670: outbuf[j++]=inbuf[i];
671: }
672: outbuf[j]=0;
673:
674: str = JS_NewStringCopyZ(cx, outbuf);
675: free(outbuf);
676: if(str==NULL)
677: return(JS_FALSE);
678:
679: *rval = STRING_TO_JSVAL(str);
680: return(JS_TRUE);
681: }
682:
683: static int get_prefix(char *text, int *bytes, int *len, int maxlen)
684: {
685: int tmp_prefix_bytes,tmp_prefix_len;
686: int expect;
687: int depth;
688:
689: *bytes=0;
690: *len=0;
691: tmp_prefix_bytes=0;
692: tmp_prefix_len=0;
693: depth=0;
694: expect=1;
695: if(text[0]!=' ')
696: expect=2;
697: while(expect) {
698: tmp_prefix_bytes++;
699: /* Skip CTRL-A codes */
700: while(text[tmp_prefix_bytes-1]=='\x01') {
701: tmp_prefix_bytes++;
702: if(text[tmp_prefix_bytes-1]=='\x01')
703: break;
704: tmp_prefix_bytes++;
705: }
706: tmp_prefix_len++;
707: if(text[tmp_prefix_bytes-1]==0 || text[tmp_prefix_bytes-1]=='\n' || text[tmp_prefix_bytes-1]=='\r')
708: break;
709: switch(expect) {
710: case 1: /* At start of possible quote (Next char should be space) */
711: if(text[tmp_prefix_bytes-1]!=' ')
712: expect=0;
713: else
714: expect++;
715: break;
716: case 2: /* At start of nick (next char should be alphanum or '>') */
717: case 3: /* At second nick initial (next char should be alphanum or '>') */
718: case 4: /* At third nick initial (next char should be alphanum or '>') */
719: if(text[tmp_prefix_bytes-1]==' ' || text[tmp_prefix_bytes-1]==0)
720: expect=0;
721: else
722: if(text[tmp_prefix_bytes-1]=='>')
723: expect=6;
724: else
725: expect++;
726: break;
727: case 5: /* After three regular chars, next HAS to be a '>') */
728: if(text[tmp_prefix_bytes-1]!='>')
729: expect=0;
730: else
731: expect++;
732: break;
733: case 6: /* At '>' next char must be a space */
734: if(text[tmp_prefix_bytes-1]!=' ')
735: expect=0;
736: else {
737: expect=1;
738: *len=tmp_prefix_len;
739: *bytes=tmp_prefix_bytes;
740: depth++;
741: /* Some editors don't put double spaces in between */
742: if(text[tmp_prefix_bytes]!=' ')
743: expect++;
744: }
745: break;
746: default:
747: expect=0;
748: break;
749: }
750: }
751: if(*bytes >= maxlen) {
752: lprintf(LOG_CRIT, "Prefix bytes %u is larger than buffer (%u) here: %*.*s",*bytes,maxlen,maxlen,maxlen,text);
753: *bytes=maxlen-1;
754: }
755: return(depth);
756: }
757:
758: static void outbuf_append(char **outbuf, char **outp, char *append, int len, int *outlen)
759: {
760: char *p;
761:
762: /* Terminate outbuf */
763: **outp=0;
764: /* Check if there's room */
765: if(*outp - *outbuf + len < *outlen) {
766: memcpy(*outp, append, len);
767: *outp+=len;
768: return;
769: }
770: /* Not enough room, double the size. */
771: *outlen *= 2;
772: p=realloc(*outbuf, *outlen);
773: if(p==NULL) {
774: /* Can't do it. */
775: *outlen/=2;
776: return;
777: }
778: /* Set outp for new buffer */
779: *outp=p+(*outp - *outbuf);
780: *outbuf=p;
781: memcpy(*outp, append, len);
782: *outp+=len;
783: return;
784: }
785:
786: static JSBool
787: js_word_wrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
788: {
789: int32 l,len=79;
790: int32 oldlen=79;
791: int32 crcount=0;
792: JSBool handle_quotes=JS_TRUE;
793: long i,k,t;
794: int ocol=1;
795: int icol=1;
796: uchar* inbuf;
797: char* outbuf;
798: char* outp;
799: char* linebuf;
800: char* prefix=NULL;
801: int prefix_len=0;
802: int prefix_bytes=0;
803: int quote_count=0;
804: int old_prefix_bytes=0;
805: int outbuf_size=0;
806: JSString* js_str;
807:
808: if(JSVAL_IS_VOID(argv[0]))
809: return(JS_TRUE);
810:
811: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
812: return(JS_FALSE);
813:
814: outbuf_size=strlen(inbuf)*3+1;
815: if((outbuf=(char*)malloc(outbuf_size))==NULL)
816: return(JS_FALSE);
817: outp=outbuf;
818:
819: if(argc>1)
820: JS_ValueToInt32(cx,argv[1],&len);
821:
822: if(argc>2)
823: JS_ValueToInt32(cx,argv[2],&oldlen);
824:
825: if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
826: handle_quotes=JSVAL_TO_BOOLEAN(argv[3]);
827:
828: if((linebuf=(char*)alloca((len*2)+2))==NULL) /* room for ^A codes ToDo: This isn't actually "enough" room */
829: return(JS_FALSE);
830:
831: if(handle_quotes) {
832: if((prefix=(char *)alloca((len*2)+2))==NULL) /* room for ^A codes ToDo: This isn't actually "enough" room */
833: return(JS_FALSE);
834: prefix[0]=0;
835: }
836:
837: outbuf[0]=0;
838: /* Get prefix from the first line (ouch) */
839: l=0;
840: i=0;
841: if(handle_quotes && (quote_count=get_prefix(inbuf, &prefix_bytes, &prefix_len, len*2+2))!=0) {
842: i+=prefix_bytes;
843: if(prefix_len>len/3*2) {
844: /* This prefix is insane (more than 2/3rds of the new width) hack it down to size */
845: /* Since we're hacking it, we will always end up with a hardcr on this line. */
846: /* ToDo: Something prettier would be nice. */
847: sprintf(prefix," %d> ",quote_count);
848: prefix_len=strlen(prefix);
849: prefix_bytes=strlen(prefix);
850: }
851: else {
852: memcpy(prefix,inbuf,prefix_bytes);
853: /* Terminate prefix */
854: prefix[prefix_bytes]=0;
855: }
856: memcpy(linebuf,prefix,prefix_bytes);
857: l=prefix_bytes;
858: ocol=prefix_len+1;
859: icol=prefix_len+1;
860: old_prefix_bytes=prefix_bytes;
861: }
862: for(; inbuf[i]; i++) {
863: if(l>=len*2+2) {
864: l-=4;
865: linebuf[l]=0;
866: lprintf(LOG_CRIT, "Word wrap line buffer exceeded... munging line %s",linebuf);
867: }
868: switch(inbuf[i]) {
869: case '\r':
870: crcount++;
871: break;
872: case '\n':
873: if(handle_quotes && (quote_count=get_prefix(inbuf+i+1, &prefix_bytes, &prefix_len, len*2+2))!=0) {
874: /* Move the input pointer offset to the last char of the prefix */
875: i+=prefix_bytes;
876: }
877: if(!inbuf[i+1]) { /* EOF */
878: linebuf[l++]='\r';
879: linebuf[l++]='\n';
880: outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
881: l=0;
882: ocol=1;
883: }
884: /* If there's a new prefix, it is a hardcr */
885: else if(prefix_bytes != old_prefix_bytes || (memcmp(prefix,inbuf+i+1-prefix_bytes,prefix_bytes))) {
886: if(prefix_len>len/3*2) {
887: /* This prefix is insane (more than 2/3rds of the new width) hack it down to size */
888: /* Since we're hacking it, we will always end up with a hardcr on this line. */
889: /* ToDo: Something prettier would be nice. */
890: sprintf(prefix," %d> ",quote_count);
891: prefix_len=strlen(prefix);
892: prefix_bytes=strlen(prefix);
893: }
894: else {
895: memcpy(prefix,inbuf+i+1-prefix_bytes,prefix_bytes);
896: /* Terminate prefix */
897: prefix[prefix_bytes]=0;
898: }
899: linebuf[l++]='\r';
900: linebuf[l++]='\n';
901: outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
902: memcpy(linebuf,prefix,prefix_bytes);
903: l=prefix_bytes;
904: ocol=prefix_len+1;
905: old_prefix_bytes=prefix_bytes;
906: }
907: else if(isspace(inbuf[i+1])) { /* Next line starts with whitespace. This is a "hard" CR. */
908: linebuf[l++]='\r';
909: linebuf[l++]='\n';
910: outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
911: l=0;
912: ocol=1;
913: }
914: else {
915: if(icol < oldlen) { /* If this line is overly long, It's impossible for the next word to fit */
916: /* k will equal the length of the first word on the next line */
917: for(k=0; inbuf[i+1+k] && (!isspace(inbuf[i+1+k])); k++);
918: if(icol+k+1 < oldlen) { /* The next word would have fit but isn't here. Must be a hard CR */
919: linebuf[l++]='\r';
920: linebuf[l++]='\n';
921: outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
922: if(prefix)
923: memcpy(linebuf,prefix,prefix_bytes);
924: l=prefix_bytes;
925: ocol=prefix_len+1;
926: }
927: else { /* Not a hard CR... add space if needed */
928: if(l<1 || !isspace(linebuf[l-1])) {
929: linebuf[l++]=' ';
930: ocol++;
931: }
932: }
933: }
934: else { /* Not a hard CR... add space if needed */
935: if(l<1 || !isspace(linebuf[l-1])) {
936: linebuf[l++]=' ';
937: ocol++;
938: }
939: }
940: }
941: icol=prefix_len+1;
942: break;
943: case '\x1f': /* Delete... meaningless... strip. */
944: break;
945: case '\b': /* Backspace... handle if possible, but don't go crazy. */
946: if(l>0) {
947: if(l>1 && linebuf[l-2]=='\x01') {
948: if(linebuf[l-1]=='\x01') {
949: ocol--;
950: icol--;
951: }
952: l-=2;
953: }
954: else {
955: l--;
956: ocol--;
957: icol--;
958: }
959: }
960: break;
961: case '\t': /* TAB */
962: linebuf[l++]=inbuf[i];
963: /* Can't ever wrap on whitespace remember. */
964: icol++;
965: ocol++;
966: while(ocol%8)
967: ocol++;
968: while(icol%8)
969: icol++;
970: break;
971: case '\x01': /* CTRL-A */
972: linebuf[l++]=inbuf[i++];
973: if(inbuf[i]!='\x01') {
974: linebuf[l++]=inbuf[i];
975: break;
976: }
977: default:
978: linebuf[l++]=inbuf[i];
979: ocol++;
980: icol++;
981: if(ocol>len && !isspace(inbuf[i])) { /* Need to wrap here */
982: /* Find the start of the last word */
983: k=l; /* Original next char */
984: l--; /* Move back to the last char */
985: while((!isspace(linebuf[l])) && l>0) /* Move back to the last non-space char */
986: l--;
987: if(l==0) { /* Couldn't wrap... must chop. */
988: l=k;
989: while(l>1 && linebuf[l-2]=='\x01' && linebuf[l-1]!='\x01')
990: l-=2;
991: if(l>0 && linebuf[l-1]=='\x01')
992: l--;
993: if(l>0)
994: l--;
995: }
996: t=l+1; /* Store start position of next line */
997: /* Move to start of whitespace */
998: while(l>0 && isspace(l))
999: l--;
1000: outbuf_append(&outbuf, &outp, linebuf, l+1, &outbuf_size);
1001: outbuf_append(&outbuf, &outp, "\r\n", 2, &outbuf_size);
1002: /* Move trailing words to start of buffer. */
1003: l=prefix_bytes;
1004: if(k-t>0) /* k-1 is the last char position. t is the start of the next line position */
1005: memmove(linebuf+l, linebuf+t, k-t);
1006: l+=k-t;
1007: /* Find new ocol */
1008: for(ocol=prefix_len+1,t=prefix_bytes; t<l; t++) {
1009: switch(linebuf[t]) {
1010: case '\x01': /* CTRL-A */
1011: if(linebuf[t+1]!='\x01')
1012: break;
1013: t++;
1014: /* Fall-through */
1015: default:
1016: ocol++;
1017: }
1018: }
1019: }
1020: }
1021: }
1022: /* Trailing bits. */
1023: if(l) {
1024: linebuf[l++]='\r';
1025: linebuf[l++]='\n';
1026: outbuf_append(&outbuf, &outp, linebuf, l, &outbuf_size);
1027: }
1028: *outp=0;
1029: /* If there were no CRs in the input, strip all CRs */
1030: if(!crcount) {
1031: for(inbuf=outbuf; *inbuf; inbuf++) {
1032: if(*inbuf=='\r')
1033: memmove(inbuf, inbuf+1, strlen(inbuf));
1034: }
1035: }
1036:
1037: js_str = JS_NewStringCopyZ(cx, outbuf);
1038: free(outbuf);
1039: if(js_str==NULL)
1040: return(JS_FALSE);
1041:
1042: *rval = STRING_TO_JSVAL(js_str);
1043: return(JS_TRUE);
1044: }
1045:
1046: static JSBool
1047: js_quote_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1048: {
1049: int32 len=79;
1050: int i,l,clen;
1051: uchar* inbuf;
1052: char* outbuf;
1053: char* linebuf;
1054: char* prefix=" > ";
1055: JSString* js_str;
1056:
1057: if(JSVAL_IS_VOID(argv[0]))
1058: return(JS_TRUE);
1059:
1060: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
1061: return(JS_FALSE);
1062:
1063: if(argc>1)
1064: JS_ValueToInt32(cx,argv[1],&len);
1065:
1066: if(argc>2)
1067: prefix=js_ValueToStringBytes(cx, argv[2], NULL);
1068:
1069: if((outbuf=(char*)malloc((strlen(inbuf)*strlen(prefix))+1))==NULL)
1070: return(JS_FALSE);
1071:
1072: len-=strlen(prefix);
1073: if(len<=0)
1074: return(JS_FALSE);
1075:
1076: if((linebuf=(char*)alloca(len*2+2))==NULL) /* (Hopefully) Room for ^A codes. ToDo */
1077: return(JS_FALSE);
1078:
1079: outbuf[0]=0;
1080: clen=0;
1081: for(i=l=0;inbuf[i];i++) {
1082: if(l==0) /* Do not use clen here since if the line starts with ^A, could stay at zero */
1083: strcat(outbuf,prefix);
1084: if(clen<len || inbuf[i]=='\n' || inbuf[i]=='\r')
1085: linebuf[l++]=inbuf[i];
1086: if(inbuf[i]=='\x01') { /* Handle CTRL-A */
1087: linebuf[l++]=inbuf[++i];
1088: if(inbuf[i]=='\x01')
1089: clen++;
1090: }
1091: else
1092: clen++;
1093: /* ToDo: Handle TABs etc. */
1094: if(inbuf[i]=='\n') {
1095: strncat(outbuf,linebuf,l);
1096: l=0;
1097: clen=0;
1098: }
1099: }
1100: if(l) /* remainder */
1101: strncat(outbuf,linebuf,l);
1102:
1103: js_str = JS_NewStringCopyZ(cx, outbuf);
1104: free(outbuf);
1105: if(js_str==NULL)
1106: return(JS_FALSE);
1107:
1108: *rval = STRING_TO_JSVAL(js_str);
1109: return(JS_TRUE);
1110: }
1111:
1112: static JSBool
1113: js_netaddr_type(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1114: {
1115: char* str;
1116:
1117: if(JSVAL_IS_VOID(argv[0]))
1118: return(JS_TRUE);
1119:
1120: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
1121: return(JS_FALSE);
1122:
1123: *rval = INT_TO_JSVAL(smb_netaddr_type(str));
1124:
1125: return(JS_TRUE);
1126: }
1127:
1128: static JSBool
1129: js_rot13(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1130: {
1131: char* p;
1132: char* str;
1133: JSString* js_str;
1134:
1135: if(JSVAL_IS_VOID(argv[0]))
1136: return(JS_TRUE);
1137:
1138: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
1139: return(JS_FALSE);
1140:
1141: if((p=strdup(str))==NULL)
1142: return(JS_FALSE);
1143:
1144: js_str = JS_NewStringCopyZ(cx, rot13(p));
1145: free(p);
1146: if(js_str==NULL)
1147: return(JS_FALSE);
1148:
1149: *rval = STRING_TO_JSVAL(js_str);
1150: return(JS_TRUE);
1151: }
1152:
1153: /* This table is used to convert between IBM ex-ASCII and HTML character entities */
1154: /* Much of this table supplied by Deuce (thanks!) */
1155: static struct {
1156: int value;
1157: char* name;
1158: } exasctbl[128] = {
1159: /* HTML val,name ASCII description */
1160: { 199 ,"Ccedil" }, /* 128 C, cedilla */
1161: { 252 ,"uuml" }, /* 129 u, umlaut */
1162: { 233 ,"eacute" }, /* 130 e, acute accent */
1163: { 226 ,"acirc" }, /* 131 a, circumflex accent */
1164: { 228 ,"auml" }, /* 132 a, umlaut */
1165: { 224 ,"agrave" }, /* 133 a, grave accent */
1166: { 229 ,"aring" }, /* 134 a, ring */
1167: { 231 ,"ccedil" }, /* 135 c, cedilla */
1168: { 234 ,"ecirc" }, /* 136 e, circumflex accent */
1169: { 235 ,"euml" }, /* 137 e, umlaut */
1170: { 232 ,"egrave" }, /* 138 e, grave accent */
1171: { 239 ,"iuml" }, /* 139 i, umlaut */
1172: { 238 ,"icirc" }, /* 140 i, circumflex accent */
1173: { 236 ,"igrave" }, /* 141 i, grave accent */
1174: { 196 ,"Auml" }, /* 142 A, umlaut */
1175: { 197 ,"Aring" }, /* 143 A, ring */
1176: { 201 ,"Eacute" }, /* 144 E, acute accent */
1177: { 230 ,"aelig" }, /* 145 ae ligature */
1178: { 198 ,"AElig" }, /* 146 AE ligature */
1179: { 244 ,"ocirc" }, /* 147 o, circumflex accent */
1180: { 246 ,"ouml" }, /* 148 o, umlaut */
1181: { 242 ,"ograve" }, /* 149 o, grave accent */
1182: { 251 ,"ucirc" }, /* 150 u, circumflex accent */
1183: { 249 ,"ugrave" }, /* 151 u, grave accent */
1184: { 255 ,"yuml" }, /* 152 y, umlaut */
1185: { 214 ,"Ouml" }, /* 153 O, umlaut */
1186: { 220 ,"Uuml" }, /* 154 U, umlaut */
1187: { 162 ,"cent" }, /* 155 Cent sign */
1188: { 163 ,"pound" }, /* 156 Pound sign */
1189: { 165 ,"yen" }, /* 157 Yen sign */
1190: { 8359 ,NULL }, /* 158 Pt (unicode) */
1191: { 402 ,NULL }, /* 402 Florin (non-standard alsi 159?) */
1192: { 225 ,"aacute" }, /* 160 a, acute accent */
1193: { 237 ,"iacute" }, /* 161 i, acute accent */
1194: { 243 ,"oacute" }, /* 162 o, acute accent */
1195: { 250 ,"uacute" }, /* 163 u, acute accent */
1196: { 241 ,"ntilde" }, /* 164 n, tilde */
1197: { 209 ,"Ntilde" }, /* 165 N, tilde */
1198: { 170 ,"ordf" }, /* 166 Feminine ordinal */
1199: { 186 ,"ordm" }, /* 167 Masculine ordinal */
1200: { 191 ,"iquest" }, /* 168 Inverted question mark */
1201: { 8976 ,NULL }, /* 169 Inverse "Not sign" (unicode) */
1202: { 172 ,"not" }, /* 170 Not sign */
1203: { 189 ,"frac12" }, /* 171 Fraction one-half */
1204: { 188 ,"frac14" }, /* 172 Fraction one-fourth */
1205: { 161 ,"iexcl" }, /* 173 Inverted exclamation point */
1206: { 171 ,"laquo" }, /* 174 Left angle quote */
1207: { 187 ,"raquo" }, /* 175 Right angle quote */
1208: { 9617 ,NULL }, /* 176 drawing symbol (unicode) */
1209: { 9618 ,NULL }, /* 177 drawing symbol (unicode) */
1210: { 9619 ,NULL }, /* 178 drawing symbol (unicode) */
1211: { 9474 ,NULL }, /* 179 drawing symbol (unicode) */
1212: { 9508 ,NULL }, /* 180 drawing symbol (unicode) */
1213: { 9569 ,NULL }, /* 181 drawing symbol (unicode) */
1214: { 9570 ,NULL }, /* 182 drawing symbol (unicode) */
1215: { 9558 ,NULL }, /* 183 drawing symbol (unicode) */
1216: { 9557 ,NULL }, /* 184 drawing symbol (unicode) */
1217: { 9571 ,NULL }, /* 185 drawing symbol (unicode) */
1218: { 9553 ,NULL }, /* 186 drawing symbol (unicode) */
1219: { 9559 ,NULL }, /* 187 drawing symbol (unicode) */
1220: { 9565 ,NULL }, /* 188 drawing symbol (unicode) */
1221: { 9564 ,NULL }, /* 189 drawing symbol (unicode) */
1222: { 9563 ,NULL }, /* 190 drawing symbol (unicode) */
1223: { 9488 ,NULL }, /* 191 drawing symbol (unicode) */
1224: { 9492 ,NULL }, /* 192 drawing symbol (unicode) */
1225: { 9524 ,NULL }, /* 193 drawing symbol (unicode) */
1226: { 9516 ,NULL }, /* 194 drawing symbol (unicode) */
1227: { 9500 ,NULL }, /* 195 drawing symbol (unicode) */
1228: { 9472 ,NULL }, /* 196 drawing symbol (unicode) */
1229: { 9532 ,NULL }, /* 197 drawing symbol (unicode) */
1230: { 9566 ,NULL }, /* 198 drawing symbol (unicode) */
1231: { 9567 ,NULL }, /* 199 drawing symbol (unicode) */
1232: { 9562 ,NULL }, /* 200 drawing symbol (unicode) */
1233: { 9556 ,NULL }, /* 201 drawing symbol (unicode) */
1234: { 9577 ,NULL }, /* 202 drawing symbol (unicode) */
1235: { 9574 ,NULL }, /* 203 drawing symbol (unicode) */
1236: { 9568 ,NULL }, /* 204 drawing symbol (unicode) */
1237: { 9552 ,NULL }, /* 205 drawing symbol (unicode) */
1238: { 9580 ,NULL }, /* 206 drawing symbol (unicode) */
1239: { 9575 ,NULL }, /* 207 drawing symbol (unicode) */
1240: { 9576 ,NULL }, /* 208 drawing symbol (unicode) */
1241: { 9572 ,NULL }, /* 209 drawing symbol (unicode) */
1242: { 9573 ,NULL }, /* 210 drawing symbol (unicode) */
1243: { 9561 ,NULL }, /* 211 drawing symbol (unicode) */
1244: { 9560 ,NULL }, /* 212 drawing symbol (unicode) */
1245: { 9554 ,NULL }, /* 213 drawing symbol (unicode) */
1246: { 9555 ,NULL }, /* 214 drawing symbol (unicode) */
1247: { 9579 ,NULL }, /* 215 drawing symbol (unicode) */
1248: { 9578 ,NULL }, /* 216 drawing symbol (unicode) */
1249: { 9496 ,NULL }, /* 217 drawing symbol (unicode) */
1250: { 9484 ,NULL }, /* 218 drawing symbol (unicode) */
1251: { 9608 ,NULL }, /* 219 drawing symbol (unicode) */
1252: { 9604 ,NULL }, /* 220 drawing symbol (unicode) */
1253: { 9612 ,NULL }, /* 221 drawing symbol (unicode) */
1254: { 9616 ,NULL }, /* 222 drawing symbol (unicode) */
1255: { 9600 ,NULL }, /* 223 drawing symbol (unicode) */
1256: { 945 ,NULL }, /* 224 alpha symbol */
1257: { 223 ,"szlig" }, /* 225 sz ligature (beta symbol) */
1258: { 915 ,NULL }, /* 226 omega symbol */
1259: { 960 ,NULL }, /* 227 pi symbol*/
1260: { 931 ,NULL }, /* 228 epsilon symbol */
1261: { 963 ,NULL }, /* 229 o with stick */
1262: { 181 ,"micro" }, /* 230 Micro sign (Greek mu) */
1263: { 964 ,NULL }, /* 231 greek char? */
1264: { 934 ,NULL }, /* 232 greek char? */
1265: { 920 ,NULL }, /* 233 greek char? */
1266: { 937 ,NULL }, /* 234 greek char? */
1267: { 948 ,NULL }, /* 235 greek char? */
1268: { 8734 ,NULL }, /* 236 infinity symbol (unicode) */
1269: { 966 ,"oslash" }, /* 237 Greek Phi */
1270: { 949 ,NULL }, /* 238 rounded E */
1271: { 8745 ,NULL }, /* 239 unside down U (unicode) */
1272: { 8801 ,NULL }, /* 240 drawing symbol (unicode) */
1273: { 177 ,"plusmn" }, /* 241 Plus or minus */
1274: { 8805 ,NULL }, /* 242 drawing symbol (unicode) */
1275: { 8804 ,NULL }, /* 243 drawing symbol (unicode) */
1276: { 8992 ,NULL }, /* 244 drawing symbol (unicode) */
1277: { 8993 ,NULL }, /* 245 drawing symbol (unicode) */
1278: { 247 ,"divide" }, /* 246 Division sign */
1279: { 8776 ,NULL }, /* 247 two squiggles (unicode) */
1280: { 176 ,"deg" }, /* 248 Degree sign */
1281: { 8729 ,NULL }, /* 249 drawing symbol (unicode) */
1282: { 183 ,"middot" }, /* 250 Middle dot */
1283: { 8730 ,NULL }, /* 251 check mark (unicode) */
1284: { 8319 ,NULL }, /* 252 superscript n (unicode) */
1285: { 178 ,"sup2" }, /* 253 superscript 2 */
1286: { 9632 ,NULL }, /* 254 drawing symbol (unicode) */
1287: { 160 ,"nbsp" } /* 255 non-breaking space */
1288: };
1289:
1290: static struct {
1291: int value;
1292: char* name;
1293: } lowasctbl[32] = {
1294: { 160 ,"nbsp" }, /* NULL non-breaking space */
1295: { 9786 ,NULL }, /* white smiling face */
1296: { 9787 ,NULL }, /* black smiling face */
1297: { 9829 ,"hearts" }, /* black heart suit */
1298: { 9830 ,"diams" }, /* black diamond suit */
1299: { 9827 ,"clubs" }, /* black club suit */
1300: { 9824 ,"spades" }, /* black spade suit */
1301: { 8226 ,"bull" }, /* bullet */
1302: { 9688 ,NULL }, /* inverse bullet */
1303: { 9702 ,NULL }, /* white bullet */
1304: { 9689 ,NULL }, /* inverse white circle */
1305: { 9794 ,NULL }, /* male sign */
1306: { 9792 ,NULL }, /* female sign */
1307: { 9834 ,NULL }, /* eighth note */
1308: { 9835 ,NULL }, /* beamed eighth notes */
1309: { 9788 ,NULL }, /* white sun with rays */
1310: { 9654 ,NULL }, /* black right-pointing triangle */
1311: { 9664 ,NULL }, /* black left-pointing triangle */
1312: { 8597 ,NULL }, /* up down arrow */
1313: { 8252 ,NULL }, /* double exclamation mark */
1314: { 182 ,"para" }, /* pilcrow sign */
1315: { 167 ,"sect" }, /* section sign */
1316: { 9644 ,NULL }, /* black rectangle */
1317: { 8616 ,NULL }, /* up down arrow with base */
1318: { 8593 ,"uarr" }, /* upwards arrow */
1319: { 8595 ,"darr" }, /* downwards arrow */
1320: { 8594 ,"rarr" }, /* rightwards arrow */
1321: { 8592 ,"larr" }, /* leftwards arrow */
1322: { 8985 ,NULL }, /* turned not sign */
1323: { 8596 ,"harr" }, /* left right arrow */
1324: { 9650 ,NULL }, /* black up-pointing triangle */
1325: { 9660 ,NULL } /* black down-pointing triangle */
1326: };
1327:
1328: static JSBool
1329: js_html_encode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1330: {
1331: int ch;
1332: ulong i,j;
1333: uchar* inbuf;
1334: uchar* tmpbuf;
1335: uchar* outbuf;
1336: uchar* param;
1337: char* lastparam;
1338: JSBool exascii=JS_TRUE;
1339: JSBool wsp=JS_TRUE;
1340: JSBool ansi=JS_TRUE;
1341: JSBool ctrl_a=JS_TRUE;
1342: JSString* js_str;
1343: int32 fg=7;
1344: int32 bg=0;
1345: JSBool blink=FALSE;
1346: JSBool bold=FALSE;
1347: int esccount=0;
1348: char ansi_seq[MAX_ANSI_SEQ+1];
1349: int ansi_param[MAX_ANSI_PARAMS];
1350: int k,l;
1351: ulong savepos=0;
1352: int32 hpos=0;
1353: int32 currrow=0;
1354: int savehpos=0;
1355: int savevpos=0;
1356: int32 wraphpos=-2;
1357: int32 wrapvpos=-2;
1358: int32 wrappos=0;
1359: BOOL extchar=FALSE;
1360: ulong obsize;
1361: int32 lastcolor=7;
1362: char tmp1[128];
1363: struct tm tm;
1364: time_t now;
1365: BOOL nodisplay=FALSE;
1366: scfg_t* cfg;
1367: uchar attr_stack[64]; /* Saved attributes (stack) */
1368: int attr_sp=0; /* Attribute stack pointer */
1369: ulong clear_screen=0;
1370: JSObject* stateobj=NULL;
1371: jsval val;
1372:
1373: if(JSVAL_IS_VOID(argv[0]))
1374: return(JS_TRUE);
1375:
1376: if((cfg=(scfg_t*)JS_GetPrivate(cx,obj))==NULL) /* Will this work? Ask DM */
1377: return(JS_FALSE);
1378:
1379: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
1380: return(JS_FALSE);
1381:
1382: if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
1383: exascii=JSVAL_TO_BOOLEAN(argv[1]);
1384:
1385: if(argc>2 && JSVAL_IS_BOOLEAN(argv[2]))
1386: wsp=JSVAL_TO_BOOLEAN(argv[2]);
1387:
1388: if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
1389: ansi=JSVAL_TO_BOOLEAN(argv[3]);
1390:
1391: if(argc>4 && JSVAL_IS_BOOLEAN(argv[4]))
1392: {
1393: ctrl_a=JSVAL_TO_BOOLEAN(argv[4]);
1394: if(ctrl_a)
1395: ansi=ctrl_a;
1396: }
1397:
1398: if(argc>5 && JSVAL_IS_OBJECT(argv[5])) {
1399: stateobj=JSVAL_TO_OBJECT(argv[5]);
1400: JS_GetProperty(cx,stateobj,"fg",&val);
1401: if(JSVAL_IS_NUMBER(val))
1402: fg=JS_ValueToInt32(cx, val, &fg);
1403: JS_GetProperty(cx,stateobj,"bg",&val);
1404: if(JSVAL_IS_NUMBER(val))
1405: fg=JS_ValueToInt32(cx, val, &bg);
1406: JS_GetProperty(cx,stateobj,"lastcolor",&val);
1407: if(JSVAL_IS_NUMBER(val))
1408: fg=JS_ValueToInt32(cx, val, &lastcolor);
1409: JS_GetProperty(cx,stateobj,"blink",&val);
1410: if(JSVAL_IS_BOOLEAN(val))
1411: fg=JS_ValueToBoolean(cx, val, &blink);
1412: JS_GetProperty(cx,stateobj,"bold",&val);
1413: if(JSVAL_IS_BOOLEAN(val))
1414: fg=JS_ValueToBoolean(cx, val, &bold);
1415: JS_GetProperty(cx,stateobj,"hpos",&val);
1416: if(JSVAL_IS_NUMBER(val))
1417: fg=JS_ValueToInt32(cx, val, &hpos);
1418: JS_GetProperty(cx,stateobj,"currrow",&val);
1419: if(JSVAL_IS_NUMBER(val))
1420: fg=JS_ValueToInt32(cx, val, &currrow);
1421: JS_GetProperty(cx,stateobj,"wraphpos",&val);
1422: if(JSVAL_IS_NUMBER(val))
1423: fg=JS_ValueToInt32(cx, val, &wraphpos);
1424: JS_GetProperty(cx,stateobj,"wrapvpos",&val);
1425: if(JSVAL_IS_NUMBER(val))
1426: fg=JS_ValueToInt32(cx, val, &wrapvpos);
1427: JS_GetProperty(cx,stateobj,"wrappos",&val);
1428: if(JSVAL_IS_NUMBER(val))
1429: fg=JS_ValueToInt32(cx, val, &wrappos);
1430: }
1431:
1432: if((tmpbuf=(char*)malloc((strlen(inbuf)*10)+1))==NULL)
1433: return(JS_FALSE);
1434:
1435: for(i=j=0;inbuf[i];i++) {
1436: switch(inbuf[i]) {
1437: case TAB:
1438: case LF:
1439: case CR:
1440: if(wsp)
1441: j+=sprintf(tmpbuf+j,"&#%u;",inbuf[i]);
1442: else
1443: tmpbuf[j++]=inbuf[i];
1444: break;
1445: case '"':
1446: j+=sprintf(tmpbuf+j,""");
1447: break;
1448: case '&':
1449: j+=sprintf(tmpbuf+j,"&");
1450: break;
1451: case '<':
1452: j+=sprintf(tmpbuf+j,"<");
1453: break;
1454: case '>':
1455: j+=sprintf(tmpbuf+j,">");
1456: break;
1457: case '\b':
1458: j--;
1459: break;
1460: default:
1461: if(inbuf[i]&0x80) {
1462: if(exascii) {
1463: ch=inbuf[i]^0x80;
1464: if(exasctbl[ch].name!=NULL)
1465: j+=sprintf(tmpbuf+j,"&%s;",exasctbl[ch].name);
1466: else
1467: j+=sprintf(tmpbuf+j,"&#%u;",exasctbl[ch].value);
1468: } else
1469: tmpbuf[j++]=inbuf[i];
1470: }
1471: else if(inbuf[i]>=' ' && inbuf[i]<DEL)
1472: tmpbuf[j++]=inbuf[i];
1473: #if 0 /* ASCII 127 - Not displayed? */
1474: else if(inbuf[i]==DEL && exascii)
1475: j+=sprintf(tmpbuf+j,"⌂",exasctbl[ch].value);
1476: #endif
1477: else if(inbuf[i]<' ') /* unknown control chars */
1478: {
1479: if(ansi && inbuf[i]==ESC)
1480: {
1481: esccount++;
1482: tmpbuf[j++]=inbuf[i];
1483: }
1484: else if(ctrl_a && inbuf[i]==1)
1485: {
1486: esccount++;
1487: tmpbuf[j++]=inbuf[i];
1488: tmpbuf[j++]=inbuf[++i];
1489: }
1490: else if(exascii) {
1491: ch=inbuf[i];
1492: if(lowasctbl[ch].name!=NULL)
1493: j+=sprintf(tmpbuf+j,"&%s;",lowasctbl[ch].name);
1494: else
1495: j+=sprintf(tmpbuf+j,"&#%u;",lowasctbl[ch].value);
1496: } else
1497: j+=sprintf(tmpbuf+j,"&#%u;",inbuf[i]);
1498: }
1499: break;
1500: }
1501: }
1502: tmpbuf[j]=0;
1503:
1504: if(ansi)
1505: {
1506: obsize=(strlen(tmpbuf)+(esccount+1)*MAX_COLOR_STRING)+1;
1507: if(obsize<2048)
1508: obsize=2048;
1509: if((outbuf=(uchar*)malloc(obsize))==NULL)
1510: {
1511: free(tmpbuf);
1512: return(JS_FALSE);
1513: }
1514: j=sprintf(outbuf,"<span style=\"%s\">",htmlansi[7]);
1515: clear_screen=j;
1516: for(i=0;tmpbuf[i];i++) {
1517: if(j>(obsize/2)) /* Completely arbitrary here... must be carefull with this eventually ToDo */
1518: {
1519: obsize+=(obsize/2);
1520: if((param=realloc(outbuf,obsize))==NULL)
1521: {
1522: free(tmpbuf);
1523: free(outbuf);
1524: return(JS_FALSE);
1525: }
1526: outbuf=param;
1527: }
1528: if(tmpbuf[i]==ESC && tmpbuf[i+1]=='[')
1529: {
1530: if(nodisplay)
1531: continue;
1532: k=0;
1533: memset(&ansi_param,0xff,sizeof(int)*MAX_ANSI_PARAMS);
1534: strncpy(ansi_seq, tmpbuf+i+2, MAX_ANSI_SEQ);
1535: ansi_seq[MAX_ANSI_SEQ]=0;
1536: for(lastparam=ansi_seq;*lastparam;lastparam++)
1537: {
1538: if(isalpha(*lastparam))
1539: {
1540: *(++lastparam)=0;
1541: break;
1542: }
1543: }
1544: k=0;
1545: param=ansi_seq;
1546: if(*param=='?') /* This is to fix ESC[?7 whatever that is */
1547: param++;
1548: if(isdigit(*param))
1549: ansi_param[k++]=atoi(ansi_seq);
1550: while(isspace(*param) || isdigit(*param))
1551: param++;
1552: lastparam=param;
1553: while((param=strchr(param,';'))!=NULL)
1554: {
1555: param++;
1556: ansi_param[k++]=atoi(param);
1557: while(isspace(*param) || isdigit(*param))
1558: param++;
1559: lastparam=param;
1560: }
1561: switch(*lastparam)
1562: {
1563: case 'm': /* Colour */
1564: for(k=0;ansi_param[k]>=0;k++)
1565: {
1566: switch(ansi_param[k])
1567: {
1568: case 0:
1569: fg=7;
1570: bg=0;
1571: blink=FALSE;
1572: bold=FALSE;
1573: break;
1574: case 1:
1575: bold=TRUE;
1576: break;
1577: case 2:
1578: bold=FALSE;
1579: break;
1580: case 5:
1581: blink=TRUE;
1582: break;
1583: case 6:
1584: blink=TRUE;
1585: break;
1586: case 7:
1587: l=fg;
1588: fg=bg;
1589: bg=l;
1590: break;
1591: case 8:
1592: fg=bg;
1593: blink=FALSE;
1594: bold=FALSE;
1595: break;
1596: case 30:
1597: case 31:
1598: case 32:
1599: case 33:
1600: case 34:
1601: case 35:
1602: case 36:
1603: case 37:
1604: fg=ansi_param[k]-30;
1605: break;
1606: case 40:
1607: case 41:
1608: case 42:
1609: case 43:
1610: case 44:
1611: case 45:
1612: case 46:
1613: case 47:
1614: bg=ansi_param[k]-40;
1615: break;
1616: }
1617: }
1618: break;
1619: case 'C': /* Move right */
1620: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1621: lastcolor=0;
1622: l=ansi_param[0]>0?ansi_param[0]:1;
1623: if(wrappos==0 && wrapvpos==currrow) {
1624: /* j+=sprintf(outbuf+j,"<!-- \r\nC after A l=%d hpos=%d -->",l,hpos); */
1625: l=l-hpos;
1626: wrapvpos=-2; /* Prevent additional move right */
1627: }
1628: if(l>81-hpos)
1629: l=81-hpos;
1630: for(k=0; k<l; k++)
1631: {
1632: j+=sprintf(outbuf+j,"%s"," ");
1633: hpos++;
1634: }
1635: break;
1636: case 's': /* Save position */
1637: savepos=j;
1638: savehpos=hpos;
1639: savevpos=currrow;
1640: break;
1641: case 'u': /* Restore saved position */
1642: j=savepos;
1643: hpos=savehpos;
1644: currrow=savevpos;
1645: break;
1646: case 'H': /* Move */
1647: k=ansi_param[0];
1648: if(k<=0)
1649: k=1;
1650: k--;
1651: l=ansi_param[1];
1652: if(l<=0)
1653: l=1;
1654: l--;
1655: while(k>currrow)
1656: {
1657: hpos=0;
1658: currrow++;
1659: outbuf[j++]='\r';
1660: outbuf[j++]='\n';
1661: }
1662: if(l>hpos)
1663: {
1664: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1665: lastcolor=0;
1666: while(l>hpos)
1667: {
1668: j+=sprintf(outbuf+j,"%s"," ");
1669: hpos++;
1670: }
1671: }
1672: break;
1673: case 'B': /* Move down */
1674: l=ansi_param[0];
1675: if(l<=0)
1676: l=1;
1677: for(k=0; k < l; k++)
1678: {
1679: currrow++;
1680: outbuf[j++]='\r';
1681: outbuf[j++]='\n';
1682: }
1683: if(hpos!=0 && tmpbuf[i+1]!=CR)
1684: {
1685: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1686: lastcolor=0;
1687: for(k=0; k<hpos ; k++)
1688: {
1689: j+=sprintf(outbuf+j,"%s"," ");
1690: }
1691: break;
1692: }
1693: break;
1694: case 'A': /* Move up */
1695: l=wrappos;
1696: if(j > (ulong)wrappos && hpos==0 && currrow==wrapvpos+1 && ansi_param[0]<=1) {
1697: hpos=wraphpos;
1698: currrow=wrapvpos;
1699: j=wrappos;
1700: wrappos=0; /* Prevent additional move up */
1701: }
1702: break;
1703: case 'J': /* Clear */
1704: if(ansi_param[0]==2) {
1705: j=clear_screen;
1706: hpos=0;
1707: currrow=0;
1708: wraphpos=-2;
1709: wrapvpos=-2;
1710: wrappos=0;
1711: }
1712: break;
1713: }
1714: i+=(int)(lastparam-ansi_seq)+2;
1715: }
1716: else if(ctrl_a && tmpbuf[i]==1) /* CTRL-A codes */
1717: {
1718: /* j+=sprintf(outbuf+j,"<!-- CTRL-A-%c (%u) -->",tmpbuf[i+1],tmpbuf[i+1]); */
1719: if(nodisplay && tmpbuf[i+1] != ')')
1720: continue;
1721: if(tmpbuf[i+1]>0x7f)
1722: {
1723: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1724: lastcolor=0;
1725: l=tmpbuf[i+1]-0x7f;
1726: if(l>81-hpos)
1727: l=81-hpos;
1728: for(k=0; k<l; k++)
1729: {
1730: j+=sprintf(outbuf+j,"%s"," ");
1731: hpos++;
1732: }
1733: }
1734: else switch(toupper(tmpbuf[i+1]))
1735: {
1736: case 'K':
1737: fg=0;
1738: break;
1739: case 'R':
1740: fg=1;
1741: break;
1742: case 'G':
1743: fg=2;
1744: break;
1745: case 'Y':
1746: fg=3;
1747: break;
1748: case 'B':
1749: fg=4;
1750: break;
1751: case 'M':
1752: fg=5;
1753: break;
1754: case 'C':
1755: fg=6;
1756: break;
1757: case 'W':
1758: fg=7;
1759: break;
1760: case '0':
1761: bg=0;
1762: break;
1763: case '1':
1764: bg=1;
1765: break;
1766: case '2':
1767: bg=2;
1768: break;
1769: case '3':
1770: bg=3;
1771: break;
1772: case '4':
1773: bg=4;
1774: break;
1775: case '5':
1776: bg=5;
1777: break;
1778: case '6':
1779: bg=6;
1780: break;
1781: case '7':
1782: bg=7;
1783: break;
1784: case 'H':
1785: bold=TRUE;
1786: break;
1787: case 'I':
1788: blink=TRUE;
1789: break;
1790: case '+':
1791: if(attr_sp<(int)sizeof(attr_stack))
1792: attr_stack[attr_sp++]=(blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | (int)fg;
1793: break;
1794: case '-':
1795: if(attr_sp>0)
1796: {
1797: blink=(attr_stack[--attr_sp]&(1<<7))?TRUE:FALSE;
1798: bg=(attr_stack[attr_sp] >> 4) & 7;
1799: blink=(attr_stack[attr_sp]&(1<<3))?TRUE:FALSE;
1800: fg=attr_stack[attr_sp] & 7;
1801: }
1802: else if(bold || blink || bg)
1803: {
1804: bold=FALSE;
1805: blink=FALSE;
1806: fg=7;
1807: bg=0;
1808: }
1809: break;
1810: case '_':
1811: if(blink || bg)
1812: {
1813: bold=FALSE;
1814: blink=FALSE;
1815: fg=7;
1816: bg=0;
1817: }
1818: break;
1819: case 'N':
1820: bold=FALSE;
1821: blink=FALSE;
1822: fg=7;
1823: bg=0;
1824: break;
1825: case 'P':
1826: case 'Q':
1827: case ',':
1828: case ';':
1829: case '.':
1830: case 'S':
1831: case '>':
1832: case '<':
1833: break;
1834:
1835: case '!': /* This needs to be fixed! (Somehow) */
1836: case '@':
1837: case '#':
1838: case '$':
1839: case '%':
1840: case '^':
1841: case '&':
1842: case '*':
1843: case '(':
1844: nodisplay=TRUE;
1845: break;
1846: case ')':
1847: nodisplay=FALSE;
1848: break;
1849:
1850: case 'D':
1851: now=time(NULL);
1852: j+=sprintf(outbuf+j,"%s",unixtodstr(cfg,now,tmp1));
1853: break;
1854: case 'T':
1855: now=time(NULL);
1856: localtime_r(&now,&tm);
1857: j+=sprintf(outbuf+j,"%02d:%02d %s"
1858: ,tm.tm_hour==0 ? 12
1859: : tm.tm_hour>12 ? tm.tm_hour-12
1860: : tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
1861: break;
1862:
1863: case 'L':
1864: currrow=0;
1865: hpos=0;
1866: outbuf[j++]='\r';
1867: outbuf[j++]='\n';
1868: break;
1869: case ']':
1870: currrow++;
1871: if(hpos!=0 && tmpbuf[i+2]!=CR && !(tmpbuf[i+2]==1 && tmpbuf[i+3]=='['))
1872: {
1873: outbuf[j++]='\r';
1874: outbuf[j++]='\n';
1875: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1876: lastcolor=0;
1877: for(k=0; k<hpos ; k++)
1878: {
1879: j+=sprintf(outbuf+j,"%s"," ");
1880: }
1881: break;
1882: }
1883: outbuf[j++]='\n';
1884: break;
1885: case '[':
1886: outbuf[j++]='\r';
1887: hpos=0;
1888: break;
1889: case 'Z':
1890: outbuf[j++]=0;
1891: break;
1892: case 'A':
1893: default:
1894: if(exascii) {
1895: ch=tmpbuf[i];
1896: if(lowasctbl[ch].name!=NULL)
1897: j+=sprintf(outbuf+j,"&%s;",lowasctbl[ch].name);
1898: else
1899: j+=sprintf(outbuf+j,"&#%u;",lowasctbl[ch].value);
1900: } else
1901: j+=sprintf(outbuf+j,"&#%u;",inbuf[i]);
1902: i--;
1903: }
1904: i++;
1905: }
1906: else
1907: {
1908: if(nodisplay)
1909: continue;
1910: switch(tmpbuf[i])
1911: {
1912: case TAB: /* This assumes that tabs do NOT use the current background. */
1913: l=hpos%8;
1914: if(l==0)
1915: l=8;
1916: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1917: lastcolor=0;
1918: for(k=0; k<l ; k++)
1919: {
1920: j+=sprintf(outbuf+j,"%s"," ");
1921: hpos++;
1922: }
1923: break;
1924: case LF:
1925: wrapvpos=currrow;
1926: if((ulong)wrappos<j-3)
1927: wrappos=j;
1928: currrow++;
1929: if(hpos!=0 && tmpbuf[i+1]!=CR)
1930: {
1931: outbuf[j++]='\r';
1932: outbuf[j++]='\n';
1933: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[0],HTML_COLOR_SUFFIX);
1934: lastcolor=0;
1935: for(k=0; k<hpos ; k++)
1936: {
1937: j+=sprintf(outbuf+j,"%s"," ");
1938: }
1939: break;
1940: }
1941: case CR:
1942: if(wraphpos==-2 || hpos!=0)
1943: wraphpos=hpos;
1944: if((ulong)wrappos<j-3)
1945: wrappos=j;
1946: outbuf[j++]=tmpbuf[i];
1947: hpos=0;
1948: break;
1949: default:
1950: if(lastcolor != ((blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | fg))
1951: {
1952: lastcolor=(blink?(1<<7):0) | (bg << 4) | (bold?(1<<3):0) | fg;
1953: j+=sprintf(outbuf+j,"%s%s%s",HTML_COLOR_PREFIX,htmlansi[lastcolor],HTML_COLOR_SUFFIX);
1954: }
1955: outbuf[j++]=tmpbuf[i];
1956: if(tmpbuf[i]=='&')
1957: extchar=TRUE;
1958: if(tmpbuf[i]==';')
1959: extchar=FALSE;
1960: if(!extchar)
1961: hpos++;
1962: /* ToDo: Fix hard-coded terminal window width (80) */
1963: if(hpos>=80 && tmpbuf[i+1] != '\r' && tmpbuf[i+1] != '\n' && tmpbuf[i+1] != ESC)
1964: {
1965: wrapvpos=-2;
1966: wraphpos=-2;
1967: wrappos=0;
1968: hpos=0;
1969: currrow++;
1970: outbuf[j++]='\r';
1971: outbuf[j++]='\n';
1972: }
1973: }
1974: }
1975: }
1976: strcpy(outbuf+j,"</span>");
1977:
1978: js_str = JS_NewStringCopyZ(cx, outbuf);
1979: free(outbuf);
1980: }
1981: else
1982: js_str = JS_NewStringCopyZ(cx, tmpbuf);
1983:
1984: free(tmpbuf); /* assertion here, Feb-20-2006 */
1985: if(js_str==NULL)
1986: return(JS_FALSE);
1987:
1988: *rval = STRING_TO_JSVAL(js_str);
1989:
1990: if(stateobj!=NULL) {
1991: JS_DefineProperty(cx, stateobj, "fg", INT_TO_JSVAL(fg)
1992: ,NULL,NULL,JSPROP_ENUMERATE);
1993: JS_DefineProperty(cx, stateobj, "bg", INT_TO_JSVAL(bg)
1994: ,NULL,NULL,JSPROP_ENUMERATE);
1995: JS_DefineProperty(cx, stateobj, "lastcolor", INT_TO_JSVAL(lastcolor)
1996: ,NULL,NULL,JSPROP_ENUMERATE);
1997: JS_DefineProperty(cx, stateobj, "blink", BOOLEAN_TO_JSVAL(blink)
1998: ,NULL,NULL,JSPROP_ENUMERATE);
1999: JS_DefineProperty(cx, stateobj, "bold", BOOLEAN_TO_JSVAL(bold)
2000: ,NULL,NULL,JSPROP_ENUMERATE);
2001: JS_DefineProperty(cx, stateobj, "hpos", INT_TO_JSVAL(hpos)
2002: ,NULL,NULL,JSPROP_ENUMERATE);
2003: JS_DefineProperty(cx, stateobj, "currrow", INT_TO_JSVAL(currrow)
2004: ,NULL,NULL,JSPROP_ENUMERATE);
2005: JS_DefineProperty(cx, stateobj, "wraphpos", INT_TO_JSVAL(wraphpos)
2006: ,NULL,NULL,JSPROP_ENUMERATE);
2007: JS_DefineProperty(cx, stateobj, "wrapvpos", INT_TO_JSVAL(wrapvpos)
2008: ,NULL,NULL,JSPROP_ENUMERATE);
2009: JS_DefineProperty(cx, stateobj, "wrappos", INT_TO_JSVAL(wrappos)
2010: ,NULL,NULL,JSPROP_ENUMERATE);
2011: }
2012:
2013: return(JS_TRUE);
2014: }
2015:
2016: static JSBool
2017: js_html_decode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2018: {
2019: int ch;
2020: int val;
2021: ulong i,j;
2022: uchar* inbuf;
2023: uchar* outbuf;
2024: char token[16];
2025: size_t t;
2026: JSString* js_str;
2027:
2028: if(JSVAL_IS_VOID(argv[0]))
2029: return(JS_TRUE);
2030:
2031: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2032: return(JS_FALSE);
2033:
2034: if((outbuf=(char*)malloc(strlen(inbuf)+1))==NULL)
2035: return(JS_FALSE);
2036:
2037: for(i=j=0;inbuf[i];i++) {
2038: if(inbuf[i]!='&') {
2039: outbuf[j++]=inbuf[i];
2040: continue;
2041: }
2042: for(i++,t=0; inbuf[i]!=0 && inbuf[i]!=';' && t<sizeof(token)-1; i++, t++)
2043: token[t]=inbuf[i];
2044: if(inbuf[i]==0)
2045: break;
2046: token[t]=0;
2047:
2048: /* First search the ex-ascii table for a name match */
2049: for(ch=0;ch<128;ch++)
2050: if(exasctbl[ch].name!=NULL && strcmp(token,exasctbl[ch].name)==0)
2051: break;
2052: if(ch<128) {
2053: outbuf[j++]=ch|0x80;
2054: continue;
2055: }
2056: if(token[0]=='#') { /* numeric constant */
2057: val=atoi(token+1);
2058:
2059: /* search ex-ascii table for a value match */
2060: for(ch=0;ch<128;ch++)
2061: if(exasctbl[ch].value==val)
2062: break;
2063: if(ch<128) {
2064: outbuf[j++]=ch|0x80;
2065: continue;
2066: }
2067:
2068: if((val>=' ' && val<=0xff) || val=='\r' || val=='\n' || val=='\t') {
2069: outbuf[j++]=val;
2070: continue;
2071: }
2072: }
2073: if(strcmp(token,"quot")==0) {
2074: outbuf[j++]='"';
2075: continue;
2076: }
2077: if(strcmp(token,"amp")==0) {
2078: outbuf[j++]='&';
2079: continue;
2080: }
2081: if(strcmp(token,"lt")==0) {
2082: outbuf[j++]='<';
2083: continue;
2084: }
2085: if(strcmp(token,"gt")==0) {
2086: outbuf[j++]='>';
2087: continue;
2088: }
2089: if(strcmp(token,"curren")==0) {
2090: outbuf[j++]=CTRL_O;
2091: continue;
2092: }
2093: if(strcmp(token,"para")==0) {
2094: outbuf[j++]=CTRL_T;
2095: continue;
2096: }
2097: if(strcmp(token,"sect")==0) {
2098: outbuf[j++]=CTRL_U;
2099: continue;
2100: }
2101: /* Unknown character entity, leave intact */
2102: j+=sprintf(outbuf+j,"&%s;",token);
2103:
2104: }
2105: outbuf[j]=0;
2106:
2107: js_str = JS_NewStringCopyZ(cx, outbuf);
2108: free(outbuf);
2109: if(js_str==NULL)
2110: return(JS_FALSE);
2111:
2112: *rval = STRING_TO_JSVAL(js_str);
2113: return(JS_TRUE);
2114: }
2115:
2116: static JSBool
2117: js_b64_encode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2118: {
2119: int res;
2120: size_t len;
2121: size_t inbuf_len;
2122: uchar* inbuf;
2123: uchar* outbuf;
2124: JSString* js_str;
2125:
2126: *rval = JSVAL_NULL;
2127:
2128: if(JSVAL_IS_VOID(argv[0]))
2129: return(JS_TRUE);
2130:
2131: if((inbuf=js_ValueToStringBytes(cx, argv[0], &inbuf_len))==NULL)
2132: return(JS_FALSE);
2133:
2134: len=(inbuf_len*10)+1;
2135:
2136: if((outbuf=(char*)malloc(len))==NULL)
2137: return(JS_FALSE);
2138:
2139: res=b64_encode(outbuf,len,inbuf,inbuf_len);
2140:
2141: if(res<1) {
2142: free(outbuf);
2143: return(JS_TRUE);
2144: }
2145:
2146: js_str = JS_NewStringCopyZ(cx, outbuf);
2147: free(outbuf);
2148: if(js_str==NULL)
2149: return(JS_FALSE);
2150:
2151: *rval = STRING_TO_JSVAL(js_str);
2152: return(JS_TRUE);
2153: }
2154:
2155: static JSBool
2156: js_b64_decode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2157: {
2158: int res;
2159: size_t len;
2160: uchar* inbuf;
2161: uchar* outbuf;
2162: JSString* js_str;
2163:
2164: *rval = JSVAL_NULL;
2165:
2166: if(JSVAL_IS_VOID(argv[0]))
2167: return(JS_TRUE);
2168:
2169: if((inbuf=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2170: return(JS_FALSE);
2171:
2172: len=strlen(inbuf)+1;
2173:
2174: if((outbuf=(char*)malloc(len))==NULL)
2175: return(JS_FALSE);
2176:
2177: res=b64_decode(outbuf,len,inbuf,strlen(inbuf));
2178:
2179: if(res<1) {
2180: free(outbuf);
2181: return(JS_TRUE);
2182: }
2183:
2184: js_str = JS_NewStringCopyN(cx, outbuf, res);
2185: free(outbuf);
2186: if(js_str==NULL)
2187: return(JS_FALSE);
2188:
2189: *rval = STRING_TO_JSVAL(js_str);
2190: return(JS_TRUE);
2191: }
2192:
2193: static JSBool
2194: js_md5_calc(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
2195: {
2196: BYTE digest[MD5_DIGEST_SIZE];
2197: JSBool hex=JS_FALSE;
2198: size_t inbuf_len;
2199: char* inbuf;
2200: char outbuf[64];
2201: JSString* js_str;
2202:
2203: *rval = JSVAL_NULL;
2204:
2205: if(JSVAL_IS_VOID(argv[0]))
2206: return(JS_TRUE);
2207:
2208: if((inbuf=js_ValueToStringBytes(cx, argv[0], &inbuf_len))==NULL)
2209: return(JS_FALSE);
2210:
2211: if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
2212: hex=JSVAL_TO_BOOLEAN(argv[1]);
2213:
2214: MD5_calc(digest,inbuf,inbuf_len);
2215:
2216: if(hex)
2217: MD5_hex(outbuf,digest);
2218: else
2219: b64_encode(outbuf,sizeof(outbuf),digest,sizeof(digest));
2220:
2221: js_str = JS_NewStringCopyZ(cx, outbuf);
2222: if(js_str==NULL)
2223: return(JS_FALSE);
2224:
2225: *rval = STRING_TO_JSVAL(js_str);
2226: return(JS_TRUE);
2227: }
2228:
2229: static JSBool
2230: js_truncsp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2231: {
2232: char* p;
2233: char* str;
2234: JSString* js_str;
2235:
2236: if(JSVAL_IS_VOID(argv[0]))
2237: return(JS_TRUE);
2238:
2239: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2240: return(JS_FALSE);
2241:
2242: if((p=strdup(str))==NULL)
2243: return(JS_FALSE);
2244:
2245: truncsp(p);
2246:
2247: js_str = JS_NewStringCopyZ(cx, p);
2248: free(p);
2249: if(js_str==NULL)
2250: return(JS_FALSE);
2251:
2252: *rval = STRING_TO_JSVAL(js_str);
2253: return(JS_TRUE);
2254: }
2255:
2256: static JSBool
2257: js_truncstr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2258: {
2259: char* p;
2260: char* str;
2261: char* set;
2262: JSString* js_str;
2263:
2264: if(JSVAL_IS_VOID(argv[0]))
2265: return(JS_TRUE);
2266:
2267: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2268: return(JS_FALSE);
2269:
2270: if((set=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
2271: return(JS_FALSE);
2272:
2273: if((p=strdup(str))==NULL)
2274: return(JS_FALSE);
2275:
2276: truncstr(p,set);
2277:
2278: js_str = JS_NewStringCopyZ(cx, p);
2279: free(p);
2280: if(js_str==NULL)
2281: return(JS_FALSE);
2282:
2283: *rval = STRING_TO_JSVAL(js_str);
2284: return(JS_TRUE);
2285: }
2286:
2287: static JSBool
2288: js_backslash(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2289: {
2290: char path[MAX_PATH+1];
2291: char* str;
2292: JSString* js_str;
2293:
2294: if(JSVAL_IS_VOID(argv[0]))
2295: return(JS_TRUE);
2296:
2297: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2298: return(JS_FALSE);
2299:
2300: SAFECOPY(path,str);
2301: backslash(path);
2302:
2303: if((js_str = JS_NewStringCopyZ(cx, path))==NULL)
2304: return(JS_FALSE);
2305:
2306: *rval = STRING_TO_JSVAL(js_str);
2307: return(JS_TRUE);
2308: }
2309:
2310:
2311: static JSBool
2312: js_getfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2313: {
2314: char* str;
2315: JSString* js_str;
2316:
2317: if(JSVAL_IS_VOID(argv[0]))
2318: return(JS_TRUE);
2319:
2320: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2321: return(JS_FALSE);
2322:
2323: js_str = JS_NewStringCopyZ(cx, getfname(str));
2324: if(js_str==NULL)
2325: return(JS_FALSE);
2326:
2327: *rval = STRING_TO_JSVAL(js_str);
2328: return(JS_TRUE);
2329: }
2330:
2331: static JSBool
2332: js_getfext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2333: {
2334: char* str;
2335: char* p;
2336: JSString* js_str;
2337:
2338: if(JSVAL_IS_VOID(argv[0]))
2339: return(JS_TRUE);
2340:
2341: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2342: return(JS_FALSE);
2343:
2344: if((p=getfext(str))==NULL)
2345: return(JS_TRUE);
2346:
2347: js_str = JS_NewStringCopyZ(cx, p);
2348: if(js_str==NULL)
2349: return(JS_FALSE);
2350:
2351: *rval = STRING_TO_JSVAL(js_str);
2352: return(JS_TRUE);
2353: }
2354:
2355: static JSBool
2356: js_getfcase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2357: {
2358: char* str;
2359: char path[MAX_PATH+1];
2360: JSString* js_str;
2361:
2362: if(JSVAL_IS_VOID(argv[0]))
2363: return(JS_TRUE);
2364:
2365: if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2366: return(JS_FALSE);
2367:
2368: SAFECOPY(path,str);
2369: if(fexistcase(path)) {
2370: js_str = JS_NewStringCopyZ(cx, path);
2371: if(js_str==NULL)
2372: return(JS_FALSE);
2373:
2374: *rval = STRING_TO_JSVAL(js_str);
2375: }
2376: return(JS_TRUE);
2377: }
2378:
2379: static JSBool
2380: js_cfgfname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2381: {
2382: char* path;
2383: char* fname;
2384: char result[MAX_PATH+1];
2385:
2386: if(JSVAL_IS_VOID(argv[0]))
2387: return(JS_TRUE);
2388:
2389: if((path=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2390: return(JS_FALSE);
2391:
2392: if((fname=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
2393: return(JS_FALSE);
2394:
2395: *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,iniFileName(result,sizeof(result),path,fname)));
2396:
2397: return(JS_TRUE);
2398: }
2399:
2400: static JSBool
2401: js_fexist(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2402: {
2403: char* p;
2404:
2405: if(JSVAL_IS_VOID(argv[0]))
2406: return(JS_TRUE);
2407:
2408: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2409: return(JS_FALSE);
2410:
2411: *rval = BOOLEAN_TO_JSVAL(fexist(p));
2412: return(JS_TRUE);
2413: }
2414:
2415: static JSBool
2416: js_removecase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2417: {
2418: char* p;
2419:
2420: if(JSVAL_IS_VOID(argv[0]))
2421: return(JS_TRUE);
2422:
2423: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2424: return(JS_FALSE);
2425:
2426: *rval = BOOLEAN_TO_JSVAL(removecase(p)==0);
2427: return(JS_TRUE);
2428: }
2429:
2430: static JSBool
2431: js_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2432: {
2433: char* p;
2434:
2435: if(JSVAL_IS_VOID(argv[0]))
2436: return(JS_TRUE);
2437:
2438: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2439: return(JS_FALSE);
2440:
2441: *rval = BOOLEAN_TO_JSVAL(remove(p)==0);
2442: return(JS_TRUE);
2443: }
2444:
2445: static JSBool
2446: js_rename(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2447: {
2448: char* oldname;
2449: char* newname;
2450:
2451: if(JSVAL_IS_VOID(argv[0]))
2452: return(JS_TRUE);
2453:
2454: *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
2455: if((oldname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2456: return(JS_TRUE);
2457: if((newname=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
2458: return(JS_TRUE);
2459:
2460: *rval = BOOLEAN_TO_JSVAL(rename(oldname,newname)==0);
2461: return(JS_TRUE);
2462: }
2463:
2464: static JSBool
2465: js_fcopy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2466: {
2467: char* src;
2468: char* dest;
2469:
2470: if(JSVAL_IS_VOID(argv[0]))
2471: return(JS_TRUE);
2472:
2473: *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
2474: if((src=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2475: return(JS_TRUE);
2476: if((dest=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
2477: return(JS_TRUE);
2478:
2479: *rval = BOOLEAN_TO_JSVAL(fcopy(src,dest));
2480: return(JS_TRUE);
2481: }
2482:
2483: static JSBool
2484: js_fcompare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2485: {
2486: char* fn1;
2487: char* fn2;
2488:
2489: if(JSVAL_IS_VOID(argv[0]))
2490: return(JS_TRUE);
2491:
2492: *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
2493: if((fn1=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2494: return(JS_TRUE);
2495: if((fn2=js_ValueToStringBytes(cx, argv[1], NULL))==NULL)
2496: return(JS_TRUE);
2497:
2498: *rval = BOOLEAN_TO_JSVAL(fcompare(fn1,fn2));
2499: return(JS_TRUE);
2500: }
2501:
2502: static JSBool
2503: js_backup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2504: {
2505: char* fname;
2506: int32 level=5;
2507: BOOL ren=FALSE;
2508:
2509: if(JSVAL_IS_VOID(argv[0]))
2510: return(JS_TRUE);
2511:
2512: *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
2513: if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2514: return(JS_TRUE);
2515:
2516: if(argc>1)
2517: JS_ValueToInt32(cx,argv[1],&level);
2518: if(argc>2)
2519: JS_ValueToBoolean(cx,argv[2],&ren);
2520:
2521: *rval = BOOLEAN_TO_JSVAL(backup(fname,level,ren));
2522: return(JS_TRUE);
2523: }
2524:
2525: static JSBool
2526: js_isdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2527: {
2528: char* p;
2529:
2530: if(JSVAL_IS_VOID(argv[0]))
2531: return(JS_TRUE);
2532:
2533: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2534: return(JS_FALSE);
2535:
2536: *rval = BOOLEAN_TO_JSVAL(isdir(p));
2537: return(JS_TRUE);
2538: }
2539:
2540: static JSBool
2541: js_fattr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2542: {
2543: char* p;
2544:
2545: if(JSVAL_IS_VOID(argv[0]))
2546: return(JS_TRUE);
2547:
2548: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2549: return(JS_FALSE);
2550:
2551: JS_NewNumberValue(cx,getfattr(p),rval);
2552: return(JS_TRUE);
2553: }
2554:
2555: static JSBool
2556: js_fdate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2557: {
2558: char* p;
2559:
2560: if(JSVAL_IS_VOID(argv[0]))
2561: return(JS_TRUE);
2562:
2563: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2564: return(JS_FALSE);
2565:
2566: JS_NewNumberValue(cx,fdate(p),rval);
2567: return(JS_TRUE);
2568: }
2569:
2570: static JSBool
2571: js_utime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2572: {
2573: char* fname;
2574: int32 actime;
2575: int32 modtime;
2576: struct utimbuf tbuf;
2577: struct utimbuf* t=NULL;
2578:
2579: if(JSVAL_IS_VOID(argv[0]))
2580: return(JS_TRUE);
2581:
2582: *rval = JSVAL_FALSE;
2583:
2584: if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2585: return(JS_FALSE);
2586:
2587: if(argc>1) {
2588: memset(&tbuf,0,sizeof(tbuf));
2589: actime=modtime=time(NULL);
2590: JS_ValueToInt32(cx,argv[1],&actime);
2591: JS_ValueToInt32(cx,argv[2],&modtime);
2592: tbuf.actime=actime;
2593: tbuf.modtime=modtime;
2594: t=&tbuf;
2595: }
2596:
2597: *rval = BOOLEAN_TO_JSVAL(utime(fname,t)==0);
2598:
2599: return(JS_TRUE);
2600: }
2601:
2602:
2603: static JSBool
2604: js_flength(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2605: {
2606: char* p;
2607:
2608: if(JSVAL_IS_VOID(argv[0]))
2609: return(JS_TRUE);
2610:
2611: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2612: return(JS_FALSE);
2613:
2614: JS_NewNumberValue(cx,flength(p),rval);
2615: return(JS_TRUE);
2616: }
2617:
2618:
2619: static JSBool
2620: js_ftouch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2621: {
2622: char* fname;
2623:
2624: if(JSVAL_IS_VOID(argv[0]))
2625: return(JS_TRUE);
2626:
2627: if((fname=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2628: return(JS_FALSE);
2629:
2630: *rval = BOOLEAN_TO_JSVAL(ftouch(fname));
2631: return(JS_TRUE);
2632: }
2633:
2634: static JSBool
2635: js_fmutex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2636: {
2637: char* fname;
2638: char* text=NULL;
2639: int32 max_age=0;
2640: uintN argn=0;
2641:
2642: if(JSVAL_IS_VOID(argv[0]))
2643: return(JS_TRUE);
2644:
2645: if((fname=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
2646: return(JS_FALSE);
2647: if(argc > argn && JSVAL_IS_STRING(argv[argn]))
2648: text=js_ValueToStringBytes(cx, argv[argn++], NULL);
2649: if(argc > argn && JSVAL_IS_NUMBER(argv[argn]))
2650: JS_ValueToInt32(cx, argv[argn++], &max_age);
2651:
2652: *rval = BOOLEAN_TO_JSVAL(fmutex(fname,text,max_age));
2653: return(JS_TRUE);
2654: }
2655:
2656: static JSBool
2657: js_sound(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2658: {
2659: char* p;
2660:
2661: if(!argc) { /* Stop playing sound */
2662: #ifdef _WIN32
2663: PlaySound(NULL,NULL,0);
2664: #endif
2665: *rval = BOOLEAN_TO_JSVAL(JS_TRUE);
2666: return(JS_TRUE);
2667: }
2668:
2669: if(JSVAL_IS_VOID(argv[0]))
2670: return(JS_TRUE);
2671:
2672: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2673: return(JS_FALSE);
2674:
2675: #ifdef _WIN32
2676: *rval = BOOLEAN_TO_JSVAL(PlaySound(p, NULL, SND_ASYNC|SND_FILENAME));
2677: #else
2678: *rval = BOOLEAN_TO_JSVAL(JS_FALSE);
2679: #endif
2680:
2681: return(JS_TRUE);
2682: }
2683:
2684: static JSBool
2685: js_directory(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2686: {
2687: int i;
2688: int32 flags=GLOB_MARK;
2689: char* p;
2690: glob_t g;
2691: JSObject* array;
2692: JSString* js_str;
2693: jsint len=0;
2694: jsval val;
2695:
2696: if(JSVAL_IS_VOID(argv[0]))
2697: return(JS_TRUE);
2698:
2699: *rval = JSVAL_NULL;
2700:
2701: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2702: return(JS_FALSE);
2703:
2704: if(argc>1)
2705: JS_ValueToInt32(cx,argv[1],&flags);
2706:
2707: if((array = JS_NewArrayObject(cx, 0, NULL))==NULL)
2708: return(JS_FALSE);
2709:
2710: glob(p,flags,NULL,&g);
2711: for(i=0;i<(int)g.gl_pathc;i++) {
2712: if((js_str=JS_NewStringCopyZ(cx,g.gl_pathv[i]))==NULL)
2713: break;
2714: val=STRING_TO_JSVAL(js_str);
2715: if(!JS_SetElement(cx, array, len++, &val))
2716: break;
2717: }
2718: globfree(&g);
2719:
2720: *rval = OBJECT_TO_JSVAL(array);
2721:
2722: return(JS_TRUE);
2723: }
2724:
2725: static JSBool
2726: js_wildmatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2727: {
2728: BOOL case_sensitive=FALSE;
2729: BOOL path=FALSE;
2730: char* fname;
2731: char* spec="*";
2732: uintN argn=0;
2733:
2734: if(JSVAL_IS_BOOLEAN(argv[argn]))
2735: JS_ValueToBoolean(cx, argv[argn++], &case_sensitive);
2736:
2737: if((fname=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
2738: return(JS_FALSE);
2739:
2740: if(argn<argc && argv[argn]!=JSVAL_VOID)
2741: if((spec=js_ValueToStringBytes(cx, argv[argn++], NULL))==NULL)
2742: return(JS_FALSE);
2743:
2744: if(argn<argc && argv[argn]!=JSVAL_VOID)
2745: JS_ValueToBoolean(cx, argv[argn++], &path);
2746:
2747: if(case_sensitive)
2748: *rval = BOOLEAN_TO_JSVAL(wildmatch(fname, spec, path));
2749: else
2750: *rval = BOOLEAN_TO_JSVAL(wildmatchi(fname, spec, path));
2751:
2752: return(JS_TRUE);
2753: }
2754:
2755:
2756: static JSBool
2757: js_freediskspace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2758: {
2759: int32 unit=0;
2760: char* p;
2761:
2762: if(JSVAL_IS_VOID(argv[0]))
2763: return(JS_TRUE);
2764:
2765: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2766: return(JS_FALSE);
2767:
2768: if(argc>1)
2769: JS_ValueToInt32(cx,argv[1],&unit);
2770:
2771: JS_NewNumberValue(cx,getfreediskspace(p,unit),rval);
2772:
2773: return(JS_TRUE);
2774: }
2775:
2776: static JSBool
2777: js_disksize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2778: {
2779: int32 unit=0;
2780: char* p;
2781:
2782: if(JSVAL_IS_VOID(argv[0]))
2783: return(JS_TRUE);
2784:
2785: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2786: return(JS_FALSE);
2787:
2788: if(argc>1)
2789: JS_ValueToInt32(cx,argv[1],&unit);
2790:
2791: JS_NewNumberValue(cx,getdisksize(p,unit),rval);
2792:
2793: return(JS_TRUE);
2794: }
2795:
2796:
2797: static JSBool
2798: js_socket_select(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2799: {
2800: JSObject* inarray=NULL;
2801: JSObject* rarray;
2802: BOOL poll_for_write=FALSE;
2803: fd_set socket_set;
2804: fd_set* rd_set=NULL;
2805: fd_set* wr_set=NULL;
2806: uintN argn;
2807: SOCKET sock;
2808: SOCKET maxsock=0;
2809: struct timeval tv = {0, 0};
2810: jsuint i;
2811: jsuint limit;
2812: SOCKET* index;
2813: jsval val;
2814: int len=0;
2815:
2816: *rval = JSVAL_NULL;
2817:
2818: for(argn=0;argn<argc;argn++) {
2819: if(JSVAL_IS_BOOLEAN(argv[argn]))
2820: poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
2821: else if(JSVAL_IS_OBJECT(argv[argn]))
2822: inarray = JSVAL_TO_OBJECT(argv[argn]);
2823: else if(JSVAL_IS_NUMBER(argv[argn]))
2824: js_timeval(cx,argv[argn],&tv);
2825: }
2826:
2827: if(inarray==NULL || !JS_IsArrayObject(cx, inarray))
2828: return(JS_TRUE); /* This not a fatal error */
2829:
2830: if(!JS_GetArrayLength(cx, inarray, &limit))
2831: return(JS_TRUE);
2832:
2833: /* Return array */
2834: if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
2835: return(JS_FALSE);
2836:
2837: if((index=(SOCKET *)alloca(sizeof(SOCKET)*limit))==NULL)
2838: return(JS_FALSE);
2839:
2840: FD_ZERO(&socket_set);
2841: if(poll_for_write)
2842: wr_set=&socket_set;
2843: else
2844: rd_set=&socket_set;
2845:
2846: for(i=0;i<limit;i++) {
2847: if(!JS_GetElement(cx, inarray, i, &val))
2848: break;
2849: sock=js_socket(cx,val);
2850: index[i]=sock;
2851: if(sock!=INVALID_SOCKET) {
2852: FD_SET(sock,&socket_set);
2853: if(sock>maxsock)
2854: maxsock=sock;
2855: }
2856: }
2857:
2858: if(select(maxsock+1,rd_set,wr_set,NULL,&tv)<0)
2859: lprintf(LOG_DEBUG,"Error in socket_select() %s (%d)",strerror(errno),errno);
2860:
2861: for(i=0;i<limit;i++) {
2862: if(index[i]!=INVALID_SOCKET && FD_ISSET(index[i],&socket_set)) {
2863: val=INT_TO_JSVAL(i);
2864: if(!JS_SetElement(cx, rarray, len++, &val))
2865: break;
2866: }
2867: }
2868:
2869: *rval = OBJECT_TO_JSVAL(rarray);
2870:
2871: return(JS_TRUE);
2872: }
2873:
2874: static JSBool
2875: js_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2876: {
2877: char* p;
2878:
2879: if(JSVAL_IS_VOID(argv[0]))
2880: return(JS_TRUE);
2881:
2882: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2883: return(JS_FALSE);
2884:
2885: *rval = BOOLEAN_TO_JSVAL(MKDIR(p)==0);
2886: return(JS_TRUE);
2887: }
2888:
2889: static JSBool
2890: js_rmdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2891: {
2892: char* p;
2893:
2894: if(JSVAL_IS_VOID(argv[0]))
2895: return(JS_TRUE);
2896:
2897: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2898: return(JS_FALSE);
2899:
2900: *rval = BOOLEAN_TO_JSVAL(rmdir(p)==0);
2901: return(JS_TRUE);
2902: }
2903:
2904:
2905: static JSBool
2906: js_strftime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2907: {
2908: char str[128];
2909: char* fmt;
2910: int32 i=time(NULL);
2911: time_t t;
2912: struct tm tm;
2913: JSString* js_str;
2914:
2915: if(JSVAL_IS_VOID(argv[0]))
2916: return(JS_TRUE);
2917:
2918: if((fmt=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2919: return(JS_FALSE);
2920:
2921: if(argc>1)
2922: JS_ValueToInt32(cx,argv[1],&i);
2923:
2924: strcpy(str,"-Invalid time-");
2925: t=i;
2926: if(localtime_r(&t,&tm)==NULL)
2927: memset(&tm,0,sizeof(tm));
2928: strftime(str,sizeof(str),fmt,&tm);
2929:
2930: if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
2931: return(JS_FALSE);
2932:
2933: *rval = STRING_TO_JSVAL(js_str);
2934: return(JS_TRUE);
2935: }
2936:
2937: static JSBool
2938: js_resolve_ip(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2939: {
2940: struct in_addr addr;
2941: JSString* str;
2942: char* p;
2943:
2944: *rval = JSVAL_NULL;
2945:
2946: if(JSVAL_IS_VOID(argv[0]))
2947: return(JS_TRUE);
2948:
2949: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2950: return(JS_FALSE);
2951:
2952: if((addr.s_addr=resolve_ip(p))==INADDR_NONE)
2953: return(JS_TRUE);
2954:
2955: if((str=JS_NewStringCopyZ(cx, inet_ntoa(addr)))==NULL)
2956: return(JS_FALSE);
2957:
2958: *rval = STRING_TO_JSVAL(str);
2959: return(JS_TRUE);
2960: }
2961:
2962:
2963: static JSBool
2964: js_resolve_host(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2965: {
2966: struct in_addr addr;
2967: HOSTENT* h;
2968: char* p;
2969:
2970: *rval = JSVAL_NULL;
2971:
2972: if(JSVAL_IS_VOID(argv[0]))
2973: return(JS_TRUE);
2974:
2975: if((p=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
2976: return(JS_FALSE);
2977:
2978: addr.s_addr=inet_addr(p);
2979: h=gethostbyaddr((char *)&addr,sizeof(addr),AF_INET);
2980:
2981: if(h!=NULL && h->h_name!=NULL)
2982: *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,h->h_name));
2983:
2984: return(JS_TRUE);
2985:
2986: }
2987:
2988: extern link_list_t named_queues; /* js_queue.c */
2989:
2990: static JSBool
2991: js_list_named_queues(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2992: {
2993: JSObject* array;
2994: jsint len=0;
2995: jsval val;
2996: list_node_t* node;
2997: msg_queue_t* q;
2998:
2999: if((array = JS_NewArrayObject(cx, 0, NULL))==NULL)
3000: return(JS_FALSE);
3001:
3002: for(node=listFirstNode(&named_queues);node!=NULL;node=listNextNode(node)) {
3003: if((q=listNodeData(node))==NULL)
3004: continue;
3005: val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,q->name));
3006: if(!JS_SetElement(cx, array, len++, &val))
3007: break;
3008: }
3009:
3010: *rval = OBJECT_TO_JSVAL(array);
3011:
3012: return(JS_TRUE);
3013: }
3014:
3015: static JSBool
3016: js_flags_str(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
3017: {
3018: char* p;
3019: char str[64];
3020: jsdouble d;
3021: JSString* js_str;
3022:
3023: if(JSVAL_IS_VOID(argv[0]))
3024: return(JS_TRUE);
3025:
3026: if(JSVAL_IS_STRING(argv[0])) { /* string to long */
3027:
3028: if((p=JS_GetStringBytes(JSVAL_TO_STRING(argv[0])))==NULL)
3029: return(JS_FALSE);
3030:
3031: JS_NewNumberValue(cx,aftol(p),rval);
3032: return(JS_TRUE);
3033: }
3034:
3035: /* number to string */
3036: JS_ValueToNumber(cx,argv[0],&d);
3037:
3038: if((js_str = JS_NewStringCopyZ(cx, ltoaf((long)d,str)))==NULL)
3039: return(JS_FALSE);
3040:
3041: *rval = STRING_TO_JSVAL(js_str);
3042: return(JS_TRUE);
3043: }
3044:
3045: static JSClass js_global_class = {
3046: "Global" /* name */
3047: ,JSCLASS_HAS_PRIVATE /* flags */
3048: ,JS_PropertyStub /* addProperty */
3049: ,JS_PropertyStub /* delProperty */
3050: ,js_system_get /* getProperty */
3051: ,JS_PropertyStub /* setProperty */
3052: ,JS_EnumerateStub /* enumerate */
3053: ,JS_ResolveStub /* resolve */
3054: ,JS_ConvertStub /* convert */
3055: ,JS_FinalizeStub /* finalize */
3056: };
3057:
3058: static jsSyncMethodSpec js_global_functions[] = {
3059: {"exit", js_exit, 0, JSTYPE_VOID, "[exit_code]"
3060: ,JSDOCSTR("stop script execution, "
3061: "optionally setting the global property <tt>exit_code</tt> to the specified numeric value")
3062: ,311
3063: },
3064: {"load", js_load, 1, JSTYPE_UNDEF
3065: ,JSDOCSTR("[<i>bool</i> background or <i>object</i> scope,] <i>string</i> filename [,args]")
3066: ,JSDOCSTR("load and execute a JavaScript module (<i>filename</i>), "
3067: "optionally specifying a target <i>scope</i> object (default: <i>this</i>) "
3068: "and a list of arguments to pass to the module (as <i>argv</i>). "
3069: "Returns the result (last executed statement) of the executed script "
3070: "or a newly created <i>Queue</i> object if <i>background</i> is <i>true</i>).<br><br>"
3071: "<b>Background</b> (added in v3.12):<br>"
3072: "If <i>background</i> is <i>true</i>, the loaded script runs in the background "
3073: "(in a child thread) but may communicate with the parent "
3074: "script/thread by reading from and/or writing to the <i>parent_queue</i> "
3075: "(an automatically created <i>Queue</i> object). "
3076: "The result (last executed statement) of the executed script "
3077: "(or the optional <i>exit_code</i> passed to the <i>exit()/<i> function) "
3078: "will be automatically written to the <i>parent_queue</i> "
3079: "which may be read later by the parent script (using <i>load_result.read()</i>, for example).")
3080: ,312
3081: },
3082: {"sleep", js_mswait, 0, JSTYPE_ALIAS },
3083: {"mswait", js_mswait, 0, JSTYPE_NUMBER, JSDOCSTR("[milliseconds=<tt>1</tt>]")
3084: ,JSDOCSTR("millisecond wait/sleep routine (AKA sleep), returns number of elapsed clock ticks (in v3.13)")
3085: ,313
3086: },
3087: {"yield", js_yield, 0, JSTYPE_VOID, JSDOCSTR("[forced=<tt>true</tt>]")
3088: ,JSDOCSTR("release current thread time-slice, "
3089: "a <i>forced</i> yield will yield to all other pending tasks (lowering CPU utilization), "
3090: "a non-<i>forced</i> yield will yield only to pending tasks of equal or higher priority. "
3091: "<i>forced</i> defaults to <i>true</i>")
3092: ,311
3093: },
3094: {"random", js_random, 1, JSTYPE_NUMBER, JSDOCSTR("max_number=<tt>100</tt>")
3095: ,JSDOCSTR("return random integer between <tt>0</tt> and <i>max_number</i>-1")
3096: ,310
3097: },
3098: {"time", js_time, 0, JSTYPE_NUMBER, ""
3099: ,JSDOCSTR("return current time and date in Unix (time_t) format "
3100: "(number of seconds since Jan-01-1970)")
3101: ,310
3102: },
3103: {"beep", js_beep, 0, JSTYPE_VOID, JSDOCSTR("[frequency=<tt>500</tt>] [,duration=<tt>500</tt>]")
3104: ,JSDOCSTR("produce a tone on the local speaker at specified frequency for specified duration (in milliseconds)")
3105: ,310
3106: },
3107: {"sound", js_sound, 0, JSTYPE_BOOLEAN, JSDOCSTR("[filename]")
3108: ,JSDOCSTR("play a waveform (.wav) sound file (currently, on Windows platforms only)")
3109: ,310
3110: },
3111: {"ctrl", js_ctrl, 1, JSTYPE_STRING, JSDOCSTR("number or string")
3112: ,JSDOCSTR("return ASCII control character representing character passed - Example: <tt>ctrl('C') returns '\3'</tt>")
3113: ,311
3114: },
3115: {"ascii", js_ascii, 1, JSTYPE_UNDEF, JSDOCSTR("[string text] or [number value]")
3116: ,JSDOCSTR("convert single character to numeric ASCII value or vice-versa (returns number OR string)")
3117: ,310
3118: },
3119: {"ascii_str", js_ascii_str, 1, JSTYPE_STRING, JSDOCSTR("text")
3120: ,JSDOCSTR("convert extended-ASCII in text string to plain ASCII, returns modified string")
3121: ,310
3122: },
3123: {"strip_ctrl", js_strip_ctrl, 1, JSTYPE_STRING, JSDOCSTR("text")
3124: ,JSDOCSTR("strip control characters from string, returns modified string")
3125: ,310
3126: },
3127: {"strip_exascii", js_strip_exascii, 1, JSTYPE_STRING, JSDOCSTR("text")
3128: ,JSDOCSTR("strip extended-ASCII characters from string, returns modified string")
3129: ,310
3130: },
3131: {"truncsp", js_truncsp, 1, JSTYPE_STRING, JSDOCSTR("text")
3132: ,JSDOCSTR("truncate (trim) white-space characters off end of string, returns modified string")
3133: ,310
3134: },
3135: {"truncstr", js_truncstr, 2, JSTYPE_STRING, JSDOCSTR("text, charset")
3136: ,JSDOCSTR("truncate (trim) string at first char in <i>charset</i>, returns modified string")
3137: ,310
3138: },
3139: {"lfexpand", js_lfexpand, 1, JSTYPE_STRING, JSDOCSTR("text")
3140: ,JSDOCSTR("expand line-feeds (LF) to carriage-return/line-feeds (CRLF), returns modified string")
3141: ,310
3142: },
3143: {"wildmatch", js_wildmatch, 2, JSTYPE_BOOLEAN, JSDOCSTR("[case_sensitive=<tt>false</tt>,] string [,pattern=<tt>'*'</tt>] [,path=<tt>false</tt>]")
3144: ,JSDOCSTR("returns <tt>true</tt> if the <i>string</i> matches the wildcard <i>pattern</i> (wildcards supported are '*' and '?'), "
3145: "if <i>path</i> is <tt>true</tt>, '*' will not match path delimeter characters (e.g. '/')")
3146: ,314
3147: },
3148: {"backslash", js_backslash, 1, JSTYPE_STRING, JSDOCSTR("path")
3149: ,JSDOCSTR("returns directory path with trailing (platform-specific) path delimeter "
3150: "(i.e. \"slash\" or \"backslash\")")
3151: ,312
3152: },
3153: {"file_getname", js_getfname, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
3154: ,JSDOCSTR("returns filename portion of passed path string")
3155: ,311
3156: },
3157: {"file_getext", js_getfext, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
3158: ,JSDOCSTR("returns file extension portion of passed path/filename string (including '.') "
3159: "or <i>undefined</i> if no extension is found")
3160: ,311
3161: },
3162: {"file_getcase", js_getfcase, 1, JSTYPE_STRING, JSDOCSTR("path/filename")
3163: ,JSDOCSTR("returns correct case of filename (long version of filename on Win32) "
3164: "or <i>undefined</i> if the file doesn't exist")
3165: ,311
3166: },
3167: {"file_cfgname", js_cfgfname, 2, JSTYPE_STRING, JSDOCSTR("path, filename")
3168: ,JSDOCSTR("returns completed configuration filename from supplied <i>path</i> and <i>filename</i>, "
3169: "optionally including the local hostname (e.g. <tt>path/file.<i>host</i>.<i>domain</i>.ext</tt> "
3170: "or <tt>path/file.<i>host</i>.ext</tt>) if such a variation of the filename exists")
3171: ,312
3172: },
3173: {"file_exists", js_fexist, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
3174: ,JSDOCSTR("verify a file's existence")
3175: ,310
3176: },
3177: {"file_remove", js_remove, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
3178: ,JSDOCSTR("delete a file")
3179: ,310
3180: },
3181: {"file_removecase", js_removecase, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
3182: ,JSDOCSTR("delete files case insensitively")
3183: ,314
3184: },
3185: {"file_rename", js_rename, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/oldname, path/newname")
3186: ,JSDOCSTR("rename a file, possibly moving it to another directory in the process")
3187: ,311
3188: },
3189: {"file_copy", js_fcopy, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/source, path/destination")
3190: ,JSDOCSTR("copy a file from one directory or filename to another")
3191: ,311
3192: },
3193: {"file_backup", js_backup, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,level=<tt>5</tt>] [,rename=<tt>false</tt>]")
3194: ,JSDOCSTR("backup the specified <i>filename</i> as <tt>filename.<i>number</i>.extension</tt> "
3195: "where <i>number</i> is the backup number 0 through <i>level</i>-1 "
3196: "(default backup <i>level</i> is 5), "
3197: "if <i>rename</i> is <i>true</i>, the original file is renamed instead of copied "
3198: "(default is <i>false</i>)")
3199: ,311
3200: },
3201: {"file_isdir", js_isdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
3202: ,JSDOCSTR("check if specified <i>filename</i> is a directory")
3203: ,310
3204: },
3205: {"file_attrib", js_fattr, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
3206: ,JSDOCSTR("get a file's permissions/attributes")
3207: ,310
3208: },
3209: {"file_date", js_fdate, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
3210: ,JSDOCSTR("get a file's last modified date/time (in time_t format)")
3211: ,310
3212: },
3213: {"file_size", js_flength, 1, JSTYPE_NUMBER, JSDOCSTR("path/filename")
3214: ,JSDOCSTR("get a file's length (in bytes)")
3215: ,310
3216: },
3217: {"file_utime", js_utime, 3, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,access_time=<i>current</i>] [,mod_time=<i>current</i>]")
3218: ,JSDOCSTR("change a file's last accessed and modification date/time (in time_t format), "
3219: "or change to current time")
3220: ,311
3221: },
3222: {"file_touch", js_ftouch, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
3223: ,JSDOCSTR("updates a file's last modification date/time to current time, "
3224: "creating an empty file if it doesn't already exist")
3225: ,311
3226: },
3227: {"file_mutex", js_fmutex, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename [,text=<i>local_hostname</i>] [,max_age=<tt>0</tt>]")
3228: ,JSDOCSTR("attempts to create an mutual-exclusion (e.g. lock) file, "
3229: "optionally with the contents of <i>text</i>. "
3230: "If a non-zero <i>max_age</i> (supported in v3.13b+) is specified "
3231: "and the lock file exists, but is older than this value (in seconds), "
3232: "it is presumed stale and removed/over-written")
3233: ,312
3234: },
3235: {"file_compare", js_fcompare, 2, JSTYPE_BOOLEAN, JSDOCSTR("path/file1, path/file2")
3236: ,JSDOCSTR("compare 2 files, returning <i>true</i> if they are identical, <i>false</i> otherwise")
3237: ,314
3238: },
3239: {"directory", js_directory, 1, JSTYPE_ARRAY, JSDOCSTR("path/pattern [,flags=<tt>GLOB_MARK</tt>]")
3240: ,JSDOCSTR("returns an array of directory entries, "
3241: "<i>pattern</i> is the path and filename or wildcards to search for (e.g. '/subdir/*.txt'), "
3242: "<i>flags</i> is a bitfield of optional <tt>glob</tt> flags (default is <tt>GLOB_MARK</tt>)")
3243: ,310
3244: },
3245: {"dir_freespace", js_freediskspace, 2, JSTYPE_NUMBER, JSDOCSTR("directory [,unit_size=<tt>1</tt>]")
3246: ,JSDOCSTR("returns the amount of available disk space in the specified <i>directory</i> "
3247: "using the specified <i>unit_size</i> in bytes (default: 1), "
3248: "specify a <i>unit_size</i> of <tt>1024</tt> to return the available space in <i>kilobytes</i>.")
3249: ,311
3250: },
3251: {"disk_size", js_disksize, 2, JSTYPE_NUMBER, JSDOCSTR("directory [,unit_size=<tt>1</tt>]")
3252: ,JSDOCSTR("returns the total disk size of the specified <i>directory</i> "
3253: "using the specified <i>unit_size</i> in bytes (default: 1), "
3254: "specify a <i>unit_size</i> of <tt>1024</tt> to return the total disk size in <i>kilobytes</i>.")
3255: ,314
3256: },
3257: {"socket_select", js_socket_select, 0, JSTYPE_ARRAY, JSDOCSTR("[array of socket objects or descriptors] [,timeout=<tt>0</tt>] [,write=<tt>false</tt>]")
3258: ,JSDOCSTR("checks an array of socket objects or descriptors for read or write ability (default is <i>read</i>), "
3259: "default timeout value is 0.0 seconds (immediate timeout), "
3260: "returns an array of 0-based index values into the socket array, representing the sockets that were ready for reading or writing")
3261: ,311
3262: },
3263: {"mkdir", js_mkdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/directory")
3264: ,JSDOCSTR("make a directory")
3265: ,310
3266: },
3267: {"rmdir", js_rmdir, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/directory")
3268: ,JSDOCSTR("remove a directory")
3269: ,310
3270: },
3271: {"strftime", js_strftime, 1, JSTYPE_STRING, JSDOCSTR("format [,time=<i>current</i>]")
3272: ,JSDOCSTR("return a formatted time string (ala C strftime)")
3273: ,310
3274: },
3275: {"format", js_format, 1, JSTYPE_STRING, JSDOCSTR("format [,args]")
3276: ,JSDOCSTR("return a formatted string (ala the standard C <tt>sprintf</tt> function)")
3277: ,310
3278: },
3279: {"html_encode", js_html_encode, 1, JSTYPE_STRING, JSDOCSTR("text [,ex_ascii=<tt>true</tt>] [,white_space=<tt>true</tt>] [,ansi=<tt>true</tt>] [,ctrl_a=<tt>true</tt>] [, state (object)]")
3280: ,JSDOCSTR("return an HTML-encoded text string (using standard HTML character entities), "
3281: "escaping IBM extended-ASCII, white-space characters, ANSI codes, and CTRL-A codes by default."
3282: "Optionally storing the current ANSI state in <i>state</i> object")
3283: ,311
3284: },
3285: {"html_decode", js_html_decode, 1, JSTYPE_STRING, JSDOCSTR("html")
3286: ,JSDOCSTR("return a decoded HTML-encoded text string")
3287: ,311
3288: },
3289: {"word_wrap", js_word_wrap, 1, JSTYPE_STRING, JSDOCSTR("text [,line_length=<tt>79</tt> [, orig_line_length=<tt>79</tt> [, handle_quotes=<tt>true</tt>]]]]")
3290: ,JSDOCSTR("returns a word-wrapped version of the text string argument optionally handing quotes magically, "
3291: "<i>line_length</i> defaults to <i>79</i> <i>orig_line_length</i> defaults to <i>79</i> "
3292: "and <i>handle_quotes</i> defaults to <i>true</i>")
3293: ,311
3294: },
3295: {"quote_msg", js_quote_msg, 1, JSTYPE_STRING, JSDOCSTR("text [,line_length=<tt>79</tt>] [,prefix=<tt>\" > \"</tt>]")
3296: ,JSDOCSTR("returns a quoted version of the message text string argument, <i>line_length</i> defaults to <i>79</i>, "
3297: "<i>prefix</i> defaults to <tt>\" > \"</tt>")
3298: ,311
3299: },
3300: {"rot13_translate", js_rot13, 1, JSTYPE_STRING, JSDOCSTR("text")
3301: ,JSDOCSTR("returns ROT13-translated version of text string (will encode or decode text)")
3302: ,311
3303: },
3304: {"base64_encode", js_b64_encode, 1, JSTYPE_STRING, JSDOCSTR("text")
3305: ,JSDOCSTR("returns base64-encoded version of text string or <i>null</i> on error")
3306: ,311
3307: },
3308: {"base64_decode", js_b64_decode, 1, JSTYPE_STRING, JSDOCSTR("text")
3309: ,JSDOCSTR("returns base64-decoded text string or <i>null</i> on error")
3310: ,311
3311: },
3312: {"crc16_calc", js_crc16, 1, JSTYPE_NUMBER, JSDOCSTR("text")
3313: ,JSDOCSTR("calculate and return 16-bit CRC of text string")
3314: ,311
3315: },
3316: {"crc32_calc", js_crc32, 1, JSTYPE_NUMBER, JSDOCSTR("text")
3317: ,JSDOCSTR("calculate and return 32-bit CRC of text string")
3318: ,311
3319: },
3320: {"chksum_calc", js_chksum, 1, JSTYPE_NUMBER, JSDOCSTR("text")
3321: ,JSDOCSTR("calculate and return 32-bit checksum of text string")
3322: ,311
3323: },
3324: {"md5_calc", js_md5_calc, 1, JSTYPE_STRING, JSDOCSTR("text [,hex=<tt>false</tt>]")
3325: ,JSDOCSTR("calculate and return 128-bit MD5 digest of text string, result encoded in base64 (default) or hexadecimal")
3326: ,311
3327: },
3328: {"gethostbyname", js_resolve_ip, 1, JSTYPE_ALIAS },
3329: {"resolve_ip", js_resolve_ip, 1, JSTYPE_STRING, JSDOCSTR("hostname")
3330: ,JSDOCSTR("resolve IP address of specified hostname (AKA gethostbyname)")
3331: ,311
3332: },
3333: {"gethostbyaddr", js_resolve_host, 1, JSTYPE_ALIAS },
3334: {"resolve_host", js_resolve_host, 1, JSTYPE_STRING, JSDOCSTR("ip_address")
3335: ,JSDOCSTR("resolve hostname of specified IP address (AKA gethostbyaddr)")
3336: ,311
3337: },
3338: {"netaddr_type", js_netaddr_type, 1, JSTYPE_NUMBER, JSDOCSTR("email_address")
3339: ,JSDOCSTR("returns the proper message <i>net_type</i> for the specified <i>email_address</i>, "
3340: "(e.g. <tt>NET_INTERNET</tt> for Internet e-mail or <tt>NET_NONE</tt> for local e-mail)")
3341: ,312
3342: },
3343: {"list_named_queues",js_list_named_queues,0,JSTYPE_ARRAY, JSDOCSTR("")
3344: ,JSDOCSTR("returns an array of <i>named queues</i> (created with the <i>Queue</i> constructor)")
3345: ,312
3346: },
3347: {"flags_str", js_flags_str, 1, JSTYPE_UNDEF, JSDOCSTR("[string] or [number]")
3348: ,JSDOCSTR("convert a string of security flags (letters) into their numeric value or vice-versa "
3349: "(returns number OR string) - (added in v3.13)")
3350: ,313
3351: },
3352: {0}
3353: };
3354:
3355: static jsConstIntSpec js_global_const_ints[] = {
3356: /* Numeric error constants from errno.h (platform-dependant) */
3357: {"EPERM" ,EPERM },
3358: {"ENOENT" ,ENOENT },
3359: {"ESRCH" ,ESRCH },
3360: {"EIO" ,EIO },
3361: {"ENXIO" ,ENXIO },
3362: {"E2BIG" ,E2BIG },
3363: {"ENOEXEC" ,ENOEXEC },
3364: {"EBADF" ,EBADF },
3365: {"ECHILD" ,ECHILD },
3366: {"EAGAIN" ,EAGAIN },
3367: {"ENOMEM" ,ENOMEM },
3368: {"EACCES" ,EACCES },
3369: {"EFAULT" ,EFAULT },
3370: {"EBUSY" ,EBUSY },
3371: {"EEXIST" ,EEXIST },
3372: {"EXDEV" ,EXDEV },
3373: {"ENODEV" ,ENODEV },
3374: {"ENOTDIR" ,ENOTDIR },
3375: {"EISDIR" ,EISDIR },
3376: {"EINVAL" ,EINVAL },
3377: {"ENFILE" ,ENFILE },
3378: {"EMFILE" ,EMFILE },
3379: {"ENOTTY" ,ENOTTY },
3380: {"EFBIG" ,EFBIG },
3381: {"ENOSPC" ,ENOSPC },
3382: {"ESPIPE" ,ESPIPE },
3383: {"EROFS" ,EROFS },
3384: {"EMLINK" ,EMLINK },
3385: {"EPIPE" ,EPIPE },
3386: {"EDOM" ,EDOM },
3387: {"ERANGE" ,ERANGE },
3388: {"EDEADLOCK" ,EDEADLOCK },
3389: {"ENAMETOOLONG" ,ENAMETOOLONG },
3390: {"ENOTEMPTY" ,ENOTEMPTY },
3391:
3392: /* Socket errors */
3393: {"EINTR" ,EINTR },
3394: {"ENOTSOCK" ,ENOTSOCK },
3395: {"EMSGSIZE" ,EMSGSIZE },
3396: {"EWOULDBLOCK" ,EWOULDBLOCK },
3397: {"EPROTOTYPE" ,EPROTOTYPE },
3398: {"ENOPROTOOPT" ,ENOPROTOOPT },
3399: {"EPROTONOSUPPORT" ,EPROTONOSUPPORT},
3400: {"ESOCKTNOSUPPORT" ,ESOCKTNOSUPPORT},
3401: {"EOPNOTSUPP" ,EOPNOTSUPP },
3402: {"EPFNOSUPPORT" ,EPFNOSUPPORT },
3403: {"EAFNOSUPPORT" ,EAFNOSUPPORT },
3404: {"EADDRINUSE" ,EADDRINUSE },
3405: {"EADDRNOTAVAIL" ,EADDRNOTAVAIL },
3406: {"ECONNABORTED" ,ECONNABORTED },
3407: {"ECONNRESET" ,ECONNRESET },
3408: {"ENOBUFS" ,ENOBUFS },
3409: {"EISCONN" ,EISCONN },
3410: {"ENOTCONN" ,ENOTCONN },
3411: {"ESHUTDOWN" ,ESHUTDOWN },
3412: {"ETIMEDOUT" ,ETIMEDOUT },
3413: {"ECONNREFUSED" ,ECONNREFUSED },
3414: {"EINPROGRESS" ,EINPROGRESS },
3415:
3416: /* Log priority values from syslog.h/sbbsdefs.h (possibly platform-dependant) */
3417: {"LOG_EMERG" ,LOG_EMERG },
3418: {"LOG_ALERT" ,LOG_ALERT },
3419: {"LOG_CRIT" ,LOG_CRIT },
3420: {"LOG_ERR" ,LOG_ERR },
3421: {"LOG_ERROR" ,LOG_ERR },
3422: {"LOG_WARNING" ,LOG_WARNING },
3423: {"LOG_NOTICE" ,LOG_NOTICE },
3424: {"LOG_INFO" ,LOG_INFO },
3425: {"LOG_DEBUG" ,LOG_DEBUG },
3426:
3427: /* Other useful constants */
3428: {"INVALID_SOCKET" ,INVALID_SOCKET },
3429:
3430: /* Terminator (Governor Arnold) */
3431: {0}
3432: };
3433:
3434: JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods)
3435: {
3436: JSObject* glob;
3437:
3438: if((glob = JS_NewObject(cx, &js_global_class, NULL, NULL)) ==NULL)
3439: return(NULL);
3440:
3441: if (!JS_InitStandardClasses(cx, glob))
3442: return(NULL);
3443:
3444: if(methods!=NULL && !js_DefineSyncMethods(cx, glob, methods, TRUE))
3445: return(NULL);
3446:
3447: if(!js_DefineSyncMethods(cx, glob, js_global_functions, TRUE))
3448: return(NULL);
3449:
3450: if(!JS_DefineProperties(cx, glob, js_global_properties))
3451: return(NULL);
3452:
3453: if(!JS_SetPrivate(cx, glob, cfg)) /* Store a pointer to scfg_t */
3454: return(NULL);
3455:
3456: #ifdef BUILD_JSDOCS
3457: js_DescribeSyncObject(cx,glob
3458: ,"Top-level functions and properties (common to all servers and services)",310);
3459: #endif
3460:
3461: if(!js_DefineConstIntegers(cx, glob, js_global_const_ints, JSPROP_READONLY))
3462: return(NULL);
3463:
3464: return(glob);
3465: }
3466:
3467: JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx
3468: ,scfg_t* cfg /* common */
3469: ,scfg_t* node_cfg /* node-specific */
3470: ,jsSyncMethodSpec* methods /* global */
3471: ,time_t uptime /* system */
3472: ,char* host_name /* system */
3473: ,char* socklib_desc /* system */
3474: ,js_branch_t* branch /* js */
3475: ,client_t* client /* client */
3476: ,SOCKET client_socket /* client */
3477: ,js_server_props_t* props /* server */
3478: )
3479: {
3480: JSObject* js_glob;
3481:
3482: if(node_cfg==NULL)
3483: node_cfg=cfg;
3484:
3485: /* Global Object */
3486: if((js_glob=js_CreateGlobalObject(js_cx, cfg, methods))==NULL)
3487: return(NULL);
3488:
3489: /* System Object */
3490: if(js_CreateSystemObject(js_cx, js_glob, node_cfg, uptime, host_name, socklib_desc)==NULL)
3491: return(NULL);
3492:
3493: /* Internal JS Object */
3494: if(branch!=NULL
3495: && js_CreateInternalJsObject(js_cx, js_glob, branch)==NULL)
3496: return(NULL);
3497:
3498: /* Client Object */
3499: if(client!=NULL
3500: && js_CreateClientObject(js_cx, js_glob, "client", client, client_socket)==NULL)
3501: return(NULL);
3502:
3503: /* Server */
3504: if(props!=NULL
3505: && js_CreateServerObject(js_cx, js_glob, props)==NULL)
3506: return(NULL);
3507:
3508: /* Socket Class */
3509: if(js_CreateSocketClass(js_cx, js_glob)==NULL)
3510: return(NULL);
3511:
3512: /* Queue Class */
3513: if(js_CreateQueueClass(js_cx, js_glob)==NULL)
3514: return(NULL);
3515:
3516: /* MsgBase Class */
3517: if(js_CreateMsgBaseClass(js_cx, js_glob, cfg)==NULL)
3518: return(NULL);
3519:
3520: /* File Class */
3521: if(js_CreateFileClass(js_cx, js_glob)==NULL)
3522: return(NULL);
3523:
3524: /* User class */
3525: if(js_CreateUserClass(js_cx, js_glob, cfg)==NULL)
3526: return(NULL);
3527:
3528: /* Area Objects */
3529: if(!js_CreateUserObjects(js_cx, js_glob, cfg, NULL, NULL, NULL))
3530: return(NULL);
3531:
3532: return(js_glob);
3533: }
3534:
3535:
3536: #endif /* JAVSCRIPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.