diff --git a/makefile b/makefile
index f3127e3..93538d3 100644
--- a/makefile
+++ b/makefile
@@ -72,7 +72,7 @@ SOURCES = microstack/ILibAsyncServerSocket.c microstack/ILibAsyncSocket.c micros
SOURCES += microstack/ILibRemoteLogging.c microstack/ILibWebClient.c microstack/ILibWebRTC.c microstack/ILibWebServer.c microstack/ILibCrypto.c
SOURCES += microstack/ILibWrapperWebRTC.c microstack/ILibSimpleDataStore.c microstack/ILibProcessPipe.c microstack/ILibIPAddressMonitor.c
SOURCES += microscript/duktape.c microscript/duk_module_duktape.c microscript/ILibDuktape_DuplexStream.c microscript/ILibDuktape_Helpers.c
-SOURCES += microscript/ILibDuktape_http.c microscript/ILibDuktape_net.c microscript/ILibDuktape_ReadableStream.c microscript/ILibDuktape_WritableStream.c
+SOURCES += microscript/ILibDuktape_net.c microscript/ILibDuktape_ReadableStream.c microscript/ILibDuktape_WritableStream.c
SOURCES += microscript/ILibDuktapeModSearch.c microscript/ILibDuktape_WebRTC.c
SOURCES += microscript/ILibDuktape_SimpleDataStore.c microscript/ILibDuktape_GenericMarshal.c
SOURCES += microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c
diff --git a/meshconsole/MeshConsole.vcxproj b/meshconsole/MeshConsole.vcxproj
index fd394b4..c998e09 100644
--- a/meshconsole/MeshConsole.vcxproj
+++ b/meshconsole/MeshConsole.vcxproj
@@ -70,7 +70,6 @@
-
@@ -120,7 +119,6 @@
-
diff --git a/meshconsole/MeshConsole.vcxproj.filters b/meshconsole/MeshConsole.vcxproj.filters
index 3cedab3..9485eaf 100644
--- a/meshconsole/MeshConsole.vcxproj.filters
+++ b/meshconsole/MeshConsole.vcxproj.filters
@@ -30,9 +30,6 @@
Microscript
-
- Microscript
-
Microscript
@@ -165,9 +162,6 @@
Microscript
-
- Microscript
-
Microscript
diff --git a/meshservice/MeshService.vcxproj b/meshservice/MeshService.vcxproj
index 0fd2cce..ddafbec 100644
--- a/meshservice/MeshService.vcxproj
+++ b/meshservice/MeshService.vcxproj
@@ -503,7 +503,6 @@
-
@@ -555,7 +554,6 @@
-
diff --git a/meshservice/MeshService.vcxproj.filters b/meshservice/MeshService.vcxproj.filters
index 1628f2c..a619213 100644
--- a/meshservice/MeshService.vcxproj.filters
+++ b/meshservice/MeshService.vcxproj.filters
@@ -43,9 +43,6 @@
Microscript
-
- Microscript
-
Microscript
@@ -186,9 +183,6 @@
Microscript
-
- Microscript
-
Microscript
diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c
index 4918ab8..375364f 100644
--- a/microscript/ILibDuktape_Polyfills.c
+++ b/microscript/ILibDuktape_Polyfills.c
@@ -301,7 +301,7 @@ duk_ret_t ILibDuktape_Polyfills_String_padStart(duk_context *ctx)
duk_push_this(ctx);
char *buffer = Duktape_GetBuffer(ctx, -1, &bufferLen);
- if (bufferLen > totalLen)
+ if ((int)bufferLen > totalLen)
{
duk_push_lstring(ctx, buffer, bufferLen);
return(1);
@@ -1856,9 +1856,12 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx)
{
// The following can be overriden by calling addModule() or by having a .js file in the module path
+ // http-digest. Refer to /modules folder for a human readable version
+ duk_peval_string_noresult(ctx, "addModule('http-digest', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTkgSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8NCg0KDQp2YXIgd3JpdGFibGUgPSByZXF1aXJlKCdzdHJlYW0nKS5Xcml0YWJsZTsNCnZhciBtZDUgPSByZXF1aXJlKCdNRDVTdHJlYW0nKS5jcmVhdGUoKTsNCg0KZnVuY3Rpb24gY2hlY2tFdmVudEZvcndhcmRpbmcoZGlnZXN0UmVxdWVzdCwgZXZlbnROYW1lKQ0Kew0KICAgIGlmIChkaWdlc3RSZXF1ZXN0Lmxpc3RlbmVyQ291bnQoZXZlbnROYW1lKSA+IDApDQogICAgew0KICAgICAgICB2YXIgZUZvcndhcmQgPSBmdW5jdGlvbiBfZUZvcndhcmQoKQ0KICAgICAgICB7DQogICAgICAgICAgICB2YXIgcCA9IFtlRm9yd2FyZC5fZXZlbnROYW1lXTsNCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgKytpKSB7IHAucHVzaChhcmd1bWVudHNbaV0pOyB9DQogICAgICAgICAgICBfZUZvcndhcmQuX2RpZ2VzdFJlcXVlc3QuZW1pdC5hcHBseShfZUZvcndhcmQuX2RpZ2VzdFJlcXVlc3QsIHApOw0KICAgICAgICB9Ow0KICAgICAgICBlRm9yd2FyZC5fZXZlbnROYW1lID0gZXZlbnROYW1lOw0KICAgICAgICBlRm9yd2FyZC5fZGlnZXN0UmVxdWVzdCA9IGRpZ2VzdFJlcXVlc3Q7DQogICAgICAgIGRpZ2VzdFJlcXVlc3QuX3JlcXVlc3Qub24oZXZlbnROYW1lLCBlRm9yd2FyZCk7DQogICAgfQ0KfQ0KDQpmdW5jdGlvbiBnZW5lcmF0ZUF1dGhIZWFkZXJzKGltc2csIG9wdGlvbnMsIGRpZ2VzdCkNCnsNCiAgICB2YXIgYXV0aDsNCg0KICAgIGlmIChpbXNnICE9IG51bGwpDQogICAgew0KICAgICAgICBhdXRoID0geyByZWFsbTogbnVsbCwgbm9uY2U6IG51bGwsIG9wYXF1ZTogbnVsbCwgcW9wOiBudWxsIH07DQogICAgICAgIHZhciB3d3cgPSBpbXNnLmhlYWRlcnNbJ1dXVy1BdXRoZW50aWNhdGUnXTsNCiAgICAgICAgdmFyIHRva2VucyA9IHd3dy5zcGxpdCgnLCcpOw0KDQogICAgICAgIHZhciBwYWlyczsNCiAgICAgICAgZm9yICh2YXIgaSBpbiB0b2tlbnMpDQogICAgICAgIHsNCiAgICAgICAgICAgIHBhaXJzID0gdG9rZW5zW2ldLnNwbGl0KCc9Jyk7DQogICAgICAgICAgICBpZiAocGFpcnMubGVuZ3RoID09IDIpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgc3dpdGNoIChwYWlyc1swXS50b0xvd2VyQ2FzZSgpLnRyaW0oKSkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgJ2RpZ2VzdCByZWFsbSc6DQogICAgICAgICAgICAgICAgICAgICAgICBhdXRoLnJlYWxtID0gcGFpcnNbMV07DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXV0aC5yZWFsbVswXSA9PSAnIicpIHsgYXV0aC5yZWFsbSA9IGF1dGgucmVhbG0uc3Vic3RyaW5nKDEsIGF1dGgucmVhbG0ubGVuZ3RoIC0gMSk7IH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICdub25jZSc6DQogICAgICAgICAgICAgICAgICAgICAgICBhdXRoLm5vbmNlID0gcGFpcnNbMV07DQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXV0aC5ub25jZVswXSA9PSAnIicpIHsgYXV0aC5ub25jZSA9IGF1dGgubm9uY2Uuc3Vic3RyaW5nKDEsIGF1dGgubm9uY2UubGVuZ3RoIC0gMSk7IH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICdvcGFxdWUnOg0KICAgICAgICAgICAgICAgICAgICAgICAgYXV0aC5vcGFxdWUgPSBwYWlyc1sxXTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdXRoLm9wYXF1ZVswXSA9PSAnIicpIHsgYXV0aC5vcGFxdWUgPSBhdXRoLm9wYXF1ZS5zdWJzdHJpbmcoMSwgYXV0aC5vcGFxdWUubGVuZ3RoIC0gMSk7IH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlICdxb3AnOg0KICAgICAgICAgICAgICAgICAgICAgICAgYXV0aC5xb3AgPSBwYWlyc1sxXTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdXRoLnFvcFswXSA9PSAnIicpIHsgYXV0aC5xb3AgPSBhdXRoLnFvcC5zdWJzdHJpbmcoMSwgYXV0aC5xb3AubGVuZ3RoIC0gMSk7IH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBkaWdlc3QuX2F1dGggPSBhdXRoOw0KICAgIH0NCiAgICBlbHNlDQogICAgew0KICAgICAgICBpZiAoIShhdXRoID0gZGlnZXN0Ll9hdXRoKSkgeyByZXR1cm47IH0NCiAgICB9DQoNCiAgICB2YXIgc3RlcDEgPSBkaWdlc3QuX29wdGlvbnMudXNlcm5hbWUgKyAnOicgKyBhdXRoLnJlYWxtICsgJzonICsgZGlnZXN0Ll9vcHRpb25zLnBhc3N3b3JkOw0KICAgIGF1dGguc3RlcDEgPSBtZDUuc3luY0hhc2goc3RlcDEpLnRvU3RyaW5nKCdoZXgnKS50b0xvd2VyQ2FzZSgpOw0KDQogICAgdmFyIHN0ZXAyID0gb3B0aW9ucy5tZXRob2QgKyAnOicgKyBvcHRpb25zLnBhdGg7DQogICAgYXV0aC5zdGVwMiA9IG1kNS5zeW5jSGFzaChzdGVwMikudG9TdHJpbmcoJ2hleCcpLnRvTG93ZXJDYXNlKCk7DQoNCg0KICAgIGlmIChhdXRoLnFvcCA9PSBudWxsKQ0KICAgIHsNCiAgICAgICAgdmFyIHN0ZXAzID0gYXV0aC5zdGVwMSArICc6JyArIGF1dGgubm9uY2UgKyAnOicgKyBhdXRoLnN0ZXAyOw0KICAgICAgICBhdXRoLnN0ZXAzID0gbWQ1LnN5bmNIYXNoKHN0ZXAzKS50b1N0cmluZygnaGV4JykudG9Mb3dlckNhc2UoKTsNCiAgICB9DQogICAgZWxzZQ0KICAgIHsNCiAgICAgICAgZGlnZXN0Ll9OQyArPSAxOwogICAgICAgIHZhciBzdGVwMyA9IGF1dGguc3RlcDEgKyAnOicgKyBhdXRoLm5vbmNlICsgJzonICsgZGlnZXN0Ll9OQy50b1N0cmluZygxNikudG9Mb3dlckNhc2UoKS5wYWRTdGFydCg4LCAnMCcpICsgJzonICsgZGlnZXN0Ll9DTk9OQ0UgKyAnOicgKyBhdXRoLnFvcCArICc6JyArIGF1dGguc3RlcDI7CiAgICAgICAgYXV0aC5zdGVwMyA9IG1kNS5zeW5jSGFzaChzdGVwMykudG9TdHJpbmcoJ2hleCcpLnRvTG93ZXJDYXNlKCk7DQogICAgfQ0KDQogICAgdmFyIHJldCA9ICdEaWdlc3QgdXNlcm5hbWU9IicgKyBkaWdlc3QuX29wdGlvbnMudXNlcm5hbWUgKyAnIixyZWFsbT0iJyArIGF1dGgucmVhbG0gKyAnIixub25jZT0iJyArIGF1dGgubm9uY2UgKyAnIix1cmk9IicgKyBvcHRpb25zLnBhdGggKyAnIic7DQogICAgaWYgKGF1dGgub3BhcXVlICE9IG51bGwpIHsgcmV0ICs9ICgnLG9wYXF1ZT0iJyArIGF1dGgub3BhcXVlICsgJyInKTsgfQ0KICAgIHJldCArPSAoJyxyZXNwb25zZT0iJyArIGF1dGguc3RlcDMgKyAnIicpOw0KDQogICAgaWYgKGF1dGgucW9wICE9IG51bGwpDQogICAgew0KICAgICAgICByZXQgKz0gKCcscW9wPSInICsgYXV0aC5xb3AgKyAnIixuYz0iJyArIGRpZ2VzdC5fTkMudG9TdHJpbmcoMTYpLnRvTG93ZXJDYXNlKCkucGFkU3RhcnQoOCwgJzAnKSArICciLGNub25jZT0iJyArIGRpZ2VzdC5fQ05PTkNFICsgJyInKTsNCiAgICB9DQoNCg0KICAgIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7IG9wdGlvbnMuaGVhZGVycyA9IHt9OyB9DQogICAgb3B0aW9ucy5oZWFkZXJzWydBdXRob3JpemF0aW9uJ10gPSByZXQ7DQogICAgcmV0dXJuIChyZXQpOw0KfQ0KDQpmdW5jdGlvbiBodHRwX2RpZ2VzdCgpDQp7DQogICAgdGhpcy5fT2JqZWN0SUQgPSAiaHR0cC1kaWdlc3QiOw0KICAgIHRoaXMuY3JlYXRlID0gZnVuY3Rpb24oKQ0KICAgIHsNCiAgICAgICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PSAxICYmIHR5cGVvZihhcmd1bWVudHNbMF0gPT0gJ29iamVjdCcpKQ0KICAgICAgICB7DQogICAgICAgICAgICByZXR1cm4gKG5ldyBodHRwX2RpZ2VzdF9pbnN0YW5jZShhcmd1bWVudHNbMF0pKTsNCiAgICAgICAgfQ0KICAgICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09IDIgJiYgdHlwZW9mKGFyZ3VtZW50c1swXSkgPT0gJ3N0cmluZycgJiYgdHlwZW9mKGFyZ3VtZW50c1sxXSkgPT0gJ3N0cmluZycpDQogICAgICAgIHsNCiAgICAgICAgICAgIHJldHVybiAobmV3IGh0dHBfZGlnZXN0X2luc3RhbmNlKHt1c2VybmFtZTogYXJndW1lbnRzWzBdLCBwYXNzd29yZDogYXJndW1lbnRzWzFdfSkpOw0KICAgICAgICB9DQogICAgICAgIHRocm93ICgnSW52YWxpZCBQYXJhbWV0ZXJzJyk7DQogICAgfQ0KfQ0KDQpmdW5jdGlvbiBodHRwX2RpZ2VzdF9pbnN0YW5jZShvcHRpb25zKQ0Kew0KICAgIHRoaXMuX09iamVjdElEID0gJ2h0dHAtZGlnZXN0Lmluc3RhbmNlJzsNCiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9uczsNCiAgICB0aGlzLmh0dHAgPSBudWxsOw0KICAgIHRoaXMuX05DID0gMDsNCiAgICB0aGlzLl9DTk9OQ0UgPSByZXF1aXJlKCdodHRwJykuZ2VuZXJhdGVOb25jZSgxNik7DQoNCiAgICB0aGlzLmdldCA9IGZ1bmN0aW9uKHVyaSkNCiAgICB7DQogICAgICAgIHJldHVybiAodGhpcy5yZXF1ZXN0KHVyaSkpOw0KICAgIH0NCiAgICB0aGlzLnJlcXVlc3QgPSBmdW5jdGlvbiAocGFyMSkNCiAgICB7DQogICAgICAgIHZhciBjYWxsZW5kID0gZmFsc2U7DQogICAgICAgIHZhciByZXQgPSBuZXcgd3JpdGFibGUoDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgd3JpdGU6IGZ1bmN0aW9uIChjaHVuaywgZmx1c2gpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZW5kZWQpIHsgdGhyb3cgKCdTdHJlYW0gYWxyZWFkeSBlbmRlZCcpOyB9DQogICAgICAgICAgICAgICAgICAgIGlmKCF0aGlzLl9idWZmZXJlZCkgDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2J1ZmZlcmVkID0gQnVmZmVyLmFsbG9jKGNodW5rLmxlbmd0aCk7DQogICAgICAgICAgICAgICAgICAgICAgICBjaHVuay5jb3B5KHRoaXMuX2J1ZmZlcmVkKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2J1ZmZlcmVkID0gQnVmZmVyLmNvbmNhdChbdGhpcy5fYnVmZmVyZWQsIGNodW5rXSwgdGhpcy5fYnVmZmVyZWQubGVuZ3RoICsgY2h1bmsubGVuZ3RoKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0KSB7IHRoaXMuX3JlcXVlc3Qud3JpdGUoY2h1bmspOyB9DQogICAgICAgICAgICAgICAgICAgIGlmIChmbHVzaCAhPSBudWxsKSB7IGZsdXNoKCk7IH0NCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICh0cnVlKTsNCiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIGZpbmFsOiBmdW5jdGlvbiAoZmx1c2gpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZW5kZWQpIHsgdGhyb3cgKCdTdHJlYW0gYWxyZWFkeSBlbmRlZCcpOyB9DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX2VuZGVkID0gdHJ1ZTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3JlcXVlc3QpIHsgdGhpcy5fcmVxdWVzdC5lbmQoKTsgfQ0KICAgICAgICAgICAgICAgICAgICBpZiAoZmx1c2ggIT0gbnVsbCkgeyBmbHVzaCgpOyB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfSk7DQogICAgICAgIHJldC5fYnVmZmVyZWQgPSBudWxsOw0KICAgICAgICByZXQuX2VuZGVkID0gZmFsc2U7DQogICAgICAgIHN3aXRjaCAodHlwZW9mIChwYXIxKSkNCiAgICAgICAgew0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ0ludmFsaWQgUGFyYW1ldGVyJyk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBjYXNlICdzdHJpbmcnOg0KICAgICAgICAgICAgICAgIHJldC5vcHRpb25zID0gdGhpcy5odHRwLnBhcnNlVXJpKHBhcjEpOw0KICAgICAgICAgICAgICAgIGNhbGxlbmQgPSB0cnVlOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgY2FzZSAnb2JqZWN0JzoNCiAgICAgICAgICAgICAgICByZXQub3B0aW9ucyA9IHBhcjE7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICAgICAgcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyLmNhbGwocmV0LCB0cnVlKQ0KICAgICAgICAgICAgLmNyZWF0ZUV2ZW50KCdyZXNwb25zZScpDQogICAgICAgICAgICAuY3JlYXRlRXZlbnQoJ2Vycm9yJykNCiAgICAgICAgICAgIC5jcmVhdGVFdmVudCgndXBncmFkZScpDQogICAgICAgICAgICAuY3JlYXRlRXZlbnQoJ2NvbnRpbnVlJykNCiAgICAgICAgICAgIC5jcmVhdGVFdmVudCgndGltZW91dCcpOw0KICAgICAgICByZXQuX2RpZ2VzdCA9IHRoaXM7DQoNCiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIHR5cGVvZiAoYXJndW1lbnRzWzFdKSA9PSAnZnVuY3Rpb24nKQ0KICAgICAgICB7DQogICAgICAgICAgICByZXQub25jZSgncmVzcG9uc2UnLCBhcmd1bWVudHNbMV0pOw0KICAgICAgICB9DQoNCiAgICAgICAgLy8NCiAgICAgICAgLy8gQ2hlY2sgaWYgd2UgY2FuIGFkZCBBdXRoSGVhZGVycyBub3cNCiAgICAgICAgLy8NCiAgICAgICAgZ2VuZXJhdGVBdXRoSGVhZGVycyhudWxsLCByZXQub3B0aW9ucywgdGhpcyk7DQoNCiAgICAgICAgLy8gV2hlbiBzb21lYm9keSBob29rcyB1cCBldmVudHMgdG8gZGlnZXN0LmNsaWVudFJlcXVlc3QsIHdlIG5lZWQgdG8gaG9vayB0aGUgcmVhbCBldmVudCBvbiBodHRwLmNsaWVudFJlcXVlc3QNCiAgICAgICAgcmV0Ll9yZXF1ZXN0ID0gdGhpcy5odHRwLnJlcXVlc3QocmV0Lm9wdGlvbnMpOw0KICAgICAgICByZXQuX3JlcXVlc3QuZGlnUmVxdWVzdCA9IHJldDsNCiAgICAgICAgcmV0Lm9uKCdfZXZlbnRIb29rJywgZnVuY3Rpb24gKGV2TmFtZSwgY2FsbGJhY2spDQogICAgICAgIHsNCiAgICAgICAgICAgIGlmIChldk5hbWUgIT0gJ3VwZ3JhZGUnICYmIGV2TmFtZSAhPSAnZXJyb3InICYmIGV2TmFtZSAhPSAnY29udGludWUnICYmIGV2TmFtZSAhPSAndGltZW91dCcgJiYgZXZOYW1lICE9ICdkcmFpbicpIHsgcmV0dXJuOyB9DQogICAgICAgICAgICBpZiAodGhpcy5fcmVxdWVzdC5saXN0ZW5lckNvdW50KGV2TmFtZSkgPT0gMCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICB2YXIgZXZTaW5rID0gZnVuY3Rpb24gX2V2U2luaygpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB2YXIgcGFybXMgPSBbX2V2U2luay5ldmVudE5hbWVdOw0KICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGk9MDtpPGFyZ3VtZW50cy5sZW5ndGg7KytpKSB7cGFybXMucHVzaChhcmd1bWVudHNbaV0pO30NCiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaWdSZXF1ZXN0LmVtaXQuYXBwbHkodGhpcy5kaWdSZXF1ZXN0LCBwYXJtcyk7DQogICAgICAgICAgICAgICAgfTsNCiAgICAgICAgICAgICAgICBldlNpbmsuZXZlbnROYW1lID0gZXZOYW1lOw0KICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3Qub24oZXZOYW1lLCBldlNpbmspOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9KTsNCg0KICAgICAgICByZXQuX3JlcXVlc3Qub25jZSgncmVzcG9uc2UnLCBmdW5jdGlvbiAoaW1zZykNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKGltc2cuc3RhdHVzQ29kZSA9PSA0MDEpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgdmFyIGNhbGxlbmQgPSB0aGlzLmRpZ1JlcXVlc3QuX3JlcXVlc3QuX2NhbGxlbmQ7DQogICAgICAgICAgICAgICAgdmFyIGF1dGggPSBnZW5lcmF0ZUF1dGhIZWFkZXJzKGltc2csIHRoaXMuZGlnUmVxdWVzdC5vcHRpb25zLCB0aGlzLmRpZ1JlcXVlc3QuX2RpZ2VzdCk7DQoNCiAgICAgICAgICAgICAgICB0aGlzLmRpZ1JlcXVlc3QuX3JlcXVlc3QgPSB0aGlzLmRpZ1JlcXVlc3QuX2RpZ2VzdC5odHRwLnJlcXVlc3QodGhpcy5kaWdSZXF1ZXN0Lm9wdGlvbnMpOw0KICAgICAgICAgICAgICAgIHRoaXMuZGlnUmVxdWVzdC5fcmVxdWVzdC5kaWdSZXF1ZXN0ID0gdGhpcy5kaWdSZXF1ZXN0Ow0KICAgICAgICAgICAgICAgIHRoaXMuZGlnUmVxdWVzdC5fcmVxdWVzdC5vbmNlKCdyZXNwb25zZScsIGZ1bmN0aW9uIChpbXNnKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoKGltc2cuc3RhdHVzQ29kZSkNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA0MDE6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaWdSZXF1ZXN0LmVtaXQoJ2Vycm9yJywgJ0RpZ2VzdCBmYWlsZWQgdG9vIG1hbnkgdGltZXMnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaWdSZXF1ZXN0LmVtaXQoJ3Jlc3BvbnNlJywgaW1zZyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICBjaGVja0V2ZW50Rm9yd2FyZGluZyh0aGlzLmRpZ1JlcXVlc3QsICd1cGdyYWRlJyk7DQogICAgICAgICAgICAgICAgY2hlY2tFdmVudEZvcndhcmRpbmcodGhpcy5kaWdSZXF1ZXN0LCAnZXJyb3InKTsNCiAgICAgICAgICAgICAgICBjaGVja0V2ZW50Rm9yd2FyZGluZyh0aGlzLmRpZ1JlcXVlc3QsICdjb250aW51ZScpOw0KICAgICAgICAgICAgICAgIGNoZWNrRXZlbnRGb3J3YXJkaW5nKHRoaXMuZGlnUmVxdWVzdCwgJ3RpbWVvdXQnKTsNCiAgICAgICAgICAgICAgICBjaGVja0V2ZW50Rm9yd2FyZGluZyh0aGlzLmRpZ1JlcXVlc3QsICdkcmFpbicpOw0KICAgICAgICAgICAgICAgIGlmIChjYWxsZW5kKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaWdSZXF1ZXN0Ll9yZXF1ZXN0LmVuZCgpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaWdSZXF1ZXN0Ll9idWZmZXJlZCkgeyB0aGlzLmRpZ1JlcXVlc3QuX3JlcXVlc3Qud3JpdGUodGhpcy5kaWdSZXF1ZXN0Ll9idWZmZXJlZCk7IH0NCiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlnUmVxdWVzdC5fZW5kZWQpIHsgdGhpcy5kaWdSZXF1ZXN0Ll9yZXF1ZXN0LmVuZCgpOyB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHRoaXMuZGlnUmVxdWVzdC5lbWl0KCdyZXNwb25zZScsIGltc2cpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9KTsNCiAgICAgICAgaWYgKGNhbGxlbmQpDQogICAgICAgIHsNCiAgICAgICAgICAgIHJldC5fcmVxdWVzdC5fY2FsbGVuZCA9IHRydWU7IHJldC5fcmVxdWVzdC5lbmQoKTsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlDQogICAgICAgIHsNCiAgICAgICAgICAgIGlmIChyZXQuX2J1ZmZlcmVkKSB7IHJldC5fcmVxdWVzdC53cml0ZShyZXQuX2J1ZmZlcmVkKTsgfQ0KICAgICAgICAgICAgaWYgKHJldC5fZW5kZWQpIHsgcmV0Ll9yZXF1ZXN0LmVuZCgpOyB9DQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuIChyZXQpOw0KICAgIH07DQp9DQoNCg0KbW9kdWxlLmV4cG9ydHMgPSBuZXcgaHR0cF9kaWdlc3QoKTsNCg0K', 'base64').toString());");
+
// Clipboard. Refer to /modules folder for a human readable version
- duk_peval_string_noresult(ctx, "addModule('clipboard', Buffer.from('DQpmdW5jdGlvbiBuYXRpdmVBZGRNb2R1bGUobmFtZSkNCnsNCiAgICB2YXIgdmFsdWUgPSBnZXRKU01vZHVsZShuYW1lKTsNCiAgICB2YXIgcmV0ID0gImR1a19wZXZhbF9zdHJpbmdfbm9yZXN1bHQoY3R4LCBcImFkZE1vZHVsZSgnIiArIG5hbWUgKyAiJywgQnVmZmVyLmZyb20oJyIgKyBCdWZmZXIuZnJvbSh2YWx1ZSkudG9TdHJpbmcoJ2Jhc2U2NCcpICsgIicsICdiYXNlNjQnKS50b1N0cmluZygpKTtcIik7IjsNCiAgICBtb2R1bGUuZXhwb3J0cyhyZXQpOw0KfQ0KDQoNCmZ1bmN0aW9uIHdpbl9yZWFkdGV4dCgpDQp7DQogICAgdmFyIHJldCA9ICcnOw0KICAgIHZhciBDRl9URVhUID0gMTsNCiAgICB2YXIgR00gPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsNCiAgICB2YXIgdXNlcjMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ3VzZXIzMi5kbGwnKTsNCiAgICB2YXIga2VybmVsMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgna2VybmVsMzIuZGxsJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHbG9iYWxBbGxvYycpOw0KICAgIGtlcm5lbDMyLkNyZWF0ZU1ldGhvZCgnR2xvYmFsTG9jaycpOw0KICAgIGtlcm5lbDMyLkNyZWF0ZU1ldGhvZCgnR2xvYmFsVW5sb2NrJyk7DQogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnT3BlbkNsaXBib2FyZCcpOw0KICAgIHVzZXIzMi5DcmVhdGVNZXRob2QoJ0Nsb3NlQ2xpcGJvYXJkJyk7DQogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnR2V0Q2xpcGJvYXJkRGF0YScpOw0KDQogICAgdXNlcjMyLk9wZW5DbGlwYm9hcmQoMCk7DQogICAgdmFyIGggPSB1c2VyMzIuR2V0Q2xpcGJvYXJkRGF0YShDRl9URVhUKTsNCiAgICBpZihoLlZhbCE9MCkNCiAgICB7DQogICAgICAgIHZhciBoYnVmZmVyID0ga2VybmVsMzIuR2xvYmFsTG9jayhoKTsNCiAgICAgICAgcmV0ID0gaGJ1ZmZlci5TdHJpbmc7DQogICAgICAgIGtlcm5lbDMyLkdsb2JhbFVubG9jayhoKTsNCiAgICB9DQogICAgdXNlcjMyLkNsb3NlQ2xpcGJvYXJkKCk7DQogICAgcmV0dXJuIChyZXQpOw0KfQ0KDQpmdW5jdGlvbiB3aW5fY29weXRleHQodHh0KQ0Kew0KICAgIHZhciBHTUVNX01PVkVBQkxFID0gMHgwMDAyOw0KICAgIHZhciBDRl9URVhUID0gMTsNCg0KICAgIHZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOw0KICAgIHZhciB1c2VyMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgndXNlcjMyLmRsbCcpOw0KICAgIHZhciBrZXJuZWwzMiA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdrZXJuZWwzMi5kbGwnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dsb2JhbEFsbG9jJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHbG9iYWxMb2NrJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHbG9iYWxVbmxvY2snKTsNCiAgICB1c2VyMzIuQ3JlYXRlTWV0aG9kKCdPcGVuQ2xpcGJvYXJkJyk7DQogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnRW1wdHlDbGlwYm9hcmQnKTsNCiAgICB1c2VyMzIuQ3JlYXRlTWV0aG9kKCdDbG9zZUNsaXBib2FyZCcpOw0KICAgIHVzZXIzMi5DcmVhdGVNZXRob2QoJ1NldENsaXBib2FyZERhdGEnKTsNCg0KICAgIHZhciBoID0ga2VybmVsMzIuR2xvYmFsQWxsb2MoR01FTV9NT1ZFQUJMRSwgdHh0Lmxlbmd0aCArIDIpOw0KICAgIGguYXV0b0ZyZWUoZmFsc2UpOw0KICAgIHZhciBoYnVmZmVyID0ga2VybmVsMzIuR2xvYmFsTG9jayhoKTsNCiAgICBoYnVmZmVyLmF1dG9GcmVlKGZhbHNlKTsNCiAgICB2YXIgdG1wID0gQnVmZmVyLmFsbG9jKHR4dC5sZW5ndGggKyAxKTsNCiAgICBCdWZmZXIuZnJvbSh0eHQpLmNvcHkodG1wKTsNCiAgICB0bXAuY29weShoYnVmZmVyLkRlcmVmKDAsIHR4dC5sZW5ndGggKyAxKS50b0J1ZmZlcigpKTsNCiAgICBrZXJuZWwzMi5HbG9iYWxVbmxvY2soaCk7DQoNCiAgICB1c2VyMzIuT3BlbkNsaXBib2FyZCgwKTsNCiAgICB1c2VyMzIuRW1wdHlDbGlwYm9hcmQoKTsNCiAgICB1c2VyMzIuU2V0Q2xpcGJvYXJkRGF0YShDRl9URVhULCBoKTsNCiAgICB1c2VyMzIuQ2xvc2VDbGlwYm9hcmQoKTsNCn0NCg0Kc3dpdGNoKHByb2Nlc3MucGxhdGZvcm0pDQp7DQogICAgY2FzZSAnd2luMzInOg0KICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHdpbl9jb3B5dGV4dDsNCiAgICAgICAgbW9kdWxlLmV4cG9ydHMucmVhZCA9IHdpbl9yZWFkdGV4dDsNCiAgICAgICAgYnJlYWs7DQogICAgY2FzZSAnbGludXgnOg0KICAgICAgICBicmVhazsNCiAgICBjYXNlICdkYXJ3aW4nOg0KICAgICAgICBicmVhazsNCn0NCm1vZHVsZS5leHBvcnRzLm5hdGl2ZUFkZE1vZHVsZSA9IG5hdGl2ZUFkZE1vZHVsZTs=', 'base64').toString());");
-
+ duk_peval_string_noresult(ctx, "addModule('clipboard', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTkgSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCgpmdW5jdGlvbiBuYXRpdmVBZGRNb2R1bGUobmFtZSkKewogICAgdmFyIHZhbHVlID0gZ2V0SlNNb2R1bGUobmFtZSk7CiAgICB2YXIgcmV0ID0gImR1a19wZXZhbF9zdHJpbmdfbm9yZXN1bHQoY3R4LCBcImFkZE1vZHVsZSgnIiArIG5hbWUgKyAiJywgQnVmZmVyLmZyb20oJyIgKyBCdWZmZXIuZnJvbSh2YWx1ZSkudG9TdHJpbmcoJ2Jhc2U2NCcpICsgIicsICdiYXNlNjQnKS50b1N0cmluZygpKTtcIik7IjsKICAgIG1vZHVsZS5leHBvcnRzKHJldCk7Cn0KCgpmdW5jdGlvbiB3aW5fcmVhZHRleHQoKQp7CiAgICB2YXIgcmV0ID0gJyc7CiAgICB2YXIgQ0ZfVEVYVCA9IDE7CiAgICB2YXIgR00gPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsKICAgIHZhciB1c2VyMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgndXNlcjMyLmRsbCcpOwogICAgdmFyIGtlcm5lbDMyID0gR00uQ3JlYXRlTmF0aXZlUHJveHkoJ2tlcm5lbDMyLmRsbCcpOwogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHbG9iYWxBbGxvYycpOwogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdHbG9iYWxMb2NrJyk7CiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dsb2JhbFVubG9jaycpOwogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnT3BlbkNsaXBib2FyZCcpOwogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnQ2xvc2VDbGlwYm9hcmQnKTsKICAgIHVzZXIzMi5DcmVhdGVNZXRob2QoJ0dldENsaXBib2FyZERhdGEnKTsKCiAgICB1c2VyMzIuT3BlbkNsaXBib2FyZCgwKTsKICAgIHZhciBoID0gdXNlcjMyLkdldENsaXBib2FyZERhdGEoQ0ZfVEVYVCk7CiAgICBpZihoLlZhbCE9MCkKICAgIHsKICAgICAgICB2YXIgaGJ1ZmZlciA9IGtlcm5lbDMyLkdsb2JhbExvY2soaCk7CiAgICAgICAgcmV0ID0gaGJ1ZmZlci5TdHJpbmc7CiAgICAgICAga2VybmVsMzIuR2xvYmFsVW5sb2NrKGgpOwogICAgfQogICAgdXNlcjMyLkNsb3NlQ2xpcGJvYXJkKCk7CiAgICByZXR1cm4gKHJldCk7Cn0KCmZ1bmN0aW9uIHdpbl9jb3B5dGV4dCh0eHQpCnsKICAgIHZhciBHTUVNX01PVkVBQkxFID0gMHgwMDAyOwogICAgdmFyIENGX1RFWFQgPSAxOwoKICAgIHZhciBHTSA9IHJlcXVpcmUoJ19HZW5lcmljTWFyc2hhbCcpOwogICAgdmFyIHVzZXIzMiA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCd1c2VyMzIuZGxsJyk7CiAgICB2YXIga2VybmVsMzIgPSBHTS5DcmVhdGVOYXRpdmVQcm94eSgna2VybmVsMzIuZGxsJyk7CiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dsb2JhbEFsbG9jJyk7CiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dsb2JhbExvY2snKTsKICAgIGtlcm5lbDMyLkNyZWF0ZU1ldGhvZCgnR2xvYmFsVW5sb2NrJyk7CiAgICB1c2VyMzIuQ3JlYXRlTWV0aG9kKCdPcGVuQ2xpcGJvYXJkJyk7CiAgICB1c2VyMzIuQ3JlYXRlTWV0aG9kKCdFbXB0eUNsaXBib2FyZCcpOwogICAgdXNlcjMyLkNyZWF0ZU1ldGhvZCgnQ2xvc2VDbGlwYm9hcmQnKTsKICAgIHVzZXIzMi5DcmVhdGVNZXRob2QoJ1NldENsaXBib2FyZERhdGEnKTsKCiAgICB2YXIgaCA9IGtlcm5lbDMyLkdsb2JhbEFsbG9jKEdNRU1fTU9WRUFCTEUsIHR4dC5sZW5ndGggKyAyKTsKICAgIGguYXV0b0ZyZWUoZmFsc2UpOwogICAgdmFyIGhidWZmZXIgPSBrZXJuZWwzMi5HbG9iYWxMb2NrKGgpOwogICAgaGJ1ZmZlci5hdXRvRnJlZShmYWxzZSk7CiAgICB2YXIgdG1wID0gQnVmZmVyLmFsbG9jKHR4dC5sZW5ndGggKyAxKTsKICAgIEJ1ZmZlci5mcm9tKHR4dCkuY29weSh0bXApOwogICAgdG1wLmNvcHkoaGJ1ZmZlci5EZXJlZigwLCB0eHQubGVuZ3RoICsgMSkudG9CdWZmZXIoKSk7CiAgICBrZXJuZWwzMi5HbG9iYWxVbmxvY2soaCk7CgogICAgdXNlcjMyLk9wZW5DbGlwYm9hcmQoMCk7CiAgICB1c2VyMzIuRW1wdHlDbGlwYm9hcmQoKTsKICAgIHVzZXIzMi5TZXRDbGlwYm9hcmREYXRhKENGX1RFWFQsIGgpOwogICAgdXNlcjMyLkNsb3NlQ2xpcGJvYXJkKCk7Cn0KCnN3aXRjaChwcm9jZXNzLnBsYXRmb3JtKQp7CiAgICBjYXNlICd3aW4zMic6CiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB3aW5fY29weXRleHQ7CiAgICAgICAgbW9kdWxlLmV4cG9ydHMucmVhZCA9IHdpbl9yZWFkdGV4dDsKICAgICAgICBicmVhazsKICAgIGNhc2UgJ2xpbnV4JzoKICAgICAgICBicmVhazsKICAgIGNhc2UgJ2Rhcndpbic6CiAgICAgICAgYnJlYWs7Cn0KbW9kdWxlLmV4cG9ydHMubmF0aXZlQWRkTW9kdWxlID0gbmF0aXZlQWRkTW9kdWxlO/==', 'base64').toString());");
+
// Promise: This is very important, as it is used everywhere. Refer to /modules folder to see a human readable version of promise.js
duk_peval_string_noresult(ctx, "addModule('promise', Buffer.from('LyoKQ29weXJpZ2h0IDIwMTggSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCnZhciByZWZUYWJsZSA9IHt9OwoKZnVuY3Rpb24gZXZlbnRfc3dpdGNoZXJfaGVscGVyKGRlc2lyZWRfY2FsbGVlLCB0YXJnZXQpCnsKICAgIHRoaXMuX09iamVjdElEID0gJ2V2ZW50X3N3aXRjaGVyJzsKICAgIHRoaXMuZnVuYyA9IGZ1bmN0aW9uIGZ1bmMoKQogICAgewogICAgICAgIHZhciBhcmdzID0gW107CiAgICAgICAgZm9yKHZhciBpIGluIGFyZ3VtZW50cykKICAgICAgICB7CiAgICAgICAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbaV0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKGZ1bmMudGFyZ2V0LmFwcGx5KGZ1bmMuZGVzaXJlZCwgYXJncykpOwogICAgfTsKICAgIHRoaXMuZnVuYy5kZXNpcmVkID0gZGVzaXJlZF9jYWxsZWU7CiAgICB0aGlzLmZ1bmMudGFyZ2V0ID0gdGFyZ2V0OwogICAgdGhpcy5mdW5jLnNlbGYgPSB0aGlzOwp9CmZ1bmN0aW9uIGV2ZW50X3N3aXRjaGVyKGRlc2lyZWRfY2FsbGVlLCB0YXJnZXQpCnsKICAgIHJldHVybiAobmV3IGV2ZW50X3N3aXRjaGVyX2hlbHBlcihkZXNpcmVkX2NhbGxlZSwgdGFyZ2V0KSk7Cn0KCmZ1bmN0aW9uIFByb21pc2UocHJvbWlzZUZ1bmMpCnsKICAgIHRoaXMuX09iamVjdElEID0gJ3Byb21pc2UnOwogICAgdGhpcy5wcm9taXNlID0gdGhpczsKICAgIHRoaXMuX2ludGVybmFsID0geyBfT2JqZWN0SUQ6ICdwcm9taXNlLmludGVybmFsJywgcHJvbWlzZTogdGhpcywgZnVuYzogcHJvbWlzZUZ1bmMsIGNvbXBsZXRlZDogZmFsc2UsIGVycm9yczogZmFsc2UsIGNvbXBsZXRlZEFyZ3M6IFtdIH07CiAgICByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzLl9pbnRlcm5hbCk7CiAgICB0aGlzLl9pbnRlcm5hbC5vbignX2V2ZW50SG9vaycsIGZ1bmN0aW9uIChldmVudE5hbWUsIGV2ZW50Q2FsbGJhY2spCiAgICB7CiAgICAgICAgLy9jb25zb2xlLmxvZygnaG9vaycsIGV2ZW50TmFtZSwgJ2Vycm9ycy8nICsgdGhpcy5lcnJvcnMgKyAnIGNvbXBsZXRlZC8nICsgdGhpcy5jb21wbGV0ZWQpOwogICAgICAgIHZhciByID0gbnVsbDsKCiAgICAgICAgaWYgKGV2ZW50TmFtZSA9PSAncmVzb2x2ZWQnICYmICF0aGlzLmVycm9ycyAmJiB0aGlzLmNvbXBsZXRlZCkKICAgICAgICB7CiAgICAgICAgICAgIHIgPSBldmVudENhbGxiYWNrLmFwcGx5KHRoaXMsIHRoaXMuY29tcGxldGVkQXJncyk7CiAgICAgICAgICAgIGlmKHIhPW51bGwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRoaXMuZW1pdF9yZXR1cm5WYWx1ZSgncmVzb2x2ZWQnLCByKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoZXZlbnROYW1lID09ICdyZWplY3RlZCcgJiYgdGhpcy5lcnJvcnMgJiYgdGhpcy5jb21wbGV0ZWQpCiAgICAgICAgewogICAgICAgICAgICBldmVudENhbGxiYWNrLmFwcGx5KHRoaXMsIHRoaXMuY29tcGxldGVkQXJncyk7CiAgICAgICAgfQogICAgICAgIGlmIChldmVudE5hbWUgPT0gJ3NldHRsZWQnICYmIHRoaXMuY29tcGxldGVkKQogICAgICAgIHsKICAgICAgICAgICAgZXZlbnRDYWxsYmFjay5hcHBseSh0aGlzLCBbXSk7CiAgICAgICAgfQogICAgfSk7CiAgICB0aGlzLl9pbnRlcm5hbC5yZXNvbHZlciA9IGZ1bmN0aW9uIF9yZXNvbHZlcigpCiAgICB7CiAgICAgICAgX3Jlc29sdmVyLl9zZWxmLmVycm9ycyA9IGZhbHNlOwogICAgICAgIF9yZXNvbHZlci5fc2VsZi5jb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIF9yZXNvbHZlci5fc2VsZi5jb21wbGV0ZWRBcmdzID0gW107CiAgICAgICAgdmFyIGFyZ3MgPSBbJ3Jlc29sdmVkJ107CiAgICAgICAgaWYgKHRoaXMuZW1pdF9yZXR1cm5WYWx1ZSAmJiB0aGlzLmVtaXRfcmV0dXJuVmFsdWUoJ3Jlc29sdmVkJykgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIF9yZXNvbHZlci5fc2VsZi5jb21wbGV0ZWRBcmdzLnB1c2godGhpcy5lbWl0X3JldHVyblZhbHVlKCdyZXNvbHZlZCcpKTsKICAgICAgICAgICAgYXJncy5wdXNoKHRoaXMuZW1pdF9yZXR1cm5WYWx1ZSgncmVzb2x2ZWQnKSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIGZvciAodmFyIGEgaW4gYXJndW1lbnRzKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBfcmVzb2x2ZXIuX3NlbGYuY29tcGxldGVkQXJncy5wdXNoKGFyZ3VtZW50c1thXSk7CiAgICAgICAgICAgICAgICBhcmdzLnB1c2goYXJndW1lbnRzW2FdKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBfcmVzb2x2ZXIuX3NlbGYuZW1pdC5hcHBseShfcmVzb2x2ZXIuX3NlbGYsIGFyZ3MpOwogICAgICAgIF9yZXNvbHZlci5fc2VsZi5lbWl0KCdzZXR0bGVkJyk7CiAgICB9OwogICAgdGhpcy5faW50ZXJuYWwucmVqZWN0b3IgPSBmdW5jdGlvbiBfcmVqZWN0b3IoKQogICAgewogICAgICAgIF9yZWplY3Rvci5fc2VsZi5lcnJvcnMgPSB0cnVlOwogICAgICAgIF9yZWplY3Rvci5fc2VsZi5jb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIF9yZWplY3Rvci5fc2VsZi5jb21wbGV0ZWRBcmdzID0gW107CiAgICAgICAgdmFyIGFyZ3MgPSBbJ3JlamVjdGVkJ107CiAgICAgICAgZm9yICh2YXIgYSBpbiBhcmd1bWVudHMpCiAgICAgICAgewogICAgICAgICAgICBfcmVqZWN0b3IuX3NlbGYuY29tcGxldGVkQXJncy5wdXNoKGFyZ3VtZW50c1thXSk7CiAgICAgICAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbYV0pOwogICAgICAgIH0KCiAgICAgICAgX3JlamVjdG9yLl9zZWxmLmVtaXQuYXBwbHkoX3JlamVjdG9yLl9zZWxmLCBhcmdzKTsKICAgICAgICBfcmVqZWN0b3IuX3NlbGYuZW1pdCgnc2V0dGxlZCcpOwogICAgfTsKICAgIHRoaXMuY2F0Y2ggPSBmdW5jdGlvbihmdW5jKQogICAgewogICAgICAgIHRoaXMuX2ludGVybmFsLm9uY2UoJ3JlamVjdGVkJywgZXZlbnRfc3dpdGNoZXIodGhpcywgZnVuYykuZnVuYyk7CiAgICB9CiAgICB0aGlzLmZpbmFsbHkgPSBmdW5jdGlvbiAoZnVuYykKICAgIHsKICAgICAgICB0aGlzLl9pbnRlcm5hbC5vbmNlKCdzZXR0bGVkJywgZXZlbnRfc3dpdGNoZXIodGhpcywgZnVuYykuZnVuYyk7CiAgICB9OwogICAgdGhpcy50aGVuID0gZnVuY3Rpb24gKHJlc29sdmVkLCByZWplY3RlZCkKICAgIHsKICAgICAgICBpZiAocmVzb2x2ZWQpIHsgdGhpcy5faW50ZXJuYWwub25jZSgncmVzb2x2ZWQnLCBldmVudF9zd2l0Y2hlcih0aGlzLCByZXNvbHZlZCkuZnVuYyk7IH0KICAgICAgICBpZiAocmVqZWN0ZWQpIHsgdGhpcy5faW50ZXJuYWwub25jZSgncmVqZWN0ZWQnLCBldmVudF9zd2l0Y2hlcih0aGlzLCByZWplY3RlZCkuZnVuYyk7IH0KCiAgICAgICAgdmFyIHJldFZhbCA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyLCBqKSB7IH0pOwogICAgICAgIHRoaXMuX2ludGVybmFsLm9uY2UoJ3Jlc29sdmVkJywgcmV0VmFsLl9pbnRlcm5hbC5yZXNvbHZlcik7CiAgICAgICAgdGhpcy5faW50ZXJuYWwub25jZSgncmVqZWN0ZWQnLCByZXRWYWwuX2ludGVybmFsLnJlamVjdG9yKTsKICAgICAgICByZXRWYWwucGFyZW50UHJvbWlzZSA9IHRoaXM7CiAgICAgICAgcmV0dXJuIChyZXRWYWwpOwogICAgfTsKCiAgICB0aGlzLl9pbnRlcm5hbC5yZXNvbHZlci5fc2VsZiA9IHRoaXMuX2ludGVybmFsOwogICAgdGhpcy5faW50ZXJuYWwucmVqZWN0b3IuX3NlbGYgPSB0aGlzLl9pbnRlcm5hbDs7CgogICAgdHJ5CiAgICB7CiAgICAgICAgcHJvbWlzZUZ1bmMuY2FsbCh0aGlzLCB0aGlzLl9pbnRlcm5hbC5yZXNvbHZlciwgdGhpcy5faW50ZXJuYWwucmVqZWN0b3IpOwogICAgfQogICAgY2F0Y2goZSkKICAgIHsKICAgICAgICB0aGlzLl9pbnRlcm5hbC5lcnJvcnMgPSB0cnVlOwogICAgICAgIHRoaXMuX2ludGVybmFsLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgdGhpcy5faW50ZXJuYWwuY29tcGxldGVkQXJncyA9IFtlXTsKICAgICAgICB0aGlzLl9pbnRlcm5hbC5lbWl0KCdyZWplY3RlZCcsIGUpOwogICAgICAgIHRoaXMuX2ludGVybmFsLmVtaXQoJ3NldHRsZWQnKTsKICAgIH0KCiAgICBpZighdGhpcy5faW50ZXJuYWwuY29tcGxldGVkKQogICAgewogICAgICAgIC8vIFNhdmUgcmVmZXJlbmNlIG9mIHRoaXMgb2JqZWN0CiAgICAgICAgcmVmVGFibGVbdGhpcy5faW50ZXJuYWwuX2hhc2hDb2RlKCldID0gdGhpcy5faW50ZXJuYWw7CiAgICAgICAgdGhpcy5faW50ZXJuYWwub25jZSgnc2V0dGxlZCcsIGZ1bmN0aW9uICgpIHsgcmVmVGFibGVbdGhpcy5faGFzaENvZGUoKV0gPSBudWxsOyB9KTsKICAgIH0KfQoKUHJvbWlzZS5yZXNvbHZlID0gZnVuY3Rpb24gcmVzb2x2ZSgpCnsKICAgIHZhciByZXRWYWwgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAociwgaikgeyB9KTsKICAgIHZhciBhcmdzID0gW107CiAgICBmb3IgKHZhciBpIGluIGFyZ3VtZW50cykKICAgIHsKICAgICAgICBhcmdzLnB1c2goYXJndW1lbnRzW2ldKTsKICAgIH0KICAgIHJldFZhbC5faW50ZXJuYWwucmVzb2x2ZXIuYXBwbHkocmV0VmFsLl9pbnRlcm5hbCwgYXJncyk7CiAgICByZXR1cm4gKHJldFZhbCk7Cn07ClByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24gcmVqZWN0KCkgewogICAgdmFyIHJldFZhbCA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyLCBqKSB7IH0pOwogICAgdmFyIGFyZ3MgPSBbXTsKICAgIGZvciAodmFyIGkgaW4gYXJndW1lbnRzKSB7CiAgICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7CiAgICB9CiAgICByZXRWYWwuX2ludGVybmFsLnJlamVjdG9yLmFwcGx5KHJldFZhbC5faW50ZXJuYWwsIGFyZ3MpOwogICAgcmV0dXJuIChyZXRWYWwpOwp9OwpQcm9taXNlLmFsbCA9IGZ1bmN0aW9uIGFsbChwcm9taXNlTGlzdCkKewogICAgdmFyIHJldCA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXMsIHJlaikKICAgIHsKICAgICAgICB0aGlzLl9fcmVqZWN0b3IgPSByZWo7CiAgICAgICAgdGhpcy5fX3Jlc29sdmVyID0gcmVzOwogICAgICAgIHRoaXMuX19wcm9taXNlTGlzdCA9IHByb21pc2VMaXN0OwogICAgICAgIHRoaXMuX19kb25lID0gZmFsc2U7CiAgICAgICAgdGhpcy5fX2NvdW50ID0gMDsKICAgIH0pOwoKICAgIGZvciAodmFyIGkgaW4gcHJvbWlzZUxpc3QpCiAgICB7CiAgICAgICAgcHJvbWlzZUxpc3RbaV0udGhlbihmdW5jdGlvbiAoKQogICAgICAgIHsKICAgICAgICAgICAgLy8gU3VjY2VzcwogICAgICAgICAgICBpZigrK3JldC5fX2NvdW50ID09IHJldC5fX3Byb21pc2VMaXN0Lmxlbmd0aCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0Ll9fZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICByZXQuX19yZXNvbHZlcihyZXQuX19wcm9taXNlTGlzdCk7CiAgICAgICAgICAgIH0KICAgICAgICB9LCBmdW5jdGlvbiAoYXJnKQogICAgICAgIHsKICAgICAgICAgICAgLy8gRmFpbHVyZQogICAgICAgICAgICBpZighcmV0Ll9fZG9uZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0Ll9fZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICByZXQuX19yZWplY3RvcihhcmcpOwogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICB9CiAgICBpZiAocHJvbWlzZUxpc3QubGVuZ3RoID09IDApCiAgICB7CiAgICAgICAgcmV0Ll9fcmVzb2x2ZXIocHJvbWlzZUxpc3QpOwogICAgfQogICAgcmV0dXJuIChyZXQpOwp9OwoKbW9kdWxlLmV4cG9ydHMgPSBQcm9taXNlOw==', 'base64').toString());");
@@ -1898,11 +1901,76 @@ void ILibDuktape_ChainViewer_Push(duk_context *ctx, void *chain)
ILibPrependToChain(chain, (void*)t);
}
+duk_ret_t ILibDuktape_httpHeaders(duk_context *ctx)
+{
+ ILibHTTPPacket *packet = NULL;
+ packetheader_field_node *node;
+ int headersOnly = duk_get_top(ctx) > 1 ? (duk_require_boolean(ctx, 1) ? 1 : 0) : 0;
+
+ duk_size_t bufferLen;
+ char *buffer = (char*)Duktape_GetBuffer(ctx, 0, &bufferLen);
+
+ packet = ILibParsePacketHeader(buffer, 0, (int)bufferLen);
+ if (packet == NULL) { return(ILibDuktape_Error(ctx, "http-headers(): Error parsing data")); }
+
+ if (headersOnly == 0)
+ {
+ duk_push_object(ctx);
+ if (packet->Directive != NULL)
+ {
+ duk_push_lstring(ctx, packet->Directive, packet->DirectiveLength);
+ duk_put_prop_string(ctx, -2, "method");
+ duk_push_lstring(ctx, packet->DirectiveObj, packet->DirectiveObjLength);
+ duk_put_prop_string(ctx, -2, "url");
+ }
+ else
+ {
+ duk_push_int(ctx, packet->StatusCode);
+ duk_put_prop_string(ctx, -2, "statusCode");
+ duk_push_lstring(ctx, packet->StatusData, packet->StatusDataLength);
+ duk_put_prop_string(ctx, -2, "statusMessage");
+ }
+ if (packet->VersionLength == 3)
+ {
+ duk_push_object(ctx);
+ duk_push_lstring(ctx, packet->Version, 1);
+ duk_put_prop_string(ctx, -2, "major");
+ duk_push_lstring(ctx, packet->Version + 2, 1);
+ duk_put_prop_string(ctx, -2, "minor");
+ duk_put_prop_string(ctx, -2, "version");
+ }
+ }
+
+ duk_push_object(ctx); // headers
+ node = packet->FirstField;
+ while (node != NULL)
+ {
+ duk_push_lstring(ctx, node->Field, node->FieldLength); // [str]
+ duk_get_prop_string(ctx, -1, "toLowerCase"); // [str][toLower]
+ duk_swap_top(ctx, -2); // [toLower][this]
+ duk_call_method(ctx, 0); // [result]
+ duk_push_lstring(ctx, node->FieldData, node->FieldDataLength);
+ duk_put_prop(ctx, -3);
+ node = node->NextField;
+ }
+ if (headersOnly == 0)
+ {
+ duk_put_prop_string(ctx, -2, "headers");
+ }
+ ILibDestructPacket(packet);
+ return(1);
+}
+void ILibDuktape_httpHeaders_PUSH(duk_context *ctx, void *chain)
+{
+ duk_push_c_function(ctx, ILibDuktape_httpHeaders, DUK_VARARGS);
+}
void ILibDuktape_Polyfills_Init(duk_context *ctx)
{
ILibDuktape_ModSearch_AddHandler(ctx, "queue", ILibDuktape_Queue_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "DynamicBuffer", ILibDuktape_DynamicBuffer_Push);
ILibDuktape_ModSearch_AddHandler(ctx, "stream", ILibDuktape_Stream_Init);
+ ILibDuktape_ModSearch_AddHandler(ctx, "http-headers", ILibDuktape_httpHeaders_PUSH);
+
#ifndef MICROSTACK_NOTLS
ILibDuktape_ModSearch_AddHandler(ctx, "pkcs7", ILibDuktape_PKCS7_Push);
#endif
@@ -1913,6 +1981,7 @@ void ILibDuktape_Polyfills_Init(duk_context *ctx)
#endif
ILibDuktape_ModSearch_AddHandler(ctx, "ChainViewer", ILibDuktape_ChainViewer_Push);
+
// Global Polyfills
duk_push_global_object(ctx); // [g]
diff --git a/microscript/ILibDuktape_ScriptContainer.c b/microscript/ILibDuktape_ScriptContainer.c
index 55882ea..0555e4b 100644
--- a/microscript/ILibDuktape_ScriptContainer.c
+++ b/microscript/ILibDuktape_ScriptContainer.c
@@ -1845,7 +1845,6 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_conte
if ((securityFlags & SCRIPT_ENGINE_NO_NETWORK_ACCESS) == 0)
{
ILibDuktape_WebRTC_Init(ctx); // WebRTC library (browser api)
- ILibDuktape_http_init(ctx, chain); // HTTP-Digest library (node api)
ILibDuktape_net_init(ctx, chain); // Network library (node api)
ILibDuktape_DGram_Init(ctx); // Datagram Sockets
ILibDuktape_HttpStream_Init(ctx); // HTTP Library (node api)
diff --git a/microscript/ILibDuktape_http.c b/microscript/ILibDuktape_http.c
deleted file mode 100644
index 0e70d28..0000000
--- a/microscript/ILibDuktape_http.c
+++ /dev/null
@@ -1,1131 +0,0 @@
-/*
-Copyright 2006 - 2018 Intel Corporation
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-#include "ILibDuktape_http.h"
-#include "ILibDuktapeModSearch.h"
-#include "ILibDuktape_Helpers.h"
-#include "ILibDuktape_EventEmitter.h"
-#include "ILibDuktape_DuplexStream.h"
-#include "microstack/ILibRemoteLogging.h"
-#include "microstack/ILibCrypto.h"
-
-#define DIGEST_USERNAME "\xFF_DigestUsername"
-#define DIGEST_PASSWORD "\xFF_DigestPassword"
-#define DIGEST_AUTHTOKEN "\xFF_DigestAuthToken"
-#define HTTP_DIGEST "\xFF_HTTP_DIGEST"
-#define DIGEST_CLIENT_REQUEST "\xFF_DIGEST_CLIENT_REQUEST"
-#define HTTP_CLIENTREQUEST_DATAPTR "\xFF_CLIENTREQUEST_DATAPTR"
-#define CLIENTREQUEST_EVENT_NAME "\xFF_CLIENTREQUEST_EVENT_NAME"
-#define CLIENTREQUEST_IMSG_RSPTR "\xFF_CLIENTREQUEST_IMSG_RSPTR"
-
-#define DIGEST2CNONCE "\xFF_DIGEST2CNONCE"
-#define DIGEST2NC "\xFF_DIGEST2NONCECOUNT"
-#define DIGEST2WWWAUTH "\xFF_DIGEST2WWWAUTH"
-
-#define DIGESTCLIENTREQUEST_END_CALLED "\xFF_DIGESTCLIENTREQUEST_END_CALLED"
-#define DIGESTCLIENTREQUEST_CONTINUE "\xFF_DIGESTCLIENTREQUEST_CONTINUE"
-#define DIGESTCLIENTREQUEST_TmpBuffer "\xFF_DIGESTCLIENTREQUEST_TmpBuffer"
-#define DIGESTCLIENTREQUEST_DIGEST "\xFF_DIGESTCLIENTREQUEST_DIGEST"
-
-duk_ret_t ILibDuktape_httpDigest_clientRequest_response2(duk_context *ctx)
-{
- duk_push_current_function(ctx);
- duk_get_prop_string(ctx, -1, "digestClientRequest");// [digestClientRequest]
-
- int statusCode = Duktape_GetIntPropertyValue(ctx, 0, "statusCode", 0);
-
- if (statusCode == 200)
- {
- duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "response"); // [emit][this][response]
- duk_dup(ctx, 0); // [emit][this][response][imsg]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error dispatching response event"); }
- }
- else
- {
- duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "error"); // [emit][this][error]
- duk_dup(ctx, 0); // [emit][this][error][imsg]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error dispatching response event"); }
- }
-
- return(0);
-}
-
-duk_ret_t ILibDuktape_httpDigest_clientRequest_onDrain(duk_context *ctx)
-{
- duk_push_this(ctx); // [clientRequest]
- if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
- {
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [clientRequest][digestClientRequest]
- if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
- {
- duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS);
- ILibDuktape_WritableStream_Ready((ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL));
- }
- }
- return(0);
-}
-
-duk_ret_t ILibDuktape_httpDigest_clientRequest_propagateEvent(duk_context *ctx)
-{
- int i, nargs = duk_get_top(ctx);
- duk_push_current_function(ctx); // [func]
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [func][digestClientRequest]
- duk_get_prop_string(ctx, -1, "emit"); // [func][digestClientRequest][emit]
- duk_swap_top(ctx, -2); // [func][emit][this]
- duk_get_prop_string(ctx, -3, CLIENTREQUEST_EVENT_NAME); // [func][emit][this][eventName]
- for (i = 0; i < nargs; ++i)
- {
- duk_dup(ctx, i); // [func][emit][this][eventName][params]
- }
- if (duk_pcall_method(ctx, 1 + nargs) != 0) { return(ILibDuktape_Error(ctx, "propagateEvent() Error")); }
- return(0);
-}
-
-void ILibDuktape_httpDigest_clientRequest_IncomingMessage_PauseHandler(ILibDuktape_readableStream *sender, void *user)
-{
- duk_push_heapptr(sender->ctx, user); // [imsg]
- duk_get_prop_string(sender->ctx, -1, "pause"); // [imsg][pause]
- duk_swap_top(sender->ctx, -2); // [pause][this]
- if (duk_pcall_method(sender->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(sender->ctx, "ILibDuktape_httpDigest_clientRequest_IncomingMessage_PauseHandler: Error Invoking Pause on ClientRequest: "); }
- duk_pop(sender->ctx); // ...
-}
-void ILibDuktape_httpDigest_clientRequest_IncomingMessage_ResumeHandler(ILibDuktape_readableStream *sender, void *user)
-{
- duk_push_heapptr(sender->ctx, user); // [imsg]
- duk_get_prop_string(sender->ctx, -1, "resume"); // [imsg][pause]
- duk_swap_top(sender->ctx, -2); // [pause][this]
- if (duk_pcall_method(sender->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(sender->ctx, "ILibDuktape_httpDigest_clientRequest_IncomingMessage_ResumeHandler: Error Invoking Resume on ClientRequest: "); }
- duk_pop(sender->ctx); // ...
-}
-duk_ret_t ILibDuktape_httpDigest_clientRequest_OnData(duk_context *ctx)
-{
- // http.IncomingMessage.data
-
- duk_push_current_function(ctx);
- duk_get_prop_string(ctx, -1, CLIENTREQUEST_IMSG_RSPTR);
- ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
- duk_size_t bufferLen;
- char *buffer;
-
- buffer = Duktape_GetBuffer(ctx, 0, &bufferLen);
- ILibDuktape_readableStream_WriteData(rs, buffer, (int)bufferLen);
-
- return(0);
-}
-duk_ret_t ILibDuktape_httpDigest_clientRequest_OnEnd(duk_context *ctx)
-{
- duk_push_current_function(ctx);
- duk_get_prop_string(ctx, -1, CLIENTREQUEST_IMSG_RSPTR);
- ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
- ILibDuktape_readableStream_WriteEnd(rs);
- return(0);
-}
-
-extern void ILibWebServer_Digest_ParseAuthenticationHeader(void* table, char* value, int valueLen);
-char *ILibDuktape_httpDigest_generateAuthenticationHeader(duk_context *ctx, void *digestObj, void *optionsObj)
-{
- int top = duk_get_top(ctx);
- int NC = 0;
- char *CNONCE = NULL;
-
- char *wwwauth, *username, *password;
- char *method, *path;
- duk_size_t wwwauthLen;
- void *ReservedMemory = ILibMemory_AllocateA(8000);
- void *table = ILibInitHashTree_CaseInSensitiveEx(ReservedMemory);
- int tmpLen;
- char result1[33];
- char result2[33];
- char result3[33];
-
- duk_push_heapptr(ctx, digestObj); // [digest]
- wwwauth = (char*)Duktape_GetStringPropertyValueEx(ctx, -1, DIGEST2WWWAUTH, NULL, &wwwauthLen);
- username = (char*)Duktape_GetStringPropertyValue(ctx, -1, DIGEST_USERNAME, NULL);
- password = (char*)Duktape_GetStringPropertyValue(ctx, -1, DIGEST_PASSWORD, NULL);
- if (!duk_has_prop_string(ctx, -1, DIGEST_AUTHTOKEN))
- {
- if (wwwauth == NULL || username == NULL || password == NULL) { duk_pop(ctx); return(NULL); }
- }
- duk_push_heapptr(ctx, optionsObj); // [digest][options]
- method = (char*)Duktape_GetStringPropertyValue(ctx, -1, "method", NULL);
- path = (char*)Duktape_GetStringPropertyValue(ctx, -1, "path", NULL);
- duk_pop(ctx); // [digest]
-
- ILibWebServer_Digest_ParseAuthenticationHeader(table, wwwauth, (int)wwwauthLen);
- char *realm, *nonce, *opaque, *qop;
- int realmLen, nonceLen, opaqueLen, qopLen;
-
- ILibGetEntryEx(table, "realm", 5, (void**)&realm, &realmLen); if (realmLen > 0) { realm[realmLen] = 0; }
- ILibGetEntryEx(table, "nonce", 5, (void**)&nonce, &nonceLen); if (nonceLen > 0) { nonce[nonceLen] = 0; }
- ILibGetEntryEx(table, "opaque", 6, (void**)&opaque, &opaqueLen); if (opaqueLen > 0) { opaque[opaqueLen] = 0; }
- ILibGetEntryEx(table, "qop", 3, (void**)&qop, &qopLen); if (qopLen > 0) { qop[qopLen] = 0; }
-
- if (duk_has_prop_string(ctx, -1, DIGEST_AUTHTOKEN))
- {
- duk_size_t authTokenLen;
- char *authToken = Duktape_GetStringPropertyValueEx(ctx, -1, DIGEST_AUTHTOKEN, NULL, &authTokenLen);
-
- if (authTokenLen < sizeof(result1))
- {
- memcpy_s(result1, sizeof(result1), authToken, authTokenLen);
- result1[32] = 0;
- username = "admin";
- tmpLen = (int)authTokenLen;
- }
- }
- else
- {
- tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", username, realm, password);
- util_md5hex(ILibScratchPad2, tmpLen, result1);
- }
- tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s", method, path);
- util_md5hex(ILibScratchPad2, tmpLen, result2);
-
- if (qop == NULL)
- {
- tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%s", result1, nonce, result2);
- }
- else
- {
- duk_get_prop_string(ctx, -1, DIGEST2CNONCE); // [digest][buffer]
- CNONCE = (char*)Duktape_GetBuffer(ctx, -1, NULL);
- duk_pop(ctx); // [digest]
- NC = Duktape_GetIntPropertyValue(ctx, -1, DIGEST2NC, 0) + 1;
- duk_push_int(ctx, NC); // [digest][NC]
- duk_put_prop_string(ctx, -2, DIGEST2NC); // [digest]
-
- tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "%s:%s:%08x:%s:%s:%s", result1, nonce, NC, CNONCE, qop, result2);
- }
- util_md5hex(ILibScratchPad2, tmpLen, result3);
- duk_pop(ctx); // ...
-
- tmpLen = sprintf_s(ILibScratchPad2, sizeof(ILibScratchPad2), "Digest username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s\"", username, realm, nonce, path);
- if (opaque != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",opaque=\"%s\"", opaque); }
- tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",response=\"%s\"", result3);
- if (qop != NULL) { tmpLen += sprintf_s(ILibScratchPad2 + tmpLen, sizeof(ILibScratchPad2) - tmpLen, ",qop=\"%s\",nc=\"%08x\",cnonce=\"%s\"", qop, NC, CNONCE); }
-
- if (realmLen > 0) { realm[realmLen] = '"'; }
- if (nonceLen > 0) { nonce[nonceLen] = '"'; }
- if (opaqueLen > 0) { opaque[opaqueLen] = '"'; }
- if (qopLen > 0) { qop[qopLen] = '"'; }
-
- duk_set_top(ctx, top);
- return(ILibScratchPad2);
-}
-
-duk_ret_t ILibDuktape_httpDigest_clientRequest_response(duk_context *ctx)
-{
- void *digestClientPtr, *digestObj, *optionsObj;
- int statusCode;
-
- duk_push_this(ctx);
- optionsObj = Duktape_GetHeapptrProperty(ctx, -1, ILibDuktape_CR2Options);
-
- duk_push_current_function(ctx);
- duk_get_prop_string(ctx, -1, "digestClientRequest");
- digestClientPtr = duk_get_heapptr(ctx, -1);
- duk_get_prop_string(ctx, -1, "digest");
- digestObj = duk_get_heapptr(ctx, -1);
- duk_get_prop_string(ctx, -1, DIGEST_USERNAME);
- duk_get_prop_string(ctx, -2, DIGEST_PASSWORD);
-
- statusCode = Duktape_GetIntPropertyValue(ctx, 0, "statusCode", -1);
- if (statusCode == 401)
- {
- duk_push_heapptr(ctx, digestClientPtr); // [digestClientRequest]
- int endCalledAlready = Duktape_GetBooleanProperty(ctx, -1, DIGESTCLIENTREQUEST_END_CALLED, 0);
- if (endCalledAlready == 0 && duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
- {
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
- duk_get_prop_string(ctx, -1, "end"); // [digestClientRequest][clientRequest][end]
- duk_dup(ctx, -2); // [digestClientRequest][clientRequest][end][this]
- if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest.onResponse(): "); }
- duk_pop_2(ctx); // [digestClientRequest]
- }
- duk_pop(ctx); // ...
-
- // UnAuthorized, need to retry request with Authorization Headers
- char *auth, *wwwauth;
-
- duk_dup(ctx, 0); // [IMSG]
- duk_get_prop_string(ctx, -1, "headers"); // [IMSG][headers]
- if ((wwwauth = Duktape_GetStringPropertyValue(ctx, -1, "WWW-Authenticate", NULL)) != NULL)
- {
- duk_push_heapptr(ctx, digestObj); // [IMSG][headers][digest]
- duk_push_string(ctx, wwwauth); // [IMSG][headers][digest][www]
- duk_put_prop_string(ctx, -2, DIGEST2WWWAUTH); // [IMSG][headers][digest]
- duk_pop(ctx); // [IMSG][headers]
- }
- duk_pop_2(ctx); // ...
-
- duk_push_this(ctx); // [clientRequest]
- auth = ILibDuktape_httpDigest_generateAuthenticationHeader(ctx, digestObj, optionsObj);
-
- duk_get_prop_string(ctx, -1, ILibDuktape_CR2HTTP); // [clientReqeust][http]
- duk_get_prop_string(ctx, -1, "request"); // [clientRequest][http][request]
- duk_swap_top(ctx, -2); // [clientRequest][request][this]
- duk_get_prop_string(ctx, -3, ILibDuktape_CR2Options); // [clientRequest][request][this][options]
-
- if(!duk_has_prop_string(ctx, -1, "headers"))
- {
- duk_push_object(ctx); // [clientReqeust][request][this][options][headers]
- }
- else
- {
- duk_get_prop_string(ctx, -1, "headers"); // [clientReqeust][request][this][options][headers]
- }
-
- duk_push_string(ctx, auth); // [clientReqeust][request][this][options][headers][Auth]
- duk_put_prop_string(ctx, -2, "Authorization"); // [clientReqeust][request][this][options][headers]
- duk_put_prop_string(ctx, -2, "headers"); // [clientReqeust][request][this][options]
- duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response2, DUK_VARARGS); // [clientReqeust][request][this][options][callback]
- duk_push_heapptr(ctx, digestClientPtr); // [clientReqeust][request][this][options][callback][digestClientRequest]
- duk_put_prop_string(ctx, -2, "digestClientRequest"); // [clientReqeust][request][this][options][callback]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digest_onResponse: Error Invoking http.get"); }
-
- duk_push_heapptr(ctx, digestClientPtr); // [clientRequest][digestClientRequest]
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "upgrade", -1, "upgrade");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "error", -1, "error");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "continue", -1, "continue");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "timeout", -1, "timeout");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "drain", -1, "drain");
- duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [clientRequest]
-
- if (endCalledAlready != 0)
- {
- duk_push_heapptr(ctx, digestClientPtr);
- if (duk_has_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer))
- {
- duk_get_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer); // [clientReqeust][digestClientRequest][buffer]
- duk_swap_top(ctx, -2); // [clientRequesat][buffer][digestClientRequest]
- duk_pop(ctx); // [clientRequest][buffer]
- duk_dup(ctx, -2); // [clientRequest][buffer][clientRequest]
- duk_get_prop_string(ctx, -1, "write"); // [clientRequest][buffer][clientRequest][write]
- duk_swap_top(ctx, -2); // [clientRequest][buffer][write][this]
- duk_dup(ctx, -3); // [clientRequest][buffer][write][this][buffer]
- duk_remove(ctx, -4); // [clientRequest][write][this][buffer]
- if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpDigest.clientRequest.onResponse(): Error calling clientRequest.write(): "); }
- duk_pop(ctx); // [clientRequest]
- }
- else
- {
- duk_pop(ctx); // [clientRequest]
- }
-
- duk_dup(ctx, -1); // [clientReqeust][clientReqeust]
- duk_get_prop_string(ctx, -1, "end"); // [clientReqeust][clientReqeust][end]
- duk_swap_top(ctx, -2); // [clientReqeust][end][this]
- if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpDigest.onResponse(): Error invoking ClientRequest.end(): "); }
- duk_pop(ctx); // [clientRequest]
- }
-
- duk_push_heapptr(ctx, digestClientPtr); // [clientRequest][digestClientRequest]
- duk_swap_top(ctx, -2); // [digestClientRequest][clientRequest]
- duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [digestClientRequest]
- }
- else
- {
- duk_push_heapptr(ctx, digestClientPtr); // [digestClientRequest]
- duk_del_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST);
- duk_push_this(ctx);
- duk_del_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST);
- duk_pop(ctx);
-
- duk_get_prop_string(ctx, -1, "emit"); // [digestClientRequest][emit]
- duk_swap_top(ctx, -2); // [emit][this]
- duk_push_string(ctx, "response"); // [emit][this][response]
- duk_dup(ctx, 0); // [emit][this][response][IMSG]
-
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "digestClientRequest.onResponse(): "); }
- duk_pop(ctx); // ...
- }
- return(0);
-}
-duk_ret_t ILibDuktape_httpDigest_clientRequest_setter(duk_context *ctx)
-{
- duk_dup(ctx, 0); // [clientRequest]
- duk_get_prop_string(ctx, -1, "once"); // [clientRequest][once]
- duk_swap_top(ctx, -2); // [once][this]
- duk_push_string(ctx, "response"); // [once][this][response]
- duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response, DUK_VARARGS); // [once][this][response][method]
- duk_push_this(ctx); // [once][this][response][method][digest]
- duk_put_prop_string(ctx, -2, "digest"); // [once][this][response][method]
- if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest: Error setting clientRequest"); }
- duk_pop(ctx); // ..
- return(0);
-}
-duk_ret_t ILibDuktape_httpDigest_http_setter(duk_context *ctx)
-{
- duk_push_this(ctx); // [digest]
- duk_dup(ctx, 0); // [digest][http]
- duk_put_prop_string(ctx, -2, HTTP_DIGEST); // [digest]
- return(0);
-}
-duk_ret_t ILibDuktape_httpDigest_digestRequest_end(duk_context *ctx)
-{
- int nargs = duk_get_top(ctx);
- int i;
- duk_push_this(ctx); // [digestClientRequest]
- if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
- {
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
- duk_get_prop_string(ctx, -1, "end"); // [digestClientRequest][clientRequest][end]
- duk_swap_top(ctx, -2); // [digestClientRequest][end][this]
-
- for (i = 0; i < nargs; ++i)
- {
- duk_dup(ctx, i); // [digestClientRequest][end][this][params...]
- }
- if (duk_pcall_method(ctx, nargs) != 0) { return(ILibDuktape_Error(ctx, "digestRequest().end() error")); }
-
- duk_push_this(ctx);
- duk_del_prop_string(ctx, -1, "DIGEST_CLIENT_REQUEST");
- }
- return(0);
-}
-
-ILibTransport_DoneState ILibDuktape_httpDigest_http_request_WriteHandler(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
-{
- ILibTransport_DoneState retVal = ILibTransport_DoneState_ERROR;
-
- duk_context *ctx = stream->ctx;
- duk_push_heapptr(ctx, stream->obj); // [digestClientRequest]
-
- if (Duktape_GetBooleanProperty(ctx, -1, DIGESTCLIENTREQUEST_CONTINUE, 0) == 0)
- {
- duk_size_t bufLen;
- char *tmpBuffer;
-
- if (duk_has_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer))
- {
- duk_get_prop_string(ctx, -1, DIGESTCLIENTREQUEST_TmpBuffer); // [digestClientRequest][oldBuffer]
- bufLen = duk_get_length(ctx, -1);
- duk_resize_buffer(ctx, -1, bufLen + bufferLen);
- tmpBuffer = (char*)Duktape_GetBuffer(ctx, -1, &bufLen);
- memcpy_s(tmpBuffer + bufLen - (size_t)bufferLen, (size_t)bufferLen, buffer, (size_t)bufferLen);
- duk_pop(ctx); // [digestClientRequest]
- }
- else
- {
- duk_push_dynamic_buffer(ctx, (duk_size_t)bufferLen); // [digestClientRequest][buffer]
- tmpBuffer = (char*)Duktape_GetBuffer(ctx, -1, &bufLen);
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_TmpBuffer); // [digestClientRequest]
- memcpy_s(tmpBuffer, bufLen, buffer, (size_t)bufferLen);
- }
-
- if (stream->endBytes > 0)
- {
- duk_push_true(ctx);
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
- }
- }
-
- if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
- {
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
- duk_get_prop_string(ctx, -1, "write"); // [digestClientRequest][clientRequest][write]
- duk_swap_top(ctx, -2); // [digestClientRequest][write][this]
-
- if (stream->Reserved == 0)
- {
- duk_push_external_buffer(ctx);
- duk_config_buffer(ctx, -1, buffer, (duk_size_t)bufferLen);
- }
- else
- {
- duk_push_lstring(ctx, buffer, (duk_size_t)bufferLen);
- }
-
- if (duk_pcall_method(ctx, 1) != 0)
- {
- ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest.clientRequest.write(): ");
- retVal = ILibTransport_DoneState_ERROR;
- }
- else
- {
- retVal = duk_get_boolean(ctx, -1) ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE;
- }
- duk_pop(ctx); // [digestClientRequest]
-
- }
- duk_pop(ctx); // ...
- return(retVal);
-}
-void ILibDuktape_httpDigest_http_request_DoneHandler(struct ILibDuktape_WritableStream *stream, void *user)
-{
- duk_context *ctx = stream->ctx;
-
- duk_push_heapptr(ctx, stream->obj); // [digestClientRequest]
- duk_push_true(ctx);
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
-
- if (duk_has_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST))
- {
- duk_get_prop_string(ctx, -1, DIGEST_CLIENT_REQUEST); // [digestClientRequest][clientRequest]
- duk_get_prop_string(ctx, -1, "end"); // [digestClientRequest][clientRequest][end]
- duk_swap_top(ctx, -2); // [digestClientRequest][end][this]
-
- if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "http-digest.clientRequest.end(): "); }
- duk_pop(ctx); // [digestClientRequest]
- duk_del_prop_string(ctx, -1, "DIGEST_CLIENT_REQUEST");
- }
- duk_pop(ctx); // ...
-}
-duk_ret_t ILibDuktape_httpDigest_http_request_continueOccured(duk_context *ctx)
-{
- duk_push_this(ctx); // [digestClientRequest]
- duk_push_true(ctx);
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_CONTINUE);
- return(0);
-}
-
-duk_ret_t ILibDuktape_httpDigest_http_request(duk_context *ctx)
-{
- int nargs = duk_get_top(ctx);
- void *clientRequest = NULL;
- ILibDuktape_EventEmitter *emitter;
- char *auth = NULL;
- int needCallEnd = 0;
-
- duk_push_this(ctx); // [digest]
- duk_get_prop_string(ctx, -1, HTTP_DIGEST); // [digest][http]
- duk_get_prop_string(ctx, -1, "request"); // [digest][http][request]
- duk_swap_top(ctx, -2); // [digest][request][this]
-
- if (duk_is_string(ctx, 0))
- {
- duk_get_prop_string(ctx, -1, "parseUri"); // [digest][request][this][parseUri]
- duk_dup(ctx, -2); // [digest][request][this][parseUri][this]
- duk_dup(ctx, 0); // [digest][request][this][parseUri][this][uri]
- duk_call_method(ctx, 1); // [digest][request][this][options]
- needCallEnd = 1;
- }
- else
- {
- duk_dup(ctx, 0); // [digest][request][this][options]
- }
-
- // Before we make the request, let's check to see if we can put in Authorization header right now
- if ((auth = ILibDuktape_httpDigest_generateAuthenticationHeader(ctx, duk_get_heapptr(ctx, -4), duk_get_heapptr(ctx, -1))) != NULL)
- {
- if (!duk_has_prop_string(ctx, -1, "headers"))
- {
- duk_push_object(ctx); // [digest][request][this][options][headers]
- duk_dup(ctx, -1); // [digest][request][this][options][headers][dup]
- duk_put_prop_string(ctx, -3, "headers"); // [digest][request][this][options][headers]
- }
- else
- {
- duk_get_prop_string(ctx, -1, "headers"); // [digest][request][this][options][headers]
- }
- duk_push_string(ctx, auth); // [digest][request][this][options][headers][auth]
- duk_put_prop_string(ctx, -2, "Authorization"); // [digest][request][this][options][headers]
- duk_pop(ctx); // [digest][request][this][options]
- }
-
- duk_call_method(ctx, 1); // [digest][clientRequest]
-
- clientRequest = duk_get_heapptr(ctx, -1);
- duk_get_prop_string(ctx, -1, "once"); // [clientRequest][once]
- duk_swap_top(ctx, -2); // [once][this]
- duk_push_string(ctx, "response"); // [once][this][response]
- duk_push_c_function(ctx, ILibDuktape_httpDigest_clientRequest_response, DUK_VARARGS); // [once][this][response][method]
-
- duk_push_object(ctx); // [once][this][response][method][digest-clientRequest]
- ILibDuktape_WriteID(ctx, "httpDigest.clientRequest");
- if (needCallEnd)
- {
- duk_push_true(ctx);
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_END_CALLED);
- }
-
- duk_push_this(ctx); // [once][this][response][method][digest-clientRequest][digest]
- duk_put_prop_string(ctx, -2, DIGESTCLIENTREQUEST_DIGEST); // [once][this][response][method][digest-clientRequest]
- duk_push_heapptr(ctx, clientRequest); // [once][this][response][method][digest-clientRequest][clientRequest]
- duk_dup(ctx, -2); // [once][this][response][method][digest-clientRequest][clientRequest][digest-clientRequest]
- duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [once][this][response][method][digest-clientRequest][clientRequest]
- duk_put_prop_string(ctx, -2, DIGEST_CLIENT_REQUEST); // [once][this][response][method][digest-clientRequest]
-
- emitter = ILibDuktape_EventEmitter_Create(ctx);
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "response");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "upgrade");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "continue");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "timeout");
-
- ILibDuktape_EventEmitter_AddOnceEx(emitter, "continue", ILibDuktape_httpDigest_http_request_continueOccured, 0);
- ILibDuktape_WritableStream_Init(ctx, ILibDuktape_httpDigest_http_request_WriteHandler, ILibDuktape_httpDigest_http_request_DoneHandler, NULL);
-
- if (nargs > 1 && duk_is_function(ctx, 1))
- {
- ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter(ctx, -1), "response", duk_require_heapptr(ctx, 1));
- }
-
- duk_push_this(ctx); // [once][this][response][method][digest-clientRequest][digest]
- duk_put_prop_string(ctx, -2, "digest"); // [once][this][response][method][digest-clientRequest]
- duk_put_prop_string(ctx, -2, "digestClientRequest"); // [once][this][response][method]
- if (duk_pcall_method(ctx, 2) != 0) { return(ILibDuktape_Error(ctx, "request error")); } // [clientRequest]
-
- duk_push_heapptr(emitter->ctx, clientRequest);
- duk_push_heapptr(emitter->ctx, emitter->object); // [clientRequest][digestClientRequest]
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "upgrade", -1, "upgrade");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "error", -1, "error");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "continue", -1, "continue");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "timeout", -1, "timeout");
- ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "drain", -1, "drain");
-
- if (needCallEnd)
- {
- duk_get_prop_string(ctx, -2, "end"); // [clientRequest][digestClientRequest][end]
- duk_dup(ctx, -3); // [clientRequest][digestClientRequest][end][this]
- duk_call_method(ctx, 0); duk_pop(ctx); // [clientRequest][digestClientRequest]
- }
-
- return(1);
-}
-duk_ret_t ILibduktape_httpDigest_create(duk_context *ctx)
-{
- duk_size_t usernameLen, passwordLen, authTokenLen;
- ILibDuktape_EventEmitter *emitter;
- char *username = NULL, *password = NULL, *authToken = NULL;
-
- if (duk_get_top(ctx) == 1 && duk_is_object(ctx, 0))
- {
- if ((authToken = Duktape_GetStringPropertyValueEx(ctx, 0, "authToken", NULL, &authTokenLen)) == NULL) { return(ILibDuktape_Error(ctx, "authToken Required")); }
- }
- else
- {
- username = (char*)duk_require_lstring(ctx, 0, &usernameLen), password = (char*)duk_require_lstring(ctx, 1, &passwordLen);
- }
-
- duk_push_object(ctx); // [obj]
- ILibDuktape_WriteID(ctx, "httpDigest");
- ILibDuktape_CreateEventWithSetterEx(ctx, "clientRequest", ILibDuktape_httpDigest_clientRequest_setter);
- ILibDuktape_CreateEventWithSetterEx(ctx, "http", ILibDuktape_httpDigest_http_setter);
- emitter = ILibDuktape_EventEmitter_Create(ctx);
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "response");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
- ILibDuktape_EventEmitter_CreateEventEx(emitter, "upgrade");
- ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isGet", 1, "get", ILibDuktape_httpDigest_http_request, DUK_VARARGS);
- ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isGet", 0, "request", ILibDuktape_httpDigest_http_request, DUK_VARARGS);
-
- if (authToken == NULL)
- {
- duk_push_string(ctx, username);
- duk_put_prop_string(ctx, -2, DIGEST_USERNAME);
- duk_push_string(ctx, password);
- duk_put_prop_string(ctx, -2, DIGEST_PASSWORD);
- }
- else
- {
- duk_push_lstring(ctx, authToken, authTokenLen);
- duk_put_prop_string(ctx, -2, DIGEST_AUTHTOKEN);
- }
- duk_push_fixed_buffer(ctx, 16);
- util_randomtext(16, (char*)Duktape_GetBuffer(ctx, -1, NULL));
- ((char*)Duktape_GetBuffer(ctx, -1, NULL))[15] = 0;
- duk_put_prop_string(ctx, -2, DIGEST2CNONCE);
- duk_push_int(ctx, 0);
- duk_put_prop_string(ctx, -2, DIGEST2NC);
-
- return(1);
-}
-
-void ILibDuktape_httpDigest_PUSH(duk_context *ctx, void *chain)
-{
- duk_push_object(ctx);
- ILibDuktape_CreateInstanceMethod(ctx, "create", ILibduktape_httpDigest_create, DUK_VARARGS);
-}
-duk_ret_t ILibDuktape_httpHeaders(duk_context *ctx)
-{
- ILibHTTPPacket *packet = NULL;
- packetheader_field_node *node;
- int headersOnly = duk_get_top(ctx) > 1 ? (duk_require_boolean(ctx, 1) ? 1 : 0) : 0;
-
- duk_size_t bufferLen;
- char *buffer = (char*)Duktape_GetBuffer(ctx, 0, &bufferLen);
-
- packet = ILibParsePacketHeader(buffer, 0, (int)bufferLen);
- if (packet == NULL) { return(ILibDuktape_Error(ctx, "http-headers(): Error parsing data")); }
-
- if (headersOnly == 0)
- {
- duk_push_object(ctx);
- if (packet->Directive != NULL)
- {
- duk_push_lstring(ctx, packet->Directive, packet->DirectiveLength);
- duk_put_prop_string(ctx, -2, "method");
- duk_push_lstring(ctx, packet->DirectiveObj, packet->DirectiveObjLength);
- duk_put_prop_string(ctx, -2, "url");
- }
- else
- {
- duk_push_int(ctx, packet->StatusCode);
- duk_put_prop_string(ctx, -2, "statusCode");
- duk_push_lstring(ctx, packet->StatusData, packet->StatusDataLength);
- duk_put_prop_string(ctx, -2, "statusMessage");
- }
- if (packet->VersionLength == 3)
- {
- duk_push_object(ctx);
- duk_push_lstring(ctx, packet->Version, 1);
- duk_put_prop_string(ctx, -2, "major");
- duk_push_lstring(ctx, packet->Version + 2, 1);
- duk_put_prop_string(ctx, -2, "minor");
- duk_put_prop_string(ctx, -2, "version");
- }
- }
-
- duk_push_object(ctx); // headers
- node = packet->FirstField;
- while (node != NULL)
- {
- duk_push_lstring(ctx, node->Field, node->FieldLength); // [str]
- duk_get_prop_string(ctx, -1, "toLowerCase"); // [str][toLower]
- duk_swap_top(ctx, -2); // [toLower][this]
- duk_call_method(ctx, 0); // [result]
- duk_push_lstring(ctx, node->FieldData, node->FieldDataLength);
- duk_put_prop(ctx, -3);
- node = node->NextField;
- }
- if (headersOnly == 0)
- {
- duk_put_prop_string(ctx, -2, "headers");
- }
- ILibDestructPacket(packet);
- return(1);
-}
-void ILibDuktape_httpHeaders_PUSH(duk_context *ctx, void *chain)
-{
- duk_push_c_function(ctx, ILibDuktape_httpHeaders, DUK_VARARGS);
-}
-void ILibDuktape_http_init(duk_context * ctx, void * chain)
-{
- ILibDuktape_ModSearch_AddHandler(ctx, "http-digest", ILibDuktape_httpDigest_PUSH);
- ILibDuktape_ModSearch_AddHandler(ctx, "http-headers", ILibDuktape_httpHeaders_PUSH);
-}
-
-#ifdef __DOXY__
-
-/*!
-\brief Http exposed using Node APIs. Note: To use, must require('http') or require('https')
-*/
-class Http
-{
-public:
- /*!
- \brief Parses a uri string
- \param str \ The uri to parse
- \return Uri object of the parsed string
- */
- static Uri parseUri(str);
- /*!
- \brief Returns a new instance of Server
- *
- static Server createServer([options][, callback]);
- \param options