Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package moolticute for openSUSE:Factory checked in at 2023-06-29 17:29:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/moolticute (Old) and /work/SRC/openSUSE:Factory/.moolticute.new.13546 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "moolticute" Thu Jun 29 17:29:09 2023 rev:4 rq:1095913 version:1.01.0.r0.g77100ea Changes: -------- --- /work/SRC/openSUSE:Factory/moolticute/moolticute.changes 2022-12-14 14:12:51.792068797 +0100 +++ /work/SRC/openSUSE:Factory/.moolticute.new.13546/moolticute.changes 2023-06-29 17:29:27.590657003 +0200 @@ -1,0 +2,18 @@ +Thu Jun 29 07:08:47 UTC 2023 - Stefan Weiberg <opens...@hibiki.eu> + +- Update to v1.01.0 + [BLE] Remove not tagged notes during import + [BLE] Fetch notes after import + [BLE] Fix import data nodes + [BLE] Display when entered multiple domain is invalid + [BLE] Fix multiple low battery notification + [BLE] Improve NoBundle FW upload + Fix application exit on Mac + bug fix: in a "no bundle" case, allow moolticute to fetch platform info + Mini BLE: increase file size to 20kB + Fix saving credential without passwords Qt6 + changing hidden tabs shortcuts to SHIFT + Fx + increasing daemon log size + Mini: fix files upload + +------------------------------------------------------------------- Old: ---- moolticute-1.00.1.r0.gf211d93.tar.gz New: ---- moolticute-1.01.0.r0.g77100ea.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ moolticute.spec ++++++ --- /var/tmp/diff_new_pack.dWXUoh/_old 2023-06-29 17:29:28.382661642 +0200 +++ /var/tmp/diff_new_pack.dWXUoh/_new 2023-06-29 17:29:28.390661689 +0200 @@ -1,7 +1,7 @@ # # spec file for package moolticute # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %global UDEVDIR %{_udevrulesdir} %global QMAKE_BIN qmake-qt5 Name: moolticute -Version: 1.00.1.r0.gf211d93 +Version: 1.01.0.r0.g77100ea Release: 0 Summary: Companion GUI application for Mooltipass password manager devices License: GPL-3.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.dWXUoh/_old 2023-06-29 17:29:28.450662040 +0200 +++ /var/tmp/diff_new_pack.dWXUoh/_new 2023-06-29 17:29:28.454662063 +0200 @@ -4,7 +4,7 @@ <param name="url">https://github.com/mooltipass/moolticute.git</param> <param name="filename">moolticute</param> <param name="package-meta">yes</param> - <param name="revision">v1.00.1</param> + <param name="revision">v1.01.0</param> <param name="versionrewrite-pattern">v([0-9\.]*)(-testing)?(.*)</param> <param name="versionrewrite-replacement">\1\3</param> <param name="versionformat">@PARENT_TAG@.r@TAG_OFFSET@.g%h</param> ++++++ moolticute-1.00.1.r0.gf211d93.tar.gz -> moolticute-1.01.0.r0.g77100ea.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/README.md new/moolticute-1.01.0.r0.g77100ea/README.md --- old/moolticute-1.00.1.r0.gf211d93/README.md 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/README.md 2023-02-05 21:17:46.000000000 +0100 @@ -32,6 +32,7 @@ ##### Linux - Requires the qt-dbus module - Requires to install [udev rule](https://github.com/mooltipass/mooltipass-udev) for it + - Note: For Linux systems without systemd please refer to [dedicated section](#non-systemd-linux) Moolticute comes in two part on Linux: - A daemon that runs in background named moolticuted that proxy @@ -96,6 +97,17 @@ ''; ``` +##### Non systemd Linux +The main [udev rules](https://github.com/mooltipass/mooltipass-udev) +relies on integration between systemd, systemd-login and systemd-udevd +to automatically allow any user logged in to access mooltipass devices. +This will not work on Linux ecosystem without systemd, one +workaround is to change the `TAG+="uaccess"` to +`GROUP="plugdev"` and add your interactive user to this group. + +Refer to [this +issue](https://github.com/mooltipass/mooltipass-udev/pull/3) for more information. + ### How to build For now, no binary releases are out yet. You will need to build the software by following the next step. @@ -108,7 +120,7 @@ - Download and install the Qt SDK from their [website](http://qt.io) - Start Qt-Creator - - Open the main Moolticute.pro project file + - Open the main Moolticute.pro project file - Note for Windows users: make sure that you select a "kit" that uses the MinGW compiler. Moolticute currently won't compile successfully when using the Microsoft Visual C++ compiler. - Click on the "play" button to build and run @@ -143,6 +155,4 @@ ### Licensing -Moolticute is free software: you can redistribute it and/or modify it under the terms of the GNU Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - - +Moolticute is free software: you can redistribute it and/or modify it under the terms of the GNU Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/AppGui.cpp new/moolticute-1.01.0.r0.g77100ea/src/AppGui.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/AppGui.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/AppGui.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -137,7 +137,14 @@ }); QAction* quitAction = new QAction(tr("&Quit"), this); + +#ifdef Q_OS_MAC + // Since Qt6 quit is not exiting application properly on Mac + // daemon keeps running and prepareToQuit is not called + connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::exit, Qt::QueuedConnection); +#else connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit, Qt::QueuedConnection); +#endif QMenu *systrayMenu = new QMenu(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/BleDev.cpp new/moolticute-1.01.0.r0.g77100ea/src/BleDev.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/BleDev.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/BleDev.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -69,6 +69,10 @@ { DeviceDetector::instance().shiftPressed(); } + if (event->key() == Qt::Key_Control) + { + DeviceDetector::instance().ctrlPressed(); + } } void BleDev::keyReleaseEvent(QKeyEvent *event) @@ -77,6 +81,10 @@ { DeviceDetector::instance().shiftReleased(); } + if (event->key() == Qt::Key_Control) + { + DeviceDetector::instance().ctrlReleased(); + } } void BleDev::initUITexts() @@ -179,11 +187,16 @@ } QSettings s; + bool skipFilePwdCheck = wsClient->get_status() == Common::NoBundle && + DeviceDetector::instance().isCtrlPressed(); + QString fileName = QFileDialog::getOpenFileName(this, tr("Select bundle file"), s.value("last_used_path/bundle_dir", QDir::homePath()).toString(), "*.img"); + // Due to file selection dialog opened, release events are not catched DeviceDetector::instance().shiftReleased(); + DeviceDetector::instance().ctrlReleased(); if (fileName.isEmpty()) { @@ -211,8 +224,9 @@ } QString password = ""; - if (!checkBundleFilePassword(QFileInfo{file}, password)) + if (!skipFilePwdCheck && !checkBundleFilePassword(QFileInfo{file}, password)) { + qCritical() << "Invalid bundle file password"; return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.cpp new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -31,6 +31,9 @@ #include "SettingsGuiBLE.h" #include "ParseDomain.h" +const QString CredentialsManagement::INVALID_DOMAIN_TEXT = + tr("The following domains are invalid or private: <b><ul><li>%1</li></ul></b>They are not saved."); + CredentialsManagement::CredentialsManagement(QWidget *parent) : QWidget(parent), ui(new Ui::CredentialsManagement), m_pAddedLoginItem(nullptr) { @@ -185,7 +188,7 @@ connect(ui->credentialTreeView, &CredentialView::collapsed, this, &CredentialsManagement::onItemCollapsed); connect(ui->pushButtonExpandAll, &QPushButton::clicked, ui->credentialTreeView, &CredentialView::onChangeExpandedState); connect(ui->credentialTreeView, &CredentialView::expandedStateChanged, this, &CredentialsManagement::onExpandedStateChanged); - connect(m_pCredModel, &CredentialModel::selectLoginItem, this, &CredentialsManagement::onSelectLoginItem, Qt::QueuedConnection); + connect(m_pCredModel, &CredentialModel::selectLoginItem, this, &CredentialsManagement::onSelectLoginItem); m_tSelectLoginTimer.setInterval(50); m_tSelectLoginTimer.setSingleShot(true); @@ -533,6 +536,11 @@ if (currentSelectionIndex.isValid()) saveCredential(currentSelectionIndex); + + if (!m_credentialLinkedAddr.isEmpty()) + { + m_credentialLinkedAddr.clear(); + } } void CredentialsManagement::saveSelectedTOTP() @@ -634,6 +642,7 @@ void CredentialsManagement::keyPressEvent(QKeyEvent *event) { + QWidget::keyPressEvent(event); if (wsClient->get_memMgmtMode() || !wsClient->isMPBLE()) { return; @@ -647,6 +656,7 @@ void CredentialsManagement::keyReleaseEvent(QKeyEvent *event) { + QWidget::keyReleaseEvent(event); if (wsClient->get_memMgmtMode() || !wsClient->isMPBLE()) { return; @@ -1405,7 +1415,7 @@ } } -QString CredentialsManagement::processMultipleDomainsInput(const QString& service, const QString &domains) +QString CredentialsManagement::processMultipleDomainsInput(const QString& service, const QString &domains, const bool disable_tld_check) { #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) auto splitBehavior = QString::SkipEmptyParts; @@ -1414,6 +1424,7 @@ #endif auto domainList = domains.split(MULT_DOMAIN_SEPARATOR, splitBehavior); QStringList validDomains; + QStringList invalidDomains; QString result = ""; auto serviceDomain = service; if (serviceDomain.contains('.')) @@ -1428,15 +1439,21 @@ domain.prepend('.'); } ParseDomain dom(serviceDomain + domain); - if (domain == dom.tld()) + if (disable_tld_check || domain == dom.tld()) { validDomains.append(domain); } else { qWarning() << "The following domain is not valid: " << domain; + invalidDomains.append(domain); } } + if (!invalidDomains.isEmpty()) + { + QMessageBox::information(this, tr("Invalid domain"), + INVALID_DOMAIN_TEXT.arg(invalidDomains.join("</li><li>"))); + } return validDomains.join(MULT_DOMAIN_SEPARATOR); } @@ -1670,13 +1687,15 @@ serviceNameChanged = true; } } + QSettings s; bool ok = false; + bool disable_tld_check = s.value("settings/disable_tld_check", false).toBool(); QString text = QInputDialog::getText(this, tr("Multiple Domains for %1").arg(pServiceItem->name()), tr("Enter comma separated domain extensions:"), QLineEdit::Normal, defaultDomains, &ok); if (ok) { - text = processMultipleDomainsInput(serviceName, text); + text = processMultipleDomainsInput(serviceName, text, disable_tld_check); if (!text.isEmpty()) { pServiceItem->setMultipleDomains(text); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.h new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.h --- old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.h 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.h 2023-02-05 21:17:46.000000000 +0100 @@ -54,8 +54,10 @@ public slots: bool confirmDiscardUneditedCredentialChanges(const QModelIndex &proxyIndex = {}); void saveChanges(); - void keyPressEvent(QKeyEvent* event); - void keyReleaseEvent(QKeyEvent* event); + +protected: + virtual void keyPressEvent(QKeyEvent *event) override; + virtual void keyReleaseEvent(QKeyEvent *event) override; private slots: void enableCredentialsManagement(bool); @@ -140,7 +142,7 @@ void checkLinkingOnLoginSelected(const QModelIndex &srcIndex); - QString processMultipleDomainsInput(const QString& service, const QString &domains); + QString processMultipleDomainsInput(const QString& service, const QString &domains, const bool disable_tld_check); bool isUICategoryClean() const; @@ -176,6 +178,7 @@ static constexpr int MINI_PASSWORD_LENGTH = 31; static constexpr int BLE_PASSWORD_LENGTH = 64; static constexpr char MULT_DOMAIN_SEPARATOR = ','; + static const QString INVALID_DOMAIN_TEXT; signals: void wantEnterMemMode(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.ui new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.ui --- old/moolticute-1.00.1.r0.gf211d93/src/CredentialsManagement.ui 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/CredentialsManagement.ui 2023-02-05 21:17:46.000000000 +0100 @@ -54,14 +54,14 @@ </widget> </item> <item row="1" column="1"> - <widget class="QLineEdit" name="addCredLoginInput"> + <widget class="SimpleLineEdit" name="addCredLoginInput"> <property name="maxLength"> <number>62</number> </property> </widget> </item> <item row="1" column="0"> - <widget class="QLineEdit" name="addCredServiceInput"> + <widget class="SimpleLineEdit" name="addCredServiceInput"> <property name="maxLength"> <number>57</number> </property> @@ -1020,6 +1020,11 @@ </customwidget> <customwidget> <class>LockedPasswordLineEdit</class> + <extends>SimpleLineEdit</extends> + <header>PasswordLineEdit.h</header> + </customwidget> + <customwidget> + <class>SimpleLineEdit</class> <extends>QLineEdit</extends> <header>PasswordLineEdit.h</header> </customwidget> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/DeviceDetector.h new/moolticute-1.01.0.r0.g77100ea/src/DeviceDetector.h --- old/moolticute-1.00.1.r0.gf211d93/src/DeviceDetector.h 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/DeviceDetector.h 2023-02-05 21:17:46.000000000 +0100 @@ -40,6 +40,9 @@ void shiftPressed() { m_isShiftPressed = true; } void shiftReleased() { m_isShiftPressed = false; } bool isShiftPressed() const { return m_isShiftPressed; } + void ctrlPressed() { m_isCtrlPressed = true; } + void ctrlReleased() { m_isCtrlPressed = false; } + bool isCtrlPressed() const { return m_isCtrlPressed; } signals: void deviceChanged(Common::MPHwVersion newDevType); @@ -53,6 +56,7 @@ bool m_isConnectedWithBluetooth = false; quint8 m_battery = 0; bool m_isShiftPressed = false; + bool m_isCtrlPressed = false; }; #endif // DEVICEDETECTOR_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/FilesManagement.cpp new/moolticute-1.01.0.r0.g77100ea/src/FilesManagement.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/FilesManagement.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/FilesManagement.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -578,7 +578,8 @@ //Force all service names to lowercase service = service.toLower(); - qint64 maxSize = MP_MAX_FILE_SIZE; + // For BLE increase max file size to 20kB + qint64 maxSize = DeviceDetector::instance().isBle() ? 2*MP_MAX_FILE_SIZE : MP_MAX_FILE_SIZE; if (service == MC_SSH_SERVICE) maxSize = MP_MAX_SSH_SIZE; QFileInfo fi(filename); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MPDevice.cpp new/moolticute-1.01.0.r0.g77100ea/src/MPDevice.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/MPDevice.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MPDevice.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -4917,7 +4917,7 @@ if (!isBLE()) { currentDataNode.resize(MP_DATA_HEADER_SIZE); - qToBigEndian(nodeData.size(), (quint8 *)currentDataNode.data()); + qToBigEndian<quint32>(nodeData.size(), (quint8 *)currentDataNode.data()); } currentDataNode.append(nodeData); @@ -6739,7 +6739,7 @@ /* Create new node with null address and virtual address set to our counter value */ MPNode* newNodePt = pMesProt->createMPNode(QByteArray(getParentNodeSize(), 0), this, QByteArray(), newAddressesNeededCounter); newNodePt->setType(MPNode::NodeParent); - newNodePt->setLoginNodeData(importNodes[i]->getNodeFlags(), importNodes[i]->getLoginNodeData()); + newNodePt->setDataNodeData(importNodes[i]->getNodeFlags(), importNodes[i]->getDataNodeData()); newNodePt->setMergeTagged(); /* Add node to list */ @@ -6936,62 +6936,16 @@ } } - /* Now we check all our parents and childs for non merge tag */ - QListIterator<MPNode*> j(dataNodes); - while (j.hasNext()) + if (!finishImportDataNodes(stringError, Common::DATA_ADDR_IDX)) { - MPNode* nodeItem = j.next(); - - /* No need to check for merge tagged for parent, as it'll automatically be removed if it doesn't have any child */ - QByteArray curChildNodeAddr = nodeItem->getStartChildAddress(); - bool deleteDataNode = false; - - /* Special case: no child */ - if (curChildNodeAddr == MPNode::EmptyAddress) - { - /* Remove parent */ - qDebug() << "Empty data parent " << nodeItem->getService() << " detected, deleting it..."; - removeEmptyParentFromDB(nodeItem, true, Common::CRED_ADDR_IDX, Common::DATA_ADDR_IDX); - } - - /* Check every children */ - while (curChildNodeAddr != MPNode::EmptyAddress) - { - MPNode* curNode = findNodeWithAddressInList(dataChildNodes, curChildNodeAddr); - - /* Safety checks */ - if (!curNode) - { - qCritical() << "Couldn't find child node in list (error in algo?)"; - stringError = "Moolticute Internal Error: Please Contact The Team (IFM#2)"; - cleanImportedVars(); - return false; - } - - /* Next item */ - curChildNodeAddr = curNode->getNextDataAddress(); - - /* Marked for deletion? */ - if (!curNode->getMergeTagged()) - { - /* First child? */ - if (curNode->getAddress() == nodeItem->getStartChildAddress()) - { - deleteDataNode = true; - } - - /* Delete child */ - dataChildNodes.removeOne(curNode); - nodeItem->removeChild(curNode); - delete(curNode); - } - } + return false; + } - /* If parent node is marked for deletion */ - if(deleteDataNode) + if (isBLE()) + { + if (!finishImportDataNodes(stringError, Common::NOTE_ADDR_IDX)) { - nodeItem->setStartChildAddress(MPNode::EmptyAddress); - removeEmptyParentFromDB(nodeItem, true); + return false; } } } @@ -7116,6 +7070,72 @@ } } return true; +} + +bool MPDevice::finishImportDataNodes(QString &stringError, Common::DataAddressType addrType) +{ + const bool isFile = Common::DATA_ADDR_IDX == addrType; + NodeList& nodes = isFile ? dataNodes : notesLoginNodes; + NodeList& childNodes = isFile? dataChildNodes : notesLoginChildNodes; + /* Now we check all our parents and childs for non merge tag */ + QListIterator<MPNode*> j(nodes); + while (j.hasNext()) + { + MPNode* nodeItem = j.next(); + + /* No need to check for merge tagged for parent, as it'll automatically be removed if it doesn't have any child */ + QByteArray curChildNodeAddr = nodeItem->getStartChildAddress(); + bool deleteDataNode = false; + + /* Special case: no child */ + if (curChildNodeAddr == MPNode::EmptyAddress) + { + /* Remove parent */ + qDebug() << "Empty data parent " << nodeItem->getService() << " detected, deleting it..."; + removeEmptyParentFromDB(nodeItem, true, Common::CRED_ADDR_IDX /*not used*/, addrType); + } + + /* Check every children */ + while (curChildNodeAddr != MPNode::EmptyAddress) + { + MPNode* curNode = findNodeWithAddressInList(childNodes, curChildNodeAddr); + + /* Safety checks */ + if (!curNode) + { + qCritical() << "Couldn't find child node in list (error in algo?)"; + stringError = "Moolticute Internal Error: Please Contact The Team (IFM#2)"; + cleanImportedVars(); + return false; + } + + /* Next item */ + curChildNodeAddr = curNode->getNextDataAddress(); + + /* Marked for deletion? */ + if (!curNode->getMergeTagged()) + { + /* First child? */ + if (curNode->getAddress() == nodeItem->getStartChildAddress()) + { + deleteDataNode = true; + } + + /* Delete child */ + childNodes.removeOne(curNode); + nodeItem->removeChild(curNode); + delete(curNode); + } + } + + /* If parent node is marked for deletion */ + if(deleteDataNode) + { + nodeItem->setStartChildAddress(MPNode::EmptyAddress); + removeEmptyParentFromDB(nodeItem, true, Common::CRED_ADDR_IDX /*not used*/, Common::NOTE_ADDR_IDX); + } + } + return true; } void MPDevice::loadFreeAddresses(AsyncJobs *jobs, const QByteArray &addressFrom, bool discardFirstAddr, const MPDeviceProgressCb &cbProgress) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MPDevice.h new/moolticute-1.01.0.r0.g77100ea/src/MPDevice.h --- old/moolticute-1.00.1.r0.gf211d93/src/MPDevice.h 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MPDevice.h 2023-02-05 21:17:46.000000000 +0100 @@ -329,6 +329,7 @@ void deletePossibleFavorite(QByteArray parentAddr, QByteArray childAddr); bool finishImportFileMerging(QString &stringError, bool noDelete); bool finishImportLoginNodes(QString &stringError, Common::AddressType addrType); + bool finishImportDataNodes(QString &stringError, Common::DataAddressType addrType); QByteArray getNextNodeAddressInMemory(const QByteArray &address); quint16 getFlashPageFromAddress(const QByteArray &address); MPNode *findNodeWithServiceInList(const QString &service, Common::AddressType addrType = Common::CRED_ADDR_IDX); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MPDeviceBleImpl.cpp new/moolticute-1.01.0.r0.g77100ea/src/MPDeviceBleImpl.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/MPDeviceBleImpl.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MPDeviceBleImpl.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -23,7 +23,8 @@ MPCmd::CANCEL_USER_REQUEST, MPCmd::INFORM_LOCKED, MPCmd::INFORM_UNLOCKED, - MPCmd::SET_DATE}; + MPCmd::SET_DATE + }; } bool MPDeviceBleImpl::isFirstPacket(const QByteArray &data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.cpp new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -29,7 +29,6 @@ #include "DeviceDetector.h" #include "SystemNotifications/SystemNotification.h" -#include "qtcsv/stringdata.h" #include "qtcsv/reader.h" const QString MainWindow::NONE_STRING = tr("None"); @@ -40,7 +39,7 @@ const QString MainWindow::MANUAL_STRING = "<a href=\"%1\">" + tr("User Manual") + "</a>"; const QString MainWindow::BLE_MANUAL_URL = "https://raw.githubusercontent.com/mooltipass/minible/master/MooltipassMiniBLEUserManual.pdf"; const QString MainWindow::MINI_MANUAL_URL = "https://raw.githubusercontent.com/limpkin/mooltipass/master/user_manual_mini.pdf"; -const QString MainWindow::BUNDLE_OUTDATED_TEXT = tr("New bundle update available <a href=\"https://www.themooltipass.com/updates/index.php?sn=%1&bundlev=%2\">here.</a>"); +const QString MainWindow::BUNDLE_OUTDATED_TEXT = tr("Bundle v%1 is available <a href=\"https://www.themooltipass.com/updates/index.php?sn=%2&bundlev=%3\">here</a>"); const QString MainWindow::SERIAL_STR_START = "MOOLTIP"; void MainWindow::initHelpLabels() @@ -167,9 +166,6 @@ ui->pushButtonNotes->setVisible(false); unsigned int keyModifiers = Qt::SHIFT; -#ifndef Q_OS_MACOS - keyModifiers |= Qt::CTRL; -#endif m_FilesAndSSHKeysTabsShortcut = new QShortcut(QKeySequence(keyModifiers | Qt::Key_F1), this); setKeysTabVisibleOnDemand(bSSHKeysTabVisibleOnDemand); @@ -294,15 +290,23 @@ [this]() { ui->lineEdit_AvailableUsers->setText(""); + m_firstBatteryPctReceived = BatteryNotiStatus::NO_STATUS; }); connect(wsClient, &WSClient::updateBatteryPercent, [this](int battery) { DeviceDetector::instance().setBattery(battery); ui->pbBleBattery->setValue(battery); - if (battery < BATTERY_WARNING_LIMIT && !ui->label_charging->isVisible()) + if (battery < BATTERY_WARNING_LIMIT && !ui->label_charging->isVisible() && + BatteryNotiStatus::VALID_BATTERY_RECIEVED == m_firstBatteryPctReceived) { SystemNotification::instance().createNotification(tr("Low Battery"), tr("Battery is below %1%, please charge your Mooltipass.").arg(BATTERY_WARNING_LIMIT)); + m_firstBatteryPctReceived = BatteryNotiStatus::LOW_BATTERY_DISPLAYED; + } + // Only display low battery warning after we received a valid battery pct + if (BatteryNotiStatus::NO_STATUS == m_firstBatteryPctReceived) + { + m_firstBatteryPctReceived = BatteryNotiStatus::VALID_BATTERY_RECIEVED; } }); @@ -316,6 +320,7 @@ else { ui->label_charging->hide(); + m_firstBatteryPctReceived = BatteryNotiStatus::NO_STATUS; } }); @@ -504,7 +509,7 @@ { QString bundleStr = QString::number(wsClient->get_bundleVersion()); setSecurityChallengeText(serialStr, bundleStr); - ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(serial).arg(bundleStr)); + ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(Common::BLE_LATEST_BUNDLE_VERSION).arg(serial).arg(bundleStr)); } else { @@ -514,7 +519,7 @@ connect(wsClient, &WSClient::bundleVersionChanged, [this](int bundleVersion) { auto serial = wsClient->get_hwSerial(); - ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(serial).arg(bundleVersion)); + ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(Common::BLE_LATEST_BUNDLE_VERSION).arg(serial).arg(bundleVersion)); if (wsClient->isMPBLE()) { QString serialStr = serial > 0 ? QString::number(serial) : "XXXX"; @@ -659,6 +664,7 @@ //Check is ssh agent opt has to be checked ui->checkBoxSSHAgent->setChecked(s.value("settings/auto_start_ssh").toBool()); + ui->checkBoxTLDCheck->setChecked(s.value("settings/disable_tld_check").toBool()); ui->lineEditSshArgs->setText(s.value("settings/ssh_args").toString()); ui->scrollArea->setStyleSheet("QScrollArea { background-color:transparent; }"); @@ -685,6 +691,8 @@ ui->labelBundleOutdatedWarning->hide(); ui->labelBundleOutdatedWarning->setPixmap(AppGui::qtAwesome()->icon(fa::warning).pixmap(QSize(20, 20))); + ui->labelBundleOutdatedWarning2->hide(); + ui->labelBundleOutdatedWarning2->setPixmap(AppGui::qtAwesome()->icon(fa::warning).pixmap(QSize(20, 20))); ui->labelBundleOutdatedText->hide(); ui->labelBundleOutdatedText->setTextFormat(Qt::RichText); ui->labelBundleOutdatedText->setTextInteractionFlags(Qt::TextBrowserInteraction); @@ -1412,7 +1420,7 @@ dialogLog->appendData(logdata); logBuffer.append(logdata); - const int maxsz = 100 * 1024; + const int maxsz = 1000 * 1024; if (logBuffer.size() > maxsz) logBuffer = logBuffer.right(maxsz); @@ -1456,6 +1464,12 @@ s.setValue("settings/auto_start_ssh", ui->checkBoxSSHAgent->isChecked()); } +void MainWindow::on_checkBoxTLDCheck_stateChanged(int) +{ + QSettings s; + s.setValue("settings/disable_tld_check", ui->checkBoxTLDCheck->isChecked()); +} + void MainWindow::on_pushButtonExportFile_clicked() { wsClient->exportDbFile(Common::SIMPLE_CRYPT); @@ -1549,6 +1563,7 @@ if (wsClient->isMPBLE()) { wsClient->sendGetUserCategories(); + wsClient->sendFetchNotes(); } QMessageBox::information(this, tr("Moolticute"), tr("Successfully imported and merged database into the device.")); } @@ -1838,14 +1853,16 @@ ui->pushButtonNotes->setVisible(wsClient->get_bundleVersion() >= 1); if (wsClient->get_bundleVersion() < Common::BLE_LATEST_BUNDLE_VERSION) { - ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(wsClient->get_hwSerial()).arg(wsClient->get_bundleVersion())); + ui->labelBundleOutdatedText->setText(BUNDLE_OUTDATED_TEXT.arg(Common::BLE_LATEST_BUNDLE_VERSION).arg(wsClient->get_hwSerial()).arg(wsClient->get_bundleVersion())); ui->labelBundleOutdatedText->show(); ui->labelBundleOutdatedWarning->show(); + ui->labelBundleOutdatedWarning2->show(); } else { ui->labelBundleOutdatedText->hide(); ui->labelBundleOutdatedWarning->hide(); + ui->labelBundleOutdatedWarning2->hide(); } } else @@ -1854,6 +1871,7 @@ ui->labelBundleVersionValue->hide(); ui->labelBundleOutdatedText->hide(); ui->labelBundleOutdatedWarning->hide(); + ui->labelBundleOutdatedWarning2->hide(); } } @@ -2389,10 +2407,15 @@ void MainWindow::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Control) + QMainWindow::keyPressEvent(event); + if (event->key() == Qt::Key_Shift) { DeviceDetector::instance().shiftPressed(); } + if (event->key() == Qt::Key_Control) + { + DeviceDetector::instance().ctrlPressed(); + } if (!ui->tutorialWidget->isTutorialFinished() && event->key() == Qt::Key_Escape) { ui->tutorialWidget->onExitClicked(); @@ -2401,10 +2424,15 @@ void MainWindow::keyReleaseEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Control) + QMainWindow::keyReleaseEvent(event); + if (event->key() == Qt::Key_Shift) { DeviceDetector::instance().shiftReleased(); } + if (event->key() == Qt::Key_Control) + { + DeviceDetector::instance().ctrlReleased(); + } } void MainWindow::on_checkBoxBackupNotification_stateChanged(int) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.h new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.h --- old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.h 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.h 2023-02-05 21:17:46.000000000 +0100 @@ -128,6 +128,7 @@ void on_pushButtonAutoStart_clicked(); void on_checkBoxSSHAgent_stateChanged(int arg1); + void on_checkBoxTLDCheck_stateChanged(int arg1); void on_pushButtonExportFile_clicked(); void on_pushButtonImportFile_clicked(); @@ -302,6 +303,15 @@ bool m_notesFetched = false; + enum class BatteryNotiStatus + { + NO_STATUS, + VALID_BATTERY_RECIEVED, + LOW_BATTERY_DISPLAYED + }; + + BatteryNotiStatus m_firstBatteryPctReceived = BatteryNotiStatus::NO_STATUS; + bool m_computerUnlocked = true; struct LockUnlockItem { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.ui new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.ui --- old/moolticute-1.00.1.r0.gf211d93/src/MainWindow.ui 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/MainWindow.ui 2023-02-05 21:17:46.000000000 +0100 @@ -3535,6 +3535,18 @@ </widget> </item> <item> + <widget class="QLabel" name="labelBundleOutdatedWarning2"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer_58"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -4051,6 +4063,37 @@ </property> </widget> </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_15"> + <item> + <widget class="QLabel" name="label_27"> + <property name="text"> + <string>Allow to use invalid or private TLDs</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_63"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="checkBoxTLDCheck"> + <property name="text"> + <string>Disable TLD check</string> + </property> + </widget> + </item> </layout> </item> <item> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/PasswordLineEdit.cpp new/moolticute-1.01.0.r0.g77100ea/src/PasswordLineEdit.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/PasswordLineEdit.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/PasswordLineEdit.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -48,7 +48,7 @@ "}" PasswordLineEdit::PasswordLineEdit(QWidget* parent): - QLineEdit(parent), + SimpleLineEdit(parent), m_passwordProfilesModel(nullptr), m_passwordOptionsPopup(nullptr) @@ -515,3 +515,17 @@ addAction(pwdAction, QLineEdit::TrailingPosition); } } + +SimpleLineEdit::SimpleLineEdit(QWidget *parent) + : QLineEdit{parent} +{ + +} + +void SimpleLineEdit::keyReleaseEvent(QKeyEvent *event) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QLineEdit::keyReleaseEvent(event); +#endif + QWidget::keyReleaseEvent(event); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/PasswordLineEdit.h new/moolticute-1.01.0.r0.g77100ea/src/PasswordLineEdit.h --- old/moolticute-1.00.1.r0.gf211d93/src/PasswordLineEdit.h 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/PasswordLineEdit.h 2023-02-05 21:17:46.000000000 +0100 @@ -70,7 +70,24 @@ class PasswordOptionsPopup; -class PasswordLineEdit : public QLineEdit + +/** + * @brief The SimpleLineEdit class + * keyReleaseEvent is overwritten for QLineEdit in Qt6, but overwritten + * parent function is not called, so event is not delegated from QLineEdit, + * to fix this we call keyReleaseEvent for parent (QWidget) here. + */ +class SimpleLineEdit : public QLineEdit +{ + Q_OBJECT +public: + SimpleLineEdit(QWidget* parent = nullptr); + +protected: + virtual void keyReleaseEvent(QKeyEvent *event) override; +}; + +class PasswordLineEdit : public SimpleLineEdit { Q_OBJECT public: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/moolticute-1.00.1.r0.gf211d93/src/WSServerCon.cpp new/moolticute-1.01.0.r0.g77100ea/src/WSServerCon.cpp --- old/moolticute-1.00.1.r0.gf211d93/src/WSServerCon.cpp 2022-12-01 00:09:56.000000000 +0100 +++ new/moolticute-1.01.0.r0.g77100ea/src/WSServerCon.cpp 2023-02-05 21:17:46.000000000 +0100 @@ -401,7 +401,8 @@ return; } - int maxSize = MP_MAX_FILE_SIZE; + // For BLE increase max file size to 20kB + int maxSize = mpdevice->isBLE() ? 2*MP_MAX_FILE_SIZE : MP_MAX_FILE_SIZE; if (service.toLower() == MC_SSH_SERVICE) maxSize = MP_MAX_SSH_SIZE; if (data.size() > maxSize)