Freeciv-3.3
Loading...
Searching...
No Matches
script_fcdb.c
Go to the documentation of this file.
1/*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12*****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdlib.h>
20#include <time.h>
21
22/* dependencies/lua */
23#include "lua.h"
24#include "lualib.h"
25
26/* dependencies/tolua */
27#include "tolua.h"
28
29/* dependencies/luasql */
30#ifdef HAVE_FCDB_MYSQL
31#include "ls_mysql.h"
32#endif
33#ifdef HAVE_FCDB_ODBC
34#include "ls_odbc.h"
35#endif
36#ifdef HAVE_FCDB_POSTGRES
37#include "ls_postgres.h"
38#endif
39#ifdef HAVE_FCDB_SQLITE3
40#include "ls_sqlite3.h"
41#endif
42
43/* utility */
44#include "capability.h"
45#include "log.h"
46#include "md5.h"
47#include "registry.h"
48#include "string_vector.h"
49
50/* common/scriptcore */
51#include "luascript.h"
52#include "luascript_types.h"
53#include "tolua_common_a_gen.h"
54#include "tolua_common_z_gen.h"
55#include "tolua_game_gen.h"
56
57/* server */
58#include "console.h"
59#include "srv_main.h"
60#include "stdinhand.h"
61
62/* server/scripting */
63#include "api_fcdb_specenum.h"
64
65#ifdef HAVE_FCDB
66#include <tolua_fcdb_gen.h> /* <> so looked from the build directory first. */
67#endif /* HAVE_FCDB */
68
69#include "script_fcdb.h"
70
71#ifdef HAVE_FCDB
72
73#define SCRIPT_FCDB_LUA_FILE "database.lua"
74
75#define FCDB_CAPS "+fcdb"
76
77static void script_fcdb_functions_define(void);
78static bool script_fcdb_functions_check(const char *fcdb_luafile);
79
80static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
81 const char *format, ...)
83
84/**********************************************************************/
88
89/**********************************************************************/
123{
124 luascript_func_add(fcl, "database_init", TRUE, 0, 0);
125 luascript_func_add(fcl, "database_capstr", TRUE, 0, 1, API_TYPE_STRING);
126 luascript_func_add(fcl, "database_free", TRUE, 0, 0);
127
128 luascript_func_add(fcl, "user_exists", TRUE, 1, 1, API_TYPE_CONNECTION,
130 luascript_func_add(fcl, "user_verify", TRUE, 2, 1, API_TYPE_CONNECTION,
132 luascript_func_add(fcl, "user_save", FALSE, 2, 0, API_TYPE_CONNECTION,
136 luascript_func_add(fcl, "user_delegate_to", FALSE, 3, 1,
139 luascript_func_add(fcl, "user_take", FALSE, 4, 1, API_TYPE_CONNECTION,
142 luascript_func_add(fcl, "conn_established", FALSE, 1, 0, API_TYPE_CONNECTION);
143 luascript_func_add(fcl, "game_start", FALSE, 1, 1,
145}
146
147/**********************************************************************/
150static bool script_fcdb_functions_check(const char *fcdb_luafile)
151{
152 bool ret = TRUE;
155
159 log_error("Database script '%s' does not define the required function "
160 "'%s'.", fcdb_luafile, func_name);
161 ret = FALSE;
164 log_verbose("Database script '%s' does not define the optional "
165 "function '%s'.", fcdb_luafile, func_name);
167 }
168
171
172 return ret;
173}
174
175/**********************************************************************/
178static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
179 const char *format, ...)
180{
181 va_list args;
183 char buf[1024];
184
185 va_start(args, format);
186 fc_vsnprintf(buf, sizeof(buf), format, args);
187 va_end(args);
188
189 switch (level) {
190 case LOG_FATAL:
191 /* Special case - will quit the server. */
192 log_fatal("%s", buf);
193 break;
194 case LOG_ERROR:
195 case LOG_WARN:
197 break;
198 case LOG_NORMAL:
200 break;
201 case LOG_VERBOSE:
203 break;
204 case LOG_DEBUG:
206 break;
207 }
208
209 cmd_reply(CMD_FCDB, lfcl->caller, rfc_status, "%s", buf);
210}
211
212/**********************************************************************/
215static int md5sum(lua_State *L)
216{
217 int n = lua_gettop(L);
218 char sum[MD5_HEX_BYTES + 1];
219 const char *plaintext;
220 size_t len;
221
222 if (n != 1 || lua_type(L, -1) != LUA_TSTRING) {
223 lua_pushliteral(L, "invalid argument");
224 lua_error(L);
225 }
226
227 plaintext = lua_tolstring(L, -1, &len);
228 create_md5sum((unsigned char*)plaintext, len, sum);
229
230 lua_pushstring(L, sum);
231 return 1;
232}
233#endif /* HAVE_FCDB */
234
235/**********************************************************************/
240{
241#ifdef HAVE_FCDB
242 if (fcl != NULL) {
243 fc_assert_ret_val(fcl->state != NULL, FALSE);
244
245 return TRUE;
246 }
247
248 if (!fcdb_luafile) {
249 /* Use default freeciv database lua file. */
251 }
252
254 if (fcl == NULL) {
255 log_error("Error loading the Freeciv database lua definition.");
256 return FALSE;
257 }
258
259 tolua_common_a_open(fcl->state);
261 tolua_game_open(fcl->state);
262
263#ifdef MESON_BUILD
264 /* Tolua adds 'tolua_' prefix to _open() function names,
265 * and we can't pass it a basename where the original
266 * 'tolua_' has been stripped when generating from meson. */
268#else /* MESON_BUILD */
269 tolua_fcdb_open(fcl->state);
270#endif /* MESON_BUILD */
271 lua_register(fcl->state, "md5sum", md5sum);
272#ifdef HAVE_FCDB_MYSQL
273 luaL_requiref(fcl->state, "ls_mysql", luaopen_luasql_mysql, 1);
274 lua_pop(fcl->state, 1);
275#endif
276#ifdef HAVE_FCDB_ODBC
277 luaL_requiref(fcl->state, "ls_odbc", luaopen_luasql_odbc, 1);
278 lua_pop(fcl->state, 1);
279#endif
280#ifdef HAVE_FCDB_POSTGRES
281 luaL_requiref(fcl->state, "ls_postgres", luaopen_luasql_postgres, 1);
282 lua_pop(fcl->state, 1);
283#endif
284#ifdef HAVE_FCDB_SQLITE3
285 luaL_requiref(fcl->state, "ls_sqlite3", luaopen_luasql_sqlite3, 1);
286 lua_pop(fcl->state, 1);
287#endif
288 tolua_common_z_open(fcl->state);
289
291
292 /* Define the prototypes for the needed lua functions. */
294
297 log_error("Error loading the Freeciv database lua script '%s'.",
300 return FALSE;
301 }
302
303 if (srvarg.fcdb_enabled) {
304 if (!script_fcdb_call("database_init")) {
305 log_error("Error connecting to the database");
307 return FALSE;
308 }
309
310 if (!script_fcdb_capstr()) {
311 log_error(_("Database capabilities not compatible with server"));
312 return FALSE;
313 }
314 }
315
316#endif /* HAVE_FCDB */
317
318 return TRUE;
319}
320
321/**********************************************************************/
325{
326#ifdef HAVE_FCDB
327 static int checked = 0;
328 const char *fcdb_caps;
329
330 if (checked) {
331 return checked > 0;
332 }
333
334 script_fcdb_call("database_capstr", &fcdb_caps);
335
336 log_verbose("Server caps: %s", FCDB_CAPS);
337 log_verbose("DB caps: %s", fcdb_caps);
338
341 log_error(_("Database not compatible. Freeciv caps: %s, DB caps: %s"),
343 checked = -1; /* Negative */
344 return FALSE;
345 }
346
347 checked = 1; /* Positive */
348#endif /* HAVE_FCDB */
349
350 return TRUE;
351}
352
353/**********************************************************************/
359bool script_fcdb_call(const char *func_name, ...)
360{
361 bool success = TRUE;
362#ifdef HAVE_FCDB
363
364 va_list args;
365 va_start(args, func_name);
366
368 va_end(args);
369#endif /* HAVE_FCDB */
370
371 return success;
372}
373
374/**********************************************************************/
378{
379#ifdef HAVE_FCDB
380 if (!script_fcdb_call("database_free", 0)) {
381 log_error("Error closing the database connection. Continuing anyway...");
382 }
383
384 if (fcl) {
385 /* luascript_func_free() is called by luascript_destroy(). */
387 fcl = NULL;
388 }
389#endif /* HAVE_FCDB */
390}
391
392/**********************************************************************/
396bool script_fcdb_do_string(struct connection *caller, const char *str)
397{
398#ifdef HAVE_FCDB
399 int status;
400 struct connection *save_caller;
402
403 /* Set a log callback function which allows to send the results of the
404 * command to the clients. */
405 save_caller = fcl->caller;
406 save_output_fct = fcl->output_fct;
407 fcl->output_fct = script_fcdb_cmd_reply;
408 fcl->caller = caller;
409
411
412 /* Reset the changes. */
413 fcl->caller = save_caller;
414 fcl->output_fct = save_output_fct;
415
416 return (status == 0);
417#else
418 return TRUE;
419#endif /* HAVE_FCDB */
420}
int api_fcdb_specenum_open(lua_State *L)
#define str
Definition astring.c:76
#define n
Definition astring.c:77
bool has_capabilities(const char *us, const char *them)
Definition capability.c:88
@ CMD_FCDB
Definition commands.h:98
char * incite_cost
Definition comments.c:76
rfc_status
Definition console.h:35
@ C_DEBUG
Definition console.h:39
@ C_OK
Definition console.h:41
@ C_LOG_BASE
Definition console.h:40
@ C_COMMENT
Definition console.h:37
@ C_WARNING
Definition console.h:50
#define _(String)
Definition fcintl.h:67
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_fatal(message,...)
Definition log.h:101
log_level
Definition log.h:29
@ LOG_ERROR
Definition log.h:31
@ LOG_DEBUG
Definition log.h:35
@ LOG_NORMAL
Definition log.h:33
@ LOG_FATAL
Definition log.h:30
@ LOG_VERBOSE
Definition log.h:34
@ LOG_WARN
Definition log.h:32
#define log_error(message,...)
Definition log.h:104
int luascript_do_string(struct fc_lua *fcl, const char *str, const char *name)
Definition luascript.c:617
int luascript_do_file(struct fc_lua *fcl, const char *filename)
Definition luascript.c:637
struct fc_lua * luascript_new(luascript_log_func_t output_fct, bool secured_environment)
Definition luascript.c:332
void luascript_destroy(struct fc_lua *fcl)
Definition luascript.c:386
void(* luascript_log_func_t)(struct fc_lua *fcl, enum log_level level, const char *format,...) fc__attribute((__format__(__printf__
Definition luascript.h:39
bool luascript_func_call_valist(struct fc_lua *fcl, const char *func_name, va_list args)
bool luascript_func_check(struct fc_lua *fcl, struct strvec *missing_func_required, struct strvec *missing_func_optional)
void luascript_func_init(struct fc_lua *fcl)
void luascript_func_add(struct fc_lua *fcl, const char *func_name, bool required, int nargs, int nreturns,...)
void create_md5sum(const unsigned char *input, int len, char output[MD5_HEX_BYTES+1])
Definition md5.c:335
#define MD5_HEX_BYTES
Definition md5.h:21
int len
Definition packhand.c:127
void script_fcdb_free(void)
bool script_fcdb_do_string(struct connection *caller, const char *str)
bool script_fcdb_call(const char *func_name,...)
bool script_fcdb_init(const char *fcdb_luafile)
bool script_fcdb_capstr(void)
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
struct server_arguments srvarg
Definition srv_main.c:181
void cmd_reply(enum command_id cmd, struct connection *caller, enum rfc_status rfc_status, const char *format,...)
Definition stdinhand.c:420
void strvec_destroy(struct strvec *psv)
struct strvec * strvec_new(void)
#define strvec_iterate(psv, str)
#define strvec_iterate_end
enum auth_status status
Definition connection.h:217
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
#define fc__attribute(x)
Definition support.h:99
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
TOLUA_API int tolua_common_a_open(lua_State *tolua_S)
TOLUA_API int tolua_common_z_open(lua_State *tolua_S)
TOLUA_API int tolua_fcdb_open(lua_State *tolua_S)
TOLUA_API int tolua_game_open(lua_State *tolua_S)