/ Check-in [e68e7c1ad1]
DEMO | DOWNLOAD | DEPLOY | SEARCH
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Cleanups
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e68e7c1ad15ef36dbd3eb4bcd8a0cd33f47927f8
User & Date: pmacdona 2018-12-02 03:12:18
Context
2019-01-24
23:58
Release "2.7.2". Changes to support embedding in fossil. Stop using min version of markdeep. Move to new documentation. Disallow loading .so from noexec mount. Cleanup option parsing. Support for unix exec with no shell (for jails). check-in: 5106a19352 user: pmacdona tags: trunk
2018-12-02
03:12
Cleanups check-in: e68e7c1ad1 user: pmacdona tags: trunk
2018-11-28
18:11
Release "2.7". check-in: f8bdb1a6c7 user: pmacdona tags: trunk
Changes

Changes to Makefile.

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
$(WEBSOCKLIB):
ifeq ($(USECMAKE), 1)
	$(MAKE) -C $(WEBSOCKDIR) -f Makefile.cmake CC=$(CC) AR=$(AR) WIN=$(WIN) TARGET=$(TARGET) USECMAKE=$(USECMAKE) MINIZ=$(JSI__MINIZ)
else
	$(MAKE) -C $(WEBSOCKDIR) CC=$(CC) AR=$(AR) WIN=$(WIN) TARGET=$(TARGET) USECMAKE=$(USECMAKE) MINIZ=$(JSI__MINIZ)
endif

$(SQLITELIB):
	$(MAKE) -C $(SQLITEDIR) CC=$(CC) AR=$(AR) LD=$(LD) WIN=$(WIN) TARGET=$(TARGET)


src/%.o: src/%.c
	$(CC) -c -o $@ $< $(CFLAGS) 









|







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
$(WEBSOCKLIB):
ifeq ($(USECMAKE), 1)
	$(MAKE) -C $(WEBSOCKDIR) -f Makefile.cmake CC=$(CC) AR=$(AR) WIN=$(WIN) TARGET=$(TARGET) USECMAKE=$(USECMAKE) MINIZ=$(JSI__MINIZ)
else
	$(MAKE) -C $(WEBSOCKDIR) CC=$(CC) AR=$(AR) WIN=$(WIN) TARGET=$(TARGET) USECMAKE=$(USECMAKE) MINIZ=$(JSI__MINIZ)
endif

$(SQLITELIB): $(SQLITEDIR)/Makefile
	$(MAKE) -C $(SQLITEDIR) CC=$(CC) AR=$(AR) LD=$(LD) WIN=$(WIN) TARGET=$(TARGET)


src/%.o: src/%.c
	$(CC) -c -o $@ $< $(CFLAGS) 


Changes to TODO.


1
2
3
4
5

InterpConfCmd: clean incoming data.
Rename to IntegralJS
Funcs support (void) parm.
Memory leaks in tests/prob/proto2.jsi are fixed by using subOpts.noOOP=true
Small memory leak in WebSockets on bad port.
>





1
2
3
4
5
6
Integrate with fossil (fissile).
InterpConfCmd: clean incoming data.
Rename to IntegralJS
Funcs support (void) parm.
Memory leaks in tests/prob/proto2.jsi are fixed by using subOpts.noOOP=true
Small memory leak in WebSockets on bad port.

Changes to doc/md/Jsish.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
..
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Jsish
=====
Jsish is a self-contained, dependency-free javascript interpreter and Web development environment.
No need to learn a new language:
its just javascript enhanced with 
[parameter types](Types), and everything required for web application development built-in.

    *********************************
    * .---------.                   *
    * | Browser |                   *
    * '----+----'                   *
    *      ^         .------.       *
    *      |   .--->|Database|      *
................................................................................
    * |  Jsish  +   | Script  |     *
    * +---------+<--+  File   |     *
    * |  ZVFS   |   '---------'     *
    *  '-------'                    *
    *                               *
    *********************************

WebSocket and Sqlite are compiled in, and
support scripts are bundled in a ZVFS appended to the binary,
so writing code is easier, and deployment is trivial.


Deploys
------
A [Deploy](Deploy) is a zip/sqlar archive or fossil
repository containing one or more applications, which Jsi can mount and execute.

For example, this [Ledger](https://jsish.org/App10/Ledger) demo is
served out as follows
using [jsi-app](https://jsish.org/jsi-app) fossil


|
|
|
|







 







|
|
<


|







1
2
3
4
5
6
7
8
9
10
11
12
13
..
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
Jsish
=====
Jsish is a self-contained and dependency-free server-side Web development environment.
There is no need to learn a new language:
Jsi javascript interpreter (enhanced with 
[parameter types](Types)) provides everything required for web application development already built-in.

    *********************************
    * .---------.                   *
    * | Browser |                   *
    * '----+----'                   *
    *      ^         .------.       *
    *      |   .--->|Database|      *
................................................................................
    * |  Jsish  +   | Script  |     *
    * +---------+<--+  File   |     *
    * |  ZVFS   |   '---------'     *
    *  '-------'                    *
    *                               *
    *********************************

WebSocket and Sqlite are compiled in and
support scripts are bundled into a ZVFS appended to the binary.



Deploy
------
A [Deploy](Deploy) is a zip/sqlar archive or fossil
repository containing one or more applications, which Jsi can mount and execute.

For example, this [Ledger](https://jsish.org/App10/Ledger) demo is
served out as follows
using [jsi-app](https://jsish.org/jsi-app) fossil

Changes to lib/Jsi_GenDeep.jsi.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
53
54
55
56
57
58
59



60
61
62
63
64
65
66
67
..
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
    };
    var options = { // Load markdeep and export (via websocket) to local file.
        create  :false,             // Creates include.shtml and md dir and exits.
        inDir   :'md',              // Input directory.
        incFile :'include.shtml',   // Template file.
        extn    :'.html',           // File extension.
        force   :false,             // Do all files, even if unchanged.
        outDir  :'.',               // Output directory.
        strip   :false              // Strip trailing script.
    };
    var links = [];
    parseOpts(self, options, opts);

    function checkLinks() {
        for (var i of links) {
................................................................................
        var vals = reg.exec(str);
        var fnam = vals[1];
        var fh = self.outDir+'/'+fnam+'.html';
        if (!File.exists(fh))
            links.push([fh, str, self.curFile]);
        var sfx = vals[2];
        if (!sfx) sfx = '';
        return '<a href="'+fnam+'.html'+sfx+'">';
    }

    function DeepFileSave(ws:userobj, id:number, data:object) {
        if (data.cmd === 'save') {
            var file = File.tail(data.url);
            file = file.split('?')[0];
            file = File.rootname(file)+self.extn;
................................................................................
            if (self.strip) {
                var nend = ndat.lastIndexOf('<script>window.alreadyProcessedMarkdeep|');
                if (nend>0)
                    ndat = ndat.substr(0,nend-1)+'</div></div><p></p>&nbsp;<p></p>';
            }
            ndat += '<style>body{visibility:visible;}</style>';
            self.curFile = file;



            ndat = ndat.replace(/<a href="[-a-zA-Z1-9_]+(#[-a-zA-Z1-9_\/]+)?">/gm, repHref);
            File.write(self.outDir+'/'+file, ndat);
            puts('Saved file',file);
            if (!self.fileList.length) {
                ws.send(id, 'DONE!!!');
                checkLinks();
                setTimeout(function () { puts('DONE!!!'); exit(0); }, 1000);
                return;
................................................................................
        var fl = [];
        if (args.length == 1 && File.isdir(args[0]))
            self.inDir = args[0];
        else
            for (var i of args)
                fl.push(i);
        if (!File.exists(self.outDir))

            throw('output directory does not exits: ' + self.outDir);
        if (!fl.length) {
            if (!File.isdir(self.inDir))
                throw('directory not found: '+self.inDir);
            if (!File.exists(self.incFile))
                throw('template not found: '+self.incFile);            
            for (i of File.glob('*.md', {dir:self.inDir})) {
                LogTrace('I',i);







|







 







|







 







>
>
>
|







 







>
|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    };
    var options = { // Load markdeep and export (via websocket) to local file.
        create  :false,             // Creates include.shtml and md dir and exits.
        inDir   :'md',              // Input directory.
        incFile :'include.shtml',   // Template file.
        extn    :'.html',           // File extension.
        force   :false,             // Do all files, even if unchanged.
        outDir  :'html',             // Output directory.
        strip   :false              // Strip trailing script.
    };
    var links = [];
    parseOpts(self, options, opts);

    function checkLinks() {
        for (var i of links) {
................................................................................
        var vals = reg.exec(str);
        var fnam = vals[1];
        var fh = self.outDir+'/'+fnam+'.html';
        if (!File.exists(fh))
            links.push([fh, str, self.curFile]);
        var sfx = vals[2];
        if (!sfx) sfx = '';
        return '<a href="'+fh+sfx+'">';
    }

    function DeepFileSave(ws:userobj, id:number, data:object) {
        if (data.cmd === 'save') {
            var file = File.tail(data.url);
            file = file.split('?')[0];
            file = File.rootname(file)+self.extn;
................................................................................
            if (self.strip) {
                var nend = ndat.lastIndexOf('<script>window.alreadyProcessedMarkdeep|');
                if (nend>0)
                    ndat = ndat.substr(0,nend-1)+'</div></div><p></p>&nbsp;<p></p>';
            }
            ndat += '<style>body{visibility:visible;}</style>';
            self.curFile = file;
            var base = '';
            if (self.outDir != '.')
                base = '<base href="..">';
            ndat = base'+ndat.replace(/<a href="[-a-zA-Z1-9_]+(#[-a-zA-Z1-9_\/]+)?">/gm, repHref);
            File.write(self.outDir+'/'+file, ndat);
            puts('Saved file',file);
            if (!self.fileList.length) {
                ws.send(id, 'DONE!!!');
                checkLinks();
                setTimeout(function () { puts('DONE!!!'); exit(0); }, 1000);
                return;
................................................................................
        var fl = [];
        if (args.length == 1 && File.isdir(args[0]))
            self.inDir = args[0];
        else
            for (var i of args)
                fl.push(i);
        if (!File.exists(self.outDir))
            File.mkdir('html');
            //throw('output directory does not exits: ' + self.outDir);
        if (!fl.length) {
            if (!File.isdir(self.inDir))
                throw('directory not found: '+self.inDir);
            if (!File.exists(self.incFile))
                throw('template not found: '+self.incFile);            
            for (i of File.glob('*.md', {dir:self.inDir})) {
                LogTrace('I',i);

Changes to lib/Jsi_Websrv.jsi.

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
...
330
331
332
333
334
335
336
337

338


339
340
341
342
343
344
345
...
350
351
352
353
354
355
356


357
358
359
360
361
362
363
        timeout     :60000,     // Set timeout (in ms) to shutdown. This is idle time, unless negative.
        trace       :false,     // Tracing output.
        url         :"",        // The file/url to serve out and clears timeout.
        urlPrefix   :'/Websrv', // Prefix for urls
        useridPass  :'',        // USER:PASS for web GUI.
        wsdebug     :0,         // Debug option for websockets.
        wsOpts      :{},        // Websocket options.
        zip         :''         // A .zip, .sqlar, or .fossil file to mount and use as rootdir.

    };
    parseOpts(self, options, conf);
    if (self.confFile != '')
        parseOpts(self, options, JSON.parse(File.read(self.confFile)));
    
    function DoExit()   // Notify all going down, then exit.
    {
................................................................................
            if (self.url)
                throw('can not have args and specify -url');
            else
                self.url = urlarg;
        }
        
        if (self.zip) {
            self.mnt = Jsi_Archive([self.zip], {noRun:true});

            self.rootdir = self.mnt;


            if (!self.url)
                self.url = getUrlInDir(self.mnt);
        }
        else if (!self.rootdir) {
            if (!self.url.length)
                self.rootdir = Info.scriptDir();
            else
................................................................................
        }
        if (!self.rootdir)
            self.rootdir = '.';
        if (urlOrig!=='' && self.timeout === 60000)
            self.timeout = 0;
        if (!self.server && !self.pageStr && urlOrig=='' && (!self.url || !File.isfile(self.rootdir+'/'+self.url)))
            throw("url file empty or not found: "+self.url);


        
        // Provide default values for websocket.
        var wo = self.wsopts = {
            local:self.local,
            debug:self.wsdebug,
            extHandler:true,
            onOpen:WsOpen,







|
>







 







|
>
|
>
>







 







>
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
        timeout     :60000,     // Set timeout (in ms) to shutdown. This is idle time, unless negative.
        trace       :false,     // Tracing output.
        url         :"",        // The file/url to serve out and clears timeout.
        urlPrefix   :'/Websrv', // Prefix for urls
        useridPass  :'',        // USER:PASS for web GUI.
        wsdebug     :0,         // Debug option for websockets.
        wsOpts      :{},        // Websocket options.
        zip         :'',        // A .zip, .sqlar, or .fossil file to mount and use as rootdir.
        zipVer      :''         // Version to mount in fossil.
    };
    parseOpts(self, options, conf);
    if (self.confFile != '')
        parseOpts(self, options, JSON.parse(File.read(self.confFile)));
    
    function DoExit()   // Notify all going down, then exit.
    {
................................................................................
            if (self.url)
                throw('can not have args and specify -url');
            else
                self.url = urlarg;
        }
        
        if (self.zip) {
            self.mnt = Jsi_Archive([self.zip], {noRun:true, version:self.zipVer});
            if (!self.rootdir)
                self.rootdir = self.mnt;
            else
                self.rootdir = self.mnt + '/' + self.rootdir;
            if (!self.url)
                self.url = getUrlInDir(self.mnt);
        }
        else if (!self.rootdir) {
            if (!self.url.length)
                self.rootdir = Info.scriptDir();
            else
................................................................................
        }
        if (!self.rootdir)
            self.rootdir = '.';
        if (urlOrig!=='' && self.timeout === 60000)
            self.timeout = 0;
        if (!self.server && !self.pageStr && urlOrig=='' && (!self.url || !File.isfile(self.rootdir+'/'+self.url)))
            throw("url file empty or not found: "+self.url);
        if (self.urlPrefix.length && self.urlPrefix[0] != '/')
            throw('urlPrefix must start with a slash');
        
        // Provide default values for websocket.
        var wo = self.wsopts = {
            local:self.local,
            debug:self.wsdebug,
            extHandler:true,
            onOpen:WsOpen,

Changes to sqlite/Makefile.

1
2
3
4
5
6
7
8
9
10
11
..
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Makefile to download/compile libsqlite.a
TARGET=unix
SOURCEDIR=src
CFLAGS  = -I$(SOURCEDIR) -I$(LWSBASE)/build -I../miniz -I$(TARGET)/
SQLVER=3240000
SQLURL=https://www.sqlite.org/2018/sqlite-amalgamation-$(SQLVER).zip

BUILDDIR=build/$(TARGET)
LIBNAME=libsqlite3.a
LWSLIBBUILD=$(LIBNAME)
CMAKE=cmake
................................................................................
$(SOURCEDIR)/sqlite3.c:
	wget $(SQLURL) || wget http://jsish.org/download/sqlite-amalgamation-$(SQLVER).zip
	unzip sqlite-amalgamation-$(SQLVER).zip
	ln -sf sqlite-amalgamation-$(SQLVER) src
	rm sqlite-amalgamation-$(SQLVER).zip


$(BUILDDIR)/libsqlite3.a: $(SOURCEDIR)/sqlite3.c
	$(CC) -c -I$(SOURCEDIR) $(SOURCEDIR)/sqlite3.c
	$(AR) rv $(BUILDDIR)/libsqlite3.a sqlite3.o

clean:
	rm -f $(OBJECTS) $(BUILDDIR)/libsqlite3.a

cleanall: clean
	rm -rf build
	
.PHONY: all depend remake clean cleanall download



|







 







|
|









1
2
3
4
5
6
7
8
9
10
11
..
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Makefile to download/compile libsqlite.a
TARGET=unix
SOURCEDIR=src
CFLAGS= -I$(SOURCEDIR) -I$(LWSBASE)/build -I../miniz -I$(TARGET)/ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_DBSTAT_VTAB
SQLVER=3240000
SQLURL=https://www.sqlite.org/2018/sqlite-amalgamation-$(SQLVER).zip

BUILDDIR=build/$(TARGET)
LIBNAME=libsqlite3.a
LWSLIBBUILD=$(LIBNAME)
CMAKE=cmake
................................................................................
$(SOURCEDIR)/sqlite3.c:
	wget $(SQLURL) || wget http://jsish.org/download/sqlite-amalgamation-$(SQLVER).zip
	unzip sqlite-amalgamation-$(SQLVER).zip
	ln -sf sqlite-amalgamation-$(SQLVER) src
	rm sqlite-amalgamation-$(SQLVER).zip


$(BUILDDIR)/libsqlite3.a: $(SOURCEDIR)/sqlite3.c Makefile
	$(CC) -c -I$(SOURCEDIR) $(SOURCEDIR)/sqlite3.c $(CFLAGS)
	$(AR) rv $(BUILDDIR)/libsqlite3.a sqlite3.o

clean:
	rm -f $(OBJECTS) $(BUILDDIR)/libsqlite3.a

cleanall: clean
	rm -rf build
	
.PHONY: all depend remake clean cleanall download

Changes to src/jsi.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
50502
50503
50504
50505
50506
50507
50508

50509
50510
50511
50512
50513
50514
50515
.....
51110
51111
51112
51113
51114
51115
51116



















51117
51118
51119
51120
51121
51122
51123
.....
51128
51129
51130
51131
51132
51133
51134




51135
51136
51137
51138
51139
51140
51141
51142
51143
51144
51145
51146
51147
51148
51149
51150



51151
51152
51153
51154
51155
51156
51157
51158
.....
51174
51175
51176
51177
51178
51179
51180
51181
51182
51183
51184
51185
51186
51187
51188
51189
51190
51191
51192
51193


51194
51195
51196
51197
51198
51199
51200
.....
51323
51324
51325
51326
51327
51328
51329
51330
51331
51332
51333
51334
51335
51336
51337
51338
51339
51340
51341
51342
51343
51344
51345
51346
51347
51348
51349
51350
51351
51352
51353
51354
51355
51356
51357
51358
51359
51360
.....
51614
51615
51616
51617
51618
51619
51620
51621
51622
51623
51624
51625
51626
51627
51628
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   7
#define JSI_VERSION_RELEASE 0

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
    char *ssl_cert_filepath;
    char *ssl_private_key_filepath;
    int ws_uid;
    int ws_gid;
    const char *clientHost;
    const char *clientOrigin;
    const char *formParams;

    // Preserve headers from http for use in websockets.
    int sfd;        // File descriptor for http.
    int hdrSz[200]; // Space for up to 100 headers
    int hdrNum;     // Num of above.
    Jsi_DString dHdrs; // Store header string here.
} jsi_wsCmdObj;

................................................................................
            if (n>0)
                Jsi_DSAppendLen(hStr, (char*)buffer, n);
            p = buffer;
        }
    }
    return true;
}




















static Jsi_RC jsi_wsTemplateFill(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, Jsi_Value *fn, Jsi_DString *dStr,
    int lvl) {
    Jsi_Value *fval;
    Jsi_RC rc = JSI_OK;
    char *cp, *cp2, *ce, pref[] = "<!--#include file=\"", suffix[] = "\"-->",
        pref2[] = "<!--#include virtual=\"";
................................................................................
                "<!--#include file=\"$inc\"-->\n"
                "<script src=\"markdeep.min.js\"></script>\n"
                "<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility='visible')</script>";
    char *fs, *fname = Jsi_ValueString(interp, fn, &flen), *fend = fname;
    char fbuf[PATH_MAX];
    if (lvl>10)
        return JSI_ERROR;




    fs = Jsi_Strrchr(fname, '/');
    if (fs) {
        flen = fs-fname;
        fend = fs+1;
    }
    if (lvl>0) {
        rc = Jsi_FileRead(interp, fn, &tStr);
        cs = Jsi_DSValue(&tStr);
    } else {
        snprintf(fbuf, sizeof(fbuf), "%.*s%s", flen, fname, cmdPtr->includeFile);
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        Jsi_StatBuf sb;
        int n = Jsi_Stat(interp, fval, &sb);
        if (!n && sb.st_size>0) {
            rc = Jsi_FileRead(interp, fval, &tStr);



            cs = Jsi_DSValue(&tStr);
        }
        Jsi_DecrRefCount(interp, fval);
    }

    while (rc == JSI_OK && cs) {
        char *ext = NULL, *sfname = fname;
        int sflen = flen;
................................................................................
            uint i;
            for (i=0; i<sizeof(sfx); i++) {
                if ((sfx[i] = cp[plen+i+1]) == '"' || !sfx[i]) {
                    sfx[i] = 0;
                    break;
                }
            }
            snprintf(fbuf, sizeof(fbuf), "%.*s%s/%s.%s", flen, fname, sfx, fend, sfx);
        } else {
            cp += plen;
            int elen = ce-cp;
            snprintf(fbuf, sizeof(fbuf), "%.*s/%.*s", sflen, sfname, elen, cp);
            ext = Jsi_Strrchr(fbuf, '.');
        }
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        if (!ext || Jsi_Strcmp(ext, ".shtml"))
            rc = Jsi_FileRead(interp, fval, dStr);
        else
            rc = jsi_wsTemplateFill(interp, cmdPtr, fval, dStr, lvl+1);


        Jsi_DecrRefCount(interp, fval);

        cs = ce + slen;
        if (*cs == '\n')
            cs++;
    }
    Jsi_DSFree(&tStr);
................................................................................
                default: break;
            }
        }
    }
    ext = Jsi_Strrchr(inPtr, '.');

    Jsi_Value *rdir = (pss->rootdir?pss->rootdir:cmdPtr->rootdir);
    const char *rootDir = (rdir?Jsi_ValueString(cmdPtr->interp, rdir, NULL):"./");
    char statPath[PATH_MAX];
#if 0
    if (!Jsi_Strncmp(inPtr, "/jsi/", 5)) {
        // Get the path for system files, eg /zvfs or /usr/local/lib/jsi
        const char *loadFile = NULL;
        Jsi_PkgRequire(interp, "Jsish", 0);
        if (Jsi_PkgVersion(interp, "Jsish", &loadFile)>=0) {
            if (loadFile) {
                snprintf(statPath, sizeof(statPath), "%s", loadFile);
                char *lcp = Jsi_Strrchr(statPath, '/');
                if (lcp) {
                    *lcp = 0;
                    inPtr += 5;
                    rootDir = statPath;
                }
            }
        }
    }
#endif

    snprintf(buf, sizeof(buf), "%s/%s", rootDir, inPtr);
    if (cmdPtr->debug>1)
        fprintf(stderr, "FILE: %s in %s | %s\n", buf, rootDir, Jsi_ValueString(interp, cmdPtr->rootdir, NULL));
    char extBuf[100];
    bool isgzip = 0;
    if (!ext || !ext[1])
        mime = "text/html";
    else {
        const char *eext = ext+1;
        uint elen = Jsi_Strlen(ext);
................................................................................
            goto bail;
    } else {
        // Need to read data for non-native files.
        Jsi_DString dStr = {}, fStr = {};
        if (isMdi)
            rc = jsi_wsTemplateFill(interp, cmdPtr, fname, &fStr, (essi?1:0));
        else
            rc = Jsi_FileRead(interp, fname, &fStr);
        if (rc != JSI_OK)
            goto nofile;
        int hrc = jsi_wsServeHeader(pss, wsi, (int)Jsi_DSLength(&fStr), 200, Jsi_DSValue(&hStr), mime, &dStr);
        if (hrc>=0) {
            Jsi_DSAppendLen(&dStr, Jsi_DSValue(&fStr), Jsi_DSLength(&fStr));
            char *strVal = Jsi_DSValue(&dStr);
            int strLen = Jsi_DSLength(&dStr);






|







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>






|


|






>
>
>
|







 







|



|





|


>
>







 







|













|






|

|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
50502
50503
50504
50505
50506
50507
50508
50509
50510
50511
50512
50513
50514
50515
50516
.....
51111
51112
51113
51114
51115
51116
51117
51118
51119
51120
51121
51122
51123
51124
51125
51126
51127
51128
51129
51130
51131
51132
51133
51134
51135
51136
51137
51138
51139
51140
51141
51142
51143
.....
51148
51149
51150
51151
51152
51153
51154
51155
51156
51157
51158
51159
51160
51161
51162
51163
51164
51165
51166
51167
51168
51169
51170
51171
51172
51173
51174
51175
51176
51177
51178
51179
51180
51181
51182
51183
51184
51185
.....
51201
51202
51203
51204
51205
51206
51207
51208
51209
51210
51211
51212
51213
51214
51215
51216
51217
51218
51219
51220
51221
51222
51223
51224
51225
51226
51227
51228
51229
.....
51352
51353
51354
51355
51356
51357
51358
51359
51360
51361
51362
51363
51364
51365
51366
51367
51368
51369
51370
51371
51372
51373
51374
51375
51376
51377
51378
51379
51380
51381
51382
51383
51384
51385
51386
51387
51388
51389
.....
51643
51644
51645
51646
51647
51648
51649
51650
51651
51652
51653
51654
51655
51656
51657
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   7
#define JSI_VERSION_RELEASE 1

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
    char *ssl_cert_filepath;
    char *ssl_private_key_filepath;
    int ws_uid;
    int ws_gid;
    const char *clientHost;
    const char *clientOrigin;
    const char *formParams;
    const char *curRoot;
    // Preserve headers from http for use in websockets.
    int sfd;        // File descriptor for http.
    int hdrSz[200]; // Space for up to 100 headers
    int hdrNum;     // Num of above.
    Jsi_DString dHdrs; // Store header string here.
} jsi_wsCmdObj;

................................................................................
            if (n>0)
                Jsi_DSAppendLen(hStr, (char*)buffer, n);
            p = buffer;
        }
    }
    return true;
}

// Read native file only if inside rootdir
static Jsi_RC jsi_wsFileRead(Jsi_Interp *interp, Jsi_Value *name, Jsi_DString *dStr, jsi_wsCmdObj *cmdPtr) {
    Jsi_StatBuf sb;
    Jsi_RC rc = JSI_ERROR;
    int n = Jsi_Stat(interp, name, &sb);
    if (!n && sb.st_size>0) {
        char fdir[PATH_MAX];
        const char* cr = cmdPtr->curRoot, *fpath;
        if (!Jsi_FSNative(interp, name) || ((fpath= Jsi_Realpath(interp, name, fdir))
            && cr && !Jsi_Strncmp(fpath, cr, Jsi_Strlen(cr))))
            rc = Jsi_FileRead(interp, name, dStr);
        else
            fprintf(stderr, "Skip read file %s\n", Jsi_ValueString(interp, name, NULL));
    }
    if (cmdPtr->noWarn)
        return JSI_OK;
    return rc;
}

static Jsi_RC jsi_wsTemplateFill(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, Jsi_Value *fn, Jsi_DString *dStr,
    int lvl) {
    Jsi_Value *fval;
    Jsi_RC rc = JSI_OK;
    char *cp, *cp2, *ce, pref[] = "<!--#include file=\"", suffix[] = "\"-->",
        pref2[] = "<!--#include virtual=\"";
................................................................................
                "<!--#include file=\"$inc\"-->\n"
                "<script src=\"markdeep.min.js\"></script>\n"
                "<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility='visible')</script>";
    char *fs, *fname = Jsi_ValueString(interp, fn, &flen), *fend = fname;
    char fbuf[PATH_MAX];
    if (lvl>10)
        return JSI_ERROR;
    int rlen;
    char *root = Jsi_ValueString(interp, cmdPtr->rootdir, &rlen);
    if (!Jsi_Strncmp(root, fname, rlen))
        fname = fname + rlen;
    fs = Jsi_Strrchr(fname, '/');
    if (fs) {
        flen = fs-fname;
        fend = fs+1;
    }
    if (lvl>0) {
        rc = jsi_wsFileRead(interp, fn, &tStr, cmdPtr);
        cs = Jsi_DSValue(&tStr);
    } else {
        snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%s", root, flen, fname, cmdPtr->includeFile);
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        Jsi_StatBuf sb;
        int n = Jsi_Stat(interp, fval, &sb);
        if (!n && sb.st_size>0) {
            rc = Jsi_FileRead(interp, fval, &tStr);
            if (cmdPtr->noWarn)
                rc = JSI_OK;
            else
                cs = Jsi_DSValue(&tStr);
        }
        Jsi_DecrRefCount(interp, fval);
    }

    while (rc == JSI_OK && cs) {
        char *ext = NULL, *sfname = fname;
        int sflen = flen;
................................................................................
            uint i;
            for (i=0; i<sizeof(sfx); i++) {
                if ((sfx[i] = cp[plen+i+1]) == '"' || !sfx[i]) {
                    sfx[i] = 0;
                    break;
                }
            }
            snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%s/%s.%s", root, flen, fname, sfx, fend, sfx);
        } else {
            cp += plen;
            int elen = ce-cp;
            snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%.*s", root, sflen, sfname, elen, cp);
            ext = Jsi_Strrchr(fbuf, '.');
        }
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        if (!ext || Jsi_Strcmp(ext, ".shtml"))
            rc = jsi_wsFileRead(interp, fval, dStr, cmdPtr);
        else
            rc = jsi_wsTemplateFill(interp, cmdPtr, fval, dStr, lvl+1);
        if (cmdPtr->noWarn)
            rc = JSI_OK;
        Jsi_DecrRefCount(interp, fval);

        cs = ce + slen;
        if (*cs == '\n')
            cs++;
    }
    Jsi_DSFree(&tStr);
................................................................................
                default: break;
            }
        }
    }
    ext = Jsi_Strrchr(inPtr, '.');

    Jsi_Value *rdir = (pss->rootdir?pss->rootdir:cmdPtr->rootdir);
    cmdPtr->curRoot = (rdir?Jsi_ValueString(cmdPtr->interp, rdir, NULL):"./");
    char statPath[PATH_MAX];
#if 0
    if (!Jsi_Strncmp(inPtr, "/jsi/", 5)) {
        // Get the path for system files, eg /zvfs or /usr/local/lib/jsi
        const char *loadFile = NULL;
        Jsi_PkgRequire(interp, "Jsish", 0);
        if (Jsi_PkgVersion(interp, "Jsish", &loadFile)>=0) {
            if (loadFile) {
                snprintf(statPath, sizeof(statPath), "%s", loadFile);
                char *lcp = Jsi_Strrchr(statPath, '/');
                if (lcp) {
                    *lcp = 0;
                    inPtr += 5;
                    cmdPtr->curRoot = statPath;
                }
            }
        }
    }
#endif

    snprintf(buf, sizeof(buf), "%s/%s", cmdPtr->curRoot, inPtr);
    if (cmdPtr->debug>1)
        fprintf(stderr, "FILE: %s in %s | %s\n", buf, cmdPtr->curRoot, Jsi_ValueString(interp, cmdPtr->rootdir, NULL));
    char extBuf[100];
    bool isgzip = 0;
    if (!ext || !ext[1])
        mime = "text/html";
    else {
        const char *eext = ext+1;
        uint elen = Jsi_Strlen(ext);
................................................................................
            goto bail;
    } else {
        // Need to read data for non-native files.
        Jsi_DString dStr = {}, fStr = {};
        if (isMdi)
            rc = jsi_wsTemplateFill(interp, cmdPtr, fname, &fStr, (essi?1:0));
        else
            rc = jsi_wsFileRead(interp, fname, &fStr, cmdPtr);
        if (rc != JSI_OK)
            goto nofile;
        int hrc = jsi_wsServeHeader(pss, wsi, (int)Jsi_DSLength(&fStr), 200, Jsi_DSValue(&hStr), mime, &dStr);
        if (hrc>=0) {
            Jsi_DSAppendLen(&dStr, Jsi_DSValue(&fStr), Jsi_DSLength(&fStr));
            char *strVal = Jsi_DSValue(&dStr);
            int strLen = Jsi_DSLength(&dStr);

Changes to src/jsi.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   7
#define JSI_VERSION_RELEASE 0

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   7
#define JSI_VERSION_RELEASE 1

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

Changes to src/jsiWebSocket.c.

165
166
167
168
169
170
171

172
173
174
175
176
177
178
...
773
774
775
776
777
778
779



















780
781
782
783
784
785
786
...
791
792
793
794
795
796
797




798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813



814
815
816
817
818
819
820
821
...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856


857
858
859
860
861
862
863
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
....
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
    char *ssl_cert_filepath;
    char *ssl_private_key_filepath;
    int ws_uid;
    int ws_gid;
    const char *clientHost;
    const char *clientOrigin;
    const char *formParams;

    // Preserve headers from http for use in websockets.
    int sfd;        // File descriptor for http.
    int hdrSz[200]; // Space for up to 100 headers
    int hdrNum;     // Num of above.
    Jsi_DString dHdrs; // Store header string here.
} jsi_wsCmdObj;

................................................................................
            if (n>0)
                Jsi_DSAppendLen(hStr, (char*)buffer, n);
            p = buffer;
        }
    }
    return true;
}




















static Jsi_RC jsi_wsTemplateFill(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, Jsi_Value *fn, Jsi_DString *dStr,
    int lvl) {
    Jsi_Value *fval;
    Jsi_RC rc = JSI_OK;
    char *cp, *cp2, *ce, pref[] = "<!--#include file=\"", suffix[] = "\"-->",
        pref2[] = "<!--#include virtual=\"";
................................................................................
                "<!--#include file=\"$inc\"-->\n"
                "<script src=\"markdeep.min.js\"></script>\n"
                "<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility='visible')</script>";
    char *fs, *fname = Jsi_ValueString(interp, fn, &flen), *fend = fname;
    char fbuf[PATH_MAX];
    if (lvl>10)
        return JSI_ERROR;




    fs = Jsi_Strrchr(fname, '/');
    if (fs) {
        flen = fs-fname;
        fend = fs+1;
    }
    if (lvl>0) {
        rc = Jsi_FileRead(interp, fn, &tStr);
        cs = Jsi_DSValue(&tStr);
    } else {
        snprintf(fbuf, sizeof(fbuf), "%.*s%s", flen, fname, cmdPtr->includeFile);
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        Jsi_StatBuf sb;
        int n = Jsi_Stat(interp, fval, &sb);
        if (!n && sb.st_size>0) {
            rc = Jsi_FileRead(interp, fval, &tStr);



            cs = Jsi_DSValue(&tStr);
        }
        Jsi_DecrRefCount(interp, fval);
    }

    while (rc == JSI_OK && cs) {
        char *ext = NULL, *sfname = fname;
        int sflen = flen;
................................................................................
            uint i;
            for (i=0; i<sizeof(sfx); i++) {
                if ((sfx[i] = cp[plen+i+1]) == '"' || !sfx[i]) {
                    sfx[i] = 0;
                    break;
                }
            }
            snprintf(fbuf, sizeof(fbuf), "%.*s%s/%s.%s", flen, fname, sfx, fend, sfx);
        } else {
            cp += plen;
            int elen = ce-cp;
            snprintf(fbuf, sizeof(fbuf), "%.*s/%.*s", sflen, sfname, elen, cp);
            ext = Jsi_Strrchr(fbuf, '.');
        }
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        if (!ext || Jsi_Strcmp(ext, ".shtml"))
            rc = Jsi_FileRead(interp, fval, dStr);
        else
            rc = jsi_wsTemplateFill(interp, cmdPtr, fval, dStr, lvl+1);


        Jsi_DecrRefCount(interp, fval);

        cs = ce + slen;
        if (*cs == '\n')
            cs++;
    }
    Jsi_DSFree(&tStr);
................................................................................
                default: break;
            }
        }
    }
    ext = Jsi_Strrchr(inPtr, '.');

    Jsi_Value *rdir = (pss->rootdir?pss->rootdir:cmdPtr->rootdir);
    const char *rootDir = (rdir?Jsi_ValueString(cmdPtr->interp, rdir, NULL):"./");
    char statPath[PATH_MAX];
#if 0
    if (!Jsi_Strncmp(inPtr, "/jsi/", 5)) {
        // Get the path for system files, eg /zvfs or /usr/local/lib/jsi
        const char *loadFile = NULL;
        Jsi_PkgRequire(interp, "Jsish", 0);
        if (Jsi_PkgVersion(interp, "Jsish", &loadFile)>=0) {
            if (loadFile) {
                snprintf(statPath, sizeof(statPath), "%s", loadFile);
                char *lcp = Jsi_Strrchr(statPath, '/');
                if (lcp) {
                    *lcp = 0;
                    inPtr += 5;
                    rootDir = statPath;
                }
            }
        }
    }
#endif

    snprintf(buf, sizeof(buf), "%s/%s", rootDir, inPtr);
    if (cmdPtr->debug>1)
        fprintf(stderr, "FILE: %s in %s | %s\n", buf, rootDir, Jsi_ValueString(interp, cmdPtr->rootdir, NULL));
    char extBuf[100];
    bool isgzip = 0;
    if (!ext || !ext[1])
        mime = "text/html";
    else {
        const char *eext = ext+1;
        uint elen = Jsi_Strlen(ext);
................................................................................
            goto bail;
    } else {
        // Need to read data for non-native files.
        Jsi_DString dStr = {}, fStr = {};
        if (isMdi)
            rc = jsi_wsTemplateFill(interp, cmdPtr, fname, &fStr, (essi?1:0));
        else
            rc = Jsi_FileRead(interp, fname, &fStr);
        if (rc != JSI_OK)
            goto nofile;
        int hrc = jsi_wsServeHeader(pss, wsi, (int)Jsi_DSLength(&fStr), 200, Jsi_DSValue(&hStr), mime, &dStr);
        if (hrc>=0) {
            Jsi_DSAppendLen(&dStr, Jsi_DSValue(&fStr), Jsi_DSLength(&fStr));
            char *strVal = Jsi_DSValue(&dStr);
            int strLen = Jsi_DSLength(&dStr);







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>






|


|






>
>
>
|







 







|



|





|


>
>







 







|













|






|

|







 







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
....
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
....
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
    char *ssl_cert_filepath;
    char *ssl_private_key_filepath;
    int ws_uid;
    int ws_gid;
    const char *clientHost;
    const char *clientOrigin;
    const char *formParams;
    const char *curRoot;
    // Preserve headers from http for use in websockets.
    int sfd;        // File descriptor for http.
    int hdrSz[200]; // Space for up to 100 headers
    int hdrNum;     // Num of above.
    Jsi_DString dHdrs; // Store header string here.
} jsi_wsCmdObj;

................................................................................
            if (n>0)
                Jsi_DSAppendLen(hStr, (char*)buffer, n);
            p = buffer;
        }
    }
    return true;
}

// Read native file only if inside rootdir
static Jsi_RC jsi_wsFileRead(Jsi_Interp *interp, Jsi_Value *name, Jsi_DString *dStr, jsi_wsCmdObj *cmdPtr) {
    Jsi_StatBuf sb;
    Jsi_RC rc = JSI_ERROR;
    int n = Jsi_Stat(interp, name, &sb);
    if (!n && sb.st_size>0) {
        char fdir[PATH_MAX];
        const char* cr = cmdPtr->curRoot, *fpath;
        if (!Jsi_FSNative(interp, name) || ((fpath= Jsi_Realpath(interp, name, fdir))
            && cr && !Jsi_Strncmp(fpath, cr, Jsi_Strlen(cr))))
            rc = Jsi_FileRead(interp, name, dStr);
        else
            fprintf(stderr, "Skip read file %s\n", Jsi_ValueString(interp, name, NULL));
    }
    if (cmdPtr->noWarn)
        return JSI_OK;
    return rc;
}

static Jsi_RC jsi_wsTemplateFill(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, Jsi_Value *fn, Jsi_DString *dStr,
    int lvl) {
    Jsi_Value *fval;
    Jsi_RC rc = JSI_OK;
    char *cp, *cp2, *ce, pref[] = "<!--#include file=\"", suffix[] = "\"-->",
        pref2[] = "<!--#include virtual=\"";
................................................................................
                "<!--#include file=\"$inc\"-->\n"
                "<script src=\"markdeep.min.js\"></script>\n"
                "<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility='visible')</script>";
    char *fs, *fname = Jsi_ValueString(interp, fn, &flen), *fend = fname;
    char fbuf[PATH_MAX];
    if (lvl>10)
        return JSI_ERROR;
    int rlen;
    char *root = Jsi_ValueString(interp, cmdPtr->rootdir, &rlen);
    if (!Jsi_Strncmp(root, fname, rlen))
        fname = fname + rlen;
    fs = Jsi_Strrchr(fname, '/');
    if (fs) {
        flen = fs-fname;
        fend = fs+1;
    }
    if (lvl>0) {
        rc = jsi_wsFileRead(interp, fn, &tStr, cmdPtr);
        cs = Jsi_DSValue(&tStr);
    } else {
        snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%s", root, flen, fname, cmdPtr->includeFile);
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        Jsi_StatBuf sb;
        int n = Jsi_Stat(interp, fval, &sb);
        if (!n && sb.st_size>0) {
            rc = Jsi_FileRead(interp, fval, &tStr);
            if (cmdPtr->noWarn)
                rc = JSI_OK;
            else
                cs = Jsi_DSValue(&tStr);
        }
        Jsi_DecrRefCount(interp, fval);
    }

    while (rc == JSI_OK && cs) {
        char *ext = NULL, *sfname = fname;
        int sflen = flen;
................................................................................
            uint i;
            for (i=0; i<sizeof(sfx); i++) {
                if ((sfx[i] = cp[plen+i+1]) == '"' || !sfx[i]) {
                    sfx[i] = 0;
                    break;
                }
            }
            snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%s/%s.%s", root, flen, fname, sfx, fend, sfx);
        } else {
            cp += plen;
            int elen = ce-cp;
            snprintf(fbuf, sizeof(fbuf), "%s/%.*s/%.*s", root, sflen, sfname, elen, cp);
            ext = Jsi_Strrchr(fbuf, '.');
        }
        fval = Jsi_ValueNewStringConst(interp, fbuf, -1);
        Jsi_IncrRefCount(interp, fval);
        if (!ext || Jsi_Strcmp(ext, ".shtml"))
            rc = jsi_wsFileRead(interp, fval, dStr, cmdPtr);
        else
            rc = jsi_wsTemplateFill(interp, cmdPtr, fval, dStr, lvl+1);
        if (cmdPtr->noWarn)
            rc = JSI_OK;
        Jsi_DecrRefCount(interp, fval);

        cs = ce + slen;
        if (*cs == '\n')
            cs++;
    }
    Jsi_DSFree(&tStr);
................................................................................
                default: break;
            }
        }
    }
    ext = Jsi_Strrchr(inPtr, '.');

    Jsi_Value *rdir = (pss->rootdir?pss->rootdir:cmdPtr->rootdir);
    cmdPtr->curRoot = (rdir?Jsi_ValueString(cmdPtr->interp, rdir, NULL):"./");
    char statPath[PATH_MAX];
#if 0
    if (!Jsi_Strncmp(inPtr, "/jsi/", 5)) {
        // Get the path for system files, eg /zvfs or /usr/local/lib/jsi
        const char *loadFile = NULL;
        Jsi_PkgRequire(interp, "Jsish", 0);
        if (Jsi_PkgVersion(interp, "Jsish", &loadFile)>=0) {
            if (loadFile) {
                snprintf(statPath, sizeof(statPath), "%s", loadFile);
                char *lcp = Jsi_Strrchr(statPath, '/');
                if (lcp) {
                    *lcp = 0;
                    inPtr += 5;
                    cmdPtr->curRoot = statPath;
                }
            }
        }
    }
#endif

    snprintf(buf, sizeof(buf), "%s/%s", cmdPtr->curRoot, inPtr);
    if (cmdPtr->debug>1)
        fprintf(stderr, "FILE: %s in %s | %s\n", buf, cmdPtr->curRoot, Jsi_ValueString(interp, cmdPtr->rootdir, NULL));
    char extBuf[100];
    bool isgzip = 0;
    if (!ext || !ext[1])
        mime = "text/html";
    else {
        const char *eext = ext+1;
        uint elen = Jsi_Strlen(ext);
................................................................................
            goto bail;
    } else {
        // Need to read data for non-native files.
        Jsi_DString dStr = {}, fStr = {};
        if (isMdi)
            rc = jsi_wsTemplateFill(interp, cmdPtr, fname, &fStr, (essi?1:0));
        else
            rc = jsi_wsFileRead(interp, fname, &fStr, cmdPtr);
        if (rc != JSI_OK)
            goto nofile;
        int hrc = jsi_wsServeHeader(pss, wsi, (int)Jsi_DSLength(&fStr), 200, Jsi_DSValue(&hStr), mime, &dStr);
        if (hrc>=0) {
            Jsi_DSAppendLen(&dStr, Jsi_DSValue(&fStr), Jsi_DSLength(&fStr));
            char *strVal = Jsi_DSValue(&dStr);
            int strLen = Jsi_DSLength(&dStr);

Changes to tools/protos.jsi.

1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.7.0
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};
|







1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.7.1
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};