1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include "webview.h"
#include <QWebFrame>
#include <QNetworkReply>
#include <QMessageBox>
#include <QTimer>
#include <QUrlQuery>
#include <QCryptographicHash>
#include <QCursor>
#include <QWebHistory>
#include <QNetworkCookieJar>
#include <QWebElement>
#include <QRegularExpression>
#include <QWebPage>
// Override user-agent to make it appear mobile
class UaWebPage : public QWebPage
{
public:
static QRegularExpression re;
QString userAgentForUrl(const QUrl &url) const override {
return QWebPage::userAgentForUrl(url).replace(re, "Mobile \\1");
}
};
QRegularExpression UaWebPage::re("(\\S+)$");
WebView::WebView(QWidget* parent)
: QWebView(parent),
_timerAbortMessage(new QTimer(this)),
_abortedDownload(false),
_timerReset(new QTimer(this))
{
this->setPage(new UaWebPage);
_timerAbortMessage->setSingleShot(true);
_timerReset->setSingleShot(true);
connect(page(), SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested()));
page()->setForwardUnsupportedContent(true);
connect(page(), SIGNAL(unsupportedContent(QNetworkReply*)),this,SLOT(unsupportedContent(QNetworkReply*)));
connect(page(), SIGNAL(downloadRequested(QNetworkRequest)),this,SLOT(downloadRequest(QNetworkRequest)));
connect(_timerAbortMessage, &QTimer::timeout, this, &WebView::downloadDeniedMessage);
connect(_timerReset, &QTimer::timeout, this, [this]() {
emit triggerReset(tr("Inactivity Timeout"));
this->stop();
this->page()->mainFrame()->setContent("");
});
connect(this, &QWebView::loadFinished, this, &WebView::onLoadFinished);
}
void WebView::windowCloseRequested()
{
// If we have an old URL stored on the stack, navigate back to it, otherwise we return and nothing happens
if (_urls.empty())
return;
QUrl url = _urls.pop();
page()->mainFrame()->load(url);
}
QWebView* WebView::createWindow(QWebPage::WebWindowType)
{
// Remember current URL, then return the current Web View so no new window opens
_urls.push(this->url());
return this;
}
void WebView::unsupportedContent(QNetworkReply* rep)
{
_abortedDownload = true;
rep->abort();
rep->deleteLater();
_timerAbortMessage->start(1);
}
void WebView::downloadRequest(QNetworkRequest)
{
_timerAbortMessage->start(1);
}
void WebView::downloadDeniedMessage()
{
QMessageBox::warning(this->parentWidget(), QString::fromUtf8("Denied"),
QString::fromUtf8("The requested action triggered a download, which is not allowed.\n\n"
"Diese Aktion löst einen Download aus, was nicht erlaubt ist."));
}
void WebView::onLoadFinished(bool ok)
{
if (_abortedDownload || !ok) {
_abortedDownload = false;
_timerReset->start(10000);
return;
}
auto user = this->page()->mainFrame()->documentElement().findFirst("#bwlp-username");
auto pass = this->page()->mainFrame()->documentElement().findFirst("#bwlp-password");
auto err = this->page()->mainFrame()->documentElement().findFirst("#bwlp-error");
if (!user.isNull() && !pass.isNull()) {
emit startAuthentication(user.toPlainText(), "shib=" + _token + pass.toPlainText());
} else if (!err.isNull()) {
emit triggerReset(err.toPlainText());
this->stop();
this->page()->mainFrame()->setContent("");
} else {
_timerReset->start(60000);
}
}
void WebView::reset(const QString baseUrl)
{
QUrl url(baseUrl);
QUrlQuery q(url.query());
q.addQueryItem("action", "browser");
QByteArray input;
input.append((const char*)this, sizeof(*this));
input.append(QString().sprintf("%d %d", QCursor::pos().x(), QCursor::pos().y()));
input.append(QString::number(QDateTime::currentMSecsSinceEpoch()));
_token = QCryptographicHash::hash(input, QCryptographicHash::Md5).chopped(8).toHex();
q.addQueryItem("token", _token);
url.setQuery(q);
_urls.clear();
this->page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar);
this->history()->clear();
this->setUrl(url);
_timerAbortMessage->stop();
_timerReset->stop();
}
|