You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_classifier.c 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (c) 2009, Rambler media
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY Rambler media ''AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "lua_common.h"
  25. #include "../cfg_file.h"
  26. #include "../classifiers/classifiers.h"
  27. /* Classifier methods */
  28. LUA_FUNCTION_DEF (classifier, register_pre_callback);
  29. LUA_FUNCTION_DEF (classifier, register_post_callback);
  30. LUA_FUNCTION_DEF (classifier, get_statfiles);
  31. static const struct luaL_reg classifierlib_m[] = {
  32. LUA_INTERFACE_DEF (classifier, register_pre_callback),
  33. LUA_INTERFACE_DEF (classifier, register_post_callback),
  34. LUA_INTERFACE_DEF (classifier, get_statfiles),
  35. {"__tostring", lua_class_tostring},
  36. {NULL, NULL}
  37. };
  38. static const struct luaL_reg statfilelib_m[] = {
  39. {"__tostring", lua_class_tostring},
  40. {NULL, NULL}
  41. };
  42. struct classifier_callback_data {
  43. lua_State *L;
  44. const gchar *name;
  45. };
  46. static struct statfile* lua_check_statfile (lua_State * L);
  47. /* Classifier implementation */
  48. static struct classifier_config *
  49. lua_check_classifier (lua_State * L)
  50. {
  51. void *ud = luaL_checkudata (L, 1, "rspamd{classifier}");
  52. luaL_argcheck (L, ud != NULL, 1, "'classifier' expected");
  53. return *((struct classifier_config **)ud);
  54. }
  55. /* Return list of statfiles that should be checked for this message */
  56. GList *
  57. call_classifier_pre_callbacks (struct classifier_config *ccf, struct worker_task *task)
  58. {
  59. GList *res = NULL, *cur;
  60. struct classifier_callback_data *cd;
  61. struct classifier_config **pccf;
  62. struct worker_task **ptask;
  63. struct statfile *st;
  64. gint i, len;
  65. /* Go throught all callbacks and call them, appending results to list */
  66. cur = g_list_first (ccf->pre_callbacks);
  67. while (cur) {
  68. cd = cur->data;
  69. lua_getglobal (cd->L, cd->name);
  70. pccf = lua_newuserdata (cd->L, sizeof (struct classifier_config *));
  71. lua_setclass (cd->L, "rspamd{classifier}", -1);
  72. *pccf = ccf;
  73. ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *));
  74. lua_setclass (cd->L, "rspamd{task}", -1);
  75. *ptask = task;
  76. if (lua_pcall (cd->L, 2, 1, 0) != 0) {
  77. msg_warn ("error running function %s: %s", cd->name, lua_tostring (cd->L, -1));
  78. }
  79. else {
  80. if (lua_istable (cd->L, 1)) {
  81. len = lua_objlen (cd->L, 1);
  82. for (i = 1; i <= len; i ++) {
  83. lua_rawgeti (cd->L, 1, i);
  84. st = lua_check_statfile (cd->L);
  85. if (st) {
  86. res = g_list_prepend (res, st);
  87. }
  88. }
  89. }
  90. }
  91. cur = g_list_next (cur);
  92. }
  93. return res;
  94. }
  95. /* Return result mark for statfile */
  96. double
  97. call_classifier_post_callbacks (struct classifier_config *ccf, struct worker_task *task, double in)
  98. {
  99. struct classifier_callback_data *cd;
  100. struct classifier_config **pccf;
  101. struct worker_task **ptask;
  102. double out = in;
  103. GList *cur;
  104. /* Go throught all callbacks and call them, appending results to list */
  105. cur = g_list_first (ccf->pre_callbacks);
  106. while (cur) {
  107. cd = cur->data;
  108. lua_getglobal (cd->L, cd->name);
  109. pccf = lua_newuserdata (cd->L, sizeof (struct classifier_config *));
  110. lua_setclass (cd->L, "rspamd{classifier}", -1);
  111. *pccf = ccf;
  112. ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *));
  113. lua_setclass (cd->L, "rspamd{task}", -1);
  114. *ptask = task;
  115. lua_pushnumber (cd->L, out);
  116. if (lua_pcall (cd->L, 3, 1, 0) != 0) {
  117. msg_warn ("error running function %s: %s", cd->name, lua_tostring (cd->L, -1));
  118. }
  119. else {
  120. if (lua_isnumber (cd->L, 1)) {
  121. out = lua_tonumber (cd->L, 1);
  122. }
  123. }
  124. cur = g_list_next (cur);
  125. }
  126. return out;
  127. }
  128. static gint
  129. lua_classifier_register_pre_callback (lua_State *L)
  130. {
  131. struct classifier_config *ccf = lua_check_classifier (L);
  132. struct classifier_callback_data *cd;
  133. const gchar *name;
  134. if (ccf) {
  135. name = luaL_checkstring (L, 2);
  136. if (name) {
  137. cd = g_malloc (sizeof (struct classifier_callback_data));
  138. cd->name = g_strdup (name);
  139. cd->L = L;
  140. ccf->pre_callbacks = g_list_prepend (ccf->pre_callbacks, cd);
  141. }
  142. }
  143. return 0;
  144. }
  145. static gint
  146. lua_classifier_register_post_callback (lua_State *L)
  147. {
  148. struct classifier_config *ccf = lua_check_classifier (L);
  149. struct classifier_callback_data *cd;
  150. const gchar *name;
  151. if (ccf) {
  152. name = luaL_checkstring (L, 2);
  153. if (name) {
  154. cd = g_malloc (sizeof (struct classifier_callback_data));
  155. cd->name = g_strdup (name);
  156. cd->L = L;
  157. ccf->pre_callbacks = g_list_prepend (ccf->pre_callbacks, cd);
  158. }
  159. }
  160. return 0;
  161. }
  162. /* Return table of statfiles indexed by theirs name */
  163. static gint
  164. lua_classifier_get_statfiles (lua_State *L)
  165. {
  166. struct classifier_config *ccf = lua_check_classifier (L);
  167. GList *cur;
  168. struct statfile *st, **pst;
  169. if (ccf) {
  170. lua_newtable (L);
  171. cur = g_list_first (ccf->statfiles);
  172. while (cur) {
  173. st = cur->data;
  174. /* t['statfile_name'] = statfile */
  175. lua_pushstring (L, st->symbol);
  176. pst = lua_newuserdata (L, sizeof (struct statfile *));
  177. lua_setclass (L, "rspamd{statfile}", -1);
  178. *pst = st;
  179. lua_settable (L, -3);
  180. cur = g_list_next (cur);
  181. }
  182. }
  183. else {
  184. lua_pushnil (L);
  185. }
  186. return 1;
  187. }
  188. /* Statfile functions */
  189. static struct statfile *
  190. lua_check_statfile (lua_State * L)
  191. {
  192. void *ud = luaL_checkudata (L, 1, "rspamd{statfile}");
  193. luaL_argcheck (L, ud != NULL, 1, "'statfile' expected");
  194. return *((struct statfile **)ud);
  195. }
  196. /* Open functions */
  197. gint
  198. luaopen_classifier (lua_State * L)
  199. {
  200. lua_newclass (L, "rspamd{classifier}", classifierlib_m);
  201. luaL_openlib (L, "rspamd_classifier", null_reg, 0);
  202. return 1;
  203. }
  204. gint
  205. luaopen_statfile (lua_State * L)
  206. {
  207. lua_newclass (L, "rspamd{statfile}", statfilelib_m);
  208. luaL_openlib (L, "rspamd_statfile", null_reg, 0);
  209. return 1;
  210. }