CrashReportUploader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "CrashReportUploader.h"
00019
00020 #include <QtGlobal>
00021 #include <QDateTime>
00022 #include <QSslSocket>
00023 #include <QSslCertificate>
00024 #include <QHttpRequestHeader>
00025 #include <QHttpResponseHeader>
00026 #include <QMap>
00027 #include <QUrl>
00028
00029
00030 CrashReportUploader::CrashReportUploader(QObject *parent)
00031 : QObject(parent),
00032 _requestId(-1)
00033 {
00034
00035 QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
00036 QSslSocket::addDefaultCaCertificates(":/pki/gd-class2-root.crt");
00037
00038
00039 _http = new QHttp(this);
00040 connect(_http, SIGNAL(stateChanged(int)),
00041 this, SLOT(httpStateChanged(int)));
00042 connect(_http, SIGNAL(requestFinished(int, bool)),
00043 this, SLOT(httpRequestFinished(int, bool)));
00044 connect(_http, SIGNAL(dataSendProgress(int, int)),
00045 this, SIGNAL(uploadProgress(int, int)));
00046
00047
00048 qsrand(QDateTime::currentDateTime().toTime_t());
00049 }
00050
00051 void
00052 CrashReportUploader::uploadMinidump(const QUrl &serverUrl,
00053 const QString &minidumpId,
00054 const QByteArray &minidump,
00055 const QMap<QString,QString> ¶meters)
00056 {
00057 QByteArray body;
00058
00059
00060
00061 if (! serverUrl.scheme().compare("https", Qt::CaseInsensitive)) {
00062 _http->setHost(serverUrl.host(), QHttp::ConnectionModeHttps,
00063 serverUrl.port(443));
00064 } else {
00065 _http->setHost(serverUrl.host(), QHttp::ConnectionModeHttp,
00066 serverUrl.port(80));
00067 }
00068
00069
00070 QHttpRequestHeader header("POST", serverUrl.path());
00071 QString boundary = generateBoundaryMarker();
00072 header.setValue("Host", serverUrl.host());
00073 header.setContentType(QString("multipart/form-data; boundary=%1")
00074 .arg(boundary));
00075
00076
00077 foreach (QString key, parameters.keys()) {
00078 QString value = parameters.value(key);
00079 if (! value.isEmpty()) {
00080 body.append(QString("--%1\r\n").arg(boundary));
00081 body.append(QString("Content-Disposition: form-data; name=\"%1\"").arg(key));
00082 body.append("\r\n\r\n");
00083 body.append(value.toUtf8());
00084 body.append("\r\n");
00085 }
00086 }
00087
00088
00089 body.append(QString("--%1\r\n").arg(boundary));
00090 body.append("Content-Disposition: form-data; ");
00091 body.append("name=\"upload_file_minidump\"; ");
00092 body.append(QString("filename=\"%1\"\r\n").arg(minidumpId));
00093 body.append("Content-Type: application/octet-stream\r\n\r\n");
00094 body.append(minidump);
00095 body.append(QString("\r\n--%1\r\n").arg(boundary));
00096
00097
00098 _requestId = _http->request(header, body);
00099 }
00100
00101 QString
00102 CrashReportUploader::generateBoundaryMarker() const
00103 {
00104 return QString("%1%2").arg((quint32)qrand(), 8, 16, QChar('0'))
00105 .arg((quint32)qrand(), 8, 16, QChar('0'));
00106 }
00107
00108 void
00109 CrashReportUploader::cancel()
00110 {
00111 _http->abort();
00112 }
00113
00114 void
00115 CrashReportUploader::httpStateChanged(int state)
00116 {
00117 switch (state) {
00118 case QHttp::Connecting:
00119 emit statusChanged(tr("Connecting..."));
00120 break;
00121
00122 case QHttp::Sending:
00123 emit statusChanged(tr("Sending crash report..."));
00124 break;
00125
00126 case QHttp::Reading:
00127 emit statusChanged(tr("Receiving response..."));
00128 break;
00129
00130 default:
00131 break;
00132 }
00133 }
00134
00135 void
00136 CrashReportUploader::httpRequestFinished(int id, bool error)
00137 {
00138 if (id != _requestId)
00139 return;
00140
00141 if (error) {
00142 QString errorString = _http->errorString();
00143 emit uploadFailed(errorString);
00144 } else {
00145 QHttpResponseHeader response = _http->lastResponse();
00146 if (response.statusCode() == 200)
00147 emit uploadFinished();
00148 else
00149 emit uploadFailed(response.reasonPhrase());
00150 }
00151 _http->close();
00152 }
00153