webmcp
changeset 402:04172238d79b
Do not require "engine" field to be set for mondelefant.connect{...}; Fixed bugs in mondelefant.connect{...} that could have crashed Lua; Shortened Lua registry key for mondelefant library
author | jbe |
---|---|
date | Wed Jan 06 02:39:50 2016 +0100 (2016-01-06) |
parents | ad437022be90 |
children | 0cb4bf644f1b |
files | libraries/mondelefant/mondelefant_native.c |
line diff
1.1 --- a/libraries/mondelefant/mondelefant_native.c Mon Jan 04 00:48:47 2016 +0100 1.2 +++ b/libraries/mondelefant/mondelefant_native.c Wed Jan 06 02:39:50 2016 +0100 1.3 @@ -9,7 +9,7 @@ 1.4 // NOTE: Comments with format "// <number>" denote the Lua stack position 1.5 1.6 // prefix for all Lua registry entries of this library: 1.7 -#define MONDELEFANT_REGKEY "e449ba8d9a53d353_mondelefant_" 1.8 +#define MONDELEFANT_REGKEY "mondelefant_" 1.9 1.10 // registry key of module "mondelefant_native": 1.11 #define MONDELEFANT_MODULE_REGKEY (MONDELEFANT_REGKEY "module") 1.12 @@ -194,76 +194,63 @@ 1.13 // "connect" function of library, which establishes a database connection 1.14 // and returns a database connection handle: 1.15 static int mondelefant_connect(lua_State *L) { 1.16 - luaL_Buffer buf; // Lua string buffer to create 'conninfo' (see below) 1.17 const char *conninfo; // string for PQconnectdb function 1.18 PGconn *pgconn; // PGconn object as returned by PQconnectdb function 1.19 mondelefant_conn_t *conn; // C-structure for userdata 1.20 - // expect a table as first argument: 1.21 - luaL_checktype(L, 1, LUA_TTABLE); 1.22 - // if engine is anything but "postgresql", then raise error: 1.23 - lua_settop(L, 1); 1.24 - lua_getfield(L, 1, "engine"); // 2 1.25 - if (!lua_toboolean(L, 2)) { 1.26 - return luaL_argerror(L, 1, "no database engine selected"); 1.27 - } 1.28 - lua_pushliteral(L, "postgresql"); // 3 1.29 - if (!lua_rawequal(L, 2, 3)) { 1.30 - return luaL_argerror(L, 1, 1.31 - "only database engine 'postgresql' is supported" 1.32 - ); 1.33 - } 1.34 - // copy conninfo string for PQconnectdb function from argument table to 1.35 - // stack position 2: 1.36 - lua_settop(L, 1); 1.37 - lua_getfield(L, 1, "conninfo"); // 2 1.38 - // if no conninfo string was found, then assemble one from the named 1.39 - // options except "engine" option: 1.40 - if (!lua_toboolean(L, 2)) { 1.41 + // check if string is given as first argument: 1.42 + if (lua_type(L, 1) != LUA_TSTRING) { 1.43 + // expect a table as first argument if no string is given: 1.44 + luaL_checktype(L, 1, LUA_TTABLE); 1.45 + // copy conninfo string for PQconnectdb function from argument table to 1.46 + // stack position 2: 1.47 lua_settop(L, 1); 1.48 - lua_pushnil(L); // slot for key at stack position 2 1.49 - lua_pushnil(L); // slot for value at stack position 3 1.50 - luaL_buffinit(L, &buf); 1.51 - { 1.52 + lua_getfield(L, 1, "conninfo"); // 2 1.53 + // check if conninfo is set: 1.54 + if (!lua_isnil(L, 2)) { 1.55 + // if yes, use that value but check its type: 1.56 + luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING, 2, "\"conninfo\" value is not a string"); 1.57 + } else { 1.58 + // otherwise assemble conninfo string from the named options: 1.59 + luaL_Buffer buf; 1.60 int need_seperator = 0; 1.61 + const char *value; 1.62 + size_t value_len; 1.63 + size_t value_pos = 0; 1.64 + lua_settop(L, 1); 1.65 + lua_pushnil(L); // slot for key at stack position 2 1.66 + lua_pushnil(L); // slot for value at stack position 3 1.67 + luaL_buffinit(L, &buf); 1.68 while (lua_pushvalue(L, 2), lua_next(L, 1)) { 1.69 + luaL_argcheck(L, lua_isstring(L, -2), 1, "key in table is not a string"); 1.70 + luaL_argcheck(L, lua_isstring(L, -1), 1, "value in table is not a string"); 1.71 + value = lua_tolstring(L, -1, &value_len); 1.72 lua_replace(L, 3); 1.73 + lua_pop(L, 1); 1.74 lua_replace(L, 2); 1.75 + if (need_seperator) luaL_addchar(&buf, ' '); 1.76 // NOTE: numbers will be converted to strings automatically here, 1.77 // but perhaps this will change in future versions of lua 1.78 - luaL_argcheck(L, 1.79 - lua_isstring(L, 2) && lua_isstring(L, 3), 1, "key is not a string" 1.80 - ); 1.81 lua_pushvalue(L, 2); 1.82 - lua_pushliteral(L, "engine"); 1.83 - if (!lua_rawequal(L, -2, -1)) { 1.84 - const char *value; 1.85 - size_t value_len; 1.86 - size_t value_pos = 0; 1.87 - lua_pop(L, 1); 1.88 - if (need_seperator) luaL_addchar(&buf, ' '); 1.89 - luaL_addvalue(&buf); 1.90 - luaL_addchar(&buf, '='); 1.91 - luaL_addchar(&buf, '\''); 1.92 - value = lua_tolstring(L, 3, &value_len); 1.93 - do { 1.94 - char c; 1.95 - c = value[value_pos++]; 1.96 - if (c == '\'') luaL_addchar(&buf, '\\'); 1.97 - luaL_addchar(&buf, c); 1.98 - } while (value_pos < value_len); 1.99 - luaL_addchar(&buf, '\''); 1.100 - need_seperator = 1; 1.101 - } else { 1.102 - lua_pop(L, 1); 1.103 - } 1.104 + luaL_addvalue(&buf); 1.105 + luaL_addchar(&buf, '='); 1.106 + luaL_addchar(&buf, '\''); 1.107 + do { 1.108 + char c; 1.109 + c = value[value_pos++]; 1.110 + if (c == '\'') luaL_addchar(&buf, '\\'); 1.111 + luaL_addchar(&buf, c); 1.112 + } while (value_pos < value_len); 1.113 + luaL_addchar(&buf, '\''); 1.114 + need_seperator = 1; 1.115 } 1.116 + luaL_pushresult(&buf); 1.117 } 1.118 - luaL_pushresult(&buf); 1.119 - lua_replace(L, 2); 1.120 - lua_settop(L, 2); 1.121 + // ensure that string is on stack position 1 which is the top of stack: 1.122 + lua_replace(L, 1); 1.123 + lua_settop(L, 1); 1.124 } 1.125 - // use conninfo string on stack position 2: 1.126 - conninfo = lua_tostring(L, 2); 1.127 + // use conninfo string on stack position 1: 1.128 + conninfo = lua_tostring(L, 1); 1.129 // call PQconnectdb function of libpq: 1.130 pgconn = PQconnectdb(conninfo); 1.131 // throw or return errors, if neccessary: 1.132 @@ -273,18 +260,18 @@ 1.133 ); 1.134 } 1.135 if (PQstatus(pgconn) != CONNECTION_OK) { 1.136 - lua_pushnil(L); // 3 1.137 - mondelefant_push_first_line(L, PQerrorMessage(pgconn)); // 4 1.138 - lua_newtable(L); // 5 1.139 + lua_pushnil(L); // 2 1.140 + mondelefant_push_first_line(L, PQerrorMessage(pgconn)); // 3 1.141 + lua_newtable(L); // 4 1.142 lua_getfield(L, 1.143 LUA_REGISTRYINDEX, 1.144 MONDELEFANT_ERROROBJECT_MT_REGKEY 1.145 ); 1.146 - lua_setmetatable(L, 5); 1.147 + lua_setmetatable(L, 4); 1.148 lua_pushliteral(L, MONDELEFANT_ERRCODE_CONNECTION); 1.149 - lua_setfield(L, 5, "code"); 1.150 - lua_pushvalue(L, 4); 1.151 - lua_setfield(L, 5, "message"); 1.152 + lua_setfield(L, 4, "code"); 1.153 + lua_pushvalue(L, 3); 1.154 + lua_setfield(L, 4, "message"); 1.155 PQfinish(pgconn); 1.156 return 3; 1.157 }