From 7ce35f81de4629094b8d5d5dfc2a29bc426f2e9d Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 11 Nov 2020 17:40:42 -0500 Subject: [PATCH 1/6] Cleanup entry level Auto-Type menu * Show the sequence that will be typed when performing the default action * Combine default sequence action with Username / Password options * Fix #4939 - confirm prior to performing entry level auto-type if "Always Ask Before Auto-Type" is enabled --- docs/images/autotype_entrylevel.png | Bin 106903 -> 84016 bytes src/gui/DatabaseWidget.cpp | 36 ++++++++++----------- src/gui/DatabaseWidget.h | 4 +-- src/gui/MainWindow.cpp | 37 ++++++++++++++------- src/gui/MainWindow.ui | 48 ++++++++++++++++++++-------- 5 files changed, 80 insertions(+), 45 deletions(-) diff --git a/docs/images/autotype_entrylevel.png b/docs/images/autotype_entrylevel.png index 5a92df4e9417c3c0af1006ae1a8afdc9ddb5bb14..0c9479912f185db4f3dfefe9acf7cd26ac89d204 100644 GIT binary patch literal 84016 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 literal 106903 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�rjQFU96M5=mJi^%H*(G4U;dn;iHOZacXwe#ED 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 Y-*m&29L2R diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 9d861fb3c..737a4a2f6 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -759,44 +759,44 @@ void DatabaseWidget::removeFromAgent() } #endif -void DatabaseWidget::performAutoType() +void DatabaseWidget::performAutoType(const QString& sequence) { auto currentEntry = currentSelectedEntry(); if (currentEntry) { - autoType()->performAutoType(currentEntry, window()); + // TODO: Include name of previously active window in confirmation question + if (config()->get(Config::Security_AutoTypeAsk).toBool() + && MessageBox::question( + this, tr("Confirm Auto-Type"), tr("Perform Auto-Type into the previously active window?")) + != MessageBox::Yes) { + return; + } + + if (sequence.isEmpty()) { + autoType()->performAutoType(currentEntry, window()); + } else { + autoType()->performAutoTypeWithSequence(currentEntry, sequence, window()); + } } } void DatabaseWidget::performAutoTypeUsername() { - auto currentEntry = currentSelectedEntry(); - if (currentEntry) { - autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{USERNAME}"), window()); - } + performAutoType(QStringLiteral("{USERNAME}")); } void DatabaseWidget::performAutoTypeUsernameEnter() { - auto currentEntry = currentSelectedEntry(); - if (currentEntry) { - autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{USERNAME}{ENTER}"), window()); - } + performAutoType(QStringLiteral("{USERNAME}{ENTER}")); } void DatabaseWidget::performAutoTypePassword() { - auto currentEntry = currentSelectedEntry(); - if (currentEntry) { - autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{PASSWORD}"), window()); - } + performAutoType(QStringLiteral("{PASSWORD}")); } void DatabaseWidget::performAutoTypePasswordEnter() { - auto currentEntry = currentSelectedEntry(); - if (currentEntry) { - autoType()->performAutoTypeWithSequence(currentEntry, QStringLiteral("{PASSWORD}{ENTER}"), window()); - } + performAutoType(QStringLiteral("{PASSWORD}{ENTER}")); } void DatabaseWidget::openUrl() diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index fc8d9ee73..e56e65956 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -105,6 +105,7 @@ public: QStringList customEntryAttributes() const; bool isEditWidgetModified() const; void clearAllWidgets(); + Entry* currentSelectedEntry(); bool currentEntryHasTitle(); bool currentEntryHasUsername(); bool currentEntryHasPassword(); @@ -181,7 +182,7 @@ public slots: void addToAgent(); void removeFromAgent(); #endif - void performAutoType(); + void performAutoType(const QString& sequence = {}); void performAutoTypeUsername(); void performAutoTypeUsernameEnter(); void performAutoTypePassword(); @@ -257,7 +258,6 @@ private: bool confirmDeleteEntries(QList entries, bool permanent); void performIconDownloads(const QList& entries, bool force = false); bool performSave(QString& errorMessage, const QString& fileName = {}); - Entry* currentSelectedEntry(); QSharedPointer m_db; diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index ceb1739b5..de19f37a9 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "config-keepassx.h" @@ -128,7 +129,6 @@ MainWindow::MainWindow() m_entryContextMenu->addAction(m_ui->menuEntryTotp->menuAction()); m_entryContextMenu->addSeparator(); m_entryContextMenu->addAction(m_ui->actionEntryAutoType); - m_entryContextMenu->addAction(m_ui->menuEntryAutoTypeWithSequence->menuAction()); m_entryContextMenu->addSeparator(); m_entryContextMenu->addAction(m_ui->actionEntryEdit); m_entryContextMenu->addAction(m_ui->actionEntryClone); @@ -144,6 +144,20 @@ MainWindow::MainWindow() m_entryNewContextMenu = new QMenu(this); m_entryNewContextMenu->addAction(m_ui->actionEntryNew); + // Build Entry Level Auto-Type menu + auto autotypeMenu = new QMenu({}, this); + autotypeMenu->addAction(m_ui->actionEntryAutoTypeSequence); + autotypeMenu->addSeparator(); + autotypeMenu->addAction(m_ui->actionEntryAutoTypeUsername); + autotypeMenu->addAction(m_ui->actionEntryAutoTypeUsernameEnter); + autotypeMenu->addAction(m_ui->actionEntryAutoTypePassword); + autotypeMenu->addAction(m_ui->actionEntryAutoTypePasswordEnter); + m_ui->actionEntryAutoType->setMenu(autotypeMenu); + auto autoTypeButton = qobject_cast(m_ui->toolBar->widgetForAction(m_ui->actionEntryAutoType)); + if (autoTypeButton) { + autoTypeButton->setPopupMode(QToolButton::MenuButtonPopup); + } + restoreGeometry(config()->get(Config::GUI_MainWindowGeometry).toByteArray()); restoreState(config()->get(Config::GUI_MainWindowState).toByteArray()); #ifdef WITH_XC_BROWSER @@ -223,12 +237,7 @@ MainWindow::MainWindow() m_ui->toolbarSeparator->setVisible(false); m_showToolbarSeparator = config()->get(Config::GUI_ApplicationTheme).toString() != "classic"; - bool isAutoTypeAvailable = autoType()->isAvailable(); - m_ui->actionEntryAutoType->setVisible(isAutoTypeAvailable); - m_ui->actionEntryAutoTypeUsername->setVisible(isAutoTypeAvailable); - m_ui->actionEntryAutoTypeUsernameEnter->setVisible(isAutoTypeAvailable); - m_ui->actionEntryAutoTypePassword->setVisible(isAutoTypeAvailable); - m_ui->actionEntryAutoTypePasswordEnter->setVisible(isAutoTypeAvailable); + m_ui->actionEntryAutoType->setVisible(autoType()->isAvailable()); m_inactivityTimer = new InactivityTimer(this); connect(m_inactivityTimer, SIGNAL(inactivityDetected()), this, SLOT(lockDatabasesAfterInactivity())); @@ -257,7 +266,7 @@ MainWindow::MainWindow() m_ui->actionEntryMoveDown->setShortcut(Qt::CTRL + Qt::ALT + Qt::Key_Down); m_ui->actionEntryCopyUsername->setShortcut(Qt::CTRL + Qt::Key_B); m_ui->actionEntryCopyPassword->setShortcut(Qt::CTRL + Qt::Key_C); - m_ui->actionEntryAutoType->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_V); + m_ui->actionEntryAutoTypeSequence->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_V); m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_U); m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::Key_U); @@ -284,7 +293,7 @@ MainWindow::MainWindow() m_ui->actionEntryMoveDown->setShortcutVisibleInContextMenu(true); m_ui->actionEntryCopyUsername->setShortcutVisibleInContextMenu(true); m_ui->actionEntryCopyPassword->setShortcutVisibleInContextMenu(true); - m_ui->actionEntryAutoType->setShortcutVisibleInContextMenu(true); + m_ui->actionEntryAutoTypeSequence->setShortcutVisibleInContextMenu(true); m_ui->actionEntryOpenUrl->setShortcutVisibleInContextMenu(true); m_ui->actionEntryCopyURL->setShortcutVisibleInContextMenu(true); m_ui->actionEntryAddToAgent->setShortcutVisibleInContextMenu(true); @@ -360,7 +369,7 @@ MainWindow::MainWindow() m_ui->actionEntryEdit->setIcon(icons()->icon("entry-edit")); m_ui->actionEntryDelete->setIcon(icons()->icon("entry-delete")); m_ui->actionEntryAutoType->setIcon(icons()->icon("auto-type")); - m_ui->menuEntryAutoTypeWithSequence->setIcon(icons()->icon("auto-type")); + m_ui->actionEntryAutoTypeSequence->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypeUsername->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypeUsernameEnter->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypePassword->setIcon(icons()->icon("auto-type")); @@ -458,6 +467,7 @@ MainWindow::MainWindow() m_actionMultiplexer.connect(m_ui->actionEntryCopyURL, SIGNAL(triggered()), SLOT(copyURL())); m_actionMultiplexer.connect(m_ui->actionEntryCopyNotes, SIGNAL(triggered()), SLOT(copyNotes())); m_actionMultiplexer.connect(m_ui->actionEntryAutoType, SIGNAL(triggered()), SLOT(performAutoType())); + m_actionMultiplexer.connect(m_ui->actionEntryAutoTypeSequence, SIGNAL(triggered()), SLOT(performAutoType())); m_actionMultiplexer.connect( m_ui->actionEntryAutoTypeUsername, SIGNAL(triggered()), SLOT(performAutoTypeUsername())); m_actionMultiplexer.connect( @@ -782,7 +792,11 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->menuEntryCopyAttribute->setEnabled(singleEntrySelected); m_ui->menuEntryTotp->setEnabled(singleEntrySelected); m_ui->actionEntryAutoType->setEnabled(singleEntrySelected); - m_ui->menuEntryAutoTypeWithSequence->setEnabled(singleEntrySelected); + m_ui->actionEntryAutoType->menu()->setEnabled(singleEntrySelected); + m_ui->actionEntryAutoTypeSequence->setText( + singleEntrySelected ? dbWidget->currentSelectedEntry()->effectiveAutoTypeSequence() + : Group::RootAutoTypeSequence); + m_ui->actionEntryAutoTypeSequence->setEnabled(singleEntrySelected); m_ui->actionEntryAutoTypeUsername->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername()); m_ui->actionEntryAutoTypeUsernameEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername()); @@ -841,7 +855,6 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyURL, m_ui->actionEntryOpenUrl, m_ui->actionEntryAutoType, - m_ui->menuEntryAutoTypeWithSequence->menuAction(), m_ui->actionEntryDownloadIcon, m_ui->actionEntryCopyNotes, m_ui->actionEntryCopyTitle, diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index b57ef8482..125ef23f2 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -310,18 +310,6 @@ - - - false - - - Perform Auto-Type Sequence - - - - - - @@ -336,7 +324,6 @@ - @@ -704,6 +691,12 @@ {USERNAME} + + {USERNAME} + + + {USERNAME} + @@ -712,6 +705,12 @@ {USERNAME}{ENTER} + + {USERNAME}{ENTER} + + + {USERNAME}{ENTER} + @@ -720,6 +719,12 @@ {PASSWORD} + + {PASSWORD} + + + {PASSWORD} + @@ -728,6 +733,12 @@ {PASSWORD}{ENTER} + + {PASSWORD}{ENTER} + + + {PASSWORD}{ENTER} + @@ -1023,6 +1034,17 @@ Ctrl+Shift+C + + + {USERNAME}{TAB}{PASSWORD}{ENTER} + + + {USERNAME}{TAB}{PASSWORD}{ENTER} + + + {USERNAME}{TAB}{PASSWORD}{ENTER} + + From d9ae449f0424c7d296a2fd1372d3393b5c7c0152 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Mon, 15 Feb 2021 17:28:16 -0500 Subject: [PATCH 2/6] Improve Auto-Type Select Dialog Significant improvements to the Auto-Type select dialog. Reduce stale and unnecessary code paths. * Close select dialog when databases are locked. * Close open modal dialogs prior to showing the Auto-Type select dialog to prevent interference. * Never perform Auto-Type on the KeePassXC window. * Only filter match list based on Group, Title, and Username column data (ie, ignore sequence column) * Always show the sequence column (revert feature) * Show selection dialog if there are no matches to allow for a database search * Close #3630 - Allow typing {USERNAME} and {PASSWORD} from selection dialog (right-click menu). * Close #429 - Ability to search open databases for an entry from the Auto-Type selection dialog. * Fix #5361 - Default size of selection dialog doesn't cut off matches --- docs/images/autotype_selection_dialog.png | Bin 32857 -> 27332 bytes .../autotype_selection_dialog_search.png | Bin 0 -> 31823 bytes .../autotype_selection_dialog_type_menu.png | Bin 0 -> 36766 bytes docs/topics/AutoType.adoc | 14 +- docs/topics/DownloadInstall.adoc | 2 + docs/topics/Welcome.adoc | 2 + src/CMakeLists.txt | 8 +- src/autotype/AutoType.cpp | 204 ++------- src/autotype/AutoType.h | 9 +- src/autotype/AutoTypeFilterLineEdit.cpp | 39 -- src/autotype/AutoTypeFilterLineEdit.h | 42 -- src/{core => autotype}/AutoTypeMatch.h | 27 +- .../entry => autotype}/AutoTypeMatchModel.cpp | 25 +- .../entry => autotype}/AutoTypeMatchModel.h | 2 +- src/autotype/AutoTypeMatchView.cpp | 120 +++++ .../entry => autotype}/AutoTypeMatchView.h | 25 +- src/autotype/AutoTypeSelectDialog.cpp | 420 ++++++++++++------ src/autotype/AutoTypeSelectDialog.h | 47 +- src/autotype/AutoTypeSelectDialog.ui | 197 ++++++++ src/autotype/AutoTypeSelectView.cpp | 62 --- src/autotype/AutoTypeSelectView.h | 41 -- src/autotype/WildcardMatcher.cpp | 96 ---- src/autotype/WildcardMatcher.h | 46 -- src/browser/BrowserService.cpp | 4 + src/core/AutoTypeMatch.cpp | 43 -- src/core/Entry.cpp | 70 +++ src/core/Entry.h | 1 + src/fdosecrets/objects/Service.cpp | 2 +- src/gui/DatabaseTabWidget.cpp | 8 +- src/gui/DatabaseTabWidget.h | 4 +- src/gui/MainWindow.cpp | 13 +- src/gui/MainWindow.h | 7 +- src/gui/SearchHelpWidget.ui | 2 +- src/gui/SearchWidget.cpp | 4 +- src/gui/entry/AutoTypeMatchView.cpp | 154 ------- tests/CMakeLists.txt | 3 - tests/TestWildcardMatcher.cpp | 88 ---- tests/TestWildcardMatcher.h | 46 -- 38 files changed, 830 insertions(+), 1047 deletions(-) create mode 100644 docs/images/autotype_selection_dialog_search.png create mode 100644 docs/images/autotype_selection_dialog_type_menu.png delete mode 100644 src/autotype/AutoTypeFilterLineEdit.cpp delete mode 100644 src/autotype/AutoTypeFilterLineEdit.h rename src/{core => autotype}/AutoTypeMatch.h (56%) rename src/{gui/entry => autotype}/AutoTypeMatchModel.cpp (88%) rename src/{gui/entry => autotype}/AutoTypeMatchModel.h (98%) create mode 100644 src/autotype/AutoTypeMatchView.cpp rename src/{gui/entry => autotype}/AutoTypeMatchView.h (72%) create mode 100644 src/autotype/AutoTypeSelectDialog.ui delete mode 100644 src/autotype/AutoTypeSelectView.cpp delete mode 100644 src/autotype/AutoTypeSelectView.h delete mode 100644 src/autotype/WildcardMatcher.cpp delete mode 100644 src/autotype/WildcardMatcher.h delete mode 100644 src/core/AutoTypeMatch.cpp delete mode 100644 src/gui/entry/AutoTypeMatchView.cpp delete mode 100644 tests/TestWildcardMatcher.cpp delete mode 100644 tests/TestWildcardMatcher.h diff --git a/docs/images/autotype_selection_dialog.png b/docs/images/autotype_selection_dialog.png index 6f15a6ea68f0cc9fc40b391e2a4a0acf2cc76a2c..ce94f6cfa9a033b748177074c81d57149a94bf92 100644 GIT binary patch literal 27332 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⁣ob|d;ouI2DQfN@O`3MdAZD{n1n#M z9^1LMCGBNDl{N7!^`zn%cK+Dk;v`N^hs2EA1-$KorSd{%IsQ6lBLXjMbV^7B#x#CS zBmmQ=1UEr=i9Vk@Oo^pTOKum$D(ux)BUCcZ4AwT-5=g7vYJHbL03g@IF+-!;MhIV0E&X^$5D%I*#cvE7$^7p75eb8 zBa?n1`}eAhf>2lpAQ-$>x{jPt_C*~b(4%J723>&wTmvc(6-={AV+fnTj{tiyZZKpi_D-wA^o>sE=fiiQECj^+64FX_#c5}W{0azEaHzkC zOlW9F-;H`Upld=Rf!k=;GJ`$?$8qhA)F2F+iQh)e-e8DDAN&{6N@m25epn6KSe2Zj zrYrV!P1ZrZaxjN-k_ug_SZFXHp0&TOxnH7xRqSBD;O57#Mq4#DnH|gG`ggUyO;}X# zag$#|l-zi?RksCVtu?zGXhLmAQNRp&g4jTBXNxun*fI_S+%dlLuH!i{j?}eV!H0;l zAW?4^3CW*We5_Cab`O#*?(FAC)kQ=a5pZYdIW8`$+_7OsX1$zCwX`6I2d!}yVo
N?hj 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 literal 32857 zcmZ5{Wl&r})9ykD5&{HSAOr{y2(UN>WS-0C)`q0A4Ymzj~3ZqWb3n z0LcFozC*yz&(C*vcW2kfr>CcRt>KDVmKPTn4-XH@z7&m(jW_pKG&FSk`};C3q_eZL zg@uKB7S7w-+sDVptE;Pvi;Ei@8+r+!$HvC``}>hyS~@#BNj`k2c#Sp(|C<8Xdc#hKJHetlv`Ll+}QcXmC>8GK}0cPbM*UU_{o7ymtG z=J>qM?tCWN%F1dyPVV8MDY{!Pe(o+QDe3NR_65I%2;JP>U0$n~W8=g9e4<4`IE}V7 z4GnKzge(n>LbMByT*4gWGo2$19iOvTqAcA)YHD7qwO4Dn02MVPB7#O(C%QGGz2Z|6$+%ca(w60IiI~;Qv1j-z ztf%e9q`~>qV!h|*Wq5YZ!Si$f#y%u|Ob-BfUT%JV9y>iP<^TXV0)~r*kHTUzZ8FE` zVDU}Q&j7vRAREU>q_?`ddd1VLK%XKK+lJu)j?>`)_rl7)=VzPX#>}P|y{o!zf42(0NJiq4V#=d4lJDD%2bM!}%ynLE%e0tMJrgQW1b7XaT z+1|6YO~y;(I$1**8JT@a=F(|HI}KqkX!v4(CpRS22ic&aq6Q3~4wt7C>j5m`?Mj*% zikblxPCv$;o&W&7`GX^6kD34ufMdB-a>;OvuTgVSa>CMcMM->VRYR1acvajrDUu8@}PTlC_`G_I4tQ;RdpMwwO zd*8ohLkaS7^kMbx)#{SZhe_piV~6gZp=Bc?#3FrV6vyR%n#!;<97v^cx2BW3jp9rBqb&c zah*S0YO`1nB5k)z8YdvysFr<`JBrqj6`^ROULDl+o4Fs#q#d%W_s-34TuM}fF(?@A zOTa3nCgZLdPyLtC!baX6L2mo?X{Yw^wvQw`j54(Hx|cn2Y1#lETW2yrJ4X>Z0D=oB zpaLj>0hus>5D>`+ge(;P^5CkV_)xu68{g<6?$3&)-7mGgxB-8F+bVXnZgF|$D$gNT z@*MwCX+}oK0Is*&kh9>EmZrgQ!LDqVgtfDc2*C{PT8-rc1~dS9>zzudvN!u+<%pfD z`{KEP*N+;FrZ&?5epay_;1x~nHSDzX^)3IGa`^o=puJPIY&|Bube$Ro!EJ}qtDc#U zIQ{Et!v#lxkZ0d)fv(R<=BejD@6%z&7q0&V5_HpILK|=@@c}6!LmC}^91@e0tSW=q zYGnqWRSvJeP&=}!nFDd!8eth__ZErMDL2}PD#_On+*yI*Qn=BW z0JAQb8&cf^Tf^k`JuVR0J#6Q5?2!&jzIS5!IuNpg<98kTWR+&JJX3DGAB~Tk*o!hOit&>>H8| zUfgq)o!nfWudCS~___e`OaDHEMqnZPdb6W=2Ng&Y{NY228%5-SPP`!tvgV$=i zv;FN!5j<@Wde%acL{%)57dv-2Y$cAfvP<--NwDd~;-K0E&Ui^9%)Yu_3z!o8p^+^C z=-?Y~Ig$x(fSEdzF6toU1gevGZ}GknYO7A-*mXk3%4|%la1e8!CuVC(tOdWyH994@pACR2d`or74!@_CMp}Ll7MaQS+LXcv zIh7H|YGk?UllicA6OE>yqx_!b#@AeSnZ;@hDvD^MK>WM zcWdi#qNbN|Rn|C~60!3{0(>6a)A;aKqy#cuZ@t()~m$P({~@P{=0 zCRZGd7Z+a^$Ix`-Oa&SOzq|b9H`9wLS-8n$XoTT`ZR}BxW-OGz^a(sg(4JaJC2&ms zL}NKo-|Y6F*Y0W858fi(t76O|Gbp2%&KP5ja{rIJ!=}zbkL0luwTOFj!N@cPu%2(p z!ph*@olb#U%;$MV_r6aJ3sl%Vp1I+bc@9-DG}Uv@_$0fWZ?$AGH+GC#;S{Dqy z{l}Qe&Yf!_$54ur#cuyYkY^bK^1EjZMAwjvtElBWXlmLu$@7%@k`|yo0>p_gxHJ6b zUs^wA5xO3OBoGty^XG`oY&Hx~`*#r};Lc&4z-<`XbDaTX zB)+DL0F$>zG`=VhDf5LU+vSe#ya9m!q0#!X|I4Pf+W#fh$rn~FcFuZ- zHbi;!MHkpcdb!!yTo$=^0~*Vqh?u{@juo;%v>ofCk`*O{?RA|(;}13)@^XXv^XBBu zbr=XaNX3r(touT&8fwRlJM*Quz+_$;IM`a#>&UN~YgIIm0|PiKAQWeVu50~N_!{4` znN-<)VO?5XB$CZ&u7|?_Ji1`Fka{YXGpB&8N7gxBx>3lo&Qn|I+k=k% zG~tGv88ctR<&+;$wd06eY|tRE{ikSsCNO1dGrX7IMzDEcMjioC>4J^DwG6TsX5KZ7&Nzm9vuLUFNprJE>_e22(e1r z`c(w8;@wSu$o;t* z6uVdA@-WgUc#YQK+#M)`rF18)xu{Xwurd~+GGt? zSIF8fe_h`Ds{!j>@-vsl3H-AhkBT2din;NsC6YS=GTA2^CW& z_Jp1D#Ky$URFwmk%H)qdtu>|m%COd3kE92Qe<*AHQ&od{orl%_mxMxSV3*O#ibd5h z-rb`YQm|14Hyl;+wWM*hsm5lxo7F?yN?GOeo_-rQ1}*!R;rwR}6u@8aX&2KG5gGED zEr}cq3#b)+jKUeN>Y}v+p>-9Tb?QK)$k<0^&p`d096I2TX~zN3bU6d3%2;jp3mofz zli9y>`<4944Hq-n|U%_1|gFH%i&MU zFimV-^N^)f0gXG+@S{dJ-{^G{6RT+nOd>bqXMwL{qe5XsfK1ImG^>6!jB`-#L1Jy( z5{~Xj;O!JISc&cfQUU`YQ6S{Zmv8}~^0E$I;+bY`APzo2s1)`Q2@uy}bdCg2I8*r! z$W;FSVjX}A%70ex^IV;wYW^=SpAA(SECB=A7y_A&wswvX@1XU}Vqd!5%$O8rDgrHS zt=CSrp;SEeKs!5oe4?J;!-$n7nihz;*;NkF@{L3O(a-qn29G=KzxXdu=3m;XRs;jg zUWRZ~{DlI1Pe8*3R6d5sMhk^=p&(?gWzNrtxxzX6BJ@?Yg+zj@+sO4e{g5C*RsUV3Q0l@!V-(J^W1 zW<(u`^TuwU+wO=O;AghfwWjz}i=ZL{R4X?k!5Yg69#mr_WN0?7p5Lw9wS5fr%x#kc=xprBJh4j-O)vh4>G0=VUIC* z18C8&+zkNR%m8OxG%Af!#Q~%E=K7U%+W%EjYzs>wa01doaD{AgvON|T?JHC+ZR=>_ zt!#u2ieVe6AmrUJN67c@gr3kb@EB?4%chk1ZQP*|cKr4z7iPc@>PJd`(TTV`q_e>Z z(J@72m8~bf2yhDx_!*`DHmk4@xLml@HbUt|^lE?0p#0oh)V z=;pwV|H5a~D;i4bYhWQ@x2?ba3|j`cNJ4a+#jcwU(8IEIcnPbqk%|-%lAl2x=sp8@ zqVmd3`)s4f)QuQ&Lj^$p`^yBusye@axfeHn&Wh~wj?@Io$QI`jH{+Q$G9(ITtwg6l zM@s^pY!#__DzA58(6pA?$2kO{zWXgY2n&&>DZW!GW!fngQ(3e}QYglw7X`X0E(WLa zsz+8Ca7SVf?-;72^b*N%&}GM~CX}^?UZ1LQFiSkxX54(n8#%FgP`jh0DQop4c8W?^ zawjwYI5i>JT+a(#|961iJ{&OfMO-()tJ2lfHvb=Am%5@j;-f=FXdLdBo%NpWKexAO zM*H$BHa5ZIzI%@DqWsZq8UI9qx_pZAbvwst%@1g~*)vN!->$K~ETB25Je%zlQvE^0 z53?Y48;0{?o;R*j#V9I1IEn-x#{3g8E`vqqfBRV80BE!s_*U0w9&4N4wd zIwBE28Zm3UJKLAxJ%0)XJQ|#Ys?WpVTwWw3(p`uwiq~!aA-dV4ky+}}b{2JA@_J~v zuSG{YItu9^Xt-Ha2B<`o>YEL-Qp;41)iQPIE>A7|Uj#g+*mtY$o=d*ae%TSQN%*+a z`qO4vC{@ZWNTbV=<%B_QV3suqtVmB{$eM3eQb$;ZdEt~ScOTZi|WK}ViinTaC0Ewl4Ke-u@i?-}6Ioge)_wF+awvkOTF!;mG|*R0^86&P`A@>#g;{#QdVLGZii^n#PyNarCz z$3@smr`fl(eaey`_1G^7S?}I%nB$DHRA^aBpuhKHle9B~q^rQ1bQC2+6C3NLy z*q_W)--fF*z_l>VU+^N422|qS@elbk+El>H_s%9A(HVvVfuet$r(w4_W&Fal=#;Nm z3J2`P^PrP+@$vA_p}Mb#L-{r=JcNn(%QyaJhW#3k6(?Nz7DJQ9l2Ltp8DLC@)}eSdZ6-lG=Rg?oZVN zDm*j+T~hi7e`}6KD{Nk=+tp$)sz`D80Xq#45DQS3JEA|7#%0U3$lmxky?DMl0u2hc zuqmY_6~vE(Se+z@^&A?B=g zEeh1RO*&-9k;R*CQo5iR?0HnLmPCJ_sHk3^czDa}!a&8>6W%7!)ZwSka}$08%wo_! z34$}#V_BV-76elFDf2rrxce3VBt&*3{Pxz+?`T zY4gdL`qkEd8D93m*pxTxt3o*0l{oXQQisM(xq?xWlTg}P-TQCB!oF|BGxrmW`t+Pc zIQ5dIKDv`107cU^Sx`vk4#YfVE;8w>=X$H)I`z{D`&pV}PtDh6{isWg(iM~veJsp(b;Ir$#HfV}SYvnEsZ(5sRvqHe zCBRN`-qcg>$fIJ={HD4hlWU^f)mJNom6NuoY>Js*1iz5e-p?Yd4})ifXybl-K=NE@ z7ycW#Yk5ol^SW8RJe}c{5lP_^Iv4lkDYcwXtY>p5&x{BIp2!MthJ=}LeYlzuf-lzxAp)PC=#VVguvPCt+V=m3_{fBCg_L;|+o#L&Mgfy>dw+`xcx z^i?2IGgZ4JFhi9OfZL{{2>kW=e}z7(D8z+uRTOwL)l2ad2GGIP%Yo_O2A%(>*v^3L z3igQtxq~VC8ITjws_NoM(6i}iB5i)ZL&~CgSBOjbnnL&wGPjVU(DrXSpHzZiY&suo zij57O08BL#qTg4E{1WReXTv8l;m58fNR?CofI2R~rvx1^8Vu}%0sbiW!Tg3y!?voaWJ&HpIu&I0eoT(yI|f?z=%Mb(0>|duC7m; zy47B{9UiX$&YjchXKP2kk*>pa>z(p8HmQiFDSg(7%bt6*5$w9C$^>)XcHU5Vx8bZgOkv@7hO9z<)77Kr418LZzxq%!}o zs`b$p;KyaJr<}{c{|JVv;MKSxyG&XoyPd?qm*Z_OowH)anBjsm@;P%dIY9X{AiNK@a zUNQR$ogZL^PULD1EzcVw26qCMIhg2&EmH=sg7b@?z(<2(-ICpIW;BdZ!RgXna3d*e zgwsxqR8>z&8x~vf>`()5JFv91M#>en3Y27g z6l}RtJ5vig)hSbHJ4{wC1M!;M_V_70SZJsz{+f{Id>BjD)EGNj5|$~Zo zJkLM>JQ0*BChFp#3ShBy?X@%+G$t5G)P% zNfn0xFBr7XBk$s&q37$vxj_D`nWW%=eN|wKwgy_gbL|L>FvP?8R<6n*x2KyR4xv<0 zbVlbu0A%Rb;zp+mnOo0`#t8T~CIO8FCGQ)6-!o(|%4-^AUzF@d8?15XGb!d?(jYbV>890k z!CD>jAQvWg7DD1EyP>6R3#=mx^gnYpTAi(_6Xt6!CJA)G zI9-ab{m;7jL=`2eL07ab*}xHV$V&K)KStrc53iIGOl7Zso4Rj??z~jGY94OkEys-&S<) zf(B~txo#NX=jwhX+<7{oyUDNw{SR6h6T`m3ee@>!2L|NB-^By}Lk~V5UO2)hyhIX; z;*%xSRGjX%tAfBCYy5!Mq~pXsNB^sWLPFLL9~aA^wOrr zn(7}Fh1IPaA49*}OCgzV;=2FMPuKVAC0>z0kaVq)^6u zrb?Svw3p|o;08t&FpiHZxW1xj3rkStJNi&C=c-zEQP!mTX!CL&v4 zn8|#UOeqeUST}yR#@Xfjvwe$m#vILwyq=(rRylmP?cNG(^isGsL z`!g&r&NUG_yd+RTo?$xS&opJ@p*UsfaF1W2K$nMbx+pdAL5)AQn{WP25=&K| z!YiWA5c8JBQi2TP%&bKuKFj@FuZ<8pSVQtpaGod4Ts3E-9jZI2i(W5DHEQV1M4Uyc zDj!QpvE}FQRD4CMeZ?G`Kr90;($nFVNt?$rE!!0e%Tw5yl(kJzoVAqo3F&dCjW?qx z^e@MBuU@6kI7awhU$a5kw-B<=QN_FV!ylb3H|{9MHGGF-Z7!u5u0H6(*tXVd{-Bm8 z;tTz4XLjIv+P%0v8ZixH+C1rHc%z5|;Tg(i$sLvKj(xZzU~cP%SjuWu;zSHA3Y!#2N}_4hefT%m{_SJ$2NjzeH?Fn23e*@SqD;@5?r!b}Yc;Ty%OZ!Yo= zF_{aoDPB#%RX*tYJp|pwc|dPYYB&F8s^@+Pv1F(C7n@>`cYV{co}uBlco2+LPDsO24+G?Tmg59O&-oV`w!`ZM|s<*5`Y-_BPkSbsxS86eTfH z8q3iP34zKTbUs(OT-W0g2on&BP!#|u#Z022nJPnH2~mBLK*kl)6Yj$3jZ76my;)@> zMZ#ki@)469`57yiZb9_nVxxxrU@qx+KiSF2=_cjd6o1oeZt5&gPLSB2c_OzZAuHaK z@0Lvi&ne3rT4T2(pUQSCv`CwHI$A*tyfg42UbTZk-1GgOnSid>K{Ik%-j4=4Iy@d` z*JCuoy+z#CANFPpnObxO3zak*7^|J_!KOJe8JJd#K3r47qU4LU@OdT`p0>3hFF%(J zSoYxElykx}QA<8u&RI*ElU5WZ4$}3&du;A~%6IK%0nelQRm*Rftm|F>^{al6oqXWv zwDl(aST^Ou*NOM#cidA%0udV7NBzBj_f8h-gbvVZev@{Nok{NKH_|X9d5|iI#9H8X z#r$NRNRhWKS~uO$%H^&Nlphi^kkWJUZz(iQ=_DJ`2LLvFXT2=-yBXjeD8oBPcLB5UU5*d#CQelvE;oS{2Yb?9OlH zLk9CeKcUsN9b6XXjc10DnHr+ybl8>pJ$DTpXx=@s&GR`$_B^MfBclV3A|^?g2Pex5#V!kb8gP z-ty4kN+ep}Fyq0Plw@cTp1vvkhg9RyVj~C>cjkCQm8qvsfxq5B_>E1g*8)b{@_jp} zE@uZ~oa%ndMO?I-;=?^N>g%1by5^v+f&w<_0<~1((J(D1nU+il9x87@G}BL`D^5#v_~D zyT=AK+H*KxlVEOGN>j}&n9(#b^k#uL>6*)u@VpFNB$aL&$;51e3?oQa=Msa3kbfj9SJhnAkiC=iy z%{S7xcPVSnbR2G7tsvQYeOE0rG-_N{$NDXU`q-k&+Xbq}A03sm@JR2lR$5T`uoYg;S=NY;8 zgdNOhJI-S^JwC_mV4E{*93IX&fC*=<_+xpED3=2*A+7&LAkO#gN1n?;^Bq8$0yf35%r*V4wkehkKTjbn%`xe9&Dt;zdvF4+D*NzS zBd4<{LibB3Y-Mh9Yl=n|i>M&{3FVuA3zm*48MS*oAHOJ~iNb>P+fcsOhXtOZ;UX#C z@Oex?+LIZ4-9m{kz@=oAhR&`qt!8QKxh3`8X{IlS^&BkS@mOo@0U=w@W(9c!H;elz z`c%1Fjg;)urA-Z$vZniPnyaI$x!qLuu3ruKeN1+;O`i?Su~O{->f%KayNrGt=$5T@ z)Qa&afq%s%$a7`Luo|f;r}05MNC|g9#3eKcwlRtE_J+wcH~$+*;e6;ZZacbWOb~fL z&Glm|R!;s4wHeidEW=VLPUoG2; zir0U^v?m5$XLRxs9StZHwXOMUKiTwE-Iz%zGKweNjPE@C2zh1M`p0GEFr_}FRaH^0 zuOOzGZY`!alFoFVoUxk*`PcI!Dgb(yUZS(D&KjpyNH z@J@Nq~igTge?Y%3)lA_C!k%!?YMUdu?ep zCE}}Zz});WOCz1B1Zr%Ye{H$UXVqA#S!&fa2z|{R8L}FyIRL=3U>3xw)wa5=&t5C< z#)0Wr$0WyyaF6e~r~|?Y&QxW(WY!qA{a)zR8qK6s!%j{Y^3@ z_eWGK7gBVI{3(Jn+bBU$$=X~Do7<4Dl_vv5=x(r$jkY3f%PG?!LIRj71Wrg|U+*&_ zmJ;*mJ}BQ9iH9#TI52i)+aewmSw5D2ew6w8cA&dzq{q$RuZ*UeA+|e>A@uS3ivsSx zr+HI3c>ru}8GkdrRa$8};FDgjnFhTZK&x6!8o!hSn)aa+`xym@37HfugMi%6wBCRF zYM&q|oladrr;zMrkVZ<+EPOJ!0Yg}TJ3^$?upsOoH?iIA!AmC{;v0-sijVP8ovtB{Mgn2y_zt51K2+!JqU4;D~=_3tDI)19t zuyO*~nDtRP359O2aZb#G^Dla6X0=rp(C#A=)I$EpHZf?u#(J_6|MW+F{5u%|nGtcY z^W92}G9+o}OJ2V=qVG^IV~1SzN2Y=mPgzER+Mp}m#qlq>q+Bgk(7*OD73vanYUHnS zrYy&XDcAH!bHvbmQK_pXA-vm>v&c)?m@cqw~%ee+FqK>{BWgBpy&e0BSPXFuqK zWokaKnG;5Z0;!rFy|~l-sg3Pauu@Beh2IPBJf?B)*9ki;&OwnOM#kaL3^%(V$1oUZ zqB3M%B$|>x^Rtv8E$#sJn7zgI#>W@>rwD;J3ZbhlS z%rjx;*9HHIzPr%GE0;Fztv=OM%6w87OP}gbg-AnrD`U_QPCpa!o9lnU%>rUYyqA^y z+9VXtn%mg&SM}eQ^(C$WSCp%Q$?AUU^62axwW}l9;EoRz7CnybNYyItJWck?QLAq1 zM|AgM>s0h(4-?FAhHoO{63a?>eMZ8hY3FkrU=B8(abPy?29}pR9AH2oWr9uUc{J2{ zQ%O+NkAp(g0#aIGFo)0h_YT-3hALo-2vuu@C-3&HZ=wBzO(vC0ooH|q>!^3=V2J|j zrZ%~KzP%l~s573-!0b?dI|!EE;j&GDeXiVmX+X|p(h#JRupj1P2TpUK7)IoNxU?RDo+YFMf<+??&vM7a6cEdC#OhEESOJ@5D z;@}-cI@z~N+L)-daD7z5s^{;5?=h?U$ef(cbfeu^ttJKTUso!S_ z?aOVg)`}xaoS|cVia(XA zkmpQBSI$07P8CfrY%zk<^oh|8qF-psKd=SC1$)=?enfa9B{5lctZ-%AP=pwbO_=u= z3$_2uHUY4W?7$AnO*LT=N#|X`F2Nj>NKnftjVZmJ+R$$AidMDhgY;Q4Ary1;@5-8d zw3Z6XTWxs#{8u3xLc9vae~tihg9wdokbYs6jAQdBkl0co#vUHXq-G(K3gf}^BQ)D$a#y3PzPHO18XEhG5B>Po9>(`i@dhO_Zr?PsbW-b zefw|R8g8kSdXSxyk6a1$!2sJFb#8uCPHUmMaW%)}q3v_3@5E&?S`Jhe`Bq(;6`Y@{ zWa|}Db0Yu3O9EaM2-92*ewO~_WUE=i9ClOjJaofOA2`z6RaKXLjbR&CK~ZZf$L_k? z&itI#@^c~VL%=V<{qXbiDl$!wZ-?Gk50AQya!(!|j3}5lp6UZXS~it(e?=GwK89o~ zQ~h=%LzNUdpeuv&_=jog_o+4eFCajK`si3NawOceS|ueEaa; zkBdG;CeBn2LW>e6ZtUp_6;Q$O(zio7d>?tLd^qNtM9Q}I?djAH_ud&3!c1lV;ubPK zNN9d5?|rH-;$J8=mN%zAs7njU%xS1jXm#wcOhupTdY2qp!7Tb)s^a50qxCD&Y< zq_@=J74vwzenhAJ8ZGGCU->L?l1P+KbID(M;L48mOyJ;t_q;*YZOf8rWlIn@;V;1j z&LuPRm6p66k`TUbsbE7zx||`rz^Anc(b7P=>C&*veW= z?a-VR8R{|TVj9s_+25WD#&5)r3p**Dn1tc-xB?sC+0wtf*x%9gKd#E`#vV&gNZyK7 zO-7w5Cvs)|f&T~wWT%2jx@9-`rPW{8hx)sp=7+FoR&cwt?nR;+g z{e>CDU#zM*E2}m&t4ImIHZHXGS{n=+j z5c$YeC0uc9{sz?;j{7`xNprar817^g=z*pr7hu$-#s84RojvfIKD#I9nUu`ck%5zk z`z4Y7sz~i?*hANr7Fi%4NN?DYn@cD#-L-!V{xb)XH|`EEoKpDtx)oVGJPT79cjP&Z zsGQlq?7Co)!yzj>f0@y<0PehIeUw@h8vs1=(=)41z*h~Hj%MU{X?s&VVSP0^9sCt< zV)y#$@~!Z7Yyh>pLl~7}C!^m;H>^1QxieF<&Eazr_vW|nq4R?bPj(~`QvsT4QB_CX zoumgVt;>?be}Kr=KB0I)iPOoII6OL2p>?`3DT%1!MKywWIgx;a$)VvAS>vi5e*pWa zT18WhNKrH!cX_YaxuxDH#)uKMS?AE^n^D5xUxBD=<3^Ib9uNMG!>WJfvj-I>RGgNQ z4SBD16kX4MY7!5&UJ@i$K6TVi5>meY#ov>lbCTMB1XdtAOn zFSO_{xD!&ebbkgelG9Gcu-us@4V#`v<6uh=!0;$hxCyT7}LI{@=cx{Wiuu!!X%b(x(x^H>P`dL>hVuV4LE_T0s7!+oCo4 z_c&JKeMiIG6-b5d-6xJd({SC$;~lfmP`Co&w{o?I^7p_-mmLa4mRI?C)@x#)B}8+@ zhC*v=mEP>zY-i}GOe+6rBI@YQC!zVp%Khc>v`y7WIme?)#TOAfc+Ohiif>_%AkQs; zLPvJgU80SgtFyA(lG2Y0NE^Yl48ThMqJKrgAonHw8#J`C_x+~DTg^|JHT|qp7n~+s z6}W%4_p}v)(B93QE;xU+ zko0v0XC{#U40ttUMjYkJ3T>9X?)>@Fjeqw`>ihxsm!rG*T@TSgp0#B|)){3}V+&(+ z$-&lfmps@l?{JM>^e-hoqFR*@S3b?}U1q52V{hkv%mGma7JqXDPx4zxC0UKqyQm@j zs$l1uj`5hjRTI+h)ZMAfy#r5IP}xc;f-RkC$1xlzH0GW(Q$}n)38A&vfz_bdx%V~W zx1x-hm!p0nKl)f~`Q5fRhq(WJJ1xGNd9c|1W)#D7AkV=}BGYeV&%#+CKahXy>m_)y z^RGGM`O57x)Z>53f``);7@b0I1ID@|Sq+T}OIBL~U?5!!9lAQ$3)C0@X5RxMJx zx;TOw09Vj7?U3vH5XHBDU_#bACF{xz$l$bUmfPcAYzPxply=M4$ee}*$gg6NK&z^So z>R2%sda_I;L{;^%45kTTk1IHG^GZ~&q}24^V|U9iB-r0_q5~u=ow=!ACRta0bN9Ql zArH8-!I~=Ucg6&Ol+Mgm-zJGM{-me3XSTpdS*Gb$jMeGPfZ5WhEvymFdz^dObfjtv)j7ifaP7CZ`S*(WV_X!%%NBzkg4Yt|8 zN6orQQ&*Y~mfL@SN=}$k%}*xG0%XzvGaM0O1OsliUirlgggkMRtxRPDr-teW%C7)q zqboo%MH0d29Jt@Q7vHxPrv7UMkGh~KdL`UU%>5>VdT22HvEiDZhmKH;Y`{w*`Cx8jb|hFpLieAYO{+$AhtX~fU%&9wf){VC%=+9O$b&A(kDU6q$M!WIQ_Di4fXpd~u)a<-7kNSn?*2$p zc3}Q6aAhC0dMnHn25mVak!|1b?z_8Qzq<%Ix+5+%)S|j-%b`N?V|s?ctOu83US+PE zs80w-+Dm;-=WDePt`Yk!%N52xw!6pH|GIddxilP7*ExjY}6i@GfXyM74xyAmmxheGOM-OfcI0< zoz@xa>Bzb#A_7`=tc|TO*01=Oq;u%M5`JMIl=4eViIfXi-faX#MJyJo`M))RuwxvM zgZib>3zR`{1etLMxkRi?U&q~QgL)3c5viGny2Q7jp4A$Hr2J&hO#sPE@ ztX^U{U%E~d)e*M5H@t9DKI=17q{)H{C_U3f*rWw1~@NrLNM zwT{&m6lkwb5EW_{P_dc?v7Gf3(q-OLl}}=rwWjq7waSaGDJ>0d8jnjx`Vd8v#Pd+U zN)`Wz3*8&FQdSfEW5@EXTChCQnUnRTVZ8yV{vs^ivD~i5ck!DDV(({^Fu7>q#Nb?|hKMSz# z8yHMJBj=467x=SOdK6Ldw&h5#ut2W7Mu|8nO#Ea`F>1pL#7aqs>^z@Q1cUG*sGv)H=}ubsR-Igor0KP->Yee?2W2 zV)VKN^Go1Ye6aLDpaAIiJF9l~Wrm`S);^Vp2~_u{G9K;hEe-txgQd!r-j#5Nilgak zCB+YGJ{Fz!g+{t`*Yq6la0uiU@%NWf0P_H|!3;dgSy?HrkZ_nwkx-p&Q9DYJ>VWHe zA^h>5Rc@^N3PH4Fb`pkHsz)tOLGf_PfX_Lw%2pp%t=^@GN0Q)hsb%*9k!4*LqZY{2 z{g#QAPFXIKY7IXbGs@Q*r1Y)jx5mVQ{4nlusRD{-qjsF)B;-^PtRU7c3pj7v4O z{`a&6x9y32LaTw@<{Ni>DCZ%`2b;G<;;zM>M2unxrTKcZC<12Zqmw~OaToEYKn6ye zs)>AO9&E+&XV0dYlw)%D`Xji(UW>H~6f7tO*9wyMmP&xcE+Z|W;M^a=fDopaSccrN}4E1<~khS&jJy1St#VXB7e!qX~ryvYHcZl zmF>pl5g+}32AqF%DR4Tf{zl$93$`KtVCS2{J>350eo)ZmIwF0fu_leBF~qN*V`lvf z)kGBQ!|dzWLUTMeW{$tgGJlzg4Y+~YC?{)@ShcFO(o}4-vpK*$bRwfdGr`??f?up^ z?o`mIA=^-mzAr|10$hL1$F)!)_K46Q@1Oakl5-DkWm^S2JDm8VVXX<7$?uRU4M2fD z<~?*v;??XxH83c7@gIa5w7MlidZ~cB0Ml}dPB#LH>D^qSo+lrXy<>%3rjaDgiHd{k z!Y&v!SV7l2SGCG^`~17k-=bW$4*ULz30w;%ZIqRKa%VYQ)y;EBUV0^hahSA-bHw1> zLPjeYc#Zf9ObBy%A3Vvs`X=l%Vhxb6&dn#%o(iLiN;rUslc~e6fBOK;!IMK~CKkkK z?yqMcDGBX=#QMIYX3zpbvRhIP^yxY*rl?XW;QG@gXTtTNLOP(ax44|n5YSel%dbzuBx@Mj#XX4Np?HWc^eyoyGv>HiZs*M1eLfA8dd#z;t z2uOl=IR1KZvR*W-YaW+*csRVLZhFOkNl$QYd*=@%9Ez5G>F5_B+1v@@~BK^ zL!Hz1k9EcKuN^*KB4e>Z#I;o+9MA&Emf^_|kg0ngR+M_%P7B&WW?*hR9L$qDpE9AfV$l0^BPcy#4@ezZy{b~sAx zRPA|^Aj#J=PSrOiHvKj;%g$8=lPt05$>Ee54^z682h9ZsOyQnQn6&ZeQKqcuHWbB8 zyAPua`5uUU#%&2fkN{h<3|sQ_#X<8w;l;KZm_$n*zhhp1Hn}Ny2$oIkP3>e<8Rf1= z`+_>?^Dm1$DO>kFu;O-B-&oukLwiQU|I`@sU43E5UFon0hfdGhz(^{LV1@+ZVL+al zf8f_knp>@?*u(HjuFa%h6VK`}=dY=wN>S-$3r~3(jBc~`eG3!DOFn4|rl6clXAzlz z{G9G3Q2~O_%pzhK(`(N(492Alg5>D5aRD`*z(xok_4D>OA$eS7^98*gz_(8?V1RZS zX|VD@>wE|`el_8}QRPetOQ=O>Ee`hDHI3@9?50CHs zJ8}r))9%wEGU=JIV6@x!Z&=o|)Q%uVH6$L52x)_Qnd=~1lyp=~ z66-xHNrJgIb2gtzq$()>pTgb(D2^w17zJVwLI`qLup9}2!!3Bw3oZwTTX1&>1Pu<0 zyW3%h2MG`~2^{Vc9KzuQ2?W=7`Tf7I>Z|way|-0+w<9|})7vxKz1`D2LinX58d$Z> z6{cZg3h#ZDfMea?J^%B( zVi!o51(`ZqtBP=K7ziXYYYKx(&D@^?e+3^>kPOIIsl|KU%)#xZLGfS8L(@R7G8aF{(CHZ3 z4*^7gUMIRN>;du8bcc-Igt*%!dSkpt-Y*{515HHhfz=N8xaUEcrQr)a!R-PvKQ|No zPvL={zrey0Tw5lr$B_atRqeY<^VV5??j@GF2c<*dM!k<+XB&Ebtr zJ$ka+fn=U#au7ucF!OL}9o~j9mCL?@>N=NyuJO?vIDh3YaFFw`jO^L_ zaPkZWJCJrmjS7F!l!K-Gi}!8xGyQWq+IV_1bM`B*-cXu86vj7S)@wH^d31iR!i_xx zVC5A89uCk)SpL$Rnr>K5biXysSa4KhDsi#wpjfJE&;~HpI;Pq;jKSk8jq47*Ljg)3 zM}vb!!oYj)@$?QQemJ-so=AYO2P*7Q8XA>Z?~KJLsY}7{)AK8vylhnxvgY{Rt)IN5 z%g5xUrB`ZyaVeXqT975TF`NbgidOh-`k zFb(&+ly1(N7@?e5b1)rExvUfbMKA*c0($&lcN^o9?OQz=qF0WHE64^*B&O{OFJ+Js zZ6j!&_p$opM1kreEu-b;dgYK`Ev%Rd`!~rD97fSnfN&m2?se%k`rr+f>2cqOqoi(k z4iX_a9lO~|_yjPD9=_-J!oshfq_(>CIdyz8>+F|Nt*vQPP0?f})nPWTOv?VDjCh%p z+*%Du(C3jso{YM15dh!!a7!8`$4FW9 zWI;bwf3?1gK~V&mDQuaJGxZLpCy&f~=9-Ou z%+`K9SvDKkIGHb#W9;igmTKFuVEVVnNE89(i+ZzIG}lOcXfa?rV^-GMmA zlqs;KnGsHHwQA&};Z|WA)$*$6P}}mJ_7RD?eCoJ}85D)GmR^ zPV;b-*kTB+cH=w=PfM);ziRVJ4w$ae}THN8W;>&W@0SC-+e zpV4xmfV4xUe6U?xspqkSTmIQ;9yo{?0#>4S65_XlgjP)&&2YOx*niq-HL^ZNK00=N zh zB|-{NzXJSVy9aO)3WKd=nOKX`rVR{g$U!%MRkT8PC2X$~d}iQD;3?%!&fv+A%v=!8 zoTaO0$I4 zVeWroP873|eSxd3;bN9(GueV?;wS6J{943{lBmi<9Cef^<*9G!)`$=yccRAu zwHHXNUoTUKdvFZ&!p{XkoA}(DrCYlsAU#Spkb)ib)QL{a^@3ZGlsSIF0DinzsFV5C zLDu4fMNSNCSHDi0&Fw>ld&PlR(JMU_2wHM^PYO!;{0W0@u}*>0`OidUhddp!@kt8E z1LXn*EsNAiPi__sQtk=s)lMp7<~-w*JiO&9#K&Wo7I;5SROz!Dd5;y_^)P85Tc>B^ z{c|~{G5p#*4mX88s|8-8VQNsOYW&-1>Oq-ev&2stCG|N+ukaQEfr!d2+mr&t4o5!P zjO8IE4=9z)YxF4P-dPNdicwA4VO~Dkd&2zbl8C;@kNFwl7a@7BDPL_hnIbU+M#k=z z18~#kf!Tf+BY3#0uGDLc<-}jHZE*r+y=xg~U3da=^(mu3XwzE}pVf0aZTxR$z@;=s z`VAQ1VffiW5dRP&m7_@9)8y8?UbX*0hRQ3o22=_2{k0j$3_Pn2R%OS=4c3TpS>bxR zvyRl}E32gg(eT4+%HAoW#`(5V0#akcv{($cI6+WUStc-IQ#|P&+kIjEm&s@8Rs?oy zRk?@%Jp4tAU6v$avw^9O{nr=dLQ<$d0RzePyLyCpkh!g$1Dr&yqA)5Yh(J&G3>o8XF~=9{<}vSGF7ddfO79WKW9p`Qziu63C`LIdH*>AW57L}c3512dMx zWP7n7t9?cvuQ8piJBL#HTRtd_;W4oSRT!{|(x&?J2(f_&Z=8So-?CRAkg{2QM~Wb> zp_u37<(lO+HpbJfh($uQs*!a2@i7C0YNu@jWWOf!LFMhSz`wVKp*)$kvTzbv=$lh}LkBN3JtmculvB9p z6va%Usx)qp-`qT%w>KmOed^kP@ZF+?!$ZAlLFG1+aDCldMlSr=>l(|kyrg>u(olz7 zWe9hQe5vOj^a%(1@poEyJ>k%tOOgY`OGH$&GZGnIo}LeuQLQN+gE43uF&ev{7WA7` zB5}xCs8=dJLYnV~Aq<~gCb*T8gVMDW`3SDYtsZ-{REPd-9xtU!Pn`jCGOb^QcZgr&c%X}&V#Hg&Y+#C<{L&!>aDIPaY0#5k zU_Z8PWN6<98)KN;?9j7!radOHZ!UJwH8Y8P<%?HH?=`j}(Mb`|LWIBR6IrZ{K5gFye@U_{&3#1e#U?uU*0n5Avtu5mq!vUhc~ z@0R*@okIn>pF6Vj>>f`M;=nLjvSA4>0$Y)^EbWC@W;YBLwAxz6@T=V(4O53SBYP{- z5{ragN!5tF1ZLRES0ARt4QAW}MfOUbyhi^So6A*=AA%K|l%=LKSGu(FggGRu5oNh- z8Gh6q)u_FLW=6Ob4k_-~TvEF=GcSuV{!u8oQXKOW>dtZ(9XczV3Ne2} zq0eK&u3+(-8fkwH3c;DLdQ(ae>(XDYBk|jg-sb=gxnV?XtIjcwrM+Y+Mhhr=2Y2XRN+w?7Mjv^n`$Vjq3PVzC+?}A0o0hc4&uxf7ByGVsHYN+IF$1MrAI7%kl-%q| zhgqI~YbPGnA~k_r24^Zph#|n~i>#J6FF?#pYOt+rq_)Otkx6M~FZZ$Y(q}6{3rX6t zOBk1=W%;8ou|mi#Z{oU=IADrJf6EXaC6%3WaZOmtwEAgGRUDeUHSXE~K5#cH#*b!t z5p?ZMnEE2>iU9oM&)r3Cj{B(V|m<8++&)oR=V7Gbzg4pe08bk&0Ok9io~^4fa+mmaG%VG z;FAO2XGUh6^VuYj+jhl~hI(#82-ytK`%&MD_8Omy<>BAPl4Vuri%2Whr>p*YpVMv= z-lHb(`6vuy7{Z527*>kN_Hf2riik3yC{3-#3*|NN4B136cDvN^4qAV>%zs*RfWGxj zUqaECb-`I1LFsy}PC_^8TLIV6Q?bb26x5vqi=W9s42&ccEfAA<{BRM+Fkk8*Ufs<3 zkm(Rt((9heXpPkC@872+oVH%sm>v?%1+s;l`5#@_rDt7VL`yGEtZpl%`91vku-monqpQ$#dR#gl22B#z z7NCjhTf<6lQc<2}ls%>evP%?1Qb*nv^?7b+W%SH`p1o(_YJJ|pL&PDs5={E;KM{@o zpVIT!e@ai>e@ahW<^PrKY0jdFmEL8Cdi+bMs2ZVpKX3xT(j}trh1fvp|3{_^tU&KI zpx0#s_ZB@DN8Ww`wbpsu(#L?DsW)F}H)R{pXRYa9!Ci2PiTIGrUx4IiRdOE}$O4i| z_aCp2m4_sMNel{dgLn+N^ggc5`#iP6{3widh8cpZ?6;ilL!IM#(AG9J*m?28;b>#% z?rh_)Uq`xJ!W5&q-eDkb^If3ZnMJXQre@~U8@)p(AyHPf$*tb!k+0JM9UXhkNIO(# z$K8>&ixsuIb3PBKu2#3==M1oJ)W?x9j`Xho@W1j>W&rh(u8VyW4-ZQR{VXy(>q*hm zZuF`ms-l9doTdStN>iP!m#R7UC5R)^jd$n6fj9Z3;XkL z?FxA7)H59^y@nLfanxx|Elo?F(k*giX%pn14}= zmX+lsFB=(W9; zgu(SuLD5RMxO(gv0B?66AMycwVTo#vKyq2n-!46LL9DglIY@_E1Y zM8d!~5SYLxVlu=`RA|CdZU3%jK!w?ReLz8QLFgy=DO^jQs)MlynR>>$J1k$w+;aQ&K&BB=)YKKE~jSsmXJBCHf%-*Bb1|QrRyyoC=nNWBkfyKxc zFP_NZBg;d9zrSiDdkiF#@et4Qt+5Cy*^kq`L8?sIiAfhR3SAQkR4}=y&U{@`+VId@ zMkZLi<@{-0m;P+V)8mxO0NTc`+Tt5LmgVa)nO~H|Kd0A|a>g4#gxJ4KmLvxG=5n$- z;m9r3ErYFsSvxg3RPJIy%ME-jpgP{^l{4fNU;>>`?ZZAZt?dk@c(&!=Lqq0l4wA~BZndv z*NGXan8zw9K<=?K)I*;r$pxQfypHcNcHLmvYW<*--)uyhYIcGQ$M@9_15R5lM^$;W zN|P6mby^y#tbhOR%Ih(Qmo2c>xKP>VFz+(e+m|ffD93&xEv_UEUO!Fz6kM4$Z#FGa1x0J9(uH zEh7H{_i>_K7$aVPMh%|_%qR;GJ(&jTD4YSHST!4C&t8m%&H!N>Y{L6Pk zv{PJeo6QQGh+0k9wV5Bb>u)`V>{N}v$FBCep}*82+bLSw$$i+85YBDM<-LTnQ_jCw6Il7zo9wS|YP@+FAJdmH73T*xIJIm? zn+FeuYJZ<6uAf}e^?S_(1G-koJaB!ZLYIMBF`{q-xo9I91(ZFE&BK1Z^0}&GS?`-Q zQZ~Ll;Jd^F&|b*v(KjsJLX|X+o{fqj6uOHg8xKR1vSGD=ifGJV|rF2D%!_Z!TI3;6={y3XSOEvcmj^Jv&l|7?MwWCznfQ-uiG!c5(3 zx(e^0m_U%*;J16v=;sAp3wdk1Ez=`xHL2J?&!L%zfAy$-DAi~RrGCZyag;-`R8FD} zZgB2!`0Qo){ve*vV&Q4{OJflVjUa$gbNbwQ|%<+TW=W*fp`!R ziP^_681HhAV2j@A6*oYYj=R6Uiv81z;BGme2JIe*ndc>O&_nI-~}`(~le zLHtGN0>`!*?I3`vsX6*b2C5V}cZ(>VDn=X`zYn&pawAy?^%8!>Mjt_6{zC&R+wty)A6`D_O{5`7(v(p+V>faJ-?a#@zid~cyuyZ%s{TBu zpyeLqoru-b-gKIv@Ynqm&z=U|14(HNz|H6g);m8w_^cnRUQO@fmTwdF_=%{M5Lob) z1B>DMJwH2i&H;N$>JOD`l$Kso`scg0wV%%J*C*7~rddHiqsmOJwj9*^kPvR835Aj` zzp|2sUiI`&h#_TVK;MGs-AU@U4Y5Jy8Xr^VWMKXFZI206<|BHOON_IGz6$;7ZW@@z(&ro&%6w*?^@0<^T zsK@{KtRYzG)GSHJhx+k37%AT+oEvreYD?<10}E~KH^jO{^;doh!UYorN%-!t!*Xkj zp<_B+9p<4y0)Z%T!|Q9N2zLaS)N358HJz0R?LGlqdhs=7)=Qxc2*o-fc#=O|Bk1If zGE^wXa*)%@wzRm+-|5dwz4#xK72Ke7WmwM92hzxL2RXLMS|jLC16q9^!#NPsU6_s_ z#3Sw*qyh^rFpQL%q2}zedhrEcv{VARsA1m2tPEWoUM@!~VT4p2C1_g^(3CO*)iwef zA0FnWklR8TlaFF>lIk;nehHa&qi6Pb85&{0;5vb|wbeO%kR=6al^)Gfifd)^7Z9Q= z0I%rBa)V0Kyxx@t200nVqlg~Ur*eas4Gi*+e@75kJziBV8GsM|1qke+A6VrTFrw>A zF_>y5(Args^xrHtsrir}YpV)t94#qw&n}xH%YJ)cqreB!*<`J3U?R9#wQqKIY?Wj@ zRT;&oQWc|6rA>Thzj`b_G_IDjIYVj-2W=7@sX|pIvIRr5FEKX;IGYjZ{#NFKl>KEE zl!sQd8n4l72U$4hDz7v!!-%5FSdzA%vrDgZtp)tOq)TyJO8@KD0G?a@O)tsem0y%H zYzRvPni*!QxGdg>!Y3Jt213jTke-fvnAsg)dTyxAvuIM2EjTCpaX(v72vCg|j5 zob$xjIyw8P53Su)|2URg`bE-_6Y`Tbw)0VHt~m6K3?7$phh5}&O6-S?(TZj`{FYeQDA2;Gv? zvb*yA+rI5JU{|1!T6#X&0B#QIwA1}V5Xnt_Fj)Z3)iVAe_6}-ME2|j zm3LI*56JQ@e6k9pp$(t2Y{?s&KqZJAyx%jT_z0P6PVSYk85Y|6_X&efaDBlno)Xv=Vz67B|5T! zr2@_8QU=m(k*ct>XBH|_5VDe{(J#oYFd@E)3;#ldkK$kqhEe&FoK+gb{ekYMHZ^3f}Zi)g996tnu+eEbf#zQ57yt&uM~pmc!Tm<18rYTa9p*#5b5 zBLf8o0uR`aZ{&zORR2_S9QSceWJ!4~KMJ6St==aW{B#fEAdU^l%HY_9o5ync-jBDal*ABuB)ckJtf55g5Q03~~91?oagRhn4`cmax3|EZ^z zhwgW^js(LOdc|MfqFzK*ym=Jzr=^L%73l2BEv#P>ZViZgpRTlxpt?k# zTIvs{-K4T^Cj)@zBaTSMRUup5G7QR;}IJ00Fw z@1}qJ%iPr1vLtv~>#fT=nl8>xTSt$1c1Dj$frSjHNUAML%6>2_n?!2+1Wt4tLP2*-Zz5W9M>uq1hi(IDG5&3APjQTpbo|{y2 z1w5KKdT~CWMl(j)qo^-Sy(N`C2=A#e5(<$(-JW zt3=eJQ8eXKS~r`!6kV53b*0M*I-5KgGi^^Yy;m$8mczh2bueaD9?;-sFn6tq%<2 zLJH3vYuW9LX!;uBh#Rz1+;lkw-C4GU%@DVg4?vsVNreeX=8=4BQAr3PHD>gL^gTm_ z5Wzr=#v3Ii*>P2c>NT49s0A$_$lVdweq7zl&**cvPXMFI>o$`b2MBFTuGChWD7=e| zN|Q_Jv}iph12EcL8|G#1Rz_v_@j@W-Kjfg$*P?|Pvd{~td(t|kGxTc$wb8yxqJ;uP z_ml1(@z+FE>Zph^IN<@)CL7f!Ia^o%5@H?(EtijMwUVPUKj{gkOe0hMAZ62B#?EW) z;Ol!4e3X63e|OJAlRdtOGOctD^19i*RAl}9Tk55r)oan9P_yE@ zSKEhwo%WmTg+MEicEtqje(uk!~i0U2?dBG8N!5+ zO>7VN?nFSHTMU}=Jgy3ZOa8Hdeq(946t&8_eZ@$6q+ULwnxh)|qJLdsEMSuv%9>lN`=#aN z%oY*gr{b*N?3^pD5~h{fb@f^E{6mLNrwWfMdTndoLZ~E{5Awm9X-Zu=>!=Lg2dl|X zf7B*fO5pDkQk7=^ipVIgI3)$tz#fVod|-KP_x_0_#^P8b2mIvbKtj2rOH!$G%?oDr z!YXKwV*W^kA;=5%L5M62bdxsDM{7wAnhm5xm~`v0PGm$9B}T&?R4wM@pt+<5b*fu= z641HsiJ~bNkf6*E#vnPkb+==;f(ZgT0aZGD0_NN}KzHOuhgy{^h7neR&IjiaN3Y2q zfvrlKh_HeEn$r0W$|oaYbcOX8oo1m;rq$m6cFxOa?yLVlRCo znQJIo3$@-7*)Y9RNQjQJNS%XE77Lfk&fO`abk6d`c>e4}98Un`wpuU-)%xBLB%*3s!I8$PEb ztA8455pi{UiGs*1Z4z(3m~S=4MLPIc0&8IsJgP((D;9UDEn|qu&otTDx;LOs8@?}w z5J|8_>?Ybu9oqMJCkzWqmEP46*c3G`lSGO5PE+CVq$oPS&Q*p&lvY{K=ZR7HZ4~(6 z_0L=EKK!|o{wxqRZ2bz0>M%_TJl_e<_qb93e95%{VR9@kLJqIj_vL=%LG82EjT-7N z$s9L=nYpRh@?tCUy;MSl+Cm;%d9BSn&ZI3wcny7~i^eRmt>5vQ?VwHZK8K`DbMw#1E4 z2T39_zLtsLB#Ee=L5fEWRy4tYzw##`Qa%zyU@Y%vMwO(tvXEZO*mWeI+s?+cLh}6RN-L-)M%x|^2Z5}~V2b(u}Uw+Wiu1oB6h8wz9&8ZDUB8)}=rWg%{>co@^4d z{)9X}j;1@(y3Sl0uJ5;dRQlWKOz$ayI+0dsDo|_33x9&U&wANZRE$>c80|j#mRn*n zua)IF?Jgu;v5x$i=$9BQqk59u11OD<0E~bl!z*VO!rg+LvgnJ1SXY`J<+XF zT8sQB2_quDr>d~FVPDj&zuc2U7XKWb`$-Q++u)Nq8SqJEiz0OX0DpVvC}!CX*J*Cd zDpG>(?&8tph5+xRJK<~D@W~(U3CHd9D+pJ*0`@aN(#o71kCdhu%;%JRf)GeC(Y^EyqN~=;YDkZsaCVhb;`3brq&4dgv#c9?fwXL zmxeB}V~Q>8CpzI~$iMEWbboiUuR9w+)|wG1byf(_USHaqi{V-j)h~{3ons%ez)O?8WF`d zZn7%!c@iEy&X-k!wumHI{*u?8Inr&5uU(x!^AbExUlK^~{KlgGMN?Yipl@jbHWE1J zkmTIb^TN~1^p{!88&O%PZf@@2_6aEYFXw2r6#1s>Ifs8X+zip;HPls68lEl9M)tcH z-3JXFHGsc#(Pi>ZiEb-KL~e-ra)*^;B+|nddLOx8S0TacA7w^xjIOb;jb93`7+Dxc zy36DDl?l9s zEv2-u5kMX*Ei1dWZ$)>^#dnls5!}>F9(j-2j1Y2Mp!TpKHWT;Y@aj83khd>%JsjJ$ z7ti0AsOM0YA9T?U4Dc&Knl;U8oj;!!V3mo>j~P$iy2j z2It}lo=LtejaLm0F@q;W+K#QSoS2$R~JulW)pl$HALuJpHR$JBh&60T@1`v50ckq55B0oZO z_4ceZyp-zlL@l1G)VEjb*n>t+65lE~YWRf#7Ib&*k6wjO=yvQhNWBk>U26xm6;l(} zXMCbQCRpZpPeiwlTucpu?xg&)iCj>Raw|*(x{uM}lE;|uP-iSJ6_HYn!;8-3(#Nm( z#Bi3cSDcDWJdb16p$8syECvvAPMk>^6T0yIa zI!Z=uRGx1y7O#Ta2>Fdr#g4@5r0&-f^8GL)!B~fqx57RF{wbRcQI4p&L!G;CvxmHK zHlUI__WbI(N|OuH7chud8QtEx6)JjaR4a6fH^~b$phd<|Ve&T!V>`?!r|bOt$f{}E z|0`vTqzI*d4ZZk#ro9VUSFTfSCMQ7nye)Qqw4A94sEFH|Bo75pbCVY5itv36|5Vgt}1cky4rQe zAUJ{;dHX-RY8HSm=|5#i6eA z7>zPkhQKb_p>EA@MyzPJ#kZP=J;R#yfViEvF0>N&<&^v3FsKsDseAg*_SxybR`2Uz zO753{u>UtOr;mQ~F3w!op7a-x;YzUBY>Vka@psOc&N9+com%INrB0@MixuFSiF_Wl zBI-|1(nUUhSfkz6Xu|Tlnbj^{Tu3-08R4n#PCF^-=qSc@Nn{Q()J2y3?ScYY_fsI%=;q3qQt+Qf%q=b~>`zHoLz=C- z7xp$+yQ{1nX;+2VS0mI=z8|sZ)j`wtsChcqY5Ak#ahidXZR@7H3oeH`(YhB-O!mEJgbWCh6R^)Tzv#!v}DbaQVTuVprTdTJZjrchS18tQQ7E#TY|O~|u! z_I$#z1&hxS_14_@mfGXMjs0untRB`-N(eP`u}+5+zzO{{Z7y~sLzc3UwhQh(_bcUE*j7$7A^Oh z!uK|WmNoD9ZniZbAUN)|po^g#8gvsuurbA(`OoHWrBqbcDI_Gk1F{NU%f44p@1uvJ z9;6^XJRk9&0!JH8Un?_~BN#`ONb4tXX(<^b{h|DD8;Voo8Z_o_^K zMCVzlze_8>ZC{$O;0Wr^%j?@i>BH1ptXV!=t6;__rAMGg)T@C~I-HBI#6_Y9HShl; z;&)}|)EENJ$HdrS!TEnX88m!iFmP4bFg39?uB|}Jc2I2^4WG3k&EP2*O2*Lsf09%G zk{FDs{;!j%81VP^JLoS%RN_wcYoT0898xtfP=js06xb;}xq)B+N`B$iI25SvS{3>) zaRfhHpcXm+1yGrlq7UeXK37$QL6zW;4d<2-~zAZ+rP0_UTf&nBGf^v zc4f;BVz;?^j6W^h$tSRXcK0G~|!4@E-N&9=e>0cq$u~(3H_Z&NtI*!}HoGc+_ z6tmB(v(?E){IghM8d=)=BCsafdQc%jl{DG13`el=Z)-|BnLxpJzY-WVir> zYhDG+xW)f(=X;=?5<{auN{vnkv`=2^5izZd^P@3j`ihmKq#e6tU|jP)E`uHsebj$+ z{hka1AV41TR%rl#s>FTIf;0FZjWg>J{c6W>RvJEapnzhxu!w)virpUlH!+;5a5-0= zdR=PjOM^UYHSXISwE&R`dR%4aNX*g`3UTPy;%YFdLcaqA*yxv^w=PzBpc>JhpU(>c zaZvFM3v_m7jBd0WOGzY6bKq%fYJA>|)|2EL+5STy(6(H8a?7hK|a# z7!bY#>be`f(X@PE^zhNASwMa-wvzy3?2Rf*BP6TVxwbfn(IkoZ&iRA|`w{f9jY4X` z(w)5nxAiF<`GTeenVN4-aD&X=>;OOH_~`QJh%1>WPyL`{Y1x(J&WF`<9WvZ)(r2=7 zLck#2`1VNIrxF%b+BBzWr@=Zh+M~XQ{*5ml_SS_kGOKGqFVaL2RiqI`PNqkuN6w*6 zX)x_B+>*<#PGSku{{m!o)M+=Lf56^S9$tZW?H+rO)(t^&(N)!~7Da$MS!~HJL7rIZ z&6^aVccp_yG z$wfY)LlIDwT{jtO@`hBV<;{GgJ; z)Y+(GK?9Yd|LK-s&#wg7Ec@)?4u9{O-1Pn+%j zG|ZpFHYTQ$iZTcr6MX6a{NdKPpQaA|bjR$gfx3^0a*7GW^?&{hBEjDbQnZ{0iN8rv z)IHF!yL--uEfStp?+gR=v=!lsBqX4O%dMDkVt4t4&tiUXK9hpgJMl$FCe7VRc8cRb z7{+HtHd*QEdGwR|O3Hp#0B@l5v$m=BaA+nt&fd~l4Vo)Ou8)G)IU1^FRjIrbXhM+ zY#Ss)7UaCUyqh%=IidQjhp_GUScmx5kl6cHCd1u6QL11=Z>I+nzfM(BH1tO!d9u44P2ObMP<>RgeBV-Sz1%u@*5;FTW;z|6H~-q= z3d{}3*h7Ejhv-VbgYrB-b-2IymTR6o9yVr29@YjM`&T~u*@I#0G-9?rJPNRA5!j6e z$S~!Dp>5A48dU~Qp=NO2d6cmuy#8N#)zd5N6JhqbyJGM$MT()v1SU_|3T5nnXXxY* zUFz|0hp|q|L{Fc&0P)l9egb*FWX6TGSj#LTh0ImMqN!n70MFOu*$@d^;E*bj2hP+5 zPQ+gHk?48v>l!QCcYnR)tsN21)NHVI`=Y`aa=|Gh5>l{qY|go7%!N6Rr4 z2D5EW5He)KV=ioat>CpZg!wXju68YtgMZ;J+VNOIgYhK#*Kc*Ml;=S^k|=d%y!0cu ze$=dC4C5nx(?qyWvyDTn(b?GJJWuhqNY>m)ZC(tFaDZZOOk;;UpMoZJBo8(Lg`m3y zqKpGMNOfY`H!OTAjrPbP5aNf@0dMXV{>%frh3stcw!f_0c`jX8bjw&8zHC+WOm$1% z|2b$VqYynbZ4l)?`HjTr9kg_NP~Bx^H%@>-aaHDUtWQ6UtaoJjJi6fP0*8w!sNAhWBPDUZQp5S z5X&qj-ON4RL=yF4W90V*fi=>E`vs{_nT+97AAT;vw+I{@i4EF|DbZg!ru4#1rw}4w z9abmGyUhJ+vOGKV2GhPMWJze-w;fo|CvHFq8d8s;zn6_Sz__GR^y9@=$={95`GG(I zfdT3HIq=xlGA<6I_H!56&Mc=gy)>I9-L>nD8wdYy?Ri2%N?eALP{sVrV#HDplBdn` zH(;S>y{QhP>v-H??1D`8V=Toq98b5;Ti#D9T(jTMg}i<|#uv@S zgOx)3uJ8FiT#DRUY5IXXUzIbR*NGv4J4$LqV7-e^{H*NP5G_BHQpD3T?b1cCizcR*22u&HqH(kK3Ak^h|UI`l2(Ky3SyIy zW#)l(zcYn<63%%LN4|sB>B75y?qu6}O z7MU0dSbO~0xsu3ZHk6HAg+S0noU~REcEQZlp<%9gpm}59y!dn zIrUEq2boR37_qYUPNS-YbaR0tV`?|a6Z%Je?#~~>gLmS5ceWQnmZL*zM3sshwZ1zR z9$ncym?u*J?|PB+Mm641G(@>L%|QbfQLnm9UK@`4qquLfw9I5NY*O1az|Ng#QyXB2tZuU;?RZ*j~|$>Q&Ocql5kc zgPqL`_DgAY>aF}YfYvku0@gp(b4)Excl_S$8i zX;xow`Hh*~R2G12-MRbXB3YKQ-1J2_kru{E;>S?yVb8*|;0Xv|J}xETt@4)RLB@Ln zLwD>K;~$Rmd`Oroi;|W|g-@-Vi;{rzjT2$9UKCzEY-~3dDa(RCTw-#2z2vq{lD!l9 zZFgXYkgFjMNPPYlI&uUJ7CK?_nz_O6cu}OT3^j-cXax7_1U3dqf2?g|p@$+hG`0FYs?tQL$S!lA~Ncz1v@4}H;mq;Hf zgmjAu=>y8EHZmp=?i5Pwk|455J~bjpL-p-|{9z^j;T>jkdfOQr;b=e5U~EHDihEag zb5VTmMw$R99G2_nS0M2Xh<@fdGmIoGvjrEL+}vzkxJ+sChPHvDX1Aj&y7tv;9s%z} zAq_84P+cc3KDq+P%OAMB{cG;5o-M zTEI{kdJ4pudlQZMbsnoqYXytXM~0t1FU|$45n=t}0WAww{c_g4!~F#E6p9yq(&49K T5bzX%g*oJ)%F>Tq6|ay(Fq|@ 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 YN4zmRj*shI{mVEg%Bsm!NtuNHFUpX@*Z=?k literal 0 HcmV?d00001 diff --git a/docs/images/autotype_selection_dialog_type_menu.png b/docs/images/autotype_selection_dialog_type_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e83ee80fd985e4e49976a797b78ad01be02489 GIT binary patch literal 36766 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 literal 0 HcmV?d00001 diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index 6e608a9ab..eb6a76909 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -69,12 +69,22 @@ image::autotype_entry_sequences.png[] === Performing Global Auto-Type The global Auto-Type keyboard shortcut is used when you have focus on the window you want to type into. To make use of this feature, you must have previously configured an Auto-Type hotkey. -Pressing the global Auto-Type hotkey cause KeePassXC to search the database for entries that match the window title. Multiple matches may be returned and will cause the sequence selection dialog to appear. Click on a sequence line will immediately execute the Auto-Type action. A search box is also available in case numerous matches are returned. +When you press the global Auto-Type hotkey, KeePassXC searches all unlocked databases for entries that match the focused window title. The Auto-Type selection dialog will appear in the following circumstances: there are no matches found, there are multiple matches found, or the setting "Always ask before performing Auto-Type" is enabled. .Auto-Type sequence selection image::autotype_selection_dialog.png[,70%] -TIP: The _Sequence_ column will only appear when there are different sequences defined by one or more entries displayed in the selection dialog. +Perform the selected Auto-Type sequence by double clicking the desired row or pressing _Enter_. Press the up and down arrows to navigate the list. Sequences can be filtered through the text edit field. + +.Auto-Type search database +image::autotype_selection_dialog_search.png[,70%] + +Search the unlocked databases by activating Search Database radio button. Use the text edit field to issue search queries using the same syntax as database searching. + +.Additional Auto-Type choices +image::autotype_selection_dialog_type_menu.png[,70%] + +The option to type just the username, password, or current TOTP value is available by right clicking the desired row or expanding the Type Sequence button options. === Performing Entry-Level Auto-Type You can quickly activate the default Auto-Type sequence for a particular entry using Entry-Level Auto-Type. For this operation, the KeePassXC window will be minimized and the Auto-Type sequence occurs in the previously selected window. You can perform Entry-Level Auto-Type from the toolbar icon *(A)*, entry context menu *(B)*, or by pressing `Ctrl+Shift+V`. diff --git a/docs/topics/DownloadInstall.adoc b/docs/topics/DownloadInstall.adoc index cc6f1fcb7..5f692638c 100644 --- a/docs/topics/DownloadInstall.adoc +++ b/docs/topics/DownloadInstall.adoc @@ -60,3 +60,5 @@ To install the KeePassXC app on macOS, double click on the downloaded DMG file a image::macos_install.png[,80%] // end::content[] +// tag::advanced[] +// end::advanced[] \ No newline at end of file diff --git a/docs/topics/Welcome.adoc b/docs/topics/Welcome.adoc index 507419029..4eb168e6c 100644 --- a/docs/topics/Welcome.adoc +++ b/docs/topics/Welcome.adoc @@ -44,3 +44,5 @@ KeePassXC has numerous features for novice and power users alike. This guide wil ** FreeDesktop.org Secret Service (replace Gnome keyring, etc.) ** Additional encryption choices: Twofish and ChaCha20 // end::content[] +// tag::advanced[] +// end::advanced[] \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b308df2f3..ba8acdc77 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,7 +33,6 @@ endif(NOT ZXCVBN_LIBRARIES) set(keepassx_SOURCES core/Alloc.cpp core/AutoTypeAssociations.cpp - core/AutoTypeMatch.cpp core/Base32.cpp core/Bootstrap.cpp core/Clock.cpp @@ -139,8 +138,6 @@ set(keepassx_SOURCES gui/csvImport/CsvImportWizard.cpp gui/csvImport/CsvParserModel.cpp gui/entry/AutoTypeAssociationsModel.cpp - gui/entry/AutoTypeMatchModel.cpp - gui/entry/AutoTypeMatchView.cpp gui/entry/EditEntryWidget.cpp gui/entry/EntryAttachmentsModel.cpp gui/entry/EntryAttachmentsWidget.cpp @@ -273,11 +270,10 @@ set(autotype_SOURCES core/Tools.cpp autotype/AutoType.cpp autotype/AutoTypeAction.cpp - autotype/AutoTypeFilterLineEdit.cpp + autotype/AutoTypeMatchModel.cpp + autotype/AutoTypeMatchView.cpp autotype/AutoTypeSelectDialog.cpp - autotype/AutoTypeSelectView.cpp autotype/ShortcutWidget.cpp - autotype/WildcardMatcher.cpp autotype/WindowSelectComboBox.cpp) if(MINGW) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 94dd432c9..7a52491b3 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -21,13 +21,12 @@ #include #include #include +#include #include "config-keepassx.h" #include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeSelectDialog.h" -#include "autotype/WildcardMatcher.h" -#include "core/AutoTypeMatch.h" #include "core/Config.h" #include "core/Database.h" #include "core/Entry.h" @@ -250,12 +249,10 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow) return; } - QList sequences = autoTypeSequences(entry); - if (sequences.isEmpty()) { - return; + auto sequences = entry->autoTypeSequences(); + if (!sequences.isEmpty()) { + executeAutoTypeActions(entry, hideWindow, sequences.first()); } - - executeAutoTypeActions(entry, hideWindow, sequences.first()); } /** @@ -273,6 +270,11 @@ void AutoType::performAutoTypeWithSequence(const Entry* entry, const QString& se void AutoType::startGlobalAutoType() { + // Never Auto-Type into KeePassXC itself + if (qApp->focusWindow()) { + return; + } + m_windowForGlobal = m_plugin->activeWindow(); m_windowTitleForGlobal = m_plugin->activeWindowTitle(); #ifdef Q_OS_MACOS @@ -331,58 +333,62 @@ void AutoType::performGlobalAutoType(const QList>& dbLi for (const auto& db : dbList) { const QList dbEntries = db->rootGroup()->entriesRecursive(); - for (Entry* entry : dbEntries) { + for (auto entry : dbEntries) { + auto group = entry->group(); + if (!group || !group->resolveAutoTypeEnabled() || !entry->autoTypeEnabled()) { + continue; + } + if (hideExpired && entry->isExpired()) { continue; } - const QSet sequences = autoTypeSequences(entry, m_windowTitleForGlobal).toSet(); - for (const QString& sequence : sequences) { - if (!sequence.isEmpty()) { - matchList << AutoTypeMatch(entry, sequence); - } + auto sequences = entry->autoTypeSequences(m_windowTitleForGlobal).toSet(); + for (const auto& sequence : sequences) { + matchList << AutoTypeMatch(entry, sequence); } } } - if (matchList.isEmpty()) { - if (qobject_cast(QCoreApplication::instance())) { - auto* msgBox = new QMessageBox(); - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->setWindowTitle(tr("Auto-Type - KeePassXC")); - msgBox->setText(tr("Couldn't find an entry that matches the window title:") - .append("\n\n") - .append(m_windowTitleForGlobal)); - msgBox->setIcon(QMessageBox::Information); - msgBox->setStandardButtons(QMessageBox::Ok); -#ifdef Q_OS_MACOS - m_plugin->raiseOwnWindow(); - Tools::wait(200); -#endif - msgBox->exec(); - restoreWindowState(); + // Show the selection dialog if we always ask, have multiple matches, or no matches + if (config()->get(Config::Security_AutoTypeAsk).toBool() || matchList.size() > 1 || matchList.isEmpty()) { + // Close any open modal windows that would interfere with the process + if (qApp->modalWindow()) { + qApp->modalWindow()->close(); } - m_inGlobalAutoTypeDialog.unlock(); - emit autotypeRejected(); - } else if ((matchList.size() == 1) && !config()->get(Config::Security_AutoTypeAsk).toBool()) { - executeAutoTypeActions(matchList.first().entry, nullptr, matchList.first().sequence, m_windowForGlobal); - m_inGlobalAutoTypeDialog.unlock(); - } else { auto* selectDialog = new AutoTypeSelectDialog(); + selectDialog->setMatches(matchList, dbList); - // connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex - connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), SLOT(performAutoTypeFromGlobal(AutoTypeMatch))); - connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal())); + connect(getMainWindow(), &MainWindow::databaseLocked, selectDialog, &AutoTypeSelectDialog::reject); + connect(selectDialog, &AutoTypeSelectDialog::matchActivated, this, [this](AutoTypeMatch match) { + restoreWindowState(); + QApplication::processEvents(); + m_plugin->raiseWindow(m_windowForGlobal); + executeAutoTypeActions(match.first, nullptr, match.second, m_windowForGlobal); + resetAutoTypeState(); + }); + connect(selectDialog, &QDialog::rejected, this, [this] { + restoreWindowState(); + resetAutoTypeState(); + emit autotypeRejected(); + }); - selectDialog->setMatchList(matchList); #ifdef Q_OS_MACOS m_plugin->raiseOwnWindow(); Tools::wait(200); #endif selectDialog->show(); selectDialog->raise(); - // necessary when the main window is minimized selectDialog->activateWindow(); + } else if (!matchList.isEmpty()) { + // Only one match and not asking, do it! + executeAutoTypeActions(matchList.first().first, nullptr, matchList.first().second, m_windowForGlobal); + resetAutoTypeState(); + } else { + // We should never get here + Q_ASSERT(false); + resetAutoTypeState(); + emit autotypeRejected(); } } @@ -399,29 +405,12 @@ void AutoType::restoreWindowState() #endif } -void AutoType::performAutoTypeFromGlobal(AutoTypeMatch match) +void AutoType::resetAutoTypeState() { - restoreWindowState(); - - m_plugin->raiseWindow(m_windowForGlobal); - executeAutoTypeActions(match.entry, nullptr, match.sequence, m_windowForGlobal); - - // make sure the mutex is definitely locked before we unlock it - Q_UNUSED(m_inGlobalAutoTypeDialog.tryLock()); - m_inGlobalAutoTypeDialog.unlock(); -} - -void AutoType::autoTypeRejectedFromGlobal() -{ - // this slot can be called twice when the selection dialog is deleted, - // so make sure the mutex is locked before we try unlocking it - Q_UNUSED(m_inGlobalAutoTypeDialog.tryLock()); - m_inGlobalAutoTypeDialog.unlock(); m_windowForGlobal = 0; m_windowTitleForGlobal.clear(); - - restoreWindowState(); - emit autotypeRejected(); + Q_UNUSED(m_inGlobalAutoTypeDialog.tryLock()); + m_inGlobalAutoTypeDialog.unlock(); } /** @@ -622,101 +611,6 @@ QList AutoType::createActionFromTemplate(const QString& tmpl, c return list; } -/** - * Retrive the autotype sequences matches for a given windowTitle - * This returns a list with priority ordering. If you don't want duplicates call .toSet() on it. - */ -QList AutoType::autoTypeSequences(const Entry* entry, const QString& windowTitle) -{ - QList sequenceList; - const Group* group = entry->group(); - - if (!group || !entry->autoTypeEnabled()) { - return sequenceList; - } - - do { - if (group->autoTypeEnabled() == Group::Disable) { - return sequenceList; - } else if (group->autoTypeEnabled() == Group::Enable) { - break; - } - group = group->parentGroup(); - - } while (group); - - if (!windowTitle.isEmpty()) { - const QList assocList = entry->autoTypeAssociations()->getAll(); - for (const AutoTypeAssociations::Association& assoc : assocList) { - const QString window = entry->resolveMultiplePlaceholders(assoc.window); - if (windowMatches(windowTitle, window)) { - if (!assoc.sequence.isEmpty()) { - sequenceList.append(assoc.sequence); - } else { - sequenceList.append(entry->effectiveAutoTypeSequence()); - } - } - } - - if (config()->get(Config::AutoTypeEntryTitleMatch).toBool() - && windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title()))) { - sequenceList.append(entry->effectiveAutoTypeSequence()); - } - - if (config()->get(Config::AutoTypeEntryURLMatch).toBool() - && windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url()))) { - sequenceList.append(entry->effectiveAutoTypeSequence()); - } - - if (sequenceList.isEmpty()) { - return sequenceList; - } - } else { - sequenceList.append(entry->effectiveAutoTypeSequence()); - } - - return sequenceList; -} - -/** - * Checks if a window title matches a pattern - */ -bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPattern) -{ - if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) { - QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2); - return (regExp.indexIn(windowTitle) != -1); - } - return WildcardMatcher(windowTitle).match(windowPattern); -} - -/** - * Checks if a window title matches an entry Title - * The entry title should be Spr-compiled by the caller - */ -bool AutoType::windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle) -{ - return !resolvedTitle.isEmpty() && windowTitle.contains(resolvedTitle, Qt::CaseInsensitive); -} - -/** - * Checks if a window title matches an entry URL - * The entry URL should be Spr-compiled by the caller - */ -bool AutoType::windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl) -{ - if (!resolvedUrl.isEmpty() && windowTitle.contains(resolvedUrl, Qt::CaseInsensitive)) { - return true; - } - - QUrl url(resolvedUrl); - if (url.isValid() && !url.host().isEmpty()) { - return windowTitle.contains(url.host(), Qt::CaseInsensitive); - } - - return false; -} - /** * Checks if the overall syntax of an autotype sequence is fine */ diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index 8d0cf3d14..0af78c4c5 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -24,7 +24,7 @@ #include #include -#include "core/AutoTypeMatch.h" +#include "autotype/AutoTypeMatch.h" class AutoTypeAction; class AutoTypeExecutor; @@ -68,8 +68,6 @@ signals: private slots: void startGlobalAutoType(); - void performAutoTypeFromGlobal(AutoTypeMatch match); - void autoTypeRejectedFromGlobal(); void unloadPlugin(); private: @@ -89,11 +87,8 @@ private: WId window = 0); bool parseActions(const QString& sequence, const Entry* entry, QList& actions); QList createActionFromTemplate(const QString& tmpl, const Entry* entry); - QList autoTypeSequences(const Entry* entry, const QString& windowTitle = QString()); - bool windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle); - bool windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl); - bool windowMatches(const QString& windowTitle, const QString& windowPattern); void restoreWindowState(); + void resetAutoTypeState(); QMutex m_inAutoType; QMutex m_inGlobalAutoTypeDialog; diff --git a/src/autotype/AutoTypeFilterLineEdit.cpp b/src/autotype/AutoTypeFilterLineEdit.cpp deleted file mode 100644 index d94292d26..000000000 --- a/src/autotype/AutoTypeFilterLineEdit.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "AutoTypeFilterLineEdit.h" -#include - -void AutoTypeFilterLineEdit::keyPressEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_Up) { - emit keyUpPressed(); - } else if (event->key() == Qt::Key_Down) { - emit keyDownPressed(); - } else { - QLineEdit::keyPressEvent(event); - } -} - -void AutoTypeFilterLineEdit::keyReleaseEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_Escape) { - emit escapeReleased(); - } else { - QLineEdit::keyReleaseEvent(event); - } -} diff --git a/src/autotype/AutoTypeFilterLineEdit.h b/src/autotype/AutoTypeFilterLineEdit.h deleted file mode 100644 index 6f8ca570d..000000000 --- a/src/autotype/AutoTypeFilterLineEdit.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_AUTOTYPEFILTERLINEEDIT_H -#define KEEPASSX_AUTOTYPEFILTERLINEEDIT_H - -#include - -class AutoTypeFilterLineEdit : public QLineEdit -{ - Q_OBJECT - -public: - AutoTypeFilterLineEdit(QWidget* widget) - : QLineEdit(widget) - { - } - -protected: - virtual void keyPressEvent(QKeyEvent* event); - virtual void keyReleaseEvent(QKeyEvent* event); -signals: - void keyUpPressed(); - void keyDownPressed(); - void escapeReleased(); -}; - -#endif // KEEPASSX_AUTOTYPEFILTERLINEEDIT_H diff --git a/src/core/AutoTypeMatch.h b/src/autotype/AutoTypeMatch.h similarity index 56% rename from src/core/AutoTypeMatch.h rename to src/autotype/AutoTypeMatch.h index 768cf1682..4f396546a 100644 --- a/src/core/AutoTypeMatch.h +++ b/src/autotype/AutoTypeMatch.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2015 David Wu - * Copyright (C) 2017 KeePassXC Team + * Copyright (C) 2021 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,26 +15,14 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_AUTOTYPEMATCH_H -#define KEEPASSX_AUTOTYPEMATCH_H +#ifndef KPXC_AUTOTYPEMATCH_H +#define KPXC_AUTOTYPEMATCH_H -#include +#include +#include #include class Entry; +typedef QPair, QString> AutoTypeMatch; -struct AutoTypeMatch -{ - Entry* entry; - QString sequence; - - AutoTypeMatch(); - AutoTypeMatch(Entry* entry, QString sequence); - - bool operator==(const AutoTypeMatch& other) const; - bool operator!=(const AutoTypeMatch& other) const; -}; - -Q_DECLARE_TYPEINFO(AutoTypeMatch, Q_MOVABLE_TYPE); - -#endif // KEEPASSX_AUTOTYPEMATCH_H +#endif // KPXC_AUTOTYPEMATCH_H diff --git a/src/gui/entry/AutoTypeMatchModel.cpp b/src/autotype/AutoTypeMatchModel.cpp similarity index 88% rename from src/gui/entry/AutoTypeMatchModel.cpp rename to src/autotype/AutoTypeMatchModel.cpp index ac2d0f874..f15df233b 100644 --- a/src/gui/entry/AutoTypeMatchModel.cpp +++ b/src/autotype/AutoTypeMatchModel.cpp @@ -56,7 +56,7 @@ void AutoTypeMatchModel::setMatchList(const QList& matches) QSet databases; for (AutoTypeMatch& match : m_matches) { - databases.insert(match.entry->group()->database()); + databases.insert(match.first->group()->database()); } for (Database* db : asConst(databases)) { @@ -88,7 +88,6 @@ int AutoTypeMatchModel::rowCount(const QModelIndex& parent) const int AutoTypeMatchModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); - return 4; } @@ -103,30 +102,30 @@ QVariant AutoTypeMatchModel::data(const QModelIndex& index, int role) const if (role == Qt::DisplayRole) { switch (index.column()) { case ParentGroup: - if (match.entry->group()) { - return match.entry->group()->name(); + if (match.first->group()) { + return match.first->group()->name(); } break; case Title: - return match.entry->resolveMultiplePlaceholders(match.entry->title()); + return match.first->resolveMultiplePlaceholders(match.first->title()); case Username: - return match.entry->resolveMultiplePlaceholders(match.entry->username()); + return match.first->resolveMultiplePlaceholders(match.first->username()); case Sequence: - return match.sequence; + return match.second; } } else if (role == Qt::DecorationRole) { switch (index.column()) { case ParentGroup: - if (match.entry->group()) { - return match.entry->group()->iconPixmap(); + if (match.first->group()) { + return match.first->group()->iconPixmap(); } break; case Title: - return match.entry->iconPixmap(); + return match.first->iconPixmap(); } } else if (role == Qt::FontRole) { QFont font; - if (match.entry->isExpired()) { + if (match.first->isExpired()) { font.setStrikeOut(true); } return font; @@ -157,7 +156,7 @@ void AutoTypeMatchModel::entryDataChanged(Entry* entry) { for (int row = 0; row < m_matches.size(); ++row) { AutoTypeMatch match = m_matches[row]; - if (match.entry == entry) { + if (match.first == entry) { emit dataChanged(index(row, 0), index(row, columnCount() - 1)); } } @@ -167,7 +166,7 @@ void AutoTypeMatchModel::entryAboutToRemove(Entry* entry) { for (int row = 0; row < m_matches.size(); ++row) { AutoTypeMatch match = m_matches[row]; - if (match.entry == entry) { + if (match.first == entry) { beginRemoveRows(QModelIndex(), row, row); m_matches.removeAt(row); endRemoveRows(); diff --git a/src/gui/entry/AutoTypeMatchModel.h b/src/autotype/AutoTypeMatchModel.h similarity index 98% rename from src/gui/entry/AutoTypeMatchModel.h rename to src/autotype/AutoTypeMatchModel.h index 58b89465b..e5c86e84d 100644 --- a/src/gui/entry/AutoTypeMatchModel.h +++ b/src/autotype/AutoTypeMatchModel.h @@ -21,7 +21,7 @@ #include -#include "core/AutoTypeMatch.h" +#include "autotype/AutoTypeMatch.h" class Entry; class Group; diff --git a/src/autotype/AutoTypeMatchView.cpp b/src/autotype/AutoTypeMatchView.cpp new file mode 100644 index 000000000..453d9072e --- /dev/null +++ b/src/autotype/AutoTypeMatchView.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 David Wu + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "AutoTypeMatchView.h" + +#include "core/Entry.h" +#include "gui/Clipboard.h" +#include "gui/Icons.h" + +#include +#include +#include +#include + +class CustomSortFilterProxyModel : public QSortFilterProxyModel +{ +public: + explicit CustomSortFilterProxyModel(QObject* parent = nullptr) + : QSortFilterProxyModel(parent){}; + ~CustomSortFilterProxyModel() override = default; + + // Only search the first three columns (ie, ignore sequence column) + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override + { + auto index0 = sourceModel()->index(sourceRow, 0, sourceParent); + auto index1 = sourceModel()->index(sourceRow, 1, sourceParent); + auto index2 = sourceModel()->index(sourceRow, 2, sourceParent); + + return sourceModel()->data(index0).toString().contains(filterRegExp()) + || sourceModel()->data(index1).toString().contains(filterRegExp()) + || sourceModel()->data(index2).toString().contains(filterRegExp()); + } +}; + +AutoTypeMatchView::AutoTypeMatchView(QWidget* parent) + : QTableView(parent) + , m_model(new AutoTypeMatchModel(this)) + , m_sortModel(new CustomSortFilterProxyModel(this)) +{ + m_sortModel->setSourceModel(m_model); + m_sortModel->setDynamicSortFilter(true); + m_sortModel->setSortLocaleAware(true); + m_sortModel->setSortCaseSensitivity(Qt::CaseInsensitive); + m_sortModel->setFilterKeyColumn(-1); + m_sortModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + setModel(m_sortModel); + + sortByColumn(0, Qt::AscendingOrder); + + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, &QTableView::doubleClicked, this, [this](const QModelIndex& index) { + emit matchActivated(matchFromIndex(index)); + }); +} + +void AutoTypeMatchView::keyPressEvent(QKeyEvent* event) +{ + if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) && currentIndex().isValid()) { + emit matchActivated(matchFromIndex(currentIndex())); + } + + QTableView::keyPressEvent(event); +} + +void AutoTypeMatchView::setMatchList(const QList& matches) +{ + m_model->setMatchList(matches); + m_sortModel->setFilterWildcard({}); + + horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); + selectionModel()->setCurrentIndex(m_sortModel->index(0, 0), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + emit currentMatchChanged(currentMatch()); +} + +void AutoTypeMatchView::filterList(const QString& filter) +{ + m_sortModel->setFilterWildcard(filter); + setCurrentIndex(m_sortModel->index(0, 0)); +} + +AutoTypeMatch AutoTypeMatchView::currentMatch() +{ + QModelIndexList list = selectionModel()->selectedRows(); + if (list.size() == 1) { + return m_model->matchFromIndex(m_sortModel->mapToSource(list.first())); + } + return {}; +} + +AutoTypeMatch AutoTypeMatchView::matchFromIndex(const QModelIndex& index) +{ + if (index.isValid()) { + return m_model->matchFromIndex(m_sortModel->mapToSource(index)); + } + return {}; +} + +void AutoTypeMatchView::currentChanged(const QModelIndex& current, const QModelIndex& previous) +{ + auto match = matchFromIndex(current); + emit currentMatchChanged(match); + QTableView::currentChanged(current, previous); +} diff --git a/src/gui/entry/AutoTypeMatchView.h b/src/autotype/AutoTypeMatchView.h similarity index 72% rename from src/gui/entry/AutoTypeMatchView.h rename to src/autotype/AutoTypeMatchView.h index 69d0795d9..90442baa6 100644 --- a/src/gui/entry/AutoTypeMatchView.h +++ b/src/autotype/AutoTypeMatchView.h @@ -19,42 +19,37 @@ #ifndef KEEPASSX_AUTOTYPEMATCHVIEW_H #define KEEPASSX_AUTOTYPEMATCHVIEW_H -#include +#include -#include "core/AutoTypeMatch.h" +#include "autotype/AutoTypeMatch.h" +#include "autotype/AutoTypeMatchModel.h" -#include "gui/entry/AutoTypeMatchModel.h" +class QSortFilterProxyModel; -class SortFilterHideProxyModel; - -class AutoTypeMatchView : public QTreeView +class AutoTypeMatchView : public QTableView { Q_OBJECT public: explicit AutoTypeMatchView(QWidget* parent = nullptr); AutoTypeMatch currentMatch(); - void setCurrentMatch(const AutoTypeMatch& match); AutoTypeMatch matchFromIndex(const QModelIndex& index); void setMatchList(const QList& matches); - void setFirstMatchActive(); + void filterList(const QString& filter); signals: + void currentMatchChanged(AutoTypeMatch match); void matchActivated(AutoTypeMatch match); - void matchSelectionChanged(); - void matchTextCopied(); protected: void keyPressEvent(QKeyEvent* event) override; -private slots: - void emitMatchActivated(const QModelIndex& index); - void userNameCopied(); - void passwordCopied(); +protected slots: + void currentChanged(const QModelIndex& current, const QModelIndex& previous) override; private: AutoTypeMatchModel* const m_model; - SortFilterHideProxyModel* const m_sortModel; + QSortFilterProxyModel* const m_sortModel; }; #endif // KEEPASSX_AUTOTYPEMATCHVIEW_H diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index e91355f4a..836ba3070 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -1,6 +1,6 @@ /* + * Copyright (C) 2021 KeePassXC Team * Copyright (C) 2012 Felix Geyer - * Copyright (C) 2020 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,168 +17,324 @@ */ #include "AutoTypeSelectDialog.h" +#include "ui_AutoTypeSelectDialog.h" -#include +#include +#include +#include #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) #include #else #include #endif -#include -#include -#include -#include -#include -#include -#include "autotype/AutoTypeSelectView.h" -#include "core/AutoTypeMatch.h" #include "core/Config.h" +#include "core/Database.h" +#include "core/Entry.h" +#include "core/EntrySearcher.h" +#include "gui/Clipboard.h" #include "gui/Icons.h" -#include "gui/entry/AutoTypeMatchModel.h" AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) : QDialog(parent) - , m_view(new AutoTypeSelectView(this)) - , m_filterLineEdit(new AutoTypeFilterLineEdit(this)) - , m_matchActivatedEmitted(false) - , m_rejected(false) + , m_ui(new Ui::AutoTypeSelectDialog()) { setAttribute(Qt::WA_DeleteOnClose); // Places the window on the active (virtual) desktop instead of where the main window is. setAttribute(Qt::WA_X11BypassTransientForHint); - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - setWindowTitle(tr("Auto-Type - KeePassXC")); + setWindowFlags((windowFlags() | Qt::WindowStaysOnTopHint) & ~Qt::WindowContextHelpButtonHint); setWindowIcon(icons()->applicationIcon()); + buildActionMenu(); + + m_ui->setupUi(this); + + connect(m_ui->view, &AutoTypeMatchView::matchActivated, this, &AutoTypeSelectDialog::submitAutoTypeMatch); + connect(m_ui->view, &AutoTypeMatchView::currentMatchChanged, this, &AutoTypeSelectDialog::updateActionMenu); + connect(m_ui->view, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) { + if (m_ui->view->currentMatch().first) { + m_actionMenu->popup(m_ui->view->viewport()->mapToGlobal(pos)); + } + }); + + + m_ui->search->setFocus(); + m_ui->search->installEventFilter(this); + + m_searchTimer.setInterval(300); + m_searchTimer.setSingleShot(true); + + connect(m_ui->search, SIGNAL(textChanged(QString)), &m_searchTimer, SLOT(start())); + connect(m_ui->search, SIGNAL(returnPressed()), SLOT(activateCurrentMatch())); + connect(&m_searchTimer, SIGNAL(timeout()), SLOT(performSearch())); + + connect(m_ui->filterRadio, &QRadioButton::toggled, this, [this](bool checked) { + if (checked) { + // Reset to original match list + m_ui->view->setMatchList(m_matches); + performSearch(); + m_ui->search->setFocus(); + } + }); + connect(m_ui->searchRadio, &QRadioButton::toggled, this, [this](bool checked) { + if (checked) { + performSearch(); + m_ui->search->setFocus(); + } + }); + + m_actionMenu->installEventFilter(this); + m_ui->action->setMenu(m_actionMenu); + m_ui->action->installEventFilter(this); + connect(m_ui->action, &QToolButton::clicked, this, &AutoTypeSelectDialog::activateCurrentMatch); + + connect(m_ui->cancelButton, SIGNAL(clicked()), SLOT(reject())); +} + +// Required for QScopedPointer +AutoTypeSelectDialog::~AutoTypeSelectDialog() +{ +} + +void AutoTypeSelectDialog::setMatches(const QList& matches, const QList>& dbs) +{ + m_matches = matches; + m_dbs = dbs; + + m_ui->view->setMatchList(m_matches); + if (m_matches.isEmpty()) { + m_ui->searchRadio->setChecked(true); + } else { + m_ui->filterRadio->setChecked(true); + } +} + +void AutoTypeSelectDialog::submitAutoTypeMatch(AutoTypeMatch match) +{ + m_accepted = true; + accept(); + emit matchActivated(std::move(match)); +} + +void AutoTypeSelectDialog::performSearch() +{ + if (m_ui->filterRadio->isChecked()) { + m_ui->view->filterList(m_ui->search->text()); + return; + } + + auto searchText = m_ui->search->text(); + // If no search text, find all entries + if (searchText.isEmpty()) { + searchText.append("*"); + } + + EntrySearcher searcher; + QList matches; + for (const auto& db : m_dbs) { + auto found = searcher.search(searchText, db->rootGroup()); + for (auto* entry : found) { + QSet sequences; + auto defSequence = entry->effectiveAutoTypeSequence(); + if (!defSequence.isEmpty()) { + matches.append({entry, defSequence}); + sequences << defSequence; + } + for (const auto& assoc : entry->autoTypeAssociations()->getAll()) { + if (!sequences.contains(assoc.sequence) && !assoc.sequence.isEmpty()) { + matches.append({entry, assoc.sequence}); + sequences << assoc.sequence; + } + } + } + } + + m_ui->view->setMatchList(matches); +} + +void AutoTypeSelectDialog::moveSelectionUp() +{ + auto current = m_ui->view->currentIndex(); + auto previous = current.sibling(current.row() - 1, 0); + + if (previous.isValid()) { + m_ui->view->setCurrentIndex(previous); + } +} + +void AutoTypeSelectDialog::moveSelectionDown() +{ + auto current = m_ui->view->currentIndex(); + auto next = current.sibling(current.row() + 1, 0); + + if (next.isValid()) { + m_ui->view->setCurrentIndex(next); + } +} + +void AutoTypeSelectDialog::activateCurrentMatch() +{ + submitAutoTypeMatch(m_ui->view->currentMatch()); +} + +bool AutoTypeSelectDialog::eventFilter(QObject* obj, QEvent* event) +{ + if (obj == m_ui->action) { + if (event->type() == QEvent::FocusIn) { + m_ui->action->showMenu(); + return true; + } else if (event->type() == QEvent::KeyPress && static_cast(event)->key() == Qt::Key_Return) { + // handle case where the menu is closed but the button has focus + activateCurrentMatch(); + return true; + } + } else if (obj == m_actionMenu) { + if (event->type() == QEvent::KeyPress) { + auto* keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Tab: + m_actionMenu->close(); + focusNextPrevChild(true); + return true; + case Qt::Key_Backtab: + m_actionMenu->close(); + focusNextPrevChild(false); + return true; + case Qt::Key_Return: + // accept the dialog with default sequence if no action selected + if (!m_actionMenu->activeAction()) { + activateCurrentMatch(); + return true; + } + default: + break; + } + } + } else if (obj == m_ui->search) { + if (event->type() == QEvent::KeyPress) { + auto* keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Up: + moveSelectionUp(); + return true; + case Qt::Key_Down: + moveSelectionDown(); + return true; + case Qt::Key_Escape: + if (m_ui->search->text().isEmpty()) { + reject(); + } else { + m_ui->search->clear(); + } + return true; + default: + break; + } + } + } + + return QDialog::eventFilter(obj, event); +} + +void AutoTypeSelectDialog::updateActionMenu(const AutoTypeMatch& match) +{ + if (!match.first) { + m_ui->action->setEnabled(false); + return; + } + + m_ui->action->setEnabled(true); + + bool hasUsername = !match.first->username().isEmpty(); + bool hasPassword = !match.first->password().isEmpty(); + bool hasTotp = match.first->hasTotp(); + + auto actions = m_actionMenu->actions(); + Q_ASSERT(actions.size() >= 6); + actions[0]->setEnabled(hasUsername); + actions[1]->setEnabled(hasPassword); + actions[2]->setEnabled(hasTotp); + actions[3]->setEnabled(hasUsername); + actions[4]->setEnabled(hasPassword); + actions[5]->setEnabled(hasTotp); +} + +void AutoTypeSelectDialog::buildActionMenu() +{ + m_actionMenu = new QMenu(this); + auto typeUsernameAction = new QAction(icons()->icon("auto-type"), tr("Type {USERNAME}"), this); + auto typePasswordAction = new QAction(icons()->icon("auto-type"), tr("Type {PASSWORD}"), this); + auto typeTotpAction = new QAction(icons()->icon("auto-type"), tr("Type {TOTP}"), this); + auto copyUsernameAction = new QAction(icons()->icon("username-copy"), tr("Copy Username"), this); + auto copyPasswordAction = new QAction(icons()->icon("password-copy"), tr("Copy Password"), this); + auto copyTotpAction = new QAction(icons()->icon("chronometer"), tr("Copy TOTP"), this); + m_actionMenu->addAction(typeUsernameAction); + m_actionMenu->addAction(typePasswordAction); + m_actionMenu->addAction(typeTotpAction); + m_actionMenu->addAction(copyUsernameAction); + m_actionMenu->addAction(copyPasswordAction); + m_actionMenu->addAction(copyTotpAction); + + connect(typeUsernameAction, &QAction::triggered, this, [&] { + auto match = m_ui->view->currentMatch(); + match.second = "{USERNAME}"; + submitAutoTypeMatch(match); + }); + connect(typePasswordAction, &QAction::triggered, this, [&] { + auto match = m_ui->view->currentMatch(); + match.second = "{PASSWORD}"; + submitAutoTypeMatch(match); + }); + connect(typeTotpAction, &QAction::triggered, this, [&] { + auto match = m_ui->view->currentMatch(); + match.second = "{TOTP}"; + submitAutoTypeMatch(match); + }); + + connect(copyUsernameAction, &QAction::triggered, this, [&] { + clipboard()->setText(m_ui->view->currentMatch().first->username()); + reject(); + }); + connect(copyPasswordAction, &QAction::triggered, this, [&] { + clipboard()->setText(m_ui->view->currentMatch().first->password()); + reject(); + }); + connect(copyTotpAction, &QAction::triggered, this, [&] { + clipboard()->setText(m_ui->view->currentMatch().first->totp()); + reject(); + }); +} + +void AutoTypeSelectDialog::showEvent(QShowEvent* event) +{ + QDialog::showEvent(event); + #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - QRect screenGeometry = QApplication::screenAt(QCursor::pos())->availableGeometry(); + auto screen = QApplication::screenAt(QCursor::pos()); + if (!screen) { + // screenAt can return a nullptr, default to the primary screen + screen = QApplication::primaryScreen(); + } + QRect screenGeometry = screen->availableGeometry(); #else QRect screenGeometry = QApplication::desktop()->availableGeometry(QCursor::pos()); #endif + + // Resize to last used size QSize size = config()->get(Config::GUI_AutoTypeSelectDialogSize).toSize(); size.setWidth(qMin(size.width(), screenGeometry.width())); size.setHeight(qMin(size.height(), screenGeometry.height())); resize(size); // move dialog to the center of the screen - QPoint screenCenter = screenGeometry.center(); - move(screenCenter.x() - (size.width() / 2), screenCenter.y() - (size.height() / 2)); - - QVBoxLayout* layout = new QVBoxLayout(this); - - QLabel* descriptionLabel = new QLabel(tr("Select entry to Auto-Type:"), this); - layout->addWidget(descriptionLabel); - - // clang-format off - connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); - connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); - connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved())); - connect(m_view, SIGNAL(rejected()), SLOT(reject())); - connect(m_view, SIGNAL(matchTextCopied()), SLOT(reject())); - // clang-format on - - QSortFilterProxyModel* proxy = qobject_cast(m_view->model()); - if (proxy) { - proxy->setFilterKeyColumn(-1); - proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); - } - - layout->addWidget(m_view); - - connect(m_filterLineEdit, SIGNAL(textChanged(QString)), SLOT(filterList(QString))); - connect(m_filterLineEdit, SIGNAL(returnPressed()), SLOT(activateCurrentIndex())); - connect(m_filterLineEdit, SIGNAL(keyUpPressed()), SLOT(moveSelectionUp())); - connect(m_filterLineEdit, SIGNAL(keyDownPressed()), SLOT(moveSelectionDown())); - connect(m_filterLineEdit, SIGNAL(escapeReleased()), SLOT(reject())); - - m_filterLineEdit->setPlaceholderText(tr("Search…")); - layout->addWidget(m_filterLineEdit); - - QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this); - connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); - layout->addWidget(buttonBox); - - m_filterLineEdit->setFocus(); + move(screenGeometry.center().x() - (size.width() / 2), screenGeometry.center().y() - (size.height() / 2)); } -void AutoTypeSelectDialog::setMatchList(const QList& matchList) -{ - m_view->setMatchList(matchList); - - m_view->header()->resizeSections(QHeaderView::ResizeToContents); -} - -void AutoTypeSelectDialog::done(int r) +void AutoTypeSelectDialog::hideEvent(QHideEvent* event) { config()->set(Config::GUI_AutoTypeSelectDialogSize, size()); - - QDialog::done(r); -} - -void AutoTypeSelectDialog::reject() -{ - m_rejected = true; - - QDialog::reject(); -} - -void AutoTypeSelectDialog::emitMatchActivated(const QModelIndex& index) -{ - // make sure we don't emit the signal twice when both activated() and clicked() are triggered - if (m_matchActivatedEmitted) { - return; + if (!m_accepted) { + emit rejected(); } - m_matchActivatedEmitted = true; - - AutoTypeMatch match = m_view->matchFromIndex(index); - accept(); - emit matchActivated(match); -} - -void AutoTypeSelectDialog::matchRemoved() -{ - if (m_rejected) { - return; - } - - if (m_view->model()->rowCount() == 0 && m_filterLineEdit->text().isEmpty()) { - reject(); - } -} - -void AutoTypeSelectDialog::filterList(QString filterString) -{ - QSortFilterProxyModel* proxy = qobject_cast(m_view->model()); - if (proxy) { - proxy->setFilterWildcard(filterString); - if (!m_view->currentIndex().isValid()) { - m_view->setCurrentIndex(m_view->model()->index(0, 0)); - } - } -} - -void AutoTypeSelectDialog::moveSelectionUp() -{ - auto current = m_view->currentIndex(); - auto previous = current.sibling(current.row() - 1, 0); - - if (previous.isValid()) { - m_view->setCurrentIndex(previous); - } -} - -void AutoTypeSelectDialog::moveSelectionDown() -{ - auto current = m_view->currentIndex(); - auto next = current.sibling(current.row() + 1, 0); - - if (next.isValid()) { - m_view->setCurrentIndex(next); - } -} - -void AutoTypeSelectDialog::activateCurrentIndex() -{ - emitMatchActivated(m_view->currentIndex()); + QDialog::hideEvent(event); } diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h index a22218f1f..2adf67424 100644 --- a/src/autotype/AutoTypeSelectDialog.h +++ b/src/autotype/AutoTypeSelectDialog.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2021 Team KeePassXC * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -18,14 +19,17 @@ #ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H #define KEEPASSX_AUTOTYPESELECTDIALOG_H -#include +#include "autotype/AutoTypeMatch.h" #include -#include +#include -#include "autotype/AutoTypeFilterLineEdit.h" -#include "core/AutoTypeMatch.h" +class Database; +class QMenu; -class AutoTypeSelectView; +namespace Ui +{ + class AutoTypeSelectDialog; +} class AutoTypeSelectDialog : public QDialog { @@ -33,28 +37,37 @@ class AutoTypeSelectDialog : public QDialog public: explicit AutoTypeSelectDialog(QWidget* parent = nullptr); - void setMatchList(const QList& matchList); + ~AutoTypeSelectDialog() override; + + void setMatches(const QList& matchList, const QList>& dbs); signals: void matchActivated(AutoTypeMatch match); -public slots: - void done(int r) override; - void reject() override; +protected: + bool eventFilter(QObject* obj, QEvent* event) override; + void showEvent(QShowEvent* event) override; + void hideEvent(QHideEvent* event) override; private slots: - void emitMatchActivated(const QModelIndex& index); - void matchRemoved(); - void filterList(QString filterString); + void submitAutoTypeMatch(AutoTypeMatch match); + void performSearch(); void moveSelectionUp(); void moveSelectionDown(); - void activateCurrentIndex(); + void activateCurrentMatch(); + void updateActionMenu(const AutoTypeMatch& match); private: - AutoTypeSelectView* const m_view; - AutoTypeFilterLineEdit* const m_filterLineEdit; - bool m_matchActivatedEmitted; - bool m_rejected; + void buildActionMenu(); + + QScopedPointer m_ui; + + QList> m_dbs; + QList m_matches; + QTimer m_searchTimer; + QPointer m_actionMenu; + + bool m_accepted = false; }; #endif // KEEPASSX_AUTOTYPESELECTDIALOG_H diff --git a/src/autotype/AutoTypeSelectDialog.ui b/src/autotype/AutoTypeSelectDialog.ui new file mode 100644 index 000000000..2f77bd2b2 --- /dev/null +++ b/src/autotype/AutoTypeSelectDialog.ui @@ -0,0 +1,197 @@ + + + AutoTypeSelectDialog + + + + 0 + 0 + 418 + 295 + + + + Auto-Type - KeePassXC + + + + + + Double click a row to perform Auto-Type or find an entry using the search: + + + + + + + + 0 + 0 + + + + + 0 + 175 + + + + PointingHandCursor + + + false + + + false + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + true + + + false + + + + + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Filter Matches + + + true + + + + + + + &Search Database + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 400 + 0 + + + + Filter or Search… + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Type Sequence + + + QToolButton::MenuButtonPopup + + + + + + + Cancel + + + false + + + + + + + + + + AutoTypeMatchView + QTableView +

autotype/AutoTypeMatchView.h
+ + + + view + filterRadio + searchRadio + search + + + + diff --git a/src/autotype/AutoTypeSelectView.cpp b/src/autotype/AutoTypeSelectView.cpp deleted file mode 100644 index cfa113671..000000000 --- a/src/autotype/AutoTypeSelectView.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "AutoTypeSelectView.h" - -#include -#include - -AutoTypeSelectView::AutoTypeSelectView(QWidget* parent) - : AutoTypeMatchView(parent) -{ - setMouseTracking(true); - setAllColumnsShowFocus(true); - - connect(model(), SIGNAL(modelReset()), SLOT(selectFirstMatch())); -} - -void AutoTypeSelectView::mouseMoveEvent(QMouseEvent* event) -{ - QModelIndex index = indexAt(event->pos()); - - if (index.isValid()) { - setCurrentIndex(index); - setCursor(Qt::PointingHandCursor); - } else { - unsetCursor(); - } - - AutoTypeMatchView::mouseMoveEvent(event); -} - -void AutoTypeSelectView::selectFirstMatch() -{ - QModelIndex index = model()->index(0, 0); - - if (index.isValid()) { - setCurrentIndex(index); - } -} - -void AutoTypeSelectView::keyReleaseEvent(QKeyEvent* e) -{ - if (e->key() == Qt::Key_Escape) { - emit rejected(); - } else { - e->ignore(); - } -} \ No newline at end of file diff --git a/src/autotype/AutoTypeSelectView.h b/src/autotype/AutoTypeSelectView.h deleted file mode 100644 index e6a2ec652..000000000 --- a/src/autotype/AutoTypeSelectView.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_AUTOTYPESELECTVIEW_H -#define KEEPASSX_AUTOTYPESELECTVIEW_H - -#include "gui/entry/AutoTypeMatchView.h" - -class AutoTypeSelectView : public AutoTypeMatchView -{ - Q_OBJECT - -public: - explicit AutoTypeSelectView(QWidget* parent = nullptr); - -protected: - void mouseMoveEvent(QMouseEvent* event) override; - void keyReleaseEvent(QKeyEvent* e) override; - -private slots: - void selectFirstMatch(); - -signals: - void rejected(); -}; - -#endif // KEEPASSX_AUTOTYPESELECTVIEW_H diff --git a/src/autotype/WildcardMatcher.cpp b/src/autotype/WildcardMatcher.cpp deleted file mode 100644 index b69425ee1..000000000 --- a/src/autotype/WildcardMatcher.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "WildcardMatcher.h" - -#include -#include - -const QChar WildcardMatcher::Wildcard = '*'; -const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive; - -WildcardMatcher::WildcardMatcher(QString text) - : m_text(std::move(text)) -{ -} - -bool WildcardMatcher::match(const QString& pattern) -{ - m_pattern = pattern; - - if (patternContainsWildcard()) { - return matchWithWildcards(); - } else { - return patternEqualsText(); - } -} - -bool WildcardMatcher::patternContainsWildcard() -{ - return m_pattern.contains(Wildcard); -} - -bool WildcardMatcher::patternEqualsText() -{ - return m_text.compare(m_pattern, Sensitivity) == 0; -} - -bool WildcardMatcher::matchWithWildcards() -{ - QStringList parts = m_pattern.split(Wildcard, QString::KeepEmptyParts); - Q_ASSERT(parts.size() >= 2); - - if (startOrEndDoesNotMatch(parts)) { - return false; - } - - return partsMatch(parts); -} - -bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts) -{ - return !m_text.startsWith(parts.first(), Sensitivity) || !m_text.endsWith(parts.last(), Sensitivity); -} - -bool WildcardMatcher::partsMatch(const QStringList& parts) -{ - int index = 0; - for (const QString& part : parts) { - int matchIndex = getMatchIndex(part, index); - if (noMatchFound(matchIndex)) { - return false; - } - index = calculateNewIndex(matchIndex, part.length()); - } - - return true; -} - -int WildcardMatcher::getMatchIndex(const QString& part, int startIndex) -{ - return m_text.indexOf(part, startIndex, Sensitivity); -} - -bool WildcardMatcher::noMatchFound(int index) -{ - return index == -1; -} - -int WildcardMatcher::calculateNewIndex(int matchIndex, int partLength) -{ - return matchIndex + partLength; -} diff --git a/src/autotype/WildcardMatcher.h b/src/autotype/WildcardMatcher.h deleted file mode 100644 index d8ee1dc79..000000000 --- a/src/autotype/WildcardMatcher.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_WILDCARDMATCHER_H -#define KEEPASSX_WILDCARDMATCHER_H - -#include - -class WildcardMatcher -{ -public: - explicit WildcardMatcher(QString text); - bool match(const QString& pattern); - - static const QChar Wildcard; - -private: - bool patternEqualsText(); - bool patternContainsWildcard(); - bool matchWithWildcards(); - bool startOrEndDoesNotMatch(const QStringList& parts); - bool partsMatch(const QStringList& parts); - int getMatchIndex(const QString& part, int startIndex); - bool noMatchFound(int index); - int calculateNewIndex(int matchIndex, int partLength); - - static const Qt::CaseSensitivity Sensitivity; - const QString m_text; - QString m_pattern; -}; - -#endif // KEEPASSX_WILDCARDMATCHER_H diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index ae6d9f1f5..69367fbac 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -70,6 +70,10 @@ BrowserService::BrowserService() , m_keepassBrowserUUID(Tools::hexToUuid("de887cc3036343b8974b5911b8816224")) { connect(m_browserHost, &BrowserHost::clientMessageReceived, this, &BrowserService::processClientMessage); + connect(getMainWindow(), &MainWindow::databaseUnlocked, this, &BrowserService::databaseUnlocked); + connect(getMainWindow(), &MainWindow::databaseLocked, this, &BrowserService::databaseLocked); + connect(getMainWindow(), &MainWindow::activeDatabaseChanged, this, &BrowserService::activeDatabaseChanged); + setEnabled(browserSettings()->isEnabled()); } diff --git a/src/core/AutoTypeMatch.cpp b/src/core/AutoTypeMatch.cpp deleted file mode 100644 index 13b037bb6..000000000 --- a/src/core/AutoTypeMatch.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2015 David Wu - * Copyright (C) 2017 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "AutoTypeMatch.h" - -#include - -AutoTypeMatch::AutoTypeMatch() - : entry(nullptr) - , sequence() -{ -} - -AutoTypeMatch::AutoTypeMatch(Entry* entry, QString sequence) - : entry(entry) - , sequence(std::move(sequence)) -{ -} - -bool AutoTypeMatch::operator==(const AutoTypeMatch& other) const -{ - return entry == other.entry && sequence == other.sequence; -} - -bool AutoTypeMatch::operator!=(const AutoTypeMatch& other) const -{ - return entry != other.entry || sequence != other.sequence; -} diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index c749b03e4..61f48b780 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -20,6 +20,7 @@ #include "config-keepassx.h" #include "core/Clock.h" +#include "core/Config.h" #include "core/Database.h" #include "core/DatabaseIcons.h" #include "core/Group.h" @@ -280,6 +281,75 @@ QString Entry::effectiveAutoTypeSequence() const return sequence; } +/** + * Retrive the autotype sequences matches for a given windowTitle + * This returns a list with priority ordering. If you don't want duplicates call .toSet() on it. + */ +QList Entry::autoTypeSequences(const QString& windowTitle) const +{ + // If no window just return the effective sequence + if (windowTitle.isEmpty()) { + return {effectiveAutoTypeSequence()}; + } + + // Define helper functions to match window titles + auto windowMatches = [&](const QString& pattern) { + // Regex searching + if (pattern.startsWith("//") && pattern.endsWith("//") && pattern.size() >= 4) { + QRegExp regExp(pattern.mid(2, pattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2); + return (regExp.indexIn(windowTitle) != -1); + } + + // Wildcard searching + auto regex = Tools::convertToRegex(pattern, true, false, false); + return windowTitle.contains(regex); + }; + + auto windowMatchesTitle = [&](const QString& entryTitle) { + return !entryTitle.isEmpty() && windowTitle.contains(entryTitle, Qt::CaseInsensitive); + }; + + auto windowMatchesUrl = [&](const QString& entryUrl) { + if (!entryUrl.isEmpty() && windowTitle.contains(entryUrl, Qt::CaseInsensitive)) { + return true; + } + + QUrl url(entryUrl); + if (url.isValid() && !url.host().isEmpty()) { + return windowTitle.contains(url.host(), Qt::CaseInsensitive); + } + + return false; + }; + + QList sequenceList; + + // Add window association matches + const auto assocList = autoTypeAssociations()->getAll(); + for (const auto& assoc : assocList) { + auto window = resolveMultiplePlaceholders(assoc.window); + if (windowMatches(window)) { + if (!assoc.sequence.isEmpty()) { + sequenceList << assoc.sequence; + } else { + sequenceList << effectiveAutoTypeSequence(); + } + } + } + + // Try to match window title + if (config()->get(Config::AutoTypeEntryTitleMatch).toBool() && windowMatchesTitle(resolvePlaceholder(title()))) { + sequenceList << effectiveAutoTypeSequence(); + } + + // Try to match url in window title + if (config()->get(Config::AutoTypeEntryURLMatch).toBool() && windowMatchesUrl(resolvePlaceholder(url()))) { + sequenceList << effectiveAutoTypeSequence(); + } + + return sequenceList; +} + AutoTypeAssociations* Entry::autoTypeAssociations() { return m_autoTypeAssociations; diff --git a/src/core/Entry.h b/src/core/Entry.h index a86aded10..be666b9a0 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -95,6 +95,7 @@ public: QString defaultAutoTypeSequence() const; QString effectiveAutoTypeSequence() const; QString effectiveNewAutoTypeSequence() const; + QList autoTypeSequences(const QString& pattern = {}) const; AutoTypeAssociations* autoTypeAssociations(); const AutoTypeAssociations* autoTypeAssociations() const; QString title() const; diff --git a/src/fdosecrets/objects/Service.cpp b/src/fdosecrets/objects/Service.cpp index 38dc0aff6..603aaba1e 100644 --- a/src/fdosecrets/objects/Service.cpp +++ b/src/fdosecrets/objects/Service.cpp @@ -82,7 +82,7 @@ namespace FdoSecrets }); // make default alias track current activated database - connect(m_databases.data(), &DatabaseTabWidget::activateDatabaseChanged, this, &Service::ensureDefaultAlias); + connect(m_databases.data(), &DatabaseTabWidget::activeDatabaseChanged, this, &Service::ensureDefaultAlias); return true; } diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 2683cecec..6f79873af 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -57,8 +57,8 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) // clang-format off connect(this, SIGNAL(tabCloseRequested(int)), SLOT(closeDatabaseTab(int))); - connect(this, SIGNAL(currentChanged(int)), SLOT(emitActivateDatabaseChanged())); - connect(this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), + connect(this, SIGNAL(currentChanged(int)), SLOT(emitActiveDatabaseChanged())); + connect(this, SIGNAL(activeDatabaseChanged(DatabaseWidget*)), m_dbWidgetStateSync, SLOT(setActive(DatabaseWidget*))); connect(autoType(), SIGNAL(globalAutoTypeTriggered()), SLOT(performGlobalAutoType())); connect(autoType(), SIGNAL(autotypePerformed()), SLOT(relockPendingDatabase())); @@ -715,9 +715,9 @@ void DatabaseTabWidget::updateLastDatabases(const QString& filename) } } -void DatabaseTabWidget::emitActivateDatabaseChanged() +void DatabaseTabWidget::emitActiveDatabaseChanged() { - emit activateDatabaseChanged(currentDatabaseWidget()); + emit activeDatabaseChanged(currentDatabaseWidget()); } void DatabaseTabWidget::emitDatabaseLockChanged() diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index e59681ea7..fbb6411f8 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -89,7 +89,7 @@ signals: void databaseClosed(const QString& filePath); void databaseUnlocked(DatabaseWidget* dbWidget); void databaseLocked(DatabaseWidget* dbWidget); - void activateDatabaseChanged(DatabaseWidget* dbWidget); + void activeDatabaseChanged(DatabaseWidget* dbWidget); void tabNameChanged(); void tabVisibilityChanged(bool tabsVisible); void messageGlobal(const QString&, MessageWidget::MessageType type); @@ -98,7 +98,7 @@ signals: private slots: void toggleTabbar(); - void emitActivateDatabaseChanged(); + void emitActiveDatabaseChanged(); void emitDatabaseLockChanged(); private: diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index de19f37a9..5b40a9b8e 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -160,14 +160,13 @@ MainWindow::MainWindow() restoreGeometry(config()->get(Config::GUI_MainWindowGeometry).toByteArray()); restoreState(config()->get(Config::GUI_MainWindowState).toByteArray()); + + connect(m_ui->tabWidget, &DatabaseTabWidget::databaseLocked, this, &MainWindow::databaseLocked); + connect(m_ui->tabWidget, &DatabaseTabWidget::databaseUnlocked, this, &MainWindow::databaseUnlocked); + connect(m_ui->tabWidget, &DatabaseTabWidget::activeDatabaseChanged, this, &MainWindow::activeDatabaseChanged); + #ifdef WITH_XC_BROWSER m_ui->settingsWidget->addSettingsPage(new BrowserSettingsPage()); - connect(m_ui->tabWidget, &DatabaseTabWidget::databaseLocked, browserService(), &BrowserService::databaseLocked); - connect(m_ui->tabWidget, &DatabaseTabWidget::databaseUnlocked, browserService(), &BrowserService::databaseUnlocked); - connect(m_ui->tabWidget, - &DatabaseTabWidget::activateDatabaseChanged, - browserService(), - &BrowserService::activeDatabaseChanged); connect( browserService(), &BrowserService::requestUnlock, m_ui->tabWidget, &DatabaseTabWidget::performBrowserUnlock); #endif @@ -411,7 +410,7 @@ MainWindow::MainWindow() // Notify search when the active database changes or gets locked connect(m_ui->tabWidget, - SIGNAL(activateDatabaseChanged(DatabaseWidget*)), + SIGNAL(activeDatabaseChanged(DatabaseWidget*)), m_searchWidget, SLOT(databaseChanged(DatabaseWidget*))); connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), m_searchWidget, SLOT(databaseChanged())); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 63163c8d2..13e59b5ae 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -60,6 +60,11 @@ public: PasswordGeneratorScreen = 3 }; +signals: + void databaseUnlocked(DatabaseWidget* dbWidget); + void databaseLocked(DatabaseWidget* dbWidget); + void activeDatabaseChanged(DatabaseWidget* dbWidget); + public slots: void openDatabase(const QString& filePath, const QString& password = {}, const QString& keyfile = {}); void appExit(); @@ -136,8 +141,6 @@ private slots: void obtainContextFocusLock(); void releaseContextFocusLock(); void agentEnabled(bool enabled); - -private slots: void updateTrayIcon(); private: diff --git a/src/gui/SearchHelpWidget.ui b/src/gui/SearchHelpWidget.ui index ebc62e991..bd8731eb9 100644 --- a/src/gui/SearchHelpWidget.ui +++ b/src/gui/SearchHelpWidget.ui @@ -118,7 +118,7 @@ - + 10 diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index 7daea45d8..787b544ce 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -51,8 +51,8 @@ SearchWidget::SearchWidget(QWidget* parent) connect(m_clearSearchTimer, SIGNAL(timeout()), m_ui->searchEdit, SLOT(clear())); connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear())); - new QShortcut(QKeySequence::Find, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut); - new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut); + new QShortcut(QKeySequence::Find, this, SLOT(searchFocus())); + new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear())); m_ui->searchEdit->setPlaceholderText(tr("Search (%1)…", "Search placeholder text, %1 is the keyboard shortcut") .arg(QKeySequence(QKeySequence::Find).toString(QKeySequence::NativeText))); diff --git a/src/gui/entry/AutoTypeMatchView.cpp b/src/gui/entry/AutoTypeMatchView.cpp deleted file mode 100644 index 72ee32fde..000000000 --- a/src/gui/entry/AutoTypeMatchView.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2015 David Wu - * Copyright (C) 2017 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "AutoTypeMatchView.h" - -#include "core/Entry.h" -#include "gui/Clipboard.h" -#include "gui/SortFilterHideProxyModel.h" - -#include -#include -#include - -AutoTypeMatchView::AutoTypeMatchView(QWidget* parent) - : QTreeView(parent) - , m_model(new AutoTypeMatchModel(this)) - , m_sortModel(new SortFilterHideProxyModel(this)) -{ - m_sortModel->setSourceModel(m_model); - m_sortModel->setDynamicSortFilter(true); - m_sortModel->setSortLocaleAware(true); - m_sortModel->setSortCaseSensitivity(Qt::CaseInsensitive); - setModel(m_sortModel); - - setUniformRowHeights(true); - setRootIsDecorated(false); - setAlternatingRowColors(true); - setDragEnabled(false); - setSortingEnabled(true); - setSelectionMode(QAbstractItemView::SingleSelection); - header()->setDefaultSectionSize(150); - - setContextMenuPolicy(Qt::ActionsContextMenu); - auto* copyUserNameAction = new QAction(tr("Copy &username"), this); - auto* copyPasswordAction = new QAction(tr("Copy &password"), this); - addAction(copyUserNameAction); - addAction(copyPasswordAction); - - connect(copyUserNameAction, SIGNAL(triggered()), this, SLOT(userNameCopied())); - connect(copyPasswordAction, SIGNAL(triggered()), this, SLOT(passwordCopied())); - - connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); - // clang-format off - connect(selectionModel(), - SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - SIGNAL(matchSelectionChanged())); - // clang-format on -} - -void AutoTypeMatchView::userNameCopied() -{ - clipboard()->setText(currentMatch().entry->username()); - emit matchTextCopied(); -} - -void AutoTypeMatchView::passwordCopied() -{ - clipboard()->setText(currentMatch().entry->password()); - emit matchTextCopied(); -} - -void AutoTypeMatchView::keyPressEvent(QKeyEvent* event) -{ - if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) && currentIndex().isValid()) { - emitMatchActivated(currentIndex()); -#ifdef Q_OS_MACOS - // Pressing return does not emit the QTreeView::activated signal on mac os - emit activated(currentIndex()); -#endif - } - - QTreeView::keyPressEvent(event); -} - -void AutoTypeMatchView::setMatchList(const QList& matches) -{ - m_model->setMatchList(matches); - - bool sameSequences = true; - if (matches.count() > 1) { - QString sequenceTest = matches[0].sequence; - for (const auto& match : matches) { - if (match.sequence != sequenceTest) { - sameSequences = false; - break; - } - } - } - setColumnHidden(AutoTypeMatchModel::Sequence, sameSequences); - - for (int i = 0; i < m_model->columnCount(); ++i) { - resizeColumnToContents(i); - if (columnWidth(i) > 250) { - setColumnWidth(i, 250); - } - } - - setFirstMatchActive(); -} - -void AutoTypeMatchView::setFirstMatchActive() -{ - if (m_model->rowCount() > 0) { - QModelIndex index = m_sortModel->mapToSource(m_sortModel->index(0, 0)); - setCurrentMatch(m_model->matchFromIndex(index)); - } else { - emit matchSelectionChanged(); - } -} - -void AutoTypeMatchView::emitMatchActivated(const QModelIndex& index) -{ - AutoTypeMatch match = matchFromIndex(index); - - emit matchActivated(match); -} - -AutoTypeMatch AutoTypeMatchView::currentMatch() -{ - QModelIndexList list = selectionModel()->selectedRows(); - if (list.size() == 1) { - return m_model->matchFromIndex(m_sortModel->mapToSource(list.first())); - } - return AutoTypeMatch(); -} - -void AutoTypeMatchView::setCurrentMatch(const AutoTypeMatch& match) -{ - selectionModel()->setCurrentIndex(m_sortModel->mapFromSource(m_model->indexFromMatch(match)), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); -} - -AutoTypeMatch AutoTypeMatchView::matchFromIndex(const QModelIndex& index) -{ - if (index.isValid()) { - return m_model->matchFromIndex(m_sortModel->mapToSource(index)); - } - return AutoTypeMatch(); -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 28d8516cf..b532acba9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -149,9 +149,6 @@ add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp add_unit_test(NAME testopvaultreader SOURCES TestOpVaultReader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp - LIBS ${TEST_LIBRARIES}) - if(WITH_XC_NETWORKING) add_unit_test(NAME testupdatecheck SOURCES TestUpdateCheck.cpp LIBS ${TEST_LIBRARIES}) diff --git a/tests/TestWildcardMatcher.cpp b/tests/TestWildcardMatcher.cpp deleted file mode 100644 index b7b92fdd7..000000000 --- a/tests/TestWildcardMatcher.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "TestWildcardMatcher.h" -#include "TestGlobal.h" -#include "autotype/WildcardMatcher.h" - -QTEST_GUILESS_MAIN(TestWildcardMatcher) - -const QString TestWildcardMatcher::DefaultText = QString("some text"); -const QString TestWildcardMatcher::AlternativeText = QString("some other text"); - -void TestWildcardMatcher::testMatcher_data() -{ - QTest::addColumn("text"); - QTest::addColumn("pattern"); - QTest::addColumn("match"); - - QTest::newRow("MatchWithoutWildcard") << DefaultText << DefaultText << true; - QTest::newRow("NoMatchWithoutWildcard") << DefaultText << QString("no match text") << false; - QTest::newRow("MatchWithOneWildcardInTheMiddle") << AlternativeText << QString("some*text") << true; - QTest::newRow("NoMatchWithOneWildcardInTheMiddle") << AlternativeText << QString("differen*text") << false; - QTest::newRow("MatchWithOneWildcardAtBegin") << DefaultText << QString("*text") << true; - QTest::newRow("NoMatchWithOneWildcardAtBegin") << DefaultText << QString("*text something else") << false; - QTest::newRow("NatchWithOneWildcardAtEnd") << DefaultText << QString("some*") << true; - QTest::newRow("NoMatchWithOneWildcardAtEnd") << DefaultText << QString("some other*") << false; - QTest::newRow("MatchWithMultipleWildcards") << AlternativeText << QString("some*th*text") << true; - QTest::newRow("NoMatchWithMultipleWildcards") << AlternativeText << QString("some*abc*text") << false; - QTest::newRow("MatchJustWildcard") << DefaultText << QString("*") << true; - QTest::newRow("MatchFollowingWildcards") << DefaultText << QString("some t**t") << true; - QTest::newRow("CaseSensitivity") << DefaultText.toUpper() << QString("some t**t") << true; -} - -void TestWildcardMatcher::testMatcher() -{ - QFETCH(QString, text); - QFETCH(QString, pattern); - QFETCH(bool, match); - - initMatcher(text); - verifyMatchResult(pattern, match); - cleanupMatcher(); -} - -void TestWildcardMatcher::initMatcher(QString text) -{ - m_matcher = new WildcardMatcher(text); -} - -void TestWildcardMatcher::cleanupMatcher() -{ - delete m_matcher; -} - -void TestWildcardMatcher::verifyMatchResult(QString pattern, bool expected) -{ - if (expected) { - verifyMatch(pattern); - } else { - verifyNoMatch(pattern); - } -} - -void TestWildcardMatcher::verifyMatch(QString pattern) -{ - bool matchResult = m_matcher->match(pattern); - QVERIFY(matchResult); -} - -void TestWildcardMatcher::verifyNoMatch(QString pattern) -{ - bool matchResult = m_matcher->match(pattern); - QVERIFY(!matchResult); -} diff --git a/tests/TestWildcardMatcher.h b/tests/TestWildcardMatcher.h deleted file mode 100644 index e23770937..000000000 --- a/tests/TestWildcardMatcher.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_TESTWILDCARDMATCHER_H -#define KEEPASSX_TESTWILDCARDMATCHER_H - -#include - -class WildcardMatcher; - -class TestWildcardMatcher : public QObject -{ - Q_OBJECT - -private slots: - void testMatcher(); - void testMatcher_data(); - -private: - static const QString DefaultText; - static const QString AlternativeText; - - void initMatcher(QString text); - void cleanupMatcher(); - void verifyMatchResult(QString pattern, bool expected); - void verifyMatch(QString pattern); - void verifyNoMatch(QString pattern); - - WildcardMatcher* m_matcher; -}; - -#endif // KEEPASSX_TESTWILDCARDMATCHER_H From 027ff9f2bfac35ca74b0e91bd72625a2b790f050 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 13 Feb 2021 22:13:10 -0500 Subject: [PATCH 3/6] Overhaul Auto-Type Action Handling * Close #2603 - Add support for modifier syntax (+, ^, and %) * Fix #2633 - Allow reference syntax {REF:...} in Auto-Type sequences * Close #5334 - Tell the user which part of the Auto-Type sequence is invalid for easy correction * Fix #2401 - Select the right window on macOS prior to starting Auto-Type * Allow for nested placeholders --- src/autotype/AutoType.cpp | 532 +++++++++-------------- src/autotype/AutoType.h | 13 +- src/autotype/AutoTypeAction.cpp | 73 +--- src/autotype/AutoTypeAction.h | 59 +-- src/autotype/AutoTypeSelectDialog.cpp | 1 - src/autotype/mac/AutoTypeMac.cpp | 62 +-- src/autotype/mac/AutoTypeMac.h | 5 +- src/autotype/test/AutoTypeTest.cpp | 30 +- src/autotype/test/AutoTypeTest.h | 9 +- src/autotype/windows/AutoTypeWindows.cpp | 62 +-- src/autotype/windows/AutoTypeWindows.h | 5 +- src/autotype/xcb/AutoTypeXCB.cpp | 33 +- src/autotype/xcb/AutoTypeXCB.h | 5 +- src/core/Global.h | 6 +- src/core/MacPasteboard.h | 2 +- src/gui/MainWindow.cpp | 7 + src/gui/MainWindow.h | 1 + src/gui/entry/EditEntryWidget.cpp | 32 +- src/gui/osutils/nixutils/X11Funcs.cpp | 2 + tests/TestAutoType.cpp | 62 +-- 20 files changed, 435 insertions(+), 566 deletions(-) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 7a52491b3..3373342ef 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -38,11 +38,89 @@ #include "gui/MessageBox.h" #include "gui/osutils/OSUtils.h" +namespace +{ + // Basic Auto-Type placeholder associations + const QHash g_placeholderToKey = {{"tab", Qt::Key_Tab}, + {"enter", Qt::Key_Enter}, + {"space", Qt::Key_Space}, + {"up", Qt::Key_Up}, + {"down", Qt::Key_Down}, + {"left", Qt::Key_Left}, + {"right", Qt::Key_Right}, + {"insert", Qt::Key_Insert}, + {"ins", Qt::Key_Insert}, + {"delete", Qt::Key_Delete}, + {"del", Qt::Key_Delete}, + {"home", Qt::Key_Home}, + {"end", Qt::Key_End}, + {"pgup", Qt::Key_PageUp}, + {"pgdown", Qt::Key_PageDown}, + {"backspace", Qt::Key_Backspace}, + {"bs", Qt::Key_Backspace}, + {"bksp", Qt::Key_Backspace}, + {"break", Qt::Key_Pause}, + {"capslock", Qt::Key_CapsLock}, + {"esc", Qt::Key_Escape}, + {"help", Qt::Key_Help}, + {"numlock", Qt::Key_NumLock}, + {"ptrsc", Qt::Key_Print}, + {"scrolllock", Qt::Key_ScrollLock}, + {"win", Qt::Key_Meta}, + {"lwin", Qt::Key_Meta}, + {"rwin", Qt::Key_Meta}, + {"apps", Qt::Key_Menu}, + {"help", Qt::Key_Help}, + {"add", Qt::Key_Plus}, + {"subtract", Qt::Key_Minus}, + {"multiply", Qt::Key_Asterisk}, + {"divide", Qt::Key_Slash}, + {"leftbrace", Qt::Key_BraceLeft}, + {"{", Qt::Key_BraceLeft}, + {"rightbrace", Qt::Key_BraceRight}, + {"}", Qt::Key_BraceRight}, + {"leftparen", Qt::Key_ParenLeft}, + {"(", Qt::Key_ParenLeft}, + {"rightparen", Qt::Key_ParenRight}, + {")", Qt::Key_ParenRight}, + {"[", Qt::Key_BracketLeft}, + {"]", Qt::Key_BracketRight}, + {"+", Qt::Key_Plus}, + {"%", Qt::Key_Percent}, + {"^", Qt::Key_AsciiCircum}, + {"~", Qt::Key_AsciiTilde}, + {"numpad0", Qt::Key_0}, + {"numpad1", Qt::Key_1}, + {"numpad2", Qt::Key_2}, + {"numpad3", Qt::Key_3}, + {"numpad4", Qt::Key_4}, + {"numpad5", Qt::Key_5}, + {"numpad6", Qt::Key_6}, + {"numpad7", Qt::Key_7}, + {"numpad8", Qt::Key_8}, + {"numpad9", Qt::Key_9}, + {"f1", Qt::Key_F1}, + {"f2", Qt::Key_F2}, + {"f3", Qt::Key_F3}, + {"f4", Qt::Key_F4}, + {"f5", Qt::Key_F5}, + {"f6", Qt::Key_F6}, + {"f7", Qt::Key_F7}, + {"f8", Qt::Key_F8}, + {"f9", Qt::Key_F9}, + {"f10", Qt::Key_F10}, + {"f11", Qt::Key_F11}, + {"f12", Qt::Key_F12}, + {"f13", Qt::Key_F13}, + {"f14", Qt::Key_F14}, + {"f15", Qt::Key_F15}, + {"f16", Qt::Key_F16}}; +} // namespace + AutoType* AutoType::m_instance = nullptr; AutoType::AutoType(QObject* parent, bool test) : QObject(parent) - , m_autoTypeDelay(0) , m_pluginLoader(new QPluginLoader(this)) , m_plugin(nullptr) , m_executor(nullptr) @@ -174,22 +252,6 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c return; } - // no edit to the sequence beyond this point - if (!verifyAutoTypeSyntax(sequence)) { - emit autotypeRejected(); - m_inAutoType.unlock(); - return; - } - - QList actions; - ListDeleter actionsDeleter(&actions); - - if (!parseActions(sequence, entry, actions)) { - emit autotypeRejected(); - m_inAutoType.unlock(); - return; - } - if (hideWindow) { #if defined(Q_OS_MACOS) // Check for accessibility permission @@ -209,16 +271,21 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c #endif } - Tools::wait(qMax(100, config()->get(Config::AutoTypeStartDelay).toInt())); + auto actions = parseActions(sequence, entry); + + // Restore window state in case app stole focus + restoreWindowState(); + QApplication::processEvents(); + m_plugin->raiseWindow(m_windowForGlobal); // Used only for selected entry auto-type if (!window) { window = m_plugin->activeWindow(); } - QCoreApplication::processEvents(QEventLoop::AllEvents, 10); + Tools::wait(qMax(100, config()->get(Config::AutoTypeStartDelay).toInt())); - for (AutoTypeAction* action : asConst(actions)) { + for (auto action : asConst(actions)) { if (m_plugin->activeWindow() != window) { qWarning("Active window changed, interrupting auto-type."); emit autotypeRejected(); @@ -226,7 +293,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c return; } - action->accept(m_executor); + action->exec(m_executor); QCoreApplication::processEvents(QEventLoop::AllEvents, 10); } @@ -235,7 +302,6 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c // emit signal only if autotype performed correctly emit autotypePerformed(); - m_inAutoType.unlock(); } @@ -350,20 +416,16 @@ void AutoType::performGlobalAutoType(const QList>& dbLi } // Show the selection dialog if we always ask, have multiple matches, or no matches - if (config()->get(Config::Security_AutoTypeAsk).toBool() || matchList.size() > 1 || matchList.isEmpty()) { + if (getMainWindow() + && (config()->get(Config::Security_AutoTypeAsk).toBool() || matchList.size() > 1 || matchList.isEmpty())) { // Close any open modal windows that would interfere with the process - if (qApp->modalWindow()) { - qApp->modalWindow()->close(); - } + getMainWindow()->closeModalWindow(); auto* selectDialog = new AutoTypeSelectDialog(); selectDialog->setMatches(matchList, dbList); connect(getMainWindow(), &MainWindow::databaseLocked, selectDialog, &AutoTypeSelectDialog::reject); connect(selectDialog, &AutoTypeSelectDialog::matchActivated, this, [this](AutoTypeMatch match) { - restoreWindowState(); - QApplication::processEvents(); - m_plugin->raiseWindow(m_windowForGlobal); executeAutoTypeActions(match.first, nullptr, match.second, m_windowForGlobal); resetAutoTypeState(); }); @@ -375,7 +437,7 @@ void AutoType::performGlobalAutoType(const QList>& dbLi #ifdef Q_OS_MACOS m_plugin->raiseOwnWindow(); - Tools::wait(200); + Tools::wait(50); #endif selectDialog->show(); selectDialog->raise(); @@ -386,7 +448,6 @@ void AutoType::performGlobalAutoType(const QList>& dbLi resetAutoTypeState(); } else { // We should never get here - Q_ASSERT(false); resetAutoTypeState(); emit autotypeRejected(); } @@ -414,316 +475,135 @@ void AutoType::resetAutoTypeState() } /** - * Parse an autotype sequence and resolve its Template/command inside as AutoTypeActions + * Parse an autotype sequence into a list of AutoTypeActions. + * If error is provided then syntax checking will be performed. */ -bool AutoType::parseActions(const QString& actionSequence, const Entry* entry, QList& actions) +QList> +AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString* error) { - QString tmpl; - bool inTmpl = false; - m_autoTypeDelay = qMax(config()->get(Config::AutoTypeDelay).toInt(), 0); + const int maxTypeDelay = 100; + const int maxWaitDelay = 10000; + const int maxRepetition = 100; - QString sequence = actionSequence; + QList> actions; + actions << QSharedPointer::create(qMax(0, config()->get(Config::AutoTypeDelay).toInt()), true); + + // Replace escaped braces with a template for easier regex + QString sequence = entrySequence; sequence.replace("{{}", "{LEFTBRACE}"); sequence.replace("{}}", "{RIGHTBRACE}"); - for (const QChar& ch : sequence) { - if (inTmpl) { - if (ch == '{') { - qWarning("Syntax error in Auto-Type sequence."); - return false; - } else if (ch == '}') { - QList autoType = createActionFromTemplate(tmpl, entry); - if (!autoType.isEmpty()) { - actions.append(autoType); + // Quick test for bracket syntax + if ((sequence.count("{") + sequence.count("}")) % 2 != 0 && error) { + *error = tr("Bracket imbalance detected, found extra { or }"); + return {}; + } + + // Group 1 = modifier key (opt) + // Group 2 = full placeholder + // Group 3 = inner placeholder (allows nested placeholders) + // Group 4 = repeat (opt) + // Group 5 = character + QRegularExpression regex("([+%^]*)({((?>[^{}]+?|(?2))+?)(?:\\s+(\\d+))?})|(.)"); + auto results = regex.globalMatch(sequence); + while (results.hasNext()) { + auto match = results.next(); + + // Parse modifier keys + Qt::KeyboardModifiers modifiers; + if (match.captured(1).contains('+')) { + modifiers |= Qt::ShiftModifier; + } + if (match.captured(1).contains('^')) { + modifiers |= Qt::ControlModifier; + } + if (match.captured(1).contains('%')) { + modifiers |= Qt::AltModifier; + } + + const auto fullPlaceholder = match.captured(2); + auto placeholder = match.captured(3).toLower(); + auto repeat = 1; + if (!match.captured(4).isEmpty()) { + repeat = match.captured(4).toInt(); + } + auto character = match.captured(5); + + if (!placeholder.isEmpty()) { + if (g_placeholderToKey.contains(placeholder)) { + // Basic key placeholder, allow repeat + if (repeat > maxRepetition && error) { + *error = tr("Too many repetitions detected, max is %1: %2").arg(maxRepetition).arg(fullPlaceholder); + return {}; } - inTmpl = false; - tmpl.clear(); + auto action = QSharedPointer::create(g_placeholderToKey[placeholder], modifiers); + for (int i = 1; i <= repeat && i <= maxRepetition; ++i) { + actions << action; + } + } else if (placeholder.startsWith("delay=")) { + // Change keypress delay + int delay = placeholder.replace("delay=", "").toInt(); + if (delay > maxTypeDelay && error) { + *error = tr("Very slow key press detected, max is %1: %2").arg(maxTypeDelay).arg(fullPlaceholder); + return {}; + } + actions << QSharedPointer::create(qBound(0, delay, maxTypeDelay), true); + } else if (placeholder == "delay") { + // Mid typing delay (wait) + if (repeat > maxWaitDelay && error) { + *error = tr("Very long delay detected, max is %1: %2").arg(maxWaitDelay).arg(fullPlaceholder); + return {}; + } + actions << QSharedPointer::create(qBound(0, repeat, maxWaitDelay)); + } else if (placeholder == "clearfield") { + // Platform-specific field clearing + actions << QSharedPointer::create(); + } else if (placeholder == "totp") { + // Entry totp (requires special handling) + QString totp = entry->totp(); + for (const auto& ch : totp) { + actions << QSharedPointer::create(ch); + } + } else if (placeholder == "beep" || placeholder.startsWith("vkey") + || placeholder.startsWith("appactivate")) { + // Ignore these commands } else { - tmpl += ch; + // Attempt to resolve an entry attribute + auto resolved = entry->resolvePlaceholder(fullPlaceholder); + if (resolved != fullPlaceholder) { + // Attribute resolved, add characters to action list + for (const QChar& ch : resolved) { + if (ch == '\n') { + actions << QSharedPointer::create(g_placeholderToKey["enter"]); + } else if (ch == '\t') { + actions << QSharedPointer::create(g_placeholderToKey["tab"]); + } else { + actions << QSharedPointer::create(ch); + } + } + } else if (error) { + // Invalid placeholder, issue error and stop processing + *error = tr("Invalid placeholder: %1").arg(fullPlaceholder); + return {}; + } } - } else if (ch == '{') { - inTmpl = true; - } else if (ch == '}') { - qWarning("Syntax error in Auto-Type sequence."); - return false; - } else { - actions.append(new AutoTypeChar(ch)); + } else if (!character.isEmpty()) { + // Type a single character with modifier + actions << QSharedPointer::create(character[0], modifiers); } } - if (m_autoTypeDelay > 0) { - QList::iterator i; - i = actions.begin(); - while (i != actions.end()) { - ++i; - if (i != actions.end()) { - i = actions.insert(i, new AutoTypeDelay(m_autoTypeDelay)); - ++i; - } - } - } - return true; + + return actions; } /** - * Convert an autotype Template/command to its AutoTypeAction that will be executed by the plugin executor + * Verify if the syntax of an autotype sequence is correct and doesn't have invalid parameters */ -QList AutoType::createActionFromTemplate(const QString& tmpl, const Entry* entry) +bool AutoType::verifyAutoTypeSyntax(const QString& sequence, const Entry* entry, QString& error) { - QString tmplName = tmpl; - int num = -1; - QList list; - - QRegExp delayRegEx("delay=(\\d+)", Qt::CaseInsensitive, QRegExp::RegExp2); - if (delayRegEx.exactMatch(tmplName)) { - num = delayRegEx.cap(1).toInt(); - m_autoTypeDelay = std::max(0, std::min(num, 10000)); - return list; + error.clear(); + if (!sequence.isEmpty()) { + parseActions(sequence, entry, &error); } - - QRegExp repeatRegEx("(.+) (\\d+)", Qt::CaseInsensitive, QRegExp::RegExp2); - if (repeatRegEx.exactMatch(tmplName)) { - tmplName = repeatRegEx.cap(1); - num = repeatRegEx.cap(2).toInt(); - - if (num == 0) { - return list; - } - } - - if (tmplName.compare("tab", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Tab)); - } else if (tmplName.compare("enter", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Enter)); - } else if (tmplName.compare("space", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Space)); - } else if (tmplName.compare("up", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Up)); - } else if (tmplName.compare("down", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Down)); - } else if (tmplName.compare("left", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Left)); - } else if (tmplName.compare("right", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Right)); - } else if (tmplName.compare("insert", Qt::CaseInsensitive) == 0 - || tmplName.compare("ins", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Insert)); - } else if (tmplName.compare("delete", Qt::CaseInsensitive) == 0 - || tmplName.compare("del", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Delete)); - } else if (tmplName.compare("home", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Home)); - } else if (tmplName.compare("end", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_End)); - } else if (tmplName.compare("pgup", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_PageUp)); - } else if (tmplName.compare("pgdown", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_PageDown)); - } else if (tmplName.compare("backspace", Qt::CaseInsensitive) == 0 - || tmplName.compare("bs", Qt::CaseInsensitive) == 0 - || tmplName.compare("bksp", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Backspace)); - } else if (tmplName.compare("break", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Pause)); - } else if (tmplName.compare("capslock", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_CapsLock)); - } else if (tmplName.compare("esc", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Escape)); - } else if (tmplName.compare("help", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Help)); - } else if (tmplName.compare("numlock", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_NumLock)); - } else if (tmplName.compare("ptrsc", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_Print)); - } else if (tmplName.compare("scrolllock", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeKey(Qt::Key_ScrollLock)); - } - // Qt doesn't know about keypad keys so use the normal ones instead - else if (tmplName.compare("add", Qt::CaseInsensitive) == 0 || tmplName.compare("+", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('+')); - } else if (tmplName.compare("subtract", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('-')); - } else if (tmplName.compare("multiply", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('*')); - } else if (tmplName.compare("divide", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('/')); - } else if (tmplName.compare("^", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('^')); - } else if (tmplName.compare("%", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('%')); - } else if (tmplName.compare("~", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('~')); - } else if (tmplName.compare("(", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('(')); - } else if (tmplName.compare(")", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar(')')); - } else if (tmplName.compare("leftbrace", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('{')); - } else if (tmplName.compare("rightbrace", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeChar('}')); - } else { - QRegExp fnRegexp("f(\\d+)", Qt::CaseInsensitive, QRegExp::RegExp2); - if (fnRegexp.exactMatch(tmplName)) { - int fnNo = fnRegexp.cap(1).toInt(); - if (fnNo >= 1 && fnNo <= 16) { - list.append(new AutoTypeKey(static_cast(Qt::Key_F1 - 1 + fnNo))); - } - } - } - - if (!list.isEmpty()) { - for (int i = 1; i < num; i++) { - list.append(list.at(0)->clone()); - } - return list; - } - - if (tmplName.compare("delay", Qt::CaseInsensitive) == 0 && num > 0) { - list.append(new AutoTypeDelay(num)); - } else if (tmplName.compare("clearfield", Qt::CaseInsensitive) == 0) { - list.append(new AutoTypeClearField()); - } else if (tmplName.compare("totp", Qt::CaseInsensitive) == 0) { - QString totp = entry->totp(); - if (!totp.isEmpty()) { - for (const QChar& ch : totp) { - list.append(new AutoTypeChar(ch)); - } - } - } - - if (!list.isEmpty()) { - return list; - } - - const QString placeholder = QString("{%1}").arg(tmplName); - const QString resolved = entry->resolvePlaceholder(placeholder); - if (placeholder != resolved) { - for (const QChar& ch : resolved) { - if (ch == '\n') { - list.append(new AutoTypeKey(Qt::Key_Enter)); - } else if (ch == '\t') { - list.append(new AutoTypeKey(Qt::Key_Tab)); - } else { - list.append(new AutoTypeChar(ch)); - } - } - } - - return list; -} - -/** - * Checks if the overall syntax of an autotype sequence is fine - */ -bool AutoType::checkSyntax(const QString& string) -{ - QString allowRepetition = "(?:\\s\\d+)?"; - // the ":" allows custom commands with syntax S:Field - // exclude BEEP otherwise will be checked as valid - QString normalCommands = "(?!BEEP\\s)[A-Z:_]*" + allowRepetition; - QString specialLiterals = "[\\^\\%\\(\\)~\\{\\}\\[\\]\\+]" + allowRepetition; - QString functionKeys = "(?:F[1-9]" + allowRepetition + "|F1[0-2])" + allowRepetition; - QString numpad = "NUMPAD\\d" + allowRepetition; - QString delay = "DELAY=\\d+"; - QString beep = "BEEP\\s\\d+\\s\\d+"; - QString vkey = "VKEY(?:-[EN]X)?\\s\\w+"; - QString customAttributes = "S:(?:[^\\{\\}])+"; - - // these chars aren't in parentheses - QString shortcutKeys = "[\\^\\%~\\+@]"; - // a normal string not in parentheses - QString fixedStrings = "[^\\^\\%~\\+@\\{\\}]*"; - // clang-format off - QRegularExpression autoTypeSyntax( - "^(?:" + shortcutKeys + "|" + fixedStrings + "|\\{(?:" + normalCommands + "|" + specialLiterals + "|" - + functionKeys - + "|" - + numpad - + "|" - + delay - + "|" - + beep - + "|" - + vkey - + ")\\}|\\{" - + customAttributes - + "\\})*$", - QRegularExpression::CaseInsensitiveOption); - // clang-format on - QRegularExpressionMatch match = autoTypeSyntax.match(string); - return match.hasMatch(); -} - -/** - * Checks an autotype sequence for high delay - */ -bool AutoType::checkHighDelay(const QString& string) -{ - // 5 digit numbers(10 seconds) are too much - QRegularExpression highDelay("\\{DELAY\\s\\d{5,}\\}", QRegularExpression::CaseInsensitiveOption); - QRegularExpressionMatch match = highDelay.match(string); - return match.hasMatch(); -} - -/** - * Checks an autotype sequence for slow keypress - */ -bool AutoType::checkSlowKeypress(const QString& string) -{ - // 3 digit numbers(100 milliseconds) are too much - QRegularExpression slowKeypress("\\{DELAY=\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption); - QRegularExpressionMatch match = slowKeypress.match(string); - return match.hasMatch(); -} - -/** - * Checks an autotype sequence for high repetition command - */ -bool AutoType::checkHighRepetition(const QString& string) -{ - // 3 digit numbers are too much - QRegularExpression highRepetition("\\{(?!DELAY\\s)\\w+\\s\\d{3,}\\}", QRegularExpression::CaseInsensitiveOption); - QRegularExpressionMatch match = highRepetition.match(string); - return match.hasMatch(); -} - -/** - * Verify if the syntax of an autotype sequence is correct and doesn't have silly parameters - */ -bool AutoType::verifyAutoTypeSyntax(const QString& sequence) -{ - if (!AutoType::checkSyntax(sequence)) { - QMessageBox::critical(nullptr, tr("Auto-Type"), tr("The Syntax of your Auto-Type statement is incorrect!")); - return false; - } else if (AutoType::checkHighDelay(sequence)) { - QMessageBox::StandardButton reply; - reply = QMessageBox::question( - nullptr, - tr("Auto-Type"), - tr("This Auto-Type command contains a very long delay. Do you really want to proceed?")); - - if (reply == QMessageBox::No) { - return false; - } - } else if (AutoType::checkSlowKeypress(sequence)) { - QMessageBox::StandardButton reply; - reply = QMessageBox::question( - nullptr, - tr("Auto-Type"), - tr("This Auto-Type command contains very slow key presses. Do you really want to proceed?")); - - if (reply == QMessageBox::No) { - return false; - } - } else if (AutoType::checkHighRepetition(sequence)) { - QMessageBox::StandardButton reply; - reply = QMessageBox::question(nullptr, - tr("Auto-Type"), - tr("This Auto-Type command contains arguments which are " - "repeated very often. Do you really want to proceed?")); - - if (reply == QMessageBox::No) { - return false; - } - } - return true; + return error.isEmpty(); } diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index 0af78c4c5..c11845d41 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -41,14 +41,11 @@ public: QStringList windowTitles(); bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers, QString* error = nullptr); void unregisterGlobalShortcut(); - static bool checkSyntax(const QString& string); - static bool checkHighRepetition(const QString& string); - static bool checkSlowKeypress(const QString& string); - static bool checkHighDelay(const QString& string); - static bool verifyAutoTypeSyntax(const QString& sequence); void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr); void performAutoTypeWithSequence(const Entry* entry, const QString& sequence, QWidget* hideWindow = nullptr); + static bool verifyAutoTypeSyntax(const QString& sequence, const Entry* entry, QString& error); + inline bool isAvailable() { return m_plugin; @@ -85,14 +82,14 @@ private: QWidget* hideWindow = nullptr, const QString& customSequence = QString(), WId window = 0); - bool parseActions(const QString& sequence, const Entry* entry, QList& actions); - QList createActionFromTemplate(const QString& tmpl, const Entry* entry); void restoreWindowState(); void resetAutoTypeState(); + static QList> + parseActions(const QString& entrySequence, const Entry* entry, QString* error = nullptr); + QMutex m_inAutoType; QMutex m_inGlobalAutoTypeDialog; - int m_autoTypeDelay; QPluginLoader* m_pluginLoader; AutoTypePlatformInterface* m_plugin; AutoTypeExecutor* m_executor; diff --git a/src/autotype/AutoTypeAction.cpp b/src/autotype/AutoTypeAction.cpp index f9d928f0d..469243371 100644 --- a/src/autotype/AutoTypeAction.cpp +++ b/src/autotype/AutoTypeAction.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2021 Team KeePassXC * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -19,77 +20,41 @@ #include "core/Tools.h" -AutoTypeChar::AutoTypeChar(const QChar& character) - : character(character) -{ -} - -AutoTypeAction* AutoTypeChar::clone() -{ - return new AutoTypeChar(character); -} - -void AutoTypeChar::accept(AutoTypeExecutor* executor) -{ - executor->execChar(this); -} - -AutoTypeKey::AutoTypeKey(Qt::Key key) +AutoTypeKey::AutoTypeKey(Qt::Key key, Qt::KeyboardModifiers modifiers) : key(key) + , modifiers(modifiers) { } -AutoTypeAction* AutoTypeKey::clone() +AutoTypeKey::AutoTypeKey(const QChar& character, Qt::KeyboardModifiers modifiers) + : character(character) + , modifiers(modifiers) { - return new AutoTypeKey(key); } -void AutoTypeKey::accept(AutoTypeExecutor* executor) +void AutoTypeKey::exec(AutoTypeExecutor* executor) const { - executor->execKey(this); + executor->execType(this); } -AutoTypeDelay::AutoTypeDelay(int delayMs) +AutoTypeDelay::AutoTypeDelay(int delayMs, bool setExecDelay) : delayMs(delayMs) + , setExecDelay(setExecDelay) { } -AutoTypeAction* AutoTypeDelay::clone() +void AutoTypeDelay::exec(AutoTypeExecutor* executor) const { - return new AutoTypeDelay(delayMs); + if (setExecDelay) { + // Change the delay between actions + executor->execDelayMs = delayMs; + } else { + // Pause execution + Tools::wait(delayMs); + } } -void AutoTypeDelay::accept(AutoTypeExecutor* executor) -{ - executor->execDelay(this); -} - -AutoTypeClearField::AutoTypeClearField() -{ -} - -AutoTypeAction* AutoTypeClearField::clone() -{ - return new AutoTypeClearField(); -} - -void AutoTypeClearField::accept(AutoTypeExecutor* executor) +void AutoTypeClearField::exec(AutoTypeExecutor* executor) const { executor->execClearField(this); } - -void AutoTypeExecutor::execDelay(AutoTypeDelay* action) -{ - Tools::wait(action->delayMs); -} - -void AutoTypeExecutor::execClearField(AutoTypeClearField* action) -{ - Q_UNUSED(action); -} - -AutoTypeAction::~AutoTypeAction() -{ - // This makes sure that AutoTypeAction's vtable is placed - // in this translation unit. -} diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h index e598b1dcc..fdb068736 100644 --- a/src/autotype/AutoTypeAction.h +++ b/src/autotype/AutoTypeAction.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2021 Team KeePassXC * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -19,69 +20,55 @@ #define KEEPASSX_AUTOTYPEACTION_H #include -#include -#include #include "core/Global.h" class AutoTypeExecutor; -class KEEPASSX_EXPORT AutoTypeAction +class KEEPASSXC_EXPORT AutoTypeAction { public: - virtual AutoTypeAction* clone() = 0; - virtual void accept(AutoTypeExecutor* executor) = 0; - virtual ~AutoTypeAction(); + AutoTypeAction() = default; + virtual void exec(AutoTypeExecutor* executor) const = 0; + virtual ~AutoTypeAction() = default; }; -class KEEPASSX_EXPORT AutoTypeChar : public AutoTypeAction +class KEEPASSXC_EXPORT AutoTypeKey : public AutoTypeAction { public: - explicit AutoTypeChar(const QChar& character); - AutoTypeAction* clone() override; - void accept(AutoTypeExecutor* executor) override; + explicit AutoTypeKey(const QChar& character, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + explicit AutoTypeKey(Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + void exec(AutoTypeExecutor* executor) const override; const QChar character; + const Qt::Key key = Qt::Key_unknown; + const Qt::KeyboardModifiers modifiers; }; -class KEEPASSX_EXPORT AutoTypeKey : public AutoTypeAction +class KEEPASSXC_EXPORT AutoTypeDelay : public AutoTypeAction { public: - explicit AutoTypeKey(Qt::Key key); - AutoTypeAction* clone() override; - void accept(AutoTypeExecutor* executor) override; - - const Qt::Key key; -}; - -class KEEPASSX_EXPORT AutoTypeDelay : public AutoTypeAction -{ -public: - explicit AutoTypeDelay(int delayMs); - AutoTypeAction* clone() override; - void accept(AutoTypeExecutor* executor) override; + explicit AutoTypeDelay(int delayMs, bool setExecDelay = false); + void exec(AutoTypeExecutor* executor) const override; const int delayMs; + const bool setExecDelay; }; -class KEEPASSX_EXPORT AutoTypeClearField : public AutoTypeAction +class KEEPASSXC_EXPORT AutoTypeClearField : public AutoTypeAction { public: - AutoTypeClearField(); - AutoTypeAction* clone() override; - void accept(AutoTypeExecutor* executor) override; + void exec(AutoTypeExecutor* executor) const override; }; -class KEEPASSX_EXPORT AutoTypeExecutor +class KEEPASSXC_EXPORT AutoTypeExecutor { public: - virtual ~AutoTypeExecutor() - { - } - virtual void execChar(AutoTypeChar* action) = 0; - virtual void execKey(AutoTypeKey* action) = 0; - virtual void execDelay(AutoTypeDelay* action); - virtual void execClearField(AutoTypeClearField* action); + virtual ~AutoTypeExecutor() = default; + virtual void execType(const AutoTypeKey* action) = 0; + virtual void execClearField(const AutoTypeClearField* action) = 0; + + int execDelayMs = 25; }; #endif // KEEPASSX_AUTOTYPEACTION_H diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 836ba3070..8b80f491c 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -57,7 +57,6 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) } }); - m_ui->search->setFocus(); m_ui->search->installEventFilter(this); diff --git a/src/autotype/mac/AutoTypeMac.cpp b/src/autotype/mac/AutoTypeMac.cpp index 6f9cb997c..1ae8b38d5 100644 --- a/src/autotype/mac/AutoTypeMac.cpp +++ b/src/autotype/mac/AutoTypeMac.cpp @@ -17,6 +17,7 @@ */ #include "AutoTypeMac.h" +#include "core/Tools.h" #include "gui/osutils/macutils/MacUtils.h" #include "gui/MessageBox.h" @@ -214,36 +215,43 @@ AutoTypeExecutorMac::AutoTypeExecutorMac(AutoTypePlatformMac* platform) { } -void AutoTypeExecutorMac::execChar(AutoTypeChar* action) +void AutoTypeExecutorMac::execType(const AutoTypeKey* action) { - m_platform->sendChar(action->character, true); - m_platform->sendChar(action->character, false); + if (action->modifiers & Qt::ShiftModifier) { + m_platform->sendKey(Qt::Key_Shift, true); + } + if (action->modifiers & Qt::ControlModifier) { + m_platform->sendKey(Qt::Key_Control, true); + } + if (action->modifiers & Qt::AltModifier) { + m_platform->sendKey(Qt::Key_Alt, true); + } + + if (action->key != Qt::Key_unknown) { + m_platform->sendKey(action->key, true); + m_platform->sendKey(action->key, false); + } else { + m_platform->sendChar(action->character, true); + m_platform->sendChar(action->character, false); + } + + if (action->modifiers & Qt::ShiftModifier) { + m_platform->sendKey(Qt::Key_Shift, false); + } + if (action->modifiers & Qt::ControlModifier) { + m_platform->sendKey(Qt::Key_Control, false); + } + if (action->modifiers & Qt::AltModifier) { + m_platform->sendKey(Qt::Key_Alt, false); + } + + Tools::sleep(execDelayMs); } -void AutoTypeExecutorMac::execKey(AutoTypeKey* action) -{ - m_platform->sendKey(action->key, true); - m_platform->sendKey(action->key, false); -} - -void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action = nullptr) +void AutoTypeExecutorMac::execClearField(const AutoTypeClearField* action) { Q_UNUSED(action); - - m_platform->sendKey(Qt::Key_Control, true, Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Up, true, Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Up, false, Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Control, false); - usleep(25 * 1000); - m_platform->sendKey(Qt::Key_Shift, true, Qt::ShiftModifier); - m_platform->sendKey(Qt::Key_Control, true, Qt::ShiftModifier | Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Down, true, Qt::ShiftModifier | Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Down, false, Qt::ShiftModifier | Qt::ControlModifier); - m_platform->sendKey(Qt::Key_Control, false, Qt::ShiftModifier); - m_platform->sendKey(Qt::Key_Shift, false); - usleep(25 * 1000); - m_platform->sendKey(Qt::Key_Backspace, true); - m_platform->sendKey(Qt::Key_Backspace, false); - - usleep(25 * 1000); + execType(new AutoTypeKey(Qt::Key_Up, Qt::ControlModifier)); + execType(new AutoTypeKey(Qt::Key_Down, Qt::ControlModifier | Qt::ShiftModifier)); + execType(new AutoTypeKey(Qt::Key_Backspace)); } diff --git a/src/autotype/mac/AutoTypeMac.h b/src/autotype/mac/AutoTypeMac.h index 4ae9e2140..f23a7c1d8 100644 --- a/src/autotype/mac/AutoTypeMac.h +++ b/src/autotype/mac/AutoTypeMac.h @@ -57,9 +57,8 @@ class AutoTypeExecutorMac : public AutoTypeExecutor public: explicit AutoTypeExecutorMac(AutoTypePlatformMac* platform); - void execChar(AutoTypeChar* action) override; - void execKey(AutoTypeKey* action) override; - void execClearField(AutoTypeClearField* action) override; + void execType(const AutoTypeKey* action) override; + void execClearField(const AutoTypeClearField* action) override; private: AutoTypePlatformMac* const m_platform; diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp index aa768238f..906edae34 100644 --- a/src/autotype/test/AutoTypeTest.cpp +++ b/src/autotype/test/AutoTypeTest.cpp @@ -59,27 +59,23 @@ QString AutoTypePlatformTest::actionChars() int AutoTypePlatformTest::actionCount() { - return m_actionList.size(); + return m_actionCount; } void AutoTypePlatformTest::clearActions() { - qDeleteAll(m_actionList); - m_actionList.clear(); - m_actionChars.clear(); + m_actionCount = 0; } -void AutoTypePlatformTest::addActionChar(AutoTypeChar* action) +void AutoTypePlatformTest::addAction(const AutoTypeKey* action) { - m_actionList.append(action->clone()); - m_actionChars += action->character; -} - -void AutoTypePlatformTest::addActionKey(AutoTypeKey* action) -{ - m_actionList.append(action->clone()); - m_actionChars.append(keyToString(action->key)); + ++m_actionCount; + if (action->key != Qt::Key_unknown) { + m_actionChars += keyToString(action->key); + } else { + m_actionChars += action->character; + } } bool AutoTypePlatformTest::raiseWindow(WId window) @@ -106,12 +102,12 @@ AutoTypeExecutorTest::AutoTypeExecutorTest(AutoTypePlatformTest* platform) { } -void AutoTypeExecutorTest::execChar(AutoTypeChar* action) +void AutoTypeExecutorTest::execType(const AutoTypeKey* action) { - m_platform->addActionChar(action); + m_platform->addAction(action); } -void AutoTypeExecutorTest::execKey(AutoTypeKey* action) +void AutoTypeExecutorTest::execClearField(const AutoTypeClearField* action) { - m_platform->addActionKey(action); + Q_UNUSED(action); } diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index dbbbe4642..9758d281f 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -51,12 +51,11 @@ public: int actionCount() override; void clearActions() override; - void addActionChar(AutoTypeChar* action); - void addActionKey(AutoTypeKey* action); + void addAction(const AutoTypeKey* action); private: QString m_activeWindowTitle; - QList m_actionList; + int m_actionCount = 0; QString m_actionChars; }; @@ -65,8 +64,8 @@ class AutoTypeExecutorTest : public AutoTypeExecutor public: explicit AutoTypeExecutorTest(AutoTypePlatformTest* platform); - void execChar(AutoTypeChar* action) override; - void execKey(AutoTypeKey* action) override; + void execType(const AutoTypeKey* action) override; + void execClearField(const AutoTypeClearField* action) override; private: AutoTypePlatformTest* const m_platform; diff --git a/src/autotype/windows/AutoTypeWindows.cpp b/src/autotype/windows/AutoTypeWindows.cpp index 435c52d09..6e796e5c7 100644 --- a/src/autotype/windows/AutoTypeWindows.cpp +++ b/src/autotype/windows/AutoTypeWindows.cpp @@ -17,6 +17,7 @@ */ #include "AutoTypeWindows.h" +#include "core/Tools.h" #include "gui/osutils/OSUtils.h" #include @@ -225,36 +226,43 @@ AutoTypeExecutorWin::AutoTypeExecutorWin(AutoTypePlatformWin* platform) { } -void AutoTypeExecutorWin::execChar(AutoTypeChar* action) +void AutoTypeExecutorWin::execType(const AutoTypeKey* action) { - m_platform->sendChar(action->character, true); - m_platform->sendChar(action->character, false); + if (action->modifiers & Qt::ShiftModifier) { + m_platform->sendKey(Qt::Key_Shift, true); + } + if (action->modifiers & Qt::ControlModifier) { + m_platform->sendKey(Qt::Key_Control, true); + } + if (action->modifiers & Qt::AltModifier) { + m_platform->sendKey(Qt::Key_Alt, true); + } + + if (action->key != Qt::Key_unknown) { + m_platform->sendKey(action->key, true); + m_platform->sendKey(action->key, false); + } else { + m_platform->sendChar(action->character, true); + m_platform->sendChar(action->character, false); + } + + if (action->modifiers & Qt::ShiftModifier) { + m_platform->sendKey(Qt::Key_Shift, false); + } + if (action->modifiers & Qt::ControlModifier) { + m_platform->sendKey(Qt::Key_Control, false); + } + if (action->modifiers & Qt::AltModifier) { + m_platform->sendKey(Qt::Key_Alt, false); + } + + Tools::sleep(execDelayMs); } -void AutoTypeExecutorWin::execKey(AutoTypeKey* action) -{ - m_platform->sendKey(action->key, true); - m_platform->sendKey(action->key, false); -} - -void AutoTypeExecutorWin::execClearField(AutoTypeClearField* action = nullptr) +void AutoTypeExecutorWin::execClearField(const AutoTypeClearField* action) { Q_UNUSED(action); - - m_platform->sendKey(Qt::Key_Control, true); - m_platform->sendKey(Qt::Key_Home, true); - m_platform->sendKey(Qt::Key_Home, false); - m_platform->sendKey(Qt::Key_Control, false); - ::Sleep(25); - m_platform->sendKey(Qt::Key_Control, true); - m_platform->sendKey(Qt::Key_Shift, true); - m_platform->sendKey(Qt::Key_End, true); - m_platform->sendKey(Qt::Key_End, false); - m_platform->sendKey(Qt::Key_Shift, false); - m_platform->sendKey(Qt::Key_Control, false); - ::Sleep(25); - m_platform->sendKey(Qt::Key_Backspace, true); - m_platform->sendKey(Qt::Key_Backspace, false); - - ::Sleep(25); + execType(new AutoTypeKey(Qt::Key_Home, Qt::ControlModifier)); + execType(new AutoTypeKey(Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier)); + execType(new AutoTypeKey(Qt::Key_Backspace)); } diff --git a/src/autotype/windows/AutoTypeWindows.h b/src/autotype/windows/AutoTypeWindows.h index 2f624e924..fe3ea82ec 100644 --- a/src/autotype/windows/AutoTypeWindows.h +++ b/src/autotype/windows/AutoTypeWindows.h @@ -54,9 +54,8 @@ class AutoTypeExecutorWin : public AutoTypeExecutor public: explicit AutoTypeExecutorWin(AutoTypePlatformWin* platform); - void execChar(AutoTypeChar* action) override; - void execKey(AutoTypeKey* action) override; - void execClearField(AutoTypeClearField* action) override; + void execType(const AutoTypeKey* action) override; + void execClearField(const AutoTypeClearField* action) override; private: AutoTypePlatformWin* const m_platform; diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp index 950a91178..40127c9a7 100644 --- a/src/autotype/xcb/AutoTypeXCB.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -569,32 +569,23 @@ AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform) { } -void AutoTypeExecutorX11::execChar(AutoTypeChar* action) +void AutoTypeExecutorX11::execType(const AutoTypeKey* action) { - m_platform->sendKey(qcharToNativeKeyCode(action->character)); + if (action->key != Qt::Key_unknown) { + m_platform->sendKey(qtToNativeKeyCode(action->key), qtToNativeModifiers(action->modifiers)); + } else { + m_platform->sendKey(qcharToNativeKeyCode(action->character), qtToNativeModifiers(action->modifiers)); + } + + Tools::sleep(execDelayMs); } -void AutoTypeExecutorX11::execKey(AutoTypeKey* action) -{ - m_platform->sendKey(qtToNativeKeyCode(action->key)); -} - -void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr) +void AutoTypeExecutorX11::execClearField(const AutoTypeClearField* action) { Q_UNUSED(action); - - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 25 * 1000 * 1000; - - m_platform->sendKey(qtToNativeKeyCode(Qt::Key_Home), static_cast(ControlMask)); - nanosleep(&ts, nullptr); - - m_platform->sendKey(qtToNativeKeyCode(Qt::Key_End), static_cast(ControlMask | ShiftMask)); - nanosleep(&ts, nullptr); - - m_platform->sendKey(qtToNativeKeyCode(Qt::Key_Backspace)); - nanosleep(&ts, nullptr); + execType(new AutoTypeKey(Qt::Key_Home, Qt::ControlModifier)); + execType(new AutoTypeKey(Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier)); + execType(new AutoTypeKey(Qt::Key_Backspace)); } bool AutoTypePlatformX11::raiseWindow(WId window) diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h index 54bb675ec..5f4795552 100644 --- a/src/autotype/xcb/AutoTypeXCB.h +++ b/src/autotype/xcb/AutoTypeXCB.h @@ -103,9 +103,8 @@ class AutoTypeExecutorX11 : public AutoTypeExecutor public: explicit AutoTypeExecutorX11(AutoTypePlatformX11* platform); - void execChar(AutoTypeChar* action) override; - void execKey(AutoTypeKey* action) override; - void execClearField(AutoTypeClearField* action) override; + void execType(const AutoTypeKey* action) override; + void execClearField(const AutoTypeClearField* action) override; private: AutoTypePlatformX11* const m_platform; diff --git a/src/core/Global.h b/src/core/Global.h index 5e7375148..6f48977b6 100644 --- a/src/core/Global.h +++ b/src/core/Global.h @@ -25,12 +25,12 @@ #if defined(Q_OS_WIN) #if defined(KEEPASSX_BUILDING_CORE) -#define KEEPASSX_EXPORT Q_DECL_IMPORT +#define KEEPASSXC_EXPORT Q_DECL_IMPORT #else -#define KEEPASSX_EXPORT Q_DECL_EXPORT +#define KEEPASSXC_EXPORT Q_DECL_EXPORT #endif #else -#define KEEPASSX_EXPORT Q_DECL_EXPORT +#define KEEPASSXC_EXPORT Q_DECL_EXPORT #endif #ifndef QUINT32_MAX diff --git a/src/core/MacPasteboard.h b/src/core/MacPasteboard.h index f2a71e73f..503741ca8 100644 --- a/src/core/MacPasteboard.h +++ b/src/core/MacPasteboard.h @@ -18,9 +18,9 @@ #ifndef KEEPASSXC_MACPASTEBOARD_H #define KEEPASSXC_MACPASTEBOARD_H -#include #include #include +#include class MacPasteboard : public QObject, public QMacPasteboardMime { diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 5b40a9b8e..dcc4d34cf 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1613,6 +1613,13 @@ void MainWindow::toggleWindow() } } +void MainWindow::closeModalWindow() +{ + if (qApp->modalWindow()) { + qApp->modalWindow()->close(); + } +} + void MainWindow::lockDatabasesAfterInactivity() { m_ui->tabWidget->lockDatabases(); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 13e59b5ae..4163ba71a 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -87,6 +87,7 @@ public slots: void bringToFront(); void closeAllDatabases(); void lockAllDatabases(); + void closeModalWindow(); void displayDesktopNotification(const QString& msg, QString title = "", int msTimeoutHint = 10000); void restartApp(const QString& message); diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index d6d696ac6..3a8a606ec 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -1028,8 +1028,36 @@ bool EditEntryWidget::commitEntry() } // Check Auto-Type validity early - if (!AutoType::verifyAutoTypeSyntax(m_autoTypeUi->sequenceEdit->text())) { - return false; + QString error; + if (m_autoTypeUi->customSequenceButton->isChecked() + && !AutoType::verifyAutoTypeSyntax(m_autoTypeUi->sequenceEdit->text(), m_entry, error)) { + auto res = MessageBox::question(this, + tr("Auto-Type Validation Error"), + tr("An error occurred while validating the custom Auto-Type sequence:\n%1\n" + "Would you like to correct it?") + .arg(error), + MessageBox::Yes | MessageBox::No, + MessageBox::Yes); + if (res == MessageBox::Yes) { + setCurrentPage(3); + return false; + } + } + for (const auto& assoc : m_autoTypeAssoc->getAll()) { + if (!AutoType::verifyAutoTypeSyntax(assoc.sequence, m_entry, error)) { + auto res = + MessageBox::question(this, + tr("Auto-Type Validation Error"), + tr("An error occurred while validating the Auto-Type sequence for \"%1\":\n%2\n" + "Would you like to correct it?") + .arg(assoc.window.left(40), error), + MessageBox::Yes | MessageBox::No, + MessageBox::Yes); + if (res == MessageBox::Yes) { + setCurrentPage(3); + return false; + } + } } if (m_advancedUi->attributesView->currentIndex().isValid() && m_advancedUi->attributesEdit->isEnabled()) { diff --git a/src/gui/osutils/nixutils/X11Funcs.cpp b/src/gui/osutils/nixutils/X11Funcs.cpp index a942b42ee..5f3313035 100644 --- a/src/gui/osutils/nixutils/X11Funcs.cpp +++ b/src/gui/osutils/nixutils/X11Funcs.cpp @@ -99,6 +99,8 @@ KeySym qtToNativeKeyCode(Qt::Key key) default: if (key >= Qt::Key_F1 && key <= Qt::Key_F16) { return XK_F1 + (key - Qt::Key_F1); + } else if (key >= Qt::Key_Space && key <= Qt::Key_AsciiTilde) { + return key && 0xff; } else { return NoSymbol; } diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 5403670bd..fba75189a 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -280,43 +280,47 @@ void TestAutoType::testGlobalAutoTypeRegExp() void TestAutoType::testAutoTypeSyntaxChecks() { + auto entry = new Entry(); + QString error; + // Huge sequence - QVERIFY(AutoType::checkSyntax( - "{word 23}{F1 23}{~ 23}{% 23}{^}{F12}{(}{) 23}{[}{[}{]}{Delay=23}{+}{SUBTRACT}~+%@fixedstring")); + QVERIFY2(AutoType::verifyAutoTypeSyntax( + "{F1 23}{~ 23}{% 23}{^}{F12}{(}{) 23}{[}{[}{]}{Delay=23}{+}{SUBTRACT}~+%@fixedstring", entry, error), + error.toLatin1()); - QVERIFY(AutoType::checkSyntax("{NUMPAD1 3}")); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{NUMPAD1 3}", entry, error), error.toLatin1()); - QVERIFY(AutoType::checkSyntax("{S:SPECIALTOKEN}")); - QVERIFY(AutoType::checkSyntax("{S:SPECIAL TOKEN}")); - QVERIFY(AutoType::checkSyntax("{S:SPECIAL_TOKEN}")); - QVERIFY(AutoType::checkSyntax("{S:SPECIAL-TOKEN}")); - QVERIFY(AutoType::checkSyntax("{S:SPECIAL:TOKEN}")); - QVERIFY(AutoType::checkSyntax("{S:SPECIAL_TOKEN}{ENTER}")); - QVERIFY(AutoType::checkSyntax("{S:FOO}{S:HELLO WORLD}")); - QVERIFY(!AutoType::checkSyntax("{S:SPECIAL_TOKEN{}}")); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIALTOKEN}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL TOKEN}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL-TOKEN}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL:TOKEN}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN}{ENTER}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{S:FOO}{S:HELLO WORLD}", entry, error), error.toLatin1()); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{S:SPECIAL_TOKEN{}}", entry, error), error.toLatin1()); - QVERIFY(AutoType::checkSyntax("{BEEP 3 3}")); - QVERIFY(!AutoType::checkSyntax("{BEEP 3}")); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{BEEP 3 3}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{BEEP 3}", entry, error), error.toLatin1()); - QVERIFY(AutoType::checkSyntax("{VKEY 0x01}")); - QVERIFY(AutoType::checkSyntax("{VKEY VK_LBUTTON}")); - QVERIFY(AutoType::checkSyntax("{VKEY-EX 0x01}")); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY 0x01}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY VK_LBUTTON}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{VKEY-EX 0x01}", entry, error), error.toLatin1()); // Bad sequence - QVERIFY(!AutoType::checkSyntax("{{{}}{}{}}{{}}")); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{{{}}{}{}}{{}}", entry, error), error.toLatin1()); // Good sequence - QVERIFY(AutoType::checkSyntax("{{}{}}{}}{{}")); - QVERIFY(AutoType::checkSyntax("{]}{[}{[}{]}")); - QVERIFY(AutoType::checkSyntax("{)}{(}{(}{)}")); - // High DelAY / low delay - QVERIFY(AutoType::checkHighDelay("{DelAY 50000}")); - QVERIFY(!AutoType::checkHighDelay("{delay 50}")); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{{}{}}{}}{{}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{]}{[}{[}{]}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{)}{(}{(}{)}", entry, error), error.toLatin1()); + // High delay + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{DELAY 50000}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay 50}", entry, error), error.toLatin1()); // Slow typing - QVERIFY(AutoType::checkSlowKeypress("{DelAY=50000}")); - QVERIFY(!AutoType::checkSlowKeypress("{delay=50}")); - // Many repetition / few repetition / delay not repetition - QVERIFY(AutoType::checkHighRepetition("{LEFT 50000000}")); - QVERIFY(!AutoType::checkHighRepetition("{SPACE 10}{TAB 3}{RIGHT 50}")); - QVERIFY(!AutoType::checkHighRepetition("{delay 5000000000}")); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{DELAY=50000}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay=50}", entry, error), error.toLatin1()); + // Many repetition + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{LEFT 50000000}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{SPACE 10}{TAB 3}{RIGHT 50}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay 5000000000}", entry, error), error.toLatin1()); } void TestAutoType::testAutoTypeEffectiveSequences() From 813ab47e2997f31eae5cb8c3daef8128e6923ff7 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 13 Feb 2021 22:08:29 -0500 Subject: [PATCH 4/6] Implement Auto-Type {PICKCHARS} * Closes #725 Support Auto-Type {PICKCHARS} placeholder. Open a dialog that lets you pick characters of an entry's password by their position. Supports typing {TAB} in between characters to move between fields (if necessary). Also supports using arrow keys to quickly navigate around the choice grid. --- docs/topics/AutoType.adoc | 1 + src/CMakeLists.txt | 1 + src/autotype/AutoType.cpp | 22 ++++ src/autotype/PickcharsDialog.cpp | 172 +++++++++++++++++++++++++++++++ src/autotype/PickcharsDialog.h | 52 ++++++++++ src/autotype/PickcharsDialog.ui | 87 ++++++++++++++++ 6 files changed, 335 insertions(+) create mode 100644 src/autotype/PickcharsDialog.cpp create mode 100644 src/autotype/PickcharsDialog.h create mode 100644 src/autotype/PickcharsDialog.ui diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index eb6a76909..b58830598 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -47,6 +47,7 @@ image::autotype_entry_sequences.png[] |{DELAY X} |Delay typing start by X milliseconds |{CLEARFIELD} |Clear the input field before typing |{TOTP} |Insert calculated TOTP value (if configured) +|{PICKCHARS} |Pick specific password characters from a dialog |{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) |=== + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba8acdc77..80ce5247c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -273,6 +273,7 @@ set(autotype_SOURCES autotype/AutoTypeMatchModel.cpp autotype/AutoTypeMatchView.cpp autotype/AutoTypeSelectDialog.cpp + autotype/PickcharsDialog.cpp autotype/ShortcutWidget.cpp autotype/WindowSelectComboBox.cpp) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 3373342ef..0fd79c13e 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -27,6 +27,7 @@ #include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeSelectDialog.h" +#include "autotype/PickcharsDialog.h" #include "core/Config.h" #include "core/Database.h" #include "core/Entry.h" @@ -564,6 +565,27 @@ AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString for (const auto& ch : totp) { actions << QSharedPointer::create(ch); } + } else if (placeholder == "pickchars") { + if (error) { + // Ignore this if we are syntax checking + continue; + } + // Show pickchars dialog for entry's password + auto password = entry->resolvePlaceholder(entry->password()); + if (!password.isEmpty()) { + PickcharsDialog pickcharsDialog(password); + if (pickcharsDialog.exec() == QDialog::Accepted && !pickcharsDialog.selectedChars().isEmpty()) { + auto chars = pickcharsDialog.selectedChars(); + auto iter = chars.begin(); + while (iter != chars.end()) { + actions << QSharedPointer::create(*iter); + ++iter; + if (pickcharsDialog.pressTab() && iter != chars.end()) { + actions << QSharedPointer::create(g_placeholderToKey["tab"]); + } + } + } + } } else if (placeholder == "beep" || placeholder.startsWith("vkey") || placeholder.startsWith("appactivate")) { // Ignore these commands diff --git a/src/autotype/PickcharsDialog.cpp b/src/autotype/PickcharsDialog.cpp new file mode 100644 index 000000000..4735e1ec9 --- /dev/null +++ b/src/autotype/PickcharsDialog.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2021 Team KeePassXC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "PickcharsDialog.h" +#include "ui_PickcharsDialog.h" + +#include "core/Entry.h" +#include "gui/Icons.h" + +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) +#include +#else +#include +#endif + +PickcharsDialog::PickcharsDialog(const QString& string, QWidget* parent) + : QDialog(parent) + , m_ui(new Ui::PickcharsDialog()) +{ + if (string.isEmpty()) { + reject(); + } + + // Places the window on the active (virtual) desktop instead of where the main window is. + setAttribute(Qt::WA_X11BypassTransientForHint); + setWindowFlags((windowFlags() | Qt::WindowStaysOnTopHint | Qt::MSWindowsFixedSizeDialogHint) + & ~Qt::WindowContextHelpButtonHint); + setWindowIcon(icons()->applicationIcon()); + + m_ui->setupUi(this); + + // Increase max columns with longer passwords for better display + int width = 10; + if (string.length() >= 100) { + width = 20; + } else if (string.length() >= 60) { + width = 15; + } + + int count = 0; + for (const auto& ch : string) { + auto btn = new QPushButton(QString::number(count + 1)); + btn->setProperty("char", ch); + btn->setProperty("count", count); + connect(btn, &QPushButton::clicked, this, &PickcharsDialog::charSelected); + m_ui->charsGrid->addWidget(btn, count / width, count % width); + m_lastSelected = count; + ++count; + } + // Prevent stretched buttons + if (m_ui->charsGrid->rowCount() == 1 && m_ui->charsGrid->columnCount() < 5) { + m_ui->charsGrid->addItem(new QSpacerItem(5, 5, QSizePolicy::MinimumExpanding), count / width, count % width); + } + m_ui->charsGrid->itemAtPosition(0, 0)->widget()->setFocus(); + + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + // Navigate grid layout using up/down/left/right motion + new QShortcut(Qt::Key_Up, this, SLOT(upPressed())); + new QShortcut(Qt::Key_Down, this, SLOT(downPressed())); + // Remove last selected character + auto shortcut = new QShortcut(Qt::Key_Backspace, this); + connect(shortcut, &QShortcut::activated, this, [this] { + auto text = m_ui->selectedChars->text(); + m_ui->selectedChars->setText(text.left(text.size() - 1)); + }); + // Submit the form + shortcut = new QShortcut(Qt::CTRL + Qt::Key_S, this); + connect(shortcut, &QShortcut::activated, this, [this] { accept(); }); +} + +void PickcharsDialog::upPressed() +{ + auto focus = focusWidget(); + if (!focus) { + return; + } + + auto count = focus->property("count"); + if (count.isValid()) { + // Lower bound not checked by QGridLayout::itemAt https://bugreports.qt.io/browse/QTBUG-91261 + auto upCount = count.toInt() - m_ui->charsGrid->columnCount(); + if (upCount >= 0) { + m_ui->charsGrid->itemAt(upCount)->widget()->setFocus(); + } + } else if (focus == m_ui->selectedChars) { + // Move back to the last selected button + auto item = m_ui->charsGrid->itemAt(m_lastSelected); + if (item) { + item->widget()->setFocus(); + } + } else if (focus == m_ui->pressTab) { + m_ui->selectedChars->setFocus(); + } +} + +void PickcharsDialog::downPressed() +{ + auto focus = focusWidget(); + if (!focus) { + return; + } + + auto count = focus->property("count"); + if (count.isValid()) { + auto item = m_ui->charsGrid->itemAt(count.toInt() + m_ui->charsGrid->columnCount()); + if (item) { + item->widget()->setFocus(); + } else { + // Store the currently selected button and move to the line edit + m_lastSelected = count.toInt(); + m_ui->selectedChars->setFocus(); + } + } else if (focus == m_ui->selectedChars) { + m_ui->pressTab->setFocus(); + } +} + +QString PickcharsDialog::selectedChars() +{ + return m_ui->selectedChars->text(); +} + +bool PickcharsDialog::pressTab() +{ + return m_ui->pressTab->isChecked(); +} + +void PickcharsDialog::charSelected() +{ + auto btn = qobject_cast(sender()); + if (!btn) { + return; + } + + m_ui->selectedChars->setText(m_ui->selectedChars->text() + btn->property("char").toChar()); +} + +void PickcharsDialog::showEvent(QShowEvent* event) +{ + QDialog::showEvent(event); + + // Center on active screen +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + auto screen = QApplication::screenAt(QCursor::pos()); + if (!screen) { + // screenAt can return a nullptr, default to the primary screen + screen = QApplication::primaryScreen(); + } + QRect screenGeometry = screen->availableGeometry(); +#else + QRect screenGeometry = QApplication::desktop()->availableGeometry(QCursor::pos()); +#endif + move(screenGeometry.center().x() - (size().width() / 2), screenGeometry.center().y() - (size().height() / 2)); +} diff --git a/src/autotype/PickcharsDialog.h b/src/autotype/PickcharsDialog.h new file mode 100644 index 000000000..dc35ae0bf --- /dev/null +++ b/src/autotype/PickcharsDialog.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 Team KeePassXC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_PICKCHARSDIALOG_H +#define KEEPASSXC_PICKCHARSDIALOG_H + +#include +#include +#include + +namespace Ui +{ + class PickcharsDialog; +} + +class PickcharsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PickcharsDialog(const QString& string, QWidget* parent = nullptr); + QString selectedChars(); + bool pressTab(); + +protected: + void showEvent(QShowEvent*) override; + +private slots: + void charSelected(); + void upPressed(); + void downPressed(); + +private: + QSharedPointer m_ui; + int m_lastSelected; +}; + +#endif // KEEPASSXC_PICKCHARSDIALOG_H diff --git a/src/autotype/PickcharsDialog.ui b/src/autotype/PickcharsDialog.ui new file mode 100644 index 000000000..de9704eb0 --- /dev/null +++ b/src/autotype/PickcharsDialog.ui @@ -0,0 +1,87 @@ + + + PickcharsDialog + + + + 0 + 0 + 418 + 188 + + + + KeePassXC - Pick Characters + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + Select characters to type, navigate with arrow keys, Ctrl + S submits. + + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + + + + + + Press &Tab between characters + + + true + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + PasswordEdit + QLineEdit +
gui/PasswordEdit.h
+
+
+ + selectedChars + + + +
From 02446af7438ad116872b669a8cecae7b67df2c04 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 24 Dec 2020 10:58:11 -0500 Subject: [PATCH 5/6] Auto-Type support for T-CONV, T-REPLACE-RX, and Comments * Close #1825 - Add full support for T-CONV and T-REPLACE-RX placeholders. Exception is support for the "raw" type in T-CONV. * Close #5333 - Allow comment syntax to be present in the Auto-Type sequence --- docs/topics/AutoType.adoc | 49 +++++++++++++++++------------- src/autotype/AutoType.cpp | 63 +++++++++++++++++++++++++++++++++++++-- tests/TestAutoType.cpp | 44 +++++++++++++++++++++++++++ tests/TestAutoType.h | 2 ++ 4 files changed, 135 insertions(+), 23 deletions(-) diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index b58830598..a53766918 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -31,27 +31,9 @@ To configure Auto-Type sequences for your entries, perform the following steps: .Auto-Type entry sequences image::autotype_entry_sequences.png[] -2. _(Optional)_ Define a custom auto-type sequence for each window title match by selecting the _Use specific sequence for this association_ checkbox. Sequence action codes and field placeholders are detailed in the following table. A complete list of supported actions and placeholders can be found at https://keepass.info/help/base/autotype.html#autoseq[KeePass Auto-Type Action Codes] and https://keepass.info/help/base/placeholders.html[KeePass Placeholders]. Action codes and placeholders are not case sensitive. +2. _(Optional)_ Define a custom Auto-Type sequence for each window title match by selecting the _Use specific sequence for this association_ checkbox. Sequence action codes and field placeholders are detailed in the following table. Beyond the most important ones detailed below, there are additional action codes and placeholders available: https://keepass.info/help/base/autotype.html#autoseq[KeePass Auto-Type Action Codes, window=_blank] and https://keepass.info/help/base/placeholders.html[KeePass Placeholders, window=_blank]. Action codes and placeholders are not case sensitive. + -[grid=rows, frame=none, width=70%] -|=== -|Action Code |Description - -|{TAB}, {ENTER}, {SPACE}, {INSERT}, {DELETE}, {HOME}, {END}, {PGUP}, {PGDN}, {BACKSPACE}, {CAPSLOCK}, {ESC} -|Press the corresponding keyboard key - -|{UP}, {DOWN}, {LEFT}, {RIGHT} |Press the corresponding arrow key -|{F1}, {F2}, ..., {F16} |Press F1, F2, etc. -|{LEFTBRACE}, {RIGHTBRACE} |Press `{` or `}`, respectively -|{DELAY=X} |Set key press delay to X milliseconds -|{DELAY X} |Delay typing start by X milliseconds -|{CLEARFIELD} |Clear the input field before typing -|{TOTP} |Insert calculated TOTP value (if configured) -|{PICKCHARS} |Pick specific password characters from a dialog -|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) -|=== -+ -[grid=rows, frame=none, width=70%] +[grid=rows, frame=none, width=90%] |=== |Placeholder |Description @@ -64,8 +46,33 @@ image::autotype_entry_sequences.png[] |{DT_SIMPLE} |Current date-time |{DB_DIR} |Absolute directory path for database file |{S:} |Value for the given attribute name -|{REF:@:} |Search for a field in another entry using the reference syntax. +|{REF:@:} |Search for a field in another entry using the reference syntax. https://keepass.info/help/base/fieldrefs.html[Read more…, window=_blank] |=== ++ +[grid=rows, frame=none, width=90%] +|=== +|Action Code |Description + +|{TAB}, {ENTER}, {SPACE}, {INSERT}, {DELETE}, {HOME}, {END}, {PGUP}, {PGDN}, {BACKSPACE}, {CAPSLOCK}, {ESC} +|Press the corresponding keyboard key + +|{UP}, {DOWN}, {LEFT}, {RIGHT} |Press the corresponding arrow key +|{F1}, {F2}, ..., {F16} |Press F1, F2, etc. +|{LEFTBRACE}, {RIGHTBRACE} |Press `{` or `}`, respectively +|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) +|{DELAY=X} |Set delay between key presses to X milliseconds +|{DELAY X} |Pause typing for X milliseconds +|{CLEARFIELD} |Clear the input field +|{PICKCHARS} |Pick specific password characters from a dialog +|=== ++ +*Text Conversions:* ++ +*{T-CONV:///}* + +Convert resolved placeholder (e.g., {USERNAME}, {PASSWORD}, etc.) using the following methods: UPPER, LOWER, BASE64, HEX, URI, URI-DEC. https://keepass.info/help/base/placeholders.html#conv[Read more…, window=_blank] ++ +*{T-REPLACE-RX:////}* + +Use regular expressions to find and replace data from a resolved placeholder. Refer to match groups using $1, $2, etc. https://keepass.info/help/base/placeholders.html#replacerx[Read more…, window=_blank] === Performing Global Auto-Type The global Auto-Type keyboard shortcut is used when you have focus on the window you want to type into. To make use of this feature, you must have previously configured an Auto-Type hotkey. diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 0fd79c13e..75c7f9904 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -586,8 +586,67 @@ AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString } } } - } else if (placeholder == "beep" || placeholder.startsWith("vkey") - || placeholder.startsWith("appactivate")) { + } else if (placeholder.startsWith("t-conv:")) { + // Reset to the original capture to preserve case + placeholder = match.captured(3); + placeholder.replace("t-conv:", "", Qt::CaseInsensitive); + if (!placeholder.isEmpty()) { + auto sep = placeholder[0]; + auto parts = placeholder.split(sep); + if (parts.size() >= 4) { + auto resolved = entry->resolveMultiplePlaceholders(parts[1]); + auto type = parts[2].toLower(); + + if (type == "base64") { + resolved = resolved.toUtf8().toBase64(); + } else if (type == "hex") { + resolved = resolved.toUtf8().toHex(); + } else if (type == "uri") { + resolved = QUrl::toPercentEncoding(resolved.toUtf8()); + } else if (type == "uri-dec") { + resolved = QUrl::fromPercentEncoding(resolved.toUtf8()); + } else if (type.startsWith("u")) { + resolved = resolved.toUpper(); + } else if (type.startsWith("l")) { + resolved = resolved.toLower(); + } else if (error) { + *error = tr("Invalid conversion type: %1").arg(type); + continue; + } + for (const QChar& ch : resolved) { + actions << QSharedPointer::create(ch); + } + } else if (error) { + *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + } + } else if (error) { + *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + } + } else if (placeholder.startsWith("t-replace-rx:")) { + // Reset to the original capture to preserve case + placeholder = match.captured(3); + placeholder.replace("t-replace-rx:", "", Qt::CaseInsensitive); + if (!placeholder.isEmpty()) { + auto sep = placeholder[0]; + auto parts = placeholder.split(sep); + if (parts.size() >= 5) { + auto resolvedText = entry->resolveMultiplePlaceholders(parts[1]); + auto resolvedSearch = entry->resolveMultiplePlaceholders(parts[2]); + auto resolvedReplace = entry->resolveMultiplePlaceholders(parts[3]); + // Replace $ with \s to support Qt substitutions + resolvedReplace.replace(QRegularExpression("\\$(\\d+)"), "\\\\1"); + auto resolved = resolvedText.replace(QRegularExpression(resolvedSearch), resolvedReplace); + for (const QChar& ch : resolved) { + actions << QSharedPointer::create(ch); + } + } else if (error) { + *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + } + } else if (error) { + *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + } + } else if (placeholder == "beep" || placeholder.startsWith("vkey") || placeholder.startsWith("appactivate") + || placeholder.startsWith("c:")) { // Ignore these commands } else { // Attempt to resolve an entry attribute diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index fba75189a..c053d317e 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -278,6 +278,43 @@ void TestAutoType::testGlobalAutoTypeRegExp() m_test->clearActions(); } +void TestAutoType::testAutoTypeResults() +{ + QScopedPointer entry(new Entry()); + entry->setUsername("Username"); + entry->setPassword("Password@1"); + entry->setUrl("https://example.com"); + entry->attributes()->set("attr1", "value1"); + entry->attributes()->set("attr2", "decode%20me"); + + QFETCH(QString, sequence); + QFETCH(QString, expectedResult); + + m_autoType->performAutoTypeWithSequence(entry.data(), sequence); + QCOMPARE(m_test->actionChars(), expectedResult); +} + +void TestAutoType::testAutoTypeResults_data() +{ + QTest::addColumn("sequence"); + QTest::addColumn("expectedResult"); + + // Normal Sequences + QTest::newRow("Sequence with Attributes") << QString("{USERNAME} {PASSWORD} {URL} {S:attr1}") + << QString("Username Password@1 https://example.com value1"); + QTest::newRow("Sequence with Comment") << QString("{USERNAME}{TAB}{C:Extra Tab}{TAB}{S:attr1}") + << QString("Username[Key0x1000001][Key0x1000001]value1"); + + // Conversions and Replacements + QTest::newRow("T-CONV UPPER") << QString("{T-CONV:/{USERNAME}/UPPER/}") << QString("USERNAME"); + QTest::newRow("T-CONV LOWER") << QString("{T-CONV:/{USERNAME}/LOWER/}") << QString("username"); + QTest::newRow("T-CONV BASE64") << QString("{T-CONV:/{USERNAME}/BASE64/}") << QString("VXNlcm5hbWU="); + QTest::newRow("T-CONV HEX") << QString("{T-CONV:/{USERNAME}/HEX/}") << QString("557365726e616d65"); + QTest::newRow("T-CONV URI ENCODE") << QString("{T-CONV:/{URL}/URI/}") << QString("https%3A%2F%2Fexample.com"); + QTest::newRow("T-CONV URI DECODE") << QString("{T-CONV:/{S:attr2}/URI-DEC/}") << QString("decode me"); + QTest::newRow("T-REPLACE-RX") << QString("{T-REPLACE-RX:/{USERNAME}/User/Pass/}") << QString("Passname"); +} + void TestAutoType::testAutoTypeSyntaxChecks() { auto entry = new Entry(); @@ -321,6 +358,13 @@ void TestAutoType::testAutoTypeSyntaxChecks() QVERIFY2(!AutoType::verifyAutoTypeSyntax("{LEFT 50000000}", entry, error), error.toLatin1()); QVERIFY2(AutoType::verifyAutoTypeSyntax("{SPACE 10}{TAB 3}{RIGHT 50}", entry, error), error.toLatin1()); QVERIFY2(AutoType::verifyAutoTypeSyntax("{delay 5000000000}", entry, error), error.toLatin1()); + // Conversion and Regex + QVERIFY2(AutoType::verifyAutoTypeSyntax("{T-CONV:/{USERNAME}/base64/}", entry, error), error.toLatin1()); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-CONV:/{USERNAME}/junk/}", entry, error), error.toLatin1()); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-CONV:}", entry, error), error.toLatin1()); + QVERIFY2(AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:/{USERNAME}/a/b/}", entry, error), error.toLatin1()); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:/{USERNAME}/a/}", entry, error), error.toLatin1()); + QVERIFY2(!AutoType::verifyAutoTypeSyntax("{T-REPLACE-RX:}", entry, error), error.toLatin1()); } void TestAutoType::testAutoTypeEffectiveSequences() diff --git a/tests/TestAutoType.h b/tests/TestAutoType.h index 03086a68e..035c0d5c0 100644 --- a/tests/TestAutoType.h +++ b/tests/TestAutoType.h @@ -47,6 +47,8 @@ private slots: void testGlobalAutoTypeUrlSubdomainMatch(); void testGlobalAutoTypeTitleMatchDisabled(); void testGlobalAutoTypeRegExp(); + void testAutoTypeResults(); + void testAutoTypeResults_data(); void testAutoTypeSyntaxChecks(); void testAutoTypeEffectiveSequences(); From 8d058cbd043175b0624e82f20d6c4cbc7f33ea35 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Mon, 15 Feb 2021 17:26:23 -0500 Subject: [PATCH 6/6] Additional Auto-Type improvements based on PR feedback * Improve documentation and remove external links to keepass.info documentation --- docs/UserGuide.adoc | 2 + docs/topics/AutoType.adoc | 16 +- docs/topics/DatabaseOperations.adoc | 15 +- docs/topics/Reference.adoc | 94 ++++++++ src/autotype/AutoType.cpp | 323 +++++++++++++++------------- src/autotype/AutoType.h | 2 +- src/autotype/mac/CMakeLists.txt | 14 +- src/autotype/test/CMakeLists.txt | 4 +- src/autotype/windows/CMakeLists.txt | 6 +- src/autotype/xcb/CMakeLists.txt | 6 +- tests/TestAutoType.cpp | 4 +- 11 files changed, 292 insertions(+), 194 deletions(-) create mode 100644 docs/topics/Reference.adoc diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 439bcd417..4000f5641 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -34,3 +34,5 @@ include::topics/AutoType.adoc[tags=*] include::topics/KeeShare.adoc[tags=*] include::topics/SSHAgent.adoc[tags=*] + +include::topics/Reference.adoc[tags=*] diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index a53766918..019afd2b2 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -31,7 +31,7 @@ To configure Auto-Type sequences for your entries, perform the following steps: .Auto-Type entry sequences image::autotype_entry_sequences.png[] -2. _(Optional)_ Define a custom Auto-Type sequence for each window title match by selecting the _Use specific sequence for this association_ checkbox. Sequence action codes and field placeholders are detailed in the following table. Beyond the most important ones detailed below, there are additional action codes and placeholders available: https://keepass.info/help/base/autotype.html#autoseq[KeePass Auto-Type Action Codes, window=_blank] and https://keepass.info/help/base/placeholders.html[KeePass Placeholders, window=_blank]. Action codes and placeholders are not case sensitive. +2. _(Optional)_ Define a custom Auto-Type sequence for each window title match by selecting the _Use specific sequence for this association_ checkbox. Sequence action codes and field placeholders are detailed in the following table. Beyond the most important ones detailed below, there are additional action codes and placeholders available: xref:UserGuide.adoc#_auto_type_actions[Auto-Type Actions Reference] and xref:UserGuide.adoc#_entry_placeholders[Entry Placeholders Reference]. Action codes and placeholders are not case sensitive. + [grid=rows, frame=none, width=90%] |=== @@ -43,10 +43,7 @@ image::autotype_entry_sequences.png[] |{URL} |URL |{NOTES} |Notes |{TOTP} |Current TOTP value (if configured) -|{DT_SIMPLE} |Current date-time -|{DB_DIR} |Absolute directory path for database file |{S:} |Value for the given attribute name -|{REF:@:} |Search for a field in another entry using the reference syntax. https://keepass.info/help/base/fieldrefs.html[Read more…, window=_blank] |=== + [grid=rows, frame=none, width=90%] @@ -57,22 +54,13 @@ image::autotype_entry_sequences.png[] |Press the corresponding keyboard key |{UP}, {DOWN}, {LEFT}, {RIGHT} |Press the corresponding arrow key -|{F1}, {F2}, ..., {F16} |Press F1, F2, etc. |{LEFTBRACE}, {RIGHTBRACE} |Press `{` or `}`, respectively -|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) +|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) |{DELAY=X} |Set delay between key presses to X milliseconds |{DELAY X} |Pause typing for X milliseconds |{CLEARFIELD} |Clear the input field |{PICKCHARS} |Pick specific password characters from a dialog |=== -+ -*Text Conversions:* -+ -*{T-CONV:///}* + -Convert resolved placeholder (e.g., {USERNAME}, {PASSWORD}, etc.) using the following methods: UPPER, LOWER, BASE64, HEX, URI, URI-DEC. https://keepass.info/help/base/placeholders.html#conv[Read more…, window=_blank] -+ -*{T-REPLACE-RX:////}* + -Use regular expressions to find and replace data from a resolved placeholder. Refer to match groups using $1, $2, etc. https://keepass.info/help/base/placeholders.html#replacerx[Read more…, window=_blank] === Performing Global Auto-Type The global Auto-Type keyboard shortcut is used when you have focus on the window you want to type into. To make use of this feature, you must have previously configured an Auto-Type hotkey. diff --git a/docs/topics/DatabaseOperations.adoc b/docs/topics/DatabaseOperations.adoc index 0cb15ea3a..0b5790bd1 100644 --- a/docs/topics/DatabaseOperations.adoc +++ b/docs/topics/DatabaseOperations.adoc @@ -120,18 +120,7 @@ image::clone_entry_dialog.png[,70%] .References in a cloned entry image::clone_entry_references.png[] -4. You can create your own references using the following syntax: -+ -`{REF:@I:}` -+ -Where `` is the Unique Identifier of the entry to pull data from and `` is from the following: -+ - * T - Title - * U - Username - * P - Password - * A - URL - * N - Notes - * I - UUID +4. You can create your own references using the xref:UserGuide.adoc#_entry_cross_reference[Entry Reference Syntax] == Searching the Database KeePassXC provides an enhanced and granular search features the enables you to search for specific entries in the databases using the different modifiers, wild card characters, and logical operators. @@ -287,7 +276,7 @@ image::database_security.png[] + .Database credentials image::database_security_credentials.png[] - ++ WARNING: Consider creating a backup of your YubiKey. Please refer to <> 5. Encryption settings allows you to change the average time it takes to encrypt and decrypt the database. The longer time that is chosen, the harder it will be to brute force attack your database. *We recommend a setting of one second.* diff --git a/docs/topics/Reference.adoc b/docs/topics/Reference.adoc new file mode 100644 index 000000000..3a19c23fc --- /dev/null +++ b/docs/topics/Reference.adoc @@ -0,0 +1,94 @@ += KeePassXC - Reference +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Reference +This section contains full details on advanced features available in KeePassXC. + +=== Entry Placeholders +[grid=rows, frame=none, width=90%] +|=== +|Placeholder |Description + +|{TITLE} |Entry Title +|{USERNAME} |Username +|{PASSWORD} |Password +|{URL} |URL +|{NOTES} |Notes +|{TOTP} |Current TOTP value (if configured) +|{S:} |Value for the given attribute (case sensitive) +|{URL:RMVSCM} |URL without scheme (e.g., https) +|{URL:WITHOUTSCHEME} |URL without scheme +|{URL:SCM} |URL Scheme +|{URL:SCHEME} |URL Scheme +|{URL:HOST} |URL Host (e.g., example.com) +|{URL:PORT} |URL Port +|{URL:PATH} |URL Path (e.g., /path/to/page.html) +|{URL:QUERY} |URL Query String +|{URL:FRAGMENT} |URL Fragment +|{URL:USERINFO} |URL Username:Password +|{URL:USERNAME} |URL Username +|{URL:PASSWORD} |URL Password +|{DT_SIMPLE} |Current Date-Time (yyyyMMddhhmmss) +|{DT_YEAR} |Current Year (yyyy) +|{DT_MONTH} |Current Month (MM) +|{DT_DAY} |Current Day (dd) +|{DT_HOUR} |Current Hour (hh) +|{DT_MINUTE} |Current Minutes (mm) +|{DT_SECOND} |Current Seconds (ss) +|{DT_UTC_SIMPLE} |Current UTC Date-Time (yyyyMMddhhmmss) +|{DT_UTC_YEAR} |Current UTC Year (yyyy) +|{DT_UTC_MONTH} |Current UTC Month (MM) +|{DT_UTC_DAY} |Current UTC Day (dd) +|{DT_UTC_HOUR} |Current UTC Hour (hh) +|{DT_UTC_MINUTE} |Current UTC Minutes (mm) +|{DT_UTC_SECOND} |Current UTC Seconds (ss) +|{DB_DIR} |Absolute directory path of database file +|=== + +=== Entry Cross-Reference +A reference to another entry's field is possible using the short-hand syntax: +`{REF:@:}` + +`` and `` can be one of following: + +* T - Title +* U - Username +* P - Password +* A - URL +* N - Notes +* I - UUID (found on entry properties page) +* O - Custom Attribute _(SEARCH_IN only)_ + +Examples: + +`{REF:U@I:033054D445C648C59092CC1D661B1B71}` + +`{REF:P@T:Other Entry}` + +`{REF:A@O:Attribute 1}` + +=== Auto-Type Actions +[grid=rows, frame=none, width=90%] +|=== +|Action Code |Description + +|{TAB}, {ENTER}, {SPACE}, {INSERT}, {DELETE}, {HOME}, {END}, {PGUP}, {PGDN}, {BACKSPACE}, {CAPSLOCK}, {ESC} +|Press the corresponding keyboard key + +|{UP}, {DOWN}, {LEFT}, {RIGHT} |Press the corresponding arrow key +|{F1}, {F2}, ..., {F16} |Press F1, F2, etc. +|{LEFTBRACE}, {RIGHTBRACE} |Press `{` or `}`, respectively +|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) +|{DELAY=X} |Set delay between key presses to X milliseconds +|{DELAY X} |Pause typing for X milliseconds +|{CLEARFIELD} |Clear the input field +|{PICKCHARS} |Pick specific password characters from a dialog +|=== + +*Text Conversions:* + +*{T-CONV:///}* + +Convert resolved placeholder (e.g., {USERNAME}, {PASSWORD}, etc.) using the following methods: UPPER, LOWER, BASE64, HEX, URI, URI-DEC. + +*{T-REPLACE-RX:////}* + +Use regular expressions to find and replace data from a resolved placeholder. Refer to match groups using $1, $2, etc. +// end::content[] diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 75c7f9904..513d85908 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include "config-keepassx.h" @@ -32,7 +31,6 @@ #include "core/Database.h" #include "core/Entry.h" #include "core/Group.h" -#include "core/ListDeleter.h" #include "core/Resources.h" #include "core/Tools.h" #include "gui/MainWindow.h" @@ -131,7 +129,7 @@ AutoType::AutoType(QObject* parent, bool test) // prevent crash when the plugin has unresolved symbols m_pluginLoader->setLoadHints(QLibrary::ResolveAllSymbolsHint); - QString pluginName = "keepassx-autotype-"; + QString pluginName = "keepassxc-autotype-"; if (!test) { pluginName += QApplication::platformName(); } else { @@ -169,7 +167,7 @@ void AutoType::loadPlugin(const QString& pluginPath) if (m_plugin) { if (m_plugin->isAvailable()) { m_executor = m_plugin->createExecutor(); - connect(osUtils, &OSUtilsBase::globalShortcutTriggered, this, [this](QString name) { + connect(osUtils, &OSUtilsBase::globalShortcutTriggered, this, [this](const QString& name) { if (name == "autotype") { startGlobalAutoType(); } @@ -249,6 +247,20 @@ void AutoType::unregisterGlobalShortcut() */ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& sequence, WId window) { + QString error; + auto actions = parseSequence(sequence, entry, error); + + if (!error.isEmpty()) { + auto errorMsg = tr("The requested Auto-Type sequence cannot be used due to an error:"); + errorMsg.append(QString("\n%1\n%2").arg(sequence, error)); + if (getMainWindow()) { + MessageBox::critical(getMainWindow(), tr("Auto-Type Error"), errorMsg); + } + qWarning() << errorMsg; + emit autotypeRejected(); + return; + } + if (!m_inAutoType.tryLock()) { return; } @@ -272,11 +284,9 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c #endif } - auto actions = parseActions(sequence, entry); - // Restore window state in case app stole focus restoreWindowState(); - QApplication::processEvents(); + QCoreApplication::processEvents(); m_plugin->raiseWindow(m_windowForGlobal); // Used only for selected entry auto-type @@ -286,7 +296,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c Tools::wait(qMax(100, config()->get(Config::AutoTypeStartDelay).toInt())); - for (auto action : asConst(actions)) { + for (const auto& action : asConst(actions)) { if (m_plugin->activeWindow() != window) { qWarning("Active window changed, interrupting auto-type."); emit autotypeRejected(); @@ -301,7 +311,6 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c m_windowForGlobal = 0; m_windowTitleForGlobal.clear(); - // emit signal only if autotype performed correctly emit autotypePerformed(); m_inAutoType.unlock(); } @@ -426,7 +435,7 @@ void AutoType::performGlobalAutoType(const QList>& dbLi selectDialog->setMatches(matchList, dbList); connect(getMainWindow(), &MainWindow::databaseLocked, selectDialog, &AutoTypeSelectDialog::reject); - connect(selectDialog, &AutoTypeSelectDialog::matchActivated, this, [this](AutoTypeMatch match) { + connect(selectDialog, &AutoTypeSelectDialog::matchActivated, this, [this](const AutoTypeMatch& match) { executeAutoTypeActions(match.first, nullptr, match.second, m_windowForGlobal); resetAutoTypeState(); }); @@ -480,7 +489,7 @@ void AutoType::resetAutoTypeState() * If error is provided then syntax checking will be performed. */ QList> -AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString* error) +AutoType::parseSequence(const QString& entrySequence, const Entry* entry, QString& error, bool syntaxOnly) { const int maxTypeDelay = 100; const int maxWaitDelay = 10000; @@ -495,8 +504,8 @@ AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString sequence.replace("{}}", "{RIGHTBRACE}"); // Quick test for bracket syntax - if ((sequence.count("{") + sequence.count("}")) % 2 != 0 && error) { - *error = tr("Bracket imbalance detected, found extra { or }"); + if (sequence.count("{") != sequence.count("}")) { + error = tr("Bracket imbalance detected, found extra { or }"); return {}; } @@ -530,147 +539,163 @@ AutoType::parseActions(const QString& entrySequence, const Entry* entry, QString } auto character = match.captured(5); - if (!placeholder.isEmpty()) { - if (g_placeholderToKey.contains(placeholder)) { - // Basic key placeholder, allow repeat - if (repeat > maxRepetition && error) { - *error = tr("Too many repetitions detected, max is %1: %2").arg(maxRepetition).arg(fullPlaceholder); - return {}; - } - auto action = QSharedPointer::create(g_placeholderToKey[placeholder], modifiers); - for (int i = 1; i <= repeat && i <= maxRepetition; ++i) { - actions << action; - } - } else if (placeholder.startsWith("delay=")) { - // Change keypress delay - int delay = placeholder.replace("delay=", "").toInt(); - if (delay > maxTypeDelay && error) { - *error = tr("Very slow key press detected, max is %1: %2").arg(maxTypeDelay).arg(fullPlaceholder); - return {}; - } - actions << QSharedPointer::create(qBound(0, delay, maxTypeDelay), true); - } else if (placeholder == "delay") { - // Mid typing delay (wait) - if (repeat > maxWaitDelay && error) { - *error = tr("Very long delay detected, max is %1: %2").arg(maxWaitDelay).arg(fullPlaceholder); - return {}; - } - actions << QSharedPointer::create(qBound(0, repeat, maxWaitDelay)); - } else if (placeholder == "clearfield") { - // Platform-specific field clearing - actions << QSharedPointer::create(); - } else if (placeholder == "totp") { - // Entry totp (requires special handling) - QString totp = entry->totp(); - for (const auto& ch : totp) { - actions << QSharedPointer::create(ch); - } - } else if (placeholder == "pickchars") { - if (error) { - // Ignore this if we are syntax checking - continue; - } - // Show pickchars dialog for entry's password - auto password = entry->resolvePlaceholder(entry->password()); - if (!password.isEmpty()) { - PickcharsDialog pickcharsDialog(password); - if (pickcharsDialog.exec() == QDialog::Accepted && !pickcharsDialog.selectedChars().isEmpty()) { - auto chars = pickcharsDialog.selectedChars(); - auto iter = chars.begin(); - while (iter != chars.end()) { - actions << QSharedPointer::create(*iter); - ++iter; - if (pickcharsDialog.pressTab() && iter != chars.end()) { - actions << QSharedPointer::create(g_placeholderToKey["tab"]); - } - } - } - } - } else if (placeholder.startsWith("t-conv:")) { - // Reset to the original capture to preserve case - placeholder = match.captured(3); - placeholder.replace("t-conv:", "", Qt::CaseInsensitive); - if (!placeholder.isEmpty()) { - auto sep = placeholder[0]; - auto parts = placeholder.split(sep); - if (parts.size() >= 4) { - auto resolved = entry->resolveMultiplePlaceholders(parts[1]); - auto type = parts[2].toLower(); + if (placeholder.isEmpty()) { + if (!character.isEmpty()) { + // Type a single character with modifier + actions << QSharedPointer::create(character[0], modifiers); + } + continue; + } - if (type == "base64") { - resolved = resolved.toUtf8().toBase64(); - } else if (type == "hex") { - resolved = resolved.toUtf8().toHex(); - } else if (type == "uri") { - resolved = QUrl::toPercentEncoding(resolved.toUtf8()); - } else if (type == "uri-dec") { - resolved = QUrl::fromPercentEncoding(resolved.toUtf8()); - } else if (type.startsWith("u")) { - resolved = resolved.toUpper(); - } else if (type.startsWith("l")) { - resolved = resolved.toLower(); - } else if (error) { - *error = tr("Invalid conversion type: %1").arg(type); - continue; - } - for (const QChar& ch : resolved) { - actions << QSharedPointer::create(ch); - } - } else if (error) { - *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); - } - } else if (error) { - *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); - } - } else if (placeholder.startsWith("t-replace-rx:")) { - // Reset to the original capture to preserve case - placeholder = match.captured(3); - placeholder.replace("t-replace-rx:", "", Qt::CaseInsensitive); - if (!placeholder.isEmpty()) { - auto sep = placeholder[0]; - auto parts = placeholder.split(sep); - if (parts.size() >= 5) { - auto resolvedText = entry->resolveMultiplePlaceholders(parts[1]); - auto resolvedSearch = entry->resolveMultiplePlaceholders(parts[2]); - auto resolvedReplace = entry->resolveMultiplePlaceholders(parts[3]); - // Replace $ with \s to support Qt substitutions - resolvedReplace.replace(QRegularExpression("\\$(\\d+)"), "\\\\1"); - auto resolved = resolvedText.replace(QRegularExpression(resolvedSearch), resolvedReplace); - for (const QChar& ch : resolved) { - actions << QSharedPointer::create(ch); - } - } else if (error) { - *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); - } - } else if (error) { - *error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); - } - } else if (placeholder == "beep" || placeholder.startsWith("vkey") || placeholder.startsWith("appactivate") - || placeholder.startsWith("c:")) { - // Ignore these commands - } else { - // Attempt to resolve an entry attribute - auto resolved = entry->resolvePlaceholder(fullPlaceholder); - if (resolved != fullPlaceholder) { - // Attribute resolved, add characters to action list - for (const QChar& ch : resolved) { - if (ch == '\n') { - actions << QSharedPointer::create(g_placeholderToKey["enter"]); - } else if (ch == '\t') { + if (g_placeholderToKey.contains(placeholder)) { + // Basic key placeholder, allow repeat + if (repeat > maxRepetition) { + error = tr("Too many repetitions detected, max is %1: %2").arg(maxRepetition).arg(fullPlaceholder); + return {}; + } + auto action = QSharedPointer::create(g_placeholderToKey[placeholder], modifiers); + for (int i = 1; i <= repeat && i <= maxRepetition; ++i) { + actions << action; + } + } else if (placeholder.startsWith("delay=")) { + // Change keypress delay + int delay = placeholder.replace("delay=", "").toInt(); + if (delay > maxTypeDelay) { + error = tr("Very slow key press detected, max is %1: %2").arg(maxTypeDelay).arg(fullPlaceholder); + return {}; + } + actions << QSharedPointer::create(qBound(0, delay, maxTypeDelay), true); + } else if (placeholder == "delay") { + // Mid typing delay (wait) + if (repeat > maxWaitDelay) { + error = tr("Very long delay detected, max is %1: %2").arg(maxWaitDelay).arg(fullPlaceholder); + return {}; + } + actions << QSharedPointer::create(qBound(0, repeat, maxWaitDelay)); + } else if (placeholder == "clearfield") { + // Platform-specific field clearing + actions << QSharedPointer::create(); + } else if (placeholder == "totp") { + // Entry totp (requires special handling) + QString totp = entry->totp(); + for (const auto& ch : totp) { + actions << QSharedPointer::create(ch); + } + } else if (placeholder == "pickchars") { + // Ignore this if we are syntax checking + if (syntaxOnly) { + continue; + } + // Show pickchars dialog for entry's password + auto password = entry->resolvePlaceholder(entry->password()); + if (!password.isEmpty()) { + PickcharsDialog pickcharsDialog(password); + if (pickcharsDialog.exec() == QDialog::Accepted && !pickcharsDialog.selectedChars().isEmpty()) { + for (const auto& ch : pickcharsDialog.selectedChars()) { + actions << QSharedPointer::create(ch); + if (pickcharsDialog.pressTab()) { actions << QSharedPointer::create(g_placeholderToKey["tab"]); - } else { - actions << QSharedPointer::create(ch); } } - } else if (error) { - // Invalid placeholder, issue error and stop processing - *error = tr("Invalid placeholder: %1").arg(fullPlaceholder); - return {}; + if (pickcharsDialog.pressTab()) { + // Remove extra tab + actions.removeLast(); + } } } - } else if (!character.isEmpty()) { - // Type a single character with modifier - actions << QSharedPointer::create(character[0], modifiers); + } else if (placeholder.startsWith("t-conv:")) { + // Reset to the original capture to preserve case + placeholder = match.captured(3); + placeholder.replace("t-conv:", "", Qt::CaseInsensitive); + if (!placeholder.isEmpty()) { + auto sep = placeholder[0]; + auto parts = placeholder.split(sep); + if (parts.size() >= 4) { + auto resolved = entry->resolveMultiplePlaceholders(parts[1]); + auto type = parts[2].toLower(); + + if (type == "base64") { + resolved = resolved.toUtf8().toBase64(); + } else if (type == "hex") { + resolved = resolved.toUtf8().toHex(); + } else if (type == "uri") { + resolved = QUrl::toPercentEncoding(resolved.toUtf8()); + } else if (type == "uri-dec") { + resolved = QUrl::fromPercentEncoding(resolved.toUtf8()); + } else if (type.startsWith("u")) { + resolved = resolved.toUpper(); + } else if (type.startsWith("l")) { + resolved = resolved.toLower(); + } else { + error = tr("Invalid conversion type: %1").arg(type); + return {}; + } + for (const QChar& ch : resolved) { + actions << QSharedPointer::create(ch); + } + } else { + error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + return {}; + } + } else { + error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + return {}; + } + } else if (placeholder.startsWith("t-replace-rx:")) { + // Reset to the original capture to preserve case + placeholder = match.captured(3); + placeholder.replace("t-replace-rx:", "", Qt::CaseInsensitive); + if (!placeholder.isEmpty()) { + auto sep = placeholder[0]; + auto parts = placeholder.split(sep); + if (parts.size() >= 5) { + auto resolvedText = entry->resolveMultiplePlaceholders(parts[1]); + auto resolvedSearch = entry->resolveMultiplePlaceholders(parts[2]); + auto resolvedReplace = entry->resolveMultiplePlaceholders(parts[3]); + // Replace $ with \\ to support Qt substitutions + resolvedReplace.replace(QRegularExpression(R"(\$(\d+))"), R"(\\1)"); + + auto searchRegex = QRegularExpression(resolvedSearch); + if (!searchRegex.isValid()) { + error = tr("Invalid regular expression syntax %1\n%2") + .arg(resolvedSearch, searchRegex.errorString()); + return {}; + } + + auto resolved = resolvedText.replace(searchRegex, resolvedReplace); + for (const QChar& ch : resolved) { + actions << QSharedPointer::create(ch); + } + } else { + error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + return {}; + } + } else { + error = tr("Invalid conversion syntax: %1").arg(fullPlaceholder); + return {}; + } + } else if (placeholder == "beep" || placeholder.startsWith("vkey") || placeholder.startsWith("appactivate") + || placeholder.startsWith("c:")) { + // Ignore these commands + } else { + // Attempt to resolve an entry attribute + auto resolved = entry->resolvePlaceholder(fullPlaceholder); + if (resolved != fullPlaceholder) { + // Attribute resolved, add characters to action list + for (const QChar& ch : resolved) { + if (ch == '\n') { + actions << QSharedPointer::create(g_placeholderToKey["enter"]); + } else if (ch == '\t') { + actions << QSharedPointer::create(g_placeholderToKey["tab"]); + } else { + actions << QSharedPointer::create(ch); + } + } + } else { + // Invalid placeholder, issue error and stop processing + error = tr("Invalid placeholder: %1").arg(fullPlaceholder); + return {}; + } } } @@ -684,7 +709,7 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence, const Entry* entry, { error.clear(); if (!sequence.isEmpty()) { - parseActions(sequence, entry, &error); + parseSequence(sequence, entry, error, true); } return error.isEmpty(); } diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index c11845d41..e9d7e25e8 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -86,7 +86,7 @@ private: void resetAutoTypeState(); static QList> - parseActions(const QString& entrySequence, const Entry* entry, QString* error = nullptr); + parseSequence(const QString& entrySequence, const Entry* entry, QString& error, bool syntaxOnly = false); QMutex m_inAutoType; QMutex m_inGlobalAutoTypeDialog; diff --git a/src/autotype/mac/CMakeLists.txt b/src/autotype/mac/CMakeLists.txt index adc439221..883eeab73 100644 --- a/src/autotype/mac/CMakeLists.txt +++ b/src/autotype/mac/CMakeLists.txt @@ -1,18 +1,18 @@ set(autotype_mac_SOURCES AutoTypeMac.cpp) -add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES}) -set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon") -target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets) +add_library(keepassxc-autotype-cocoa MODULE ${autotype_mac_SOURCES}) +set_target_properties(keepassxc-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon") +target_link_libraries(keepassxc-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets) if(WITH_APP_BUNDLE) - add_custom_command(TARGET keepassx-autotype-cocoa + add_custom_command(TARGET keepassxc-autotype-cocoa POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassx-autotype-cocoa.so ${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so - COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so -no-plugins 2> /dev/null + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassxc-autotype-cocoa.so ${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so + COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so -no-plugins 2> /dev/null WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src COMMENT "Deploying autotype plugin") else() - install(TARGETS keepassx-autotype-cocoa + install(TARGETS keepassxc-autotype-cocoa BUNDLE DESTINATION . COMPONENT Runtime LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) endif() diff --git a/src/autotype/test/CMakeLists.txt b/src/autotype/test/CMakeLists.txt index a9cf998df..453e36af5 100644 --- a/src/autotype/test/CMakeLists.txt +++ b/src/autotype/test/CMakeLists.txt @@ -1,4 +1,4 @@ set(autotype_test_SOURCES AutoTypeTest.cpp) -add_library(keepassx-autotype-test MODULE ${autotype_test_SOURCES}) -target_link_libraries(keepassx-autotype-test keepassx_core ${autotype_LIB} Qt5::Core Qt5::Widgets) +add_library(keepassxc-autotype-test MODULE ${autotype_test_SOURCES}) +target_link_libraries(keepassxc-autotype-test keepassx_core ${autotype_LIB} Qt5::Core Qt5::Widgets) diff --git a/src/autotype/windows/CMakeLists.txt b/src/autotype/windows/CMakeLists.txt index be74b7aa7..33bd54c58 100644 --- a/src/autotype/windows/CMakeLists.txt +++ b/src/autotype/windows/CMakeLists.txt @@ -1,7 +1,7 @@ set(autotype_win_SOURCES AutoTypeWindows.cpp) -add_library(keepassx-autotype-windows MODULE ${autotype_win_SOURCES}) -target_link_libraries(keepassx-autotype-windows keepassx_core ${autotype_LIB} Qt5::Core Qt5::Widgets) -install(TARGETS keepassx-autotype-windows +add_library(keepassxc-autotype-windows MODULE ${autotype_win_SOURCES}) +target_link_libraries(keepassxc-autotype-windows keepassx_core ${autotype_LIB} Qt5::Core Qt5::Widgets) +install(TARGETS keepassxc-autotype-windows BUNDLE DESTINATION . COMPONENT Runtime LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) diff --git a/src/autotype/xcb/CMakeLists.txt b/src/autotype/xcb/CMakeLists.txt index e41d4a099..0704de639 100644 --- a/src/autotype/xcb/CMakeLists.txt +++ b/src/autotype/xcb/CMakeLists.txt @@ -2,8 +2,8 @@ include_directories(SYSTEM ${X11_X11_INCLUDE_PATH}) set(autotype_XCB_SOURCES AutoTypeXCB.cpp) -add_library(keepassx-autotype-xcb MODULE ${autotype_XCB_SOURCES}) -target_link_libraries(keepassx-autotype-xcb keepassx_core Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB}) -install(TARGETS keepassx-autotype-xcb +add_library(keepassxc-autotype-xcb MODULE ${autotype_XCB_SOURCES}) +target_link_libraries(keepassxc-autotype-xcb keepassx_core Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB}) +install(TARGETS keepassxc-autotype-xcb BUNDLE DESTINATION . COMPONENT Runtime LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index c053d317e..ee1906dd4 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -40,7 +40,7 @@ void TestAutoType::initTestCase() config()->set(Config::Security_AutoTypeAsk, false); AutoType::createTestInstance(); - QPluginLoader loader(resources()->pluginPath("keepassx-autotype-test")); + QPluginLoader loader(resources()->pluginPath("keepassxc-autotype-test")); loader.setLoadHints(QLibrary::ResolveAllSymbolsHint); QVERIFY(loader.instance()); @@ -312,7 +312,7 @@ void TestAutoType::testAutoTypeResults_data() QTest::newRow("T-CONV HEX") << QString("{T-CONV:/{USERNAME}/HEX/}") << QString("557365726e616d65"); QTest::newRow("T-CONV URI ENCODE") << QString("{T-CONV:/{URL}/URI/}") << QString("https%3A%2F%2Fexample.com"); QTest::newRow("T-CONV URI DECODE") << QString("{T-CONV:/{S:attr2}/URI-DEC/}") << QString("decode me"); - QTest::newRow("T-REPLACE-RX") << QString("{T-REPLACE-RX:/{USERNAME}/User/Pass/}") << QString("Passname"); + QTest::newRow("T-REPLACE-RX") << QString("{T-REPLACE-RX:/{USERNAME}/(User)/$1Pass/}") << QString("UserPassname"); } void TestAutoType::testAutoTypeSyntaxChecks()