summaryrefslogtreecommitdiffstats
path: root/drkonqi/toplevel.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2014-03-29 04:12:02 -0500
committerTimothy Pearson <[email protected]>2014-03-29 04:12:02 -0500
commit39808986b1df661b2a02c9e762eb55ff9a2ea618 (patch)
tree8f886f8350f7b3f81bfc7fccbed96f092cbba127 /drkonqi/toplevel.cpp
parent71be0ee5d441711ed7070bb69f4db18f775b1030 (diff)
downloadtdebase-39808986b1df661b2a02c9e762eb55ff9a2ea618.tar.gz
tdebase-39808986b1df661b2a02c9e762eb55ff9a2ea618.zip
Add preliminary support for uploading crash reports to a central server without requiring Bugzilla
Diffstat (limited to 'drkonqi/toplevel.cpp')
-rw-r--r--drkonqi/toplevel.cpp213
1 files changed, 207 insertions, 6 deletions
diff --git a/drkonqi/toplevel.cpp b/drkonqi/toplevel.cpp
index 3368f6dcf..6903ad4ff 100644
--- a/drkonqi/toplevel.cpp
+++ b/drkonqi/toplevel.cpp
@@ -42,8 +42,10 @@
#include "backtrace.h"
#include "drbugreport.h"
+#include "bugdescription.h"
#include "debugger.h"
#include "krashconf.h"
+#include "sha1.h"
#include "toplevel.h"
#include "toplevel.moc"
@@ -57,9 +59,10 @@ Toplevel :: Toplevel(KrashConfig *krashconf, TQWidget *parent, const char *name)
true, // modal
false, // no separator
i18n("&Bug report"),
- i18n("&Debugger")
+ i18n("&Debugger"),
+ i18n("&Report Crash")
),
- m_krashconf(krashconf), m_bugreport(0)
+ m_krashconf(krashconf), m_bugreport(0), m_bugdescription(0)
{
TQHBox *page = addHBoxPage(i18n("&General"));
page->setSpacing(20);
@@ -82,7 +85,7 @@ Toplevel :: Toplevel(KrashConfig *krashconf, TQWidget *parent, const char *name)
showButton( User1, m_krashconf->showBugReport() );
showButton( User2, m_krashconf->showDebugger() );
- showButton( User3, false );
+ showButton( User3, true );
connect(this, TQT_SIGNAL(closeClicked()), TQT_SLOT(accept()));
connect(m_krashconf, TQT_SIGNAL(newDebuggingApplication(const TQString&)), TQT_SLOT(slotNewDebuggingApp(const TQString&)));
@@ -156,8 +159,7 @@ void Toplevel :: slotUser1()
// generate the backtrace
BackTrace *backtrace = new BackTrace(m_krashconf, TQT_TQOBJECT(this));
connect(backtrace, TQT_SIGNAL(someError()), TQT_SLOT(slotBacktraceSomeError()));
- connect(backtrace, TQT_SIGNAL(done(const TQString &)),
- TQT_SLOT(slotBacktraceDone(const TQString &)));
+ connect(backtrace, TQT_SIGNAL(done(const TQString &)), TQT_SLOT(slotBacktraceDone(const TQString &)));
backtrace->start();
@@ -190,7 +192,16 @@ void Toplevel :: slotNewDebuggingApp(const TQString& launchName)
void Toplevel :: slotUser3()
{
- m_krashconf->acceptDebuggingApp();
+ TQApplication::setOverrideCursor ( tqwaitCursor );
+
+ // generate the backtrace
+ BackTrace *backtrace = new BackTrace(m_krashconf, TQT_TQOBJECT(this));
+ connect(backtrace, TQT_SIGNAL(someError()), TQT_SLOT(slotSendReportBacktraceSomeError()));
+ connect(backtrace, TQT_SIGNAL(done(const TQString &)), TQT_SLOT(slotSendReportBacktraceDone(const TQString &)));
+
+ backtrace->start();
+
+ return;
}
void Toplevel :: slotBacktraceDone(const TQString &str)
@@ -220,3 +231,193 @@ void Toplevel :: slotBacktraceSomeError()
m_bugreport = 0;
}
+void Toplevel::slotSendReportBacktraceSomeError()
+{
+ TQApplication::restoreOverrideCursor();
+
+ KMessageBox::sorry(0, i18n("It was not possible to generate a backtrace."), i18n("Backtrace Not Possible"));
+
+ delete m_bugdescription;
+ m_bugdescription = 0;
+}
+
+void Toplevel::slotSendReportBacktraceDone(const TQString &str)
+{
+ int i = KMessageBox::No;
+ if ( m_krashconf->pid() != 0 ) {
+ i = KMessageBox::warningYesNoCancel
+ (0,
+ i18n("<p>Do you want to include a "
+ "description of what you were doing "
+ "when this application crashed? This "
+ "would help the "
+ "developers to figure out what went "
+ "wrong.</p>\n"),
+ i18n("Include Description"),i18n("Add Description"),i18n("Just Report the Crash"));
+ }
+
+ if (i == KMessageBox::Cancel) {
+ TQApplication::restoreOverrideCursor();
+
+ return;
+ }
+
+ m_bugdescription = new BugDescription(0, true, m_krashconf->aboutData());
+
+ if (i == KMessageBox::Yes) {
+ // Get description
+ // Also get Email address if desired
+ // Possibly reduce hash difficulty if Email address provided?
+ // BugDescription
+ if (m_bugdescription->exec() == TQDialog::Rejected) {
+ delete m_bugdescription;
+ m_bugdescription = 0;
+
+ return;
+ }
+ }
+
+ // Generate automatic crash description
+ TQString autoCrashDescription = m_krashconf->errorDescriptionText();
+ m_krashconf->expandString(autoCrashDescription, false);
+
+ // Generate full crash report
+ TQString backtraceSubmission = str;
+ backtraceSubmission.append("\n==== (tdebugreport) automatic crash description ====\n");
+ backtraceSubmission.append(TQString("%1\n").arg(autoCrashDescription));
+ if (m_bugdescription->emailAddress().contains("@") && m_bugdescription->emailAddress().contains(".")) {
+ backtraceSubmission.append("\n==== (tdebugreport) reporting Email address ====\n");
+ backtraceSubmission.append(TQString("%1\n").arg(m_bugdescription->emailAddress()));
+ }
+ if (m_bugdescription->crashDescription() != "") {
+ backtraceSubmission.append("\n==== (tdebugreport) user-generated crash description ====\n");
+ backtraceSubmission.append(TQString("%1\n").arg(m_bugdescription->crashDescription()));
+ }
+
+ // Calculate proof-of-work hash
+ SHA1 sha;
+ TQByteArray hash(sha.size() / 8);
+ hash.fill(255);
+
+ backtraceSubmission.append("\n==== (tdebugreport) proof of work ====\n");
+ int proofOfWorkPos = backtraceSubmission.length();
+ backtraceSubmission.append(TQUuid::createUuid().toString());
+ TQCString backtraceSubmissionData(backtraceSubmission.ascii());
+
+ while ((hash[0] != 0) || ((hash[1] & 0xfc) != 0)) { // First 14 bits of the SHA1 hash must be zero
+ TQCString proofOfWork(TQUuid::createUuid().toString().ascii());
+ memcpy(backtraceSubmissionData.data() + proofOfWorkPos, proofOfWork.data(), proofOfWork.size());
+ sha.reset();
+ sha.process(backtraceSubmissionData, backtraceSubmissionData.length());
+ memcpy(hash.data(), sha.hash(), hash.size());
+ }
+
+ TQApplication::restoreOverrideCursor();
+
+ i = KMessageBox::Yes;
+ while (i == KMessageBox::Yes) {
+ i = KMessageBox::warningYesNoCancel
+ (0,
+ i18n("<p>The crash report is ready. Do you want to send it now?</p>\n"),
+ i18n("Ready to Send"),i18n("View Report"),i18n("Send Report"));
+
+ if (i == KMessageBox::Cancel) {
+ delete m_bugdescription;
+ m_bugdescription = 0;
+
+ return;
+ }
+
+ if (i == KMessageBox::Yes) {
+ BugDescription fullReport(0, true, NULL);
+ fullReport.fullReportViewMode(true);
+ fullReport.setText(TQString(backtraceSubmissionData.data()));
+ fullReport.showMaximized();
+ fullReport.exec();
+ }
+ }
+
+ postCrashDataToServer(backtraceSubmissionData);
+
+ delete m_bugdescription;
+ m_bugdescription = 0;
+}
+
+int Toplevel::postCrashDataToServer(TQByteArray data) {
+ serverResponse = "";
+ TQCString formDataBoundary = "-----------------------------------DrKonqiCrashReporterBoundary";
+
+ TQCString postData;
+ postData += "--";
+ postData += formDataBoundary;
+ postData += "\r\n";
+ postData += "Content-Disposition: form-data; name=\"crashreport\"; filename=\"crashreport.txt\"\r\n";
+ postData += "Content-Type: application/octet-stream\r\n";
+ postData += "Content-Transfer-Encoding: binary\r\n\r\n";
+ postData += data;
+ postData += "--";
+ postData += formDataBoundary;
+ postData += "--";
+
+ KURL url("https://crashreport.trinitydesktop.org/");
+// TDEIO::TransferJob* job = TDEIO::http_post(url, postData, false);
+ TDEIO::TransferJob* job = TDEIO::http_post(url, postData, true);
+ job->addMetaData("content-type", TQString("Content-Type: multipart/form-data, boundary=%1").arg(formDataBoundary));
+ job->addMetaData("referrer", "http://drkonqi-client.crashreport.trinitydesktop.org");
+ connect(job, TQT_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), TQT_SLOT(postCrashDataToServerData(TDEIO::Job *, const TQByteArray &)));
+ connect(job, TQT_SIGNAL(result(TDEIO::Job *)), TQT_SLOT(postCrashDataToServerResult(TDEIO::Job *)));
+// connect(job, TQT_SIGNAL(totalSize(TDEIO::Job *, TDEIO::filesize_t )),
+// TQT_SLOT(totalSize(TDEIO::Job *, TDEIO::filesize_t)));
+// connect(job, TQT_SIGNAL(mimetype(TDEIO::Job *, const TQString &)),
+// TQT_SLOT(mimetype(TDEIO::Job *, const TQString &)));
+ connect(job, TQT_SIGNAL(redirection(TDEIO::Job *, const KURL&)), TQT_SLOT(postCrashDataToServerDataRedirection(TDEIO::Job *, const KURL&)));
+
+ return 0;
+}
+
+void Toplevel::postCrashDataToServerData(TDEIO::Job *, const TQByteArray &ba)
+{
+ uint offset = 0;
+ if (serverResponse.count() > 0) {
+ offset = serverResponse.count() - 1;
+ }
+ uint size = ba.count();
+
+ serverResponse.resize(offset + size + 1);
+ memcpy(serverResponse.data() + offset, ba.data(), size);
+ *(serverResponse.data() + offset + size) = 0;
+}
+
+void Toplevel::postCrashDataToServerResult(TDEIO::Job *job)
+{
+ int err = job->error();
+ if (err == 0) {
+ TQString responseString(serverResponse);
+ if (responseString.startsWith("ACK\n")) {
+ responseString = responseString.mid(4);
+ KMessageBox::information
+ (0,
+ i18n("<p>Your crash report has been uploaded!</p></p>You may reference it if desired by its unique ID:<br>%1</p>").arg(responseString),
+ i18n("Report uploaded"));
+ close();
+ }
+ else {
+ responseString = responseString.mid(4);
+ KMessageBox::error
+ (0,
+ i18n("<p>Your crash report failed to upload!</p><p>Please check your network settings and try again.</p><p>The server responded:<br>%1</p>").arg(responseString),
+ i18n("Upload failure"));
+ }
+ }
+ else {
+ KMessageBox::error
+ (0,
+ i18n("<p>Your crash report failed to upload!</p><p>Please check your network settings and try again.</p>"),
+ i18n("Upload failure"));
+ }
+}
+
+void Toplevel::postCrashDataToServerDataRedirection(TDEIO::Job * /*job*/, const KURL& url)
+{
+ //
+} \ No newline at end of file