diff --git a/src/CLI/dbus.cpp b/src/CLI/dbus.cpp
index 600d855..9dd5bff 100644
--- a/src/CLI/dbus.cpp
+++ b/src/CLI/dbus.cpp
@@ -160,6 +160,7 @@ map_crash_data_t call_CreateReport(const char* crash_id)
 }
 
 report_status_t call_Report(const map_crash_data_t& report,
+			    const vector_string_t& reporters,
 			    const map_map_string_t &plugins)
 {
     DBusMessage* msg = new_call_msg(__func__ + 5);
@@ -169,8 +170,7 @@ report_status_t call_Report(const map_crash_data_t& report,
     /* parameter #1: report data */
     store_val(&out_iter, report);
     /* parameter #2: reporters to use */
-    vector_string_t reporters;
-    store_val(&out_iter, reporters); /* unused by daemon so far */
+    store_val(&out_iter, reporters);
     /* parameter #3 (opt): plugin config */
     if (!plugins.empty())
         store_val(&out_iter, plugins);
@@ -248,6 +248,22 @@ map_plugin_settings_t call_GetPluginSettings(const char *name)
     return argout;
 }
 
+map_map_string_t call_GetSettings()
+{
+    DBusMessage *msg = new_call_msg(__func__ + 5);
+    DBusMessage *reply = send_get_reply_and_unref(msg);
+
+    DBusMessageIter in_iter;
+    dbus_message_iter_init(reply, &in_iter);
+    map_map_string_t argout;
+    int r = load_val(&in_iter, argout);
+    if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */
+        error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5);
+
+    dbus_message_unref(reply);
+    return argout;
+}
+
 void handle_dbus_err(bool error_flag, DBusError *err)
 {
     if (dbus_error_is_set(err))
diff --git a/src/CLI/dbus.h b/src/CLI/dbus.h
index be6b961..4aaa4e9 100644
--- a/src/CLI/dbus.h
+++ b/src/CLI/dbus.h
@@ -24,21 +24,30 @@
 extern DBusConnection* s_dbus_conn;
 
 vector_map_crash_data_t call_GetCrashInfos();
+
 map_crash_data_t call_CreateReport(const char *crash_id);
 
 /** Sends report using enabled Reporter plugins.
+ * @param report
+ *  The report sent to Reporter plugins.
+ * @param reporters
+ *  List of names of Reporters which should be called.
  * @param plugins
- *  Optional settings for plugins, can be empty.
+ *  Optional settings for Reporter plugins, can be empty.
  *  Format: plugins["PluginName"]["SettingsKey"] = "SettingsValue"
  *  If it contains settings for some plugin, it must contain _all fields_
  *  obtained by call_GetPluginSettings, otherwise the plugin might ignore
  *  the settings.
  */
 report_status_t call_Report(const map_crash_data_t& report,
+			    const vector_string_t& reporters,
 			    const map_map_string_t &plugins);
+
 int32_t call_DeleteDebugDump(const char* crash_id);
 
 /* Gets basic data about all installed plugins.
+ * @todo
+ *  Return more semantically structured output - maybe a struct instead of a map.
  */
 map_map_string_t call_GetPluginsInfo();
 
@@ -48,6 +57,12 @@ map_map_string_t call_GetPluginsInfo();
  */
 map_plugin_settings_t call_GetPluginSettings(const char *name);
 
+/** Gets global daemon settings. 
+ * @todo
+ *   Return more semantically structured output - maybe a struct instead of a map.
+ */
+map_map_string_t call_GetSettings();
+
 void handle_dbus_err(bool error_flag, DBusError *err);
 
 #endif
diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp
index 2d79d38..bb8ed87 100644
--- a/src/CLI/report.cpp
+++ b/src/CLI/report.cpp
@@ -22,6 +22,9 @@
 #include "DebugDump.h"
 #include "CrashTypes.h" // FILENAME_* defines
 #include "Plugin.h" // LoadPluginSettings
+#include <cassert>
+#include <sstream>
+#include <algorithm>
 #if HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -432,17 +435,58 @@ static void read_from_stdin(const char *question, char *result, int result_size)
     *newline = '\0';
 }
 
-/**
- * Gets reporter plugin settings.
- * @param ask_user
- *   If it's set to true and some reporter plugin settings are found to be missing
- *   (like login name or password), user is asked to provide the missing parts.
- * @param settings
- *   A structure filled with reporter plugin settings.
+/** Splits a string into substrings using a chosen delimiter. */
+static vector_string_t split(const std::string &s, char delim) 
+{
+  std::stringstream ss(s);
+  std::string item;
+  std::vector<std::string> elems;
+  while (std::getline(ss, item, delim))
+    elems.push_back(item);
+  return elems;
+}
+
+/** Returns a list of enabled Reporter plugins, that are used to report
+ * a particular crash.
+ * @todo
+ *  Very similar code is used in the GUI, and also in the Daemon.
+ *  It should be shared.
  */
-static void get_reporter_plugin_settings(map_map_string_t &settings, bool ask_user)
+static vector_string_t get_enabled_reporters(map_crash_data_t &crash_data)
 {
-  /* First of all, load system-wide report plugin settings. */
+  vector_string_t result;
+
+  /* Get global daemon settings. Analyzer->Reporters mapping is stored there. */
+  map_map_string_t settings = call_GetSettings();
+  /* Reporters are separated by comma in the following map. */
+  map_string_t &analyzer_to_reporters = settings["AnalyzerActionsAndReporters"];
+
+  /* Get the analyzer from the crash. */
+  map_crash_data_t::const_iterator analyzerit = crash_data.find(FILENAME_ANALYZER);
+  if (analyzerit == crash_data.end())
+    return result; /* No analyzer found in the crash data. */
+  std::string analyzer = analyzerit->second[CD_CONTENT];
+
+  /* First try to find package name dependent analyzer.
+   * Copied from MiddleWare.cpp
+   */
+  map_crash_data_t::const_iterator its_PACKAGE = crash_data.find(FILENAME_PACKAGE);
+  std::string packageNVR = its_PACKAGE->second[CD_CONTENT];
+  std::string packageName = packageNVR.substr(0, packageNVR.rfind("-", packageNVR.rfind("-") - 1));
+  // analyzer with package name (CCpp:xorg-x11-app) has higher priority
+  std::string package_specific_analyzer = analyzer + ":" + packageName;
+
+  map_string_t::const_iterator reporters_iter = analyzer_to_reporters.find(package_specific_analyzer);
+  if (analyzer_to_reporters.end() == reporters_iter)
+  {
+    reporters_iter = analyzer_to_reporters.find(analyzer);
+    if (analyzer_to_reporters.end() == reporters_iter)
+      return result; /* No reporters found for the analyzer. */
+  }
+
+  /* Reporters found, now parse the list. */
+  vector_string_t reporter_vec = split(reporters_iter->second, ',');
+
   // Get informations about all plugins.
   map_map_string_t plugins = call_GetPluginsInfo();
   // Check the configuration of each enabled Reporter plugin.
@@ -455,11 +499,49 @@ static void get_reporter_plugin_settings(map_map_string_t &settings, bool ask_us
     // Skip nonReporter plugins.
     if (0 != strcmp(it->second["Type"].c_str(), "Reporter"))
       continue;
-    map_string_t single_plugin_settings = call_GetPluginSettings(it->first.c_str());
+    // Skip plugins not used in this particular crash.
+    if (reporter_vec.end() == std::find(reporter_vec.begin(), reporter_vec.end(), std::string(it->first)))
+      continue;
+    result.push_back(it->first);
+  }
+  return result;
+}
+
+/* Asks a [y/n] question on stdin/stdout. 
+ * Returns true if the answer is yes, false otherwise. 
+ */
+static bool ask_yesno(const char *question)
+{
+  printf(question);
+  fflush(NULL);
+  char answer[16] = "n";
+  fgets(answer, sizeof(answer), stdin);
+  /* TODO: localize 'y' */
+  return ((answer[0] | 0x20) == 'y');
+}
+
+/**
+ * Gets reporter plugin settings.
+ * @param reporters
+ *   List of reporter names. Settings of these reporters are handled.
+ * @param settings
+ *   A structure filled with reporter plugin settings.
+ * @param ask_user
+ *   If it's set to true and some reporter plugin settings are found to be missing
+ *   (like login name or password), user is asked to provide the missing parts.
+ */
+static void get_reporter_plugin_settings(const vector_string_t& reporters, 
+					 map_map_string_t &settings, 
+					 bool ask_user)
+{
+  /* First of all, load system-wide report plugin settings. */
+  for (vector_string_t::const_iterator it = reporters.begin(); it != reporters.end(); ++it)
+  {
+    map_string_t single_plugin_settings = call_GetPluginSettings(it->c_str());
     // Copy the received settings as defaults.
     // Plugins won't work without it, if some value is missing
     // they use their default values for all fields.
-    settings[it->first] = single_plugin_settings;
+    settings[it->c_str()] = single_plugin_settings;
   }
 
   /* Second, load user-specific settings, which override
@@ -468,8 +550,8 @@ static void get_reporter_plugin_settings(map_map_string_t &settings, bool ask_us
   const char* homedir = pw ? pw->pw_dir : NULL;
   if (homedir)
   {
-    itend = settings.end();
-    for (it = settings.begin(); it != itend; ++it)
+    map_map_string_t::const_iterator itend = settings.end();
+    for (map_map_string_t::iterator it = settings.begin(); it != itend; ++it)
     {
       map_string_t single_plugin_settings;
       std::string path = std::string(homedir) + "/.abrt/"
@@ -491,8 +573,8 @@ static void get_reporter_plugin_settings(map_map_string_t &settings, bool ask_us
     return;
 
   /* Third, check if a login or password is missing, and ask for it. */
-  itend = settings.end();
-  for (it = settings.begin(); it != itend; ++it)
+  map_map_string_t::const_iterator itend = settings.end();
+  for (map_map_string_t::iterator it = settings.begin(); it != itend; ++it)
   {
     map_string_t &single_plugin_settings = it->second;
     // Login information is missing.
@@ -538,40 +620,55 @@ int report(const char *crash_id, bool always)
       return result;
   }
 
-  /* Read the plugin settings. */
-  map_map_string_t pluginSettings;
-  get_reporter_plugin_settings(pluginSettings, !always);
+  /* Get enabled reporters associated with this particular crash. */
+  vector_string_t reporters = get_enabled_reporters(cr);
 
-  /* Ask if user really wants to send the report. */
-  if (!always)
+  int errors = 0;
+  int plugins = 0;
+  if (always)
   {
-    // Report only if the user is sure.
-    printf(_("Do you want to send the report? [y/N]: "));
-    fflush(NULL);
-    char answer[16] = "n";
-    fgets(answer, sizeof(answer), stdin);
-    if ((answer[0] | 0x20) != 'y')
+    map_map_string_t reporters_settings; /* to be filled on the next line */
+    get_reporter_plugin_settings(reporters, reporters_settings, false);
+
+    puts(_("Reporting..."));
+    report_status_t r = call_Report(cr, reporters, reporters_settings);
+    report_status_t::iterator it = r.begin();
+    while (it != r.end())
     {
-      puts(_("Crash report was not sent."));
-      return 0;
+      vector_string_t &v = it->second;
+      printf("%s: %s\n", it->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str());
+      plugins++;
+      if (v[REPORT_STATUS_IDX_FLAG] == "0")
+	errors++;
+      it++;
     }
   }
-
-  int errors = 0;
-  int plugins = 0;
-  puts(_("Reporting..."));
-  report_status_t r = call_Report(cr, pluginSettings);
-  report_status_t::iterator it = r.begin();
-  while (it != r.end())
+  else
   {
-    vector_string_t &v = it->second;
-    printf("%s: %s\n", it->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str());
-    plugins++;
-    if (v[REPORT_STATUS_IDX_FLAG] == "0")
-      errors++;
-    it++;
+    /* For every reporter, ask if user really wants to report using it. */
+    for (vector_string_t::const_iterator it = reporters.begin(); it != reporters.end(); ++it)
+    {
+      char question[255];
+      snprintf(question, 255, _("Report using %s? [y/N]: "), it->c_str());
+      if (!ask_yesno(question))
+      {
+	puts(_("Skipping..."));
+	continue;
+      }
+
+      vector_string_t cur_reporter(1, *it);
+      map_map_string_t reporters_settings; /* to be filled on the next line */
+      get_reporter_plugin_settings(cur_reporter, reporters_settings, true);
+      report_status_t r = call_Report(cr, cur_reporter, reporters_settings);
+      assert(r.size() == 1); /* one reporter --> one report status */
+      vector_string_t &v = r.begin()->second;
+      printf("%s: %s\n", r.begin()->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str());
+      plugins++;
+      if (v[REPORT_STATUS_IDX_FLAG] == "0")
+	errors++;
+    }
   }
-  printf(_("Crash reported via %d plugins (%d errors)\n"), plugins, errors);
 
+  printf(_("Crash reported via %d plugins (%d errors)\n"), plugins, errors);
   return errors != 0;
 }
diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp
index 103f867..d45209a 100644
--- a/src/Daemon/CommLayerServerDBus.cpp
+++ b/src/Daemon/CommLayerServerDBus.cpp
@@ -247,7 +247,7 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply)
         return 0;
     }
 
-    /* Second parameter: reporters to use */
+    /* Second parameter: list of reporters to use */
     vector_string_t reporters;
     r = load_val(&in_iter, reporters);
     if (r == ABRT_DBUS_ERROR)
@@ -256,7 +256,7 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply)
         return -1;
     }
 
-    /* Third parameter is optional */
+    /* Third parameter (optional): configuration data for plugins */
     map_map_string_t user_conf_data;
     if (r == ABRT_DBUS_MORE_FIELDS)
     {
@@ -294,7 +294,7 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply)
     report_status_t argout1;
     try
     {
-        argout1 = Report(argin1, user_conf_data, unix_uid);
+        argout1 = Report(argin1, reporters, user_conf_data, unix_uid);
     }
     catch (CABRTException &e)
     {
diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp
index 3ab3ddd..7792f5b 100644
--- a/src/Daemon/MiddleWare.cpp
+++ b/src/Daemon/MiddleWare.cpp
@@ -27,6 +27,7 @@
 #include "ABRTException.h"
 #include "CommLayerInner.h"
 #include "MiddleWare.h"
+#include <algorithm>
 
 using namespace std;
 
@@ -377,10 +378,11 @@ void RunActionsAndReporters(const char *pDebugDumpDir)
 }
 
 
-// We must not trust client_report here!
+// Do not trust client_report here!
 // dbus handler passes it from user without checking
 report_status_t Report(const map_crash_data_t& client_report,
-                       map_map_string_t& pSettings,
+                       const vector_string_t &reporters,
+                       map_map_string_t& settings,
                        long caller_uid)
 {
     // Get ID fields
@@ -498,39 +500,20 @@ report_status_t Report(const map_crash_data_t& client_report,
         for (; it_r != keyPtr->second.end(); it_r++)
         {
             const char *plugin_name = it_r->first.c_str();
+
+	    /* Check if the reporter is in the input list of allowed reporters. */
+	    if (reporters.end() == std::find(reporters.begin(), reporters.end(), plugin_name))
+	    {
+	        continue;
+	    }
+
             try
             {
                 if (g_pPluginManager->GetPluginType(plugin_name) == REPORTER)
                 {
                     CReporter* reporter = g_pPluginManager->GetReporter(plugin_name); /* can't be NULL */
-#if 0 /* Using ~user/.abrt/ is bad wrt security */
-                    std::string home;
-                    map_plugin_settings_t oldSettings;
-                    map_plugin_settings_t newSettings;
-
-                    if (pUID != "")
-                    {
-                        home = get_home_dir(xatoi_u(pUID.c_str()));
-                        if (home != "")
-                        {
-                            oldSettings = reporter->GetSettings();
-
-                            if (LoadPluginSettings(home + "/.abrt/" + plugin_name + "."PLUGINS_CONF_EXTENSION, newSettings))
-                            {
-                                reporter->SetSettings(newSettings);
-                            }
-                        }
-                    }
-#endif
-                    map_plugin_settings_t plugin_settings = pSettings[plugin_name];
+                    map_plugin_settings_t plugin_settings = settings[plugin_name];
                     std::string res = reporter->Report(stored_report, plugin_settings, it_r->second.c_str());
-
-#if 0 /* Using ~user/.abrt/ is bad wrt security */
-                    if (home != "")
-                    {
-                        reporter->SetSettings(oldSettings);
-                    }
-#endif
                     ret[plugin_name].push_back("1"); // REPORT_STATUS_IDX_FLAG
                     ret[plugin_name].push_back(res); // REPORT_STATUS_IDX_MSG
                     if (message != "")
@@ -589,7 +572,7 @@ static bool IsDebugDumpSaved(long uid,
     vector_database_rows_t rows = database->GetUIDData(uid);
     database->DisConnect();
 
-    int ii;
+    size_t ii;
     bool found = false;
     for (ii = 0; ii < rows.size(); ii++)
     {
diff --git a/src/Daemon/MiddleWare.h b/src/Daemon/MiddleWare.h
index 275d531..4a2903c 100644
--- a/src/Daemon/MiddleWare.h
+++ b/src/Daemon/MiddleWare.h
@@ -87,12 +87,20 @@ void RunActionsAndReporters(const char *pDebugDumpDir);
  * fails, then default config is used. If pUID is emply string, default
  * config is used.
  * ...).
- * @param pCrashData A crash report.
- * @param pUID An user uid
- * @return A report status, which reporters ends successfuly with messages.
+ * @param crash_data 
+ *  A crash report.
+ * @param reporters
+ *  List of allowed reporters. Which reporters will be used depends
+ *  on the analyzer of the crash_data. Reporters missing from this list 
+ *  will not be used.
+ * @param caller_uid 
+ *  An user uid.
+ * @return 
+ *  A report status, which reporters ends successfuly with messages.
  */
-report_status_t Report(const map_crash_data_t& pCrashData,
-                       map_map_string_t& pSettings,
+report_status_t Report(const map_crash_data_t& crash_data,
+                       const vector_string_t& reporters,
+                       map_map_string_t& settings,
                        long caller_uid);
 /**
  * Adds package name and description to debugdump dir.
