PageRenderTime 664ms CodeModel.GetById 0ms RepoModel.GetById 8ms app.codeStats 0ms

/qesteidutil-0.3.1/src/jsextender.cpp

#
C++ | 484 lines | 424 code | 39 blank | 21 comment | 98 complexity | 55169476ae3baf265f8482472bfc95d3 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * QEstEidUtil
  3. *
  4. * Copyright (C) 2009-2010 Estonian Informatics Centre
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. #include <QApplication>
  22. #include <QDesktopServices>
  23. #include <QDomDocument>
  24. #include <QFileDialog>
  25. #include <QLocale>
  26. #include <QMessageBox>
  27. #include <QTemporaryFile>
  28. #include "CertUpdate.h"
  29. #include "mainwindow.h"
  30. #include "jsextender.h"
  31. #include "common/Settings.h"
  32. #include "SettingsDialog.h"
  33. JsExtender::JsExtender( MainWindow *main )
  34. : QObject( main )
  35. , m_mainWindow( main )
  36. , m_loading( 0 )
  37. {
  38. QString deflang;
  39. switch( QLocale().language() )
  40. {
  41. case QLocale::English: deflang = "en"; break;
  42. case QLocale::Russian: deflang = "ru"; break;
  43. case QLocale::Estonian:
  44. default: deflang = "et"; break;
  45. }
  46. m_locale = Settings().value( "Main/Language", deflang ).toString();
  47. if ( m_locale.isEmpty() )
  48. m_locale = QLocale::system().name().left( 2 );
  49. setLanguage( m_locale );
  50. connect( m_mainWindow->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
  51. this, SLOT(javaScriptWindowObjectCleared()));
  52. }
  53. JsExtender::~JsExtender()
  54. {
  55. if ( m_loading )
  56. m_loading->deleteLater();
  57. if ( QFile::exists( m_tempFile ) )
  58. QFile::remove( m_tempFile );
  59. }
  60. void JsExtender::setLanguage( const QString &lang )
  61. {
  62. m_locale = lang;
  63. if ( m_locale == "C" )
  64. m_locale = "en";
  65. Settings().setValue( "Main/Language", m_locale );
  66. m_mainWindow->retranslate( m_locale );
  67. }
  68. void JsExtender::registerObject( const QString &name, QObject *object )
  69. {
  70. m_mainWindow->page()->mainFrame()->addToJavaScriptWindowObject( name, object );
  71. m_registeredObjects[name] = object;
  72. }
  73. void JsExtender::javaScriptWindowObjectCleared()
  74. {
  75. for (QMap<QString, QObject *>::Iterator it = m_registeredObjects.begin(); it != m_registeredObjects.end(); ++it)
  76. m_mainWindow->page()->mainFrame()->addToJavaScriptWindowObject( it.key(), it.value() );
  77. m_mainWindow->page()->mainFrame()->addToJavaScriptWindowObject( "extender", this );
  78. }
  79. QVariant JsExtender::jsCall( const QString &function, int argument )
  80. {
  81. return m_mainWindow->page()->mainFrame()->evaluateJavaScript(
  82. QString( "%1(%2)" ).arg( function ).arg( argument ) );
  83. }
  84. QVariant JsExtender::jsCall( const QString &function, const QString &argument )
  85. {
  86. return m_mainWindow->page()->mainFrame()->evaluateJavaScript(
  87. QString( "%1(\"%2\")" ).arg( function ).arg( argument ) );
  88. }
  89. QVariant JsExtender::jsCall( const QString &function, const QString &argument, const QString &argument2 )
  90. {
  91. return m_mainWindow->page()->mainFrame()->evaluateJavaScript(
  92. QString( "%1(\"%2\",\"%3\")" ).arg( function ).arg( argument ).arg( argument2 ) );
  93. }
  94. void JsExtender::openUrl( const QString &url )
  95. { QDesktopServices::openUrl( QUrl( url ) ); }
  96. QString JsExtender::checkPin()
  97. {
  98. if ( !m_mainWindow->eidCard() || !m_mainWindow->eidCard()->m_card )
  99. throw std::runtime_error( "noCard" );
  100. if ( activeDocument.isEmpty() || activeDocument != m_mainWindow->eidCard()->getDocumentId() || pin.isEmpty() ||
  101. Settings().value( "Util/sessionTime").toInt() == 0 ||
  102. !m_dateTime.isValid() || m_dateTime.addSecs( Settings().value( "Util/sessionTime").toInt() * 60 ) < QDateTime::currentDateTime() )
  103. {
  104. activeDocument = m_mainWindow->eidCard()->getDocumentId();
  105. m_dateTime = QDateTime::currentDateTime();
  106. return QString();
  107. }
  108. return pin;
  109. }
  110. QByteArray JsExtender::getUrl( SSLConnect::RequestType type, const QString &def )
  111. {
  112. QByteArray buffer;
  113. try {
  114. SSLConnect sslConnect;
  115. sslConnect.setPin( checkPin() );
  116. sslConnect.setCard( m_mainWindow->cardManager()->cardId(
  117. m_mainWindow->cardManager()->activeReaderNum() ) );
  118. buffer = sslConnect.getUrl( type, def );
  119. pin = Settings().value( "Util/sessionTime").toInt() ? sslConnect.pin() : QString();
  120. } catch( const std::runtime_error &e ) {
  121. throw std::runtime_error( e );
  122. }
  123. m_mainWindow->eidCard()->reconnect();
  124. return buffer;
  125. }
  126. void JsExtender::activateEmail( const QString &email )
  127. {
  128. QByteArray buffer;
  129. try {
  130. buffer = getUrl( SSLConnect::ActivateEmails, email );
  131. } catch( std::runtime_error &e ) {
  132. jsCall( "handleError", e.what() );
  133. jsCall( "setEmails", "forwardFailed", "" );
  134. return;
  135. }
  136. if ( !buffer.size() )
  137. {
  138. jsCall( "setEmails", "forwardFailed", "" );
  139. return;
  140. }
  141. xml.clear();
  142. xml.addData( buffer );
  143. QString result = "forwardFailed";
  144. while ( !xml.atEnd() )
  145. {
  146. xml.readNext();
  147. if ( xml.isStartElement() && xml.name() == "fault_code" )
  148. {
  149. result = xml.readElementText();
  150. break;
  151. }
  152. }
  153. jsCall( "setEmailActivate", result );
  154. }
  155. void JsExtender::loadEmails()
  156. {
  157. QByteArray buffer;
  158. try {
  159. buffer = getUrl( SSLConnect::EmailInfo, "" );
  160. } catch( std::runtime_error &e ) {
  161. jsCall( "handleError", e.what() );
  162. jsCall( "setEmails", "loadFailed", "" );
  163. return;
  164. }
  165. if ( !buffer.size() )
  166. {
  167. jsCall( "setEmails", "loadFailed", "" );
  168. return;
  169. }
  170. xml.clear();
  171. xml.addData( buffer );
  172. QString result = "loadFailed", emails;
  173. while ( !xml.atEnd() )
  174. {
  175. xml.readNext();
  176. if ( xml.isStartElement() )
  177. {
  178. if ( xml.name() == "fault_code" )
  179. {
  180. result = xml.readElementText();
  181. continue;
  182. }
  183. if ( xml.name() == "ametlik_aadress" )
  184. emails += readEmailAddresses();
  185. }
  186. }
  187. if ( emails.length() > 4 )
  188. emails = emails.right( emails.length() - 4 );
  189. jsCall( "setEmails", result, emails );
  190. }
  191. QString JsExtender::readEmailAddresses()
  192. {
  193. Q_ASSERT( xml.isStartElement() && xml.name() == "ametlik_aadress" );
  194. QString emails;
  195. while ( !xml.atEnd() )
  196. {
  197. xml.readNext();
  198. if ( xml.isStartElement() )
  199. {
  200. if ( xml.name() == "epost" )
  201. emails += "<BR>" + xml.readElementText();
  202. else if ( xml.name() == "suunamine" )
  203. emails += readForwards();
  204. }
  205. }
  206. return emails;
  207. }
  208. QString JsExtender::readForwards()
  209. {
  210. Q_ASSERT( xml.isStartElement() && xml.name() == "suunamine" );
  211. bool emailActive = false, forwardActive = false;
  212. QString email;
  213. while ( !xml.atEnd() )
  214. {
  215. xml.readNext();
  216. if ( xml.isEndElement() )
  217. break;
  218. if ( xml.isStartElement() )
  219. {
  220. if ( xml.name() == "epost" )
  221. email = xml.readElementText();
  222. else if ( xml.name() == "aktiivne" && xml.readElementText() == "true" )
  223. emailActive = true;
  224. else if ( xml.name() == "aktiiveeritud" && xml.readElementText() == "true" )
  225. forwardActive = true;
  226. }
  227. }
  228. return (emailActive && forwardActive ) ? tr( " - %1 (active)" ).arg( email ) : tr( " - %1 (not active)" ).arg( email );
  229. }
  230. void JsExtender::loadPicture()
  231. {
  232. QString result = "loadPicFailed";
  233. QByteArray buffer;
  234. try {
  235. buffer = getUrl( SSLConnect::PictureInfo, "" );
  236. } catch( std::runtime_error &e ) {
  237. jsCall( "handleError", e.what() );
  238. jsCall( "setPicture", "", result );
  239. return;
  240. }
  241. if ( !buffer.size() )
  242. {
  243. jsCall( "setPicture", "", result );
  244. return;
  245. }
  246. QPixmap pix;
  247. if ( pix.loadFromData( buffer ) )
  248. {
  249. QTemporaryFile file( QString( "%1%2XXXXXX.jpg" )
  250. .arg( QDir::tempPath() ).arg( QDir::separator() ) );
  251. file.setAutoRemove( false );
  252. if ( file.open() )
  253. {
  254. m_tempFile = file.fileName();
  255. if ( pix.save( &file ) )
  256. {
  257. jsCall( "setPicture", QUrl::fromLocalFile(m_tempFile).toString(), "" );
  258. return;
  259. }
  260. }
  261. jsCall( "setPicture", "", QString( "loadPicFailed3|%1" ).arg( file.errorString() ) );
  262. } else { //probably got xml error string
  263. QString result2 = "loadPicFailed2";
  264. xml.clear();
  265. xml.addData( buffer );
  266. while ( !xml.atEnd() )
  267. {
  268. xml.readNext();
  269. if ( xml.isStartElement() && xml.name() == "fault_code" )
  270. {
  271. result2 = xml.readElementText();
  272. break;
  273. }
  274. }
  275. jsCall( "setPicture", "", result2 );
  276. }
  277. }
  278. void JsExtender::savePicture()
  279. {
  280. if ( !QFile::exists( m_tempFile ) )
  281. {
  282. jsCall( "handleError", "savePicFailed" );
  283. return;
  284. }
  285. QString pFile = QDesktopServices::storageLocation( QDesktopServices::PicturesLocation );
  286. if ( m_mainWindow->eidCard() )
  287. pFile += QString( "%1%2.jpg" ).arg( QDir::separator() ).arg( m_mainWindow->eidCard()->getId() );
  288. QString file = QFileDialog::getSaveFileName( m_mainWindow, tr( "Save picture" ), pFile, tr( "JPEG (*.jpg *.jpeg);;PNG (*.png);;TIFF (*.tif *.tiff);;24-bit Bitmap (*.bmp)" ) );
  289. if( file.isEmpty() )
  290. return;
  291. QString ext = QFileInfo( file ).suffix();
  292. if( ext != "png" && ext != "jpg" && ext != "jpeg" && ext != "tiff" && ext != "bmp" )
  293. file.append( ".jpg" );
  294. QPixmap pix;
  295. if ( !pix.load( m_tempFile ) )
  296. {
  297. jsCall( "handleError", "savePicFailed" );
  298. return;
  299. }
  300. pix.save( file );
  301. }
  302. void JsExtender::getMidStatus()
  303. {
  304. QString result = "mobileFailed";
  305. QByteArray buffer;
  306. QString data = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
  307. "<SOAP-ENV:Body>"
  308. "<m:GetMIDTokens xmlns:m=\"urn:GetMIDTokens\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"/>"
  309. "</SOAP-ENV:Body>"
  310. "</SOAP-ENV:Envelope>";
  311. QString header = "POST /id/midstatusinfolive/ HTTP/1.1\r\n"
  312. "Host: " + QString(SK) + "\r\n"
  313. "Content-Type: text/xml\r\n"
  314. "Content-Length: " + QString::number( data.size() ) + "\r\n"
  315. "SOAPAction: \"\"\r\n"
  316. "Connection: close\r\n\r\n";
  317. try {
  318. buffer = getUrl( SSLConnect::MobileInfo, header + data );
  319. } catch( std::runtime_error &e ) {
  320. jsCall( "handleError", e.what() );
  321. jsCall( "setMobile", "", result );
  322. return;
  323. }
  324. if ( !buffer.size() )
  325. {
  326. jsCall( "setMobile", "", result );
  327. return;
  328. }
  329. //qDebug() << buffer;
  330. if ( !buffer.isEmpty() )
  331. {
  332. QDomDocument doc;
  333. if ( !doc.setContent( buffer ) )
  334. {
  335. jsCall( "handleError", result );
  336. return;
  337. }
  338. QDomElement e = doc.documentElement();
  339. if ( !e.elementsByTagName( "ResponseStatus" ).size() )
  340. {
  341. jsCall( "handleError", result );
  342. return;
  343. }
  344. MobileResult mRes = (MobileResult)e.elementsByTagName( "ResponseStatus" ).item(0).toElement().text().toInt();
  345. QString mResString, mNotice;
  346. switch( mRes )
  347. {
  348. case NoCert: mNotice = "mobileNoCert"; break;
  349. case NotActive: mNotice = "mobileNotActive"; break;
  350. case NoIDCert: mResString = "noIDCert"; break;
  351. case InternalError: mResString = "mobileInternalError"; break;
  352. case InterfaceNotReady: mResString = "mobileInterfaceNotReady"; break;
  353. case OK:
  354. default: break;
  355. }
  356. if ( !mResString.isEmpty() )
  357. {
  358. jsCall( "handleError", mResString );
  359. return;
  360. }
  361. if ( !mNotice.isEmpty() )
  362. {
  363. jsCall( "handleNotice", mNotice );
  364. return;
  365. }
  366. mResString = QString( "%1;%2;%3;%4" )
  367. .arg( e.elementsByTagName( "MSISDN" ).item(0).toElement().text() )
  368. .arg( e.elementsByTagName( "Operator" ).item(0).toElement().text() )
  369. .arg( e.elementsByTagName( "Status" ).item(0).toElement().text() )
  370. .arg( e.elementsByTagName( "URL" ).item(0).toElement().text() );
  371. jsCall( "setMobile", mResString );
  372. }
  373. }
  374. void JsExtender::httpRequestFinished( int, bool error )
  375. {
  376. if ( error)
  377. qDebug() << "Download failed: " << m_http.errorString();
  378. QByteArray result = m_http.readAll();
  379. }
  380. void JsExtender::showSettings()
  381. { (new SettingsDialog( m_mainWindow ) )->show(); }
  382. void JsExtender::showLoading( const QString &str )
  383. {
  384. bool wide = (str.size() > 20);
  385. if ( !m_loading )
  386. {
  387. m_loading = new QLabel( m_mainWindow );
  388. m_loading->setStyleSheet( "background-color: rgba(255,255,255,200); border: 1px solid #cddbeb; border-radius: 5px;"
  389. "color: #509b00; font-weight: bold; font-family: Arial; font-size: 18px;" );
  390. m_loading->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
  391. }
  392. m_loading->setFixedSize( wide ? 300 : 250, 100 );
  393. m_loading->move( wide ? 155 : 180, 305 );
  394. m_loading->setText( str );
  395. m_loading->show();
  396. QCoreApplication::processEvents();
  397. }
  398. void JsExtender::closeLoading()
  399. {
  400. if ( m_loading )
  401. m_loading->close();
  402. }
  403. void JsExtender::showMessage( const QString &type, const QString &message, const QString &title )
  404. {
  405. if ( type == "warning" )
  406. QMessageBox::warning( m_mainWindow, title.isEmpty() ? m_mainWindow->windowTitle() : title, message, QMessageBox::Ok );
  407. else if ( type == "error" )
  408. QMessageBox::critical( m_mainWindow, title.isEmpty() ? m_mainWindow->windowTitle() : title, message, QMessageBox::Ok );
  409. else
  410. QMessageBox::information( m_mainWindow, title.isEmpty() ? m_mainWindow->windowTitle() : title, message, QMessageBox::Ok );
  411. }
  412. bool JsExtender::updateCertAllowed()
  413. {
  414. QMessageBox::StandardButton b = QMessageBox::warning( m_mainWindow, tr("Certificate update"),
  415. tr("For updating certificates please close all programs which are interacting with smartcard "
  416. "(qdigidocclient, qdigidoccrypto, Firefox, Safari, Internet Explorer...)<br />"
  417. "After updating certificates it will no longer be possible to decrypt documents that were encrypted with the old certificate.<br />"
  418. "Do you want to continue?"),
  419. QMessageBox::Yes|QMessageBox::No, QMessageBox::No );
  420. if( b == QMessageBox::No )
  421. return false;
  422. bool result = false;
  423. try {
  424. CertUpdate *c = new CertUpdate( m_mainWindow->cardManager()->activeReaderNum(), this );
  425. result = c->checkUpdateAllowed();
  426. } catch ( std::runtime_error &e ) {
  427. QMessageBox::warning( m_mainWindow, tr( "Certificate update" ), tr("Certificate update failed:<br />%1").arg( QString::fromUtf8( e.what() ) ), QMessageBox::Ok );
  428. }
  429. return result;
  430. }
  431. bool JsExtender::updateCert()
  432. {
  433. bool result = false;
  434. try {
  435. CertUpdate *c = new CertUpdate( m_mainWindow->cardManager()->activeReaderNum(), this );
  436. if ( c->checkUpdateAllowed() && m_mainWindow->eidCard()->m_authCert )
  437. {
  438. c->startUpdate();
  439. result = true;
  440. }
  441. } catch ( std::runtime_error &e ) {
  442. QMessageBox::warning( m_mainWindow, tr( "Certificate update" ), tr("Certificate update failed: %1").arg( QString::fromUtf8( e.what() ) ), QMessageBox::Ok );
  443. }
  444. return result;
  445. }