]> source.dussan.org Git - rspamd.git/commitdiff
Move mimepart functions to a separate module.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Apr 2015 17:12:21 +0000 (18:12 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Apr 2015 17:12:21 +0000 (18:12 +0100)
src/lua/CMakeLists.txt
src/lua/lua_common.h
src/lua/lua_mimepart.c [new file with mode: 0644]
src/lua/lua_task.c

index ab4e85ac4cbc46b37589d10a17ed9068f4eaf7c8..57503a3b65caf2768080d081d8f925a6e101e334 100644 (file)
@@ -18,6 +18,7 @@ SET(LUASRC                      ${CMAKE_CURRENT_SOURCE_DIR}/lua_common.c
                                          ${CMAKE_CURRENT_SOURCE_DIR}/lua_rsa.c
                                          ${CMAKE_CURRENT_SOURCE_DIR}/lua_ip.c
                                          ${CMAKE_CURRENT_SOURCE_DIR}/lua_expression.c
-                                         ${CMAKE_CURRENT_SOURCE_DIR}/lua_trie.c)
+                                         ${CMAKE_CURRENT_SOURCE_DIR}/lua_trie.c
+                                         ${CMAKE_CURRENT_SOURCE_DIR}/lua_mimepart.c)
 
 SET(RSPAMD_LUA ${LUASRC} PARENT_SCOPE)
\ No newline at end of file
index cb53c05f2248ff187dd2ad7df68e94e3e600cf43..aaa13134e451a2428c07fd4c2abc7dc2076e3618 100644 (file)
@@ -147,6 +147,16 @@ struct rspamd_lua_ip * lua_check_ip (lua_State * L, gint pos);
 
 struct rspamd_lua_text * lua_check_text (lua_State * L, gint pos);
 
+/**
+ * Push specific header to lua
+ */
+gint rspamd_lua_push_header (lua_State * L,
+       GHashTable *hdrs,
+       const gchar *name,
+       gboolean strong,
+       gboolean full,
+       gboolean raw);
+
 /**
  * Check for task at the specified position
  */
diff --git a/src/lua/lua_mimepart.c b/src/lua/lua_mimepart.c
new file mode 100644 (file)
index 0000000..faadcf7
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2015, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lua_common.h"
+#include "message.h"
+#include "diff.h"
+
+/* Textpart methods */
+/***
+ * @module rspamd_textpart
+ * This module provides access to text parts found in a message
+ */
+
+LUA_FUNCTION_DEF (textpart, is_utf);
+
+/***
+ * @method textpart:get_content()
+ * Get parsed content of a part
+ * @return {string} text contained in the part
+ */
+LUA_FUNCTION_DEF (textpart, get_content);
+/***
+ * @method textpart:get_length()
+ * Get length of the text inside the part
+ * @return {integer} the lenght of text part in bytes
+ */
+LUA_FUNCTION_DEF (textpart, get_length);
+/***
+ * @method textpart:is_empty()
+ * Check whether a part is empty
+ * @return {bool} `true` if a part is empty
+ */
+LUA_FUNCTION_DEF (textpart, is_empty);
+/***
+ * @method textpart:is_html()
+ * Check whether a part contains HTML
+ * @return {bool} `true` if a part html part
+ */
+LUA_FUNCTION_DEF (textpart, is_html);
+/***
+ * @method textpart:get_fuzzy()
+ * Get fuzzy hash for a message
+ * @return {string} fuzzy hash of the part
+ */
+LUA_FUNCTION_DEF (textpart, get_fuzzy);
+/***
+ * @method textpart:get_language()
+ * Return short language code detected for the part
+ * @return {string} language code for the part or nil if language has not been detected
+ */
+LUA_FUNCTION_DEF (textpart, get_language);
+/***
+ * @method textpart:compare_distance(part)
+ * Compares two parts
+ * @param {textpart} another text part
+ * @return {number} similarity rate from 0.0 (different parts) to 1.0 (equal parts)
+ */
+LUA_FUNCTION_DEF (textpart, compare_distance);
+
+static const struct luaL_reg textpartlib_m[] = {
+       LUA_INTERFACE_DEF (textpart, is_utf),
+       LUA_INTERFACE_DEF (textpart, get_content),
+       LUA_INTERFACE_DEF (textpart, get_length),
+       LUA_INTERFACE_DEF (textpart, is_empty),
+       LUA_INTERFACE_DEF (textpart, is_html),
+       LUA_INTERFACE_DEF (textpart, get_fuzzy),
+       LUA_INTERFACE_DEF (textpart, get_language),
+       LUA_INTERFACE_DEF (textpart, compare_distance),
+       {"__tostring", rspamd_lua_class_tostring},
+       {NULL, NULL}
+};
+
+/* Mimepart methods */
+
+/***
+ * @module rspamd_mimepart
+ * This module provides access to mime parts found in a message
+@example
+rspamd_config.MISSING_CONTENT_TYPE = function(task)
+       local parts = task:get_parts()
+       if parts and table.maxn(parts) > 1 then
+               -- We have more than one part
+               for _,p in ipairs(parts) do
+                       local ct = p:get_header('Content-Type')
+                       -- And some parts have no Content-Type header
+                       if not ct then
+                               return true
+                       end
+               end
+       end
+       return false
+end
+ */
+
+/***
+ * @method mimepart:get_header(name[, case_sensitive])
+ * Get decoded value of a header specified with optional case_sensitive flag.
+ * By default headers are searched in caseless matter.
+ * @param {string} name name of header to get
+ * @param {boolean} case_sensitive case sensitiveness flag to search for a header
+ * @return {string} decoded value of a header
+ */
+LUA_FUNCTION_DEF (mimepart, get_header);
+/***
+ * @method mimepart:get_header_raw(name[, case_sensitive])
+ * Get raw value of a header specified with optional case_sensitive flag.
+ * By default headers are searched in caseless matter.
+ * @param {string} name name of header to get
+ * @param {boolean} case_sensitive case sensitiveness flag to search for a header
+ * @return {string} raw value of a header
+ */
+LUA_FUNCTION_DEF (mimepart, get_header_raw);
+/***
+ * @method mimepart:get_header_full(name[, case_sensitive])
+ * Get raw value of a header specified with optional case_sensitive flag.
+ * By default headers are searched in caseless matter. This method returns more
+ * information about the header as a list of tables with the following structure:
+ *
+ * - `name` - name of a header
+ * - `value` - raw value of a header
+ * - `decoded` - decoded value of a header
+ * - `tab_separated` - `true` if a header and a value are separated by `tab` character
+ * - `empty_separator` - `true` if there are no separator between a header and a value
+ * @param {string} name name of header to get
+ * @param {boolean} case_sensitive case sensitiveness flag to search for a header
+ * @return {list of tables} all values of a header as specified above
+@example
+function check_header_delimiter_tab(task, header_name)
+       for _,rh in ipairs(task:get_header_full(header_name)) do
+               if rh['tab_separated'] then return true end
+       end
+       return false
+end
+ */
+LUA_FUNCTION_DEF (mimepart, get_header_full);
+LUA_FUNCTION_DEF (mimepart, get_content);
+LUA_FUNCTION_DEF (mimepart, get_length);
+LUA_FUNCTION_DEF (mimepart, get_type);
+LUA_FUNCTION_DEF (mimepart, get_filename);
+
+static const struct luaL_reg mimepartlib_m[] = {
+       LUA_INTERFACE_DEF (mimepart, get_content),
+       LUA_INTERFACE_DEF (mimepart, get_length),
+       LUA_INTERFACE_DEF (mimepart, get_type),
+       LUA_INTERFACE_DEF (mimepart, get_filename),
+       LUA_INTERFACE_DEF (mimepart, get_header),
+       LUA_INTERFACE_DEF (mimepart, get_header_raw),
+       LUA_INTERFACE_DEF (mimepart, get_header_full),
+       {"__tostring", rspamd_lua_class_tostring},
+       {NULL, NULL}
+};
+
+
+static struct mime_text_part *
+lua_check_textpart (lua_State * L)
+{
+       void *ud = luaL_checkudata (L, 1, "rspamd{textpart}");
+       luaL_argcheck (L, ud != NULL, 1, "'textpart' expected");
+       return ud ? *((struct mime_text_part **)ud) : NULL;
+}
+
+static struct mime_part *
+lua_check_mimepart (lua_State * L)
+{
+       void *ud = luaL_checkudata (L, 1, "rspamd{mimepart}");
+       luaL_argcheck (L, ud != NULL, 1, "'mimepart' expected");
+       return ud ? *((struct mime_part **)ud) : NULL;
+}
+
+/***
+ * @module mime_textpart
+ * This module provides different methods to manipulate text parts data. Text parts
+ * could be obtained from the `rspamd_task` by using of method `task:get_text_parts()`
+@example
+rspamd_config.R_EMPTY_IMAGE = function (task)
+       parts = task:get_text_parts()
+       if parts then
+               for _,part in ipairs(parts) do
+                       if part:is_empty() then
+                               images = task:get_images()
+                               if images then
+                                       return true
+                               end
+                               return false
+                       end
+               end
+       end
+       return false
+end
+ */
+
+/***
+ * @method text_part:is_utf()
+ * Return TRUE if part is a valid utf text
+ * @return {boolean} true if part is valid `UTF8` part
+ */
+static gint
+lua_textpart_is_utf (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+
+       if (part == NULL || part->is_empty) {
+               lua_pushboolean (L, FALSE);
+               return 1;
+       }
+
+       lua_pushboolean (L, part->is_utf);
+
+       return 1;
+}
+
+/***
+ * @method text_part:get_content()
+ * Get the text of the part
+ * @return {string} `UTF8` encoded content of the part
+ */
+static gint
+lua_textpart_get_content (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+       struct rspamd_lua_text *t;
+
+       if (part == NULL || part->is_empty) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       t = lua_newuserdata (L, sizeof (*t));
+       rspamd_lua_setclass (L, "rspamd{text}", -1);
+       t->start = part->content->data;
+       t->len = part->content->len;
+
+       return 1;
+}
+
+/***
+ * @method text_part:get_length()
+ * Get length of the text of the part
+ * @return {integer} length of part in **bytes**
+ */
+static gint
+lua_textpart_get_length (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       if (part->is_empty) {
+               lua_pushnumber (L, 0);
+       }
+       else {
+               lua_pushnumber (L, part->content->len);
+       }
+
+       return 1;
+}
+
+/***
+ * @method text_part:is_empty()
+ * Returns `true` if the specified part is empty
+ * @return {bool} whether a part is empty
+ */
+static gint
+lua_textpart_is_empty (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       lua_pushboolean (L, part->is_empty);
+
+       return 1;
+}
+/***
+ * @method text_part:is_html()
+ * Returns `true` if the specified part has HTML content
+ * @return {bool} whether a part is HTML part
+ */
+static gint
+lua_textpart_is_html (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       lua_pushboolean (L, part->is_html);
+
+       return 1;
+}
+
+/***
+ * @method text_part:get_fuzzy()
+ * Returns base32 encoded value of fuzzy hash of the specified part
+ * @return {string} fuzzy hash value
+ */
+static gint
+lua_textpart_get_fuzzy (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+       gchar *out;
+
+       if (part == NULL || part->is_empty) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       out = rspamd_encode_base32 (part->fuzzy->hash_pipe,
+                       strlen (part->fuzzy->hash_pipe));
+       lua_pushstring (L, out);
+       g_free (out);
+
+       return 1;
+}
+
+/***
+ * @method text_part:is_language()
+ * Returns the code of the most used unicode script in the text part. Does not work with raw parts
+ * @return {string} short abbreviation (such as `ru`) for the script's language
+ */
+static gint
+lua_textpart_get_language (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L);
+
+       if (part != NULL) {
+               if (part->lang_code != NULL && part->lang_code[0] != '\0') {
+                       lua_pushstring (L, part->lang_code);
+                       return 1;
+               }
+       }
+
+       lua_pushnil (L);
+       return 1;
+}
+
+/***
+ * @method text_part:compare_distance(other)
+ * Calculates the difference to another text part.  This function is intended to work with
+ * the parts of `multipart/alternative` container only. If the two parts are not the parts of the
+ * same `multipart/alternative` container, then they are considered as unrelated and
+ * `-1` is returned.
+ * @param {text_part} other text part to compare
+ * @return {integer} commodity percentage (e.g. the same strings give `100`, different give `0` and unrelated give `-1`)
+ */
+static gint
+lua_textpart_compare_distance (lua_State * L)
+{
+       struct mime_text_part *part = lua_check_textpart (L), *other;
+       void *ud = luaL_checkudata (L, 2, "rspamd{textpart}");
+       gint diff = -1;
+       GMimeObject *parent;
+       const GMimeContentType *ct;
+
+       luaL_argcheck (L, ud != NULL, 2, "'textpart' expected");
+       other = ud ? *((struct mime_text_part **)ud) : NULL;
+
+       if (other != NULL && part->parent && part->parent == other->parent) {
+               parent = part->parent;
+               ct = g_mime_object_get_content_type (parent);
+#ifndef GMIME24
+               if (ct == NULL ||
+                       !g_mime_content_type_is_type (ct, "multipart", "alternative")) {
+#else
+               if (ct == NULL ||
+                       !g_mime_content_type_is_type ((GMimeContentType *)ct, "multipart",
+                       "alternative")) {
+#endif
+                       diff = -1;
+
+               }
+               else {
+                       if (!part->is_empty && !other->is_empty) {
+                               if (part->diff_str != NULL && other->diff_str != NULL) {
+                                       diff = rspamd_diff_distance (part->diff_str,
+                                                       other->diff_str);
+                               }
+                               else {
+                                       diff = rspamd_fuzzy_compare_parts (part, other);
+                               }
+                       }
+                       else if ((part->is_empty &&
+                               !other->is_empty) || (!part->is_empty && other->is_empty)) {
+                               /* Empty and non empty parts are different */
+                               diff = 0;
+                       }
+               }
+       }
+       else {
+               diff = -1;
+       }
+
+
+       lua_pushinteger (L, diff);
+
+       return 1;
+}
+
+/* Mimepart implementation */
+
+static gint
+lua_mimepart_get_content (lua_State * L)
+{
+       struct mime_part *part = lua_check_mimepart (L);
+       struct rspamd_lua_text *t;
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       t = lua_newuserdata (L, sizeof (*t));
+       rspamd_lua_setclass (L, "rspamd{text}", -1);
+       t->start = part->content->data;
+       t->len = part->content->len;
+
+       return 1;
+}
+
+static gint
+lua_mimepart_get_length (lua_State * L)
+{
+       struct mime_part *part = lua_check_mimepart (L);
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       lua_pushinteger (L, part->content->len);
+
+       return 1;
+}
+
+static gint
+lua_mimepart_get_type (lua_State * L)
+{
+       struct mime_part *part = lua_check_mimepart (L);
+
+       if (part == NULL) {
+               lua_pushnil (L);
+               lua_pushnil (L);
+               return 2;
+       }
+#ifndef GMIME24
+       lua_pushstring (L, part->type->type);
+       lua_pushstring (L, part->type->subtype);
+#else
+       lua_pushstring (L, g_mime_content_type_get_media_type (part->type));
+       lua_pushstring (L, g_mime_content_type_get_media_subtype (part->type));
+#endif
+
+       return 2;
+}
+
+static gint
+lua_mimepart_get_filename (lua_State * L)
+{
+       struct mime_part *part = lua_check_mimepart (L);
+
+       if (part == NULL || part->filename == NULL) {
+               lua_pushnil (L);
+               return 1;
+       }
+
+       lua_pushstring (L, part->filename);
+
+       return 1;
+}
+
+static gint
+lua_mimepart_get_header_common (lua_State *L, gboolean full, gboolean raw)
+{
+       gboolean strong = FALSE;
+       struct mime_part *part = lua_check_mimepart (L);
+       const gchar *name;
+
+       name = luaL_checkstring (L, 2);
+
+       if (name && part) {
+               if (lua_gettop (L) == 3) {
+                       strong = lua_toboolean (L, 3);
+               }
+               return rspamd_lua_push_header (L, part->raw_headers, name, strong, full, raw);
+       }
+       lua_pushnil (L);
+       return 1;
+}
+
+static gint
+lua_mimepart_get_header_full (lua_State * L)
+{
+       return lua_mimepart_get_header_common (L, TRUE, TRUE);
+}
+
+static gint
+lua_mimepart_get_header (lua_State * L)
+{
+       return lua_mimepart_get_header_common (L, FALSE, FALSE);
+}
+
+static gint
+lua_mimepart_get_header_raw (lua_State * L)
+{
+       return lua_mimepart_get_header_common (L, FALSE, TRUE);
+}
+
+void
+luaopen_textpart (lua_State * L)
+{
+       rspamd_lua_new_class (L, "rspamd{textpart}", textpartlib_m);
+       lua_pop (L, 1);                      /* remove metatable from stack */
+}
+
+void
+luaopen_mimepart (lua_State * L)
+{
+       rspamd_lua_new_class (L, "rspamd{mimepart}", mimepartlib_m);
+       lua_pop (L, 1);                      /* remove metatable from stack */
+}
+
index 555341ba98ebbecae15557f2ca8cb507407a0a7f..ae678024585532811dc6422a3e3ddcb5e5417ad4 100644 (file)
@@ -499,152 +499,6 @@ static const struct luaL_reg tasklib_m[] = {
        {NULL, NULL}
 };
 
-/* Textpart methods */
-/***
- * @module rspamd_textpart
- * This module provides access to text parts found in a message
- */
-
-LUA_FUNCTION_DEF (textpart, is_utf);
-
-/***
- * @method textpart:get_content()
- * Get parsed content of a part
- * @return {string} text contained in the part
- */
-LUA_FUNCTION_DEF (textpart, get_content);
-/***
- * @method textpart:get_length()
- * Get length of the text inside the part
- * @return {integer} the lenght of text part in bytes
- */
-LUA_FUNCTION_DEF (textpart, get_length);
-/***
- * @method textpart:is_empty()
- * Check whether a part is empty
- * @return {bool} `true` if a part is empty
- */
-LUA_FUNCTION_DEF (textpart, is_empty);
-/***
- * @method textpart:is_html()
- * Check whether a part contains HTML
- * @return {bool} `true` if a part html part
- */
-LUA_FUNCTION_DEF (textpart, is_html);
-/***
- * @method textpart:get_fuzzy()
- * Get fuzzy hash for a message
- * @return {string} fuzzy hash of the part
- */
-LUA_FUNCTION_DEF (textpart, get_fuzzy);
-/***
- * @method textpart:get_language()
- * Return short language code detected for the part
- * @return {string} language code for the part or nil if language has not been detected
- */
-LUA_FUNCTION_DEF (textpart, get_language);
-/***
- * @method textpart:compare_distance(part)
- * Compares two parts
- * @param {textpart} another text part
- * @return {number} similarity rate from 0.0 (different parts) to 1.0 (equal parts)
- */
-LUA_FUNCTION_DEF (textpart, compare_distance);
-
-static const struct luaL_reg textpartlib_m[] = {
-       LUA_INTERFACE_DEF (textpart, is_utf),
-       LUA_INTERFACE_DEF (textpart, get_content),
-       LUA_INTERFACE_DEF (textpart, get_length),
-       LUA_INTERFACE_DEF (textpart, is_empty),
-       LUA_INTERFACE_DEF (textpart, is_html),
-       LUA_INTERFACE_DEF (textpart, get_fuzzy),
-       LUA_INTERFACE_DEF (textpart, get_language),
-       LUA_INTERFACE_DEF (textpart, compare_distance),
-       {"__tostring", rspamd_lua_class_tostring},
-       {NULL, NULL}
-};
-
-/* Mimepart methods */
-
-/***
- * @module rspamd_mimepart
- * This module provides access to mime parts found in a message
-@example
-rspamd_config.MISSING_CONTENT_TYPE = function(task)
-       local parts = task:get_parts()
-       if parts and table.maxn(parts) > 1 then
-               -- We have more than one part
-               for _,p in ipairs(parts) do
-                       local ct = p:get_header('Content-Type')
-                       -- And some parts have no Content-Type header
-                       if not ct then
-                               return true
-                       end
-               end
-       end
-       return false
-end
- */
-
-/***
- * @method mimepart:get_header(name[, case_sensitive])
- * Get decoded value of a header specified with optional case_sensitive flag.
- * By default headers are searched in caseless matter.
- * @param {string} name name of header to get
- * @param {boolean} case_sensitive case sensitiveness flag to search for a header
- * @return {string} decoded value of a header
- */
-LUA_FUNCTION_DEF (mimepart, get_header);
-/***
- * @method mimepart:get_header_raw(name[, case_sensitive])
- * Get raw value of a header specified with optional case_sensitive flag.
- * By default headers are searched in caseless matter.
- * @param {string} name name of header to get
- * @param {boolean} case_sensitive case sensitiveness flag to search for a header
- * @return {string} raw value of a header
- */
-LUA_FUNCTION_DEF (mimepart, get_header_raw);
-/***
- * @method mimepart:get_header_full(name[, case_sensitive])
- * Get raw value of a header specified with optional case_sensitive flag.
- * By default headers are searched in caseless matter. This method returns more
- * information about the header as a list of tables with the following structure:
- *
- * - `name` - name of a header
- * - `value` - raw value of a header
- * - `decoded` - decoded value of a header
- * - `tab_separated` - `true` if a header and a value are separated by `tab` character
- * - `empty_separator` - `true` if there are no separator between a header and a value
- * @param {string} name name of header to get
- * @param {boolean} case_sensitive case sensitiveness flag to search for a header
- * @return {list of tables} all values of a header as specified above
-@example
-function check_header_delimiter_tab(task, header_name)
-       for _,rh in ipairs(task:get_header_full(header_name)) do
-               if rh['tab_separated'] then return true end
-       end
-       return false
-end
- */
-LUA_FUNCTION_DEF (mimepart, get_header_full);
-LUA_FUNCTION_DEF (mimepart, get_content);
-LUA_FUNCTION_DEF (mimepart, get_length);
-LUA_FUNCTION_DEF (mimepart, get_type);
-LUA_FUNCTION_DEF (mimepart, get_filename);
-
-static const struct luaL_reg mimepartlib_m[] = {
-       LUA_INTERFACE_DEF (mimepart, get_content),
-       LUA_INTERFACE_DEF (mimepart, get_length),
-       LUA_INTERFACE_DEF (mimepart, get_type),
-       LUA_INTERFACE_DEF (mimepart, get_filename),
-       LUA_INTERFACE_DEF (mimepart, get_header),
-       LUA_INTERFACE_DEF (mimepart, get_header_raw),
-       LUA_INTERFACE_DEF (mimepart, get_header_full),
-       {"__tostring", rspamd_lua_class_tostring},
-       {NULL, NULL}
-};
-
-
 /* Image methods */
 LUA_FUNCTION_DEF (image, get_width);
 LUA_FUNCTION_DEF (image, get_height);
@@ -703,22 +557,6 @@ lua_check_task (lua_State * L, gint pos)
        return ud ? *((struct rspamd_task **)ud) : NULL;
 }
 
-static struct mime_text_part *
-lua_check_textpart (lua_State * L)
-{
-       void *ud = luaL_checkudata (L, 1, "rspamd{textpart}");
-       luaL_argcheck (L, ud != NULL, 1, "'textpart' expected");
-       return ud ? *((struct mime_text_part **)ud) : NULL;
-}
-
-static struct mime_part *
-lua_check_mimepart (lua_State * L)
-{
-       void *ud = luaL_checkudata (L, 1, "rspamd{mimepart}");
-       luaL_argcheck (L, ud != NULL, 1, "'mimepart' expected");
-       return ud ? *((struct mime_part **)ud) : NULL;
-}
-
 static struct rspamd_image *
 lua_check_image (lua_State * L)
 {
@@ -1097,8 +935,8 @@ lua_task_get_parts (lua_State * L)
 }
 
 
-static gint
-lua_push_header (lua_State * L,
+gint
+rspamd_lua_push_header (lua_State * L,
                GHashTable *hdrs,
                const gchar *name,
                gboolean strong,
@@ -1187,7 +1025,7 @@ lua_task_get_header_common (lua_State *L, gboolean full, gboolean raw)
                if (lua_gettop (L) == 3) {
                        strong = lua_toboolean (L, 3);
                }
-               return lua_push_header (L, task->raw_headers, name, strong, full, raw);
+               return rspamd_lua_push_header (L, task->raw_headers, name, strong, full, raw);
        }
        lua_pushnil (L);
        return 1;
@@ -2056,352 +1894,6 @@ lua_task_get_metric_action (lua_State *L)
        return 0;
 }
 
-/***
- * @module mime_textpart
- * This module provides different methods to manipulate text parts data. Text parts
- * could be obtained from the `rspamd_task` by using of method `task:get_text_parts()`
-@example
-rspamd_config.R_EMPTY_IMAGE = function (task)
-       parts = task:get_text_parts()
-       if parts then
-               for _,part in ipairs(parts) do
-                       if part:is_empty() then
-                               images = task:get_images()
-                               if images then
-                                       return true
-                               end
-                               return false
-                       end
-               end
-       end
-       return false
-end
- */
-
-/***
- * @method text_part:is_utf()
- * Return TRUE if part is a valid utf text
- * @return {boolean} true if part is valid `UTF8` part
- */
-static gint
-lua_textpart_is_utf (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-
-       if (part == NULL || part->is_empty) {
-               lua_pushboolean (L, FALSE);
-               return 1;
-       }
-
-       lua_pushboolean (L, part->is_utf);
-
-       return 1;
-}
-
-/***
- * @method text_part:get_content()
- * Get the text of the part
- * @return {string} `UTF8` encoded content of the part
- */
-static gint
-lua_textpart_get_content (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-       struct rspamd_lua_text *t;
-
-       if (part == NULL || part->is_empty) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       t = lua_newuserdata (L, sizeof (*t));
-       rspamd_lua_setclass (L, "rspamd{text}", -1);
-       t->start = part->content->data;
-       t->len = part->content->len;
-
-       return 1;
-}
-
-/***
- * @method text_part:get_length()
- * Get length of the text of the part
- * @return {integer} length of part in **bytes**
- */
-static gint
-lua_textpart_get_length (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       if (part->is_empty) {
-               lua_pushnumber (L, 0);
-       }
-       else {
-               lua_pushnumber (L, part->content->len);
-       }
-
-       return 1;
-}
-
-/***
- * @method text_part:is_empty()
- * Returns `true` if the specified part is empty
- * @return {bool} whether a part is empty
- */
-static gint
-lua_textpart_is_empty (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       lua_pushboolean (L, part->is_empty);
-
-       return 1;
-}
-/***
- * @method text_part:is_html()
- * Returns `true` if the specified part has HTML content
- * @return {bool} whether a part is HTML part
- */
-static gint
-lua_textpart_is_html (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       lua_pushboolean (L, part->is_html);
-
-       return 1;
-}
-
-/***
- * @method text_part:get_fuzzy()
- * Returns base32 encoded value of fuzzy hash of the specified part
- * @return {string} fuzzy hash value
- */
-static gint
-lua_textpart_get_fuzzy (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-       gchar *out;
-
-       if (part == NULL || part->is_empty) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       out = rspamd_encode_base32 (part->fuzzy->hash_pipe,
-                       strlen (part->fuzzy->hash_pipe));
-       lua_pushstring (L, out);
-       g_free (out);
-
-       return 1;
-}
-
-/***
- * @method text_part:is_language()
- * Returns the code of the most used unicode script in the text part. Does not work with raw parts
- * @return {string} short abbreviation (such as `ru`) for the script's language
- */
-static gint
-lua_textpart_get_language (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L);
-
-       if (part != NULL) {
-               if (part->lang_code != NULL && part->lang_code[0] != '\0') {
-                       lua_pushstring (L, part->lang_code);
-                       return 1;
-               }
-       }
-
-       lua_pushnil (L);
-       return 1;
-}
-
-/***
- * @method text_part:compare_distance(other)
- * Calculates the difference to another text part.  This function is intended to work with
- * the parts of `multipart/alternative` container only. If the two parts are not the parts of the
- * same `multipart/alternative` container, then they are considered as unrelated and
- * `-1` is returned.
- * @param {text_part} other text part to compare
- * @return {integer} commodity percentage (e.g. the same strings give `100`, different give `0` and unrelated give `-1`)
- */
-static gint
-lua_textpart_compare_distance (lua_State * L)
-{
-       struct mime_text_part *part = lua_check_textpart (L), *other;
-       void *ud = luaL_checkudata (L, 2, "rspamd{textpart}");
-       gint diff = -1;
-       GMimeObject *parent;
-       const GMimeContentType *ct;
-
-       luaL_argcheck (L, ud != NULL, 2, "'textpart' expected");
-       other = ud ? *((struct mime_text_part **)ud) : NULL;
-
-       if (other != NULL && part->parent && part->parent == other->parent) {
-               parent = part->parent;
-               ct = g_mime_object_get_content_type (parent);
-#ifndef GMIME24
-               if (ct == NULL ||
-                       !g_mime_content_type_is_type (ct, "multipart", "alternative")) {
-#else
-               if (ct == NULL ||
-                       !g_mime_content_type_is_type ((GMimeContentType *)ct, "multipart",
-                       "alternative")) {
-#endif
-                       diff = -1;
-
-               }
-               else {
-                       if (!part->is_empty && !other->is_empty) {
-                               if (part->diff_str != NULL && other->diff_str != NULL) {
-                                       diff = rspamd_diff_distance (part->diff_str,
-                                                       other->diff_str);
-                               }
-                               else {
-                                       diff = rspamd_fuzzy_compare_parts (part, other);
-                               }
-                       }
-                       else if ((part->is_empty &&
-                               !other->is_empty) || (!part->is_empty && other->is_empty)) {
-                               /* Empty and non empty parts are different */
-                               diff = 0;
-                       }
-               }
-       }
-       else {
-               diff = -1;
-       }
-
-
-       lua_pushinteger (L, diff);
-
-       return 1;
-}
-
-/* Mimepart implementation */
-
-static gint
-lua_mimepart_get_content (lua_State * L)
-{
-       struct mime_part *part = lua_check_mimepart (L);
-       struct rspamd_lua_text *t;
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       t = lua_newuserdata (L, sizeof (*t));
-       rspamd_lua_setclass (L, "rspamd{text}", -1);
-       t->start = part->content->data;
-       t->len = part->content->len;
-
-       return 1;
-}
-
-static gint
-lua_mimepart_get_length (lua_State * L)
-{
-       struct mime_part *part = lua_check_mimepart (L);
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       lua_pushinteger (L, part->content->len);
-
-       return 1;
-}
-
-static gint
-lua_mimepart_get_type (lua_State * L)
-{
-       struct mime_part *part = lua_check_mimepart (L);
-
-       if (part == NULL) {
-               lua_pushnil (L);
-               lua_pushnil (L);
-               return 2;
-       }
-#ifndef GMIME24
-       lua_pushstring (L, part->type->type);
-       lua_pushstring (L, part->type->subtype);
-#else
-       lua_pushstring (L, g_mime_content_type_get_media_type (part->type));
-       lua_pushstring (L, g_mime_content_type_get_media_subtype (part->type));
-#endif
-
-       return 2;
-}
-
-static gint
-lua_mimepart_get_filename (lua_State * L)
-{
-       struct mime_part *part = lua_check_mimepart (L);
-
-       if (part == NULL || part->filename == NULL) {
-               lua_pushnil (L);
-               return 1;
-       }
-
-       lua_pushstring (L, part->filename);
-
-       return 1;
-}
-
-static gint
-lua_mimepart_get_header_common (lua_State *L, gboolean full, gboolean raw)
-{
-       gboolean strong = FALSE;
-       struct mime_part *part = lua_check_mimepart (L);
-       const gchar *name;
-
-       name = luaL_checkstring (L, 2);
-
-       if (name && part) {
-               if (lua_gettop (L) == 3) {
-                       strong = lua_toboolean (L, 3);
-               }
-               return lua_push_header (L, part->raw_headers, name, strong, full, raw);
-       }
-       lua_pushnil (L);
-       return 1;
-}
-
-static gint
-lua_mimepart_get_header_full (lua_State * L)
-{
-       return lua_mimepart_get_header_common (L, TRUE, TRUE);
-}
-
-static gint
-lua_mimepart_get_header (lua_State * L)
-{
-       return lua_mimepart_get_header_common (L, FALSE, FALSE);
-}
-
-static gint
-lua_mimepart_get_header_raw (lua_State * L)
-{
-       return lua_mimepart_get_header_common (L, FALSE, TRUE);
-}
-
 /* Image functions */
 static gint
 lua_image_get_width (lua_State *L)
@@ -2636,22 +2128,6 @@ luaopen_task (lua_State * L)
        rspamd_lua_add_preload (L, "rspamd_task", lua_load_task);
 }
 
-void
-luaopen_textpart (lua_State * L)
-{
-       rspamd_lua_new_class (L, "rspamd{textpart}", textpartlib_m);
-       luaL_register (L, "rspamd_textpart", null_reg);
-
-       lua_pop (L, 1);                      /* remove metatable from stack */
-}
-
-void
-luaopen_mimepart (lua_State * L)
-{
-       rspamd_lua_new_class (L, "rspamd{mimepart}", mimepartlib_m);
-       lua_pop (L, 1);                      /* remove metatable from stack */
-}
-
 void
 luaopen_image (lua_State * L)
 {
@@ -2682,4 +2158,3 @@ rspamd_lua_task_push (lua_State *L, struct rspamd_task *task)
        rspamd_lua_setclass (L, "rspamd{task}", -1);
        *ptask = task;
 }
-