summaryrefslogtreecommitdiffstats
path: root/lib/Plugins
diff options
context:
space:
mode:
authorZdenek Prikryl <zprikryl@redhat.com>2009-09-08 18:26:32 +0200
committerZdenek Prikryl <zprikryl@redhat.com>2009-09-08 18:26:32 +0200
commitd6082920ffc97274faf1a742dca074aeb14c1137 (patch)
treebc9f590b60fe8b4073f241db7c757ca9a3419ca6 /lib/Plugins
parentf02e1d87d46aa6161d0cab5444e0abfa9624b78d (diff)
downloadabrt-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.am12
-rw-r--r--lib/Plugins/TicketUploader.GTKBuilder222
-rw-r--r--lib/Plugins/TicketUploader.conf22
-rw-r--r--lib/Plugins/TicketUploader.cpp494
-rw-r--r--lib/Plugins/TicketUploader.h73
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">&#x25CF;</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">&#x25CF;</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">&#x25CF;</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">&#x25CF;</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">&#x25CF;</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_ */