summaryrefslogtreecommitdiffstats
path: root/src/plugins/ReportUploader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ReportUploader.cpp')
-rw-r--r--src/plugins/ReportUploader.cpp517
1 files changed, 0 insertions, 517 deletions
diff --git a/src/plugins/ReportUploader.cpp b/src/plugins/ReportUploader.cpp
deleted file mode 100644
index 4100e996..00000000
--- a/src/plugins/ReportUploader.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- ReportUploader.cpp
-
- Copyright (C) 2009 RedHat inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include "abrtlib.h"
-#include "abrt_curl.h"
-#include "ReportUploader.h"
-#include "abrt_exception.h"
-#include "comm_layer_inner.h"
-
-using namespace std;
-
-
-CReportUploader::CReportUploader() :
- m_bEncrypt(false),
- m_bUpload(false),
- m_nRetryCount(3),
- m_nRetryDelay(20)
-{}
-
-CReportUploader::~CReportUploader()
-{}
-
-
-static void RunCommand(const char *cmd)
-{
- int retcode = system(cmd);
- if (retcode)
- {
- throw CABRTException(EXCEP_PLUGIN, "'%s' exited with %d", cmd, retcode);
- }
-}
-
-static string ReadCommand(const char *cmd)
-{
- FILE* fp = popen(cmd, "r");
- if (!fp)
- {
- throw CABRTException(EXCEP_PLUGIN, "Error running '%s'", cmd);
- }
-
- string result;
- char *buff;
- while ((buff = xmalloc_fgetline(fp)) != NULL)
- {
- result += buff;
- free(buff);
- }
-
- int retcode = pclose(fp);
- if (retcode)
- {
- throw CABRTException(EXCEP_PLUGIN, "'%s' exited with %d", cmd, retcode);
- }
-
- return result;
-}
-
-static void WriteCommand(const char *cmd, const char *input)
-{
- FILE* fp = popen(cmd, "w");
- if (!fp)
- {
- throw CABRTException(EXCEP_PLUGIN, "error running '%s'", cmd);
- }
-
- /* Hoping it's not too big to get us forever blocked... */
- fputs(input, fp);
-
- int retcode = pclose(fp);
- if (retcode)
- {
- throw CABRTException(EXCEP_PLUGIN, "'%s' exited with %d", cmd, retcode);
- }
-}
-
-void CReportUploader::SendFile(const char *pURL, const char *pFilename, int retry_count, int retry_delay)
-{
- if (pURL[0] == '\0')
- {
- error_msg(_("FileTransfer: URL not specified"));
- return;
- }
-
- update_client(_("Sending archive %s to %s"), pFilename, pURL);
-
- const char *base = (strrchr(pFilename, '/') ? : pFilename-1) + 1;
- char *whole_url = concat_path_file(pURL, base);
- int count = retry_count;
- int result;
- while (1)
- {
- FILE* f = fopen(pFilename, "r");
- if (!f)
- {
- free(whole_url);
- throw CABRTException(EXCEP_PLUGIN, "Can't open archive file '%s'", pFilename);
- }
- struct stat buf;
- fstat(fileno(f), &buf); /* never fails */
- CURL* curl = xcurl_easy_init();
- /* enable uploading */
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
- /* specify target */
- curl_easy_setopt(curl, CURLOPT_URL, whole_url);
- curl_easy_setopt(curl, CURLOPT_READDATA, f);
- curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)buf.st_size);
- /* everything is done here; result 0 means success */
- result = curl_easy_perform(curl);
- /* goodbye */
- curl_easy_cleanup(curl);
- fclose(f);
- if (result != 0)
- {
- update_client(_("Sending failed, trying again. %s"), curl_easy_strerror((CURLcode)result));
- }
- if (result == 0 || --count <= 0)
- break;
- /* retry the upload if not succesful, wait a bit before next try */
- sleep(retry_delay);
- }
- free(whole_url);
-
- if (count <= 0 && result != 0)
- {
- throw CABRTException(EXCEP_PLUGIN, "Curl can not send a ticket");
- }
-}
-
-
-static void write_str_to_file(const char *str, const char *path, const char *fname)
-{
- char *ofile_name = concat_path_file(path, fname);
- FILE *ofile = fopen(ofile_name, "w");
- if (!ofile)
- {
- CABRTException e(EXCEP_PLUGIN, "Can't open '%s'", ofile_name);
- free(ofile_name);
- throw e;
- }
- free(ofile_name);
- fputs(str, ofile);
- fclose(ofile);
-}
-
-string CReportUploader::Report(const map_crash_data_t& pCrashData,
- const map_plugin_settings_t& pSettings,
- const char *pArgs)
-{
- string customer_name;
- string ticket_name;
- string upload_url;
- bool do_encrypt;
- bool do_upload;
- int retry_count;
- int retry_delay;
-
- /* if parse_settings fails it returns an empty map so we need to use defaults */
- map_plugin_settings_t settings = parse_settings(pSettings);
- // Get ticket name, customer name, and do_encrypt from config settings
- if (!settings.empty())
- {
- customer_name = settings["Customer"];
- ticket_name = settings["Ticket"];
- upload_url = settings["URL"];
- do_encrypt = string_to_bool(settings["Encrypt"].c_str());
- do_upload = string_to_bool(settings["Upload"].c_str());
- retry_count = xatoi_u(settings["RetryCount"].c_str());
- retry_delay = xatoi_u(settings["RetryDelay"].c_str());
- }
- else
- {
- customer_name = m_sCustomer;
- ticket_name = m_sTicket;
- upload_url = m_sURL;
- do_encrypt = m_bEncrypt;
- do_upload = m_bUpload;
- retry_count = m_nRetryCount;
- retry_delay = m_nRetryDelay;
- }
- update_client(_("Creating a ReportUploader report..."));
-
- bool have_ticket_name = (ticket_name != "");
- if (!have_ticket_name)
- {
- ticket_name = "ReportUploader-newticket";
- }
-
- // Format the time to add to the file name
- char timebuf[256];
- time_t curtime = time(NULL);
- strftime(timebuf, sizeof(timebuf), "-%Y%m%d%H%M%S", gmtime(&curtime));
-
- // Create a tmp work directory, and within that
- // create the "<ticketname>-yyyymmddhhmmss" directory
- // which will be the root of the tarball
- string file_name = ticket_name + timebuf;
-
- char tmpdir_name[] = "/tmp/abrtuploadXXXXXX";
- if (mkdtemp(tmpdir_name) == NULL)
- {
- throw CABRTException(EXCEP_PLUGIN, "Can't mkdir a temporary directory in /tmp");
- }
-
- char *tmptar_name = concat_path_file(tmpdir_name, file_name.c_str());
- if (mkdir(tmptar_name, 0700))
- {
- CABRTException e(EXCEP_PLUGIN, "Can't mkdir '%s'", tmptar_name);
- free(tmptar_name);
- throw e;
- }
-
- // Copy each entry into the tarball root.
- // Files are simply copied, strings are written to a file
- // TODO: some files are totally useless:
- // "Reported", "Message" (plugin's output), "DumpDir",
- // "Description" (package description) - maybe skip those?
- map_crash_data_t::const_iterator it;
- for (it = pCrashData.begin(); it != pCrashData.end(); it++)
- {
- const char *content = it->second[CD_CONTENT].c_str();
- if (it->second[CD_TYPE] == CD_TXT)
- {
- write_str_to_file(content, tmptar_name, it->first.c_str());
- }
- else if (it->second[CD_TYPE] == CD_BIN)
- {
- char *ofile_name = concat_path_file(tmptar_name, it->first.c_str());
- if (copy_file(content, ofile_name, 0644) < 0)
- {
- CABRTException e(EXCEP_PLUGIN,
- "Can't copy '%s' to '%s'",
- content, ofile_name
- );
- free(tmptar_name);
- free(ofile_name);
- throw e;
- }
- free(ofile_name);
- }
- }
-
- // add ticket_name and customer name to tarball
- if (have_ticket_name)
- {
- write_str_to_file(ticket_name.c_str(), tmptar_name, "TICKET");
- }
- if (customer_name != "")
- {
- write_str_to_file(customer_name.c_str(), tmptar_name, "CUSTOMER");
- }
-
- // Create the compressed tarball
- string outfile_basename = file_name + ".tar.gz";
- char *outfile_name = concat_path_file(tmpdir_name, outfile_basename.c_str());
- string cmd = ssprintf("tar -C %s --create --gzip --file=%s %s", tmpdir_name, outfile_name, file_name.c_str());
- RunCommand(cmd.c_str());
-
- // encrypt if requested
- string key;
- if (do_encrypt)
- {
- key = ReadCommand("openssl rand -base64 48");
-
- string infile_name = outfile_name;
- outfile_basename += ".aes";
- outfile_name = append_to_malloced_string(outfile_name, ".aes");
-
- cmd = ssprintf("openssl aes-128-cbc -in %s -out %s -pass stdin", infile_name.c_str(), outfile_name);
- WriteCommand(cmd.c_str(), key.c_str());
- }
-
- // generate md5sum
- cmd = ssprintf("cd %s; md5sum <%s", tmpdir_name, outfile_basename.c_str());
- string md5sum = ReadCommand(cmd.c_str());
-
- // upload or cp to /tmp
- if (do_upload)
- {
- // FIXME: SendFile isn't working sometime (scp)
- SendFile(upload_url.c_str(), outfile_name, retry_count, retry_delay);
- }
- else
- {
- cmd = ssprintf("cp %s /tmp/", outfile_name);
- RunCommand(cmd.c_str());
- }
-
- // generate a reciept telling md5sum and encryption key
- // note: do not internationalize these strings!
- string msg;
- if (have_ticket_name)
- {
- msg += "Please copy this into ticket: ";
- msg += ticket_name;
- msg += '\n';
- msg += "========cut here========\n";
- }
- else
- {
- msg += "Please send this to your technical support:\n";
- msg += "========cut here========\n";
- }
- if (do_upload)
- {
- msg += "RHUPLOAD: This report was sent to ";
- msg += upload_url;
- msg += '\n';
- }
- else
- {
- msg += "RHUPLOAD: This report was copied into /tmp/:\n";
- }
- if (have_ticket_name)
- {
- msg += "TICKET: ";
- msg += ticket_name;
- msg += '\n';
- }
- msg += "FILE: ";
- msg += outfile_basename;
- msg += "\nMD5SUM: ";
- msg += md5sum;
- msg += '\n';
- if (do_encrypt)
- {
- msg += "KEY: aes-128-cbc\n";
- msg += key;
- msg += '\n';
- }
- msg += "==========end===========\n";
-
- // warn the client (why _warn_? it's not an error, maybe update_client?):
- //error_msg("%s", msg.c_str());
-
- // delete the temporary directory
- cmd = ssprintf("rm -rf %s", tmpdir_name);
- RunCommand(cmd.c_str());
-
- free(tmptar_name);
- free(outfile_name);
-
- return msg;
-}
-
-static bool is_string_safe(const char *str)
-{
- const char *p = str;
- while (*p)
- {
- unsigned char c = *p;
- if ((c < '0' || c > '9')
- && c != '_'
- && c != '-'
- ) {
- c |= 0x20; // tolower
- if (c < 'a' || c > 'z')
- {
- return false;
- }
- }
- // only 0-9, -, _, A-Z, a-z reach this point
- p++;
- }
- return true;
-}
-
-void CReportUploader::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)
- {
- m_sCustomer = it->second;
- }
- // We use m_sTicket as part of filename,
- // and we use resulting filename in system("cd %s; ...", filename) etc,
- // so we are very paraniod about allowed chars
- it = pSettings.find("Ticket");
- if (it != end && is_string_safe(it->second.c_str()))
- {
- m_sTicket = it->second;
- }
- it = pSettings.find("URL");
- if (it != end)
- {
- m_sURL = it->second;
- }
- it = pSettings.find("Encrypt");
- if (it != end)
- {
- m_bEncrypt = string_to_bool(it->second.c_str());
- }
- it = pSettings.find("Upload");
- if (it != end)
- {
- m_bUpload = string_to_bool(it->second.c_str());
- }
- it = pSettings.find("RetryCount");
- if (it != end)
- {
- m_nRetryCount = xatoi_u(it->second.c_str());
- }
- it = pSettings.find("RetryDelay");
- if (it != end)
- {
- m_nRetryDelay = xatoi_u(it->second.c_str());
- }
-}
-
-const map_plugin_settings_t& CReportUploader::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_bUpload ? "yes" : "no";
- m_pSettings["RetryCount"] = to_string(m_nRetryCount);
- m_pSettings["RetryDelay"] = to_string(m_nRetryDelay);
-
- return m_pSettings;
-}
-
-//todo: make static
-map_plugin_settings_t CReportUploader::parse_settings(const map_plugin_settings_t& pSettings)
-{
- map_plugin_settings_t plugin_settings;
-
- map_plugin_settings_t::const_iterator end = pSettings.end();
- map_plugin_settings_t::const_iterator it;
-
- it = pSettings.find("Customer");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["Customer"] = it->second;
-
- it = pSettings.find("Ticket");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["Ticket"] = it->second;
-
- it = pSettings.find("URL");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["URL"] = it->second;
-
- it = pSettings.find("Encrypt");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["Encrypt"] = it->second;
-
- it = pSettings.find("Upload");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["Upload"] = it->second;
-
- it = pSettings.find("RetryCount");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["RetryCount"] = it->second;
-
- it = pSettings.find("RetryDelay");
- if (it == end)
- {
- plugin_settings.clear();
- return plugin_settings;
- }
- plugin_settings["RetryDelay"] = it->second;
-
- VERB1 log("User settings ok, using them instead of defaults");
- return plugin_settings;
-}
-
-PLUGIN_INFO(REPORTER,
- CReportUploader,
- "ReportUploader",
- "0.0.1",
- _("Packs crash data into .tar.gz file, optionally uploads it via FTP/SCP/etc"),
- "gavin@redhat.com",
- "https://fedorahosted.org/abrt/wiki",
- PLUGINS_LIB_DIR"/ReportUploader.glade");