PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/applicationFormFinalizePage.cpp

https://gitlab.com/bjk/qpwmc
C++ | 461 lines | 379 code | 57 blank | 25 comment | 71 complexity | 30aba0234115033586223bdb10d04b8b MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. Copyright (C) 2013-2020 Ben Kibbey <bjk@luxsci.net>
  3. This file is part of qpwmc.
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
  15. USA
  16. */
  17. #include <QTimer>
  18. #include <QCalendarWidget>
  19. #include <QDateTime>
  20. #include "pwmdMainWindow.h"
  21. #include "applicationFormFinalizePage.h"
  22. #include "applicationForm.h"
  23. #include "applicationFormXmlHandler.h"
  24. #include "applicationFormDateSelector.h"
  25. #include "cmdIds.h"
  26. ApplicationFormFinalizePage::ApplicationFormFinalizePage (QWidget *p)
  27. : QWizardPage (p)
  28. {
  29. ui.setupUi (this);
  30. pwm = NULL;
  31. newFile = false;
  32. filename = QString ();
  33. ownHandle = true;
  34. saving = false;
  35. }
  36. void
  37. ApplicationFormFinalizePage::slotBusy (int cmdId, bool b)
  38. {
  39. (void)cmdId;
  40. if (b)
  41. setCursor (Qt::WaitCursor);
  42. else
  43. unsetCursor ();
  44. }
  45. void
  46. ApplicationFormFinalizePage::slotKnownHostCallback (void *data,
  47. const char *host,
  48. const char *key, size_t len)
  49. {
  50. gpg_error_t rc = Pwmd::knownHostPrompt (data, host, key, len);
  51. ApplicationForm *w = qobject_cast<ApplicationForm *> (wizard ());
  52. w->setHasError (rc != 0);
  53. emit knownHostRc (rc);
  54. }
  55. void
  56. ApplicationFormFinalizePage::commit ()
  57. {
  58. ApplicationForm *form = static_cast<ApplicationForm *>(wizard ());
  59. bool notFound = false;
  60. wizard ()->setOptions (QWizard::NoCancelButton|QWizard::NoBackButtonOnLastPage);
  61. QAbstractButton *pb = wizard ()->button (QWizard::FinishButton);
  62. pb->setEnabled (false);
  63. foreach (ApplicationFormWidget *w, form->handler->widgets ())
  64. {
  65. QString path = QString ();
  66. if (w->id () == "pwmdRootElement")
  67. continue;
  68. if (!w->childOf ().isEmpty ())
  69. {
  70. path = form->buildElementPath (path, w->childOf (), notFound);
  71. if (notFound)
  72. break;
  73. }
  74. if (!w->pwmdName ().isEmpty ())
  75. {
  76. if (!path.isEmpty ())
  77. path += "\t";
  78. path += w->pwmdName ();
  79. path.append ("\t");
  80. if (!w->dateSelector () && !w->value ().isEmpty ())
  81. path.append (w->value ());
  82. }
  83. else if (!path.isEmpty ())
  84. path.append ("\t");
  85. if (w->dateSelector () && !w->value ().isEmpty ())
  86. {
  87. ApplicationFormDateSelector *d = qobject_cast<ApplicationFormDateSelector *> (w->widget ());
  88. path += d->date ().toString (w->value ());
  89. if (!w->value ().endsWith ("<TAB>"))
  90. path += "<TAB>";
  91. }
  92. path = path.replace ("<TAB>", "\t");
  93. if (path.isEmpty ())
  94. continue;
  95. ApplicationElement *ae = new ApplicationElement (path, w->isHidden ());
  96. ae->setAttrs (w->attrs ());
  97. elements.append (ae);
  98. }
  99. /* Remove paths that begin with elements from other paths to prevent
  100. redundant element creation. */
  101. for (int i = 0; !notFound && i < elements.count (); i++)
  102. {
  103. ApplicationElement *e = elements.at (i);
  104. for (int n = 0; n < elements.count (); n++)
  105. {
  106. ApplicationElement *x = elements.at (n);
  107. if (e->path ().startsWith (x->path ()) && x != e)
  108. {
  109. elements.removeAt (n);
  110. delete x;
  111. break;
  112. }
  113. }
  114. }
  115. ui.progressBar->setMaximum (elements.count());
  116. filename = form->buildElementPath (QString (), "pwmdFilename", notFound);
  117. QString sock = form->buildElementPath (QString (), "pwmdSocket", notFound);
  118. qRegisterMetaType <Pwmd::ConnectionState>("Pwmd::ConnectionState");
  119. qRegisterMetaType <gpg_error_t>("gpg_error_t");
  120. if (!pwm)
  121. {
  122. ownHandle = true;
  123. pwm = new Pwmd (filename, "qpwmc", sock, this);
  124. pwm->setData (sock.toUtf8 ().data ());
  125. pwm->setLockOnOpen (true);
  126. connect (pwm, SIGNAL (stateChanged (Pwmd::ConnectionState)),
  127. this, SLOT (slotConnectionStateChanged (Pwmd::ConnectionState)));
  128. connect (pwm, SIGNAL (statusMessage (QString, void *)), this,
  129. SLOT (slotStatusMessage (QString, void *)));
  130. connect (pwm, SIGNAL (knownHost (void *, const char *, const char *, size_t)), this, SLOT (slotKnownHostCallback (void *, const char *, const char *, size_t)));
  131. if (PwmdRemoteHost::fillRemoteHost (sock, hostData))
  132. {
  133. pwm->setSocket (PwmdRemoteHost::socketUrl (hostData));
  134. pwm->setConnectParameters (hostData.socketArgs ());
  135. pwmd_setopt (pwm->handle (), PWMD_OPTION_SSH_AGENT,
  136. hostData.sshAgent ());
  137. pwmd_setopt (pwm->handle (), PWMD_OPTION_SSH_NEEDS_PASSPHRASE,
  138. hostData.sshNeedsPassphrase ());
  139. pwmd_setopt (pwm->handle (), PWMD_OPTION_SOCKET_TIMEOUT,
  140. hostData.socketTimeout ());
  141. pwmd_setopt (pwm->handle (), PWMD_OPTION_TLS_VERIFY,
  142. hostData.tlsVerify ());
  143. if (!hostData.tlsPriority().isEmpty ())
  144. pwmd_setopt (pwm->handle (), PWMD_OPTION_TLS_PRIORITY,
  145. hostData.tlsPriority ().toUtf8 ().data ());
  146. }
  147. }
  148. disconnect (pwm, SIGNAL (busy (int, bool)), this, SLOT (slotBusy (int, bool)));
  149. connect (pwm, SIGNAL (busy (int, bool)), this, SLOT (slotBusy (int, bool)));
  150. disconnect (pwm, SIGNAL (commandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)), this, SLOT (slotCommandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)));
  151. connect (pwm, SIGNAL (commandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)), this, SLOT (slotCommandResult (PwmdCommandQueueItem *, QString, gpg_error_t, bool)));
  152. if (!notFound)
  153. {
  154. if (pwm->state () == Pwmd::Init)
  155. pwm->connect (0, 0, true);
  156. if (ownHandle)
  157. message (QString (tr ("Connecting to %1...")).arg (pwm->socket ()));
  158. if (pwm->state () == Pwmd::Connected || pwm->state () == Pwmd::Init)
  159. {
  160. PwmdInquireData *inq = new PwmdInquireData (pwm->handle(), pwm->filename());
  161. pwm->open (Pwmd::inquireCallback, inq);
  162. return;
  163. }
  164. openFileFinalize ();
  165. }
  166. }
  167. void
  168. ApplicationFormFinalizePage::attrStoreFinalize (ApplicationElement *e,
  169. gpg_error_t &rc, bool isFinal)
  170. {
  171. (void)rc;
  172. if (isFinal)
  173. connectionProgress (elements.indexOf (e));
  174. }
  175. void
  176. ApplicationFormFinalizePage::getContentFinalize (ApplicationElement *e,
  177. gpg_error_t &rc, bool queued)
  178. {
  179. QString attrName;
  180. QString attrValue;
  181. bool tab = e->path ().endsWith ("\t");
  182. QStringList l = e->path ().split ("\t");
  183. if (tab || e->isHidden ())
  184. l.removeLast ();
  185. QString s = QString (tr ("Creating path: %1")).arg (l.join ("->"));
  186. if (!rc)
  187. {
  188. message (s);
  189. message (tr ("Not overwriting existing content!"));
  190. connectionProgress (elements.indexOf (e));
  191. return;
  192. }
  193. else if (gpg_err_code (rc) == GPG_ERR_ELEMENT_NOT_FOUND
  194. || gpg_err_code (rc) == GPG_ERR_NO_DATA)
  195. rc = 0;
  196. if (rc)
  197. {
  198. if (!queued)
  199. {
  200. message (s);
  201. message (QString ("ERR %1: %2").arg (rc).arg (gpg_strerror (rc)));
  202. }
  203. ApplicationForm *w = qobject_cast<ApplicationForm *> (wizard ());
  204. w->setHasError ();
  205. connectionProgress (elements.indexOf (e));
  206. return;
  207. }
  208. message (s);
  209. PwmdInquireData *inq = new PwmdInquireData (e->path ());
  210. inq->setUserPtr (e);
  211. inq->setUserBool (!e->attrs ().count ()); // final command for element
  212. pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFormStoreContent, "STORE",
  213. Pwmd::inquireCallback, inq), true);
  214. for (int i = 0; i < e->attrs ().count (); i++)
  215. {
  216. ApplicationFormAttr *a = e->attrs ().at (i);
  217. QString args = QString ("SET %1 %2").arg (a->name ()).arg (e->pathNoContent ());
  218. if (!a->value ().isEmpty ())
  219. args.append (QString (" %1").arg (a->value ()));
  220. inq = new PwmdInquireData (args);
  221. inq->setUserPtr (e);
  222. pwm->command (new PwmdCommandQueueItem (PwmdCmdIdFormAttrNew, "ATTR",
  223. Pwmd::inquireCallback, inq), true);
  224. if (i+1 == e->attrs ().count ())
  225. inq->setUserBool (true); // final command for element
  226. }
  227. pwm->runQueue ();
  228. }
  229. void
  230. ApplicationFormFinalizePage::openFileFinalize ()
  231. {
  232. for (int i = 0; i < elements.count (); i++)
  233. {
  234. ApplicationElement *e = elements.at (i);
  235. /* To be on the safe side we will never overwrite the content of an
  236. element since it may be shared with another element. The exception
  237. is if the element exists but the content is empty. */
  238. PwmdInquireData *inq = new PwmdInquireData (e->pathNoContent ());
  239. inq->setUserPtr (e);
  240. PwmdCommandQueueItem *item = new PwmdCommandQueueItem (PwmdCmdIdFormGetContent,
  241. "GET",
  242. Pwmd::inquireCallback,
  243. inq);
  244. item->addError (GPG_ERR_SOURCE_USER_1, GPG_ERR_ELEMENT_NOT_FOUND);
  245. pwm->command (item, true);
  246. }
  247. pwm->runQueue ();
  248. }
  249. ApplicationFormFinalizePage::~ApplicationFormFinalizePage ()
  250. {
  251. while (elements.count ())
  252. {
  253. ApplicationElement *e = elements.takeFirst ();
  254. delete e;
  255. }
  256. elements.clear ();
  257. }
  258. void
  259. ApplicationFormFinalizePage::slotStatusMessage (QString s, void *data)
  260. {
  261. (void)data;
  262. if (s == "NEWFILE")
  263. newFile = true;
  264. }
  265. void
  266. ApplicationFormFinalizePage::slotConnectionStateChanged (Pwmd::ConnectionState s)
  267. {
  268. switch (s)
  269. {
  270. case Pwmd::Init:
  271. pwmd_setopt (pwm->handle (), PWMD_OPTION_SOCKET_TIMEOUT,
  272. hostData.connectTimeout ());
  273. pwmd_setopt (pwm->handle (), PWMD_OPTION_SSH_AGENT,
  274. hostData.sshAgent ());
  275. pwmd_setopt (pwm->handle (), PWMD_OPTION_SSH_NEEDS_PASSPHRASE,
  276. hostData.sshNeedsPassphrase ());
  277. pwmd_setopt (pwm->handle (), PWMD_OPTION_TLS_VERIFY,
  278. hostData.tlsVerify ());
  279. if (!hostData.tlsPriority().isEmpty ())
  280. pwmd_setopt (pwm->handle (), PWMD_OPTION_TLS_PRIORITY,
  281. hostData.tlsPriority ().toUtf8 ().data ());
  282. pwmd_setopt (pwm->handle (), PWMD_OPTION_SOCKET_TIMEOUT,
  283. hostData.connectTimeout ());
  284. {
  285. QAbstractButton *pb = wizard ()->button (QWizard::FinishButton);
  286. pb->setEnabled (true);
  287. }
  288. break;
  289. case Pwmd::Connected:
  290. message (QString (tr ("Opening data file %1...")).arg (filename));
  291. pwmd_setopt (pwm->handle (), PWMD_OPTION_SOCKET_TIMEOUT,
  292. hostData.socketTimeout ());
  293. break;
  294. default:
  295. break;
  296. }
  297. }
  298. void
  299. ApplicationFormFinalizePage::connectionProgress (int i)
  300. {
  301. ui.progressBar->setValue (i+1);
  302. if (!saving && ui.progressBar->value () == ui.progressBar->maximum())
  303. {
  304. saving = true;
  305. save ();
  306. }
  307. }
  308. void
  309. ApplicationFormFinalizePage::message (const QString &s)
  310. {
  311. QString str = ui.textEdit->document ()->toPlainText ();
  312. ui.textEdit->document ()->setPlainText (QString (str + s + "\n").replace ("\t", "<TAB>"));
  313. }
  314. void
  315. ApplicationFormFinalizePage::slotCommandResult (PwmdCommandQueueItem *item,
  316. QString result, gpg_error_t rc,
  317. bool queued)
  318. {
  319. (void)result;
  320. PwmdInquireData *inq = item->data ();
  321. ApplicationForm *w = qobject_cast<ApplicationForm *> (wizard ());
  322. switch (item->id ())
  323. {
  324. case PwmdCmdIdInternalPassword:
  325. if (rc)
  326. w->setHasError ();
  327. item->setSeen ();
  328. return;
  329. case PwmdCmdIdInternalStatusError:
  330. if (ownHandle) // our own pwm handle
  331. {
  332. message (QString (tr ("Connection error: %1")).arg (gpg_strerror (rc)));
  333. QAbstractButton *pb = wizard ()->button (QWizard::FinishButton);
  334. pb->setEnabled (true);
  335. }
  336. break;
  337. case PwmdCmdIdInternalConnect:
  338. if (rc)
  339. {
  340. if (gpg_err_code (rc) == GPG_ERR_ETIMEDOUT)
  341. pwm->reset ();
  342. message (tr ("Failed to connect."));
  343. }
  344. break;
  345. case PwmdCmdIdInternalOpen:
  346. if (!rc)
  347. openFileFinalize ();
  348. break;
  349. case PwmdCmdIdInternalSave:
  350. if (rc)
  351. message (tr ("Failed to save."));
  352. else
  353. message (tr ("Save succeeded."));
  354. break;
  355. case PwmdCmdIdFormGetContent:
  356. getContentFinalize (static_cast <ApplicationElement *> (inq->userPtr()), rc, queued);
  357. break;
  358. case PwmdCmdIdFormStoreContent:
  359. attrStoreFinalize (static_cast <ApplicationElement *> (inq->userPtr()), rc, inq->userBool ());
  360. break;
  361. case PwmdCmdIdFormAttrNew:
  362. attrStoreFinalize (static_cast <ApplicationElement *> (inq->userPtr()), rc, inq->userBool ());
  363. default:
  364. break;
  365. }
  366. if (rc && !item->checkError (rc) && !queued)
  367. w->setHasError ();
  368. item->setSeen ();
  369. }
  370. void
  371. ApplicationFormFinalizePage::save ()
  372. {
  373. if (ownHandle)
  374. {
  375. message (tr ("Saving ..."));
  376. PwmdSaveDialog *d = new PwmdSaveDialog (pwm, newFile);
  377. PwmdSaveWidget *w = d->widget ();
  378. if (newFile)
  379. {
  380. if (d->exec ())
  381. message (tr ("Cancelled."));
  382. }
  383. else
  384. w->save (0, true);
  385. delete d;
  386. }
  387. else
  388. {
  389. ApplicationForm *w = qobject_cast<ApplicationForm *> (wizard ());
  390. message (w->hasError () ? tr ("Failed.") : tr ("Done!"));
  391. }
  392. QAbstractButton *pb = wizard ()->button (QWizard::FinishButton);
  393. pb->setEnabled (true);
  394. }
  395. void
  396. ApplicationFormFinalizePage::setHandle (Pwmd *h)
  397. {
  398. pwm = h;
  399. ownHandle = false;
  400. }