Annotation of sbbs/src/sbbs3/js_global.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.