moved more to qbrowserlib, added download manager functions; refs #167
parent
9d50e35895
commit
99bafe0aac
17 changed files with 1066 additions and 812 deletions
@ -1,304 +0,0 @@ |
||||
/*! @file
|
||||
|
||||
@id $Id$ |
||||
*/ |
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef __DOWNLOAD_MANAGER_HXX |
||||
#define __DOWNLOAD_MANAGER_HXX |
||||
|
||||
#include <qbrowserlib/log.hxx> |
||||
#include <QtNetwork/QNetworkReply> |
||||
#include <QtNetwork/QSslError> |
||||
#include <QtNetwork/QSslConfiguration> |
||||
#include <map> |
||||
|
||||
#include <cassert> |
||||
|
||||
class DownloadManager: public QObject { |
||||
Q_OBJECT; |
||||
public: |
||||
|
||||
DownloadManager& operator+=(QNetworkReply* reply) { |
||||
TRC; |
||||
add(reply); |
||||
return *this; |
||||
} |
||||
|
||||
static QString networkError(QNetworkReply::NetworkError err) { |
||||
TRC_FN; LOG<<err; |
||||
switch (err) { |
||||
case QNetworkReply::NoError: |
||||
return tr("Network connection successful, remote host can be" |
||||
" reached."); |
||||
case QNetworkReply::ConnectionRefusedError: |
||||
return tr("The remote server refused the connection (the server is" |
||||
" not accepting requests)."); |
||||
case QNetworkReply::RemoteHostClosedError: |
||||
return tr("The remote server closed the connection prematurely," |
||||
" before the entire reply was received and processed."); |
||||
case QNetworkReply::HostNotFoundError: |
||||
return tr("The remote host name was not found (invalid hostname)."); |
||||
case QNetworkReply::TimeoutError: |
||||
return tr("The connection to the remote server timed out."); |
||||
case QNetworkReply::OperationCanceledError: |
||||
return tr("The operation was canceled via calls to abort() or" |
||||
" close() before it was finished."); |
||||
case QNetworkReply::SslHandshakeFailedError: |
||||
return tr("The SSL/TLS handshake failed and the encrypted channel" |
||||
" could not be established. See SSL-Errors above."); |
||||
case QNetworkReply::ProxyConnectionRefusedError: |
||||
return tr("The connection to the proxy server was refused (the" |
||||
" proxy server is not accepting requests)."); |
||||
case QNetworkReply::ProxyConnectionClosedError: |
||||
return tr("The proxy server closed the connection prematurely," |
||||
" before the entire reply was received and processed."); |
||||
case QNetworkReply::ProxyNotFoundError: |
||||
return tr("The proxy host name was not found (invalid proxy" |
||||
" hostname)."); |
||||
case QNetworkReply::ProxyTimeoutError: |
||||
return tr("The connection to the proxy timed out or the proxy did" |
||||
" not reply in time to the request sent."); |
||||
case QNetworkReply::ProxyAuthenticationRequiredError: |
||||
return tr("The proxy requires authentication in order to honour the" |
||||
" request but did not accept any credentials offered" |
||||
" (if any)."); |
||||
case QNetworkReply::ContentAccessDenied: |
||||
return tr("The access to the remote content was denied (similar to" |
||||
" HTTP error 401)."); |
||||
case QNetworkReply::ContentOperationNotPermittedError: |
||||
return tr("The operation requested on the remote content is not" |
||||
" permitted."); |
||||
case QNetworkReply::ContentNotFoundError: |
||||
return tr("The remote content was not found at the server (similar" |
||||
" to HTTP error 404)."); |
||||
case QNetworkReply::AuthenticationRequiredError: |
||||
return tr("The remote server requires authentication to serve the" |
||||
" content but the credentials provided were not accepted" |
||||
" (if any)."); |
||||
case QNetworkReply::ProtocolUnknownError: |
||||
return tr("The Network Access API cannot honor the request because" |
||||
" the protocol is not known."); |
||||
case QNetworkReply::ProtocolInvalidOperationError: |
||||
return tr("The requested operation is invalid for this protocol."); |
||||
case QNetworkReply::UnknownNetworkError: |
||||
return tr("An unknown network-related error was detected."); |
||||
case QNetworkReply::UnknownProxyError: |
||||
return tr("An unknown proxy-related error was detected."); |
||||
case QNetworkReply::UnknownContentError: |
||||
return tr("An unknonwn error related to the remote content was" |
||||
" detected."); |
||||
case QNetworkReply::ProtocolFailure: |
||||
return tr("A breakdown in protocol was detected (parsing error," |
||||
" invalid or unexpected responses, etc.)."); |
||||
default: |
||||
return tr("Unknown network error (code: %1).").arg(err); |
||||
} |
||||
} |
||||
|
||||
Q_SIGNALS: |
||||
|
||||
void progress(qint64 done, qint64 total); |
||||
void started(); |
||||
void finished(); |
||||
void error(QString); |
||||
void metaDataChanged(QNetworkReply*); |
||||
|
||||
public Q_SLOTS: |
||||
|
||||
void add(QNetworkReply* reply) { |
||||
TRC; LOG<<_downloads.size()<<reply->url().toString(); |
||||
LOG<<reply; |
||||
_downloads[reply].progress = Progress(0, 0); |
||||
assert(connect(reply, SIGNAL(downloadProgress(qint64, qint64)), |
||||
SLOT(downloadProgress(qint64, qint64)))); |
||||
assert(connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), |
||||
SLOT(error(QNetworkReply::NetworkError)))); |
||||
assert(connect(reply, SIGNAL(destroyed(QObject*)), |
||||
SLOT(slotDestroyed(QObject*)))); |
||||
assert(connect(reply, SIGNAL(finished()), |
||||
SLOT(slotFinished()))); |
||||
assert(connect(reply, SIGNAL(metaDataChanged()), |
||||
SLOT(slotMetaDataChanged()))); |
||||
assert(connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)), |
||||
SLOT(sslErrors(const QList<QSslError>&)))); |
||||
assert(connect(reply, SIGNAL(uploadProgress(qint64, qint64)), |
||||
SLOT(uploadProgress(qint64, qint64)))); |
||||
if (_downloads.size()==1) started(); |
||||
} |
||||
|
||||
void abort() { |
||||
while (_downloads.size()) _downloads.begin()->first->abort(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
void calcProgress() { |
||||
//TRC;
|
||||
qint64 done(0); |
||||
qint64 total(0); |
||||
for (Downloads::iterator it(_downloads.begin()); |
||||
it!=_downloads.end(); ++it) { |
||||
done += it->second.progress.first; |
||||
total += it->second.progress.second; |
||||
} |
||||
progress(done, total); |
||||
} |
||||
|
||||
private Q_SLOTS: |
||||
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { |
||||
//TRC; LOG<<bytesReceived<<bytesTotal;
|
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.first |
||||
= bytesReceived; |
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.second |
||||
= bytesTotal; |
||||
calcProgress(); |
||||
} |
||||
void error(QNetworkReply::NetworkError code) { |
||||
TRC; LOG<<"Status:"<<networkError(code); |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
_downloads[reply].error += |
||||
tr("<h1>Network Error</h1>" |
||||
"<dl><dt>URL:</dt><dd>%1</dd>" |
||||
"<dt>Error Code:</dt><dd>%3</dd>" |
||||
"<dt>Error Details:</dt><dd>%2</dd></dl>") |
||||
.arg(reply->url().toString()) |
||||
.arg(networkError(code)) |
||||
.arg(code); |
||||
} |
||||
void slotDestroyed(QObject* obj) { |
||||
TRC; LOG<<_downloads.size(); |
||||
_downloads.erase((QNetworkReply*)obj); |
||||
} |
||||
void slotFinished() { |
||||
TRC; LOG<<_downloads.size(); |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
if (_downloads[reply].error.size()) |
||||
error(_downloads[reply].error); |
||||
_downloads.erase(reply); |
||||
if (_downloads.size()==0) finished(); |
||||
} |
||||
void slotMetaDataChanged() { |
||||
TRC; |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
if (!reply) return; |
||||
LOG<<"Location:"<<reply->header(QNetworkRequest::LocationHeader) |
||||
.toString(); |
||||
LOG<<"Content-Type:"<<reply->header(QNetworkRequest::ContentTypeHeader) |
||||
.toString(); |
||||
LOG<<"Content-Disposition:"<<reply->rawHeader("Content-Disposition"); |
||||
LOG<<"Status:"<<networkError(reply->error()); |
||||
LOG<<"URL:"<<reply->url().toString(); |
||||
LOG<<"File:"<<reply->url().toLocalFile(); |
||||
LOG<<"Path:"<<reply->url().path(); |
||||
metaDataChanged(reply); |
||||
} |
||||
void sslErrors(const QList<QSslError> & errors) { |
||||
TRC; |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
for (QList<QSslError>::const_iterator err(errors.begin()); |
||||
err!=errors.end(); ++err) { |
||||
LOG<<"SSL-Error: "<<(int)err->error()<<": "<<err->errorString(); |
||||
LOG<<"Certificate Issuer: " |
||||
<<"O="<<err->certificate().issuerInfo(QSslCertificate::Organization) |
||||
<<"CN="<<err->certificate().issuerInfo(QSslCertificate::CommonName) |
||||
<<"L="<<err->certificate().issuerInfo(QSslCertificate::LocalityName) |
||||
<<"OU="<<err->certificate().issuerInfo(QSslCertificate::OrganizationalUnitName) |
||||
<<"C="<<err->certificate().issuerInfo(QSslCertificate::CountryName) |
||||
<<"ST="<<err->certificate().issuerInfo(QSslCertificate::StateOrProvinceName); |
||||
LOG<<"Certificate Subject: " |
||||
<<"O="<<err->certificate().subjectInfo(QSslCertificate::Organization) |
||||
<<"CN="<<err->certificate().subjectInfo(QSslCertificate::CommonName) |
||||
<<"L="<<err->certificate().subjectInfo(QSslCertificate::LocalityName) |
||||
<<"OU="<<err->certificate().subjectInfo(QSslCertificate::OrganizationalUnitName) |
||||
<<"C="<<err->certificate().subjectInfo(QSslCertificate::CountryName) |
||||
<<"ST="<<err->certificate().subjectInfo(QSslCertificate::StateOrProvinceName); |
||||
LOG<<"Certificate:\n"<<err->certificate().toPem(); |
||||
switch (err->error()) { |
||||
case QSslError::SelfSignedCertificate: |
||||
case QSslError::SelfSignedCertificateInChain: { |
||||
QSslConfiguration sslConfig |
||||
(QSslConfiguration::defaultConfiguration()); |
||||
QList<QSslCertificate> certs(sslConfig.caCertificates()); |
||||
for (QList<QSslCertificate>::iterator cert(certs.begin()); |
||||
cert!=certs.end(); ++cert) { |
||||
if (err->certificate().subjectInfo(QSslCertificate::CommonName) == |
||||
cert->subjectInfo(QSslCertificate::CommonName)) { |
||||
LOG<<"Found matching CN:" |
||||
<<cert->subjectInfo(QSslCertificate::CommonName); |
||||
if (err->certificate()==*cert) { |
||||
LOG<<"QT-BUG! Certificate matches known certificate"; |
||||
//! @bug work around qt bug (Qt Mac 4.8.2)
|
||||
reply->ignoreSslErrors(errors); |
||||
} else { |
||||
LOG<<"CERTIFICATE ERROR! Certificates are different"; |
||||
} |
||||
} |
||||
} |
||||
} break; |
||||
default:; // ignore
|
||||
} |
||||
_downloads[reply].error += |
||||
tr("<h1>SSL Error</h1>" |
||||
"<dl><dt>URL:</dt><dd>%1</dd>" |
||||
"<dt>Error Code:</dt><dd>%3</dd>" |
||||
"<dt>Error Details:</dt><dd>%2</dd></dl>" |
||||
"<table>" |
||||
"<caption>Certificate Issuer</caption>" |
||||
"<tr><th>Organization:</th><td>%4</td></tr>" |
||||
"<tr><th>Common Name:</th><td>%5</td></tr>" |
||||
"<tr><th>Location:</th><td>%6</td></tr>" |
||||
"<tr><th>Organizational Unit:</th><td>%7</td></tr>" |
||||
"<tr><th>Country:</th><td>%8</td></tr>" |
||||
"<tr><th>State or Provive:</th><td>%9</td></tr>" |
||||
"</table>" |
||||
"<table>" |
||||
"<caption>Certificate Subject</caption>" |
||||
"<tr><th>Organization:</th><td>%10</td></tr>" |
||||
"<tr><th>Common Name:</th><td>%11</td></tr>" |
||||
"<tr><th>Location:</th><td>%12</td></tr>" |
||||
"<tr><th>Organizational Unit:</th><td>%13</td></tr>" |
||||
"<tr><th>Country:</th><td>%14</td></tr>" |
||||
"<tr><th>State or Province:</th><td>%15</td></tr>" |
||||
"</table>") |
||||
.arg(reply->url().toString()) |
||||
.arg(err->errorString()) |
||||
.arg(err->error()) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::Organization)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::CommonName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::LocalityName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::OrganizationalUnitName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::CountryName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::StateOrProvinceName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::Organization)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::CommonName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::LocalityName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::OrganizationalUnitName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::CountryName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::StateOrProvinceName)); |
||||
} |
||||
} |
||||
|
||||
void uploadProgress(qint64 bytesSent, qint64 bytesTotal) { |
||||
//TRC; LOG<<bytesSent<<bytesTotal;
|
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.first |
||||
= bytesSent; |
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.second |
||||
= bytesTotal; |
||||
calcProgress(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
typedef std::pair<qint64, qint64> Progress; |
||||
struct Download { |
||||
Progress progress; |
||||
QString error; |
||||
}; |
||||
typedef std::map<QNetworkReply*, Download> Downloads; |
||||
|
||||
Downloads _downloads; |
||||
}; |
||||
#endif |
@ -1,42 +0,0 @@ |
||||
/*! @file
|
||||
|
||||
@id $Id$ |
||||
*/ |
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef ERRORLOG_HXX |
||||
#define ERRORLOG_HXX |
||||
|
||||
#include <qbrowserlib/log.hxx> |
||||
#include <ui_errorlog.h> |
||||
#include <QtGui/QDialog> |
||||
|
||||
class ErrorLog: public QDialog, protected Ui::ErrorLog { |
||||
public: |
||||
Q_OBJECT; |
||||
Q_SIGNALS: |
||||
void reset(); |
||||
public: |
||||
ErrorLog(QWidget* p): QDialog(p) { |
||||
TRC; |
||||
setupUi(this); |
||||
} |
||||
void append(QString text) { |
||||
TRC; LOG<<text; |
||||
_errors->append(text); |
||||
} |
||||
protected Q_SLOTS: |
||||
void on__buttons_clicked(QAbstractButton* button) { |
||||
TRC; |
||||
switch (_buttons->buttonRole(button)) { |
||||
case QDialogButtonBox::ResetRole: { |
||||
_errors->clear(); |
||||
reset(); |
||||
} break; |
||||
default:; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,341 @@ |
||||
/*! @file
|
||||
|
||||
@id $Id$ |
||||
*/ |
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef __DOWNLOAD_MANAGER_HXX |
||||
#define __DOWNLOAD_MANAGER_HXX |
||||
|
||||
#include <qbrowserlib/log.hxx> |
||||
#include <QtNetwork/QNetworkReply> |
||||
#include <QtNetwork/QSslError> |
||||
#include <QtNetwork/QSslConfiguration> |
||||
#include <map> |
||||
|
||||
#include <cassert> |
||||
|
||||
//! @addtogroup qbrowserlib
|
||||
//! @{
|
||||
namespace qbrowserlib { |
||||
|
||||
class DownloadManager: public QObject { |
||||
|
||||
Q_OBJECT; |
||||
|
||||
public: |
||||
|
||||
//! Append a Network Manager
|
||||
DownloadManager& operator+=(QNetworkAccessManager* n) { |
||||
TRC; |
||||
assert(connect(n, SIGNAL(created(QNetworkReply*)), |
||||
SLOT(add(QNetworkReply*)))); |
||||
return *this; |
||||
} |
||||
|
||||
//! Append a Network Reply
|
||||
DownloadManager& operator+=(QNetworkReply* reply) { |
||||
TRC; |
||||
add(reply); |
||||
return *this; |
||||
} |
||||
|
||||
static QString networkError(QNetworkReply::NetworkError err) { |
||||
TRC_FN; LOG<<err; |
||||
switch (err) { |
||||
case QNetworkReply::NoError: |
||||
return tr("Network connection successful, remote host can be" |
||||
" reached."); |
||||
case QNetworkReply::ConnectionRefusedError: |
||||
return tr("The remote server refused the connection (the server is" |
||||
" not accepting requests)."); |
||||
case QNetworkReply::RemoteHostClosedError: |
||||
return tr("The remote server closed the connection prematurely," |
||||
" before the entire reply was received and processed."); |
||||
case QNetworkReply::HostNotFoundError: |
||||
return tr("The remote host name was not found (invalid hostname)."); |
||||
case QNetworkReply::TimeoutError: |
||||
return tr("The connection to the remote server timed out."); |
||||
case QNetworkReply::OperationCanceledError: |
||||
return tr("The operation was canceled via calls to abort() or" |
||||
" close() before it was finished."); |
||||
case QNetworkReply::SslHandshakeFailedError: |
||||
return tr("The SSL/TLS handshake failed and the encrypted channel" |
||||
" could not be established. See SSL-Errors above."); |
||||
case QNetworkReply::ProxyConnectionRefusedError: |
||||
return tr("The connection to the proxy server was refused (the" |
||||
" proxy server is not accepting requests)."); |
||||
case QNetworkReply::ProxyConnectionClosedError: |
||||
return tr("The proxy server closed the connection prematurely," |
||||
" before the entire reply was received and processed."); |
||||
case QNetworkReply::ProxyNotFoundError: |
||||
return tr("The proxy host name was not found (invalid proxy" |
||||
" hostname)."); |
||||
case QNetworkReply::ProxyTimeoutError: |
||||
return tr("The connection to the proxy timed out or the proxy did" |
||||
" not reply in time to the request sent."); |
||||
case QNetworkReply::ProxyAuthenticationRequiredError: |
||||
return tr("The proxy requires authentication in order to honour the" |
||||
" request but did not accept any credentials offered" |
||||
" (if any)."); |
||||
case QNetworkReply::ContentAccessDenied: |
||||
return tr("The access to the remote content was denied (similar to" |
||||
" HTTP error 401)."); |
||||
case QNetworkReply::ContentOperationNotPermittedError: |
||||
return tr("The operation requested on the remote content is not" |
||||
" permitted."); |
||||
case QNetworkReply::ContentNotFoundError: |
||||
return tr("The remote content was not found at the server (similar" |
||||
" to HTTP error 404)."); |
||||
case QNetworkReply::AuthenticationRequiredError: |
||||
return tr("The remote server requires authentication to serve the" |
||||
" content but the credentials provided were not accepted" |
||||
" (if any)."); |
||||
case QNetworkReply::ProtocolUnknownError: |
||||
return tr("The Network Access API cannot honor the request because" |
||||
" the protocol is not known."); |
||||
case QNetworkReply::ProtocolInvalidOperationError: |
||||
return tr("The requested operation is invalid for this protocol."); |
||||
case QNetworkReply::UnknownNetworkError: |
||||
return tr("An unknown network-related error was detected."); |
||||
case QNetworkReply::UnknownProxyError: |
||||
return tr("An unknown proxy-related error was detected."); |
||||
case QNetworkReply::UnknownContentError: |
||||
return tr("An unknonwn error related to the remote content was" |
||||
" detected."); |
||||
case QNetworkReply::ProtocolFailure: |
||||
return tr("A breakdown in protocol was detected (parsing error," |
||||
" invalid or unexpected responses, etc.)."); |
||||
default: |
||||
return tr("Unknown network error (code: %1).").arg(err); |
||||
} |
||||
} |
||||
|
||||
Q_SIGNALS: |
||||
|
||||
void progress(qint64 done, qint64 total); |
||||
void started(); |
||||
void finished(); |
||||
void error(QString); |
||||
void metaDataChanged(QNetworkReply*); |
||||
|
||||
public Q_SLOTS: |
||||
|
||||
void add(QNetworkReply* reply) { |
||||
TRC; LOG<<_downloads.size()<<reply->url().toString(); |
||||
LOG<<reply; |
||||
_downloads[reply].progress = Progress(0, 0); |
||||
assert(connect(reply, SIGNAL(downloadProgress(qint64, qint64)), |
||||
SLOT(downloadProgress(qint64, qint64)))); |
||||
assert(connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), |
||||
SLOT(error(QNetworkReply::NetworkError)))); |
||||
assert(connect(reply, SIGNAL(destroyed(QObject*)), |
||||
SLOT(slotDestroyed(QObject*)))); |
||||
assert(connect(reply, SIGNAL(finished()), |
||||
SLOT(slotFinished()))); |
||||
assert(connect(reply, SIGNAL(metaDataChanged()), |
||||
SLOT(slotMetaDataChanged()))); |
||||
assert(connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)), |
||||
SLOT(sslErrors(const QList<QSslError>&)))); |
||||
assert(connect(reply, SIGNAL(uploadProgress(qint64, qint64)), |
||||
SLOT(uploadProgress(qint64, qint64)))); |
||||
if (_downloads.size()==1) started(); |
||||
} |
||||
|
||||
void abort() { |
||||
while (_downloads.size()) _downloads.begin()->first->abort(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
void calcProgress() { |
||||
//TRC;
|
||||
qint64 done(0); |
||||
qint64 total(0); |
||||
for (Downloads::iterator it(_downloads.begin()); |
||||
it!=_downloads.end(); ++it) { |
||||
done += it->second.progress.first; |
||||
total += it->second.progress.second; |
||||
} |
||||
progress(done, total); |
||||
} |
||||
|
||||
private Q_SLOTS: |
||||
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { |
||||
//TRC; LOG<<bytesReceived<<bytesTotal;
|
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.first |
||||
= bytesReceived; |
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.second |
||||
= bytesTotal; |
||||
calcProgress(); |
||||
} |
||||
void error(QNetworkReply::NetworkError code) { |
||||
TRC; LOG<<"Status:"<<networkError(code); |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
_downloads[reply].error += |
||||
tr("<h1>Network Error</h1>" |
||||
"<dl><dt>URL:</dt><dd>%1</dd>" |
||||
"<dt>Error Code:</dt><dd>%3</dd>" |
||||
"<dt>Error Details:</dt><dd>%2</dd></dl>") |
||||
.arg(reply->url().toString()) |
||||
.arg(networkError(code)) |
||||
.arg(code); |
||||
} |
||||
void slotDestroyed(QObject* obj) { |
||||
TRC; LOG<<_downloads.size(); |
||||
_downloads.erase((QNetworkReply*)obj); |
||||
} |
||||
void slotFinished() { |
||||
TRC; LOG<<_downloads.size(); |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
if (_downloads[reply].error.size()) |
||||
error(_downloads[reply].error); |
||||
_downloads.erase(reply); |
||||
if (_downloads.size()==0) finished(); |
||||
} |
||||
void slotMetaDataChanged() { |
||||
TRC; |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
if (!reply) return; |
||||
LOG<<"Location:"<<reply->header(QNetworkRequest::LocationHeader) |
||||
.toString(); |
||||
LOG<<"Content-Type:"<<reply->header(QNetworkRequest::ContentTypeHeader) |
||||
.toString(); |
||||
LOG<<"Content-Disposition:"<<reply->rawHeader("Content-Disposition"); |
||||
LOG<<"Status:"<<networkError(reply->error()); |
||||
LOG<<"URL:"<<reply->url().toString(); |
||||
LOG<<"File:"<<reply->url().toLocalFile(); |
||||
LOG<<"Path:"<<reply->url().path(); |
||||
metaDataChanged(reply); |
||||
} |
||||
void sslErrors(const QList<QSslError> & errors) { |
||||
TRC; |
||||
QNetworkReply* reply(qobject_cast<QNetworkReply*>(sender())); |
||||
for (QList<QSslError>::const_iterator err(errors.begin()); |
||||
err!=errors.end(); ++err) { |
||||
LOG<<"SSL-Error: "<<(int)err->error()<<": "<<err->errorString(); |
||||
LOG<<"Certificate Issuer: " |
||||
<<"O=" |
||||
<<err->certificate().issuerInfo(QSslCertificate::Organization) |
||||
<<"CN="<<err->certificate().issuerInfo(QSslCertificate::CommonName) |
||||
<<"L=" |
||||
<<err->certificate().issuerInfo(QSslCertificate::LocalityName) |
||||
<<"OU=" |
||||
<<err->certificate() |
||||
.issuerInfo(QSslCertificate::OrganizationalUnitName) |
||||
<<"C="<<err->certificate().issuerInfo(QSslCertificate::CountryName) |
||||
<<"ST=" |
||||
<<err->certificate() |
||||
.issuerInfo(QSslCertificate::StateOrProvinceName); |
||||
LOG<<"Certificate Subject: " |
||||
<<"O=" |
||||
<<err->certificate().subjectInfo(QSslCertificate::Organization) |
||||
<<"CN=" |
||||
<<err->certificate().subjectInfo(QSslCertificate::CommonName) |
||||
<<"L=" |
||||
<<err->certificate().subjectInfo(QSslCertificate::LocalityName) |
||||
<<"OU=" |
||||
<<err->certificate() |
||||
.subjectInfo(QSslCertificate::OrganizationalUnitName) |
||||
<<"C=" |
||||
<<err->certificate().subjectInfo(QSslCertificate::CountryName) |
||||
<<"ST=" |
||||
<<err->certificate() |
||||
.subjectInfo(QSslCertificate::StateOrProvinceName); |
||||
LOG<<"Certificate:\n"<<err->certificate().toPem(); |
||||
switch (err->error()) { |
||||
case QSslError::SelfSignedCertificate: |
||||
case QSslError::SelfSignedCertificateInChain: { |
||||
QSslConfiguration sslConfig |
||||
(QSslConfiguration::defaultConfiguration()); |
||||
QList<QSslCertificate> certs(sslConfig.caCertificates()); |
||||
for (QList<QSslCertificate>::iterator cert(certs.begin()); |
||||
cert!=certs.end(); ++cert) { |
||||
if (err->certificate().subjectInfo(QSslCertificate::CommonName) |
||||
== cert->subjectInfo(QSslCertificate::CommonName)) { |
||||
LOG<<"Found matching CN:" |
||||
<<cert->subjectInfo(QSslCertificate::CommonName); |
||||
if (err->certificate()==*cert) { |
||||
LOG<<"QT-BUG! Certificate matches known certificate"; |
||||
//! @bug work around qt bug (Qt Mac 4.8.2)
|
||||
reply->ignoreSslErrors(errors); |
||||
} else { |
||||
LOG<<"CERTIFICATE ERROR! Certificates are different"; |
||||
} |
||||
} |
||||
} |
||||
} break; |
||||
default:; // ignore
|
||||
} |
||||
_downloads[reply].error += |
||||
tr("<h1>SSL Error</h1>" |
||||
"<dl><dt>URL:</dt><dd>%1</dd>" |
||||
"<dt>Error Code:</dt><dd>%3</dd>" |
||||
"<dt>Error Details:</dt><dd>%2</dd></dl>" |
||||
"<table>" |
||||
"<caption>Certificate Issuer</caption>" |
||||
"<tr><th>Organization:</th><td>%4</td></tr>" |
||||
"<tr><th>Common Name:</th><td>%5</td></tr>" |
||||
"<tr><th>Location:</th><td>%6</td></tr>" |
||||
"<tr><th>Organizational Unit:</th><td>%7</td></tr>" |
||||
"<tr><th>Country:</th><td>%8</td></tr>" |
||||
"<tr><th>State or Provive:</th><td>%9</td></tr>" |
||||
"</table>" |
||||
"<table>" |
||||
"<caption>Certificate Subject</caption>" |
||||
"<tr><th>Organization:</th><td>%10</td></tr>" |
||||
"<tr><th>Common Name:</th><td>%11</td></tr>" |
||||
"<tr><th>Location:</th><td>%12</td></tr>" |
||||
"<tr><th>Organizational Unit:</th><td>%13</td></tr>" |
||||
"<tr><th>Country:</th><td>%14</td></tr>" |
||||
"<tr><th>State or Province:</th><td>%15</td></tr>" |
||||
"</table>") |
||||
.arg(reply->url().toString()) |
||||
.arg(err->errorString()) |
||||
.arg(err->error()) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::Organization)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::CommonName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::LocalityName)) |
||||
.arg(err->certificate() |
||||
.issuerInfo(QSslCertificate::OrganizationalUnitName)) |
||||
.arg(err->certificate().issuerInfo(QSslCertificate::CountryName)) |
||||
.arg(err->certificate() |
||||
.issuerInfo(QSslCertificate::StateOrProvinceName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::Organization)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::CommonName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::LocalityName)) |
||||
.arg(err->certificate() |
||||
.subjectInfo(QSslCertificate::OrganizationalUnitName)) |
||||
.arg(err->certificate().subjectInfo(QSslCertificate::CountryName)) |
||||
.arg(err->certificate() |
||||
.subjectInfo(QSslCertificate::StateOrProvinceName)); |
||||
} |
||||
} |
||||
|
||||
void uploadProgress(qint64 bytesSent, qint64 bytesTotal) { |
||||
//TRC; LOG<<bytesSent<<bytesTotal;
|
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.first |
||||
= bytesSent; |
||||
_downloads[qobject_cast<QNetworkReply*>(sender())].progress.second |
||||
= bytesTotal; |
||||
calcProgress(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
typedef std::pair<qint64, qint64> Progress; |
||||
struct Download { |
||||
Progress progress; |
||||
QString error; |
||||
}; |
||||
typedef std::map<QNetworkReply*, Download> Downloads; |
||||
|
||||
Downloads _downloads; |
||||
}; |
||||
|
||||
}
|
||||
//! @}
|
||||
|
||||
#endif |
@ -0,0 +1,59 @@ |
||||
/*! @file
|
||||
|
||||
@id $Id$ |
||||
*/ |
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef ERRORLOG_HXX |
||||
#define ERRORLOG_HXX |
||||
|
||||
#include <qbrowserlib/log.hxx> |
||||
#include <qbrowserlib/ui_errorlog.h> |
||||
#include <QtGui/QDialog> |
||||
|
||||
//! @addtogroup qbrowserlib
|
||||
//! @{
|
||||
|
||||
namespace qbrowserlib { |
||||
|
||||
//! Collect and Show Errors
|
||||
/*! Singleton */ |
||||
class ErrorLog: public QDialog, protected Ui::ErrorLog { |
||||
Q_OBJECT; |
||||
Q_SIGNALS: |
||||
void reset(); |
||||
public: |
||||
//! Singleton
|
||||
static ErrorLog& instance(QWidget* p=0) { |
||||
static ErrorLog _instance(p); |
||||
return _instance; |
||||
} |
||||
private: // singleton
|
||||
ErrorLog(const ErrorLog&); |
||||
ErrorLog(QWidget* p): QDialog(p) { |
||||
TRC; |
||||
setupUi(this); |
||||
} |
||||
public: |
||||
void append(QString text) { |
||||
TRC; LOG<<text; |
||||
_errors->append(text); |
||||
} |
||||
protected Q_SLOTS: |
||||
void on__buttons_clicked(QAbstractButton* button) { |
||||
TRC; |
||||
switch (_buttons->buttonRole(button)) { |
||||
case QDialogButtonBox::ResetRole: { |
||||
_errors->clear(); |
||||
reset(); |
||||
} break; |
||||
default:; |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
|
||||
//! @}
|
||||
|
||||
#endif |
Loading…
Reference in new issue