summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2021-08-05 10:51:39 +0200
committerSimon Rettberg2021-08-05 10:51:39 +0200
commitccd88b7fa33fc27e3d71b57f59dea55ed7430d6e (patch)
tree35edaff0695b7ed47a3f648f8295ea944935f0a0
parentPrefix usernames that start with a digit with _x_ (diff)
downloadslxgreeter-ccd88b7fa33fc27e3d71b57f59dea55ed7430d6e.tar.gz
slxgreeter-ccd88b7fa33fc27e3d71b57f59dea55ed7430d6e.tar.xz
slxgreeter-ccd88b7fa33fc27e3d71b57f59dea55ed7430d6e.zip
Add shibboleth login via browser
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/loginform.cpp168
-rw-r--r--src/loginform.h17
-rw-r--r--src/loginform.ui204
-rw-r--r--src/mainwindow.cpp11
-rw-r--r--src/mainwindow.h1
-rw-r--r--src/settings.h6
-rw-r--r--src/webview.cpp109
-rw-r--r--src/webview.h44
-rw-r--r--src/x11util.h2
10 files changed, 491 insertions, 74 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 28d953f..3b6b7be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,7 @@ set(CMAKE_AUTOMOC ON)
file(GLOB SRCS src/*.cpp src/*.c)
file(GLOB UIS src/*.ui)
-FIND_PACKAGE(Qt5 COMPONENTS Widgets X11Extras Svg Network REQUIRED)
+FIND_PACKAGE(Qt5 COMPONENTS Widgets X11Extras Svg Network WebKitWidgets REQUIRED)
FIND_PACKAGE(X11 REQUIRED)
IF(X11_Xscreensaver_FOUND)
@@ -56,6 +56,7 @@ target_link_libraries ( qt-lightdm-greeter
Qt5::X11Extras
Qt5::Svg
Qt5::Network
+ Qt5::WebKitWidgets
${LIGHTDM_QT_LIBRARIES}
${X11_LIBRARIES}
${X11_Xscreensaver_LIB}
diff --git a/src/loginform.cpp b/src/loginform.cpp
index a53c7ab..eecf34b 100644
--- a/src/loginform.cpp
+++ b/src/loginform.cpp
@@ -8,13 +8,15 @@
* Please refer to the LICENSE file for a copy of the license.
*/
+#include <QTextStream>
+
+#include "x11util.h"
#include "loginform.h"
#include "ui_loginform.h"
#include "settings.h"
#include "global.h"
#include "namereplace.h"
#include "loginrpc.h"
-#include "x11util.h"
#undef KeyPress
#undef KeyRelease
#undef FocusIn
@@ -29,6 +31,9 @@
#include <QListView>
#include <QSvgRenderer>
#include <QX11Info>
+#include "webview.h"
+#include <QSizePolicy>
+
#include <iostream>
void createSimpleBackground();
@@ -36,10 +41,19 @@ void createSimpleBackground();
LoginForm::LoginForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::LoginForm),
+ browser(nullptr),
clearMsg(false),
capsOn(-1)
{
ui->setupUi(this);
+ origSize = shibSize = sizeHint();
+ if (this->parentWidget() != nullptr) {
+ shibSize.setWidth(qMin(1000, int(this->parentWidget()->width() * .75f) ));
+ shibSize.setHeight(qMin(700, int(this->parentWidget()->height() * .75f) ));
+ } else {
+ shibSize.rwidth() += 350;
+ shibSize.rheight() += 250;
+ }
initialize();
int port = Settings::rpcPort();
if (port != 0) {
@@ -49,14 +63,14 @@ LoginForm::LoginForm(QWidget *parent) :
return;
ui->userInput->setText(username);
ui->passwordInput->setText(password);
- this->startAuthentication();
+ this->startFormBasedAuthentication();
});
}
+ connect(ui->loginChooser, &QStackedWidget::currentChanged, this, &LoginForm::setBrowserSize);
}
LoginForm::~LoginForm()
{
-
delete ui;
}
@@ -69,14 +83,45 @@ void LoginForm::setFocus(Qt::FocusReason reason)
}
}
+void LoginForm::resizeEvent(QResizeEvent *e)
+{
+ if (this->parentWidget() != nullptr) {
+ shibSize.setWidth(qMin(1000, int(this->parentWidget()->width() * .75f) ));
+ shibSize.setHeight(qMin(700, int(this->parentWidget()->height() * .75f) ));
+ }
+ const QSize *size = nullptr;
+ if (ui->loginChooser->currentWidget() == ui->shibPage) {
+ size = &shibSize;
+ } else {
+ size = &origSize;
+ }
+ if (*size != e->size()) {
+ e->ignore();
+ setMinimumSize(*size);
+ setFixedSize(*size);
+ setBaseSize(*size);
+ int pw = 0, ph = 0;
+ if (this->parentWidget() != nullptr) {
+ this->parentWidget()->pos();
+ pw = (this->parentWidget()->width() - size->width()) / 2;
+ ph = (this->parentWidget()->height() - size->height()) / 2;
+ }
+ setGeometry(pw, pw, size->width(), size->height());
+ emit resized();
+ setBrowserSize();
+ return;
+ }
+ QWidget::resizeEvent(e);
+}
void LoginForm::initialize()
{
QString path = Settings::miniIconFile();
QPixmap pixmap;
if (!path.isEmpty()) {
+ // Try to get the default size, in case this is an SVG
QSize size = QSvgRenderer(path).defaultSize();
- if (!size.isValid()) {
+ if (!size.isValid()) { // if not, use maximum of destination
size = ui->iconLabel->maximumSize();
} else {
size = size.boundedTo(ui->iconLabel->maximumSize()).expandedTo(ui->iconLabel->minimumSize());
@@ -132,13 +177,38 @@ void LoginForm::initialize()
if (!Settings::guestSessionStartButtonText().isEmpty()) {
ui->guestStartButton->setText(Settings::guestSessionStartButtonText());
}
- connect(ui->loginButton, &QAbstractButton::released, this, [this]() {
- ui->loginChooser->setCurrentWidget(ui->loginPage);
- ui->userInput->setFocus();
- });
connect(ui->guestButton, &QAbstractButton::released, this, [this]() {
ui->loginChooser->setCurrentWidget(ui->guestPage);
});
+ } else {
+ ui->guestButton->hide();
+ }
+
+ if (Settings::shibSessionEnabled()) {
+ connect(ui->shibButton, &QAbstractButton::released, this, [this]() {
+ if (browser == nullptr) {
+ browser = new WebView(ui->shibPage);
+ ui->verticalLayout_5->addWidget(browser);
+ connect(browser, &WebView::triggerReset, [this](const QString &message) {
+ this->showMessage(message, true);
+ ui->loginChooser->setCurrentWidget(ui->welcomePage);
+ });
+ connect(browser, &WebView::startAuthentication, this, &LoginForm::startAuthAs);
+ }
+ browser->reset(Settings::shibUrl());
+ ui->loginChooser->setCurrentWidget(ui->shibPage);
+ });
+ // Reduce minimum size of hostname/icon bar
+ ui->frame->setMinimumSize(10, 30);
+ ui->frame->setMaximumSize(99999, ui->iconLabel->height());
+ ui->frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
+ ui->loginChooser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
+ } else {
+ ui->shibButton->hide();
+ }
+
+ if (Settings::guestSessionEnabled() || Settings::shibSessionEnabled()) {
+ ui->loginChooser->setCurrentWidget(ui->welcomePage);
connect(ui->backButton, &QAbstractButton::released, this, [this]() {
resetForm();
});
@@ -149,7 +219,10 @@ void LoginForm::initialize()
ui->backButton->show();
}
});
- ui->loginChooser->setCurrentWidget(ui->welcomePage);
+ connect(ui->loginButton, &QAbstractButton::released, this, [this]() {
+ ui->loginChooser->setCurrentWidget(ui->loginPage);
+ ui->userInput->setFocus();
+ });
} else {
ui->loginChooser->setCurrentWidget(ui->loginPage);
}
@@ -208,19 +281,12 @@ void LoginForm::checkCaps()
}
}
-void LoginForm::startAuthentication()
+void LoginForm::startFormBasedAuthentication()
{
QString username(ui->userInput->text().trimmed());
NameReplace::replace(username);
std::cerr << "Logging in as " << username.toStdString() << std::endl;
- if (Global::testMode()) {
- showMessage(QLatin1String("Test mode..."), true);
- return;
- }
- if (Global::greeter()->inAuthentication()) {
- Global::greeter()->cancelAuthentication();
- }
if (ui->userInput->text().isEmpty()) {
ui->userInput->setFocus();
return;
@@ -229,20 +295,34 @@ void LoginForm::startAuthentication()
ui->passwordInput->setFocus();
return;
}
+ startAuthAs(username, ui->passwordInput->text());
+ ui->passwordInput->setText("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+ ui->passwordInput->clear();
+}
+void LoginForm::startAuthAs(const QString &user, const QString &pass)
+{
+ if (Global::testMode()) {
+ showMessage(QLatin1String("Test mode..."), true);
+ return;
+ }
+ if (Global::greeter()->inAuthentication()) {
+ Global::greeter()->cancelAuthentication();
+ }
showMessage(tr("Logging in..."), false);
clearMsg = false;
- ui->userInput->setEnabled(false);
- ui->passwordInput->setEnabled(false);
+ enableInputs(false);
cancelLoginTimer.start();
- Global::greeter()->authenticate(username);
+ password = pass;
+ Global::greeter()->authenticate(user);
}
void LoginForm::onPrompt(QString prompt, QLightDM::Greeter::PromptType /* promptType */)
{
std::cerr << "Prompt: " << prompt.toStdString() << std::endl;
- Global::greeter()->respond(ui->passwordInput->text());
- ui->passwordInput->clear();
+ Global::greeter()->respond(password);
+ password = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ password.clear();
}
void LoginForm::leaveDropDownActivated(int index)
@@ -298,8 +378,7 @@ void LoginForm::cancelLogin()
}
cancelLoginTimer.stop();
ui->passwordInput->clear();
- ui->userInput->setEnabled(true);
- ui->passwordInput->setEnabled(true);
+ enableInputs(true);
if (!clearMsg) {
showMessage(tr("Login failed"), true);
} else {
@@ -309,6 +388,17 @@ void LoginForm::cancelLogin()
clearMsg = true;
}
+void LoginForm::enableInputs(bool enable)
+{
+ ui->userInput->setEnabled(enable);
+ ui->passwordInput->setEnabled(enable);
+ ui->backButton->setEnabled(enable);
+ ui->guestButton->setEnabled(enable);
+ if (browser != nullptr) {
+ browser->setEnabled(enable);
+ }
+}
+
void LoginForm::showMessage(QString message, bool error)
{
hideMessageTimer.stop();
@@ -343,7 +433,7 @@ void LoginForm::keyPressEvent(QKeyEvent *event)
return;
}
if (ui->passwordInput->hasFocus()) {
- startAuthentication();
+ startFormBasedAuthentication();
return;
}
}
@@ -356,8 +446,9 @@ void LoginForm::keyPressEvent(QKeyEvent *event)
void LoginForm::resetForm()
{
- if (Settings::guestSessionEnabled())
+ if (Settings::guestSessionEnabled() || Settings::shibSessionEnabled()) {
ui->loginChooser->setCurrentWidget(ui->welcomePage);
+ }
ui->passwordInput->clear();
ui->userInput->clear();
ui->userInput->setFocus();
@@ -370,3 +461,28 @@ bool LoginForm::eventFilter(QObject *object, QEvent *event)
}
return false;
}
+
+void LoginForm::setBrowserSize()
+{
+ auto s = ui->shibPage->size();
+ auto *f = &shibSize;
+ if (ui->loginChooser->currentWidget() != ui->shibPage) {
+ f = &origSize;
+ s = QSize(50, 50);
+ }
+ if (browser != nullptr) {
+ browser->setFixedSize(s);
+ browser->setGeometry(QRect(QPoint(0, 0), s));
+ }
+ QTimer::singleShot(10, [=]() {
+ int pw = 0, ph = 0;
+ if (this->parentWidget() != nullptr) {
+ this->parentWidget()->pos();
+ pw = (this->parentWidget()->width() - f->width()) / 2;
+ ph = (this->parentWidget()->height() - f->height()) / 2;
+ }
+ this->resize(*f);
+ this->setFixedSize(*f);
+ this->setGeometry(pw, ph, f->width(), f->height());
+ });
+}
diff --git a/src/loginform.h b/src/loginform.h
index 79a862e..9f65194 100644
--- a/src/loginform.h
+++ b/src/loginform.h
@@ -26,6 +26,8 @@ namespace Ui
class LoginForm;
}
+class WebView;
+
class LoginForm : public QWidget
{
Q_OBJECT
@@ -36,17 +38,25 @@ public:
virtual void setFocus(Qt::FocusReason reason);
public slots:
- void startAuthentication();
+ void startFormBasedAuthentication();
void leaveDropDownActivated(int index);
void onPrompt(QString prompt, QLightDM::Greeter::PromptType promptType);
void onMessage(QString prompt, QLightDM::Greeter::MessageType messageType);
void onAuthenticationComplete();
void cancelLogin();
void hideMessage();
+ void startAuthAs(const QString &user, const QString &pass);
+
+private slots:
+ void setBrowserSize();
+
+signals:
+ void resized();
protected:
virtual void keyPressEvent(QKeyEvent *event) override;
virtual bool eventFilter(QObject *object, QEvent *event) override;
+ virtual void resizeEvent(QResizeEvent *) override;
private:
void initialize();
@@ -56,6 +66,7 @@ private:
void setCurrentSession(QString session);
void showMessage(QString message, bool error);
void resetForm();
+ void enableInputs(bool enable);
Ui::LoginForm *ui;
QMap<int, void (QLightDM::PowerInterface::*)()> powerSlots;
@@ -63,6 +74,10 @@ private:
QTimer cancelLoginTimer;
QTimer hideMessageTimer;
QTimer resetFormTimer;
+ QString password;
+ QSize shibSize, origSize;
+
+ WebView *browser;
bool clearMsg;
int capsOn;
diff --git a/src/loginform.ui b/src/loginform.ui
index fcf7f6a..587c0d0 100644
--- a/src/loginform.ui
+++ b/src/loginform.ui
@@ -7,11 +7,11 @@
<x>0</x>
<y>0</y>
<width>386</width>
- <height>296</height>
+ <height>316</height>
</rect>
</property>
<property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -100,7 +100,13 @@ QComboBox QAbstractItemView::item {
<property name="minimumSize">
<size>
<width>0</width>
- <height>50</height>
+ <height>45</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>128</height>
</size>
</property>
<property name="frameShape">
@@ -130,7 +136,7 @@ QComboBox QAbstractItemView::item {
<property name="minimumSize">
<size>
<width>0</width>
- <height>60</height>
+ <height>30</height>
</size>
</property>
<property name="maximumSize">
@@ -173,7 +179,7 @@ QComboBox QAbstractItemView::item {
<property name="minimumSize">
<size>
<width>10</width>
- <height>50</height>
+ <height>30</height>
</size>
</property>
<property name="maximumSize">
@@ -215,7 +221,7 @@ QComboBox QAbstractItemView::item {
<property name="bottomMargin">
<number>0</number>
</property>
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QPushButton" name="guestButton">
<property name="minimumSize">
<size>
@@ -235,7 +241,7 @@ QComboBox QAbstractItemView::item {
</property>
</widget>
</item>
- <item row="0" column="0">
+ <item row="1" column="0">
<widget class="QPushButton" name="loginButton">
<property name="minimumSize">
<size>
@@ -255,6 +261,52 @@ QComboBox QAbstractItemView::item {
</property>
</widget>
</item>
+ <item row="0" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="0">
+ <widget class="QPushButton" name="shibButton">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Shibboleth-Login</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="loginPage">
@@ -272,7 +324,7 @@ QComboBox QAbstractItemView::item {
<number>0</number>
</property>
<item row="1" column="0">
- <widget class="QLineEdit" name="passwordInput">
+ <widget class="QLineEdit" name="userInput">
<property name="minimumSize">
<size>
<width>350</width>
@@ -293,28 +345,29 @@ QComboBox QAbstractItemView::item {
<bold>true</bold>
</font>
</property>
- <property name="text">
- <string/>
- </property>
<property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ <enum>QLineEdit::Normal</enum>
</property>
<property name="placeholderText">
- <string>password</string>
- </property>
- <property name="margin" stdset="0">
- <number>0</number>
- </property>
- <property name="indent" stdset="0">
- <number>10</number>
+ <string>user id</string>
</property>
</widget>
</item>
<item row="0" column="0">
- <widget class="QLineEdit" name="userInput">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLineEdit" name="passwordInput">
<property name="minimumSize">
<size>
<width>350</width>
@@ -335,14 +388,39 @@ QComboBox QAbstractItemView::item {
<bold>true</bold>
</font>
</property>
+ <property name="text">
+ <string/>
+ </property>
<property name="echoMode">
- <enum>QLineEdit::Normal</enum>
+ <enum>QLineEdit::Password</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="placeholderText">
- <string>user id</string>
+ <string>password</string>
+ </property>
+ <property name="margin" stdset="0">
+ <number>0</number>
+ </property>
+ <property name="indent" stdset="0">
+ <number>10</number>
</property>
</widget>
</item>
+ <item row="3" column="0">
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="guestPage">
@@ -360,9 +438,9 @@ QComboBox QAbstractItemView::item {
<number>0</number>
</property>
<item row="1" column="0">
- <widget class="QPushButton" name="guestStartButton">
+ <widget class="QLabel" name="guestStartLabel">
<property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -370,25 +448,30 @@ QComboBox QAbstractItemView::item {
<property name="minimumSize">
<size>
<width>0</width>
- <height>50</height>
+ <height>45</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
- <weight>75</weight>
- <bold>true</bold>
+ <italic>true</italic>
</font>
</property>
<property name="text">
- <string>Starten einer Gast-Sitzung</string>
+ <string>Wenn Sie sich als Gast einloggen, dürfen Sie nur die Webseiten der Universtität Freiburg besuchen.</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
</property>
</widget>
</item>
- <item row="0" column="0">
- <widget class="QLabel" name="guestStartLabel">
+ <item row="2" column="0">
+ <widget class="QPushButton" name="guestStartButton">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -396,28 +479,65 @@ QComboBox QAbstractItemView::item {
<property name="minimumSize">
<size>
<width>0</width>
- <height>45</height>
+ <height>50</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
- <italic>true</italic>
+ <weight>75</weight>
+ <bold>true</bold>
</font>
</property>
<property name="text">
- <string>Wenn Sie sich als Gast einloggen, dürfen Sie nur die Webseiten der Universtität Freiburg besuchen.</string>
+ <string>Starten einer Gast-Sitzung</string>
</property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- <property name="wordWrap">
- <bool>true</bool>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
</property>
- </widget>
+ </spacer>
+ </item>
+ <item row="3" column="0">
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</widget>
+ <widget class="QWidget" name="shibPage">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ </layout>
+ </widget>
</widget>
</item>
<item>
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 2a56fbc..95d74de 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -55,6 +55,7 @@ MainWindow::MainWindow(bool primary, int screen, const QRect &screenRect, QWidge
int centerX = screenRect.width()/2 + screenRect.x();
int centerY = screenRect.height()/2 + screenRect.y();
QCursor::setPos(centerX, centerY);
+ connect(m_LoginForm, &LoginForm::resized, this, &MainWindow::reLayout);
}
// Banner
@@ -80,6 +81,11 @@ void MainWindow::resizeEvent(QResizeEvent *event)
QWidget::resizeEvent(event);
m_ScreenRect = QRect(this->pos(), event->size());
setBackground();
+ reLayout();
+}
+
+void MainWindow::reLayout()
+{
/*
* Everything is layed out manually here, since I don't know how to represent the size constraints
* and interactions of everything using layout classes. You're welcome to improve this, but I double
@@ -177,8 +183,11 @@ void MainWindow::paintEvent(QPaintEvent *event)
void MainWindow::mouseDoubleClickEvent(QMouseEvent *)
{
+ static int clicks = 0;
if (m_Snake == nullptr) {
- m_Snake = new GameCore(this);
+ if (clicks++ > 0) {
+ m_Snake = new GameCore(this);
+ }
} else {
m_Snake->addSnake();
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index e1a8011..3ea0e4a 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -51,6 +51,7 @@ protected:
public slots:
void updateClock();
+ void reLayout();
private:
diff --git a/src/settings.h b/src/settings.h
index 69554c4..1b3abfd 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -35,16 +35,18 @@ public:
static QString bannerImageFile() { return s_settings->value("greeter-banner-image").toString(); }
static QString bottomLeftLogoFile() { return s_settings->value("greeter-bottom-left-logo-file").toString(); }
static QString bottomLeftLogoDir() { return s_settings->value("greeter-bottom-left-logo-path").toString(); }
- static QStringList gradientColors() { return s_settings->value("greeter-background-gradient").toString().split(QRegExp("\\s"), QString::SkipEmptyParts); }
+ static QStringList gradientColors() { return s_settings->value("greeter-background-gradient").toString().split(QRegExp("\\s"), Qt::SkipEmptyParts); }
static QString logMessageFile() { return s_settings->value("greeter-message-file").toString(); }
static QString newsHtmlFile() { return s_settings->value("news-html-file").toString(); }
static QString autoLoginCheckCmd() { return s_settings->value("auto-login-check-cmd").toString(); }
static QString clockStyle() { return s_settings->value("clock-text-style").toString(); }
static QString clockBackgroundStyle() { return s_settings->value("clock-background-style").toString(); }
- static QStringList clockShadow() { return s_settings->value("clock-shadow").toString().split(QRegExp("\\s"), QString::SkipEmptyParts); }
+ static QStringList clockShadow() { return s_settings->value("clock-shadow").toString().split(QRegExp("\\s"), Qt::SkipEmptyParts); }
static QString usernamePlaceholder() { return s_settings->value("username-placeholder").toString(); }
static QString passwordPlaceholder() { return s_settings->value("password-placeholder").toString(); }
static bool guestSessionEnabled() { return s_settings->value("guest-session-enabled").toBool(); }
+ static bool shibSessionEnabled() { return s_settings->value("shib-session-enabled").toBool(); }
+ static QString shibUrl() { return s_settings->value("shib-url").toString(); }
static QString userSessionButtonText() { return s_settings->value("user-session-button-text").toString(); }
static QString guestSessionButtonText() { return s_settings->value("guest-session-button-text").toString(); }
static QString guestSessionStartText() { return s_settings->value("guest-session-start-text").toString(); }
diff --git a/src/webview.cpp b/src/webview.cpp
new file mode 100644
index 0000000..0ca7328
--- /dev/null
+++ b/src/webview.cpp
@@ -0,0 +1,109 @@
+#include "webview.h"
+#include <QWebFrame>
+#include <QNetworkReply>
+#include <QMessageBox>
+#include <QTimer>
+#include <QUrlQuery>
+#include <QCryptographicHash>
+#include <QCursor>
+#include <QWebHistory>
+#include <QNetworkCookieJar>
+#include <QWebElement>
+
+WebView::WebView(QWidget* parent)
+ : QWebView(parent),
+ _timerAbortMessage(new QTimer(this)),
+ _abortedDownload(false),
+ _timerReset(new QTimer(this))
+ {
+ _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();
+}
diff --git a/src/webview.h b/src/webview.h
new file mode 100644
index 0000000..79b4a64
--- /dev/null
+++ b/src/webview.h
@@ -0,0 +1,44 @@
+#ifndef WEBVIEW_H_
+#define WEBVIEW_H_
+
+#include <QStack>
+#include <QWebView>
+#include <QNetworkRequest>
+
+class QNetworkReply;
+class QTimer;
+
+/**
+ * Make sure pages that want to load in a new tab are actually loaded in the same page,
+ * and remember the previous URL in case the "new tab" requests to be closed.
+ */
+class WebView : public QWebView
+{
+Q_OBJECT
+public:
+ WebView(QWidget* parent = NULL);
+ void reset(const QString baseUrl);
+
+protected:
+ QWebView *createWindow(QWebPage::WebWindowType);
+
+signals:
+ void triggerReset(const QString &message);
+ void startAuthentication(const QString &user, const QString &pass);
+
+protected slots:
+ void windowCloseRequested();
+ void unsupportedContent(QNetworkReply*);
+ void downloadRequest(QNetworkRequest);
+ void downloadDeniedMessage();
+ void onLoadFinished(bool ok);
+
+private:
+ QStack<QUrl> _urls;
+ QTimer *_timerAbortMessage;
+ bool _abortedDownload;
+ QString _token;
+ QTimer *_timerReset;
+};
+
+#endif
diff --git a/src/x11util.h b/src/x11util.h
index 6699074..7934d20 100644
--- a/src/x11util.h
+++ b/src/x11util.h
@@ -4,7 +4,7 @@
#include <cstddef>
extern "C" {
- #include <X11/Xlib.h>
+ typedef struct _XDisplay Display;
void AddPixmapToBackground(unsigned const char* imgData, const unsigned int width, const unsigned int height,
const unsigned int depth, const int bytesPerLine, const size_t byteCount);
unsigned int getKeyMask(Display *dpy);