summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-11-12 16:58:07 +0100
committerKarel Klic <kklic@redhat.com>2009-11-12 16:58:07 +0100
commit32cee84a34c005fe0d2863f439007ec633687fa8 (patch)
tree149ca7014e4295de3788f28ae88e9d9d7003da46 /lib
parent5a8a8a6c99c9067e0dfcce839c32826a2badff0b (diff)
parent3938e6e075867ae3a349ba307ee672aa458d2662 (diff)
downloadabrt-32cee84a34c005fe0d2863f439007ec633687fa8.tar.gz
abrt-32cee84a34c005fe0d2863f439007ec633687fa8.tar.xz
abrt-32cee84a34c005fe0d2863f439007ec633687fa8.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/Bugzilla.cpp163
-rw-r--r--lib/Plugins/Bugzilla.h6
-rw-r--r--lib/Plugins/CCpp.cpp48
-rw-r--r--lib/Plugins/CCpp.h3
-rw-r--r--lib/Plugins/Catcut.cpp589
-rw-r--r--lib/Plugins/Catcut.h3
-rw-r--r--lib/Plugins/FileTransfer.cpp24
-rw-r--r--lib/Plugins/FileTransfer.h3
-rw-r--r--lib/Plugins/KerneloopsReporter.cpp21
-rw-r--r--lib/Plugins/KerneloopsReporter.h3
-rw-r--r--lib/Plugins/KerneloopsSysLog.cpp94
-rw-r--r--lib/Plugins/Logger.cpp32
-rw-r--r--lib/Plugins/Logger.h3
-rw-r--r--lib/Plugins/Mailx.cpp43
-rw-r--r--lib/Plugins/Mailx.h3
-rw-r--r--lib/Plugins/RunApp.cpp33
-rw-r--r--lib/Plugins/SOSreport.cpp54
-rw-r--r--lib/Plugins/SQLite3.cpp22
-rw-r--r--lib/Plugins/SQLite3.h3
-rw-r--r--lib/Plugins/TicketUploader.cpp32
-rw-r--r--lib/Plugins/TicketUploader.h3
-rw-r--r--lib/Utils/DebugDump.cpp28
-rw-r--r--lib/Utils/Makefile.am7
-rw-r--r--lib/Utils/abrt_xmlrpc.cpp76
-rw-r--r--lib/Utils/abrt_xmlrpc.h27
-rw-r--r--lib/Utils/parse_release.cpp38
-rw-r--r--lib/Utils/popen_and_save_output.cpp30
-rw-r--r--lib/Utils/stringops.cpp30
28 files changed, 859 insertions, 562 deletions
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp
index ecd4dd6..06f9334 100644
--- a/lib/Plugins/Bugzilla.cpp
+++ b/lib/Plugins/Bugzilla.cpp
@@ -1,69 +1,25 @@
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>
#include "abrtlib.h"
+#include "abrt_xmlrpc.h"
#include "Bugzilla.h"
#include "CrashTypes.h"
#include "DebugDump.h"
#include "ABRTException.h"
#include "CommLayerInner.h"
#ifdef HAVE_CONFIG_H
- #include <config.h>
+# include <config.h>
#endif
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
-static void get_product_and_version(const std::string& pRelease,
- std::string& pProduct,
- std::string& pVersion)
-{
- if (pRelease.find("Rawhide") != std::string::npos)
- {
- pProduct = "Fedora";
- pVersion = "rawhide";
- return;
- }
- if (pRelease.find("Fedora") != std::string::npos)
- {
- pProduct = "Fedora";
- }
- else if (pRelease.find("Red Hat Enterprise Linux") != std::string::npos)
- {
- pProduct = "Red Hat Enterprise Linux ";
- }
- std::string::size_type pos = pRelease.find("release");
- pos = pRelease.find(" ", pos) + 1;
- while (pRelease[pos] != ' ')
- {
- pVersion += pRelease[pos];
- if (pProduct == "Red Hat Enterprise Linux ")
- {
- pProduct += pRelease[pos];
- }
- pos++;
- }
-}
-
static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription)
{
pDescription = "abrt detected a crash.\n\n";
pDescription += make_description_bz(pCrashReport);
}
-// FIXME: we still leak memory if this function detects a fault:
-// many instances when we leave non-freed or non-xmlrpc_DECREF'ed data behind.
-static void throw_if_xml_fault_occurred(xmlrpc_env *env)
-{
- if (env->fault_occurred)
- {
- std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code);
- xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred
- xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env
- error_msg("%s", errmsg.c_str()); // show error in daemon log
- throw CABRTException(EXCEP_PLUGIN, errmsg);
- }
-}
-
/*
* Static namespace for xmlrpc stuff.
@@ -72,81 +28,18 @@ static void throw_if_xml_fault_occurred(xmlrpc_env *env)
namespace {
-struct ctx {
- xmlrpc_client* client;
- xmlrpc_server_info* server_info;
+struct ctx: public abrt_xmlrpc_conn {
+ ctx(const char* url, bool no_ssl_verify): abrt_xmlrpc_conn(url, no_ssl_verify) {}
- ctx(const char* url, bool no_ssl_verify) { new_xmlrpc_client(url, no_ssl_verify); }
- ~ctx() { destroy_xmlrpc_client(); }
-
- void new_xmlrpc_client(const char* url, bool no_ssl_verify);
- void destroy_xmlrpc_client();
-
- void login(const char* login, const char* passwd);
- void logout();
- int32_t check_uuid_in_bugzilla(const char* component, const char* UUID);
- bool check_cc_and_reporter(uint32_t bug_id, const char* login);
- void add_plus_one_cc(uint32_t bug_id, const char* login);
- uint32_t new_bug(const map_crash_report_t& pCrashReport);
- void add_attachments(const char* bug_id_str, const map_crash_report_t& pCrashReport);
+ void login(const char* login, const char* passwd);
+ void logout();
+ int32_t check_uuid_in_bugzilla(const char* component, const char* UUID);
+ bool check_cc_and_reporter(uint32_t bug_id, const char* login);
+ void add_plus_one_cc(uint32_t bug_id, const char* login);
+ uint32_t new_bug(const map_crash_report_t& pCrashReport);
+ void add_attachments(const char* bug_id_str, const map_crash_report_t& pCrashReport);
};
-void ctx::new_xmlrpc_client(const char* url, bool no_ssl_verify)
-{
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- /* This should be done at program startup, once.
- * We do it in abrtd's main */
- /* xmlrpc_client_setup_global_const(&env); */
-
- struct xmlrpc_curl_xportparms curlParms;
- memset(&curlParms, 0, sizeof(curlParms));
- /* curlParms.network_interface = NULL; - done by memset */
- curlParms.no_ssl_verifypeer = no_ssl_verify;
- curlParms.no_ssl_verifyhost = no_ssl_verify;
-#ifdef VERSION
- curlParms.user_agent = PACKAGE_NAME"/"VERSION;
-#else
- curlParms.user_agent = "abrt";
-#endif
-
- struct xmlrpc_clientparms clientParms;
- memset(&clientParms, 0, sizeof(clientParms));
- clientParms.transport = "curl";
- clientParms.transportparmsP = &curlParms;
- clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent);
-
- client = NULL;
- xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS,
- PACKAGE_NAME, VERSION,
- &clientParms, XMLRPC_CPSIZE(transportparm_size),
- &client);
- throw_if_xml_fault_occurred(&env);
-
- server_info = xmlrpc_server_info_new(&env, url);
- if (env.fault_occurred)
- {
- xmlrpc_client_destroy(client);
- client = NULL;
- }
- throw_if_xml_fault_occurred(&env);
-}
-
-void ctx::destroy_xmlrpc_client()
-{
- if (server_info)
- {
- xmlrpc_server_info_free(server_info);
- server_info = NULL;
- }
- if (client)
- {
- xmlrpc_client_destroy(client);
- client = NULL;
- }
-}
-
void ctx::login(const char* login, const char* passwd)
{
xmlrpc_env env;
@@ -156,7 +49,7 @@ void ctx::login(const char* login, const char* passwd)
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result = NULL;
- xmlrpc_client_call2(&env, client, server_info, "User.login", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.login", param, &result);
xmlrpc_DECREF(param);
if (result)
xmlrpc_DECREF(result);
@@ -179,7 +72,7 @@ void ctx::logout()
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result = NULL;
- xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.logout", param, &result);
xmlrpc_DECREF(param);
if (result)
xmlrpc_DECREF(result);
@@ -195,7 +88,7 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result = NULL;
- xmlrpc_client_call2(&env, client, server_info, "bugzilla.getBug", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.getBug", param, &result);
throw_if_xml_fault_occurred(&env);
xmlrpc_DECREF(param);
@@ -263,7 +156,7 @@ void ctx::add_plus_one_cc(uint32_t bug_id, const char* login)
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result = NULL;
- xmlrpc_client_call2(&env, client, server_info, "Bug.update", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.update", param, &result);
throw_if_xml_fault_occurred(&env);
xmlrpc_DECREF(result);
@@ -281,7 +174,7 @@ int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID)
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result = NULL;
- xmlrpc_client_call2(&env, client, server_info, "Bug.search", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.search", param, &result);
throw_if_xml_fault_occurred(&env);
xmlrpc_DECREF(param);
@@ -348,7 +241,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport)
std::string product;
std::string version;
- get_product_and_version(release, product, version);
+ parse_release(release.c_str(), product, version);
xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})",
"product", product.c_str(),
@@ -362,7 +255,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport)
throw_if_xml_fault_occurred(&env);
xmlrpc_value* result;
- xmlrpc_client_call2(&env, client, server_info, "Bug.create", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.create", param, &result);
throw_if_xml_fault_occurred(&env);
xmlrpc_value* id;
@@ -409,7 +302,7 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra
free(encoded64);
throw_if_xml_fault_occurred(&env);
- xmlrpc_client_call2(&env, client, server_info, "bugzilla.addAttachment", param, &result);
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.addAttachment", param, &result);
throw_if_xml_fault_occurred(&env);
xmlrpc_DECREF(result);
xmlrpc_DECREF(param);
@@ -444,14 +337,14 @@ std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport,
std::string BugzillaURL;
bool NoSSLVerify;
map_plugin_settings_t settings = parse_settings(pSettings);
- /* if parse_settings fails it returns an empty map so we need to use defaults*/
- if(!settings.empty())
+ /* if parse_settings fails it returns an empty map so we need to use defaults */
+ if (!settings.empty())
{
Login = settings["Login"];
Password = settings["Password"];
BugzillaXMLRPC = settings["BugzillaXMLRPC"];
BugzillaURL = settings["BugzillaURL"];
- NoSSLVerify = settings["NoSSLVerify"] == "yes";
+ NoSSLVerify = string_to_bool(settings["NoSSLVerify"].c_str());
}
else
{
@@ -513,9 +406,9 @@ std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport,
map_plugin_settings_t CReporterBugzilla::parse_settings(const map_plugin_settings_t& pSettings)
{
map_plugin_settings_t plugin_settings;
- map_plugin_settings_t::const_iterator it;
- map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
it = pSettings.find("BugzillaURL");
if (it != end)
{
@@ -567,6 +460,8 @@ map_plugin_settings_t CReporterBugzilla::parse_settings(const map_plugin_setting
void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings)
{
+ m_pSettings = pSettings;
+
//BUG! This gets called when user's keyring contains login data,
//then it takes precedence over /etc/abrt/plugins/Bugzilla.conf.
//I got a case when keyring had a STALE password, and there was no way
@@ -574,9 +469,8 @@ void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings)
//(by hacking abrt source!), I don't know how to purge it from the keyring.
//At the very least, log("SOMETHING") here.
- map_plugin_settings_t::const_iterator it;
map_plugin_settings_t::const_iterator end = pSettings.end();
-
+ map_plugin_settings_t::const_iterator it;
it = pSettings.find("BugzillaURL");
if (it != end)
{
@@ -614,10 +508,11 @@ void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("NoSSLVerify");
if (it != end)
{
- m_bNoSSLVerify = (it->second == "yes");
+ m_bNoSSLVerify = string_to_bool(it->second.c_str());
}
}
+/* Should not be deleted (why?) */
const map_plugin_settings_t& CReporterBugzilla::GetSettings()
{
m_pSettings["BugzillaURL"] = m_sBugzillaURL;
diff --git a/lib/Plugins/Bugzilla.h b/lib/Plugins/Bugzilla.h
index 55a5f5f..9130a69 100644
--- a/lib/Plugins/Bugzilla.h
+++ b/lib/Plugins/Bugzilla.h
@@ -19,11 +19,13 @@ class CReporterBugzilla : public CReporter
public:
CReporterBugzilla();
virtual ~CReporterBugzilla();
- virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+
virtual std::string Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings,
const std::string& pArgs);
+
+ virtual void SetSettings(const map_plugin_settings_t& pSettings);
+ virtual const map_plugin_settings_t& GetSettings();
};
#endif /* BUGZILLA_H_ */
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 6d6edd5..82c5677 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -127,6 +127,18 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
setreuid(uid, uid);
setsid();
+ /* Nuke everything which may make setlocale() switch to non-POSIX locale:
+ * we need to avoid having gdb output in some obscure language.
+ */
+ unsetenv("LANG");
+ unsetenv("LC_ALL");
+ unsetenv("LC_COLLATE");
+ unsetenv("LC_CTYPE");
+ unsetenv("LC_MESSAGES");
+ unsetenv("LC_MONETARY");
+ unsetenv("LC_NUMERIC");
+ unsetenv("LC_TIME");
+
execvp(pArgs[0], pArgs);
/* VERB1 since sometimes we expect errors here */
VERB1 perror_msg("Can't execute '%s'", pArgs[0]);
@@ -164,6 +176,8 @@ static LineRating rate_line(const char *line)
{
#define FOUND(x) (strstr(line, x) != NULL)
/* see the "enum LineRating" comments for possible combinations */
+ if (FOUND(" at "))
+ return Good;
const char *function = strstr(line, " in ");
if (function)
{
@@ -171,12 +185,6 @@ static LineRating rate_line(const char *line)
{
function = NULL;
}
- else
- {
- bool source_file = FOUND(" at ");
- if (source_file)
- return Good;
- }
}
bool library = FOUND(" from ");
if (function && library)
@@ -193,7 +201,7 @@ static LineRating rate_line(const char *line)
/* returns number of "stars" to show */
static int rate_backtrace(const char *backtrace)
{
- int i, len;
+ int i, j, len;
int multiplier = 0;
int rating = 0;
int best_possible_rating = 0;
@@ -210,6 +218,9 @@ static int rate_backtrace(const char *backtrace)
if (backtrace[i] == '#') /* this separates frames from each other */
{
std::string s(backtrace + i + 1, len);
+ for (j=0; j<len; j++) /* replace tabs with spaces */
+ if (s[j] == '\t')
+ s[j] = ' ';
multiplier++;
rating += rate_line(s.c_str()) * multiplier;
best_possible_rating += BestRating * multiplier;
@@ -969,7 +980,7 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("MemoryMap");
if (it != end)
{
- m_bMemoryMap = it->second == "yes";
+ m_bMemoryMap = string_to_bool(it->second.c_str());
}
it = pSettings.find("DebugInfo");
if (it != end)
@@ -986,19 +997,20 @@ void CAnalyzerCCpp::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("InstallDebuginfo");
if (it != end)
{
- m_bInstallDebugInfo = it->second == "yes";
+ m_bInstallDebugInfo = string_to_bool(it->second.c_str());
}
}
-const map_plugin_settings_t& CAnalyzerCCpp::GetSettings()
-{
- m_pSettings["MemoryMap"] = m_bMemoryMap ? "yes" : "no";
- m_pSettings["DebugInfo"] = m_sDebugInfo;
- m_pSettings["DebugInfoCacheMB"] = to_string(m_nDebugInfoCacheMB);
- m_pSettings["InstallDebugInfo"] = m_bInstallDebugInfo ? "yes" : "no";
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CAnalyzerCCpp::GetSettings()
+//{
+// m_pSettings["MemoryMap"] = m_bMemoryMap ? "yes" : "no";
+// m_pSettings["DebugInfo"] = m_sDebugInfo;
+// m_pSettings["DebugInfoCacheMB"] = to_string(m_nDebugInfoCacheMB);
+// m_pSettings["InstallDebugInfo"] = m_bInstallDebugInfo ? "yes" : "no";
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(ANALYZER,
CAnalyzerCCpp,
diff --git a/lib/Plugins/CCpp.h b/lib/Plugins/CCpp.h
index e2abdec..3fa0d99 100644
--- a/lib/Plugins/CCpp.h
+++ b/lib/Plugins/CCpp.h
@@ -44,7 +44,8 @@ class CAnalyzerCCpp : public CAnalyzer
virtual void Init();
virtual void DeInit();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
};
#endif /* CCPP */
diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp
index 13fa8a4..e6d16b4 100644
--- a/lib/Plugins/Catcut.cpp
+++ b/lib/Plugins/Catcut.cpp
@@ -1,7 +1,8 @@
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>
-
+#include <curl/curl.h>
#include "abrtlib.h"
+#include "abrt_xmlrpc.h"
#include "Catcut.h"
#include "CrashTypes.h"
#include "DebugDump.h"
@@ -13,108 +14,8 @@
using namespace std;
-static xmlrpc_env env;
-static xmlrpc_client* client = NULL;
-static struct xmlrpc_clientparms clientParms;
-static struct xmlrpc_curl_xportparms curlParms;
-static xmlrpc_server_info* server_info = NULL;
-
-
-static string login(const char* login, const char* passwd);
-//static void logout();
-static void new_xmlrpc_client(const char* url, bool no_ssl_verify);
-static void destroy_xmlrpc_client();
-static void create_new_bug_description(const map_crash_report_t& pCrashReport, string& pDescription);
-static void get_product_and_version(const string& pRelease,
- string& pProduct,
- string& pVersion);
-
-
-static void throw_if_xml_fault_occurred()
-{
- if (env.fault_occurred)
- {
- string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env.fault_string, env.fault_code);
- error_msg("%s", errmsg.c_str()); // show error in daemon log
- throw CABRTException(EXCEP_PLUGIN, errmsg);
- }
-}
-
-static void new_xmlrpc_client(const char* url, bool no_ssl_verify)
-{
- xmlrpc_env_init(&env);
-
- /* This should be done at program startup, once.
- * We do it in abrtd's main */
- /* xmlrpc_client_setup_global_const(&env); */
-
- curlParms.network_interface = NULL;
- curlParms.no_ssl_verifypeer = no_ssl_verify;
- curlParms.no_ssl_verifyhost = no_ssl_verify;
-#ifdef VERSION
- curlParms.user_agent = PACKAGE_NAME"/"VERSION;
-#else
- curlParms.user_agent = "abrt";
-#endif
-
- clientParms.transport = "curl";
- clientParms.transportparmsP = &curlParms;
- clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent);
-
- xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, PACKAGE_NAME, VERSION, &clientParms, XMLRPC_CPSIZE(transportparm_size),
- &client);
- throw_if_xml_fault_occurred();
-
- server_info = xmlrpc_server_info_new(&env, url);
- throw_if_xml_fault_occurred();
-}
-
-static void destroy_xmlrpc_client()
-{
- xmlrpc_server_info_free(server_info);
- xmlrpc_env_clean(&env);
- xmlrpc_client_destroy(client);
-}
-
-static string login(const char* login, const char* passwd)
-{
- xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd);
- throw_if_xml_fault_occurred();
-
- xmlrpc_value* result;
- xmlrpc_client_call2(&env, client, server_info, "Catcut.auth", param, &result);
- throw_if_xml_fault_occurred();
- xmlrpc_DECREF(param);
-
- xmlrpc_value *cookie_xml;
- const char *cookie;
- string cookie_str;
- xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml);
- throw_if_xml_fault_occurred();
- xmlrpc_read_string(&env, cookie_xml, &cookie);
- throw_if_xml_fault_occurred();
- cookie_str = cookie;
- /* xmlrpc_read_string returns *malloc'ed ptr*.
- * doc is not very clear on it, but I looked in xmlrpc sources. */
- free((void*)cookie);
- xmlrpc_DECREF(cookie_xml);
-
- xmlrpc_DECREF(result);
-
- return cookie_str;
-}
-
-// catcut does not have it (yet?)
-//static void logout()
-//{
-// xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", "");
-// throw_if_xml_fault_occurred();
-//
-// xmlrpc_value* result = NULL; /* paranoia */
-// xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result);
-// throw_if_xml_fault_occurred();
-//}
+//TODO: move to make_descr.cpp
static void create_new_bug_description(const map_crash_report_t& pCrashReport, string& pDescription)
{
string howToReproduce;
@@ -167,39 +68,253 @@ static void create_new_bug_description(const map_crash_report_t& pCrashReport, s
}
}
-static void get_product_and_version(const string& pRelease,
- string& pProduct,
- string& pVersion)
+static int
+put_stream(const char *pURL, FILE* f, size_t content_length)
{
- if (pRelease.find("Rawhide") != string::npos)
+ CURL* curl = curl_easy_init();
+ if (!curl)
{
- pProduct = "Fedora";
- pVersion = "rawhide";
+ throw CABRTException(EXCEP_PLUGIN, "put_stream: Curl library error.");
+ }
+ /* enable uploading */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+ /* specify target */
+ curl_easy_setopt(curl, CURLOPT_URL, pURL);
+ /* file handle: passed to the default callback, it will fread() it */
+ curl_easy_setopt(curl, CURLOPT_READDATA, f);
+ /* get file size */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, content_length);
+ /*everything is done here; result 0 means success*/
+ int result = curl_easy_perform(curl);
+ /* goodbye */
+ curl_easy_cleanup(curl);
+ return result;
+}
+
+static void
+send_string(const char *pURL,
+ const char *pContent,
+ int retryCount,
+ int retryDelaySeconds)
+{
+ if (pURL[0] == '\0')
+ {
+ error_msg(_("send_string: URL not specified"));
return;
}
- if (pRelease.find("Fedora") != string::npos)
+
+ do
{
- pProduct = "Fedora";
+ int content_length = strlen(pContent);
+ FILE* f = fmemopen((void*)pContent, content_length, "r");
+ if (!f)
+ {
+ throw CABRTException(EXCEP_PLUGIN, "send_string: could not open string stream");
+ }
+ int result = put_stream(pURL, f, content_length);
+ fclose(f);
+ if (!result)
+ return;
+ update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result));
}
- else if (pRelease.find("Red Hat Enterprise Linux") != string::npos)
+ /*retry the upload if not succesful, wait a bit before next try*/
+ while (--retryCount != 0 && (sleep(retryDelaySeconds), 1));
+
+ throw CABRTException(EXCEP_PLUGIN, "send_string: could not send string");
+}
+
+static void
+send_file(const char *pURL,
+ const char *pFilename,
+ int retryCount,
+ int retryDelaySeconds)
+{
+ if (pURL[0] == '\0')
{
- pProduct = "Red Hat Enterprise Linux ";
+ error_msg(_("send_file: URL not specified"));
+ return;
}
- string::size_type pos = pRelease.find("release");
- pos = pRelease.find(" ", pos) + 1;
- while (pRelease[pos] != ' ')
+
+ update_client(_("Sending file %s to %s"), pFilename, pURL);
+
+ do
{
- pVersion += pRelease[pos];
- if (pProduct == "Red Hat Enterprise Linux ")
+ FILE* f = fopen(pFilename, "r");
+ if (!f)
{
- pProduct += pRelease[pos];
+ throw CABRTException(EXCEP_PLUGIN, "send_file: could not open string stream");
}
- pos++;
+ struct stat buf;
+ fstat(fileno(f), &buf); /* can't fail */
+ int content_length = buf.st_size;
+ int result = put_stream(pURL, f, content_length);
+ fclose(f);
+ if (!result)
+ return;
+ update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result));
}
+ /*retry the upload if not succesful, wait a bit before next try*/
+ while (--retryCount != 0 && (sleep(retryDelaySeconds), 1));
+
+ throw CABRTException(EXCEP_PLUGIN, "send_file: could not send file");
}
-static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport)
+static string
+resolve_relative_url(const char *url, const char *base)
+{
+ // if 'url' is relative (not absolute) combine it with 'base'
+ // (which must be absolute)
+ // Only works in limited cases:
+ // 0) url is already absolute
+ // 1) url starts with two slashes
+ // 2) url starts with one slash
+
+ const char *colon = strchr(url, ':');
+ const char *slash = strchr(url, '/');
+
+ if (colon && (!slash || colon < slash))
+ {
+ return url;
+ }
+
+ const char *end_of_protocol = strchr(base, ':');
+ string protocol(base, end_of_protocol - base);
+
+ end_of_protocol += 3; /* skip "://" */
+ const char *end_of_host = strchr(end_of_protocol, '/');
+ string host(end_of_protocol, end_of_host - end_of_protocol);
+
+ if (url[0] == '/')
+ {
+ if (url[1] == '/')
+ {
+ protocol += ':';
+ protocol += url;
+ return protocol;
+ }
+ protocol += "://";
+ protocol += host;
+ protocol += url;
+ return protocol;
+ }
+ throw CABRTException(EXCEP_PLUGIN, "resolve_relative_url: unhandled relative url");
+}
+
+//
+// struct_find_XXXX
+// abstract all the busy work of getting a field's value from
+// a struct. XXXX is a type.
+// Return true/false = the field is in the struct
+// If true, return the field's value in 'value'.
+//
+// This function currently just assumes that the value in the
+// field can be read into the type of 'value'. This should probably
+// be fixed to either convert the fields value to the type of 'value'
+// or error specifically/usefully.
+//
+// This function probably should be converted to an overloaded function
+// (overloaded on the type of 'value'). It could also be a function
+// template.
+//
+
+static bool
+struct_find_int(xmlrpc_env* env, xmlrpc_value* result,
+ const char* fieldName, int& value)
+{
+ xmlrpc_value* an_xmlrpc_value;
+ xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value);
+ throw_if_xml_fault_occurred(env);
+ if (an_xmlrpc_value)
+ {
+ xmlrpc_read_int(env, an_xmlrpc_value, &value);
+ throw_if_xml_fault_occurred(env);
+ xmlrpc_DECREF(an_xmlrpc_value);
+ return true;
+ }
+ return false;
+}
+
+static bool
+struct_find_string(xmlrpc_env* env, xmlrpc_value* result,
+ const char* fieldName, string& value)
+{
+ xmlrpc_value* an_xmlrpc_value;
+ xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value);
+ throw_if_xml_fault_occurred(env);
+ if (an_xmlrpc_value)
+ {
+ const char* value_s;
+ xmlrpc_read_string(env, an_xmlrpc_value, &value_s);
+ throw_if_xml_fault_occurred(env);
+ value = value_s;
+ xmlrpc_DECREF(an_xmlrpc_value);
+ free((void*)value_s);
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Static namespace for xmlrpc stuff.
+ * Used mainly to ensure we always destroy xmlrpc client and server_info.
+ */
+
+namespace {
+
+struct ctx: public abrt_xmlrpc_conn {
+ ctx(const char* url, bool no_ssl_verify): abrt_xmlrpc_conn(url, no_ssl_verify) {}
+
+ string login(const char* login, const char* passwd);
+ string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport);
+ string request_upload(const char* auth_cookie, const char* pTicketName,
+ const char* fileName, const char* description);
+ void add_attachments(const char* xmlrpc_URL,
+ const char* auth_cookie,
+ const char* pTicketName,
+ const map_crash_report_t& pCrashReport,
+ int retryCount,
+ int retryDelaySeconds);
+};
+
+string
+ctx::login(const char* login, const char* passwd)
{
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result;
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.auth", param, &result);
+ xmlrpc_DECREF(param);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value *cookie_xml;
+ const char *cookie;
+ string cookie_str;
+ xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml);
+ throw_if_xml_fault_occurred(&env);
+ xmlrpc_read_string(&env, cookie_xml, &cookie);
+ throw_if_xml_fault_occurred(&env);
+ cookie_str = cookie;
+ /* xmlrpc_read_string returns *malloc'ed ptr*.
+ * doc is not very clear on it, but I looked in xmlrpc sources. */
+ free((void*)cookie);
+ xmlrpc_DECREF(cookie_xml);
+
+ xmlrpc_DECREF(result);
+
+ return cookie_str;
+}
+
+string
+ctx::new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport)
+{
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT];
string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT];
string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT];
@@ -214,7 +329,7 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR
string product;
string version;
- get_product_and_version(release, product, version);
+ parse_release(release.c_str(), product, version);
xmlrpc_value *param = xmlrpc_build_value(&env, "(s{s:s,s:s,s:s,s:s,s:s,s:s,s:s})",
auth_cookie,
@@ -226,20 +341,20 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR
"status_whiteboard", status_whiteboard.c_str(),
"platform", arch.c_str()
);
- throw_if_xml_fault_occurred();
+ throw_if_xml_fault_occurred(&env);
xmlrpc_value *result;
- xmlrpc_client_call2(&env, client, server_info, "Catcut.createTicket", param, &result);
- throw_if_xml_fault_occurred();
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.createTicket", param, &result);
xmlrpc_DECREF(param);
+ throw_if_xml_fault_occurred(&env);
xmlrpc_value *bug_id_xml;
const char *bug_id;
string bug_id_str;
xmlrpc_struct_find_value(&env, result, "ticket", &bug_id_xml);
- throw_if_xml_fault_occurred();
+ throw_if_xml_fault_occurred(&env);
xmlrpc_read_string(&env, bug_id_xml, &bug_id);
- throw_if_xml_fault_occurred();
+ throw_if_xml_fault_occurred(&env);
bug_id_str = bug_id;
log("New bug id: %s", bug_id);
update_client(_("New bug id: %s"), bug_id);
@@ -251,81 +366,177 @@ static string new_bug(const char *auth_cookie, const map_crash_report_t& pCrashR
return bug_id_str;
}
-//static
-//void add_attachments(const string& pBugId, const map_crash_report_t& pCrashReport)
-//{
-// xmlrpc_value* result = NULL;
-//
-// map_crash_report_t::const_iterator it = pCrashReport.begin();
-// for (; it != pCrashReport.end(); it++)
-// {
-// if (it->second[CD_TYPE] == CD_ATT)
-// {
-// string description = "File: " + it->first;
-// const string& to_encode = it->second[CD_CONTENT];
-// char *encoded64 = encode_base64(to_encode.c_str(), to_encode.length());
-// xmlrpc_value* param = xmlrpc_build_value(&env,"(s{s:s,s:s,s:s,s:s})",
-// pBugId.c_str(),
-// "description", description.c_str(),
-// "filename", it->first.c_str(),
-// "contenttype", "text/plain",
-// "data", encoded64
-// );
-// free(encoded64);
-// throw_if_xml_fault_occurred();
-//
-//// catcut has this API:
-//// struct response requestUpload(string cookie, string ticket, string filename, string description)
-////response MUST include "errno", "errmsg" members; if an upload is approved,
-////a "URL" MUST be returned in the response. The description string
-////should include a brief description of the file.
-////
-////The client should upload the file via HTTP PUT to the provided
-////URL. The provided URL may be absolute or relative, if relative it must
-////be combined with the base URL of the XML-RPC server using the usual
-////rules for relative URL's (RFC 3986).
-// xmlrpc_client_call2(&env, client, server_info, "catcut.addAttachment", param, &result);
-// throw_if_xml_fault_occurred();
-// }
-// }
-//}
+string
+ctx::request_upload(const char* auth_cookie, const char* pTicketName,
+ const char* fileName, const char* description)
+{
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_value* param = xmlrpc_build_value(&env, "(ssss)",
+ auth_cookie,
+ pTicketName,
+ fileName,
+ description);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.requestUpload", param, &result);
+ xmlrpc_DECREF(param);
+ throw_if_xml_fault_occurred(&env);
+
+ string URL;
+ bool has_URL = struct_find_string(&env, result, "uri", URL);
+ if (!has_URL || URL == "")
+ {
+ int err;
+ bool has_errno = struct_find_int(&env, result, "errno", err);
+ if (has_errno && err)
+ {
+ string errmsg;
+ bool has_errmsg = struct_find_string(&env, result, "errmsg", errmsg);
+ if (has_errmsg)
+ {
+ log("error returned by requestUpload: %s", errmsg.c_str());
+ update_client(_("error returned by requestUpload: %s"), errmsg.c_str());
+ }
+ else
+ {
+ log("error returned by requestUpload: %d", err);
+ update_client(_("error returned by requestUpload: %d"), err);
+ }
+ }
+ else
+ {
+ log("no URL returned by requestUpload, and no err");
+ update_client(_("no URL returned by requestUpload, and no errno"));
+ }
+ }
+
+ log("requestUpload returned URL: %s", URL.c_str());
+ update_client(_("requestUpload returned URL: %s"), URL.c_str());
+
+ xmlrpc_DECREF(result);
+ return URL;
+}
+
+void
+ctx::add_attachments(const char* xmlrpc_URL,
+ const char* auth_cookie,
+ const char* pTicketName,
+ const map_crash_report_t& pCrashReport,
+ int retryCount,
+ int retryDelaySeconds)
+{
+
+ map_crash_report_t::const_iterator it = pCrashReport.begin();
+ for (; it != pCrashReport.end(); it++)
+ {
+ if (it->second[CD_TYPE] == CD_ATT)
+ {
+ update_client(_("Attaching (CD_ATT): %s"), it->first.c_str());
+
+ string description = "File: " + it->first;
+ string URL = request_upload(auth_cookie,
+ pTicketName,
+ it->first.c_str(),
+ description.c_str());
+
+ URL = resolve_relative_url(URL.c_str(), xmlrpc_URL);
+
+ log("rebased URL: %s", URL.c_str());
+ update_client(_("rebased URL: %s"), URL.c_str());
+
+ send_string(URL.c_str(), it->second[CD_CONTENT].c_str(),
+ retryCount, retryDelaySeconds);
+ }
+ else if (it->second[CD_TYPE] == CD_BIN)
+ {
+ update_client(_("Attaching (CD_ATT): %s"), it->first.c_str());
+
+ string description = "File: " + it->first;
+ string URL = request_upload(auth_cookie,
+ pTicketName,
+ it->first.c_str(),
+ description.c_str());
+
+ URL = resolve_relative_url(URL.c_str(), xmlrpc_URL);
+
+ log("rebased URL: %s", URL.c_str());
+ update_client(_("rebased URL: %s"), URL.c_str());
+
+ send_file(URL.c_str(), it->second[CD_CONTENT].c_str(),
+ retryCount, retryDelaySeconds);
+ }
+ }
+}
+
+} /* namespace */
+
+
+/*
+ * CReporterCatcut
+ */
CReporterCatcut::CReporterCatcut() :
m_sCatcutURL("http://127.0.0.1:8080/catcut/xmlrpc"),
- m_bNoSSLVerify(false)
+ m_bNoSSLVerify(false),
+ m_nRetryCount(3),
+ m_nRetryDelay(20)
{}
CReporterCatcut::~CReporterCatcut()
{}
string CReporterCatcut::Report(const map_crash_report_t& pCrashReport,
- const map_plugin_settings_t& pSettings, const string& pArgs)
+ const map_plugin_settings_t& pSettings,
+ const string& pArgs)
{
update_client(_("Creating new bug..."));
try
{
- new_xmlrpc_client(m_sCatcutURL.c_str(), m_bNoSSLVerify);
- string auth_cookie = login(m_sLogin.c_str(), m_sPassword.c_str());
- string bug_id = (auth_cookie != "") ? new_bug(auth_cookie.c_str(), pCrashReport) : "";
-// add_attachments(to_string(bug_id), pCrashReport);
-// update_client(_("Logging out..."));
-// logout();
- destroy_xmlrpc_client();
- return "New catcut bug ID: " + bug_id;
+ ctx catcut_server(m_sCatcutURL.c_str(), m_bNoSSLVerify);
+ string auth_cookie = catcut_server.login(m_sLogin.c_str(), m_sPassword.c_str());
+ string message;
+ if (auth_cookie != "")
+ {
+ string ticket_name = catcut_server.new_bug(auth_cookie.c_str(), pCrashReport);
+ if (ticket_name != "")
+ {
+ catcut_server.add_attachments(
+ m_sCatcutURL.c_str(),
+ auth_cookie.c_str(),
+ ticket_name.c_str(),
+ pCrashReport,
+ m_nRetryCount,
+ m_nRetryDelay
+ );
+ message = "New catcut bug ID: " + ticket_name;
+ }
+ else
+ {
+ message = "Error could not create ticket";
+ }
+ }
+ else
+ {
+ message = "Error could not create ticket";
+ }
+ return message;
}
catch (CABRTException& e)
{
- destroy_xmlrpc_client();
- throw CABRTException(EXCEP_PLUGIN, string("CReporterCatcut::Report(): ") + e.what());
+ throw CABRTException(EXCEP_PLUGIN, e.what());
}
}
void CReporterCatcut::SetSettings(const map_plugin_settings_t& pSettings)
{
- map_plugin_settings_t::const_iterator it;
- map_plugin_settings_t::const_iterator end = pSettings.end();
+ m_pSettings = pSettings;
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
it = pSettings.find("CatcutURL");
if (it != end)
{
@@ -344,18 +555,18 @@ void CReporterCatcut::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("NoSSLVerify");
if (it != end)
{
- m_bNoSSLVerify = it->second == "yes";
+ m_bNoSSLVerify = string_to_bool(it->second.c_str());
+ }
+ it = pSettings.find("RetryCount");
+ if (it != end)
+ {
+ m_nRetryCount = atoi(it->second.c_str());
+ }
+ it = pSettings.find("RetryDelay");
+ if (it != end)
+ {
+ m_nRetryDelay = atoi(it->second.c_str());
}
-}
-
-const map_plugin_settings_t& CReporterCatcut::GetSettings()
-{
- m_pSettings["CatcutURL"] = m_sCatcutURL;
- m_pSettings["Login"] = m_sLogin;
- m_pSettings["Password"] = m_sPassword;
- m_pSettings["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no";
-
- return m_pSettings;
}
PLUGIN_INFO(REPORTER,
diff --git a/lib/Plugins/Catcut.h b/lib/Plugins/Catcut.h
index 15efdc1..4fb89e2 100644
--- a/lib/Plugins/Catcut.h
+++ b/lib/Plugins/Catcut.h
@@ -11,13 +11,14 @@ class CReporterCatcut : public CReporter
std::string m_sLogin;
std::string m_sPassword;
bool m_bNoSSLVerify;
+ int m_nRetryCount;
+ int m_nRetryDelay;
public:
CReporterCatcut();
virtual ~CReporterCatcut();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
virtual std::string Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings,
diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp
index 72b3b16..868f54d 100644
--- a/lib/Plugins/FileTransfer.cpp
+++ b/lib/Plugins/FileTransfer.cpp
@@ -370,8 +370,11 @@ void CFileTransfer::Run(const char *pActionDir, const char *pArgs)
void CFileTransfer::SetSettings(const map_plugin_settings_t& pSettings)
{
+ m_pSettings = pSettings;
+
map_plugin_settings_t::const_iterator end = pSettings.end();
- map_plugin_settings_t::const_iterator it = pSettings.find("URL");
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("URL");
if (it != end)
{
m_sURL = it->second;
@@ -405,15 +408,16 @@ void CFileTransfer::SetSettings(const map_plugin_settings_t& pSettings)
}
}
-const map_plugin_settings_t& CFileTransfer::GetSettings()
-{
- m_pSettings["URL"] = m_sURL;
- m_pSettings["RetryCount"] = to_string(m_nRetryCount);
- m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
- m_pSettings["ArchiveType"] = m_sArchiveType;
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CFileTransfer::GetSettings()
+//{
+// m_pSettings["URL"] = m_sURL;
+// m_pSettings["RetryCount"] = to_string(m_nRetryCount);
+// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
+// m_pSettings["ArchiveType"] = m_sArchiveType;
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(ACTION,
CFileTransfer,
diff --git a/lib/Plugins/FileTransfer.h b/lib/Plugins/FileTransfer.h
index 9caa256..91207f4 100644
--- a/lib/Plugins/FileTransfer.h
+++ b/lib/Plugins/FileTransfer.h
@@ -41,7 +41,8 @@ class CFileTransfer : public CAction
public:
CFileTransfer();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
virtual void Run(const char *pActionDir, const char *pArgs);
};
diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp
index cfb4e05..f7a6cbb 100644
--- a/lib/Plugins/KerneloopsReporter.cpp
+++ b/lib/Plugins/KerneloopsReporter.cpp
@@ -118,18 +118,23 @@ std::string CKerneloopsReporter::Report(const map_crash_report_t& pCrashReport,
void CKerneloopsReporter::SetSettings(const map_plugin_settings_t& pSettings)
{
- map_plugin_settings_t::const_iterator it = pSettings.find("SubmitURL");
- if (it != pSettings.end()) {
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("SubmitURL");
+ if (it != end) {
m_sSubmitURL = it->second;
}
}
-const map_plugin_settings_t& CKerneloopsReporter::GetSettings()
-{
- m_pSettings["SubmitURL"] = m_sSubmitURL;
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CKerneloopsReporter::GetSettings()
+//{
+// m_pSettings["SubmitURL"] = m_sSubmitURL;
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(REPORTER,
CKerneloopsReporter,
diff --git a/lib/Plugins/KerneloopsReporter.h b/lib/Plugins/KerneloopsReporter.h
index 7f6ab8c..af82afb 100644
--- a/lib/Plugins/KerneloopsReporter.h
+++ b/lib/Plugins/KerneloopsReporter.h
@@ -41,7 +41,8 @@ class CKerneloopsReporter : public CReporter
CKerneloopsReporter();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
virtual std::string Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings,
const std::string& pArgs);
diff --git a/lib/Plugins/KerneloopsSysLog.cpp b/lib/Plugins/KerneloopsSysLog.cpp
index d28ce39..cb15fcc 100644
--- a/lib/Plugins/KerneloopsSysLog.cpp
+++ b/lib/Plugins/KerneloopsSysLog.cpp
@@ -75,7 +75,6 @@ struct line_info {
int extract_oopses(vector_string_t &oopses, char *buffer, size_t buflen)
{
char *c;
- enum { maybe, no, yes } syslog_format = maybe;
int linecount = 0;
int lines_info_alloc = 0;
struct line_info *lines_info = NULL;
@@ -86,86 +85,73 @@ int extract_oopses(vector_string_t &oopses, char *buffer, size_t buflen)
buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */
c = buffer;
while (c < buffer + buflen) {
- char v, linelevel;
- int len = 0;
+ char linelevel;
char *c9;
char *linepointer;
c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */
assert(c9);
- len = c9 - c;
+ *c9 = '\0'; /* turn the \n into a string termination */
+ if (c9 == c)
+ goto next_line;
/* in /var/log/messages, we need to strip the first part off, upto the 3rd ':' */
- if (syslog_format == yes
- || (syslog_format == maybe
- && len > sizeof("Jul 4 11:11:41")
- && c[3] == ' ' && c[6] == ' ' && c[9] == ':' && c[12] == ':'
- && (v = (c[5] | c[7]|c[8] | c[10]|c[11] | c[13]|c[14])) <= '9'
- && v >= '0'
- && (v = (c[5] & c[7]&c[8] & c[10]&c[11] & c[13]&c[14])) <= '9'
- && v >= '0'
- )
+ /* 01234567890123456 */
+ if ((c9 - c) > sizeof("Jul 4 11:11:11 ")
+ && c[3] == ' '
+ && (c[4] == ' ' || isdigit(c[4]))
+ && isdigit(c[5])
+ && c[6] == ' '
+ && isdigit(c[7])
+ && isdigit(c[8])
+ && c[9] == ':'
+ && isdigit(c[10])
+ && isdigit(c[11])
+ && c[12] == ':'
+ && isdigit(c[13])
+ && isdigit(c[14])
+ && c[15] == ' '
) {
/* It's syslog file, not a bare dmesg */
- syslog_format = yes;
-
- char *c2;
- int i;
- /* skip non-kernel lines */
- c2 = (char*)memmem(c, len, "kernel:", 7);
- if (!c2)
- c2 = (char*)memmem(c, len, "abrt:", 5);
- if (!c2)
+ /* Skip over timestamp */
+ c += 16;
+
+ /* Skip non-kernel lines */
+ char *kernel_str = strstr(c, "kernel: ");
+ if (kernel_str == NULL) {
+ /* if we see our own marker:
+ * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt"
+ * we know we submitted everything upto here already */
+ if (strstr(c, "abrt:") && strstr(c, "Abrt")) {
+ linecount = 0;
+ lines_info_alloc = 0;
+ free(lines_info);
+ lines_info = NULL;
+ }
goto next_line;
-
- /* skip to message in "Jan 01 01:23:45 hostname kernel: message" */
- for (i = 0; i < 3; i++) {
- c = (char*)memchr(c, ':', len);
- if (!c)
- goto next_line;
- c++;
- len = c9 - c;
}
- c++;
- len--;
- } else if (len) {
- syslog_format = no;
+ c = kernel_str + sizeof("kernel: ")-1;
}
- linepointer = c;
linelevel = 0;
/* store and remove kernel log level */
- if (len >= 3 && *c == '<' && *(c+2) == '>') {
- linelevel = *(c+1);
+ if (*c == '<' && c[1] && c[2] == '>') {
+ linelevel = c[1];
c += 3;
- len -= 3;
- linepointer = c;
}
/* remove jiffies time stamp counter if present */
if (*c == '[') {
char *c2, *c3;
- c2 = (char*)memchr(c, '.', len);
- c3 = (char*)memchr(c, ']', len);
+ c2 = strchr(c, '.');
+ c3 = strchr(c, ']');
if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) {
c = c3 + 1;
if (*c == ' ')
c++;
- len = c9 - c;
- linepointer = c;
}
}
-
- assert(c + len == c9);
- *c9 = '\0'; /* turn the \n into a string termination */
-
- /* if we see our own marker, we know we submitted everything upto here already */
- if (len >= 4 && memmem(linepointer, len, "Abrt", 4)) {
- linecount = 0;
- lines_info_alloc = 0;
- free(lines_info);
- lines_info = NULL;
- }
+ linepointer = c;
if (linecount >= lines_info_alloc) {
lines_info_alloc += REALLOC_CHUNK;
diff --git a/lib/Plugins/Logger.cpp b/lib/Plugins/Logger.cpp
index b2ac1ad..6babc73 100644
--- a/lib/Plugins/Logger.cpp
+++ b/lib/Plugins/Logger.cpp
@@ -19,9 +19,10 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "Logger.h"
#include <fstream>
#include <sstream>
+#include "abrtlib.h"
+#include "Logger.h"
#include "DebugDump.h"
#include "CommLayerInner.h"
#include "ABRTException.h"
@@ -33,23 +34,30 @@ CLogger::CLogger() :
void CLogger::SetSettings(const map_plugin_settings_t& pSettings)
{
- if (pSettings.find("LogPath") != pSettings.end())
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("LogPath");
+ if (it != end)
{
- m_sLogPath = pSettings.find("LogPath")->second;
+ m_sLogPath = it->second;
}
- if (pSettings.find("AppendLogs") != pSettings.end())
+ it = pSettings.find("AppendLogs");
+ if (it != end)
{
- m_bAppendLogs = pSettings.find("AppendLogs")->second == "yes";
+ m_bAppendLogs = string_to_bool(it->second.c_str());
}
}
-const map_plugin_settings_t& CLogger::GetSettings()
-{
- m_pSettings["LogPath"] = m_sLogPath;
- m_pSettings["AppendLogs"] = m_bAppendLogs ? "yes" : "no";
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CLogger::GetSettings()
+//{
+// m_pSettings["LogPath"] = m_sLogPath;
+// m_pSettings["AppendLogs"] = m_bAppendLogs ? "yes" : "no";
+//
+// return m_pSettings;
+//}
std::string CLogger::Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings, const std::string& pArgs)
diff --git a/lib/Plugins/Logger.h b/lib/Plugins/Logger.h
index 0969bea..285e25b 100644
--- a/lib/Plugins/Logger.h
+++ b/lib/Plugins/Logger.h
@@ -35,7 +35,8 @@ class CLogger : public CReporter
CLogger();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
virtual std::string Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings,
const std::string& pArgs);
diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp
index f083404..1979f9e 100644
--- a/lib/Plugins/Mailx.cpp
+++ b/lib/Plugins/Mailx.cpp
@@ -201,33 +201,42 @@ std::string CMailx::Report(const map_crash_report_t& pCrashReport,
void CMailx::SetSettings(const map_plugin_settings_t& pSettings)
{
- if (pSettings.find("Subject") != pSettings.end())
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("Subject");
+ if (it != end)
{
- m_sSubject = pSettings.find("Subject")->second;
+ m_sSubject = it->second;
}
- if (pSettings.find("EmailFrom") != pSettings.end())
+ it = pSettings.find("EmailFrom");
+ if (it != end)
{
- m_sEmailFrom = pSettings.find("EmailFrom")->second;
+ m_sEmailFrom = it->second;
}
- if (pSettings.find("EmailTo") != pSettings.end())
+ it = pSettings.find("EmailTo");
+ if (it != end)
{
- m_sEmailTo = pSettings.find("EmailTo")->second;
+ m_sEmailTo = it->second;
}
- if (pSettings.find("SendBinaryData") != pSettings.end())
+ it = pSettings.find("SendBinaryData");
+ if (it != end)
{
- m_bSendBinaryData = pSettings.find("SendBinaryData")->second == "yes";
+ m_bSendBinaryData = string_to_bool(it->second.c_str());
}
}
-const map_plugin_settings_t& CMailx::GetSettings()
-{
- m_pSettings["Subject"] = m_sSubject;
- m_pSettings["EmailFrom"] = m_sEmailFrom;
- m_pSettings["EmailTo"] = m_sEmailTo;
- m_pSettings["SendBinaryData"] = m_bSendBinaryData ? "yes" : "no";
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CMailx::GetSettings()
+//{
+// m_pSettings["Subject"] = m_sSubject;
+// m_pSettings["EmailFrom"] = m_sEmailFrom;
+// m_pSettings["EmailTo"] = m_sEmailTo;
+// m_pSettings["SendBinaryData"] = m_bSendBinaryData ? "yes" : "no";
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(REPORTER,
CMailx,
diff --git a/lib/Plugins/Mailx.h b/lib/Plugins/Mailx.h
index 7af1188..4aa861f 100644
--- a/lib/Plugins/Mailx.h
+++ b/lib/Plugins/Mailx.h
@@ -47,7 +47,8 @@ class CMailx : public CReporter
CMailx();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
virtual std::string Report(const map_crash_report_t& pCrashReport,
const map_plugin_settings_t& pSettings,
const std::string& pArgs);
diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp
index f816dc2..e525d89 100644
--- a/lib/Plugins/RunApp.cpp
+++ b/lib/Plugins/RunApp.cpp
@@ -25,40 +25,11 @@
#include "DebugDump.h"
#include "ABRTException.h"
#include "CommLayerInner.h"
+#include "abrtlib.h"
#define COMMAND 0
#define FILENAME 1
-/* TODO: do not duplicate: SOSreport.cpp has same function too */
-static void ParseArgs(const char *psArgs, vector_string_t& pArgs)
-{
- unsigned ii;
- bool is_quote = false;
- std::string item;
-
- for (ii = 0; psArgs[ii]; ii++)
- {
- if (psArgs[ii] == '"')
- {
- is_quote = !is_quote;
- }
- else if (psArgs[ii] == ',' && !is_quote)
- {
- pArgs.push_back(item);
- item.clear();
- }
- else
- {
- item += psArgs[ii];
- }
- }
-
- if (item.size() != 0)
- {
- pArgs.push_back(item);
- }
-}
-
void CActionRunApp::Run(const char *pActionDir, const char *pArgs)
{
update_client(_("Executing RunApp plugin..."));
@@ -66,7 +37,7 @@ void CActionRunApp::Run(const char *pActionDir, const char *pArgs)
std::string output;
vector_string_t args;
- ParseArgs(pArgs, args);
+ parse_args(pArgs, args, '"');
FILE *fp = popen(args[COMMAND].c_str(), "r");
if (fp == NULL)
diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp
index fedc51a..287c01e 100644
--- a/lib/Plugins/SOSreport.cpp
+++ b/lib/Plugins/SOSreport.cpp
@@ -18,7 +18,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <ext/stdio_filebuf.h>
#include <fstream>
#include <sstream>
#include "abrtlib.h"
@@ -56,7 +55,7 @@ static std::string ParseFilename(const std::string& pOutput)
int filename_start = pOutput.find_first_not_of(" \n\t", p);
ErrorCheck(p);
- int line_end = pOutput.find_first_of('\n',filename_start);
+ int line_end = pOutput.find_first_of('\n', filename_start);
ErrorCheck(p);
int filename_end = pOutput.find_last_not_of(" \n\t", line_end);
@@ -65,36 +64,6 @@ static std::string ParseFilename(const std::string& pOutput)
return pOutput.substr(filename_start, filename_end - filename_start + 1);
}
-/* TODO: do not duplicate: RunApp.cpp has same function too */
-static void ParseArgs(const char *psArgs, vector_string_t& pArgs)
-{
- unsigned ii;
- bool is_quote = false;
- std::string item;
-
- for (ii = 0; psArgs[ii]; ii++)
- {
- if (psArgs[ii] == '"')
- {
- is_quote = !is_quote;
- }
- else if (psArgs[ii] == ',' && !is_quote)
- {
- pArgs.push_back(item);
- item.clear();
- }
- else
- {
- item += psArgs[ii];
- }
- }
-
- if (item.size() != 0)
- {
- pArgs.push_back(item);
- }
-}
-
void CActionSOSreport::Run(const char *pActionDir, const char *pArgs)
{
update_client(_("Executing SOSreport plugin..."));
@@ -108,7 +77,7 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs)
std::string command;
vector_string_t args;
- ParseArgs(pArgs, args);
+ parse_args(pArgs, args, '"');
if (args.size() == 0 || args[0] == "")
{
@@ -120,24 +89,11 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs)
}
update_client(_("running sosreport: %s"), command.c_str());
- FILE *fp = popen(command.c_str(), "r");
- if (fp == NULL)
- {
- throw CABRTException(EXCEP_PLUGIN, ssprintf("Can't execute '%s'", command.c_str()));
- }
-
-//vda TODO: fix this mess
- std::ostringstream output_stream;
- __gnu_cxx::stdio_filebuf<char> command_output_buffer(fp, std::ios_base::in);
-
- output_stream << command << std::endl;
- output_stream << &command_output_buffer;
-
- pclose(fp);
+ std::string output = command;
+ output += '\n';
+ output += popen_and_save_output(command.c_str());
update_client(_("done running sosreport"));
- std::string output = output_stream.str();
-
std::string sosreport_filename = ParseFilename(output);
std::string sosreport_dd_filename = concat_path_file(pActionDir, "sosreport.tar.bz2");
diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp
index ab39d04..3aad054 100644
--- a/lib/Plugins/SQLite3.cpp
+++ b/lib/Plugins/SQLite3.cpp
@@ -398,18 +398,24 @@ database_row_t CSQLite3::GetUUIDData(const std::string& pUUID, const std::string
void CSQLite3::SetSettings(const map_plugin_settings_t& pSettings)
{
- if (pSettings.find("DBPath") != pSettings.end())
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("DBPath");
+ if (it != end)
{
- m_sDBPath = pSettings.find("DBPath")->second;
+ m_sDBPath = it->second;
}
}
-const map_plugin_settings_t& CSQLite3::GetSettings()
-{
- m_pSettings["DBPath"] = m_sDBPath;
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CSQLite3::GetSettings()
+//{
+// m_pSettings["DBPath"] = m_sDBPath;
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(DATABASE,
CSQLite3,
diff --git a/lib/Plugins/SQLite3.h b/lib/Plugins/SQLite3.h
index 0eb3d08..fc13bd7 100644
--- a/lib/Plugins/SQLite3.h
+++ b/lib/Plugins/SQLite3.h
@@ -58,7 +58,8 @@ class CSQLite3 : public CDatabase
virtual database_row_t GetUUIDData(const std::string& pUUID, const std::string& pUID);
virtual void SetSettings(const map_plugin_settings_t& pSettings);
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
};
#endif /* SQLITE3_H_ */
diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp
index e380de0..76bda40 100644
--- a/lib/Plugins/TicketUploader.cpp
+++ b/lib/Plugins/TicketUploader.cpp
@@ -341,9 +341,10 @@ string CTicketUploader::Report(const map_crash_report_t& pCrashReport,
void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings)
{
+ m_pSettings = pSettings;
+
map_plugin_settings_t::const_iterator end = pSettings.end();
map_plugin_settings_t::const_iterator it;
-
it = pSettings.find("Customer");
if (it != end)
{
@@ -362,12 +363,12 @@ void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings)
it = pSettings.find("Encrypt");
if (it != end)
{
- m_bEncrypt = it->second == "yes";
+ m_bEncrypt = string_to_bool(it->second.c_str());
}
it = pSettings.find("Upload");
if (it != end)
{
- m_bUpload = it->second == "yes";
+ m_bUpload = string_to_bool(it->second.c_str());
}
it = pSettings.find("RetryCount");
if (it != end)
@@ -381,18 +382,19 @@ void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings)
}
}
-const map_plugin_settings_t& CTicketUploader::GetSettings()
-{
- m_pSettings["Customer"] = m_sCustomer;
- m_pSettings["Ticket"] = m_sTicket;
- m_pSettings["URL"] = m_sURL;
- m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no";
- m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no";
- m_pSettings["RetryCount"] = to_string(m_nRetryCount);
- m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
-
- return m_pSettings;
-}
+//ok to delete?
+//const map_plugin_settings_t& CTicketUploader::GetSettings()
+//{
+// m_pSettings["Customer"] = m_sCustomer;
+// m_pSettings["Ticket"] = m_sTicket;
+// m_pSettings["URL"] = m_sURL;
+// m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no";
+// m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no";
+// m_pSettings["RetryCount"] = to_string(m_nRetryCount);
+// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
+//
+// return m_pSettings;
+//}
PLUGIN_INFO(REPORTER,
CTicketUploader,
diff --git a/lib/Plugins/TicketUploader.h b/lib/Plugins/TicketUploader.h
index 9ae3478..2a7c98a 100644
--- a/lib/Plugins/TicketUploader.h
+++ b/lib/Plugins/TicketUploader.h
@@ -45,7 +45,8 @@ class CTicketUploader : public CReporter
public:
CTicketUploader();
virtual ~CTicketUploader();
- virtual const map_plugin_settings_t& GetSettings();
+//ok to delete?
+// virtual const map_plugin_settings_t& GetSettings();
virtual void SetSettings(const map_plugin_settings_t& pSettings);
virtual std::string Report(const map_crash_report_t& pCrashReport,
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp
index bf793bb..ba11d96 100644
--- a/lib/Utils/DebugDump.cpp
+++ b/lib/Utils/DebugDump.cpp
@@ -289,6 +289,13 @@ static void DeleteFileDir(const char *pDir)
static bool IsTextFile(const char *name)
{
+ /* Some files in our dump directories are known to always be textual */
+ if (strcmp(name, "backtrace") == 0
+ || strcmp(name, "cmdline") == 0
+ ) {
+ return true;
+ }
+
/* This idiotic library thinks that file containing just "0" is not text (!!)
magic_t m = magic_open(MAGIC_MIME_TYPE);
@@ -328,15 +335,22 @@ static bool IsTextFile(const char *name)
int r = full_read(fd, buf, sizeof(buf));
close(fd);
+ /* Every once in a while, even a text file contains a few garbled
+ * or unexpected non-ASCII chars. We should not declare it "binary".
+ */
+ const unsigned RATIO = 50;
+ unsigned total_chars = r + RATIO;
+ unsigned bad_chars = 1; /* 1 prevents division by 0 later */
while (--r >= 0)
{
- if (buf[r] >= 0x7f)
- return false;
- /* Among control chars, only '\t','\n' etc are allowed */
- if (buf[r] < ' ' && !isspace(buf[r]))
- return false;
+ if (buf[r] >= 0x7f
+ /* among control chars, only '\t','\n' etc are allowed */
+ || (buf[r] < ' ' && !isspace(buf[r]))
+ ) {
+ bad_chars++;
+ }
}
- return true;
+ return (total_chars / bad_chars) >= RATIO;
}
void CDebugDump::Delete()
@@ -471,7 +485,7 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool
{
if (is_regular_file(dent, m_sDebugDumpDir.c_str()))
{
- std::string fullname = m_sDebugDumpDir + '/' + dent->d_name;
+ std::string fullname = concat_path_file(m_sDebugDumpDir.c_str(), dent->d_name);
pFileName = dent->d_name;
if (IsTextFile(fullname.c_str()))
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index 68c925f..f752992 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -5,16 +5,20 @@ lib_LTLIBRARIES = libABRTUtils.la
# xconnect.cpp
libABRTUtils_la_SOURCES = \
+ stringops.cpp \
xfuncs.cpp \
encbase64.cpp \
read_write.cpp \
logging.cpp \
copyfd.cpp \
skip_whitespace.cpp \
+ popen_and_save_output.cpp \
+ parse_release.cpp \
CrashTypesSocket.cpp \
DebugDump.h DebugDump.cpp \
CommLayerInner.h CommLayerInner.cpp \
abrt_dbus.h abrt_dbus.cpp \
+ abrt_xmlrpc.h abrt_xmlrpc.cpp \
Plugin.h Plugin.cpp make_descr.cpp \
Polkit.h Polkit.cpp \
Action.h Database.h Reporter.h Analyzer.h \
@@ -30,6 +34,7 @@ libABRTUtils_la_CPPFLAGS = \
-DVAR_RUN=\"$(VAR_RUN)\" \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS) \
+ $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \
$(POLKIT_CFLAGS) \
-D_GNU_SOURCE
libABRTUtils_la_LDFLAGS = \
@@ -37,8 +42,10 @@ libABRTUtils_la_LDFLAGS = \
$(DL_LIBS) \
$(DBUS_LIBS)
libABRTUtils_la_LIBADD = \
+ $(XMLRPC_LIBS) $(XMLRPC_CLIENT_LIBS) \
$(POLKIT_LIBS)
+
install-data-local:
$(mkdir_p) '$(DESTDIR)/$(DEBUG_DUMPS_DIR)'
chmod 1777 '$(DESTDIR)/$(DEBUG_DUMPS_DIR)'
diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp
new file mode 100644
index 0000000..11c431b
--- /dev/null
+++ b/lib/Utils/abrt_xmlrpc.cpp
@@ -0,0 +1,76 @@
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "abrtlib.h"
+#include "abrt_xmlrpc.h"
+#include "ABRTException.h"
+
+void throw_if_xml_fault_occurred(xmlrpc_env *env)
+{
+ if (env->fault_occurred)
+ {
+ std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code);
+ xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred
+ xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env
+ error_msg("%s", errmsg.c_str()); // show error in daemon log
+ throw CABRTException(EXCEP_PLUGIN, errmsg);
+ }
+}
+
+void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify)
+{
+ m_pClient = NULL;
+ m_pServer_info = NULL;
+
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ /* This should be done at program startup, once.
+ * We do it in abrtd's main */
+ /* xmlrpc_client_setup_global_const(&env); */
+
+ struct xmlrpc_curl_xportparms curlParms;
+ memset(&curlParms, 0, sizeof(curlParms));
+ /* curlParms.network_interface = NULL; - done by memset */
+ curlParms.no_ssl_verifypeer = no_ssl_verify;
+ curlParms.no_ssl_verifyhost = no_ssl_verify;
+#ifdef VERSION
+ curlParms.user_agent = PACKAGE_NAME"/"VERSION;
+#else
+ curlParms.user_agent = "abrt";
+#endif
+
+ struct xmlrpc_clientparms clientParms;
+ memset(&clientParms, 0, sizeof(clientParms));
+ clientParms.transport = "curl";
+ clientParms.transportparmsP = &curlParms;
+ clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent);
+
+ xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS,
+ PACKAGE_NAME, VERSION,
+ &clientParms, XMLRPC_CPSIZE(transportparm_size),
+ &m_pClient);
+ throw_if_xml_fault_occurred(&env);
+
+ m_pServer_info = xmlrpc_server_info_new(&env, url);
+ if (env.fault_occurred)
+ {
+ xmlrpc_client_destroy(m_pClient);
+ m_pClient = NULL;
+ }
+ throw_if_xml_fault_occurred(&env);
+}
+
+void abrt_xmlrpc_conn::destroy_xmlrpc_client()
+{
+ if (m_pServer_info)
+ {
+ xmlrpc_server_info_free(m_pServer_info);
+ m_pServer_info = NULL;
+ }
+ if (m_pClient)
+ {
+ xmlrpc_client_destroy(m_pClient);
+ m_pClient = NULL;
+ }
+}
diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h
new file mode 100644
index 0000000..e67ab19
--- /dev/null
+++ b/lib/Utils/abrt_xmlrpc.h
@@ -0,0 +1,27 @@
+#ifndef ABRT_XMLRPC_H_
+#define ABRT_XMLRPC_H_ 1
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+/*
+ * Simple class holding XMLRPC connection data.
+ * Used mainly to ensure we always destroy xmlrpc client and server_info
+ * on return or throw.
+ */
+
+struct abrt_xmlrpc_conn {
+ xmlrpc_client* m_pClient;
+ xmlrpc_server_info* m_pServer_info;
+
+ abrt_xmlrpc_conn(const char* url, bool no_ssl_verify) { new_xmlrpc_client(url, no_ssl_verify); }
+ ~abrt_xmlrpc_conn() { destroy_xmlrpc_client(); }
+
+ void new_xmlrpc_client(const char* url, bool no_ssl_verify);
+ void destroy_xmlrpc_client();
+};
+
+/* Utility function */
+void throw_if_xml_fault_occurred(xmlrpc_env *env);
+
+#endif
diff --git a/lib/Utils/parse_release.cpp b/lib/Utils/parse_release.cpp
new file mode 100644
index 0000000..33d3edb
--- /dev/null
+++ b/lib/Utils/parse_release.cpp
@@ -0,0 +1,38 @@
+#include "abrtlib.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+using namespace std;
+
+void parse_release(const char *pRelease, string& pProduct, string& pVersion)
+{
+ if (strstr(pRelease, "Rawhide"))
+ {
+ pProduct = "Fedora";
+ pVersion = "rawhide";
+ return;
+ }
+ if (strstr(pRelease, "Fedora"))
+ {
+ pProduct = "Fedora";
+ }
+ else if (strstr(pRelease, "Red Hat Enterprise Linux"))
+ {
+ pProduct = "Red Hat Enterprise Linux ";
+ }
+
+ const char *release = strstr(pRelease, "release");
+ const char *space = release ? strchr(release, ' ') : NULL;
+
+ if (space++) while (*space != '\0' && *space != ' ')
+ {
+ /* Eat string like "5.2" */
+ pVersion += *space;
+ if (pProduct == "Red Hat Enterprise Linux ")
+ {
+ pProduct += *space;
+ }
+ space++;
+ }
+}
diff --git a/lib/Utils/popen_and_save_output.cpp b/lib/Utils/popen_and_save_output.cpp
new file mode 100644
index 0000000..4bcbcac
--- /dev/null
+++ b/lib/Utils/popen_and_save_output.cpp
@@ -0,0 +1,30 @@
+/*
+ * Utility routines.
+ *
+ * Licensed under GPLv2 or later, see file COPYING in this tarball for details.
+ */
+#include "abrtlib.h"
+
+using namespace std;
+
+string popen_and_save_output(const char *cmd)
+{
+ string result;
+
+ FILE *fp = popen(cmd, "r");
+ if (fp == NULL) /* fork or pipe failed; or out-of-mem */
+ {
+ return result;
+ }
+
+ size_t sz;
+ char buf[BUFSIZ + 1];
+ while ((sz = fread(buf, 1, sizeof(buf)-1, fp)) > 0)
+ {
+ buf[sz] = '\0';
+ result += buf;
+ }
+ pclose(fp);
+
+ return result;
+}
diff --git a/lib/Utils/stringops.cpp b/lib/Utils/stringops.cpp
new file mode 100644
index 0000000..1b3793f
--- /dev/null
+++ b/lib/Utils/stringops.cpp
@@ -0,0 +1,30 @@
+#include "abrtlib.h"
+
+void parse_args(const char *psArgs, vector_string_t& pArgs, int quote)
+{
+ unsigned ii;
+ bool is_quote = false;
+ std::string item;
+
+ for (ii = 0; psArgs[ii]; ii++)
+ {
+ if (quote != -1 && psArgs[ii] == quote)
+ {
+ is_quote = !is_quote;
+ }
+ else if (psArgs[ii] == ',' && !is_quote)
+ {
+ pArgs.push_back(item);
+ item.clear();
+ }
+ else
+ {
+ item += psArgs[ii];
+ }
+ }
+
+ if (item.size() != 0)
+ {
+ pArgs.push_back(item);
+ }
+}