mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-25 23:39:45 -05:00
Multiple browser related fixes
This commit is contained in:
parent
ee3ccf151a
commit
8ac909b0eb
@ -25,7 +25,7 @@ The following libraries are required:
|
|||||||
* zlib
|
* zlib
|
||||||
* libmicrohttpd
|
* libmicrohttpd
|
||||||
* libxi, libxtst, qtx11extras (optional for auto-type on X11)
|
* libxi, libxtst, qtx11extras (optional for auto-type on X11)
|
||||||
* libsodium (>= 1.0.12, optional for keepassxc-browser support)
|
* libsodium (>= 1.0.12, optional for KeePassXC-Browser support)
|
||||||
* libargon2
|
* libargon2
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ These steps place the compiled KeePassXC binary inside the `./build/src/` direct
|
|||||||
-DWITH_XC_AUTOTYPE=[ON|OFF] Enable/Disable Auto-Type (default: ON)
|
-DWITH_XC_AUTOTYPE=[ON|OFF] Enable/Disable Auto-Type (default: ON)
|
||||||
-DWITH_XC_HTTP=[ON|OFF] Enable/Disable KeePassHTTP and custom icon downloads (default: OFF)
|
-DWITH_XC_HTTP=[ON|OFF] Enable/Disable KeePassHTTP and custom icon downloads (default: OFF)
|
||||||
-DWITH_XC_YUBIKEY=[ON|OFF] Enable/Disable YubiKey HMAC-SHA1 authentication support (default: OFF)
|
-DWITH_XC_YUBIKEY=[ON|OFF] Enable/Disable YubiKey HMAC-SHA1 authentication support (default: OFF)
|
||||||
-DWITH_XC_BROWSER=[ON|OFF] Enable/Disable keepassxc-browser extension support (default: OFF)
|
-DWITH_XC_BROWSER=[ON|OFF] Enable/Disable KeePassXC-Browser extension support (default: OFF)
|
||||||
|
|
||||||
-DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON)
|
-DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON)
|
||||||
-DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF)
|
-DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF)
|
||||||
|
@ -33,7 +33,7 @@ so please check out your distribution's package list to see if KeePassXC is avai
|
|||||||
[Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepasshttp-connector/) and
|
[Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepasshttp-connector/) and
|
||||||
[Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepasshttp-connector/dafgdjggglmmknipkhngniifhplpcldb), and
|
[Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepasshttp-connector/dafgdjggglmmknipkhngniifhplpcldb), and
|
||||||
[passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. [[See note about KeePassHTTP]](#Note_about_KeePassHTTP)
|
[passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. [[See note about KeePassHTTP]](#Note_about_KeePassHTTP)
|
||||||
- Browser integration with keepassxc-browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf)
|
- Browser integration with KeePassXC-Browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf)
|
||||||
- Many bug fixes
|
- 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.
|
||||||
|
@ -189,7 +189,7 @@ set(keepassx_SOURCES_MAINEXE
|
|||||||
|
|
||||||
add_feature_info(Auto-Type WITH_XC_AUTOTYPE "Automatic password typing")
|
add_feature_info(Auto-Type WITH_XC_AUTOTYPE "Automatic password typing")
|
||||||
add_feature_info(Networking WITH_XC_NETWORKING "Compile KeePassXC with network access code (e.g. for downloading website icons)")
|
add_feature_info(Networking WITH_XC_NETWORKING "Compile KeePassXC with network access code (e.g. for downloading website icons)")
|
||||||
add_feature_info(keepassxc-browser WITH_XC_BROWSER "Browser integration with keepassxc-browser")
|
add_feature_info(KeePassXC-Browser WITH_XC_BROWSER "Browser integration with KeePassXC-Browser")
|
||||||
add_feature_info(KeePassHTTP WITH_XC_HTTP "Browser integration compatible with ChromeIPass and PassIFox (deprecated, implies Networking)")
|
add_feature_info(KeePassHTTP WITH_XC_HTTP "Browser integration compatible with ChromeIPass and PassIFox (deprecated, implies Networking)")
|
||||||
add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible with KeeAgent")
|
add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible with KeeAgent")
|
||||||
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
|
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>keepassxc-browser Confirm Access</string>
|
<string>KeePassXC-Browser Confirm Access</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -39,6 +39,12 @@ QJsonObject BrowserAction::readResponse(const QJsonObject& json)
|
|||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool triggerUnlock = false;
|
||||||
|
const QString trigger = json.value("triggerUnlock").toString();
|
||||||
|
if (!trigger.isEmpty() && trigger.compare("true", Qt::CaseSensitive) == 0) {
|
||||||
|
triggerUnlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
const QString action = json.value("action").toString();
|
const QString action = json.value("action").toString();
|
||||||
if (action.isEmpty()) {
|
if (action.isEmpty()) {
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
@ -48,7 +54,7 @@ QJsonObject BrowserAction::readResponse(const QJsonObject& json)
|
|||||||
if (action.compare("change-public-keys", Qt::CaseSensitive) != 0 && !m_browserService.isDatabaseOpened()) {
|
if (action.compare("change-public-keys", Qt::CaseSensitive) != 0 && !m_browserService.isDatabaseOpened()) {
|
||||||
if (m_clientPublicKey.isEmpty()) {
|
if (m_clientPublicKey.isEmpty()) {
|
||||||
return getErrorReply(action, ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED);
|
return getErrorReply(action, ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED);
|
||||||
} else if (!m_browserService.openDatabase()) {
|
} else if (!m_browserService.openDatabase(triggerUnlock)) {
|
||||||
return getErrorReply(action, ERROR_KEEPASS_DATABASE_NOT_OPENED);
|
return getErrorReply(action, ERROR_KEEPASS_DATABASE_NOT_OPENED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,10 +140,11 @@ QJsonObject BrowserAction::handleGetDatabaseHash(const QJsonObject& json, const
|
|||||||
|
|
||||||
QString command = decrypted.value("action").toString();
|
QString command = decrypted.value("action").toString();
|
||||||
if (!command.isEmpty() && command.compare("get-databasehash", Qt::CaseSensitive) == 0) {
|
if (!command.isEmpty() && command.compare("get-databasehash", Qt::CaseSensitive) == 0) {
|
||||||
QJsonObject message;
|
const QString newNonce = incrementNonce(nonce);
|
||||||
|
|
||||||
|
QJsonObject message = buildMessage(newNonce);
|
||||||
message["hash"] = hash;
|
message["hash"] = hash;
|
||||||
message["version"] = KEEPASSX_VERSION;
|
return buildResponse(action, message, newNonce);
|
||||||
return buildResponse(action, message, incrementNonce(nonce));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getErrorReply(action, ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE);
|
return getErrorReply(action, ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE);
|
||||||
@ -237,7 +244,7 @@ QJsonObject BrowserAction::handleGetLogins(const QJsonObject& json, const QStrin
|
|||||||
const QJsonArray users = m_browserService.findMatchingEntries(id, url, submit, "");
|
const QJsonArray users = m_browserService.findMatchingEntries(id, url, submit, "");
|
||||||
|
|
||||||
if (users.isEmpty()) {
|
if (users.isEmpty()) {
|
||||||
return QJsonObject(); // No logins found. Not an error, return an empty JSON object.
|
return getErrorReply(action, ERROR_KEEPASS_NO_LOGINS_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString newNonce = incrementNonce(nonce);
|
const QString newNonce = incrementNonce(nonce);
|
||||||
@ -379,21 +386,22 @@ QJsonObject BrowserAction::buildResponse(const QString& action, const QJsonObjec
|
|||||||
QString BrowserAction::getErrorMessage(const int errorCode) const
|
QString BrowserAction::getErrorMessage(const int errorCode) const
|
||||||
{
|
{
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
case ERROR_KEEPASS_DATABASE_NOT_OPENED: return "Database not opened";
|
case ERROR_KEEPASS_DATABASE_NOT_OPENED: return QObject::tr("Database not opened");
|
||||||
case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: return "Database hash not available";
|
case ERROR_KEEPASS_DATABASE_HASH_NOT_RECEIVED: return QObject::tr("Database hash not available");
|
||||||
case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: return "Client public key not received";
|
case ERROR_KEEPASS_CLIENT_PUBLIC_KEY_NOT_RECEIVED: return QObject::tr("Client public key not received");
|
||||||
case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: return "Cannot decrypt message";
|
case ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE: return QObject::tr("Cannot decrypt message");
|
||||||
case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: return "Timeout or cannot connect to KeePassXC";
|
case ERROR_KEEPASS_TIMEOUT_OR_NOT_CONNECTED: return QObject::tr("Timeout or cannot connect to KeePassXC");
|
||||||
case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: return "Action cancelled or denied";
|
case ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED: return QObject::tr("Action cancelled or denied");
|
||||||
case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE: return "Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?";
|
case ERROR_KEEPASS_CANNOT_ENCRYPT_MESSAGE: return QObject::tr("Cannot encrypt message or public key not found. Is Native Messaging enabled in KeePassXC?");
|
||||||
case ERROR_KEEPASS_ASSOCIATION_FAILED: return "KeePassXC association failed, try again";
|
case ERROR_KEEPASS_ASSOCIATION_FAILED: return QObject::tr("KeePassXC association failed, try again");
|
||||||
case ERROR_KEEPASS_KEY_CHANGE_FAILED: return "Key change was not successful";
|
case ERROR_KEEPASS_KEY_CHANGE_FAILED: return QObject::tr("Key change was not successful");
|
||||||
case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: return "Encryption key is not recognized";
|
case ERROR_KEEPASS_ENCRYPTION_KEY_UNRECOGNIZED: return QObject::tr("Encryption key is not recognized");
|
||||||
case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: return "No saved databases found";
|
case ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND: return QObject::tr("No saved databases found");
|
||||||
case ERROR_KEEPASS_INCORRECT_ACTION: return "Incorrect action";
|
case ERROR_KEEPASS_INCORRECT_ACTION: return QObject::tr("Incorrect action");
|
||||||
case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: return "Empty message received";
|
case ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED: return QObject::tr("Empty message received");
|
||||||
case ERROR_KEEPASS_NO_URL_PROVIDED: return "No URL provided";
|
case ERROR_KEEPASS_NO_URL_PROVIDED: return QObject::tr("No URL provided");
|
||||||
default: return "Unknown error";
|
case ERROR_KEEPASS_NO_LOGINS_FOUND: return QObject::tr("No logins found");
|
||||||
|
default: return QObject::tr("Unknown error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ class BrowserAction : public QObject
|
|||||||
ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11,
|
ERROR_KEEPASS_NO_SAVED_DATABASES_FOUND = 11,
|
||||||
ERROR_KEEPASS_INCORRECT_ACTION = 12,
|
ERROR_KEEPASS_INCORRECT_ACTION = 12,
|
||||||
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
ERROR_KEEPASS_EMPTY_MESSAGE_RECEIVED = 13,
|
||||||
ERROR_KEEPASS_NO_URL_PROVIDED = 14
|
ERROR_KEEPASS_NO_URL_PROVIDED = 14,
|
||||||
|
ERROR_KEEPASS_NO_LOGINS_FOUND = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
#include "core/EntryAttributes.h"
|
#include "core/EntryAttributes.h"
|
||||||
|
|
||||||
static const char KEEPASSBROWSER_NAME[] = "keepassxc-browser Settings"; //TODO: duplicated string (also in Service.cpp)
|
static const char KEEPASSBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||||
|
|
||||||
|
|
||||||
BrowserEntryConfig::BrowserEntryConfig(QObject* parent) :
|
BrowserEntryConfig::BrowserEntryConfig(QObject* parent) :
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="enableBrowserSupport">
|
<widget class="QCheckBox" name="enableBrowserSupport">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>This is required for accessing your databases with keepassxc-browser</string>
|
<string>This is required for accessing your databases with KeePassXC-Browser</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable KeepassXC browser integration</string>
|
<string>Enable KeepassXC browser integration</string>
|
||||||
|
@ -40,9 +40,9 @@ static const unsigned char KEEPASSXCBROWSER_UUID_DATA[] = {
|
|||||||
0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24
|
0x97, 0x4b, 0x59, 0x11, 0xb8, 0x81, 0x62, 0x24
|
||||||
};
|
};
|
||||||
static const Uuid KEEPASSXCBROWSER_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast<const char *>(KEEPASSXCBROWSER_UUID_DATA), sizeof(KEEPASSXCBROWSER_UUID_DATA)));
|
static const Uuid KEEPASSXCBROWSER_UUID = Uuid(QByteArray::fromRawData(reinterpret_cast<const char *>(KEEPASSXCBROWSER_UUID_DATA), sizeof(KEEPASSXCBROWSER_UUID_DATA)));
|
||||||
static const char KEEPASSXCBROWSER_NAME[] = "keepassxc-browser Settings";
|
static const char KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings";
|
||||||
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
|
static const char ASSOCIATE_KEY_PREFIX[] = "Public Key: ";
|
||||||
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "keepassxc-browser Passwords";
|
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords";
|
||||||
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
|
||||||
|
|
||||||
BrowserService::BrowserService(DatabaseTabWidget* parent) :
|
BrowserService::BrowserService(DatabaseTabWidget* parent) :
|
||||||
@ -65,7 +65,7 @@ bool BrowserService::isDatabaseOpened() const
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserService::openDatabase()
|
bool BrowserService::openDatabase(bool triggerUnlock)
|
||||||
{
|
{
|
||||||
if (!BrowserSettings::unlockDatabase()) {
|
if (!BrowserSettings::unlockDatabase()) {
|
||||||
return false;
|
return false;
|
||||||
@ -80,7 +80,9 @@ bool BrowserService::openDatabase()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KEEPASSXC_MAIN_WINDOW->bringToFront();
|
if (triggerUnlock) {
|
||||||
|
KEEPASSXC_MAIN_WINDOW->bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -189,6 +191,7 @@ QString BrowserService::storeKey(const QString& key)
|
|||||||
keyDialog.show();
|
keyDialog.show();
|
||||||
keyDialog.activateWindow();
|
keyDialog.activateWindow();
|
||||||
keyDialog.raise();
|
keyDialog.raise();
|
||||||
|
keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint);
|
||||||
auto ok = keyDialog.exec();
|
auto ok = keyDialog.exec();
|
||||||
|
|
||||||
id = keyDialog.textValue();
|
id = keyDialog.textValue();
|
||||||
@ -221,7 +224,6 @@ QString BrowserService::getKey(const QString& id)
|
|||||||
return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
return config->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to use KeepassHttpProtocol. Just return a JSON array.
|
|
||||||
QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm)
|
QJsonArray BrowserService::findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm)
|
||||||
{
|
{
|
||||||
QJsonArray result;
|
QJsonArray result;
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
explicit BrowserService(DatabaseTabWidget* parent);
|
explicit BrowserService(DatabaseTabWidget* parent);
|
||||||
|
|
||||||
bool isDatabaseOpened() const;
|
bool isDatabaseOpened() const;
|
||||||
bool openDatabase();
|
bool openDatabase(bool triggerUnlock);
|
||||||
QString getDatabaseRootUuid();
|
QString getDatabaseRootUuid();
|
||||||
QString getDatabaseRecycleBinUuid();
|
QString getDatabaseRecycleBinUuid();
|
||||||
Entry* getConfigEntry(bool create = false);
|
Entry* getConfigEntry(bool create = false);
|
||||||
|
@ -121,7 +121,7 @@ void NativeMessagingBase::sendReply(const QJsonObject& json)
|
|||||||
void NativeMessagingBase::sendReply(const QString& reply)
|
void NativeMessagingBase::sendReply(const QString& reply)
|
||||||
{
|
{
|
||||||
if (!reply.isEmpty()) {
|
if (!reply.isEmpty()) {
|
||||||
uint len = reply.length();
|
uint len = reply.length();
|
||||||
std::cout << char(((len>>0) & 0xFF)) << char(((len>>8) & 0xFF)) << char(((len>>16) & 0xFF)) << char(((len>>24) & 0xFF));
|
std::cout << char(((len>>0) & 0xFF)) << char(((len>>8) & 0xFF)) << char(((len>>16) & 0xFF)) << char(((len>>24) & 0xFF));
|
||||||
std::cout << reply.toStdString() << std::flush;
|
std::cout << reply.toStdString() << std::flush;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,11 @@ void NativeMessagingHost::run()
|
|||||||
if (BrowserSettings::supportBrowserProxy()) {
|
if (BrowserSettings::supportBrowserProxy()) {
|
||||||
QString serverPath = getLocalServerPath();
|
QString serverPath = getLocalServerPath();
|
||||||
QFile::remove(serverPath);
|
QFile::remove(serverPath);
|
||||||
|
|
||||||
|
if (m_localServer->isListening()) {
|
||||||
|
m_localServer->close();
|
||||||
|
}
|
||||||
|
|
||||||
m_localServer->listen(serverPath);
|
m_localServer->listen(serverPath);
|
||||||
connect(m_localServer.data(), SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
|
connect(m_localServer.data(), SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
|
||||||
} else {
|
} else {
|
||||||
@ -120,8 +125,10 @@ void NativeMessagingHost::readStdIn(const quint32 length)
|
|||||||
void NativeMessagingHost::newLocalConnection()
|
void NativeMessagingHost::newLocalConnection()
|
||||||
{
|
{
|
||||||
QLocalSocket* socket = m_localServer->nextPendingConnection();
|
QLocalSocket* socket = m_localServer->nextPendingConnection();
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(newLocalMessage()));
|
if (socket) {
|
||||||
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectSocket()));
|
connect(socket, SIGNAL(readyRead()), this, SLOT(newLocalMessage()));
|
||||||
|
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectSocket()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeMessagingHost::newLocalMessage()
|
void NativeMessagingHost::newLocalMessage()
|
||||||
|
Loading…
Reference in New Issue
Block a user