summaryrefslogtreecommitdiffstats
path: root/lib/Plugins/Bugzilla.cpp
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-11-09 13:55:20 +0100
committerKarel Klic <kklic@redhat.com>2009-11-09 13:55:20 +0100
commit19f406b4930c931a932dc6930762e8e12e29ce8b (patch)
treeb08468bf9a010cbce0ecd000a0279222f0d4b4e7 /lib/Plugins/Bugzilla.cpp
parent801ab58f32f2cb7dca3352b721a07c83705a0287 (diff)
parent8fa9a6ecd247454ab758efecf818d8067455c778 (diff)
downloadabrt-19f406b4930c931a932dc6930762e8e12e29ce8b.tar.gz
abrt-19f406b4930c931a932dc6930762e8e12e29ce8b.tar.xz
abrt-19f406b4930c931a932dc6930762e8e12e29ce8b.zip
merge
Diffstat (limited to 'lib/Plugins/Bugzilla.cpp')
-rw-r--r--lib/Plugins/Bugzilla.cpp839
1 files changed, 487 insertions, 352 deletions
diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp
index 48c5eb5..ecd4dd6 100644
--- a/lib/Plugins/Bugzilla.cpp
+++ b/lib/Plugins/Bugzilla.cpp
@@ -1,456 +1,590 @@
-
-#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
#include "abrtlib.h"
#include "Bugzilla.h"
#include "CrashTypes.h"
#include "DebugDump.h"
#include "ABRTException.h"
#include "CommLayerInner.h"
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
#define XML_RPC_SUFFIX "/xmlrpc.cgi"
-CReporterBugzilla::CReporterBugzilla() :
- m_pXmlrpcTransport(NULL),
- m_pXmlrpcClient(NULL),
- m_pCarriageParm(NULL),
- m_sBugzillaURL("https://bugzilla.redhat.com"),
- m_sBugzillaXMLRPC("https://bugzilla.redhat.com" + std::string(XML_RPC_SUFFIX)),
- m_bNoSSLVerify(false),
- m_bLoggedIn(false)
-{}
-CReporterBugzilla::~CReporterBugzilla()
-{}
-
-void CReporterBugzilla::NewXMLRPCClient()
-{
- m_pXmlrpcTransport = new xmlrpc_c::clientXmlTransport_curl(
- xmlrpc_c::clientXmlTransport_curl::constrOpt()
- .no_ssl_verifyhost(m_bNoSSLVerify)
- .no_ssl_verifypeer(m_bNoSSLVerify)
- );
- m_pXmlrpcClient = new xmlrpc_c::client_xml(m_pXmlrpcTransport);
- m_pCarriageParm = new xmlrpc_c::carriageParm_curl0(m_sBugzillaXMLRPC);
-}
-
-void CReporterBugzilla::DeleteXMLRPCClient()
+static void get_product_and_version(const std::string& pRelease,
+ std::string& pProduct,
+ std::string& pVersion)
{
- if (m_pCarriageParm != NULL)
+ if (pRelease.find("Rawhide") != std::string::npos)
{
- delete m_pCarriageParm;
- m_pCarriageParm = NULL;
+ pProduct = "Fedora";
+ pVersion = "rawhide";
+ return;
}
- if (m_pXmlrpcClient != NULL)
+ if (pRelease.find("Fedora") != std::string::npos)
{
- delete m_pXmlrpcClient;
- m_pXmlrpcClient = NULL;
+ pProduct = "Fedora";
}
- if (m_pXmlrpcTransport != NULL)
+ else if (pRelease.find("Red Hat Enterprise Linux") != std::string::npos)
{
- delete m_pXmlrpcTransport;
- m_pXmlrpcTransport = NULL;
+ pProduct = "Red Hat Enterprise Linux ";
}
-}
-
-PRInt32 CReporterBugzilla::Base64Encode_cb(void *arg, const char *obuf, PRInt32 size)
-{
- CReporterBugzilla* bz = static_cast<CReporterBugzilla*>(arg);
- int ii;
- for (ii = 0; ii < size; ii++)
+ std::string::size_type pos = pRelease.find("release");
+ pos = pRelease.find(" ", pos) + 1;
+ while (pRelease[pos] != ' ')
{
- if (isprint(obuf[ii]))
+ pVersion += pRelease[pos];
+ if (pProduct == "Red Hat Enterprise Linux ")
{
- bz->m_sAttchmentInBase64 += obuf[ii];
+ pProduct += pRelease[pos];
}
+ pos++;
}
- return 1;
}
-void CReporterBugzilla::Login()
+static void create_new_bug_description(const map_crash_report_t& pCrashReport, std::string& pDescription)
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t loginParams;
- map_xmlrpc_params_t ret;
- loginParams["login"] = xmlrpc_c::value_string(m_sLogin);
- loginParams["password"] = xmlrpc_c::value_string(m_sPassword);
- paramList.add(xmlrpc_c::value_struct(loginParams));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("User.login", paramList));
- try
- {
- if( (m_sLogin == "") && (m_sPassword=="") )
- {
- log("Empty login and password");
- throw std::string(_("Empty login and password. Please check Bugzilla.conf"));
- }
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- ret = xmlrpc_c::value_struct(rpc->getResult());
- std::stringstream ss;
- ss << xmlrpc_c::value_int(ret["id"]);
- log("Login id: %s", ss.str().c_str());
- }
- catch (std::exception& e)
- {
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Login(): ") + e.what());
- }
- catch (std::string& s)
- {
- throw CABRTException(EXCEP_PLUGIN, s);
- }
+ pDescription = "abrt detected a crash.\n\n";
+ pDescription += make_description_bz(pCrashReport);
}
-void CReporterBugzilla::Logout()
+// 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)
{
- xmlrpc_c::paramList paramList;
- paramList.add(xmlrpc_c::value_string(""));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("User.logout", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- }
- catch (std::exception& e)
+ if (env->fault_occurred)
{
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Logout(): ") + e.what());
+ 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);
}
}
-bool CReporterBugzilla::CheckCCAndReporter(const std::string& pBugId)
+
+/*
+ * Static namespace for xmlrpc stuff.
+ * Used mainly to ensure we always destroy xmlrpc client and server_info.
+ */
+
+namespace {
+
+struct ctx {
+ xmlrpc_client* client;
+ xmlrpc_server_info* server_info;
+
+ 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 ctx::new_xmlrpc_client(const char* url, bool no_ssl_verify)
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t ret;
+ 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);
+}
- paramList.add(xmlrpc_c::value_string(pBugId));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("bugzilla.getBug", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- ret = xmlrpc_c::value_struct(rpc->getResult());
- }
- catch (std::exception& e)
+void ctx::destroy_xmlrpc_client()
+{
+ if (server_info)
{
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::CheckCCAndReporter(): ") + e.what());
+ xmlrpc_server_info_free(server_info);
+ server_info = NULL;
}
- std::string reporter = xmlrpc_c::value_string(ret["reporter"]);
- if (reporter == m_sLogin)
+ if (client)
{
- return true;
+ xmlrpc_client_destroy(client);
+ client = NULL;
}
- std::vector<xmlrpc_c::value> ccs = xmlrpc_c::value_array(ret["cc"]).vectorValueValue();
- int ii;
- for (ii = 0; ii < ccs.size(); ii++)
- {
- std::string cc = xmlrpc_c::value_string(ccs[ii]);
- if (cc == m_sLogin)
- {
- return true;
- }
- }
- return false;
}
-void CReporterBugzilla::AddPlusOneCC(const std::string& pBugId)
+void ctx::login(const char* login, const char* passwd)
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t addCCParams;
- map_xmlrpc_params_t ret;
- map_xmlrpc_params_t updates;
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
- std::vector<xmlrpc_c::value> CCList;
- CCList.push_back(xmlrpc_c::value_string(m_sLogin));
- updates["add_cc"] = xmlrpc_c::value_array(CCList);
+ xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s})", "login", login, "password", passwd);
+ throw_if_xml_fault_occurred(&env);
- addCCParams["ids"] = xmlrpc_c::value_int(atoi(pBugId.c_str()));
- addCCParams["updates"] = xmlrpc_c::value_struct(updates);
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, client, server_info, "User.login", param, &result);
+ xmlrpc_DECREF(param);
+ if (result)
+ xmlrpc_DECREF(result);
- paramList.add(xmlrpc_c::value_struct(addCCParams));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.update", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- }
- catch (std::exception& e)
+ if (env.fault_occurred)
{
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::AddPlusOneComment(): ") + e.what());
+ std::string errmsg = ssprintf("Can't login. Check Edit->Plugins->Bugzilla and /etc/abrt/plugins/Bugzilla.conf. Server said: %s", env.fault_string);
+ xmlrpc_env_clean(&env);
+ error_msg("%s", errmsg.c_str()); // show error in daemon log
+ throw CABRTException(EXCEP_PLUGIN, errmsg);
}
- ret = xmlrpc_c::value_struct(rpc->getResult());
}
-std::string CReporterBugzilla::CheckUUIDInBugzilla(const std::string& pComponent, const std::string& pUUID)
+void ctx::logout()
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t searchParams;
- map_xmlrpc_params_t ret;
- std::string quicksearch = "ALL component:\""+ pComponent +"\" statuswhiteboard:\""+ pUUID + "\"";
- searchParams["quicksearch"] = xmlrpc_c::value_string(quicksearch.c_str());
- paramList.add(xmlrpc_c::value_struct(searchParams));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.search", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- }
- catch (std::exception& e)
- {
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::CheckUUIDInBugzilla(): ") + e.what());
- }
- ret = xmlrpc_c::value_struct(rpc->getResult());
- std::vector<xmlrpc_c::value> bugs = xmlrpc_c::value_array(ret["bugs"]).vectorValueValue();
- if (bugs.size() > 0)
- {
- map_xmlrpc_params_t bug;
- std::stringstream ss;
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", "");
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, client, server_info, "User.logout", param, &result);
+ xmlrpc_DECREF(param);
+ if (result)
+ xmlrpc_DECREF(result);
+ throw_if_xml_fault_occurred(&env);
+}
- bug = xmlrpc_c::value_struct(bugs[0]);
- ss << xmlrpc_c::value_int(bug["bug_id"]);
+bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login)
+{
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
- log("Bug is already reported: %s", ss.str().c_str());
- update_client(_("Bug is already reported: ") + ss.str());
+ xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", to_string(bug_id).c_str());
+ throw_if_xml_fault_occurred(&env);
- return ss.str();
- }
- return "";
-}
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, client, server_info, "bugzilla.getBug", param, &result);
+ throw_if_xml_fault_occurred(&env);
+ xmlrpc_DECREF(param);
-void CReporterBugzilla::CreateNewBugDescription(const map_crash_report_t& pCrashReport, std::string& pDescription)
-{
- std::string howToReproduce;
- std::string comment;
+ xmlrpc_value* reporter_member = NULL;
+ xmlrpc_struct_find_value(&env, result, "reporter", &reporter_member);
+ throw_if_xml_fault_occurred(&env);
- if (pCrashReport.find(CD_REPRODUCE) != pCrashReport.end())
+ if (reporter_member)
{
- howToReproduce = "\n\nHow to reproduce\n"
- "-----\n" +
- pCrashReport.find(CD_REPRODUCE)->second[CD_CONTENT];
- }
- if (pCrashReport.find(CD_COMMENT) != pCrashReport.end())
- {
- comment = "\n\nComment\n"
- "-----\n" +
- pCrashReport.find(CD_COMMENT)->second[CD_CONTENT];
+ const char* reporter = NULL;
+ xmlrpc_read_string(&env, reporter_member, &reporter);
+ throw_if_xml_fault_occurred(&env);
+
+ bool eq = (strcmp(reporter, login) == 0);
+ free((void*)reporter);
+ xmlrpc_DECREF(reporter_member);
+ if (eq)
+ {
+ xmlrpc_DECREF(result);
+ return true;
+ }
}
- pDescription = "\nabrt detected a crash.\n" +
- howToReproduce +
- comment +
- "\n\nAdditional information\n"
- "======\n";
-
- map_crash_report_t::const_iterator it;
- for (it = pCrashReport.begin(); it != pCrashReport.end(); it++)
+
+ xmlrpc_value* cc_member = NULL;
+ xmlrpc_struct_find_value(&env, result, "cc", &cc_member);
+ throw_if_xml_fault_occurred(&env);
+
+ if (cc_member)
{
- if (it->second[CD_TYPE] == CD_TXT)
+ uint32_t array_size = xmlrpc_array_size(&env, cc_member);
+
+ for (uint32_t i = 0; i < array_size; i++)
{
- if (it->first != CD_UUID &&
- it->first != FILENAME_ARCHITECTURE &&
- it->first != FILENAME_RELEASE &&
- it->first != CD_REPRODUCE &&
- it->first != CD_COMMENT)
+ xmlrpc_value* item = NULL;
+ xmlrpc_array_read_item(&env, cc_member, i, &item); // Correct
+ throw_if_xml_fault_occurred(&env);
+
+ const char* cc = NULL;
+ xmlrpc_read_string(&env, item, &cc);
+ throw_if_xml_fault_occurred(&env);
+
+ bool eq = (strcmp(cc, login) == 0);
+ free((void*)cc);
+ xmlrpc_DECREF(item);
+ if (eq)
{
- pDescription += "\n" + it->first + "\n";
- pDescription += "-----\n";
- pDescription += it->second[CD_CONTENT] + "\n\n";
+ xmlrpc_DECREF(cc_member);
+ xmlrpc_DECREF(result);
+ return true;
}
}
- else if (it->second[CD_TYPE] == CD_ATT)
- {
- pDescription += "\n\nAttached files\n"
- "----\n";
- pDescription += it->first + "\n";
- }
- else if (it->second[CD_TYPE] == CD_BIN)
- {
- char buffer[1024];
- snprintf(buffer, 1024, _("Binary file %s will not be reported."), it->first.c_str());
- warn_client(std::string(buffer));
- //update_client(_("Binary file ")+it->first+_(" will not be reported."));
- }
+ xmlrpc_DECREF(cc_member);
}
+
+ xmlrpc_DECREF(result);
+ return false;
}
-void CReporterBugzilla::GetProductAndVersion(const std::string& pRelease,
- std::string& pProduct,
- std::string& pVersion)
+void ctx::add_plus_one_cc(uint32_t bug_id, const char* login)
{
- 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] != ' ')
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_value* param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, client, server_info, "Bug.update", param, &result);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(param);
+}
+
+int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID)
+{
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ std::string query = ssprintf("ALL component:\"%s\" statuswhiteboard:\"%s\"", component, UUID);
+
+ xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s})", "quicksearch", query.c_str());
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result = NULL;
+ xmlrpc_client_call2(&env, client, server_info, "Bug.search", param, &result);
+ throw_if_xml_fault_occurred(&env);
+ xmlrpc_DECREF(param);
+
+ xmlrpc_value* bugs_member = NULL;
+ xmlrpc_struct_find_value(&env, result, "bugs", &bugs_member);
+ throw_if_xml_fault_occurred(&env);
+
+ if (bugs_member)
{
- pVersion += pRelease[pos];
- if (pProduct == "Red Hat Enterprise Linux ")
+ // when array size is equal 0 that means no bug reported
+ uint32_t array_size = xmlrpc_array_size(&env, bugs_member);
+ throw_if_xml_fault_occurred(&env);
+ if (array_size == 0)
{
- pProduct += pRelease[pos];
+ xmlrpc_DECREF(bugs_member);
+ xmlrpc_DECREF(result);
+ return -1;
}
- pos++;
+
+ xmlrpc_value* item = NULL;
+ xmlrpc_array_read_item(&env, bugs_member, 0, &item); // Correct
+ throw_if_xml_fault_occurred(&env);
+ xmlrpc_value* bug = NULL;
+ xmlrpc_struct_find_value(&env, item, "bug_id", &bug);
+ throw_if_xml_fault_occurred(&env);
+
+ if (bug)
+ {
+ xmlrpc_int bug_id;
+ xmlrpc_read_int(&env, bug, &bug_id);
+ log("Bug is already reported: %i", (int)bug_id);
+ update_client(_("Bug is already reported: %i"), (int)bug_id);
+
+ xmlrpc_DECREF(bug);
+ xmlrpc_DECREF(item);
+ xmlrpc_DECREF(bugs_member);
+ xmlrpc_DECREF(result);
+ return bug_id;
+ }
+ xmlrpc_DECREF(item);
+ xmlrpc_DECREF(bugs_member);
}
+
+ xmlrpc_DECREF(result);
+ return -1;
}
-std::string CReporterBugzilla::NewBug(const map_crash_report_t& pCrashReport)
+uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport)
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t bugParams;
- map_xmlrpc_params_t ret;
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
std::string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT];
std::string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT];
+ std::string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT];
+ std::string arch = pCrashReport.find(FILENAME_ARCHITECTURE)->second[CD_CONTENT];
+ std::string uuid = pCrashReport.find(CD_UUID)->second[CD_CONTENT];
+
+ std::string summary = "[abrt] crash detected in " + package;
+ std::string status_whiteboard = "abrt_hash:" + uuid;
+
std::string description;
- std::string release = pCrashReport.find(FILENAME_RELEASE)->second[CD_CONTENT];;
+ create_new_bug_description(pCrashReport, description);
+
std::string product;
std::string version;
- std::stringstream bugId;
- CreateNewBugDescription(pCrashReport, description);
- GetProductAndVersion(release, product, version);
-
- bugParams["product"] = xmlrpc_c::value_string(product);
- bugParams["component"] = xmlrpc_c::value_string(component);
- bugParams["version"] = xmlrpc_c::value_string(version);
- //bugParams["op_sys"] = xmlrpc_c::value_string("Linux");
- bugParams["summary"] = xmlrpc_c::value_string("[abrt] crash detected in " + package);
- bugParams["description"] = xmlrpc_c::value_string(description);
- bugParams["status_whiteboard"] = xmlrpc_c::value_string("abrt_hash:" + pCrashReport.find(CD_UUID)->second[CD_CONTENT]);
- bugParams["platform"] = xmlrpc_c::value_string(pCrashReport.find(FILENAME_ARCHITECTURE)->second[CD_CONTENT]);
- paramList.add(xmlrpc_c::value_struct(bugParams));
-
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("Bug.create", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- ret = xmlrpc_c::value_struct(rpc->getResult());
- bugId << xmlrpc_c::value_int(ret["id"]);
- log("New bug id: %s", bugId.str().c_str());
- update_client(_("New bug id: ") + bugId.str());
- }
- catch (std::exception& e)
- {
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::NewBug(): ") + e.what());
- }
- return bugId.str();
+ get_product_and_version(release, 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(),
+ "component", component.c_str(),
+ "version", version.c_str(),
+ "summary", summary.c_str(),
+ "description", description.c_str(),
+ "status_whiteboard", status_whiteboard.c_str(),
+ "platform", arch.c_str()
+ );
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* result;
+ xmlrpc_client_call2(&env, client, server_info, "Bug.create", param, &result);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_value* id;
+ xmlrpc_struct_find_value(&env, result, "id", &id);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_int bug_id = -1;
+ if (id)
+ {
+ xmlrpc_read_int(&env, id, &bug_id);
+ throw_if_xml_fault_occurred(&env);
+ log("New bug id: %i", bug_id);
+ update_client(_("New bug id: %i"), bug_id);
+ }
+
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(param);
+ xmlrpc_DECREF(id);
+ return bug_id;
}
-void CReporterBugzilla::AddAttachments(const std::string& pBugId, const map_crash_report_t& pCrashReport)
+void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCrashReport)
{
- xmlrpc_c::paramList paramList;
- map_xmlrpc_params_t attachmentParams;
- std::vector<xmlrpc_c::value> ret;
- NSSBase64Encoder* base64;
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
- map_crash_report_t::const_iterator it;
- for (it = pCrashReport.begin(); it != pCrashReport.end(); it++)
+ 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)
{
- m_sAttchmentInBase64 = "";
- base64 = NSSBase64Encoder_Create(Base64Encode_cb, this);
- if (!base64)
- {
- throw CABRTException(EXCEP_PLUGIN, "CReporterBugzilla::AddAttachemnt(): cannot initialize base64.");
- }
-
- NSSBase64Encoder_Update(base64,
- reinterpret_cast<const unsigned char*>(it->second[CD_CONTENT].c_str()),
- it->second[CD_CONTENT].length());
- NSSBase64Encoder_Destroy(base64, PR_FALSE);
-
- paramList.add(xmlrpc_c::value_string(pBugId));
- attachmentParams["description"] = xmlrpc_c::value_string("File: " + it->first);
- attachmentParams["filename"] = xmlrpc_c::value_string(it->first);
- attachmentParams["contenttype"] = xmlrpc_c::value_string("text/plain");
- attachmentParams["data"] = xmlrpc_c::value_string(m_sAttchmentInBase64);
- paramList.add(xmlrpc_c::value_struct(attachmentParams));
- xmlrpc_c::rpcPtr rpc(new xmlrpc_c::rpc("bugzilla.addAttachment", paramList));
- try
- {
- rpc->call(m_pXmlrpcClient, m_pCarriageParm);
- ret = xmlrpc_c::value_array(rpc->getResult()).vectorValueValue();
- std::stringstream ss;
- ss << xmlrpc_c::value_int(ret[0]);
- log("New attachment id: %s", ss.str().c_str());
- }
- catch (std::exception& e)
- {
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::AddAttachemnt(): ") + e.what());
- }
+ std::string description = "File: " + it->first;
+ const std::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})",
+ bug_id_str,
+ "description", description.c_str(),
+ "filename", it->first.c_str(),
+ "contenttype", "text/plain",
+ "data", encoded64
+ );
+ free(encoded64);
+ throw_if_xml_fault_occurred(&env);
+
+ xmlrpc_client_call2(&env, client, server_info, "bugzilla.addAttachment", param, &result);
+ throw_if_xml_fault_occurred(&env);
+ xmlrpc_DECREF(result);
+ xmlrpc_DECREF(param);
}
}
}
-std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport, const std::string& pArgs)
-{
- std::string package = pCrashReport.find(FILENAME_PACKAGE)->second[CD_CONTENT];
- std::string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT];
- std::string uuid = pCrashReport.find(CD_UUID)->second[CD_CONTENT];
- std::string bugId;
+} /* namespace */
- NewXMLRPCClient();
+/*
+ * CReporterBugzilla
+ */
- m_bLoggedIn = false;
+CReporterBugzilla::CReporterBugzilla() :
+ m_bNoSSLVerify(false),
+ m_sBugzillaURL("https://bugzilla.redhat.com"),
+ m_sBugzillaXMLRPC("https://bugzilla.redhat.com"XML_RPC_SUFFIX)
+{}
+
+CReporterBugzilla::~CReporterBugzilla()
+{}
+
+std::string CReporterBugzilla::Report(const map_crash_report_t& pCrashReport,
+ const map_plugin_settings_t& pSettings,
+ const std::string& pArgs)
+{
+ int32_t bug_id = -1;
+ std::string Login;
+ std::string Password;
+ std::string BugzillaXMLRPC;
+ 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())
+ {
+ Login = settings["Login"];
+ Password = settings["Password"];
+ BugzillaXMLRPC = settings["BugzillaXMLRPC"];
+ BugzillaURL = settings["BugzillaURL"];
+ NoSSLVerify = settings["NoSSLVerify"] == "yes";
+ }
+ else
+ {
+ Login = m_sLogin;
+ Password = m_sPassword;
+ BugzillaXMLRPC = m_sBugzillaXMLRPC;
+ BugzillaURL = m_sBugzillaURL;
+ NoSSLVerify = m_bNoSSLVerify;
+ }
+
+ std::string component = pCrashReport.find(FILENAME_COMPONENT)->second[CD_CONTENT];
+ std::string uuid = pCrashReport.find(CD_UUID)->second[CD_CONTENT];
try
{
+ ctx bz_server(BugzillaXMLRPC.c_str(), NoSSLVerify);
+
update_client(_("Checking for duplicates..."));
- bugId = CheckUUIDInBugzilla(component, uuid);
- if ( bugId != "" ) {
- update_client(_("Logging into bugzilla..."));
- Login();
- m_bLoggedIn = true;
+ bug_id = bz_server.check_uuid_in_bugzilla(component.c_str(), uuid.c_str());
+
+ update_client(_("Logging into bugzilla..."));
+ if ((Login == "") && (Password == ""))
+ {
+ VERB3 log("Empty login and password");
+ throw CABRTException(EXCEP_PLUGIN, std::string(_("Empty login and password. Please check Bugzilla.conf")));
+ }
+ bz_server.login(Login.c_str(), Password.c_str());
+
+ if (bug_id > 0)
+ {
update_client(_("Checking CC..."));
- if (!CheckCCAndReporter(bugId) && m_bLoggedIn)
+ if (!bz_server.check_cc_and_reporter(bug_id, Login.c_str()))
{
- AddPlusOneCC(bugId);
+ bz_server.add_plus_one_cc(bug_id, Login.c_str());
}
- DeleteXMLRPCClient();
- return m_sBugzillaURL + "/show_bug.cgi?id=" + bugId;
+ bz_server.logout();
+ return BugzillaURL + "/show_bug.cgi?id=" + to_string(bug_id);
}
- update_client(_("Logging into bugzilla..."));
- Login();
- m_bLoggedIn = true;
+
+ update_client(_("Creating new bug..."));
+ bug_id = bz_server.new_bug(pCrashReport);
+ bz_server.add_attachments(to_string(bug_id).c_str(), pCrashReport);
+
+ update_client(_("Logging out..."));
+ bz_server.logout();
}
catch (CABRTException& e)
{
- DeleteXMLRPCClient();
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Report(): ") + e.what());
- return "";
+ throw CABRTException(EXCEP_PLUGIN, e.what());
}
+ if (bug_id > 0)
+ {
+ return BugzillaURL + "/show_bug.cgi?id=" + to_string(bug_id);
+ }
- update_client(_("Creating new bug..."));
- try
+ return BugzillaURL + "/show_bug.cgi?id=";
+}
+
+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();
+
+ it = pSettings.find("BugzillaURL");
+ if (it != end)
{
- bugId = NewBug(pCrashReport);
- AddAttachments(bugId, pCrashReport);
- update_client(_("Logging out..."));
- Logout();
+ std::string BugzillaURL = it->second;
+ //remove the /xmlrpc.cgi part from old settings
+ //FIXME: can be removed after users are informed about new config format
+ std::string::size_type pos = BugzillaURL.find(XML_RPC_SUFFIX);
+ if (pos != std::string::npos)
+ {
+ BugzillaURL.erase(pos);
+ }
+ //remove the trailing '/'
+ while (BugzillaURL[BugzillaURL.length() - 1] == '/')
+ {
+ BugzillaURL.erase(BugzillaURL.length() - 1);
+ }
+ plugin_settings["BugzillaXMLRPC"] = BugzillaURL + XML_RPC_SUFFIX;
+ plugin_settings["BugzillaURL"] = BugzillaURL;
}
- catch (CABRTException& e)
+
+ it = pSettings.find("Login");
+ if (it == end)
{
- DeleteXMLRPCClient();
- throw CABRTException(EXCEP_PLUGIN, std::string("CReporterBugzilla::Report(): ") + e.what());
+ /* if any of the option is not set we use the defaults for everything */
+ plugin_settings.clear();
+ return plugin_settings;
}
+ plugin_settings["Login"] = it->second;
+ it = pSettings.find("Password");
+ if (it == end)
+ {
+ plugin_settings.clear();
+ return plugin_settings;
+ }
+ plugin_settings["Password"] = it->second;
- DeleteXMLRPCClient();
- return m_sBugzillaURL + "/show_bug.cgi?id=" + bugId;
+ it = pSettings.find("NoSSLVerify");
+ if (it == end)
+ {
+ plugin_settings.clear();
+ return plugin_settings;
+ }
+ plugin_settings["NoSSLVerify"] = it->second;
+ VERB1 log("User settings ok, using them instead of defaults");
+ return plugin_settings;
}
void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings)
{
- if (pSettings.find("BugzillaURL") != pSettings.end())
+//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
+//for me to know that it is being used. Moreover, when I discovered it
+//(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();
+
+ it = pSettings.find("BugzillaURL");
+ if (it != end)
{
- m_sBugzillaURL = pSettings.find("BugzillaURL")->second;
+ m_sBugzillaURL = it->second;
//remove the /xmlrpc.cgi part from old settings
//FIXME: can be removed after users are informed about new config format
std::string::size_type pos = m_sBugzillaURL.find(XML_RPC_SUFFIX);
- if(pos != std::string::npos)
+ if (pos != std::string::npos)
{
m_sBugzillaURL.erase(pos);
}
@@ -465,40 +599,41 @@ void CReporterBugzilla::SetSettings(const map_plugin_settings_t& pSettings)
m_sBugzillaURL.erase(--m_sBugzillaURL.end());
}
*/
- m_sBugzillaXMLRPC = m_sBugzillaURL + std::string(XML_RPC_SUFFIX);
+ m_sBugzillaXMLRPC = m_sBugzillaURL + XML_RPC_SUFFIX;
}
- if (pSettings.find("Login") != pSettings.end())
+ it = pSettings.find("Login");
+ if (it != end)
{
- m_sLogin = pSettings.find("Login")->second;
+ m_sLogin = it->second;
}
- if (pSettings.find("Password") != pSettings.end())
+ it = pSettings.find("Password");
+ if (it != end)
{
- m_sPassword = pSettings.find("Password")->second;
+ m_sPassword = it->second;
}
- if (pSettings.find("NoSSLVerify") != pSettings.end())
+ it = pSettings.find("NoSSLVerify");
+ if (it != end)
{
- m_bNoSSLVerify = pSettings.find("NoSSLVerify")->second == "yes";
+ m_bNoSSLVerify = (it->second == "yes");
}
}
-map_plugin_settings_t CReporterBugzilla::GetSettings()
+const map_plugin_settings_t& CReporterBugzilla::GetSettings()
{
- map_plugin_settings_t ret;
-
- ret["BugzillaURL"] = m_sBugzillaURL;
- ret["Login"] = m_sLogin;
- ret["Password"] = m_sPassword;
- ret["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no";
+ m_pSettings["BugzillaURL"] = m_sBugzillaURL;
+ m_pSettings["Login"] = m_sLogin;
+ m_pSettings["Password"] = m_sPassword;
+ m_pSettings["NoSSLVerify"] = m_bNoSSLVerify ? "yes" : "no";
- return ret;
+ return m_pSettings;
}
PLUGIN_INFO(REPORTER,
CReporterBugzilla,
"Bugzilla",
- "0.0.3",
+ "0.0.4",
"Check if a bug isn't already reported in a bugzilla "
"and if not, report it.",
- "zprikryl@redhat.com",
+ "npajkovs@redhat.com",
"https://fedorahosted.org/abrt/wiki",
PLUGINS_LIB_DIR"/Bugzilla.GTKBuilder");