From 39e461bb614d75a6f23511a016afaeb3aba35f1a Mon Sep 17 00:00:00 2001 From: aunsane Date: Tue, 10 Oct 2017 21:55:12 +0300 Subject: MirLua: - m_json moved into base plugin - added m_http module -version bump --- plugins/MirLua/Modules/m_json/m_json.vcxproj | 28 -- plugins/MirLua/Modules/m_json/src/main.cpp | 88 ----- plugins/MirLua/Modules/m_json/src/metatable.cpp | 135 -------- plugins/MirLua/Modules/m_json/src/stdafx.cxx | 1 - plugins/MirLua/Modules/m_json/src/stdafx.h | 35 -- plugins/MirLua/src/m_hotkeys.cpp | 6 +- plugins/MirLua/src/m_http.cpp | 443 ++++++++++++++++++++++++ plugins/MirLua/src/m_json.cpp | 227 ++++++++++++ plugins/MirLua/src/m_json.h | 32 ++ plugins/MirLua/src/m_protocols.cpp | 16 + plugins/MirLua/src/main.cpp | 2 +- plugins/MirLua/src/mlua.cpp | 16 +- plugins/MirLua/src/mlua_module_loader.cpp | 4 +- plugins/MirLua/src/mlua_script.cpp | 1 - plugins/MirLua/src/stdafx.h | 8 +- plugins/MirLua/src/version.h | 2 +- 16 files changed, 736 insertions(+), 308 deletions(-) delete mode 100644 plugins/MirLua/Modules/m_json/m_json.vcxproj delete mode 100644 plugins/MirLua/Modules/m_json/src/main.cpp delete mode 100644 plugins/MirLua/Modules/m_json/src/metatable.cpp delete mode 100644 plugins/MirLua/Modules/m_json/src/stdafx.cxx delete mode 100644 plugins/MirLua/Modules/m_json/src/stdafx.h create mode 100644 plugins/MirLua/src/m_http.cpp create mode 100644 plugins/MirLua/src/m_json.cpp create mode 100644 plugins/MirLua/src/m_json.h diff --git a/plugins/MirLua/Modules/m_json/m_json.vcxproj b/plugins/MirLua/Modules/m_json/m_json.vcxproj deleted file mode 100644 index 538ed63f5c..0000000000 --- a/plugins/MirLua/Modules/m_json/m_json.vcxproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - m_json - {8A645067-7F45-4E65-AAFC-AFDA81C29A1D} - - - - - \ No newline at end of file diff --git a/plugins/MirLua/Modules/m_json/src/main.cpp b/plugins/MirLua/Modules/m_json/src/main.cpp deleted file mode 100644 index 3774442d7f..0000000000 --- a/plugins/MirLua/Modules/m_json/src/main.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "stdafx.h" - -static int lua_Decode(lua_State *L) -{ - const char *string = luaL_checkstring(L, 1); - - JSONNode *node = json_parse(string); - new (L) JSON(node); - luaL_setmetatable(L, MT_JSON); - - return 1; -} - -static int lua_Encode(lua_State *L) -{ - switch (lua_type(L, 1)) - { - case LUA_TNIL: - lua_pushliteral(L, "null"); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, lua_toboolean(L, 1) ? "true" : "false"); - break; - case LUA_TNUMBER: - { - if (lua_isinteger(L, 1)) { - lua_pushfstring(L, "%I", lua_tointeger(L, 1)); - break; - } - char decpoint = lua_getlocaledecpoint(); - if (decpoint != '.') { - char p[2] = { decpoint }; - luaL_gsub(L, lua_tostring(L, 1), p, "."); - } - else - lua_pushfstring(L, "%f", lua_tonumber(L, 1)); - break; - } - case LUA_TSTRING: - lua_pushfstring(L, "\"%s\"", lua_tostring(L, 1)); - break; - case LUA_TTABLE: - { - JSONNode node; - lua_pushnil(L); - lua_pushvalue(L, 1); - lua2json(L, node); - lua_pop(L, 2); - lua_pushstring(L, node.write().c_str()); - break; - } - case LUA_TUSERDATA: - { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - lua_pushstring(L, node.write().c_str()); - break; - } - case LUA_TLIGHTUSERDATA: - if (lua_touserdata(L, 1) == NULL) - { - lua_pushliteral(L, "null"); - break; - } - default: - luaL_argerror(L, 1, luaL_typename(L, 1)); - } - - return 1; -} - -static const luaL_Reg methods[] = -{ - { "Decode", lua_Decode }, - { "Encode", lua_Encode }, - - { NULL, NULL } -}; - -extern "C" LUAMOD_API int luaopen_m_json(lua_State *L) -{ - luaL_newlib(L, methods); - - luaL_newmetatable(L, MT_JSON); - luaL_setfuncs(L, jsonApi, 0); - lua_pop(L, 1); - - return 1; -} \ No newline at end of file diff --git a/plugins/MirLua/Modules/m_json/src/metatable.cpp b/plugins/MirLua/Modules/m_json/src/metatable.cpp deleted file mode 100644 index d7bfab5583..0000000000 --- a/plugins/MirLua/Modules/m_json/src/metatable.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "stdafx.h" - -void lua2json(lua_State *L, JSONNode &node) -{ - switch (lua_type(L, -1)) - { - case LUA_TNIL: - node.nullify(); - break; - case LUA_TSTRING: - node = lua_tostring(L, -1); - break; - case LUA_TBOOLEAN: - node = lua_toboolean(L, -1) != 0; - break; - case LUA_TNUMBER: - { - lua_Integer val = lua_tointeger(L, -1); - if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MIN) - node = (long)val; - else - node = lua_tonumber(L, -1); - break; - } - case LUA_TTABLE: - { - ptrA name(mir_strdup(node.name())); - node.cast(JSON_ARRAY); - node.set_name((char*)name); - - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - JSONNode child; - if (!lua_isnumber(L, -2)) { - if (node.type() == JSON_ARRAY) { - node.cast(JSON_NODE); - node.set_name((char*)name); - } - const char *key = lua_tostring(L, -2); - child.set_name(key); - } - lua2json(L, child); - node << child; - - lua_pop(L, 1); - } - - break; - } - } -} - -static int json__index(lua_State *L) -{ - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - - switch (node.type()) - { - case JSON_NULL: - lua_pushnil(L); - break; - case JSON_STRING: - lua_pushstring(L, node.as_string().c_str()); - break; - case JSON_NUMBER: - lua_pushnumber(L, node.as_int()); - break; - case JSON_BOOL: - lua_pushboolean(L, node.as_bool()); - break; - case JSON_NODE: - case JSON_ARRAY: - new (L) JSONNode(node); - luaL_setmetatable(L, MT_JSON); - } - - return 1; -} - -static int json__newindex(lua_State *L) -{ - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - const char *key = lua_tostring(L, 2); - - JSONNode child = node[key]; - if (child.isnull()) { - child.set_name(key); - lua2json(L, child); - node << child; - return 0; - } - - lua2json(L, child); - node[key] = child; - - return 0; -} - -static int json__len(lua_State *L) -{ - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - - lua_pushnumber(L, node.size()); - - return 1; -} - -static int json__tostring(lua_State *L) -{ - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - - lua_pushstring(L, node.write().c_str()); - - return 1; -} - -static int json__gc(lua_State *L) -{ - JSON *json = (JSON*)luaL_checkudata(L, 1, MT_JSON); - - delete json; - - return 0; -} - -const struct luaL_Reg jsonApi[] = -{ - { "__index", json__index }, - { "__newindex", json__newindex }, - { "__len", json__len }, - { "__tostring", json__tostring }, - { "__gc", json__gc }, - - { NULL, NULL } -}; diff --git a/plugins/MirLua/Modules/m_json/src/stdafx.cxx b/plugins/MirLua/Modules/m_json/src/stdafx.cxx deleted file mode 100644 index 1577c4e3bc..0000000000 --- a/plugins/MirLua/Modules/m_json/src/stdafx.cxx +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" \ No newline at end of file diff --git a/plugins/MirLua/Modules/m_json/src/stdafx.h b/plugins/MirLua/Modules/m_json/src/stdafx.h deleted file mode 100644 index dcbdfbd56d..0000000000 --- a/plugins/MirLua/Modules/m_json/src/stdafx.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include - -struct JSON -{ - JSONNode *node; - bool bDelete; - - JSON(JSONNode &refNode, bool bCopy = false) - : node(bCopy ? json_copy(&refNode) : &refNode), bDelete(bCopy) { } - JSON(JSONNode *n, bool bD = true) - : node(n), bDelete(bD) { } - ~JSON() - { - if (bDelete) - json_delete(node); - } - - __inline void* operator new(size_t size, lua_State *L) - { - return lua_newuserdata(L, size); - } -}; - -void lua2json(lua_State *L, JSONNode &node); - -extern const luaL_Reg jsonApi[]; - -#define MT_JSON "JSON" \ No newline at end of file diff --git a/plugins/MirLua/src/m_hotkeys.cpp b/plugins/MirLua/src/m_hotkeys.cpp index 6ab3f07625..2661197d2a 100644 --- a/plugins/MirLua/src/m_hotkeys.cpp +++ b/plugins/MirLua/src/m_hotkeys.cpp @@ -72,12 +72,8 @@ static int hotkeys_MakeHotkey(lua_State *L) mod = (1 << (luaL_checkoption(L, 1, NULL, mods) - 1)); break; case LUA_TTABLE: - lua_pushnil(L); - while (lua_next(L, 1) != 0) - { + for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) mod |= (1 << (luaL_checkoption(L, -1, NULL, mods) - 1)); - lua_pop(L, 1); - } break; default: luaL_argerror(L, 1, luaL_typename(L, 1)); diff --git a/plugins/MirLua/src/m_http.cpp b/plugins/MirLua/src/m_http.cpp new file mode 100644 index 0000000000..ce09fdb392 --- /dev/null +++ b/plugins/MirLua/src/m_http.cpp @@ -0,0 +1,443 @@ +#include "stdafx.h" + +/***********************************************/ + +#define MT_NETLIBHTTPHEADERS "NETLIBHTTPHEADERS" + +struct NETLIBHTTPHEADERS +{ + const NETLIBHTTPHEADER *headers; + int count; +}; + +static void AddHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) +{ + request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, + sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); + NETLIBHTTPHEADER &header = request->headers[request->headersCount]; + header.szName = mir_strdup(name); + header.szValue = mir_strdup(value); + request->headersCount++; +} + +static void SetHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) +{ + for (int i = 0; i < request->headersCount; i++) { + if (mir_strcmp(request->headers[i].szName, name) == 0) { + mir_free(request->headers[i].szValue); + request->headers[i].szValue = mir_strdup(value); + return; + } + } + AddHeader(request, name, value); +} + +static int headers_Iterator(lua_State *L) +{ + NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)lua_touserdata(L, lua_upvalueindex(1)); + int count = lua_tointeger(L, lua_upvalueindex(2)); + int idx = lua_tointeger(L, lua_upvalueindex(3)); + + if (idx < count) { + lua_pushstring(L, headers[idx].szName); + lua_pushstring(L, headers[idx].szValue); + lua_pushinteger(L, idx + 1); + lua_replace(L, lua_upvalueindex(3)); + return 2; + } + + lua_pushnil(L); + + return 1; +} + +static int headers__call(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + lua_pushlightuserdata(L, (void*)headers->headers); + lua_pushinteger(L, headers->count); + lua_pushinteger(L, 0); + lua_pushcclosure(L, headers_Iterator, 3); + + return 1; +} + +static int headers__index(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + if (lua_isinteger(L, 2)) { + int idx = lua_tointeger(L, 2); + if (idx > 0 && idx <= headers->count) { + lua_pushstring(L, headers->headers[idx - 1].szValue); + return 1; + } + } + + const char *key = lua_tostring(L, 2); + for (int i = 0; i < headers->count; i++) { + if (mir_strcmp(headers->headers[i].szName, key) == 0) { + lua_pushstring(L, headers->headers[i].szValue); + return 1; + } + } + + lua_pushnil(L); + + return 1; +} + +static int headers__len(lua_State *L) +{ + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); + + lua_pushinteger(L, headers->count); + + return 1; +} + +static const luaL_Reg headersApi[] = +{ + { "__call", headers__call }, + { "__index", headers__index }, + { "__len", headers__len }, + + { NULL, NULL } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPCONTENT "NETLIBHTTPCONTENT" + +struct NETLIBHTTPCONTENT +{ + const char *data; + int length; +}; + +static int content__index(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + int idx = luaL_checkinteger(L, 2); + if (idx > 0 && idx <= content->length) { + lua_pushinteger(L, content->data[idx - 1]); + return 1; + } + + lua_pushnil(L); + + return 1; +} + +static int content__len(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + lua_pushinteger(L, content->length); + + return 1; +} + +static int content__tostring(lua_State *L) +{ + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)luaL_checkudata(L, 1, MT_NETLIBHTTPCONTENT); + + lua_pushlstring(L, content->data, content->length); + + return 1; +} + +static const luaL_Reg contentApi[] = +{ + { "__index", content__index }, + { "__len", content__len }, + { "__tostring", content__tostring }, + + { NULL, NULL } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPRESPONSE "NETLIBHTTPRESPONSE" + +static NETLIBHTTPREQUEST* response_Create(lua_State *L, NETLIBHTTPREQUEST *request) +{ + NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + *response = Netlib_HttpTransaction(hNetlib, request); + luaL_setmetatable(L, MT_NETLIBHTTPRESPONSE); + + return *response; +} + +static int response__index(lua_State *L) +{ + NETLIBHTTPREQUEST *response = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + const char *key = lua_tostring(L, 2); + + if (mir_strcmpi(key, "Headers") == 0) { + NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)lua_newuserdata(L, sizeof(NETLIBHTTPHEADERS)); + headers->headers = response->headers; + headers->count = response->headersCount; + luaL_setmetatable(L, MT_NETLIBHTTPHEADERS); + } + else if (mir_strcmpi(key, "Content") == 0) { + NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)lua_newuserdata(L, sizeof(NETLIBHTTPCONTENT)); + content->data = response->pData; + content->length = response->dataLength; + luaL_setmetatable(L, MT_NETLIBHTTPCONTENT); + } + else if (mir_strcmpi(key, "StatusCode") == 0) + lua_pushinteger(L, response->resultCode); + else if (mir_strcmpi(key, "IsSuccess") == 0) { + lua_pushboolean(L, HTTP_CODE_SUCCESS(response->resultCode)); + } + else + lua_pushnil(L); + + return 1; +} + +static int response__gc(lua_State *L) +{ + NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + + Netlib_FreeHttpRequest(*response); + + return 0; +} + +static const luaL_Reg responseApi[] = +{ + { "__index", response__index }, + { "__gc", response__gc }, + + { NULL, NULL } +}; + +/***********************************************/ + +#define MT_NETLIBHTTPREQUEST "NETLIBHTTPREQUEST" + +static NETLIBHTTPREQUEST* CreateRequest(lua_State *L) +{ + NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + *request = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + (*request)->cbSize = sizeof(NETLIBHTTPREQUEST); + (*request)->flags = NLHRF_HTTP11 | NLHRF_NODUMP; + + luaL_setmetatable(L, MT_NETLIBHTTPREQUEST); + + return *request; +} + +static void request_SetUrl(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + const char *url = luaL_checkstring(L, idx); + request->szUrl = mir_strdup(url); + if (mir_strncmpi(request->szUrl, "https", 5) == 0) + request->flags |= NLHRF_SSL; + else + request->flags &= ~(NLHRF_SSL); +} + +static void request_SetHeaders(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + if (lua_isnoneornil(L, idx)) + return; + + luaL_checktype(L, idx, LUA_TTABLE); + + idx = lua_absindex(L, idx); + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *name = lua_tostring(L, -1); + const char *value = lua_tostring(L, -2); + AddHeader(request, name, value); + } +} + +static void request_SetContent(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + CMStringA data; + + switch (lua_type(L, idx)) + { + case LUA_TNONE: + case LUA_TNIL: + return; + case LUA_TSTRING: + data = lua_tostring(L, idx); + SetHeader(request, "Content-Type", "text/plain"); + break; + case LUA_TTABLE: + { + idx = lua_absindex(L, idx); + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 2)) { + lua_pushvalue(L, -2); + const char *name = lua_tostring(L, -1); + const char *value = lua_tostring(L, -2); + data.AppendFormat("&%s=%s", name, value); + } + data.Delete(0); + SetHeader(request, "Content-Type", "application/x-www-form-urlencoded"); + break; + } + default: + luaL_argerror(L, idx, luaL_typename(L, idx)); + } + + request->pData = mir_strdup(data); + request->dataLength = data.GetLength(); +} + +static void request_SetContentType(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +{ + if (!lua_isstring(L, 2)) + return; + + const char *type = lua_tostring(L, 2); + SetHeader(request, "Content-Type", type); +} + +static const char *httpMethods[] = { "GET", "POST", "PUT", "DELETE", NULL }; + +static int request_Send(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + NETLIBHTTPREQUEST *request = CreateRequest(L); + + lua_getfield(L, 1, "Method"); + request->requestType = (1 << (luaL_checkoption(L, -1, NULL, httpMethods))); + lua_pop(L, 1); + + lua_getfield(L, 1, "Url"); + request_SetUrl(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Headers"); + request_SetHeaders(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Content"); + request_SetContent(L, -1, request); + lua_pop(L, 1); + + lua_getfield(L, 1, "Timeout"); + request->timeout = luaL_optinteger(L, -1, 0); + lua_pop(L, 1); + + response_Create(L, request); + + return 1; +} + +static int request_Get(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_GET; + request_SetUrl(L, 1, request); + + response_Create(L, request); + + return 1; +} + +static int request_Post(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_POST; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 3, request); + + response_Create(L, request); + + return 1; +} + +static int request_Put(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_PUT; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 3, request); + + response_Create(L, request); + + return 1; +} + +static int request_Delete(lua_State *L) +{ + NETLIBHTTPREQUEST *request = CreateRequest(L); + request->requestType = REQUEST_DELETE; + request_SetUrl(L, 1, request); + request_SetContent(L, 2, request); + request_SetContentType(L, 2, request); + + response_Create(L, request); + + return 1; +} + +static int request__gc(lua_State *L) +{ + NETLIBHTTPREQUEST **request = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + + mir_free((*request)->szUrl); + for (size_t i = 0; i < (*request)->headersCount; i++) { + mir_free((*request)->headers[i].szName); + mir_free((*request)->headers[i].szValue); + } + mir_free((*request)->headers); + mir_free((*request)->pData); + + return 0; +} + +static const luaL_Reg requestApi[] = +{ + { "__gc", request__gc }, + + { NULL, NULL } +}; + +/***********************************************/ + +static const luaL_Reg httpApi[] = +{ + { "Send", request_Send }, + { "Get", request_Get }, + { "Post", request_Post }, + { "Put", request_Put }, + { "Delete", request_Delete }, + + { NULL, NULL } +}; + +LUAMOD_API int luaopen_m_http(lua_State *L) +{ + luaL_newlib(L, httpApi); + + luaL_newmetatable(L, MT_NETLIBHTTPREQUEST); + luaL_setfuncs(L, requestApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPRESPONSE); + luaL_setfuncs(L, responseApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPHEADERS); + luaL_setfuncs(L, headersApi, 0); + lua_pop(L, 1); + + luaL_newmetatable(L, MT_NETLIBHTTPCONTENT); + luaL_setfuncs(L, contentApi, 0); + lua_pop(L, 1); + + return 1; +} diff --git a/plugins/MirLua/src/m_json.cpp b/plugins/MirLua/src/m_json.cpp new file mode 100644 index 0000000000..e4bbf233ef --- /dev/null +++ b/plugins/MirLua/src/m_json.cpp @@ -0,0 +1,227 @@ +#include "stdafx.h" + +static void lua2json(lua_State *L, JSONNode &node) +{ + switch (lua_type(L, -1)) + { + case LUA_TNIL: + node.nullify(); + break; + case LUA_TSTRING: + node = lua_tostring(L, -1); + break; + case LUA_TBOOLEAN: + node = lua_toboolean(L, -1) != 0; + break; + case LUA_TNUMBER: + { + lua_Integer val = lua_tointeger(L, -1); + if (lua_isinteger(L, -1) && val >= LONG_MIN && val <= LONG_MIN) + node = (long)val; + else + node = lua_tonumber(L, -1); + break; + } + case LUA_TTABLE: + { + ptrA name(mir_strdup(node.name())); + node.cast(JSON_ARRAY); + node.set_name((char*)name); + + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + JSONNode child; + if (!lua_isnumber(L, -2)) { + if (node.type() == JSON_ARRAY) { + node.cast(JSON_NODE); + node.set_name((char*)name); + } + const char *key = lua_tostring(L, -2); + child.set_name(key); + } + lua2json(L, child); + node << child; + + lua_pop(L, 1); + } + + break; + } + } +} + +/***********************************************/ + +static int json__index(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + + switch (node.type()) + { + case JSON_NULL: + lua_pushnil(L); + break; + case JSON_STRING: + lua_pushstring(L, node.as_string().c_str()); + break; + case JSON_NUMBER: + lua_pushnumber(L, node.as_int()); + break; + case JSON_BOOL: + lua_pushboolean(L, node.as_bool()); + break; + case JSON_NODE: + case JSON_ARRAY: + new (L) JSONNode(node); + luaL_setmetatable(L, MT_JSON); + } + + return 1; +} + +static int json__newindex(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + const char *key = lua_tostring(L, 2); + + JSONNode child = node[key]; + if (child.isnull()) { + child.set_name(key); + lua2json(L, child); + node << child; + return 0; + } + + lua2json(L, child); + node[key] = child; + + return 0; +} + +static int json__len(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + + lua_pushnumber(L, node.size()); + + return 1; +} + +static int json__tostring(lua_State *L) +{ + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + + lua_pushstring(L, node.write().c_str()); + + return 1; +} + +static int json__gc(lua_State *L) +{ + JSON *json = (JSON*)luaL_checkudata(L, 1, MT_JSON); + + delete json; + + return 0; +} + +const struct luaL_Reg jsonApi[] = +{ + { "__index", json__index }, + { "__newindex", json__newindex }, + { "__len", json__len }, + { "__tostring", json__tostring }, + { "__gc", json__gc }, + + { NULL, NULL } +}; + + +/***********************************************/ + +static int lua_Decode(lua_State *L) +{ + const char *string = luaL_checkstring(L, 1); + + JSONNode *node = json_parse(string); + new (L) JSON(node); + luaL_setmetatable(L, MT_JSON); + + return 1; +} + +static int lua_Encode(lua_State *L) +{ + switch (lua_type(L, 1)) + { + case LUA_TNIL: + lua_pushliteral(L, "null"); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, lua_toboolean(L, 1) ? "true" : "false"); + break; + case LUA_TNUMBER: + { + if (lua_isinteger(L, 1)) { + lua_pushfstring(L, "%I", lua_tointeger(L, 1)); + break; + } + char decpoint = lua_getlocaledecpoint(); + if (decpoint != '.') { + char p[2] = { decpoint }; + luaL_gsub(L, lua_tostring(L, 1), p, "."); + } + else + lua_pushfstring(L, "%f", lua_tonumber(L, 1)); + break; + } + case LUA_TSTRING: + lua_pushfstring(L, "\"%s\"", lua_tostring(L, 1)); + break; + case LUA_TTABLE: + { + JSONNode node; + lua_pushnil(L); + lua_pushvalue(L, 1); + lua2json(L, node); + lua_pop(L, 2); + lua_pushstring(L, node.write().c_str()); + break; + } + case LUA_TUSERDATA: + { + JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + lua_pushstring(L, node.write().c_str()); + break; + } + case LUA_TLIGHTUSERDATA: + if (lua_touserdata(L, 1) == NULL) + { + lua_pushliteral(L, "null"); + break; + } + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + return 1; +} + +static const luaL_Reg methods[] = +{ + { "Decode", lua_Decode }, + { "Encode", lua_Encode }, + + { NULL, NULL } +}; + +LUAMOD_API int luaopen_m_json(lua_State *L) +{ + luaL_newlib(L, methods); + + luaL_newmetatable(L, MT_JSON); + luaL_setfuncs(L, jsonApi, 0); + lua_pop(L, 1); + + return 1; +} \ No newline at end of file diff --git a/plugins/MirLua/src/m_json.h b/plugins/MirLua/src/m_json.h new file mode 100644 index 0000000000..bb3a2e1568 --- /dev/null +++ b/plugins/MirLua/src/m_json.h @@ -0,0 +1,32 @@ +#ifndef _LUA_M_JSON_H_ +#define _LUA_M_JSON_H_ + +#include + +struct JSON +{ + JSONNode *node; + bool bDelete; + + JSON(JSONNode &refNode, bool bCopy = false) + : node(bCopy ? json_copy(&refNode) : &refNode), bDelete(bCopy) { } + JSON(JSONNode *n, bool bD = true) + : node(n), bDelete(bD) { } + ~JSON() + { + if (bDelete) + json_delete(node); + } + + __inline void* operator new(size_t size, lua_State *L) + { + return lua_newuserdata(L, size); + } +}; + +#define MT_JSON "JSON" + +#define MLUA_JSON "m_json" +LUAMOD_API int (luaopen_m_json)(lua_State *L); + +#endif //_LUA_M_PROTOCOLS_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/m_protocols.cpp b/plugins/MirLua/src/m_protocols.cpp index 42b24c4936..ab206489f2 100644 --- a/plugins/MirLua/src/m_protocols.cpp +++ b/plugins/MirLua/src/m_protocols.cpp @@ -64,6 +64,21 @@ static int lua_Protocols(lua_State *L) return 1; } +static int lua_RegisterProtocol(lua_State *L) +{ + ptrA name(mir_utf8decodeA(luaL_checkstring(L, 1))); + + PROTOCOLDESCRIPTOR pd = { 0 }; + pd.cbSize = sizeof(pd); + pd.szName = name; + pd.type = PROTOTYPE_PROTOCOL; + int res = Proto_RegisterModule(&pd); + + lua_pushboolean(L, res == 0); + + return 1; +} + static int lua_ChainSend(lua_State *L) { MCONTACT hContact = luaL_checknumber(L, 1); @@ -222,6 +237,7 @@ static luaL_Reg protocolsApi[] = { { "GetProtocol", lua_GetProtocol }, { "Protocols", lua_Protocols }, + { "RegisterProtocol", lua_Protocols }, { "CallSendChain", lua_ChainSend }, { "CallReceiveChain", lua_ChainRecv }, diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp index 0dd0488d5c..7cb6ce4981 100644 --- a/plugins/MirLua/src/main.cpp +++ b/plugins/MirLua/src/main.cpp @@ -76,7 +76,7 @@ extern "C" int __declspec(dllexport) Load(void) HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); NETLIBUSER nlu = {}; - nlu.flags = NUF_NOOPTIONS; + nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS; nlu.szDescriptiveName.a = MODULE; nlu.szSettingsModule = MODULE; hNetlib = Netlib_RegisterUser(&nlu); diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index d3ded45a40..952e528e44 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -39,12 +39,13 @@ static int mlua_print(lua_State *L) break; case LUA_TNUMBER: data.AppendFormat("%s", lua_tostring(L, i)); + break; case LUA_TSTRING: data.AppendFormat("'%s'", lua_tostring(L, i)); break; default: if (luaL_callmeta(L, i, "__tostring")) { - data.AppendFormat("[[%s]]", lua_tostring(L, i)); + data.AppendFormat("'%s'", lua_tostring(L, -1)); break; } data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i)); @@ -142,24 +143,19 @@ static int mlua_interpolate(lua_State *L) char pattern[128]; - if (lua_istable(L, 2)) - { - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) - { + if (lua_istable(L, 2)) { + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 2)) { lua_pushvalue(L, -2); const char *key = lua_tostring(L, -1); const char *val = lua_tostring(L, -2); mir_snprintf(pattern, "{%s}", key); string = luaL_gsub(L, string, pattern, val); - lua_pop(L, 1); } } - else - { + else { int nargs = lua_gettop(L); - for (int i = 2; i <= nargs; i++) - { + for (int i = 2; i <= nargs; i++) { const char *val = lua_tostring(L, i); mir_snprintf(pattern, "{%d}", i - 1); diff --git a/plugins/MirLua/src/mlua_module_loader.cpp b/plugins/MirLua/src/mlua_module_loader.cpp index a35801373a..c28e6edaeb 100644 --- a/plugins/MirLua/src/mlua_module_loader.cpp +++ b/plugins/MirLua/src/mlua_module_loader.cpp @@ -30,9 +30,11 @@ void CMLuaModuleLoader::LoadModules() Preload(MLUA_CHAT, luaopen_m_chat); Preload(MLUA_CLIST, luaopen_m_clist); Preload(MLUA_DATABASE, luaopen_m_database); - Preload(MLUA_ICOLIB, luaopen_m_icolib); Preload(MLUA_GENMENU, luaopen_m_genmenu); Preload(MLUA_HOTKEYS, luaopen_m_hotkeys); + Preload(MLUA_HTTP, luaopen_m_http); + Preload(MLUA_ICOLIB, luaopen_m_icolib); + Preload(MLUA_JSON, luaopen_m_json); Preload(MLUA_MESSAGE, luaopen_m_message); Preload(MLUA_OPTIONS, luaopen_m_options); Preload(MLUA_PROTOCOLS, luaopen_m_protocols); diff --git a/plugins/MirLua/src/mlua_script.cpp b/plugins/MirLua/src/mlua_script.cpp index 8b56674230..ad70bef24c 100644 --- a/plugins/MirLua/src/mlua_script.cpp +++ b/plugins/MirLua/src/mlua_script.cpp @@ -44,7 +44,6 @@ CMLuaScript::~CMLuaScript() lua_pop(L, 1); mir_free(moduleName); - mir_free(fileName); } const char* CMLuaScript::GetModuleName() const diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index 08b15a246e..4b5ad5a78b 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -11,7 +11,7 @@ #include #include #include - +#include #include #include #include @@ -20,7 +20,6 @@ #include #include #include - #include #include #include @@ -73,8 +72,13 @@ LUAMOD_API int (luaopen_m_clist)(lua_State *L); #define MLUA_ICOLIB "m_icolib" LUAMOD_API int (luaopen_m_icolib)(lua_State *L); +#include "m_json.h" + #include "m_genmenu.h" +#define MLUA_HTTP "m_http" +LUAMOD_API int (luaopen_m_http)(lua_State *L); + #define MLUA_HOTKEYS "m_hotkeys" LUAMOD_API int (luaopen_m_hotkeys)(lua_State *L); diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h index 4f3f3a4c6e..1525666f2a 100644 --- a/plugins/MirLua/src/version.h +++ b/plugins/MirLua/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 11 #define __RELEASE_NUM 8 -#define __BUILD_NUM 4 +#define __BUILD_NUM 5 #include -- cgit v1.2.3