Blob Blame History Raw
From 07059f936207c33b8aabf356e22dda64fc1050cb Mon Sep 17 00:00:00 2001
From: Matej Habrnal <mhabrnal@redhat.com>
Date: Fri, 1 Apr 2016 13:23:14 +0200
Subject: [PATCH] mailx: use problem report api to define an emais' content

If formatting file is defined, the reporter-mailx
uses the given file to create content of emails. Section summary is used
for email's subject. If no formatting file is defined, the default formatting
is used and subject can be redefined either by mailx.conf file or by env
variable.

Related to rhbz#1281312

Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
---
 doc/reporter-mailx.txt           | 48 ++++++++++++++++++++-
 src/include/internal_libreport.h |  2 -
 src/lib/make_descr.c             | 56 ------------------------
 src/plugins/reporter-mailx.c     | 92 +++++++++++++++++++++++++++++++---------
 4 files changed, 119 insertions(+), 79 deletions(-)

diff --git a/doc/reporter-mailx.txt b/doc/reporter-mailx.txt
index bd0c63e..029a3d0 100644
--- a/doc/reporter-mailx.txt
+++ b/doc/reporter-mailx.txt
@@ -7,7 +7,7 @@ reporter-mailx - Sends contents of a problem directory via email.
 
 SYNOPSIS
 --------
-'reporter-mailx' [-v] -d DIR [-c CONFFILE]
+'reporter-mailx' [-v] -d DIR [-c CONFFILE] [-F FMTFILE]
 
 DESCRIPTION
 -----------
@@ -38,6 +38,49 @@ The options are:
        directory to the email. This can cause the emails to be very
        large.
 
+Formatting configuration files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Lines starting with # are ignored.
+
+Lines can be continued on the next line using trailing backslash.
+
+Format:
+
+   "%summary:: subject format"
+   "section:: element1[,element2]..."
+   The literal text line to be added to email. Can be empty.
+   (Empty lines are NOT ignored!)
+
+   Subject format is a line of text, where %element% is replaced by
+   text element's content, and [[...%element%...]] block is used only if
+   %element% exists. [[...]] blocks can nest.
+
+   Sections can be:
+   - %summary: email subject format string.
+   - %attach: a list of elements to attach.
+   - text, double colon (::) and the list of comma-separated elements.
+
+   Elements can be:
+   - problem directory element names, which get formatted as
+     <element_name>: <contents>
+     or
+     <element_name>:
+     :<contents>
+     :<contents>
+     :<contents>
+   - problem directory element names prefixed by "%bare_",
+     which is formatted as-is, without "<element_name>:" and colons
+   - %oneline, %multiline, %text wildcards, which select all corresponding
+     elements for output or attachment
+   - %binary wildcard, valid only for %attach section, instructs to attach
+     binary elements
+   - problem directory element names prefixed by "-",
+     which excludes given element from all wildcards
+
+     Nonexistent elements are silently ignored.
+     If none of elements exists, the section will not be created.
+
+
 Integration with ABRT events
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 'reporter-mailx' can be used as a reporter, to allow users report
@@ -66,6 +109,9 @@ OPTIONS
    contains site-wide configuration. Users can change the values via
    environment variables.
 
+-F CONF_FORMAT_FILE
+   Formatting file for an email.
+
 ENVIRONMENT VARIABLES
 ---------------------
 Environment variables take precedence over values provided in
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index c3b2045..cf5730c 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -668,8 +668,6 @@ enum {
 char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags);
 #define make_description_logger libreport_make_description_logger
 char* make_description_logger(problem_data_t *problem_data, unsigned max_text_size);
-#define make_description_mailx libreport_make_description_mailx
-char* make_description_mailx(problem_data_t *problem_data, unsigned max_text_size);
 
 /* See man os-release(5) for details */
 #define OSINFO_ID "ID"
diff --git a/src/lib/make_descr.c b/src/lib/make_descr.c
index a16eb98..5a6d9f4 100644
--- a/src/lib/make_descr.c
+++ b/src/lib/make_descr.c
@@ -290,52 +290,6 @@ char *make_description(problem_data_t *problem_data, char **names_to_skip,
     return strbuf_free_nobuf(buf_dsc);
 }
 
-#ifdef UNUSED
-char* make_description_mailx(problem_data_t *problem_data)
-{
-    struct strbuf *buf_dsc = strbuf_new();
-    struct strbuf *buf_additional_files = strbuf_new();
-    struct strbuf *buf_duphash_file = strbuf_new();
-    struct strbuf *buf_common_files = strbuf_new();
-
-    GHashTableIter iter;
-    char *name;
-    struct problem_item *value;
-    g_hash_table_iter_init(&iter, problem_data);
-    while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
-    {
-        if (value->flags & CD_FLAG_TXT)
-        {
-            if ((strcmp(name, FILENAME_DUPHASH) != 0)
-             && (strcmp(name, FILENAME_ARCHITECTURE) != 0)
-             && (strcmp(name, FILENAME_KERNEL) != 0)
-             && (strcmp(name, FILENAME_PACKAGE) != 0)
-            ) {
-                strbuf_append_strf(buf_additional_files, "%s\n-----\n%s\n\n", name, value->content);
-            }
-            else if (strcmp(name, FILENAME_DUPHASH) == 0)
-                strbuf_append_strf(buf_duphash_file, "%s\n-----\n%s\n\n", name, value->content);
-            else
-                strbuf_append_strf(buf_common_files, "%s\n-----\n%s\n\n", name, value->content);
-        }
-    }
-
-    char *common_files = strbuf_free_nobuf(buf_common_files);
-    char *duphash_file = strbuf_free_nobuf(buf_duphash_file);
-    char *additional_files = strbuf_free_nobuf(buf_additional_files);
-
-    strbuf_append_strf(buf_dsc, "Duplicate check\n=====\n%s\n\n", duphash_file);
-    strbuf_append_strf(buf_dsc, "Common information\n=====\n%s\n\n", common_files);
-    strbuf_append_strf(buf_dsc, "Additional information\n=====\n%s\n", additional_files);
-
-    free(common_files);
-    free(duphash_file);
-    free(additional_files);
-
-    return strbuf_free_nobuf(buf_dsc);
-}
-#endif
-
 /* Items we don't want to include to bz / logger */
 static const char *const blacklisted_items[] = {
     CD_DUMPDIR        ,
@@ -365,13 +319,3 @@ char* make_description_logger(problem_data_t *problem_data, unsigned max_text_si
                 MAKEDESC_SHOW_FILES | MAKEDESC_SHOW_MULTILINE
     );
 }
-
-char* make_description_mailx(problem_data_t *problem_data, unsigned max_text_size)
-{
-    return make_description(
-                problem_data,
-                (char**)blacklisted_items_mailx,
-                max_text_size,
-                MAKEDESC_SHOW_FILES | MAKEDESC_SHOW_MULTILINE
-    );
-}
diff --git a/src/plugins/reporter-mailx.c b/src/plugins/reporter-mailx.c
index 54dc82e..a062abd 100644
--- a/src/plugins/reporter-mailx.c
+++ b/src/plugins/reporter-mailx.c
@@ -18,6 +18,25 @@
 */
 #include "internal_libreport.h"
 #include "client.h"
+#include "problem_report.h"
+
+#define PR_DEFAULT_SUBJECT \
+    "[abrt] %pkg_name%[[: %crash_function%()]][[: %reason%]][[: TAINTED %tainted_short%]]"
+
+#define PR_MAILX_TEMPLATE \
+    "%%summary:: %s\n" \
+    "\n" \
+    "::" \
+    FILENAME_REASON","FILENAME_CRASH_FUNCTION"," \
+    FILENAME_CMDLINE","FILENAME_EXECUTABLE"," \
+    FILENAME_PACKAGE","FILENAME_COMPONENT","FILENAME_PID","FILENAME_PWD"," \
+    FILENAME_HOSTNAME","FILENAME_COUNT", %%oneline\n" \
+    "\n" \
+    "::" \
+    FILENAME_REPORTED_TO","FILENAME_BACKTRACE","FILENAME_CORE_BACKTRACE \
+    ", %%multiline"
+
+#define PR_ATTACH_BINARY "\n%attach:: %binary"
 
 static void exec_and_feed_input(const char* text, char **args)
 {
@@ -79,6 +98,7 @@ static char *ask_email_address(const char *type, const char *def_address)
 static void create_and_send_email(
                 const char *dump_dir_name,
                 map_string_t *settings,
+                const char *fmt_file,
                 bool notify_only)
 {
     problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
@@ -86,8 +106,6 @@ static void create_and_send_email(
         xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
 
     char* env;
-    env = getenv("Mailx_Subject");
-    const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : "[abrt] full crash report");
     env = getenv("Mailx_EmailFrom");
     char *email_from = (env ? xstrdup(env) : xstrdup(get_map_string_item_or_NULL(settings, "EmailFrom")) ? : ask_email_address("sender", "user@localhost"));
     env = getenv("Mailx_EmailTo");
@@ -99,22 +117,52 @@ static void create_and_send_email(
     unsigned arg_size = 0;
     args = append_str_to_vector(args, &arg_size, "/bin/mailx");
 
-    char *dsc = make_description_mailx(problem_data, CD_TEXT_ATT_SIZE_LOGGER);
+    problem_formatter_t *pf = problem_formatter_new();
+    /* formatting file is not set */
+    if (fmt_file == NULL)
+    {
+        env = getenv("Mailx_Subject");
+        const char *subject = (env ? env : get_map_string_item_or_NULL(settings, "Subject") ? : PR_DEFAULT_SUBJECT);
+
+        char *format_string = xasprintf(PR_MAILX_TEMPLATE, subject);
+
+        /* attaching binary file to the email */
+        if (send_binary_data)
+            format_string = append_to_malloced_string(format_string, PR_ATTACH_BINARY);
+
+        if (problem_formatter_load_string(pf, format_string))
+            error_msg_and_die("BUG: Invalid default problem report format string");
 
-    if (send_binary_data)
+        free(format_string);
+    }
+    else
     {
-        GHashTableIter iter;
-        char *name;
-        struct problem_item *value;
-        g_hash_table_iter_init(&iter, problem_data);
-        while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
-        {
-            if (value->flags & CD_FLAG_BIN)
-            {
-                args = append_str_to_vector(args, &arg_size, "-a");
-                args = append_str_to_vector(args, &arg_size, value->content);
-            }
-        }
+        if (problem_formatter_load_file(pf, fmt_file))
+            error_msg_and_die("Invalid format file: %s", fmt_file);
+    }
+
+    problem_report_t *pr = NULL;
+    if (problem_formatter_generate_report(pf, problem_data, &pr))
+        error_msg_and_die("Failed to format bug report from problem data");
+
+    const char *subject = problem_report_get_summary(pr);
+    const char *dsc = problem_report_get_description(pr);
+
+    log_debug("subject: %s\n"
+              "\n"
+              "%s"
+              "\n"
+              , subject
+              , dsc);
+
+    /* attaching files to the email */
+    for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
+    {
+        log_debug("Attaching '%s' to the email", (const char *)a->data);
+        args = append_str_to_vector(args, &arg_size, "-a");
+        char *full_name = concat_path_file(realpath(dump_dir_name, NULL), a->data);
+        args = append_str_to_vector(args, &arg_size, full_name);
+        free(full_name);
     }
 
     args = append_str_to_vector(args, &arg_size, "-s");
@@ -135,7 +183,8 @@ static void create_and_send_email(
     log(_("Sending an email..."));
     exec_and_feed_input(dsc, args);
 
-    free(dsc);
+    problem_report_free(pr);
+    problem_formatter_free(pf);
 
     while (*args)
         free(*args++);
@@ -173,10 +222,11 @@ int main(int argc, char **argv)
 
     const char *dump_dir_name = ".";
     const char *conf_file = CONF_DIR"/plugins/mailx.conf";
+    const char *fmt_file = NULL;
 
     /* Can't keep these strings/structs static: _() doesn't support that */
     const char *program_usage_string = _(
-        "& [-v] -d DIR [-c CONFFILE]"
+        "& [-v] -d DIR [-c CONFFILE] [-F FMTFILE]"
         "\n"
         "\n""Sends contents of a problem directory DIR via email"
         "\n"
@@ -191,13 +241,15 @@ int main(int argc, char **argv)
         OPT_v = 1 << 0,
         OPT_d = 1 << 1,
         OPT_c = 1 << 2,
-        OPT_n = 1 << 3,
+        OPT_F = 1 << 3,
+        OPT_n = 1 << 4,
     };
     /* Keep enum above and order of options below in sync! */
     struct options program_options[] = {
         OPT__VERBOSE(&g_verbose),
         OPT_STRING('d', NULL, &dump_dir_name, "DIR"     , _("Problem directory")),
         OPT_STRING('c', NULL, &conf_file    , "CONFFILE", _("Config file")),
+        OPT_STRING('F', NULL, &fmt_file     , "FILE"    , _("Formatting file for an email")),
         OPT_BOOL('n', "notify-only", NULL  , _("Notify only (Do not mark the report as sent)")),
         OPT_END()
     };
@@ -208,7 +260,7 @@ int main(int argc, char **argv)
     map_string_t *settings = new_map_string();
     load_conf_file(conf_file, settings, /*skip key w/o values:*/ false);
 
-    create_and_send_email(dump_dir_name, settings, /*notify_only*/(opts & OPT_n));
+    create_and_send_email(dump_dir_name, settings, fmt_file, /*notify_only*/(opts & OPT_n));
 
     free_map_string(settings);
     return 0;
-- 
1.8.3.1