From 25591d79bad7c201ee12717cde3c6c39e39e48e5 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 9 Jun 2011 17:33:07 +0400 Subject: [PATCH] * Add api for creating XML-rpc calls --- src/lua/lua_xmlrpc.c | 100 ++++++++++++++++++++++++++++++++++++++++++- src/printf.c | 12 ++++-- src/printf.h | 14 +++++- src/util.h | 10 ----- 4 files changed, 119 insertions(+), 17 deletions(-) diff --git a/src/lua/lua_xmlrpc.c b/src/lua/lua_xmlrpc.c index 7f08eef34..f0ba2d6c0 100644 --- a/src/lua/lua_xmlrpc.c +++ b/src/lua/lua_xmlrpc.c @@ -25,9 +25,11 @@ LUA_FUNCTION_DEF (xmlrpc, parse_reply); +LUA_FUNCTION_DEF (xmlrpc, make_request); static const struct luaL_reg xmlrpclib_m[] = { LUA_INTERFACE_DEF (xmlrpc, parse_reply), + LUA_INTERFACE_DEF (xmlrpc, make_request), {"__tostring", lua_class_tostring}, {NULL, NULL} }; @@ -362,7 +364,7 @@ xmlrpc_error (GMarkupParseContext *context, GError *error, gpointer user_data) msg_err ("xmlrpc parser error: %s", error->message, ud->parser_state); } -gint +static gint lua_xmlrpc_parse_reply (lua_State *L) { const gchar *data; @@ -395,6 +397,102 @@ lua_xmlrpc_parse_reply (lua_State *L) return 1; } +static gint +lua_xmlrpc_parse_table (lua_State *L, gint pos, gchar *databuf, gint pr, gsize size) +{ + gint r = pr; + + r += rspamd_snprintf (databuf + r, size - r, ""); + lua_pushnil (L); /* first key */ + while (lua_next (L, pos) != 0) { + /* uses 'key' (at index -2) and 'value' (at index -1) */ + if (lua_type (L, -2) != LUA_TSTRING) { + /* Ignore non sting keys */ + lua_pop(L, 1); + continue; + } + r += rspamd_snprintf (databuf + r, size - r, "%s", + lua_tostring (L, -2)); + switch (lua_type (L, -1)) { + case LUA_TNUMBER: + r += rspamd_snprintf (databuf + r, size - r, "%d", + lua_tointeger (L, -1)); + break; + case LUA_TBOOLEAN: + r += rspamd_snprintf (databuf + r, size - r, "%d", + lua_toboolean (L, -1) ? 1 : 0); + break; + case LUA_TSTRING: + r += rspamd_snprintf (databuf + r, size - r, "%s", + lua_tostring (L, -1)); + break; + case LUA_TTABLE: + /* Recursive call */ + r += lua_xmlrpc_parse_table (L, -1, databuf, r, sizeof (databuf)); + break; + } + r += rspamd_snprintf (databuf + r, size - r, ""); + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(L, 1); + } + r += rspamd_snprintf (databuf + r, size - r, ""); + + return r - pr; +} + +/* + * Internal limitation: xmlrpc request must NOT be more than + * BUFSIZ * 2 (16384 bytes) + */ +static gint +lua_xmlrpc_make_request (lua_State *L) +{ + gchar databuf[BUFSIZ * 2]; + const gchar *func; + gint r, top, i; + + func = luaL_checkstring (L, 1); + + if (func) { + r = rspamd_snprintf (databuf, sizeof(databuf), + "" + "%s", + func); + /* Extract arguments */ + top = lua_gettop (L); + /* Get additional options */ + for (i = 2; i <= top; i++) { + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, ""); + switch (lua_type (L, i)) { + case LUA_TNUMBER: + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "%d", + lua_tointeger (L, i)); + break; + case LUA_TBOOLEAN: + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "%d", + lua_toboolean (L, i) ? 1 : 0); + break; + case LUA_TSTRING: + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, "%s", + lua_tostring (L, i)); + break; + case LUA_TTABLE: + r += lua_xmlrpc_parse_table (L, i, databuf, r, sizeof (databuf)); + break; + } + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, ""); + } + + r += rspamd_snprintf (databuf + r, sizeof (databuf) - r, ""); + lua_pushlstring (L, databuf, r); + } + else { + lua_pushnil (L); + } + + return 1; +} + gint luaopen_xmlrpc (lua_State * L) { diff --git a/src/printf.c b/src/printf.c index 7bdb61cc3..a8bf0fdb1 100644 --- a/src/printf.c +++ b/src/printf.c @@ -138,7 +138,7 @@ rspamd_sprintf (gchar *buf, const gchar *fmt, ...) gint -rspamd_snprintf (gchar *buf, size_t max, const gchar *fmt, ...) +rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...) { gchar *p; va_list args; @@ -152,13 +152,17 @@ rspamd_snprintf (gchar *buf, size_t max, const gchar *fmt, ...) } gchar * -rspamd_escape_string (gchar *dst, const gchar *src, gsize len) +rspamd_escape_string (gchar *dst, const gchar *src, glong len) { gchar *buf = dst, *last = dst + len; guint8 c; const gchar *p = src; gunichar uc; + if (len <= 0) { + return dst; + } + while (*p && buf < last) { /* Detect utf8 */ uc = g_utf8_get_char_validated (p, last - buf); @@ -202,7 +206,7 @@ rspamd_escape_string (gchar *dst, const gchar *src, gsize len) } gchar * -rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args) +rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args) { gchar *p, zero, *last; gint d; @@ -213,7 +217,7 @@ rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args) guint width, sign, hex, max_width, frac_width, i; f_str_t *v; - if (max == 0) { + if (max <= 0) { return buf; } diff --git a/src/printf.h b/src/printf.h index 74f665a2d..0d41bdc80 100644 --- a/src/printf.h +++ b/src/printf.h @@ -55,7 +55,17 @@ */ gint rspamd_sprintf (gchar *buf, const gchar *fmt, ...); gint rspamd_fprintf (FILE *f, const gchar *fmt, ...); -gint rspamd_snprintf (gchar *buf, size_t max, const gchar *fmt, ...); -gchar *rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args); +gint rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...); +gchar *rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args); + +/* + * Escape rspamd string to write it to log file or other 7 bit prefferable places + * + * @param dst destination string + * @param src source string + * @param len length of destination buffer + * @return pointer to end of buffer + */ +gchar * rspamd_escape_string (gchar *dst, const gchar *src, glong len); #endif /* PRINTF_H_ */ diff --git a/src/util.h b/src/util.h index 1c29ba91d..73d96c759 100644 --- a/src/util.h +++ b/src/util.h @@ -119,16 +119,6 @@ void g_ptr_array_unref (GPtrArray *array); */ gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz); -/* - * Escape rspamd string to write it to log file or other 7 bit prefferable places - * - * @param dst destination string - * @param src source string - * @param len length of destination buffer - * @return pointer to end of buffer - */ -gchar * rspamd_escape_string (gchar *dst, const gchar *src, gsize len); - /* * Convert process type to its name * -- 2.39.5