From 39808986b1df661b2a02c9e762eb55ff9a2ea618 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 29 Mar 2014 04:12:02 -0500 Subject: Add preliminary support for uploading crash reports to a central server without requiring Bugzilla --- drkonqi/toplevel.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 207 insertions(+), 6 deletions(-) (limited to 'drkonqi/toplevel.cpp') 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("

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.

\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("

The crash report is ready. Do you want to send it now?

\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("

Your crash report has been uploaded!

You may reference it if desired by its unique ID:
%1

").arg(responseString), + i18n("Report uploaded")); + close(); + } + else { + responseString = responseString.mid(4); + KMessageBox::error + (0, + i18n("

Your crash report failed to upload!

Please check your network settings and try again.

The server responded:
%1

").arg(responseString), + i18n("Upload failure")); + } + } + else { + KMessageBox::error + (0, + i18n("

Your crash report failed to upload!

Please check your network settings and try again.

"), + i18n("Upload failure")); + } +} + +void Toplevel::postCrashDataToServerDataRedirection(TDEIO::Job * /*job*/, const KURL& url) +{ + // +} \ No newline at end of file -- cgit v1.2.3