mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-27 16:29:44 -05:00
Merge branch 'develop' into feature/yubikey
This commit is contained in:
commit
7eb7dbe0be
@ -3,22 +3,23 @@
|
|||||||
[![Travis Build Status](https://travis-ci.org/keepassxreboot/keepassxc.svg?branch=develop)](https://travis-ci.org/keepassxreboot/keepassxc) [![Coverage Status](https://coveralls.io/repos/github/keepassxreboot/keepassxc/badge.svg)](https://coveralls.io/github/keepassxreboot/keepassxc)
|
[![Travis Build Status](https://travis-ci.org/keepassxreboot/keepassxc.svg?branch=develop)](https://travis-ci.org/keepassxreboot/keepassxc) [![Coverage Status](https://coveralls.io/repos/github/keepassxreboot/keepassxc/badge.svg)](https://coveralls.io/github/keepassxreboot/keepassxc)
|
||||||
|
|
||||||
## About
|
## About
|
||||||
KeePassXC is a fork of [KeePassX](https://www.keepassx.org/) that [aims to incorporate stalled pull requests, features, and bug fixes that have never made it into the main KeePassX repository](https://github.com/keepassxreboot/keepassx/issues/43).
|
KeePassXC is a community fork of [KeePassX](https://www.keepassx.org/) with the goal to extend and improve it with new features and bugfixes to provide a feature-rich, fully cross-platform and modern open-source password manager.
|
||||||
|
|
||||||
|
|
||||||
## Additional features compared to KeePassX
|
## Additional features compared to KeePassX
|
||||||
- Autotype on all three major platforms (Linux, Windows, OS X)
|
- Auto-Type on all three major platforms (Linux, Windows, OS X)
|
||||||
- Stand-alone password generator
|
- Stand-alone password generator
|
||||||
- Password strength meter
|
- Password strength meter
|
||||||
- Use website's favicons as entry icons
|
- Using website favicons as entry icons
|
||||||
- Merging of databases
|
- Merging of databases
|
||||||
- Automatic reload when the database changed on disk
|
- Automatic reload when the database changed on disk
|
||||||
- KeePassHTTP support for use with [PassIFox](https://addons.mozilla.org/en-us/firefox/addon/passifox/) in Mozilla Firefox and [chromeIPass](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) in Google Chrome or Chromium.
|
- KeePassHTTP support for use with [PassIFox](https://addons.mozilla.org/en-us/firefox/addon/passifox/) in Mozilla Firefox and [chromeIPass](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) in Google Chrome or Chromium.
|
||||||
|
- Many bug fixes
|
||||||
|
|
||||||
For a full list of features and changes, read the [CHANGELOG](CHANGELOG) document.
|
For a full list of features and changes, read the [CHANGELOG](CHANGELOG) document.
|
||||||
|
|
||||||
### Note about KeePassHTTP
|
### Note about KeePassHTTP
|
||||||
KeePassHTTP is not a highly secure protocol and has certain flaw which allow an attacker to decrypt your passwords when they manage to intercept communication between a KeePassHTTP server and PassIFox/chromeIPass over a network connection (see [here](https://github.com/pfn/keepasshttp/issues/258) and [here](https://github.com/keepassxreboot/keepassxc/issues/147)). KeePassXC therefore strictly limits communication between itself and the browser plugin to your local computer. As long as your computer is not compromised, your passwords are fairly safe that way, but still use it at your own risk!
|
KeePassHTTP is not a highly secure protocol and has certain flaw which allow an attacker to decrypt your passwords when they manage to intercept communication between a KeePassHTTP server and PassIFox/chromeIPass over a network connection (see [here](https://github.com/pfn/keepasshttp/issues/258) and [here](https://github.com/keepassxreboot/keepassxc/issues/147)). KeePassXC therefore strictly limits communication between itself and the browser plugin to your local computer. As long as your computer is not compromised, your passwords are fairly safe that way, but use it at your own risk!
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
Pre-compiled binaries can be found on the [downloads page](https://keepassxc.org/download). Additionally, individual Linux distributions may ship their own versions, so please check out your distribution's package list to see if KeePassXC is available.
|
Pre-compiled binaries can be found on the [downloads page](https://keepassxc.org/download). Additionally, individual Linux distributions may ship their own versions, so please check out your distribution's package list to see if KeePassXC is available.
|
||||||
|
@ -166,7 +166,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw,
|
|||||||
msgBox.setIcon(QMessageBox::Question);
|
msgBox.setIcon(QMessageBox::Question);
|
||||||
msgBox.addButton(QMessageBox::Yes);
|
msgBox.addButton(QMessageBox::Yes);
|
||||||
msgBox.addButton(QMessageBox::No);
|
msgBox.addButton(QMessageBox::No);
|
||||||
auto readOnlyButton = msgBox.addButton(tr("Open read-only"), QMessageBox::AcceptRole);
|
auto readOnlyButton = msgBox.addButton(tr("Open read-only"), QMessageBox::NoRole);
|
||||||
msgBox.setDefaultButton(readOnlyButton);
|
msgBox.setDefaultButton(readOnlyButton);
|
||||||
msgBox.setEscapeButton(QMessageBox::No);
|
msgBox.setEscapeButton(QMessageBox::No);
|
||||||
auto result = msgBox.exec();
|
auto result = msgBox.exec();
|
||||||
|
@ -273,50 +273,74 @@ void EditWidgetIcons::removeCustomIcon()
|
|||||||
QModelIndex index = m_ui->customIconsView->currentIndex();
|
QModelIndex index = m_ui->customIconsView->currentIndex();
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
Uuid iconUuid = m_customIconModel->uuidFromIndex(index);
|
Uuid iconUuid = m_customIconModel->uuidFromIndex(index);
|
||||||
int iconUsedCount = 0;
|
|
||||||
|
|
||||||
const QList<Entry*> allEntries = m_database->rootGroup()->entriesRecursive(true);
|
const QList<Entry*> allEntries = m_database->rootGroup()->entriesRecursive(true);
|
||||||
|
QList<Entry*> entriesWithSameIcon;
|
||||||
QList<Entry*> historyEntriesWithSameIcon;
|
QList<Entry*> historyEntriesWithSameIcon;
|
||||||
|
|
||||||
for (Entry* entry : allEntries) {
|
for (Entry* entry : allEntries) {
|
||||||
bool isHistoryEntry = !entry->group();
|
|
||||||
if (iconUuid == entry->iconUuid()) {
|
if (iconUuid == entry->iconUuid()) {
|
||||||
if (isHistoryEntry) {
|
// Check if this is a history entry (no assigned group)
|
||||||
|
if (!entry->group()) {
|
||||||
historyEntriesWithSameIcon << entry;
|
historyEntriesWithSameIcon << entry;
|
||||||
}
|
} else if (m_currentUuid != entry->uuid()) {
|
||||||
else if (m_currentUuid != entry->uuid()) {
|
entriesWithSameIcon << entry;
|
||||||
iconUsedCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<Group*> allGroups = m_database->rootGroup()->groupsRecursive(true);
|
const QList<Group*> allGroups = m_database->rootGroup()->groupsRecursive(true);
|
||||||
for (const Group* group : allGroups) {
|
QList<Group*> groupsWithSameIcon;
|
||||||
|
|
||||||
|
for (Group* group : allGroups) {
|
||||||
if (iconUuid == group->iconUuid() && m_currentUuid != group->uuid()) {
|
if (iconUuid == group->iconUuid() && m_currentUuid != group->uuid()) {
|
||||||
iconUsedCount++;
|
groupsWithSameIcon << group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconUsedCount == 0) {
|
int iconUseCount = entriesWithSameIcon.size() + groupsWithSameIcon.size();
|
||||||
for (Entry* entry : asConst(historyEntriesWithSameIcon)) {
|
if (iconUseCount > 0) {
|
||||||
entry->setUpdateTimeinfo(false);
|
QMessageBox::StandardButton ans = MessageBox::question(this, tr("Confirm Delete"),
|
||||||
entry->setIcon(0);
|
tr("This icon is used by %1 entries, and will be replaced "
|
||||||
entry->setUpdateTimeinfo(true);
|
"by the default icon. Are you sure you want to delete it?")
|
||||||
}
|
.arg(iconUseCount), QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
m_database->metadata()->removeCustomIcon(iconUuid);
|
if (ans == QMessageBox::No) {
|
||||||
m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(),
|
// Early out, nothing is changed
|
||||||
m_database->metadata()->customIconsOrder());
|
return;
|
||||||
if (m_customIconModel->rowCount() > 0) {
|
} else {
|
||||||
m_ui->customIconsView->setCurrentIndex(m_customIconModel->index(0, 0));
|
// Revert matched entries to the default entry icon
|
||||||
}
|
for (Entry* entry : asConst(entriesWithSameIcon)) {
|
||||||
else {
|
entry->setIcon(Entry::DefaultIconNumber);
|
||||||
updateRadioButtonDefaultIcons();
|
}
|
||||||
|
|
||||||
|
// Revert matched groups to the default group icon
|
||||||
|
for (Group* group : asConst(groupsWithSameIcon)) {
|
||||||
|
group->setIcon(Group::DefaultIconNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Q_EMIT messageEditEntry(
|
|
||||||
tr("Can't delete icon. Still used by %1 items.").arg(iconUsedCount), MessageWidget::Error);
|
// Remove the icon from history entries
|
||||||
|
for (Entry* entry : asConst(historyEntriesWithSameIcon)) {
|
||||||
|
entry->setUpdateTimeinfo(false);
|
||||||
|
entry->setIcon(0);
|
||||||
|
entry->setUpdateTimeinfo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the icon from the database
|
||||||
|
m_database->metadata()->removeCustomIcon(iconUuid);
|
||||||
|
m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(),
|
||||||
|
m_database->metadata()->customIconsOrder());
|
||||||
|
|
||||||
|
// Reset the current icon view
|
||||||
|
updateRadioButtonDefaultIcons();
|
||||||
|
|
||||||
|
if (m_database->resolveEntry(m_currentUuid) != nullptr) {
|
||||||
|
m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Entry::DefaultIconNumber));
|
||||||
|
} else {
|
||||||
|
m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Group::DefaultIconNumber));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,6 +301,10 @@ MainWindow::MainWindow()
|
|||||||
connect(m_ui->welcomeWidget, SIGNAL(importKeePass1Database()), SLOT(switchToKeePass1Database()));
|
connect(m_ui->welcomeWidget, SIGNAL(importKeePass1Database()), SLOT(switchToKeePass1Database()));
|
||||||
|
|
||||||
connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(showAboutDialog()));
|
connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(showAboutDialog()));
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
setUnifiedTitleAndToolBarOnMac(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
connect(m_ui->tabWidget, SIGNAL(messageGlobal(QString,MessageWidget::MessageType)), this, SLOT(displayGlobalMessage(QString, MessageWidget::MessageType)));
|
connect(m_ui->tabWidget, SIGNAL(messageGlobal(QString,MessageWidget::MessageType)), this, SLOT(displayGlobalMessage(QString, MessageWidget::MessageType)));
|
||||||
connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage()));
|
connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage()));
|
||||||
|
@ -110,7 +110,7 @@ static QByteArray encrypt2(const QByteArray & data, SymmetricCipherGcrypt & ciph
|
|||||||
//Encrypt
|
//Encrypt
|
||||||
QByteArray buffer = data + QByteArray(paddingSize, paddingSize);
|
QByteArray buffer = data + QByteArray(paddingSize, paddingSize);
|
||||||
cipher.reset();
|
cipher.reset();
|
||||||
cipher.processInPlace(buffer);
|
Q_UNUSED(cipher.processInPlace(buffer));
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ typedef int (*http_cb) (http_parser*);
|
|||||||
|
|
||||||
|
|
||||||
/* Status Codes */
|
/* Status Codes */
|
||||||
#define HTTP_STATUS_MAP(XX) \
|
#define HTTPPARSER_HTTP_STATUS_MAP(XX) \
|
||||||
XX(100, CONTINUE, Continue) \
|
XX(100, CONTINUE, Continue) \
|
||||||
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
||||||
XX(102, PROCESSING, Processing) \
|
XX(102, PROCESSING, Processing) \
|
||||||
@ -150,12 +150,12 @@ typedef int (*http_cb) (http_parser*);
|
|||||||
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
||||||
XX(508, LOOP_DETECTED, Loop Detected) \
|
XX(508, LOOP_DETECTED, Loop Detected) \
|
||||||
XX(510, NOT_EXTENDED, Not Extended) \
|
XX(510, NOT_EXTENDED, Not Extended) \
|
||||||
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
|
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required)
|
||||||
|
|
||||||
enum http_status
|
enum http_status
|
||||||
{
|
{
|
||||||
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
||||||
HTTP_STATUS_MAP(XX)
|
HTTPPARSER_HTTP_STATUS_MAP(XX)
|
||||||
#undef XX
|
#undef XX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
if ( !icollectRequired ) // not allowed to collect data
|
if ( !icollectRequired ) // not allowed to collect data
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int newLength = icollectedData.length() + (int) length;
|
int newLength = icollectedData.length() + static_cast<int>(length);
|
||||||
|
|
||||||
if ( icollectCapacity > 0 && newLength > icollectCapacity )
|
if ( icollectCapacity > 0 && newLength > icollectCapacity )
|
||||||
return false; // the capacity is full
|
return false; // the capacity is full
|
||||||
|
@ -112,7 +112,7 @@ protected:
|
|||||||
void onReadyRead() {
|
void onReadyRead() {
|
||||||
while ( isocket.bytesAvailable() > 0 ) {
|
while ( isocket.bytesAvailable() > 0 ) {
|
||||||
char buffer[4097] = {0};
|
char buffer[4097] = {0};
|
||||||
size_t readLength = (size_t) isocket.readRaw(buffer, 4096);
|
size_t readLength = static_cast<size_t>(isocket.readRaw(buffer, 4096));
|
||||||
|
|
||||||
parse(buffer, readLength);
|
parse(buffer, readLength);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
// if it's a QLocalServer
|
// if it's a QLocalServer
|
||||||
virtual void incomingConnection(quintptr socketDescriptor) {
|
virtual void incomingConnection(quintptr socketDescriptor) {
|
||||||
iserver->incomingConnection((qintptr) socketDescriptor);
|
iserver->incomingConnection(static_cast<qintptr>(socketDescriptor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public:
|
|||||||
void onReadyRead() {
|
void onReadyRead() {
|
||||||
while ( isocket.bytesAvailable() > 0 ) {
|
while ( isocket.bytesAvailable() > 0 ) {
|
||||||
char buffer[4097] = {0};
|
char buffer[4097] = {0};
|
||||||
size_t readLength = (size_t) isocket.readRaw(buffer, 4096);
|
size_t readLength = static_cast<size_t>(isocket.readRaw(buffer, 4096));
|
||||||
|
|
||||||
parse(buffer, readLength);
|
parse(buffer, readLength);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace qhttp {
|
|||||||
# error "to compile QHttp classes, Qt 5.0 or later is needed."
|
# error "to compile QHttp classes, Qt 5.0 or later is needed."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HTTP_STATUS_MAP(XX) \
|
#define QHTTPABSTRACTS_HTTP_STATUS_MAP(XX) \
|
||||||
XX(100, "Continue") \
|
XX(100, "Continue") \
|
||||||
XX(101, "Switching Protocols") \
|
XX(101, "Switching Protocols") \
|
||||||
/* RFC 2518) obsoleted by RFC 4918 */ \
|
/* RFC 2518) obsoleted by RFC 4918 */ \
|
||||||
@ -78,7 +78,7 @@ static struct {
|
|||||||
int code;
|
int code;
|
||||||
const char* message;
|
const char* message;
|
||||||
} g_status_codes[] {
|
} g_status_codes[] {
|
||||||
HTTP_STATUS_MAP(PATCH_STATUS_CODES)
|
QHTTPABSTRACTS_HTTP_STATUS_MAP(PATCH_STATUS_CODES)
|
||||||
};
|
};
|
||||||
#undef PATCH_STATUS_CODES
|
#undef PATCH_STATUS_CODES
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user