ATLAS Offline Software
Loading...
Searching...
No Matches
VP1Authenticator Class Reference

#include <VP1Authenticator.h>

Inheritance diagram for VP1Authenticator:
Collaboration diagram for VP1Authenticator:

Classes

class  Imp

Signals

void authenticationSuccessful (QNetworkAccessManager *)

Public Member Functions

 VP1Authenticator (QWidget *, const QString &)
virtual ~VP1Authenticator ()
bool connectToServer ()
QNetworkAccessManager * networkAccessManager ()

Private Slots

void finished ()
void error (QNetworkReply::NetworkError)
void sslErrors (const QList< QSslError > &)
void loginClicked ()

Private Attributes

Impm_d {}

Detailed Description

Definition at line 28 of file VP1Authenticator.h.

Constructor & Destructor Documentation

◆ VP1Authenticator()

VP1Authenticator::VP1Authenticator ( QWidget * parent,
const QString & fileInfoUrl )

Definition at line 136 of file VP1Authenticator.cxx.

137 : QDialog(parent)
138 , m_d(new Imp(this,fileInfoUrl))
139{
140 setupUi(this);
141 setFixedSize(400,200);
142
143 // Configure GUI properties
144 teditError->setVisible(false);
145 teditError->setLineWrapMode(QTextEdit::NoWrap);
146 pbtnLogin->setDefault(true);
147
148 // Connect GUI signals to slots
149 connect(pbtnLogin,SIGNAL(clicked()),this,SLOT(loginClicked()));
150 connect(pbtnCancel,SIGNAL(clicked()),this,SLOT(reject()));
151
152#ifndef QT_NO_SSL
153 qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
154#endif
155}

◆ ~VP1Authenticator()

VP1Authenticator::~VP1Authenticator ( )
virtual

Definition at line 157 of file VP1Authenticator.cxx.

158{
159 delete m_d;
160}

Member Function Documentation

◆ authenticationSuccessful

void VP1Authenticator::authenticationSuccessful ( QNetworkAccessManager * )
signal

◆ connectToServer()

bool VP1Authenticator::connectToServer ( )

Definition at line 164 of file VP1Authenticator.cxx.

165{
166 QUrl fileinfoUrl(m_d->m_fileInfoUrl);
167 QNetworkRequest netrequest(fileinfoUrl);
168 m_d->m_netreply = m_d->m_netmanager->get(netrequest);
169 m_d->connectToAuthenticator(this);
170
171 return true;
172}

◆ error

void VP1Authenticator::error ( QNetworkReply::NetworkError err)
privateslot

Definition at line 543 of file VP1Authenticator.cxx.

544{
545 if(m_d->m_log) {
546 QString message("VP1Authenticator error. STAGE " + QString::number(m_d->stage) + ", error code: " + QString::number((int)err) + "\n");
547 QByteArray ba(message.toStdString().c_str());
548 m_d->m_log->write(ba);
549 }
550}

◆ finished

void VP1Authenticator::finished ( )
privateslot

Definition at line 174 of file VP1Authenticator.cxx.

175{
176 QString message("\n\nVP1Authenticator done. STAGE " + QString::number(m_d->stage) + "\n");
177
178 QUrl redirectionUrl;
179 QList<QNetworkCookie> cookielist;
180
181 // ******** Collect some information for the log ********
182
183 // ** Headers
184 QVariant val = m_d->m_netreply->header(QNetworkRequest::SetCookieHeader);
185 if(val.type()==QVariant::Invalid) {
186 message += QString(" No set cookies\n");
187 } else if (!val.canConvert<QList<QNetworkCookie> >()){
188 message += QString(" Cannot convert to the list of cookies\n");
189 } else {
190 cookielist = val.value<QList<QNetworkCookie> >();
191 for(int ii=0; ii<cookielist.size(); ++ii) {
192 const QNetworkCookie& cookie = cookielist.at(ii);
193 message += (" Received cookie #" + QString::number(ii) + "\n");
194 message += (" *** Path: " + cookie.path() + "\n");
195 message += (" *** Domain: " + cookie.domain() + "\n");
196 message += (QString(" *** Secure: ") + (cookie.isSecure() ? "YES" : "NO") + "\n");
197 message += (QString(" *** Session: ") + (cookie.isSessionCookie() ? "YES" : "NO") + "\n");
198 message += (" *** Name: " + QString(cookie.name().constData()) + "\n");
199 message += (" *** Value: " + QString(cookie.value().constData()) + "\n");
200 }
201 }
202
203 val = m_d->m_netreply->header(QNetworkRequest::ContentTypeHeader);
204 if(val.type()==QVariant::Invalid) {
205 message += QString(" No ContentType\n");
206 } else if (!val.canConvert<QString>()) {
207 message += QString(" Cannot convert Content Type to String\n");
208 } else {
209 QString conttype = val.value<QString>();
210 message += QString(" Content type: " + conttype + "\n");
211 }
212
213 val = m_d->m_netreply->header(QNetworkRequest::ContentLengthHeader);
214 if(val.type()==QVariant::Invalid) {
215 message += QString(" No ContentLength\n");
216 } else if (!val.canConvert<int>()) {
217 message += QString(" Cannot convert Content Length to int\n");
218 } else {
219 int contlength = val.value<int>();
220 message += QString(" Content Length: " + QString::number(contlength) + "\n");
221 }
222
223 val = m_d->m_netreply->header(QNetworkRequest::LocationHeader);
224 if(val.type()==QVariant::Invalid) {
225 message += QString(" No Location\n");
226 } else if (!val.canConvert<QUrl>()) {
227 message += QString(" Cannot convert Content Length to QUrl\n");
228 } else {
229 QUrl url = val.value<QUrl>();
230 message += QString(" Location URL " + url.toString() + "\n");
231 }
232
233 // ** Attributes
234 val = m_d->m_netreply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
235 if(val.type()==QVariant::Invalid) {
236 message += QString(" No StatusCode Attribute\n");
237 } else if (!val.canConvert<int>()) {
238 message += QString(" Cannot convert StatusCode to int\n");
239 } else {
240 int sc = val.value<int>();
241 message += QString(" StatusCode : " +QString::number(sc) + "\n");
242 }
243
244 val = m_d->m_netreply->attribute(QNetworkRequest::RedirectionTargetAttribute);
245 if(val.type()==QVariant::Invalid) {
246 message += QString(" No Redirection Attribute\n");
247 } else if (!val.canConvert<QUrl>()) {
248 message += QString(" Cannot convert Redirection to QUrl\n");
249 } else {
250 redirectionUrl = val.value<QUrl>();
251 message += QString(" Redirection : " + redirectionUrl.toString() + "\n");
252 }
253
254 message += QString("\n HTML response >>>>>\n");
255
256 QByteArray logMessage(message.toStdString().c_str());
257
258 // ** Write reply to log **
259 QByteArray ba = m_d->m_netreply->readAll();
260 logMessage = logMessage.append(ba);
261 logMessage = logMessage.append("\n<<<<< HTML response\n\n\n");
262 if(m_d->m_log)
263 m_d->m_log->write(logMessage);
264
265
266 // *** Stage 5:
267 // Final response from the server. It may happen that the
268 // authentication was successfull, however the user is not
269 // authorized to access the requested resource
270 //
271 // Check that...
272 if(m_d->stage==5) {
273 QString replyBody(ba.data());
274 if(replyBody.contains("authorization failed", Qt::CaseInsensitive)) {
275 QString errMessage("Authorization Failed");
276 m_d->displayError(errMessage);
277 m_d->m_netmanager->deleteLater();
278 m_d->m_netmanager = new QNetworkAccessManager();
279 m_d->stage=1;
280 m_d->m_netreply=0;
281 return;
282 }
283
284 if(m_d->m_netreply->error()==QNetworkReply::NoError)
285 authenticationSuccessful(m_d->m_netmanager);
286 }
287
288 // ** Check for errors **
289 if(m_d->m_netreply->error()!=QNetworkReply::NoError) {
290 QString errMessage("Network error occured during authentication phase\n");
291 errMessage += QString("Error code " + QString::number((int)m_d->m_netreply->error()) + "\nExplanation on http://doc.trolltech.com/4.4/qnetworkreply.html#NetworkError-enum");
292 m_d->displayError(errMessage);
293 m_d->stage=1;
294 return;
295 }
296
297 // *** Stage 1:
298 // Received a reply redirecting us to login.cern.ch
299 // Take the redirection URL and issue GET request for it
300 if(m_d->stage==1) {
301 if(redirectionUrl.isEmpty() || redirectionUrl.host() != m_d->m_loginServer) {
302 QString errMessage("Wrong URL: " + m_d->m_fileInfoUrl + "\nPlease fix the URL and restart the job");
303 m_d->displayError(errMessage);
304 m_d->stage=1;
305 return;
306 } else {
307 QNetworkRequest netrequest(redirectionUrl);
308 m_d->m_netreply = m_d->m_netmanager->get(netrequest);
309 if(m_d->m_log) {
310 QByteArray baLog("Get request sent\n_______________________________________________________\n\n");
311 m_d->m_log->write(baLog);
312 }
313 m_d->connectToAuthenticator(this);
314 m_d->stage++;
315 return;
316 }
317 }
318
319 // *** Stage 2:
320 // Received authentication form
321 // Parse contents of the authentication form
322 // look for input tags and collect their attributes
323 if(m_d->stage==2) {
324 QString replyBody(ba.data());
325
326 QString newRequestBody("__EVENTTARGET=&__EVENTARGUMENT=&__LASTFOCUS=");
327
328 QStringMatcher inputStartMatcher("<input ",Qt::CaseInsensitive);
329 QStringMatcher inputEndMatcher("/>");
330
331 int inputStart = inputStartMatcher.indexIn(replyBody,0);
332
333 while(inputStart!=-1) {
334 int inputEnd = inputEndMatcher.indexIn(replyBody,inputStart+inputStartMatcher.pattern().size());
335 if(inputEnd==-1) // something is wrong with this tag
336 break;
337 else {
338 // Let's parse it
339 QString tag = replyBody.mid(inputStart,inputEnd-inputStart);
340 QString typeVal = m_d->getTagAttributeVal(tag,"type");
341 QString nameVal = m_d->getTagAttributeVal(tag,"name");
342 QString valueVal = m_d->getTagAttributeVal(tag,"value").replace(" ","+");
343
344 if(QString::compare(typeVal,"text",Qt::CaseInsensitive)==0)
345 valueVal = inpPers->text();
346 else if(QString::compare(typeVal,"password",Qt::CaseInsensitive)==0)
347 valueVal = inpPhr->text();
348
349 if(QString::compare(typeVal,"checkbox",Qt::CaseInsensitive)!=0) {
350 QByteArray encodedNameVal = QUrl::toPercentEncoding(nameVal);
351 if(QString::compare(typeVal,"submit",Qt::CaseInsensitive)==0
352 || QString::compare(typeVal,"text",Qt::CaseInsensitive)==0
353 || QString::compare(typeVal,"password",Qt::CaseInsensitive)==0 ) {
354 newRequestBody+=("&"+QString(encodedNameVal)+"="+valueVal);
355 } else {
356 QByteArray encodedValueVal = QUrl::toPercentEncoding(valueVal);
357 if(newRequestBody.size()!=0)
358 newRequestBody+="&";
359 newRequestBody+=(QString(encodedNameVal)+"="+QString(encodedValueVal));
360 }
361 }
362
363 // move to the next input
364 inputStart = inputStartMatcher.indexIn(replyBody,inputEnd+inputEndMatcher.pattern().size());
365 }
366 }
367
368 QByteArray newBody = newRequestBody.toUtf8();
369
370 QString logMessage = "New Request Length: " + QString::number(newBody.size()) + "\n";
371 logMessage += ("New Request Body:\n" + newRequestBody.replace(inpPhr->text(),"xxx") + "\n");
372
373 // Get form action
374 // !!! Hardwire this for now:
375 QString actionUrlString("https://"+m_d->m_loginServer);
376
377 QStringMatcher actionStartMatcher("action=\"",Qt::CaseInsensitive);
378 QStringMatcher actionEndMatcher("\"");
379 int actionStart = actionStartMatcher.indexIn(replyBody,0);
380 if(actionStart!=-1) {
381 int actionEnd = actionEndMatcher.indexIn(replyBody,actionStart+actionStartMatcher.pattern().size());
382 if(actionEnd!=-1)
383 actionUrlString += replyBody.mid(actionStart+actionStartMatcher.pattern().size(),actionEnd-actionStart-actionStartMatcher.pattern().size());
384 }
385
386 logMessage += ("New URL: " + actionUrlString + "\n");
387 QByteArray actionUrlBa(actionUrlString.toStdString().c_str());
388 QString actionUrlStringDecoded = QUrl::fromPercentEncoding(actionUrlBa);
389 logMessage += ("Decoded URL: " + actionUrlStringDecoded.replace("&amp;","&")
390 + "\n\nPost request sent\n_______________________________________________________\n\n");
391
392 // Send Post request:
393 QNetworkRequest netrequest(QUrl(actionUrlStringDecoded.replace("&amp;","&")));
394 netrequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
395 netrequest.setHeader(QNetworkRequest::ContentLengthHeader,newBody.size());
396 m_d->m_netreply = m_d->m_netmanager->post(netrequest,newBody);
397 if(m_d->m_log) {
398 QByteArray baLog(logMessage.toStdString().c_str());
399 m_d->m_log->write(baLog);
400 }
401 m_d->connectToAuthenticator(this);
402 m_d->stage++;
403 return;
404 }
405
406 // *** Stage 3:
407 // Received response from the autentication attempt
408 //
409 // Check if the authentication was successful. This can be done
410 // either of these two ways:
411 // 1. Check number of set cookies, if it = 0 then authentication failed
412 // 2. Look for 'Logon failure' string in the response body
413 // We implement the option #1
414 //
415 // If the authentication considered successfull then parse contents of the
416 // response, look for input tags and collect their attributes
417 // and compose a new POST request
418 if(m_d->stage==3) {
419
420 if(cookielist.size()==0) {
421 // Authentication failed
422 QString errMessage("Authentication failed, please try again\n");
423 m_d->displayError(errMessage);
424 m_d->stage=1;
425 return;
426 }
427
428 QString replyBody(ba.data());
429 QByteArray excludeFromEncoding(" ");
430 QString newRequestBody("");
431
432 QStringMatcher inputStartMatcher("<input ",Qt::CaseInsensitive);
433 QStringMatcher inputEndMatcher("/>");
434
435 int inputStart = inputStartMatcher.indexIn(replyBody,0);
436
437 while(inputStart!=-1) {
438
439 // It can happen that /> is in the middle of some string, for example it can
440 // be part of value="...". We need to take this into account as well
441 int inputEnd = inputStart;
442 int quoteCount = 1; // just to be able to enter the next loop
443 int quotePos = inputStart;
444 QStringMatcher quoteMatcher("\"");
445
446 while(quoteCount%2!=0) {
447 inputEnd = inputEndMatcher.indexIn(replyBody,quotePos);
448 if(inputEnd==-1)
449 break;
450 quoteCount = 0;
451 quotePos = inputStart;
452
453 while(true) {
454 quotePos = quoteMatcher.indexIn(replyBody,quotePos);
455 if(quotePos==-1||quotePos>inputEnd)
456 break;
457 quoteCount++;
458 quotePos++;
459 }
460 }
461
462 if(inputEnd==-1) // something is wrong with this tag
463 break;
464 else {
465 // Let's parse it
466 QString tag = replyBody.mid(inputStart,inputEnd-inputStart);
467 QString typeVal = m_d->getTagAttributeVal(tag,"type");
468 QString nameVal = m_d->getTagAttributeVal(tag,"name");
469 QString valueVal = m_d->getTagAttributeVal(tag,"value");
470
471 if(QString::compare(typeVal,"text",Qt::CaseInsensitive)==0)
472 valueVal = inpPers->text();
473 else if(QString::compare(typeVal,"password",Qt::CaseInsensitive)==0)
474 valueVal = inpPhr->text();
475
476 if(QString::compare(typeVal,"checkbox",Qt::CaseInsensitive)!=0 &&
477 QString::compare(typeVal,"submit",Qt::CaseInsensitive)!=0) {
478 QByteArray encodedNameVal = QUrl::toPercentEncoding(nameVal);
479 QString valueVal1 = valueVal.replace("&lt;","<");
480 QString valueVal2 = valueVal.replace("&quot;","\"");
481 QByteArray encodedValueVal = QUrl::toPercentEncoding(valueVal2,excludeFromEncoding);
482 if(newRequestBody.size()!=0)
483 newRequestBody+="&";
484 newRequestBody+=(QString(encodedNameVal)+"="+QString(encodedValueVal).replace(" ","+"));
485 }
486
487 // move to the next input
488 inputStart = inputStartMatcher.indexIn(replyBody,inputEnd+inputEndMatcher.pattern().size());
489 }
490 }
491
492 QByteArray newBody = newRequestBody.toUtf8();
493
494 QString logMessage = "New Request Length: " + QString::number(newBody.size()) + "\n";
495 logMessage += ("New Request Body:\n" + newRequestBody + "\n");
496
497 // Get form action
498 QString actionUrlString("");
499
500 QStringMatcher actionStartMatcher("action=\"",Qt::CaseInsensitive);
501 QStringMatcher actionEndMatcher("\"");
502 int actionStart = actionStartMatcher.indexIn(replyBody,0);
503 if(actionStart!=-1) {
504 int actionEnd = actionEndMatcher.indexIn(replyBody,actionStart+actionStartMatcher.pattern().size());
505 if(actionEnd!=-1)
506 actionUrlString = replyBody.mid(actionStart+actionStartMatcher.pattern().size(),actionEnd-actionStart-actionStartMatcher.pattern().size());
507 }
508
509 logMessage += ("New URL: " + actionUrlString + "\n");
510
511 // Send Post request:
512 QNetworkRequest netrequest;
513 netrequest.setUrl(actionUrlString);
514 netrequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
515 netrequest.setHeader(QNetworkRequest::ContentLengthHeader,newBody.size());
516 m_d->m_netreply = m_d->m_netmanager->post(netrequest,newBody);
517 logMessage += ("\n\nPost request sent\n_______________________________________________________\n\n");
518 if(m_d->m_log) {
519 QByteArray baLog(logMessage.toStdString().c_str());
520 m_d->m_log->write(baLog);
521 }
522 m_d->connectToAuthenticator(this);
523 m_d->stage++;
524 return;
525 }
526
527 // *** Stage 4:
528 // Recieved a final redirection to the requested resource
529 // Just try to get it
530 if(m_d->stage==4) {
531 QNetworkRequest netrequest(redirectionUrl);
532 m_d->m_netreply = m_d->m_netmanager->get(netrequest);
533 if(m_d->m_log) {
534 QByteArray baLog("Get request sent\n_______________________________________________________\n\n");
535 m_d->m_log->write(baLog);
536 }
537 m_d->connectToAuthenticator(this);
538 m_d->stage++;
539 return;
540 }
541}
static Double_t sc
void authenticationSuccessful(QNetworkAccessManager *)

◆ loginClicked

void VP1Authenticator::loginClicked ( )
privateslot

Definition at line 567 of file VP1Authenticator.cxx.

568{
569 // Hide error box, if visible
570 if(teditError->isVisible()) {
571 teditError->setVisible(false);
572 setFixedSize(400,200);
573 teditError->clear();
574 }
575
576 // Set focus on the login box, if empty
577 if(inpPers->text().isEmpty()) {
578 inpPers->setFocus();
579 return;
580 }
581
582 // Set focus on the pass box, if empty
583 if(inpPhr->text().isEmpty()) {
584 inpPhr->setFocus();
585 return;
586 }
587
588 inpPers->setEnabled(false);
589 inpPhr->setEnabled(false);
591}

◆ networkAccessManager()

QNetworkAccessManager * VP1Authenticator::networkAccessManager ( )

Definition at line 593 of file VP1Authenticator.cxx.

594{
595 return m_d->m_netmanager;
596}

◆ sslErrors

void VP1Authenticator::sslErrors ( const QList< QSslError > & errlist)
privateslot

Definition at line 553 of file VP1Authenticator.cxx.

554{
555 if(m_d->m_log) {
556 QString message("VP1Authenticator SSL errors. STAGE " + QString::number(m_d->stage) + "\n");
557 for(int ii=0; ii<errlist.size(); ++ii)
558 message += (" " + QString::number((int)errlist.at(ii).error()) + ", " + errlist.at(ii).errorString() + "\n");
559 QByteArray ba(message.toStdString().c_str());
560 m_d->m_log->write(ba);
561 }
562 m_d->m_netreply->ignoreSslErrors();
563}

Member Data Documentation

◆ m_d

Imp* VP1Authenticator::m_d {}
private

Definition at line 58 of file VP1Authenticator.h.

58{};

The documentation for this class was generated from the following files: