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.

mime_tool.c 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "printf.h"
  18. #include "message.h"
  19. #include "util.h"
  20. #include "content_type.h"
  21. #include "task.h"
  22. #include "mime_parser.h"
  23. #include "unix-std.h"
  24. #define MODE_NORMAL 0
  25. #define MODE_GMIME 1
  26. static gdouble total_time = 0.0;
  27. static void
  28. rspamd_show_normal (struct rspamd_mime_part *part)
  29. {
  30. rspamd_printf ("got normal part %p: parent: %p, type: %T/%T,"
  31. "length: %z (%z raw)\n",
  32. part, part->parent_part,
  33. &part->ct->type, &part->ct->subtype,
  34. part->parsed_data.len,
  35. part->raw_data.len);
  36. }
  37. static void
  38. rspamd_show_multipart (struct rspamd_mime_part *part)
  39. {
  40. struct rspamd_mime_part *cur;
  41. guint i;
  42. rspamd_printf ("got multipart part %p, boundary: %T: parent: %p, type: %T/%T, children: [",
  43. part, &part->ct->boundary,
  44. part->parent_part,
  45. &part->ct->type, &part->ct->subtype);
  46. if (part->specific.mp.children) {
  47. for (i = 0; i < part->specific.mp.children->len; i ++) {
  48. cur = g_ptr_array_index (part->specific.mp.children, i);
  49. if (i != 0) {
  50. rspamd_printf (", %p{%T/%T}", cur,
  51. &cur->ct->type, &cur->ct->subtype);
  52. }
  53. else {
  54. rspamd_printf ("%p{%T/%T}", cur,
  55. &cur->ct->type, &cur->ct->subtype);
  56. }
  57. }
  58. }
  59. rspamd_printf ("]\n");
  60. }
  61. static void
  62. rspamd_show_message (struct rspamd_mime_part *part)
  63. {
  64. rspamd_printf ("got message part %p: parent: %p\n",
  65. part, part->parent_part);
  66. }
  67. #if 0
  68. static void
  69. mime_foreach_callback (GMimeObject * parent,
  70. GMimeObject * part,
  71. gpointer user_data)
  72. {
  73. GMimeContentType *type;
  74. if (GMIME_IS_MESSAGE_PART (part)) {
  75. /* message/rfc822 or message/news */
  76. GMimeMessage *message;
  77. /* g_mime_message_foreach_part() won't descend into
  78. child message parts, so if we want to count any
  79. subparts of this child message, we'll have to call
  80. g_mime_message_foreach_part() again here. */
  81. rspamd_printf ("got message part %p: parent: %p\n",
  82. part, parent);
  83. message = g_mime_message_part_get_message ((GMimeMessagePart *) part);
  84. g_mime_message_foreach (message, mime_foreach_callback, part);
  85. }
  86. else if (GMIME_IS_MULTIPART (part)) {
  87. type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
  88. part));
  89. rspamd_printf ("got multipart part %p, boundary: %s: parent: %p, type: %s/%s\n",
  90. part, g_mime_multipart_get_boundary (GMIME_MULTIPART(part)),
  91. parent,
  92. g_mime_content_type_get_media_type (type),
  93. g_mime_content_type_get_media_subtype (type));
  94. }
  95. else {
  96. type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
  97. part));
  98. rspamd_printf ("got normal part %p, parent: %p, type: %s/%s\n",
  99. part,
  100. parent,
  101. g_mime_content_type_get_media_type (type),
  102. g_mime_content_type_get_media_subtype (type));
  103. }
  104. }
  105. #endif
  106. static void
  107. rspamd_process_file (struct rspamd_config *cfg, const gchar *fname, gint mode)
  108. {
  109. struct rspamd_task *task;
  110. gint fd;
  111. gpointer map;
  112. struct stat st;
  113. GError *err = NULL;
  114. #if 0
  115. GMimeMessage *message;
  116. GMimeParser *parser;
  117. GMimeStream *stream;
  118. GByteArray tmp;
  119. #endif
  120. struct rspamd_mime_part *part;
  121. guint i;
  122. gdouble ts1, ts2;
  123. fd = open (fname, O_RDONLY);
  124. if (fd == -1) {
  125. rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, strerror (errno));
  126. exit (EXIT_FAILURE);
  127. }
  128. if (fstat (fd, &st) == -1) {
  129. rspamd_fprintf (stderr, "cannot stat %s: %s\n", fname, strerror (errno));
  130. exit (EXIT_FAILURE);
  131. }
  132. map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
  133. close (fd);
  134. if (map == MAP_FAILED) {
  135. rspamd_fprintf (stderr, "cannot mmap %s: %s\n", fname, strerror (errno));
  136. exit (EXIT_FAILURE);
  137. }
  138. task = rspamd_task_new (NULL, cfg, NULL);
  139. task->msg.begin = map;
  140. task->msg.len = st.st_size;
  141. ts1 = rspamd_get_ticks ();
  142. if (mode == MODE_NORMAL) {
  143. if (!rspamd_mime_parse_task (task, &err)) {
  144. rspamd_fprintf (stderr, "cannot parse %s: %e\n", fname, err);
  145. g_error_free (err);
  146. }
  147. }
  148. #if 0
  149. else if (mode == MODE_GMIME) {
  150. tmp.data = map;
  151. tmp.len = st.st_size;
  152. stream = g_mime_stream_mem_new_with_byte_array (&tmp);
  153. g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (stream), FALSE);
  154. parser = g_mime_parser_new_with_stream (stream);
  155. message = g_mime_parser_construct_message (parser);
  156. }
  157. #endif
  158. ts2 = rspamd_get_ticks ();
  159. total_time += ts2 - ts1;
  160. if (mode == MODE_NORMAL) {
  161. for (i = 0; i < task->parts->len; i ++) {
  162. part = g_ptr_array_index (task->parts, i);
  163. if (part->ct->flags & RSPAMD_CONTENT_TYPE_MULTIPART) {
  164. rspamd_show_multipart (part);
  165. }
  166. else if (part->ct->flags & RSPAMD_CONTENT_TYPE_MESSAGE) {
  167. rspamd_show_message (part);
  168. }
  169. else {
  170. rspamd_show_normal (part);
  171. }
  172. }
  173. }
  174. #if 0
  175. else if (mode == MODE_GMIME) {
  176. g_mime_message_foreach (message, mime_foreach_callback, NULL);
  177. }
  178. #endif
  179. rspamd_task_free (task);
  180. munmap (map, st.st_size);
  181. #if 0
  182. if (mode == MODE_GMIME) {
  183. g_object_unref (message);
  184. }
  185. #endif
  186. }
  187. int
  188. main (int argc, char **argv)
  189. {
  190. gint i, start = 1, mode = MODE_NORMAL;
  191. struct rspamd_config *cfg;
  192. rspamd_logger_t *logger = NULL;
  193. if (argc > 2 && *argv[1] == '-') {
  194. start = 2;
  195. if (argv[1][1] == 'g') {
  196. mode = MODE_GMIME;
  197. }
  198. }
  199. cfg = rspamd_config_new ();
  200. cfg->libs_ctx = rspamd_init_libs ();
  201. cfg->log_type = RSPAMD_LOG_CONSOLE;
  202. rspamd_set_logger (cfg, g_quark_from_static_string ("mime"), &logger, NULL);
  203. (void) rspamd_log_open (logger);
  204. g_log_set_default_handler (rspamd_glib_log_function, logger);
  205. g_set_printerr_handler (rspamd_glib_printerr_function);
  206. rspamd_config_post_load (cfg,
  207. RSPAMD_CONFIG_INIT_LIBS|RSPAMD_CONFIG_INIT_URL|RSPAMD_CONFIG_INIT_NO_TLD);
  208. for (i = start; i < argc; i ++) {
  209. if (argv[i]) {
  210. rspamd_process_file (cfg, argv[i], mode);
  211. }
  212. }
  213. rspamd_printf ("Total time parsing: %.4f seconds\n", total_time);
  214. rspamd_log_close (logger);
  215. REF_RELEASE (cfg);
  216. return 0;
  217. }