2016-12-14 14:42:26 +01:00
|
|
|
/*-
|
|
|
|
* Copyright 2016 Vsevolod Stakhov
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "printf.h"
|
|
|
|
#include "message.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "content_type.h"
|
|
|
|
#include "task.h"
|
|
|
|
#include "mime_parser.h"
|
|
|
|
#include "unix-std.h"
|
|
|
|
|
2016-12-15 17:08:18 +01:00
|
|
|
#define MODE_NORMAL 0
|
|
|
|
#define MODE_GMIME 1
|
2016-12-15 16:14:33 +01:00
|
|
|
static gdouble total_time = 0.0;
|
2016-12-14 14:42:26 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
rspamd_show_normal (struct rspamd_mime_part *part)
|
|
|
|
{
|
|
|
|
rspamd_printf ("got normal part %p: parent: %p, type: %T/%T,"
|
|
|
|
"length: %z (%z raw)\n",
|
|
|
|
part, part->parent_part,
|
|
|
|
&part->ct->type, &part->ct->subtype,
|
|
|
|
part->parsed_data.len,
|
|
|
|
part->raw_data.len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rspamd_show_multipart (struct rspamd_mime_part *part)
|
|
|
|
{
|
|
|
|
struct rspamd_mime_part *cur;
|
|
|
|
guint i;
|
|
|
|
|
2016-12-14 15:11:27 +01:00
|
|
|
rspamd_printf ("got multipart part %p, boundary: %T: parent: %p, type: %T/%T, children: [",
|
|
|
|
part, &part->ct->boundary,
|
|
|
|
part->parent_part,
|
2016-12-14 14:42:26 +01:00
|
|
|
&part->ct->type, &part->ct->subtype);
|
|
|
|
|
2016-12-16 18:59:15 +01:00
|
|
|
if (part->specific.mp.children) {
|
|
|
|
for (i = 0; i < part->specific.mp.children->len; i ++) {
|
|
|
|
cur = g_ptr_array_index (part->specific.mp.children, i);
|
2016-12-14 14:42:26 +01:00
|
|
|
|
|
|
|
if (i != 0) {
|
|
|
|
rspamd_printf (", %p{%T/%T}", cur,
|
|
|
|
&cur->ct->type, &cur->ct->subtype);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rspamd_printf ("%p{%T/%T}", cur,
|
|
|
|
&cur->ct->type, &cur->ct->subtype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rspamd_printf ("]\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rspamd_show_message (struct rspamd_mime_part *part)
|
|
|
|
{
|
2016-12-14 15:11:27 +01:00
|
|
|
rspamd_printf ("got message part %p: parent: %p\n",
|
2016-12-14 14:42:26 +01:00
|
|
|
part, part->parent_part);
|
|
|
|
}
|
|
|
|
|
2016-12-23 00:58:51 +01:00
|
|
|
#if 0
|
2016-12-15 17:08:18 +01:00
|
|
|
static void
|
|
|
|
mime_foreach_callback (GMimeObject * parent,
|
|
|
|
GMimeObject * part,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GMimeContentType *type;
|
|
|
|
|
|
|
|
if (GMIME_IS_MESSAGE_PART (part)) {
|
|
|
|
/* message/rfc822 or message/news */
|
|
|
|
GMimeMessage *message;
|
|
|
|
|
|
|
|
/* g_mime_message_foreach_part() won't descend into
|
|
|
|
child message parts, so if we want to count any
|
|
|
|
subparts of this child message, we'll have to call
|
|
|
|
g_mime_message_foreach_part() again here. */
|
|
|
|
rspamd_printf ("got message part %p: parent: %p\n",
|
|
|
|
part, parent);
|
|
|
|
message = g_mime_message_part_get_message ((GMimeMessagePart *) part);
|
|
|
|
g_mime_message_foreach (message, mime_foreach_callback, part);
|
|
|
|
}
|
|
|
|
else if (GMIME_IS_MULTIPART (part)) {
|
|
|
|
type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
|
|
|
|
part));
|
|
|
|
rspamd_printf ("got multipart part %p, boundary: %s: parent: %p, type: %s/%s\n",
|
|
|
|
part, g_mime_multipart_get_boundary (GMIME_MULTIPART(part)),
|
|
|
|
parent,
|
|
|
|
g_mime_content_type_get_media_type (type),
|
|
|
|
g_mime_content_type_get_media_subtype (type));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
|
|
|
|
part));
|
|
|
|
rspamd_printf ("got normal part %p, parent: %p, type: %s/%s\n",
|
|
|
|
part,
|
|
|
|
parent,
|
|
|
|
g_mime_content_type_get_media_type (type),
|
|
|
|
g_mime_content_type_get_media_subtype (type));
|
|
|
|
}
|
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#endif
|
2016-12-14 14:42:26 +01:00
|
|
|
static void
|
|
|
|
rspamd_process_file (struct rspamd_config *cfg, const gchar *fname, gint mode)
|
|
|
|
{
|
|
|
|
struct rspamd_task *task;
|
|
|
|
gint fd;
|
|
|
|
gpointer map;
|
|
|
|
struct stat st;
|
|
|
|
GError *err = NULL;
|
2016-12-23 00:58:51 +01:00
|
|
|
#if 0
|
2016-12-15 17:08:18 +01:00
|
|
|
GMimeMessage *message;
|
|
|
|
GMimeParser *parser;
|
|
|
|
GMimeStream *stream;
|
|
|
|
GByteArray tmp;
|
2016-12-23 00:58:51 +01:00
|
|
|
#endif
|
2016-12-14 14:42:26 +01:00
|
|
|
struct rspamd_mime_part *part;
|
|
|
|
guint i;
|
2016-12-15 16:14:33 +01:00
|
|
|
gdouble ts1, ts2;
|
2016-12-14 14:42:26 +01:00
|
|
|
|
|
|
|
fd = open (fname, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd == -1) {
|
|
|
|
rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, strerror (errno));
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fstat (fd, &st) == -1) {
|
|
|
|
rspamd_fprintf (stderr, "cannot stat %s: %s\n", fname, strerror (errno));
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
|
|
|
close (fd);
|
|
|
|
|
|
|
|
if (map == MAP_FAILED) {
|
|
|
|
rspamd_fprintf (stderr, "cannot mmap %s: %s\n", fname, strerror (errno));
|
|
|
|
exit (EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2017-06-27 09:44:49 +02:00
|
|
|
task = rspamd_task_new (NULL, cfg, NULL);
|
2016-12-14 14:42:26 +01:00
|
|
|
task->msg.begin = map;
|
|
|
|
task->msg.len = st.st_size;
|
|
|
|
|
2016-12-15 16:14:33 +01:00
|
|
|
ts1 = rspamd_get_ticks ();
|
|
|
|
|
2016-12-15 17:08:18 +01:00
|
|
|
if (mode == MODE_NORMAL) {
|
|
|
|
if (!rspamd_mime_parse_task (task, &err)) {
|
|
|
|
rspamd_fprintf (stderr, "cannot parse %s: %e\n", fname, err);
|
|
|
|
g_error_free (err);
|
|
|
|
}
|
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#if 0
|
2016-12-15 17:08:18 +01:00
|
|
|
else if (mode == MODE_GMIME) {
|
|
|
|
tmp.data = map;
|
|
|
|
tmp.len = st.st_size;
|
|
|
|
stream = g_mime_stream_mem_new_with_byte_array (&tmp);
|
|
|
|
g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (stream), FALSE);
|
|
|
|
parser = g_mime_parser_new_with_stream (stream);
|
|
|
|
message = g_mime_parser_construct_message (parser);
|
2016-12-14 14:42:26 +01:00
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#endif
|
2016-12-15 16:14:33 +01:00
|
|
|
ts2 = rspamd_get_ticks ();
|
|
|
|
total_time += ts2 - ts1;
|
|
|
|
|
2016-12-15 17:08:18 +01:00
|
|
|
if (mode == MODE_NORMAL) {
|
|
|
|
for (i = 0; i < task->parts->len; i ++) {
|
|
|
|
part = g_ptr_array_index (task->parts, i);
|
2016-12-14 14:42:26 +01:00
|
|
|
|
2016-12-15 17:08:18 +01:00
|
|
|
if (part->ct->flags & RSPAMD_CONTENT_TYPE_MULTIPART) {
|
|
|
|
rspamd_show_multipart (part);
|
|
|
|
}
|
|
|
|
else if (part->ct->flags & RSPAMD_CONTENT_TYPE_MESSAGE) {
|
|
|
|
rspamd_show_message (part);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rspamd_show_normal (part);
|
|
|
|
}
|
2016-12-14 14:42:26 +01:00
|
|
|
}
|
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#if 0
|
2016-12-15 17:08:18 +01:00
|
|
|
else if (mode == MODE_GMIME) {
|
|
|
|
g_mime_message_foreach (message, mime_foreach_callback, NULL);
|
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#endif
|
2016-12-14 14:42:26 +01:00
|
|
|
|
|
|
|
rspamd_task_free (task);
|
|
|
|
munmap (map, st.st_size);
|
2016-12-23 00:58:51 +01:00
|
|
|
#if 0
|
2016-12-15 17:08:18 +01:00
|
|
|
if (mode == MODE_GMIME) {
|
|
|
|
g_object_unref (message);
|
|
|
|
}
|
2016-12-23 00:58:51 +01:00
|
|
|
#endif
|
2016-12-14 14:42:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
2016-12-15 17:08:18 +01:00
|
|
|
gint i, start = 1, mode = MODE_NORMAL;
|
2016-12-14 14:42:26 +01:00
|
|
|
struct rspamd_config *cfg;
|
|
|
|
rspamd_logger_t *logger = NULL;
|
|
|
|
|
2016-12-15 17:08:18 +01:00
|
|
|
if (argc > 2 && *argv[1] == '-') {
|
|
|
|
start = 2;
|
|
|
|
|
|
|
|
if (argv[1][1] == 'g') {
|
|
|
|
mode = MODE_GMIME;
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 14:42:26 +01:00
|
|
|
cfg = rspamd_config_new ();
|
|
|
|
cfg->libs_ctx = rspamd_init_libs ();
|
|
|
|
cfg->log_type = RSPAMD_LOG_CONSOLE;
|
|
|
|
rspamd_set_logger (cfg, g_quark_from_static_string ("mime"), &logger, NULL);
|
|
|
|
(void) rspamd_log_open (logger);
|
|
|
|
g_log_set_default_handler (rspamd_glib_log_function, logger);
|
|
|
|
g_set_printerr_handler (rspamd_glib_printerr_function);
|
|
|
|
rspamd_config_post_load (cfg,
|
|
|
|
RSPAMD_CONFIG_INIT_LIBS|RSPAMD_CONFIG_INIT_URL|RSPAMD_CONFIG_INIT_NO_TLD);
|
|
|
|
|
|
|
|
for (i = start; i < argc; i ++) {
|
|
|
|
if (argv[i]) {
|
2016-12-15 17:08:18 +01:00
|
|
|
rspamd_process_file (cfg, argv[i], mode);
|
2016-12-14 14:42:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-15 16:14:33 +01:00
|
|
|
rspamd_printf ("Total time parsing: %.4f seconds\n", total_time);
|
|
|
|
|
2016-12-14 14:42:26 +01:00
|
|
|
rspamd_log_close (logger);
|
|
|
|
REF_RELEASE (cfg);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|