diff --git a/src/plugins/GnomeKeyringPasswords/gnomekeyringpasswordbackend.cpp b/src/plugins/GnomeKeyringPasswords/gnomekeyringpasswordbackend.cpp index 9b877f23..e027b319 100644 --- a/src/plugins/GnomeKeyringPasswords/gnomekeyringpasswordbackend.cpp +++ b/src/plugins/GnomeKeyringPasswords/gnomekeyringpasswordbackend.cpp @@ -1,277 +1,304 @@ /* ============================================================ * GnomeKeyringPasswords - gnome-keyring support plugin for Falkon * Copyright (C) 2013-2014 David Rosca * * 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 3 of the License, or * (at your option) any later version. * * 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 "gnomekeyringpasswordbackend.h" #include "gnomekeyringplugin.h" #include extern "C" { #include "gnome-keyring.h" } static PasswordEntry createEntry(GnomeKeyringFound* item) { PasswordEntry entry; entry.id = item->item_id; entry.password = QString::fromUtf8(item->secret); for (unsigned i = 0; i < item->attributes->len; ++i) { GnomeKeyringAttribute attr = g_array_index(item->attributes, GnomeKeyringAttribute, i); if (strcmp(attr.name, "host") == 0) { entry.host = QString::fromUtf8(attr.value.string); } else if (strcmp(attr.name, "username") == 0) { entry.username = QString::fromUtf8(attr.value.string); } else if (strcmp(attr.name, "data") == 0) { entry.data = attr.value.string; } else if (strcmp(attr.name, "updated") == 0) { entry.updated = attr.value.integer; } } entry.data.replace(QByteArray("___PASSWORD-VALUE___"), PasswordManager::urlEncodePassword(entry.password)); return entry; } static GnomeKeyringAttributeList* createAttributes(const PasswordEntry &entry) { GnomeKeyringAttributeList* attributes = gnome_keyring_attribute_list_new(); gnome_keyring_attribute_list_append_string(attributes, "application", "Falkon"); QByteArray value = entry.username.toUtf8(); gnome_keyring_attribute_list_append_string(attributes, "username", value.constData()); value = entry.data; value.replace(PasswordManager::urlEncodePassword(entry.password), "___PASSWORD-VALUE___"); gnome_keyring_attribute_list_append_string(attributes, "data", value.constData()); value = entry.host.toUtf8(); gnome_keyring_attribute_list_append_string(attributes, "host", value.constData()); gnome_keyring_attribute_list_append_uint32(attributes, "updated", entry.updated); return attributes; } +static void storeEntry(PasswordEntry &entry) +{ + guint32 itemId; + GnomeKeyringAttributeList* attributes = createAttributes(entry); + + QByteArray pass = entry.password.toUtf8(); + QByteArray host = entry.host.toUtf8(); + + GnomeKeyringResult result = gnome_keyring_item_create_sync(GNOME_KEYRING_DEFAULT, + GNOME_KEYRING_ITEM_GENERIC_SECRET, + host.constData(), + attributes, + pass.constData(), + TRUE, // Update if exists + &itemId); + + gnome_keyring_attribute_list_free(attributes); + + if (result != GNOME_KEYRING_RESULT_OK) { + qWarning() << "GnomeKeyringPasswordBackend::addEntry Cannot add entry to keyring!"; + } + + entry.id = itemId; +} + GnomeKeyringPasswordBackend::GnomeKeyringPasswordBackend() : PasswordBackend() , m_loaded(false) { } QString GnomeKeyringPasswordBackend::name() const { return GnomeKeyringPlugin::tr("Gnome Keyring"); } QVector GnomeKeyringPasswordBackend::getEntries(const QUrl &url) { initialize(); const QString host = PasswordManager::createHost(url); QVector list; foreach (const PasswordEntry &entry, m_allEntries) { if (entry.host == host) { list.append(entry); } } // Sort to prefer last updated entries std::sort(list.begin(), list.end()); return list; } QVector GnomeKeyringPasswordBackend::getAllEntries() { initialize(); return m_allEntries; } void GnomeKeyringPasswordBackend::addEntry(const PasswordEntry &entry) { initialize(); PasswordEntry stored = entry; stored.updated = QDateTime::currentDateTime().toTime_t(); - guint32 itemId; - GnomeKeyringAttributeList* attributes = createAttributes(stored); - - QByteArray pass = stored.password.toUtf8(); - QByteArray host = stored.host.toUtf8(); - - GnomeKeyringResult result = gnome_keyring_item_create_sync(GNOME_KEYRING_DEFAULT, - GNOME_KEYRING_ITEM_GENERIC_SECRET, - host.constData(), - attributes, - pass.constData(), - TRUE, // Update if exists - &itemId); - - gnome_keyring_attribute_list_free(attributes); - - if (result != GNOME_KEYRING_RESULT_OK) { - qWarning() << "GnomeKeyringPasswordBackend::addEntry Cannot add entry to keyring!"; - } - - stored.id = itemId; + storeEntry(stored); m_allEntries.append(stored); } bool GnomeKeyringPasswordBackend::updateEntry(const PasswordEntry &entry) { initialize(); // Update item attributes GnomeKeyringAttributeList* attributes = createAttributes(entry); GnomeKeyringResult result = gnome_keyring_item_set_attributes_sync(GNOME_KEYRING_DEFAULT, entry.id.toUInt(), attributes); gnome_keyring_attribute_list_free(attributes); if (result != GNOME_KEYRING_RESULT_OK) { qWarning() << "GnomeKeyringPasswordBackend::updateEntry Cannot updated entry attributes in keyring!"; return false; } // Update secret GnomeKeyringItemInfo* info; result = gnome_keyring_item_get_info_full_sync(GNOME_KEYRING_DEFAULT, entry.id.toUInt(), GNOME_KEYRING_ITEM_INFO_SECRET, &info); if (result != GNOME_KEYRING_RESULT_OK) { qWarning() << "GnomeKeyringPasswordBackend::updateEntry Cannot get entry info from keyring!"; return false; } QByteArray pass = entry.password.toUtf8(); gnome_keyring_item_info_set_secret(info, pass.constData()); result = gnome_keyring_item_set_info_sync(GNOME_KEYRING_DEFAULT, entry.id.toUInt(), info); gnome_keyring_item_info_free(info); if (result != GNOME_KEYRING_RESULT_OK) { qWarning() << "GnomeKeyringPasswordBackend::updateEntry Cannot set entry info in keyring!"; return false; } int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries[index] = entry; } return true; } void GnomeKeyringPasswordBackend::updateLastUsed(PasswordEntry &entry) { initialize(); entry.updated = QDateTime::currentDateTime().toTime_t(); GnomeKeyringAttributeList* attributes = createAttributes(entry); GnomeKeyringResult result = gnome_keyring_item_set_attributes_sync(GNOME_KEYRING_DEFAULT, entry.id.toUInt(), attributes); gnome_keyring_attribute_list_free(attributes); if (result != GNOME_KEYRING_RESULT_OK) { qWarning() << "GnomeKeyringPasswordBackend::updateLastUsed Cannot updated entry in keyring!"; return; } int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries[index] = entry; } } void GnomeKeyringPasswordBackend::removeEntry(const PasswordEntry &entry) { initialize(); GnomeKeyringResult result = gnome_keyring_item_delete_sync(GNOME_KEYRING_DEFAULT, entry.id.toUInt()); if (result != GNOME_KEYRING_RESULT_OK) { qWarning() << "GnomeKeyringPasswordBackend::removeEntry Cannot remove entry from keyring!"; return; } int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries.remove(index); } } void GnomeKeyringPasswordBackend::removeAll() { initialize(); foreach (const PasswordEntry &entry, m_allEntries) { removeEntry(entry); } m_allEntries.clear(); } void GnomeKeyringPasswordBackend::initialize() { if (m_loaded) { return; } GList* found; GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET, &found, "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, "Falkon", NULL); if (result != GNOME_KEYRING_RESULT_OK && result != GNOME_KEYRING_RESULT_NO_MATCH) { qWarning() << "GnomeKeyringPasswordBackend::initialize Cannot read items from keyring!"; return; } + bool migrate = false; + if (result == GNOME_KEYRING_RESULT_NO_MATCH) { + result = gnome_keyring_find_itemsv_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET, &found, + "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, "QupZilla", + NULL); + + if (result != GNOME_KEYRING_RESULT_OK && result != GNOME_KEYRING_RESULT_NO_MATCH) { + qWarning() << "GnomeKeyringPasswordBackend::initialize Cannot read items from keyring!"; + return; + } + + if (result == GNOME_KEYRING_RESULT_OK) { + migrate = true; + } + } + GList* tmp = found; while (tmp) { GnomeKeyringFound* item = (GnomeKeyringFound*) tmp->data; m_allEntries.append(createEntry(item)); tmp = tmp->next; } gnome_keyring_found_list_free(found); + if (migrate) { + for (PasswordEntry &entry : m_allEntries) { + storeEntry(entry); + } + } + m_loaded = true; } diff --git a/src/plugins/KWalletPasswords/kwalletpasswordbackend.cpp b/src/plugins/KWalletPasswords/kwalletpasswordbackend.cpp index fe4caeb0..e3d89869 100644 --- a/src/plugins/KWalletPasswords/kwalletpasswordbackend.cpp +++ b/src/plugins/KWalletPasswords/kwalletpasswordbackend.cpp @@ -1,196 +1,216 @@ /* ============================================================ * KWalletPasswords - KWallet support plugin for Falkon * Copyright (C) 2013-2018 David Rosca * * 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 3 of the License, or * (at your option) any later version. * * 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 "kwalletpasswordbackend.h" #include "kwalletplugin.h" #include "mainapplication.h" #include "browserwindow.h" #include #include static PasswordEntry decodeEntry(const QByteArray &data) { QDataStream stream(data); PasswordEntry entry; stream >> entry; return entry; } static QByteArray encodeEntry(const PasswordEntry &entry) { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); stream << entry; return data; } KWalletPasswordBackend::KWalletPasswordBackend() : PasswordBackend() , m_wallet(0) { } QString KWalletPasswordBackend::name() const { return KWalletPlugin::tr("KWallet"); } QVector KWalletPasswordBackend::getEntries(const QUrl &url) { initialize(); const QString host = PasswordManager::createHost(url); QVector list; foreach (const PasswordEntry &entry, m_allEntries) { if (entry.host == host) { list.append(entry); } } // Sort to prefer last updated entries qSort(list.begin(), list.end()); return list; } QVector KWalletPasswordBackend::getAllEntries() { initialize(); return m_allEntries; } void KWalletPasswordBackend::addEntry(const PasswordEntry &entry) { initialize(); PasswordEntry stored = entry; stored.id = QString("%1/%2").arg(entry.host, entry.username); stored.updated = QDateTime::currentDateTime().toTime_t(); m_wallet->writeEntry(stored.id.toString(), encodeEntry(stored)); m_allEntries.append(stored); } bool KWalletPasswordBackend::updateEntry(const PasswordEntry &entry) { initialize(); m_wallet->removeEntry(entry.id.toString()); m_wallet->writeEntry(entry.id.toString(), encodeEntry(entry)); int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries[index] = entry; } return true; } void KWalletPasswordBackend::updateLastUsed(PasswordEntry &entry) { initialize(); m_wallet->removeEntry(entry.id.toString()); entry.updated = QDateTime::currentDateTime().toTime_t(); m_wallet->writeEntry(entry.id.toString(), encodeEntry(entry)); int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries[index] = entry; } } void KWalletPasswordBackend::removeEntry(const PasswordEntry &entry) { initialize(); m_wallet->removeEntry(entry.id.toString()); int index = m_allEntries.indexOf(entry); if (index > -1) { m_allEntries.remove(index); } } void KWalletPasswordBackend::removeAll() { initialize(); m_allEntries.clear(); m_wallet->removeFolder("Falkon"); m_wallet->createFolder("Falkon"); } void KWalletPasswordBackend::initialize() { if (m_wallet) { return; } WId wid = 0; BrowserWindow *w = mApp->getWindow(); if (w && w->window()) { wid = w->window()->winId(); } m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), wid); if (!m_wallet) { qWarning() << "KWalletPasswordBackend::initialize Cannot open wallet!"; return; } + bool migrate = !m_wallet->hasFolder("Falkon") && m_wallet->hasFolder("QupZilla"); + if (!m_wallet->hasFolder("Falkon") && !m_wallet->createFolder("Falkon")) { qWarning() << "KWalletPasswordBackend::initialize Cannot create folder \"Falkon\"!"; return; } - if (!m_wallet->setFolder("Falkon")) { - qWarning() << "KWalletPasswordBackend::initialize Cannot set folder \"Falkon\"!"; - return; + if (migrate) { + if (!m_wallet->setFolder("QupZilla")) { + qWarning() << "KWalletPasswordBackend::initialize Cannot set folder \"QupZilla\"!"; + return; + } + } else { + if (!m_wallet->setFolder("Falkon")) { + qWarning() << "KWalletPasswordBackend::initialize Cannot set folder \"Falkon\"!"; + return; + } } QMap entries; if (m_wallet->readEntryList("*", entries) != 0) { qWarning() << "KWalletPasswordBackend::initialize Cannot read entries!"; return; } QMap::const_iterator i = entries.constBegin(); while (i != entries.constEnd()) { PasswordEntry entry = decodeEntry(i.value()); if (entry.isValid()) { m_allEntries.append(entry); } ++i; } + + if (migrate) { + if (!m_wallet->setFolder("Falkon")) { + qWarning() << "KWalletPasswordBackend::initialize Cannot set folder \"Falkon\"!"; + return; + } + + foreach (const PasswordEntry &entry, m_allEntries) { + m_wallet->writeEntry(entry.id.toString(), encodeEntry(entry)); + } + } } KWalletPasswordBackend::~KWalletPasswordBackend() { delete m_wallet; }