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 that specifies various parameters such as:\n - 'request' = callback to be dispatched when a request is received\n - 'pfx' = \ containing PKS encoded certificate\n - 'passphrase' = \ containing the passphrase to unlock the private key of the specified certificate\n - 'MeshAgent' = object, whose certificates we are going to use.\n - 'requestCert' = indicating if the client certificate will be requested\n - 'rejectUnauthorized' = indicating if the certificate must have a valid root of trust\n - 'checkClientIdentity' = callback to be dispatched to verify client certificate. Note: When dispatched, throw an exception to fail verification.\n - \param callback callback to be dispatched when a request is received - \return Server instance. - */ - static Server createServer([options][, callback]); - /*! - \brief Issues an HTTP Request onto the network - * - static ClientRequest request(options[, callback]); - \param options \\n - protocol \ Protocol to use. Defaults to 'http:' or 'https:' depending on configuration\n - host \ A domain name or IP address of the server to issue the request to. Defaults to localhost.\n - hostname \ Alias for host. To support url.parse(), hostname is preferred over host.\n - port Port of remote server. Defaults to 80, or 443, depending on configuration\n - localAddress \ Local interface to bind for network connections.\n - method \ A string specifying the HTTP request method. Defaults to 'GET'.\n - path \ Request path. Defaults to '/'\n - headers An object containing request headers.\n - proxy An object containing proxy settings, (ie: 'host' and 'port'), to use for this connection\n - noProxy When present, will override any previously set proxies, and disable it for this connection\n - pfx \ containing pks encoded certificate\n - passphrase \ containing passphrase used to unlock specified certificate\n - MeshAgent containing the MeshAgent instance, whose certificates will be used\n - rejectUnauthorized If true, will reject server's whose root of trust cannot be validated\n - checkServerIdentity callback that will be dispatched to validate server certificate. Note: To fail validation, throw an exception from the dispatch.\n - \param callback Optional. Set as one time listener for ClientRequest.response event. - \return ClientRequest instance. - */ - static ClientRequest request(options[, callback]); - - /*! - \brief Issues an HTTP Request onto the network. - \param url \ The url to issue a GET reqeust - \return ClientRequest instance - */ - static ClientRequest get(url); - static DuplexStream createStream(); - - - /*! - \implements EventEmitter - \brief Http Server Abstraction - */ - class Server - { - public: - /*! - \brief Event emitted each time a request with an HTTP Expect: 100-continue is received. If this event is not listened for, the server will automatically respond with a 100 Continue as appropriate. - * - Note: When this event is emitted and handled, Http.request event will not be emitted. - \param request \ - \param response \ - */ - void checkContinue; - /*! - \brief Event emitted each time a request with an HTTP Expect header is received, where the value is not 100-continue. If this event is not listened for, the server will automatically respond with a 417 Expectation Failed as appropriate. - * - Note: When this event is emitted and handled, Http.request event will not be emitted. - */ - void checkExpectation; - /*! - \brief Event emitted if the underlying Socket emits an error - \param err - \param socket \ - */ - void clientError; - /*! - \brief Event emitted when the Server closes. - */ - void close; - /*! - \brief Event emitted when the client issues a 'CONNECT' method. If this event is not listened for, then clients requesting a CONNECT method will have their connections closed. - \param request \ Arguments for the HTTP request, as it is in the 'request' event - \param socket \ Network socket between the server and client - \param head \ The first packet of the tunneling stream (may be empty) - */ - void connect; - /*! - \brief Event emitted each time a client requests an HTTP upgrade. If this event is not listened for, then clients requesting an upgrade will have their connections closed. - \param request \ Arguments for the HTTP request, as it is in the 'request' event - \param socket \ Network socket between the server and client - \param head \ The first packet of the tunneling stream (may be empty) - */ - void upgrade; - /*! - \brief Event emitted each time there is a request. Note: There may be multiple requests per connection (in the case of HTTP Keep-Alive connections). - \param request \ - \param response \ - */ - void request; - /*! - \brief Event emitted when server is listening for incoming connections - */ - void listening; - /*! - \brief Stops the server from accepting new connections - \param callback Optional. Set as one time listener for 'close' event. - */ - void close([callback]); - /*! - \brief Event emitted when an idle timeout has elapsed - \param socket \ Timed out socket - */ - void timeout; - /*! - \brief Begin accepting connections on the specified port and hostname - \param port - \param hostname \ - \param backlog - \param callback Optional. Set as one time listener to 'listening' event - */ - void listen([port][, hostname][, backlog][, callback]); - /*! - \brief Sets the timeout value for sockets, and emits a 'timeout' event on the Server object, passing the socket as an argument, if a timeout occurs. - \param msecs Optional Default: 120000 milliseconds (2 minutes) - \param callback Optional. Set as one time listener for 'timeout' event - */ - void setTimeout([msecs][, callback]); - /*! - \implements WritableStream - \implements EventEmitter - \brief Created internally by Http. - */ - class ServerResponse - { - public: - /*! - \brief Sets a single header value for implicit headers.If this header already exists in the to - be - sent headers, its value will be replaced - \param name \ - \param value \ - */ - void setHeader(name, value); - /*! - \brief Sends a response header to the request. - \param statusCode 3 digit code (ie: 200, 404, etc) - \param statusMessage \ Human readable status message (ie: 'OK', 'File Not Found', etc) - \param headers Optional. JSON object where each name/value pair is a header/value pair. - */ - void writeHead(statusCode[, statusMessage][, headers]); - /*! - \brief When using implicit headers (not calling writeHead() explicitly), this property controls the status code that will be sent to the client when the headers get flushed. - */ - Integer statusCode; - /*! - \brief When using implicit headers (not calling writeHead() explicitly), this property controls the status message that will be sent to the client when the headers get flushed - */ - String statusMessage; - }; - }; - /*! - \implements WritableStream - \brief This object is created internally and returned from http.request(). It represents an in-progress request whose header has already been queued. - */ - class ClientRequest - { - public: - /*! - \brief Event emitted when a response is received to this request. This event is emitted only once. - \param msg IncomingMessage object containing the received request - */ - void response; - /*! - \brief Event emitted each time a server responds to a request with an upgrade. - \param response IncomingMessage - \param socket WebSocket - \param head - */ - void upgrade; - }; - - /*! - \implements Socket - \brief WebSocket abstraction - */ - class WebSocket - { - public: - /*! - \brief Event emitted when a 'ping' web socket control packet is received. - \param data \ Optional data that was attached to the received 'ping' control packet. - */ - void ping; - /*! - \brief Event emitted when a 'pong' web socket control packet is received. - \param data \ Optional data that was attached to the received 'pong' control packet. - */ - void pong; - /*! - \brief Send a 'ping' web socket control packet to the connected peer. - * - void ping([data]); - \param data \ Optional data to attach to the 'ping' control packet. - */ - void ping([data]); - /*! - \brief Send a 'pong' web socket control packet to the connected peer. - * - void pong([data]); - \param data \ Optional data to attach to the 'pong' control packet. - */ - void pong([data]); - }; - - - /*! - \brief An IncomingMessage object may be used to access response status, headers and data. - */ - class IncomingMessage - { - public: - /*! - \brief Key-value pairs of header names and values. Header names are lower-cased - */ - Object headers; - /*! - \brief HTTP Version sent by client. Usually either '1.0' or '1.1' - */ - String httpVersion; - /*! - \brief Request Method as a String. (ie: GET, PUT, etc) - */ - String method; - /*! - \brief The Socket object associated with this connection - */ - Socket socket; - /*! - \brief 3 digit HTTP Status Code. (ie: 200, 404, etc) - */ - integer statusCode; - /*! - \brief HTTP Status Message (ie: 'OK', 'File Not Found', etc) - */ - String statusMessage; - /*! - \brief HTTP Request Path line (ie: '/index.html', etc) - */ - String url; - }; - - /*! - \brief Network Uri abstraction - */ - class Uri - { - public: - /*! - \brief Protocol (ie: http, https, wss, etc) - */ - String protocol; - /*! - \brief Host IP or DNS Name - */ - String host; - /*! - \brief Host port - */ - integer port; - /*! - \brief Method Path (ie: /index.html) - */ - String path; - /*! - \brief Method. (ie: GET, PUT, HEAD, etc) - */ - String method; - }; -}; - - -/*! -\brief Provides HTTP-Digest Authentication Services. Note: To use must require('http-digest').Create() -* -After creation, the 'http' property must be set, typically with require('http'). Afterwards, calls to 'request' can be made. -*/ -class HttpDigest -{ -public: - /*! - \brief Initializes an HttpDigest object with the specified username and password. - \param username \ The username to encode - \param password \ The password to encode - \return HttpDigest instance - */ - static HttpDigest Create(username, password); - /*! - \brief Wrapped Http implementation, which must be set. Typically set to require('http') or require('https') - */ - Http http; - /*! - \brief Issues a Digest-Authenticated HTTP Request onto the network - * - static DigestClientRequest request(options[, callback]); - \param options \\n - protocol \ Protocol to use. Defaults to 'http:' or 'https:' depending on configuration\n - host \ A domain name or IP address of the server to issue the request to. Defaults to localhost.\n - hostname \ Alias for host. To support url.parse(), hostname is preferred over host.\n - port Port of remote server. Defaults to 80, or 443, depending on configuration\n - localAddress \ Local interface to bind for network connections.\n - method \ A string specifying the HTTP request method. Defaults to 'GET'.\n - path \ Request path. Defaults to '/'\n - headers An object containing request headers.\n - proxy An object containing proxy settings, (ie: 'host' and 'port'), to use for this connection\n - noProxy When present, will override any previously set proxies, and disable it for this connection\n - pfx \ containing pks encoded certificate\n - passphrase \ containing passphrase used to unlock specified certificate\n - MeshAgent containing the MeshAgent instance, whose certificates will be used\n - rejectUnauthorized If true, will reject server's whose root of trust cannot be validated\n - checkServerIdentity callback that will be dispatched to validate server certificate. Note: To fail validation, throw an exception from the dispatch.\n - \param callback Optiona. Set as one time listener to DigestClientRequest.response event. - \return \ - */ - DigestClientRequest request(options[, callback]); - - /*! - \implements Http::ClientRequest - \brief Encapsulation of Http::ClientRequest. Digest-Authentication may require multiple request/response sequences, so the underlying Http::ClientRequest may change - */ - class DigestClientRequest - { - }; -}; - - -/*! -\brief Helper function to parse HTTP Headers. Note: To use, must require('http-headers') -*/ -class HttpHeaders -{ -public: - /*! - \brief Parses the specified buffer - * - static HttpHeaders HttpHeaders(data[, headersOnly]); - \param data \ The data to parse - \param headersOnly Optional parameter, that if true, will indicate to the parser to skip parsing of the Method/Path/Version/etc. - \return HttpHeaders representing the parsed data - */ - static HttpHeaders HttpHeaders(data[, headersOnly]); - - /*! - \brief HTTP Method. (ie: GET, PUT, HEAD, etc) - */ - public String method; - /*! - \brief HTTP Method Path (ie: /index.html) - */ - public String url; - /*! - \brief HTTP Status Code (ie: 200) - */ - public integer statusCode; - /*! - \brief HTTP Status Code Message (ie: OK) - */ - public String statusMessage; - /*! - \brief HttpVersion of the decoded HTTP headers - */ - public HttpVersion version; - /*! - \brief JSON object of decoded HTTP headers. Property key is header name, Property value is header value. - */ - public object headers; - - /*! - \brief HTTP Version - */ - class HttpVersion - { - public: - /*! - \brief major version - */ - public String major; - /*! - \brief minor version - */ - public String minor; - }; -}; -#endif diff --git a/microscript/ILibDuktape_http.h b/microscript/ILibDuktape_http.h deleted file mode 100644 index d9017d2..0000000 --- a/microscript/ILibDuktape_http.h +++ /dev/null @@ -1,24 +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. -*/ - -#ifndef ___ILIBDUKTAPEHTTP___ -#define ___ILIBDUKTAPEHTTP___ - -#include "duktape.h" - -void ILibDuktape_http_init(duk_context *ctx, void *chain); - -#endif diff --git a/modules/clipboard.js b/modules/clipboard.js index 5564a4c..4eec82c 100644 --- a/modules/clipboard.js +++ b/modules/clipboard.js @@ -1,3 +1,19 @@ +/* +Copyright 2019 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. +*/ + function nativeAddModule(name) { diff --git a/modules/http-digest.js b/modules/http-digest.js new file mode 100644 index 0000000..dc0487f --- /dev/null +++ b/modules/http-digest.js @@ -0,0 +1,282 @@ +/* +Copyright 2019 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. +*/ + + +var writable = require('stream').Writable; +var md5 = require('MD5Stream').create(); + +function checkEventForwarding(digestRequest, eventName) +{ + if (digestRequest.listenerCount(eventName) > 0) + { + var eForward = function _eForward() + { + var p = [eForward._eventName]; + for (var i = 0; i < arguments.length; ++i) { p.push(arguments[i]); } + _eForward._digestRequest.emit.apply(_eForward._digestRequest, p); + }; + eForward._eventName = eventName; + eForward._digestRequest = digestRequest; + digestRequest._request.on(eventName, eForward); + } +} + +function generateAuthHeaders(imsg, options, digest) +{ + var auth; + + if (imsg != null) + { + auth = { realm: null, nonce: null, opaque: null, qop: null }; + var www = imsg.headers['WWW-Authenticate']; + var tokens = www.split(','); + + var pairs; + for (var i in tokens) + { + pairs = tokens[i].split('='); + if (pairs.length == 2) + { + switch (pairs[0].toLowerCase().trim()) + { + case 'digest realm': + auth.realm = pairs[1]; + if (auth.realm[0] == '"') { auth.realm = auth.realm.substring(1, auth.realm.length - 1); } + break; + case 'nonce': + auth.nonce = pairs[1]; + if (auth.nonce[0] == '"') { auth.nonce = auth.nonce.substring(1, auth.nonce.length - 1); } + break; + case 'opaque': + auth.opaque = pairs[1]; + if (auth.opaque[0] == '"') { auth.opaque = auth.opaque.substring(1, auth.opaque.length - 1); } + break; + case 'qop': + auth.qop = pairs[1]; + if (auth.qop[0] == '"') { auth.qop = auth.qop.substring(1, auth.qop.length - 1); } + break; + } + } + } + digest._auth = auth; + } + else + { + if (!(auth = digest._auth)) { return; } + } + + var step1 = digest._options.username + ':' + auth.realm + ':' + digest._options.password; + auth.step1 = md5.syncHash(step1).toString('hex').toLowerCase(); + + var step2 = options.method + ':' + options.path; + auth.step2 = md5.syncHash(step2).toString('hex').toLowerCase(); + + + if (auth.qop == null) + { + var step3 = auth.step1 + ':' + auth.nonce + ':' + auth.step2; + auth.step3 = md5.syncHash(step3).toString('hex').toLowerCase(); + } + else + { + digest._NC += 1; + var step3 = auth.step1 + ':' + auth.nonce + ':' + digest._NC.toString(16).toLowerCase().padStart(8, '0') + ':' + digest._CNONCE + ':' + auth.qop + ':' + auth.step2; + auth.step3 = md5.syncHash(step3).toString('hex').toLowerCase(); + } + + var ret = 'Digest username="' + digest._options.username + '",realm="' + auth.realm + '",nonce="' + auth.nonce + '",uri="' + options.path + '"'; + if (auth.opaque != null) { ret += (',opaque="' + auth.opaque + '"'); } + ret += (',response="' + auth.step3 + '"'); + + if (auth.qop != null) + { + ret += (',qop="' + auth.qop + '",nc="' + digest._NC.toString(16).toLowerCase().padStart(8, '0') + '",cnonce="' + digest._CNONCE + '"'); + } + + + if (!options.headers) { options.headers = {}; } + options.headers['Authorization'] = ret; + return (ret); +} + +function http_digest() +{ + this._ObjectID = "http-digest"; + this.create = function() + { + if(arguments.length == 1 && typeof(arguments[0] == 'object')) + { + return (new http_digest_instance(arguments[0])); + } + if(arguments.length == 2 && typeof(arguments[0]) == 'string' && typeof(arguments[1]) == 'string') + { + return (new http_digest_instance({username: arguments[0], password: arguments[1]})); + } + throw ('Invalid Parameters'); + } +} + +function http_digest_instance(options) +{ + this._ObjectID = 'http-digest.instance'; + this._options = options; + this.http = null; + this._NC = 0; + this._CNONCE = require('http').generateNonce(16); + + this.get = function(uri) + { + return (this.request(uri)); + } + this.request = function (par1) + { + var callend = false; + var ret = new writable( + { + write: function (chunk, flush) + { + if (this._ended) { throw ('Stream already ended'); } + if(!this._buffered) + { + this._buffered = Buffer.alloc(chunk.length); + chunk.copy(this._buffered); + } + else + { + this._buffered = Buffer.concat([this._buffered, chunk], this._buffered.length + chunk.length); + } + + if (this._request) { this._request.write(chunk); } + if (flush != null) { flush(); } + return (true); + }, + final: function (flush) + { + if (this._ended) { throw ('Stream already ended'); } + this._ended = true; + if (this._request) { this._request.end(); } + if (flush != null) { flush(); } + } + }); + ret._buffered = null; + ret._ended = false; + switch (typeof (par1)) + { + default: + throw ('Invalid Parameter'); + break; + case 'string': + ret.options = this.http.parseUri(par1); + callend = true; + break; + case 'object': + ret.options = par1; + break; + } + require('events').EventEmitter.call(ret, true) + .createEvent('response') + .createEvent('error') + .createEvent('upgrade') + .createEvent('continue') + .createEvent('timeout'); + ret._digest = this; + + if (arguments.length > 1 && typeof (arguments[1]) == 'function') + { + ret.once('response', arguments[1]); + } + + // + // Check if we can add AuthHeaders now + // + generateAuthHeaders(null, ret.options, this); + + // When somebody hooks up events to digest.clientRequest, we need to hook the real event on http.clientRequest + ret._request = this.http.request(ret.options); + ret._request.digRequest = ret; + ret.on('_eventHook', function (evName, callback) + { + if (evName != 'upgrade' && evName != 'error' && evName != 'continue' && evName != 'timeout' && evName != 'drain') { return; } + if (this._request.listenerCount(evName) == 0) + { + var evSink = function _evSink() + { + var parms = [_evSink.eventName]; + for(var i=0;i