15#include <QInputDialog>
20#define WIN32_LEAN_AND_MEAN
21#define WIN32_EXTRA_LEAN
37 : m_mainWindow(mainWindow), freshStart(true) {
39 clearClipboardTimer.setSingleShot(
true);
40 connect(&clearClipboardTimer, &QTimer::timeout,
this,
43#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
44#pragma GCC diagnostic push
45#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
47 QObject::connect(qApp, &QApplication::aboutToQuit,
this,
49#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
50#pragma GCC diagnostic pop
65 if (fusedav.state() == QProcess::Running) {
67 fusedav.waitForFinished(2000);
85 if (version.isEmpty()) {
87 dbg() <<
"assuming fresh install";
111 m_mainWindow->config();
130void QtPass::setMainWindow() {
133 fusedav.setParent(m_mainWindow);
142 &QtPass::passShowHandlerFinished);
152 dbg() <<
"Pass git init called";
158 [
this](
const QString &batch) {
160 m_mainWindow->showStatusMessage(tr(
"Generating GPG key pair"),
169void QtPass::connectPassSignalHandlers(
Pass *pass) {
170 connect(pass, &
Pass::error,
this, &QtPass::processError);
190 &QtPass::onKeyGenerationComplete);
197void QtPass::mountWebDav() {
201 memset(&netres, 0,
sizeof(netres));
202 netres.dwType = RESOURCETYPE_DISK;
203 netres.lpLocalName =
nullptr;
209 netres.lpRemoteName =
const_cast<char *
>(webDavUrlUtf8.constData());
210 DWORD size =
sizeof(dst);
211 DWORD r = WNetUseConnectionA(
212 reinterpret_cast<HWND
>(m_mainWindow->effectiveWinId()), &netres,
213 const_cast<char *
>(webDavPasswordUtf8.constData()),
214 const_cast<char *
>(webDavUserUtf8.constData()),
215 CONNECT_TEMPORARY | CONNECT_INTERACTIVE | CONNECT_REDIRECT, dst, &size,
220 char message[256] = {0};
221 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, r, 0, message,
223 m_mainWindow->flashText(tr(
"Failed to connect WebDAV:\n") + message +
224 " (0x" + QString::number(r, 16) +
")",
228 fusedav.start(
"fusedav", QStringList()
235 fusedav.waitForStarted();
236 if (fusedav.state() == QProcess::Running) {
240 pwd = QInputDialog::getText(m_mainWindow, tr(
"QtPass WebDAV password"),
241 tr(
"Enter password to connect to WebDAV:"),
242 QLineEdit::Password,
"", &ok);
244 if (ok && !pwd.isEmpty()) {
245 fusedav.write(pwd.toUtf8() +
'\n');
246 fusedav.closeWriteChannel();
247 fusedav.waitForFinished(2000);
252 QString error = fusedav.readAllStandardError();
253 int prompt = error.indexOf(
"Password:");
255 error.remove(0, prompt + 10);
257 if (fusedav.state() != QProcess::Running) {
258 error = tr(
"fusedav exited unexpectedly\n") + error;
260 if (error.size() > 0) {
261 m_mainWindow->flashText(
262 tr(
"Failed to start fusedav to connect WebDAV:\n") + error,
true);
271void QtPass::processError(QProcess::ProcessError error) {
274 case QProcess::FailedToStart:
275 errorString = tr(
"QProcess::FailedToStart");
277 case QProcess::Crashed:
278 errorString = tr(
"QProcess::Crashed");
280 case QProcess::Timedout:
281 errorString = tr(
"QProcess::Timedout");
283 case QProcess::ReadError:
284 errorString = tr(
"QProcess::ReadError");
286 case QProcess::WriteError:
287 errorString = tr(
"QProcess::WriteError");
289 case QProcess::UnknownError:
290 errorString = tr(
"QProcess::UnknownError");
293 m_mainWindow->flashText(errorString,
true);
294 m_mainWindow->setUiElementsEnabled(
true);
302void QtPass::processErrorExit(
int exitCode,
const QString &p_error) {
303 if (
nullptr != m_mainWindow->getKeygenDialog()) {
304 m_mainWindow->cleanKeygenDialog();
306 m_mainWindow->showStatusMessage(tr(
"GPG key pair generation failed"),
311 if (!p_error.isEmpty()) {
313 QString error = p_error.toHtmlEscaped();
316 output =
"<span style=\"color: darkgray;\">" + error +
"</span><br />";
318 output =
"<span style=\"color: red;\">" + error +
"</span><br />";
322 output.replace(QStringLiteral("\n"),
"<br />");
324 m_mainWindow->flashText(output,
false,
true);
327 m_mainWindow->setUiElementsEnabled(
true);
337void QtPass::processFinished(
const QString &p_output,
const QString &p_errout) {
338 showInTextBrowser(p_output);
341 processErrorExit(0, p_errout);
343 m_mainWindow->setUiElementsEnabled(
true);
351void QtPass::passStoreChanged(
const QString &p_out,
const QString &p_err) {
352 processFinished(p_out, p_err);
361void QtPass::finishedInsert(
const QString &p_output,
const QString &p_errout) {
362 processFinished(p_output, p_errout);
364 m_mainWindow->on_treeView_clicked(m_mainWindow->getCurrentTreeViewIndex());
372void QtPass::onKeyGenerationComplete(
const QString &p_output,
373 const QString &p_errout) {
374 if (
nullptr != m_mainWindow->getKeygenDialog()) {
376 qDebug() <<
"Keygen Done";
379 m_mainWindow->cleanKeygenDialog();
380 m_mainWindow->showStatusMessage(tr(
"GPG key pair generated successfully"),
384 processFinished(p_output, p_errout);
391void QtPass::passShowHandlerFinished(QString output) {
392 showInTextBrowser(std::move(output));
401void QtPass::showInTextBrowser(QString output,
const QString &prefix,
402 const QString &postfix) {
403 output = output.toHtmlEscaped();
406 output.replace(QStringLiteral("\n"),
"<br />");
407 output = prefix + output + postfix;
409 m_mainWindow->flashText(output,
false,
true);
415void QtPass::doGitPush() {
417 m_mainWindow->onPush();
429 !p_output.isEmpty()) {
430 clippedText = password;
453 QClipboard *clipboard = QApplication::clipboard();
454 bool cleared =
false;
455 if (this->clippedText == clipboard->text(QClipboard::Selection)) {
456 clipboard->clear(QClipboard::Selection);
457 clipboard->setText(QString(
""), QClipboard::Selection);
460 if (this->clippedText == clipboard->text(QClipboard::Clipboard)) {
461 clipboard->clear(QClipboard::Clipboard);
465 m_mainWindow->showStatusMessage(tr(
"Clipboard cleared"));
467 m_mainWindow->showStatusMessage(tr(
"Clipboard not cleared"));
479 auto *mimeData =
new QMimeData();
480 mimeData->setText(text);
482 mimeData->setData(
"x-kde-passwordManagerHint", QByteArray(
"secret"));
485 mimeData->setData(
"application/x-nspasteboard-concealed-type", QByteArray());
488 mimeData->setData(
"ExcludeClipboardContentFromMonitorProcessing",
490 mimeData->setData(
"CanIncludeInClipboardHistory", dwordBytes(0));
491 mimeData->setData(
"CanUploadToCloudClipboard", dwordBytes(0));
501 QClipboard *clip = QApplication::clipboard();
503 QClipboard::Mode mode = QClipboard::Clipboard;
505 mode = QClipboard::Selection;
509 clip->setMimeData(mimeData, mode);
512 m_mainWindow->showStatusMessage(tr(
"Copied to clipboard"));
514 clearClipboardTimer.start();
525 QStringList() <<
"-o-"
527 qrencode.write(text.toUtf8());
528 qrencode.closeWriteChannel();
529 qrencode.waitForFinished();
530 QByteArray output(qrencode.readAllStandardOutput());
532 if (qrencode.exitStatus() || qrencode.exitCode()) {
533 QString error(qrencode.readAllStandardError());
534 m_mainWindow->showStatusMessage(error);
537 image.loadFromData(output,
"PNG");
551 auto *popup =
new QDialog(
nullptr, Qt::Popup | Qt::FramelessWindowHint);
552 popup->setAttribute(Qt::WA_DeleteOnClose);
553 auto *layout =
new QVBoxLayout;
554 auto *popupLabel =
new QLabel();
555 layout->addWidget(popupLabel);
556 popupLabel->setPixmap(image);
557 popupLabel->setScaledContents(
true);
559 popup->setLayout(layout);
560 popup->move(QCursor::pos());
void endReencryptPath()
Emitted after finishing re-encryption.
void startReencryptPath()
Emitted before starting re-encryption.
The MainWindow class does way too much, not only is it a switchboard, configuration handler and more,...
void startReencryptPath()
MainWindow::startReencryptPath disable ui elements and treeview.
void passShowHandler(const QString &)
void endReencryptPath()
MainWindow::endReencryptPath re-enable ui elements.
void onGrepFinished(const QList< QPair< QString, QStringList > > &results)
Display grep results in grepResultsList.
void executeWrapperStarted()
void critical(const QString &, const QString &)
MainWindow::critical critical message popup wrapper.
void showStatusMessage(const QString &msg, int timeout=2000)
Displays message in status bar.
void passOtpHandler(const QString &)
void passShowHandlerFinished(const QString &output)
void generateGPGKeyPair(const QString &batch)
Abstract base class for password store operations.
void startingExecuteWrapper()
Emitted before executing a command.
void critical(const QString &, const QString &)
Emit critical error.
void finishedCopy(const QString &, const QString &)
Emitted when copy finishes.
void finishedShow(const QString &)
Emitted when show finishes.
void finishedRemove(const QString &, const QString &)
Emitted when remove finishes.
void finishedMove(const QString &, const QString &)
Emitted when move finishes.
void statusMsg(const QString &, int)
Emit status message.
void finishedGitInit(const QString &, const QString &)
Emitted when Git init finishes.
void finishedInsert(const QString &, const QString &)
Emitted when insert finishes.
void finishedGrep(const QList< QPair< QString, QStringList > > &results)
Emitted when grep finishes with matching results.
void finishedInit(const QString &, const QString &)
Emitted when init finishes.
void finishedOtpGenerate(const QString &)
Emitted when OTP generation finishes.
void processErrorExit(int exitCode, const QString &err)
Emitted on process error exit.
void finishedGitPull(const QString &, const QString &)
Emitted when Git pull finishes.
void finishedGitPush(const QString &, const QString &)
Emitted when Git push finishes.
void error(QProcess::ProcessError)
Emitted when a process error occurs.
void finishedGenerateGPGKeys(const QString &, const QString &)
Emitted when GPG key generation finishes.
void clearClippedText()
Clears the stored clipped text.
void setClipboardTimer()
Sets the clipboard clear timer based on autoclear settings.
void clearClipboard()
MainWindow::clearClipboard remove clipboard contents.
~QtPass()
QtPass::~QtPass destroy!
void setClippedText(const QString &, const QString &p_output=QString())
Sets the text to be stored in clipboard and handles clipboard operations.
QtPass(MainWindow *mainWindow)
Constructs a QtPass instance.
static QDialog * createQRCodePopup(const QPixmap &image)
QtPass::createQRCodePopup creates a popup dialog with the given QR code image. This is extracted for ...
void copyTextToClipboard(const QString &text)
MainWindow::copyTextToClipboard copies text to your clipboard.
auto init() -> bool
QtPass::init make sure we are ready to go as soon as possible.
void showTextAsQRCode(const QString &text)
displays the text as qrcode
static auto isUseSelection(const bool &defaultValue=QVariant().toBool()) -> bool
Get whether to use selection (X11) for clipboard.
static auto isUseAutoclear(const bool &defaultValue=QVariant().toBool()) -> bool
Get whether to use autoclear for clipboard.
static void setAutoclearPanelSeconds(const int &autoClearPanelSeconds)
Save panel autoclear seconds.
static auto getWebDavPassword(const QString &defaultValue=QVariant().toString()) -> QString
Get WebDAV password.
static auto getPwgenExecutable(const QString &defaultValue=QVariant().toString()) -> QString
Get pwgen executable path.
static auto getWebDavUser(const QString &defaultValue=QVariant().toString()) -> QString
Get WebDAV username.
static void setPassStore(const QString &passStore)
Save password store path.
static auto getPass() -> Pass *
Get currently active pass backend instance.
static auto getClipBoardType(const Enums::clipBoardType &defaultValue=Enums::CLIPBOARD_NEVER) -> Enums::clipBoardType
Get clipboard type as enum.
static void setUsePwgen(const bool &usePwgen)
Save pwgen support flag.
static auto getPassStore(const QString &defaultValue=QVariant().toString()) -> QString
Get password store directory path.
static auto getVersion(const QString &defaultValue=QVariant().toString()) -> QString
Get saved application version.
static void initExecutables()
Initialize executable paths by auto-detecting them.
static void setPassTemplate(const QString &passTemplate)
Save pass entry template.
static auto getQrencodeExecutable(const QString &defaultValue=QVariant().toString()) -> QString
Get qrencode executable path.
static void setVersion(const QString &version)
Save application version.
static auto getRealPass() -> RealPass *
Get real pass backend instance.
static auto getPassTemplate(const QString &defaultValue=QVariant().toString()) -> QString
Get pass entry template.
static auto getWebDavUrl(const QString &defaultValue=QVariant().toString()) -> QString
Get WebDAV URL.
static auto isUseWebDav(const bool &defaultValue=QVariant().toBool()) -> bool
Check whether WebDAV integration is enabled.
static auto getAutoclearPanelSeconds(const int &defaultValue=QVariant().toInt()) -> int
Get panel autoclear delay in seconds.
static void setAutoclearSeconds(const int &autoClearSeconds)
Save autoclear seconds.
static auto getImitatePass() -> ImitatePass *
Get imitate pass backend instance.
static auto getAutoclearSeconds(const int &defaultValue=QVariant().toInt()) -> int
Get autoclear delay in seconds.
static auto isAutoPush(const bool &defaultValue=QVariant().toBool()) -> bool
Check whether automatic push is enabled.
static auto protocolRegex() -> const QRegularExpression &
Returns a regex to match URL protocols.
static auto findPasswordStore() -> QString
Locate the password store directory.
static auto configIsValid() -> bool
Verify that the required configuration is complete.
Debug utilities for QtPass.
#define dbg()
Simple debug macro that includes file and line number.
auto buildClipboardMimeData(const QString &text) -> QMimeData *
Build clipboard MIME data with platform-specific security hints.
auto buildClipboardMimeData(const QString &text) -> QMimeData *
Build clipboard MIME data with platform-specific security hints.
constexpr int MS_PER_SECOND