diff options
author | Zdenek Prikryl <zprikryl@redhat.com> | 2009-09-08 18:26:32 +0200 |
---|---|---|
committer | Zdenek Prikryl <zprikryl@redhat.com> | 2009-09-08 18:26:32 +0200 |
commit | d6082920ffc97274faf1a742dca074aeb14c1137 (patch) | |
tree | bc9f590b60fe8b4073f241db7c757ca9a3419ca6 /lib/Plugins | |
parent | f02e1d87d46aa6161d0cab5444e0abfa9624b78d (diff) | |
download | abrt-d6082920ffc97274faf1a742dca074aeb14c1137.tar.gz abrt-d6082920ffc97274faf1a742dca074aeb14c1137.tar.xz abrt-d6082920ffc97274faf1a742dca074aeb14c1137.zip |
added ticket uploader plugin (gavin@redhat.com)
Diffstat (limited to 'lib/Plugins')
-rw-r--r-- | lib/Plugins/Makefile.am | 12 | ||||
-rw-r--r-- | lib/Plugins/TicketUploader.GTKBuilder | 222 | ||||
-rw-r--r-- | lib/Plugins/TicketUploader.conf | 22 | ||||
-rw-r--r-- | lib/Plugins/TicketUploader.cpp | 494 | ||||
-rw-r--r-- | lib/Plugins/TicketUploader.h | 73 |
5 files changed, 820 insertions, 3 deletions
diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index 156ab206..4ed9f2c9 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -10,18 +10,19 @@ pluginslib_LTLIBRARIES = libCCpp.la \ libRunApp.la \ libSOSreport.la \ libBugzilla.la \ + libTicketUploader.la \ libPython.la \ libFileTransfer.la -dist_pluginslib_DATA = KerneloopsReporter.GTKBuilder Logger.GTKBuilder Mailx.GTKBuilder Bugzilla.GTKBuilder +dist_pluginslib_DATA = KerneloopsReporter.GTKBuilder Logger.GTKBuilder Mailx.GTKBuilder Bugzilla.GTKBuilder TicketUploader.GTKBuilder pluginsconfdir=$(PLUGINS_CONF_DIR) -dist_pluginsconf_DATA = CCpp.conf Mailx.conf SQLite3.conf Logger.conf KerneloopsScanner.conf KerneloopsReporter.conf Bugzilla.conf FileTransfer.conf +dist_pluginsconf_DATA = CCpp.conf Mailx.conf SQLite3.conf Logger.conf KerneloopsScanner.conf KerneloopsReporter.conf Bugzilla.conf TicketUploader.conf FileTransfer.conf man_MANS = abrt-FileTransfer.7 abrt-Bugzilla.7 abrt-KerneloopsReporter.7\ abrt-KerneloopsScanner.7 abrt-Logger.7 abrt-Mailx.7 abrt-plugins.7\ - abrt-SQLite3.7 abrt-RunApp.7 + abrt-SQLite3.7 abrt-RunApp.7 abrt-TicketUploader.7 EXTRA_DIST = $(man_MANS) @@ -83,6 +84,11 @@ libBugzilla_la_LIBADD = $(XMLRPC_CPP_LIBS) $(XMLRPC_CLIENT_CPP_LIBS) $(NSS_LIBS) libBugzilla_la_LDFLAGS = -avoid-version libBugzilla_la_CPPFLAGS = $(XMLRPC_CPP_CFLAGS) $(XMLRPC_CLIENT_CPP_CFLAGS) $(NSS_CFLAGS) -I$(srcdir)/../CommLayer -I$(srcdir)/../../inc -I$(srcdir)/../MiddleWare -I$(srcdir)/../Utils -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" +# TicketUploader +libTicketUploader_la_SOURCES = TicketUploader.h TicketUploader.cpp +libTicketUploader_la_LDFLAGS = -avoid-version +libTicketUploader_la_CPPFLAGS = -I$(srcdir)/../CommLayer -I$(srcdir)/../../inc -I$(srcdir)/../MiddleWare -I$(srcdir)/../Utils -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" + # Python libPython_la_SOURCES = Python.h Python.cpp #libPython_la_LIBADD = $(NSS_LIBS) diff --git a/lib/Plugins/TicketUploader.GTKBuilder b/lib/Plugins/TicketUploader.GTKBuilder new file mode 100644 index 00000000..7865e89e --- /dev/null +++ b/lib/Plugins/TicketUploader.GTKBuilder @@ -0,0 +1,222 @@ +<?xml version="1.0"?> +<interface> + <requires lib="gtk+" version="2.14"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkDialog" id="PluginDialog"> + <property name="border_width">5</property> + <property name="type_hint">normal</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Ticket Uploader plugin configuration</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">5</property> + <property name="n_columns">2</property> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Customer</property> + </object> + </child> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Ticket</property> + </object> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">URL</property> + </object> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="conf_Customer"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="conf_Ticket"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="conf_URL"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Retry count</property> + </object> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="conf_RetryCount"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Retry delay</property> + </object> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="conf_RetryDelay"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="conf_Encrypt"> + <property name="label" translatable="yes">Use encryption</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="conf_Upload"> + <property name="label" translatable="yes">Upload</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="bApply"> + <property name="label" translatable="yes">gtk-apply</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button2"> + <property name="label" translatable="yes">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-10">bApply</action-widget> + <action-widget response="-6">button2</action-widget> + </action-widgets> + </object> + <object class="GtkAction" id="action1"/> +</interface> diff --git a/lib/Plugins/TicketUploader.conf b/lib/Plugins/TicketUploader.conf new file mode 100644 index 00000000..ad5f6d28 --- /dev/null +++ b/lib/Plugins/TicketUploader.conf @@ -0,0 +1,22 @@ + + +# Customer = "Example Inc." +# Ticket = IT12345 +# Encrypt = yes +# Upload = yes + +# URL to upload the files to +# supported: ftp, ftps, http, https, scp, sftp, tftp +# for example: ftp://user:password@server.name/directory +# or: scp://user:password@server.name:port/directory etc. +# URL = + +#how many times we try to upload the file +#RetryCount = 3 + +#how long we wait between we retry the upload (in seconds) +#RetryDelay = 20 + + + + diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp new file mode 100644 index 00000000..db09b884 --- /dev/null +++ b/lib/Plugins/TicketUploader.cpp @@ -0,0 +1,494 @@ +/* + TicketUploader.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 "TicketUploader.h" +#include "DebugDump.h" +#include "ABRTException.h" +#include "CommLayerInner.h" + +#include <stdlib.h> +#include <sys/stat.h> + +#include <string> +#include <fstream> +#include <sstream> +#include <ext/stdio_filebuf.h> +#include <curl/curl.h> + + +CTicketUploader::CTicketUploader() : + m_sCustomer(""), + m_sTicket(""), + m_sURL(""), + m_bEncrypt(false), + m_bUpload(false), + m_nRetryCount(3), + m_nRetryDelay(20) +{} + +CTicketUploader::~CTicketUploader() +{} + + + +void CTicketUploader::Error(string func, string msg) +{ + update_client(msg); + throw CABRTException(EXCEP_PLUGIN, func + msg); +} + +void CTicketUploader::CopyFile(const std::string& pSourceName, const std::string& pDestName) +{ + std::ifstream source(pSourceName.c_str(), std::fstream::binary); + + if (!source) + { + throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open input sosreport filename:" + pSourceName); + } + std::ofstream dest(pDestName.c_str(),std::fstream::trunc|std::fstream::binary); + if (!dest) + { + throw CABRTException(EXCEP_PLUGIN, "CActionSOSreport::CopyFile(): could not open output sosreport filename:" + pDestName); + } + dest << source.rdbuf(); +} + +void CTicketUploader::RunCommand(string cmd) +{ + int retcode = system(cmd.c_str()); + if (retcode == -1) + { + Error("TicketUploader::RunCommand:", "error: could not start subshell: " + cmd); + } + if (retcode) + { + std::ostringstream msg; + msg << "error: subshell failed (rc=" << retcode << "):" << cmd; + Error("TicketUploader::RunCommand:", msg.str()); + } +} + +string CTicketUploader::ReadCommand(string cmd) +{ + FILE* fp = popen(cmd.c_str(),"r"); + if (!fp) + { + Error("TicketUploader::ReadCommand:", "error: could not start subshell: " + cmd); + } + + __gnu_cxx::stdio_filebuf<char> command_output_buffer(fp, std::ios_base::in); + std::ostringstream output_stream; + output_stream << &command_output_buffer; + + int retcode = pclose(fp); + if (retcode) + { + std::ostringstream msg; + msg << "error: subshell failed (rc=" << retcode << "):" << cmd; + Error("TicketUploader::ReadCommand:", msg.str()); + } + + return output_stream.str(); +} + +void CTicketUploader::WriteCommand(string cmd,string input) +{ + FILE* fp = popen(cmd.c_str(),"w"); + if (!fp) + { + Error("TicketUploader::WriteCommand:", "error: could not start subshell: " + cmd); + } + + size_t input_length = input.length(); + size_t check = fwrite(input.c_str(),1,input_length,fp); + if (input_length != check) + { + Error("TicketUploader::WriteCommand:", "error: could not send input to subshell: " + cmd); + } + + int retcode = pclose(fp); + if (retcode) + { + std::ostringstream msg; + msg << "error: subshell failed (rc=" << retcode << "):" << cmd; + Error("TicketUploader::ReadCommand:", msg.str()); + } + +} + +void CTicketUploader::SendFile(const std::string& pURL, + const std::string& pFilename) +{ + FILE * f; + struct stat buf; + CURL * curl; + std::string wholeURL, protocol; + int result, i, count = m_nRetryCount; + int len = pURL.length(); + std::string file; + + if (pURL == "") + { + warn_client(_("FileTransfer: URL not specified")); + return; + } + protocol = ""; + i = 0; + while(pURL[i] != ':') + { + protocol += pURL[i]; + i++; + if(i == len) + { + throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): malformed URL, does not contain protocol"); + } + } + + file = pFilename.substr(pFilename.rfind("/") + 1, pFilename.length()); + + if( pURL[len-1] == '/' ) + { + wholeURL = pURL + file; + } + else + { + wholeURL = pURL + "/" + file; + } + + update_client(_("Sending archive ") + pFilename + _(" via ") + protocol + _(" to ") + pURL); + + do + { + f = fopen(pFilename.c_str(),"r"); + if(!f) + { + throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot open archive file "+pFilename); + } + if (stat(pFilename.c_str(), &buf) == -1) + { + throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): cannot stat archive file "+pFilename); + } + curl = curl_easy_init(); + if(!curl) + { + throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): Curl library error."); + } + /* enable uploading */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + /* specify target */ + curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str()); + /*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, 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, try it again: ") + std::string(curl_easy_strerror((CURLcode)result))); + } + } + /*retry the upload if not succesful, wait a bit before next try*/ + while( result!=0 && --count != 0 && (sleep(m_nRetryDelay),1) ); + + if (count <= 0 && result != 0) + { + throw CABRTException(EXCEP_PLUGIN, "CFileTransfer::SendFile(): Curl can not send a ticket."); + } +} + + +string CTicketUploader::Report(const map_crash_report_t& pCrashReport, const std::string& pArgs) +{ + string ret; + update_client(_("Creating an TicketUploader report...")); + + + + // Get ticket name, customer name, and do_encrypt from config settings + string ticket_name; + string customer_name; + string upload_url; + bool do_encrypt = false; + bool do_upload = false; + + customer_name = m_sCustomer; + ticket_name = m_sTicket; + upload_url = m_sURL; + do_encrypt = m_bEncrypt; + do_upload = m_bUpload; + + bool have_ticket_name = false; + if (ticket_name == "") + { + ticket_name = "TicketUploader-newticket"; + } + else + { + have_ticket_name = true; + } + + + + // Format the time to add to the file name + const int timebufmax = 256; + char timebuf[timebufmax]; + time_t curtime = time(NULL); + if (!strftime(timebuf,timebufmax,"-%G%m%d%k%M%S",gmtime(&curtime))) + { + Error("TicketUploader::Report:","could not format time"); + } + + + + // Create a tmp work directory, and within that the directory + // that will be the root of the tarball + string file_name = ticket_name + timebuf; + + char TEMPLATE[] = "/tmp/rhuploadXXXXXX"; + string tmpdir_name = mkdtemp(TEMPLATE); + string tmptar_name = tmpdir_name + '/' + file_name; + + if (mkdir(tmptar_name.c_str(),S_IRWXU)) + { + Error("TicketUploader::Report:","error: could not mkdir: " + tmptar_name); + } + + + + // Copy each entry into the tarball root, + // files are simply copied, strings are written to a file + map_crash_report_t::const_iterator it; + for (it = pCrashReport.begin(); it != pCrashReport.end(); it++) + { + if (it->second[CD_TYPE] == CD_TXT) + { + string ofile_name = tmptar_name + '/' + it->first; + std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + if (!ofile) + { + Error("TicketUploader::Report:","error: could not open: " + ofile_name); + } + ofile << it->second[CD_CONTENT] << std::endl; + ofile.close(); + } + if (it->second[CD_TYPE] == CD_ATT) + { + string ofile_name = tmptar_name + '/' + it->first; + std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + if (!ofile) + { + Error("TicketUploader::Report:","error: could not open: " + ofile_name); + } + ofile << it->second[CD_CONTENT] << std::endl; + ofile.close(); + } + if (it->second[CD_TYPE] == CD_BIN) + { + string ofile_name = tmptar_name + '/' + it->first; + CopyFile(it->second[CD_CONTENT],ofile_name); + } + } + + + + // add ticket_name and customer name to tarball + if (have_ticket_name) + { + string ofile_name = tmptar_name + "/TICKET"; + std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + if (!ofile) + { + Error("TicketUploader::Report:","error: could not open: " + ofile_name); + } + ofile << ticket_name << std::endl; + ofile.close(); + } + if (customer_name != "") + { + string ofile_name = tmptar_name + "/CUSTOMER"; + std::ofstream ofile(ofile_name.c_str(),std::fstream::trunc|std::fstream::binary); + if (!ofile) + { + Error("TicketUploader::Report:","error: could not open: " + ofile_name); + } + ofile << customer_name << std::endl; + ofile.close(); + } + + + + // Create the compressed tarball + string outfile_basename = file_name + ".tar.gz"; + string outfile_name = tmpdir_name + '/' + outfile_basename; + string cmd = string("tar -C ") + tmpdir_name + + " --create --gzip --file=" + outfile_name + ' ' + file_name; + RunCommand(cmd); + + + + + // encrypt if requested + string key; + if (do_encrypt) + { + cmd = string("openssl rand -base64 48"); + key = ReadCommand(cmd); + + string infile_name = outfile_name; + outfile_basename += ".aes"; + outfile_name += ".aes"; + + cmd = string("openssl aes-128-cbc -in ") + infile_name + + " -out " + outfile_name + " -pass stdin"; + WriteCommand(cmd,key); + } + + + + // generate md5sum + cmd = string("cd ") + tmpdir_name + string("; md5sum ") + outfile_basename; + string md5sum = ReadCommand(cmd); + + + + // upload or cp to /tmp + if (do_upload) + { + // FIXME: SendFile isn't working sometime (scp) + SendFile(upload_url,outfile_name); + } + else + { + cmd = string("cp ") + outfile_name + " /tmp/"; + RunCommand(cmd); + } + + + + // generate a reciept telling md5sum and encryption key + std::ostringstream msgbuf; + if (have_ticket_name) + msgbuf << _("Please copy this into ticket: ") << ticket_name << std::endl; + else + msgbuf << _("Please send this to your technical support: ") << std::endl; + if (do_upload) + msgbuf << _("RHUPLOAD: This report was sent to ") + upload_url << std::endl; + else + msgbuf << _("RHUPLOAD: This report was copied into /tmp/: ") << std::endl; + if (have_ticket_name) + msgbuf << _("TICKET: ") << ticket_name << std::endl; + msgbuf << _("FILE: ") << outfile_basename << std::endl; + msgbuf << _("MD5SUM: ") << std::endl; + msgbuf << md5sum; + if (do_encrypt) + { + msgbuf << _("KEY: aes-128-cbc") << std::endl; + msgbuf << key; + } + msgbuf << _("END: ") << std::endl; + + warn_client(msgbuf.str()); + + if (do_upload) + { + string xx = _("report sent to ") + upload_url + '/' + outfile_basename; + update_client(xx); + ret = xx; + } + else + { + string xx = _("report copied to /tmp/") + outfile_basename; + update_client(xx); + ret = xx; + } + + // delete the temporary directory + cmd = string("rm -rf ") + tmpdir_name; + RunCommand(cmd); + + return ret; +} + +void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings) +{ + if (pSettings.find("Customer") != pSettings.end()) + { + m_sCustomer = pSettings.find("Customer")->second; + } + if (pSettings.find("Ticket") != pSettings.end()) + { + m_sTicket = pSettings.find("Ticket")->second; + } + if (pSettings.find("URL") != pSettings.end()) + { + m_sURL = pSettings.find("URL")->second; + } + if (pSettings.find("Encrypt") != pSettings.end()) + { + m_bEncrypt = pSettings.find("Encrypt")->second == "yes"; + } + if (pSettings.find("Upload") != pSettings.end()) + { + m_bUpload = pSettings.find("Upload")->second == "yes"; + } + if (pSettings.find("RetryCount") != pSettings.end()) + { + m_nRetryCount = atoi(pSettings.find("RetryCount")->second.c_str()); + } + if (pSettings.find("RetryDelay") != pSettings.end()) + { + m_nRetryDelay = atoi(pSettings.find("RetryDelay")->second.c_str()); + } +} + +map_plugin_settings_t CTicketUploader::GetSettings() +{ + map_plugin_settings_t ret; + + ret["Customer"] = m_sCustomer; + ret["Ticket"] = m_sTicket; + ret["URL"] = m_sURL; + ret["Encrypt"] = m_bEncrypt ? "yes" : "no"; + ret["Upload"] = m_bEncrypt ? "yes" : "no"; + + std::stringstream ss; + ss << m_nRetryCount; + ret["RetryCount"] = ss.str(); + ss.str(""); + ss << m_nRetryDelay; + ret["RetryDelay"] = ss.str(); + + return ret; +} + +PLUGIN_INFO(REPORTER, + CTicketUploader, + "TicketUploader", + "0.0.1", + "input ticket# and customer name from user, send report to FTP", + "gavin@redhat.com", + "https://fedorahosted.org/abtr/wiki", + PLUGINS_LIB_DIR"/TicketUploader.GTKBuilder"); + + diff --git a/lib/Plugins/TicketUploader.h b/lib/Plugins/TicketUploader.h new file mode 100644 index 00000000..68a29638 --- /dev/null +++ b/lib/Plugins/TicketUploader.h @@ -0,0 +1,73 @@ +/* + TicketUploader.h + + Attach a configureable Ticket Number and Customer name to a report. + Create a compressed, optionally encrypted, tarball. + Upload tarball to configureable URL. + + 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. + */ + +#ifndef TICKETUPLOADER_H_ +#define TICKETUPLOADER_H_ + +#include "Plugin.h" +#include "Reporter.h" +#include "CrashTypes.h" + +typedef std::string string; + +class CTicketUploader : public CReporter +{ + private: + string m_sCustomer; + string m_sTicket; + string m_sURL; + bool m_bEncrypt; + bool m_bUpload; + + int m_nRetryCount; + int m_nRetryDelay; + + void Error(string func, string msg); + void CopyFile(const std::string& pSourceName, const std::string& pDestName); + // Wrappers around popen/system + // the wrapper in each case handles errors, + // and converts from string->char* + // RunCommand - a wrapper around system(cmd) + void RunCommand(string cmd); + // ReadCommand - a wrapper around popen(cmd,"r") + string ReadCommand(string cmd); + // WriteCommand - a wrapper around popen(cmd,"w") + void WriteCommand(string cmd, string input ); + + void SendFile(const std::string& pURL, + const std::string& pFilename); + + public: + CTicketUploader(); + virtual ~CTicketUploader(); + virtual map_plugin_settings_t GetSettings(); + virtual void SetSettings(const map_plugin_settings_t& pSettings); + + virtual string Report(const map_crash_report_t& pCrashReport, + const std::string& pArgs); + + +}; + +#endif /* TICKETUPLOADER_H_ */ |