trunk/src/emu/webengine.c
| r32024 | r32025 | |
| 14 | 14 | #include "emuopts.h" |
| 15 | 15 | #include "ui/ui.h" |
| 16 | 16 | #include "webengine.h" |
| 17 | #include "lua/lua.hpp" |
| 17 | 18 | |
| 18 | 19 | |
| 20 | |
| 19 | 21 | //************************************************************************** |
| 20 | 22 | // WEB ENGINE |
| 21 | 23 | //************************************************************************** |
| r32024 | r32025 | |
| 130 | 132 | return MG_TRUE; |
| 131 | 133 | } |
| 132 | 134 | |
| 135 | void reg_string(struct lua_State *L, const char *name, const char *val) { |
| 136 | lua_pushstring(L, name); |
| 137 | lua_pushstring(L, val); |
| 138 | lua_rawset(L, -3); |
| 139 | } |
| 140 | |
| 141 | void reg_int(struct lua_State *L, const char *name, int val) { |
| 142 | lua_pushstring(L, name); |
| 143 | lua_pushinteger(L, val); |
| 144 | lua_rawset(L, -3); |
| 145 | } |
| 146 | |
| 147 | void reg_function(struct lua_State *L, const char *name, |
| 148 | lua_CFunction func, struct mg_connection *conn) { |
| 149 | lua_pushstring(L, name); |
| 150 | lua_pushlightuserdata(L, conn); |
| 151 | lua_pushcclosure(L, func, 1); |
| 152 | lua_rawset(L, -3); |
| 153 | } |
| 154 | |
| 155 | static int lua_write(lua_State *L) { |
| 156 | int i, num_args; |
| 157 | const char *str; |
| 158 | size_t size; |
| 159 | struct mg_connection *conn = (struct mg_connection *) |
| 160 | lua_touserdata(L, lua_upvalueindex(1)); |
| 161 | |
| 162 | num_args = lua_gettop(L); |
| 163 | for (i = 1; i <= num_args; i++) { |
| 164 | if (lua_isstring(L, i)) { |
| 165 | str = lua_tolstring(L, i, &size); |
| 166 | mg_send_data(conn, str, size); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | return 0; |
| 171 | } |
| 172 | |
| 173 | static int lua_header(lua_State *L) { |
| 174 | struct mg_connection *conn = (struct mg_connection *) |
| 175 | lua_touserdata(L, lua_upvalueindex(1)); |
| 176 | |
| 177 | const char *header = luaL_checkstring(L,1); |
| 178 | const char *value = luaL_checkstring(L,2); |
| 179 | |
| 180 | mg_send_header(conn, header, value); |
| 181 | |
| 182 | return 0; |
| 183 | } |
| 184 | |
| 185 | |
| 186 | static void prepare_lua_environment(struct mg_connection *ri, lua_State *L) { |
| 187 | extern void luaL_openlibs(lua_State *); |
| 188 | int i; |
| 189 | |
| 190 | luaL_openlibs(L); |
| 191 | |
| 192 | if (ri == NULL) return; |
| 193 | |
| 194 | // Register mg module |
| 195 | lua_newtable(L); |
| 196 | reg_function(L, "write", lua_write, ri); |
| 197 | reg_function(L, "header", lua_header, ri); |
| 198 | |
| 199 | // Export request_info |
| 200 | lua_pushstring(L, "request_info"); |
| 201 | lua_newtable(L); |
| 202 | reg_string(L, "request_method", ri->request_method); |
| 203 | reg_string(L, "uri", ri->uri); |
| 204 | reg_string(L, "http_version", ri->http_version); |
| 205 | reg_string(L, "query_string", ri->query_string); |
| 206 | reg_string(L, "remote_ip", ri->remote_ip); |
| 207 | reg_int(L, "remote_port", ri->remote_port); |
| 208 | reg_string(L, "local_ip", ri->local_ip); |
| 209 | reg_int(L, "local_port", ri->local_port); |
| 210 | lua_pushstring(L, "content"); |
| 211 | lua_pushlstring(L, ri->content == NULL ? "" : ri->content, ri->content_len); |
| 212 | lua_rawset(L, -3); |
| 213 | reg_int(L, "num_headers", ri->num_headers); |
| 214 | lua_pushstring(L, "http_headers"); |
| 215 | lua_newtable(L); |
| 216 | for (i = 0; i < ri->num_headers; i++) { |
| 217 | reg_string(L, ri->http_headers[i].name, ri->http_headers[i].value); |
| 218 | } |
| 219 | lua_rawset(L, -3); |
| 220 | lua_rawset(L, -3); |
| 221 | |
| 222 | lua_setglobal(L, "mg"); |
| 223 | |
| 224 | } |
| 225 | |
| 226 | |
| 227 | static void lsp(struct mg_connection *conn, const char *p, int len, lua_State *L) { |
| 228 | int i, j, pos = 0; |
| 229 | for (i = 0; i < len; i++) { |
| 230 | if (p[i] == '<' && p[i + 1] == '?') { |
| 231 | for (j = i + 1; j < len ; j++) { |
| 232 | if (p[j] == '?' && p[j + 1] == '>') { |
| 233 | if (i-pos!=0) mg_send_data(conn, p + pos, i - pos); |
| 234 | if (luaL_loadbuffer(L, p + (i + 2), j - (i + 2), "") == 0) { |
| 235 | lua_pcall(L, 0, LUA_MULTRET, 0); |
| 236 | } |
| 237 | pos = j + 2; |
| 238 | i = pos - 1; |
| 239 | break; |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | if (i > pos) { |
| 245 | mg_send_data(conn, p + pos, i - pos); |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | static int filename_endswith(const char *str, const char *suffix) |
| 250 | { |
| 251 | if (!str || !suffix) |
| 252 | return 0; |
| 253 | size_t lenstr = strlen(str); |
| 254 | size_t lensuffix = strlen(suffix); |
| 255 | if (lensuffix > lenstr) |
| 256 | return 0; |
| 257 | return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; |
| 258 | } |
| 259 | |
| 133 | 260 | // This function will be called by mongoose on every new request. |
| 134 | 261 | int web_engine::begin_request_handler(struct mg_connection *conn) |
| 135 | 262 | { |
| 136 | | if (!strncmp(conn->uri, "/json/",6)) |
| 263 | astring file_path(mg_get_option(m_server, "document_root"), PATH_SEPARATOR, conn->uri); |
| 264 | if (filename_endswith(file_path,".lp")) |
| 137 | 265 | { |
| 266 | FILE *fp = NULL; |
| 267 | if ((fp = fopen(file_path, "rb")) != NULL) { |
| 268 | fseek (fp, 0, SEEK_END); |
| 269 | size_t size = ftell(fp); |
| 270 | fseek (fp, 0, SEEK_SET); |
| 271 | char *data = (char*)mg_mmap(fp,size); |
| 272 | |
| 273 | lua_State *L = luaL_newstate(); |
| 274 | prepare_lua_environment(conn, L); |
| 275 | lsp(conn, data, (int) size, L); |
| 276 | if (L != NULL) lua_close(L); |
| 277 | mg_munmap(data,size); |
| 278 | fclose(fp); |
| 279 | return MG_TRUE; |
| 280 | } else { |
| 281 | return MG_FALSE; |
| 282 | } |
| 283 | } |
| 284 | else if (!strncmp(conn->uri, "/json/",6)) |
| 285 | { |
| 138 | 286 | if (!strcmp(conn->uri, "/json/game")) |
| 139 | 287 | { |
| 140 | 288 | return json_game_handler(conn); |