mirror of
				https://github.com/yuezk/GlobalProtect-openconnect.git
				synced 2025-05-20 07:26:58 -04:00 
			
		
		
		
	support 2fa
This commit is contained in:
		| @@ -33,6 +33,9 @@ add_executable(gpclient | |||||||
|     gpclient.ui |     gpclient.ui | ||||||
|     normalloginwindow.ui |     normalloginwindow.ui | ||||||
|     settingsdialog.ui |     settingsdialog.ui | ||||||
|  |     challengedialog.h | ||||||
|  |     challengedialog.cpp | ||||||
|  |     challengedialog.ui | ||||||
|     resources.qrc |     resources.qrc | ||||||
|     ${gpclient_GENERATED_SOURCES} |     ${gpclient_GENERATED_SOURCES} | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								GPClient/challengedialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								GPClient/challengedialog.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | #include <QtWidgets/QDialogButtonBox> | ||||||
|  | #include <QtWidgets/QPushButton> | ||||||
|  |  | ||||||
|  | #include "challengedialog.h" | ||||||
|  | #include "ui_challengedialog.h" | ||||||
|  |  | ||||||
|  | ChallengeDialog::ChallengeDialog(QWidget *parent) : | ||||||
|  |     QDialog(parent), | ||||||
|  |     ui(new Ui::ChallengeDialog) | ||||||
|  | { | ||||||
|  |     ui->setupUi(this); | ||||||
|  |     ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ChallengeDialog::~ChallengeDialog() | ||||||
|  | { | ||||||
|  |     delete ui; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ChallengeDialog::setMessage(const QString &message) | ||||||
|  | { | ||||||
|  |     ui->challengeMessage->setText(message); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const QString ChallengeDialog::getChallenge() | ||||||
|  | { | ||||||
|  |     return ui->challengeInput->text(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ChallengeDialog::on_challengeInput_textChanged(const QString &value) | ||||||
|  | { | ||||||
|  |     QPushButton *okBtn = ui->buttonBox->button(QDialogButtonBox::Ok); | ||||||
|  |     if (value.isEmpty()) { | ||||||
|  |         okBtn->setDisabled(true); | ||||||
|  |     } else { | ||||||
|  |         okBtn->setEnabled(true); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								GPClient/challengedialog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								GPClient/challengedialog.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | #ifndef CHALLENGEDIALOG_H | ||||||
|  | #define CHALLENGEDIALOG_H | ||||||
|  |  | ||||||
|  | #include <QDialog> | ||||||
|  |  | ||||||
|  | namespace Ui { | ||||||
|  | class ChallengeDialog; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class ChallengeDialog : public QDialog | ||||||
|  | { | ||||||
|  |     Q_OBJECT | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     explicit ChallengeDialog(QWidget *parent = nullptr); | ||||||
|  |     ~ChallengeDialog(); | ||||||
|  |  | ||||||
|  |     void setMessage(const QString &message); | ||||||
|  |     const QString getChallenge(); | ||||||
|  |  | ||||||
|  | private slots: | ||||||
|  |     void on_challengeInput_textChanged(const QString &arg1); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     Ui::ChallengeDialog *ui; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif // CHALLENGEDIALOG_H | ||||||
							
								
								
									
										111
									
								
								GPClient/challengedialog.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								GPClient/challengedialog.ui
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>ChallengeDialog</class> | ||||||
|  |  <widget class="QDialog" name="ChallengeDialog"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>405</width> | ||||||
|  |     <height>200</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>GlobalProtect Challenge</string> | ||||||
|  |   </property> | ||||||
|  |   <property name="modal"> | ||||||
|  |    <bool>true</bool> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |    <item> | ||||||
|  |     <layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,1"> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QLabel" name="label"> | ||||||
|  |        <property name="font"> | ||||||
|  |         <font> | ||||||
|  |          <pointsize>14</pointsize> | ||||||
|  |          <weight>50</weight> | ||||||
|  |          <bold>false</bold> | ||||||
|  |         </font> | ||||||
|  |        </property> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Sign In</string> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |      <item> | ||||||
|  |       <widget class="QLabel" name="challengeMessage"> | ||||||
|  |        <property name="text"> | ||||||
|  |         <string>Duo two-factor login for [redacted]  Enter a passcode or select one of the following options:   1. Duo Push to XXX-XXX-[redacted]  2. SMS passcodes to XXX-XXX-[redacted]  Passcode or option (1-2): </string> | ||||||
|  |        </property> | ||||||
|  |        <property name="alignment"> | ||||||
|  |         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||||||
|  |        </property> | ||||||
|  |        <property name="wordWrap"> | ||||||
|  |         <bool>true</bool> | ||||||
|  |        </property> | ||||||
|  |       </widget> | ||||||
|  |      </item> | ||||||
|  |     </layout> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QLineEdit" name="challengeInput"> | ||||||
|  |      <property name="echoMode"> | ||||||
|  |       <enum>QLineEdit::Password</enum> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QDialogButtonBox" name="buttonBox"> | ||||||
|  |      <property name="layoutDirection"> | ||||||
|  |       <enum>Qt::LeftToRight</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="standardButtons"> | ||||||
|  |       <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||||||
|  |      </property> | ||||||
|  |      <property name="centerButtons"> | ||||||
|  |       <bool>false</bool> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <resources/> | ||||||
|  |  <connections> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>accepted()</signal> | ||||||
|  |    <receiver>ChallengeDialog</receiver> | ||||||
|  |    <slot>accept()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>248</x> | ||||||
|  |      <y>254</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>157</x> | ||||||
|  |      <y>274</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>rejected()</signal> | ||||||
|  |    <receiver>ChallengeDialog</receiver> | ||||||
|  |    <slot>reject()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>316</x> | ||||||
|  |      <y>260</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>286</x> | ||||||
|  |      <y>274</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |  </connections> | ||||||
|  | </ui> | ||||||
| @@ -1,14 +1,17 @@ | |||||||
| #include <QtNetwork/QNetworkReply> | #include <QtNetwork/QNetworkReply> | ||||||
|  | #include <QtCore/QRegularExpression> | ||||||
|  | #include <QtCore/QRegularExpressionMatch> | ||||||
| #include <plog/Log.h> | #include <plog/Log.h> | ||||||
|  |  | ||||||
| #include "gatewayauthenticator.h" | #include "gatewayauthenticator.h" | ||||||
| #include "gphelper.h" | #include "gphelper.h" | ||||||
| #include "loginparams.h" | #include "loginparams.h" | ||||||
| #include "preloginresponse.h" | #include "preloginresponse.h" | ||||||
|  | #include "challengedialog.h" | ||||||
|  |  | ||||||
| using namespace gpclient::helper; | using namespace gpclient::helper; | ||||||
|  |  | ||||||
| GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params) | GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params) | ||||||
|     : QObject() |     : QObject() | ||||||
|     , gateway(gateway) |     , gateway(gateway) | ||||||
|     , params(params) |     , params(params) | ||||||
| @@ -33,6 +36,7 @@ void GatewayAuthenticator::authenticate() | |||||||
|     loginParams.setUser(params.username()); |     loginParams.setUser(params.username()); | ||||||
|     loginParams.setPassword(params.password()); |     loginParams.setPassword(params.password()); | ||||||
|     loginParams.setUserAuthCookie(params.userAuthCookie()); |     loginParams.setUserAuthCookie(params.userAuthCookie()); | ||||||
|  |     loginParams.setInputStr(params.inputStr()); | ||||||
|  |  | ||||||
|     login(loginParams); |     login(loginParams); | ||||||
| } | } | ||||||
| @@ -48,10 +52,10 @@ void GatewayAuthenticator::login(const LoginParams &loginParams) | |||||||
| void GatewayAuthenticator::onLoginFinished() | void GatewayAuthenticator::onLoginFinished() | ||||||
| { | { | ||||||
|     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); |     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); | ||||||
|     QByteArray response; |     QByteArray response = reply->readAll(); | ||||||
|  |  | ||||||
|     if (reply->error() || (response = reply->readAll()).contains("Authentication failure")) { |     if (reply->error() || response.contains("Authentication failure")) { | ||||||
|         PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl).arg(reply->errorString()); |         PLOGE << QString("Failed to login the gateway at %1, %2").arg(loginUrl, reply->errorString()); | ||||||
|  |  | ||||||
|         if (normalLoginWindow) { |         if (normalLoginWindow) { | ||||||
|             normalLoginWindow->setProcessing(false); |             normalLoginWindow->setProcessing(false); | ||||||
| @@ -62,6 +66,12 @@ void GatewayAuthenticator::onLoginFinished() | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // 2FA | ||||||
|  |     if (response.contains("Challenge")) { | ||||||
|  |         showChallenge(response); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (normalLoginWindow) { |     if (normalLoginWindow) { | ||||||
|         normalLoginWindow->close(); |         normalLoginWindow->close(); | ||||||
|     } |     } | ||||||
| @@ -83,7 +93,7 @@ void GatewayAuthenticator::onPreloginFinished() | |||||||
|     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); |     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); | ||||||
|  |  | ||||||
|     if (reply->error()) { |     if (reply->error()) { | ||||||
|         PLOGE << QString("Failed to prelogin the gateway at %1, %2").arg(preloginUrl).arg(reply->errorString()); |         PLOGE << QString("Failed to prelogin the gateway at %1, %2").arg(preloginUrl, reply->errorString()); | ||||||
|  |  | ||||||
|         emit fail("Error occurred on the gateway prelogin interface."); |         emit fail("Error occurred on the gateway prelogin interface."); | ||||||
|         return; |         return; | ||||||
| @@ -98,7 +108,7 @@ void GatewayAuthenticator::onPreloginFinished() | |||||||
|     } else if (response.hasNormalAuthFields()) { |     } else if (response.hasNormalAuthFields()) { | ||||||
|         normalAuth(response.labelUsername(), response.labelPassword(), response.authMessage()); |         normalAuth(response.labelUsername(), response.labelPassword(), response.authMessage()); | ||||||
|     } else { |     } else { | ||||||
|         PLOGE << QString("Unknown prelogin response for %1, got %2").arg(preloginUrl).arg(QString::fromUtf8(response.rawResponse())); |         PLOGE << QString("Unknown prelogin response for %1, got %2").arg(preloginUrl, QString::fromUtf8(response.rawResponse())); | ||||||
|         emit fail("Unknown response for gateway prelogin interface."); |         emit fail("Unknown response for gateway prelogin interface."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -107,7 +117,7 @@ void GatewayAuthenticator::onPreloginFinished() | |||||||
|  |  | ||||||
| void GatewayAuthenticator::normalAuth(QString labelUsername, QString labelPassword, QString authMessage) | void GatewayAuthenticator::normalAuth(QString labelUsername, QString labelPassword, QString authMessage) | ||||||
| { | { | ||||||
|     PLOGI << QString("Trying to perform the normal login with %1 / %2 credentials").arg(labelUsername).arg(labelPassword); |     PLOGI << QString("Trying to perform the normal login with %1 / %2 credentials").arg(labelUsername, labelPassword); | ||||||
|  |  | ||||||
|     normalLoginWindow = new NormalLoginWindow; |     normalLoginWindow = new NormalLoginWindow; | ||||||
|     normalLoginWindow->setPortalAddress(gateway); |     normalLoginWindow->setPortalAddress(gateway); | ||||||
| @@ -179,3 +189,37 @@ void GatewayAuthenticator::onSAMLLoginFail(const QString msg) | |||||||
| { | { | ||||||
|     emit fail(msg); |     emit fail(msg); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void GatewayAuthenticator::showChallenge(const QString &responseText) | ||||||
|  | { | ||||||
|  |     QRegularExpression re("\"(.*?)\";"); | ||||||
|  |     QRegularExpressionMatchIterator i = re.globalMatch(responseText); | ||||||
|  |  | ||||||
|  |     i.next(); // Skip the status value | ||||||
|  |     QString message = i.next().captured(1); | ||||||
|  |     QString inputStr = i.next().captured(1); | ||||||
|  |     // update the inputSrc field | ||||||
|  |     params.setInputStr(inputStr); | ||||||
|  |  | ||||||
|  |     challengeDialog = new ChallengeDialog; | ||||||
|  |     challengeDialog->setMessage(message); | ||||||
|  |  | ||||||
|  |     connect(challengeDialog, &ChallengeDialog::accepted, this, [this] { | ||||||
|  |         params.setPassword(challengeDialog->getChallenge()); | ||||||
|  |         authenticate(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     connect(challengeDialog, &ChallengeDialog::rejected, this, [this] { | ||||||
|  |         if (normalLoginWindow) { | ||||||
|  |             normalLoginWindow->close(); | ||||||
|  |         } | ||||||
|  |         emit fail(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     connect(challengeDialog, &ChallengeDialog::finished, this, [this] { | ||||||
|  |         delete challengeDialog; | ||||||
|  |         challengeDialog = nullptr; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     challengeDialog->show(); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #include <QtCore/QObject> | #include <QtCore/QObject> | ||||||
|  |  | ||||||
| #include "normalloginwindow.h" | #include "normalloginwindow.h" | ||||||
|  | #include "challengedialog.h" | ||||||
| #include "loginparams.h" | #include "loginparams.h" | ||||||
| #include "gatewayauthenticatorparams.h" | #include "gatewayauthenticatorparams.h" | ||||||
|  |  | ||||||
| @@ -11,7 +12,7 @@ class GatewayAuthenticator : public QObject | |||||||
| { | { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| public: | public: | ||||||
|     explicit GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params); |     explicit GatewayAuthenticator(const QString& gateway, GatewayAuthenticatorParams params); | ||||||
|     ~GatewayAuthenticator(); |     ~GatewayAuthenticator(); | ||||||
|  |  | ||||||
|     void authenticate(); |     void authenticate(); | ||||||
| @@ -31,16 +32,18 @@ private slots: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     QString gateway; |     QString gateway; | ||||||
|     const GatewayAuthenticatorParams params; |     GatewayAuthenticatorParams params; | ||||||
|     QString preloginUrl; |     QString preloginUrl; | ||||||
|     QString loginUrl; |     QString loginUrl; | ||||||
|  |  | ||||||
|     NormalLoginWindow *normalLoginWindow{ nullptr }; |     NormalLoginWindow *normalLoginWindow{ nullptr }; | ||||||
|  |     ChallengeDialog *challengeDialog{ nullptr }; | ||||||
|  |  | ||||||
|     void login(const LoginParams& loginParams); |     void login(const LoginParams& loginParams); | ||||||
|     void doAuth(); |     void doAuth(); | ||||||
|     void normalAuth(QString labelUsername, QString labelPassword, QString authMessage); |     void normalAuth(QString labelUsername, QString labelPassword, QString authMessage); | ||||||
|     void samlAuth(QString samlMethod, QString samlRequest, QString preloginUrl = ""); |     void samlAuth(QString samlMethod, QString samlRequest, QString preloginUrl = ""); | ||||||
|  |     void showChallenge(const QString &responseText); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif // GATEWAYAUTHENTICATOR_H | #endif // GATEWAYAUTHENTICATOR_H | ||||||
|   | |||||||
| @@ -55,3 +55,13 @@ void GatewayAuthenticatorParams::setClientos(const QString &newClientos) | |||||||
|     m_clientos = newClientos; |     m_clientos = newClientos; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const QString &GatewayAuthenticatorParams::inputStr() const | ||||||
|  | { | ||||||
|  |     return m_inputStr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GatewayAuthenticatorParams::setInputStr(const QString &inputStr) | ||||||
|  | { | ||||||
|  |     m_inputStr = inputStr; | ||||||
|  | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,11 +24,15 @@ public: | |||||||
|     const QString &clientos() const; |     const QString &clientos() const; | ||||||
|     void setClientos(const QString &newClientos); |     void setClientos(const QString &newClientos); | ||||||
|  |  | ||||||
|  |     const QString &inputStr() const; | ||||||
|  |     void setInputStr(const QString &inputStr); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     QString m_username; |     QString m_username; | ||||||
|     QString m_password; |     QString m_password; | ||||||
|     QString m_userAuthCookie; |     QString m_userAuthCookie; | ||||||
|     QString m_clientos; |     QString m_clientos; | ||||||
|  |     QString m_inputStr; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif // GATEWAYAUTHENTICATORPARAMS_H | #endif // GATEWAYAUTHENTICATORPARAMS_H | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ LoginParams::LoginParams(const QString clientos) | |||||||
| { | { | ||||||
|     params.addQueryItem("prot", QUrl::toPercentEncoding("https:")); |     params.addQueryItem("prot", QUrl::toPercentEncoding("https:")); | ||||||
|     params.addQueryItem("server", ""); |     params.addQueryItem("server", ""); | ||||||
|     params.addQueryItem("inputSrc", ""); |     params.addQueryItem("inputStr", ""); | ||||||
|     params.addQueryItem("jnlpReady", "jnlpReady"); |     params.addQueryItem("jnlpReady", "jnlpReady"); | ||||||
|     params.addQueryItem("user", ""); |     params.addQueryItem("user", ""); | ||||||
|     params.addQueryItem("passwd", ""); |     params.addQueryItem("passwd", ""); | ||||||
| @@ -61,6 +61,11 @@ void LoginParams::setPreloginCookie(const QString cookie) | |||||||
|     updateQueryItem("prelogin-cookie", cookie); |     updateQueryItem("prelogin-cookie", cookie); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void LoginParams::setInputStr(const QString inputStr) | ||||||
|  | { | ||||||
|  |     updateQueryItem("inputStr", inputStr); | ||||||
|  | } | ||||||
|  |  | ||||||
| QByteArray LoginParams::toUtf8() const | QByteArray LoginParams::toUtf8() const | ||||||
| { | { | ||||||
|     return params.toString().toUtf8(); |     return params.toString().toUtf8(); | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ public: | |||||||
|     void setUserAuthCookie(const QString cookie); |     void setUserAuthCookie(const QString cookie); | ||||||
|     void setPrelogonAuthCookie(const QString cookie); |     void setPrelogonAuthCookie(const QString cookie); | ||||||
|     void setPreloginCookie(const QString cookie); |     void setPreloginCookie(const QString cookie); | ||||||
|  |     void setInputStr(const QString inputStr); | ||||||
|  |  | ||||||
|     QByteArray toUtf8() const; |     QByteArray toUtf8() const; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ void PortalAuthenticator::onPreloginFinished() | |||||||
|     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); |     QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); | ||||||
|  |  | ||||||
|     if (reply->error()) { |     if (reply->error()) { | ||||||
|         PLOGE << QString("Error occurred while accessing %1, %2").arg(preloginUrl).arg(reply->errorString()); |         PLOGE << QString("Error occurred while accessing %1, %2").arg(preloginUrl, reply->errorString()); | ||||||
|         emit preloginFailed("Error occurred on the portal prelogin interface."); |         emit preloginFailed("Error occurred on the portal prelogin interface."); | ||||||
|         delete reply; |         delete reply; | ||||||
|         return; |         return; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user