SYNERGY-1032 - Send secure input notifications to client (#7043)

* SYNERGY-1017 - Try usnig NSUserNotification

* SYNERGY-1032 - Use UNUserNotificationCenter instead of deprecated notifications

* SYNERGY-1032 - Update app delegate and add log after notification access

* SYNERGY-1032 - Try using deprecated notification

* SYNERGY-1032 - Add notifications to the platform dependant code

* SYNERGY-1032 - Check for development builds before asking permission for notifications

* SYNERGY-1032 - Remove old notification and secure input detection

* SYNERGY-1032 - Add permission request to the main app

* SYNERGY-1032 - Only show notifications on server

* SYNERGY-1032 - Request and show notification from main app

* SYNERGY-1032 - Remove logging from OSX helpers

* SYNERGY-1032 - Add UN notification for testing

* SYNERGY-1032 - Show notification once

* SYNERGY-1032 - Try replicating old flow

* SYNERGY-1032 - Reuse notification center

* SYNERGY-1032 - Send notification after granting permission

* SYNERGY-1032 - Update app delegate

* SYNERGY-1032 - Remove deprecated property

* SYNERGY-1032 - Add output for debugging

* SYNERGY-1032 - Try updating delegate

* SYNERGY-1032 - Print current bundle name

* SYNERGY-1032 - Add AppDelegate to the server

* SYNERGY-1032 - Move notification creation to synergy app

* SYNERGY-1032 - Update notification text

* SYNERGY-1032 - Fix QString conversion for notification

* SYNERGY-1032 - Move notification creation outside the handler

* SYNERGY-1032 - Remove debug notification, show notification with no delay

* SYNERGY-1032 - Show notification inside the completion handler

* SYNERGY-1032 - Remove timed notification trigger

* SYNERGY-1032 - Request permissions on synergy start

* SYNERGY-1032 - Remove unused includes

* SYNERGY-1032 - Update changelog

* SYNERGY-1032 - Add empty notification implementations for Windows and Linux

* SYNERGY-1032 - Removed temporary debug messages

* SYNERGY-1032 - Resolve code smell

* SYNERGY-1032 - Add base code for handling sending secure input notification

* SYNERGY-1032 - Compile on Mac

* SYNERGY-1032 - Allow client downgrade for 1.7 down to 1.6

* SYNERGY-1032 - Add utility to show notifications. Update secure input message format

* SYNERGY-1032 - Update notification util on Mac

* SYNERGY-1032 - Don't disconnect on invalid message from client

* SYNERGY-1032 - Remove unused code

* SYNERGY-1032 - Update changelog

* SYNERGY-1032 - Update secure input notification message

* SYNERGY-1032 - Better formatting for debug comments

* SYNERGY-1032 - Resolve code smells

* SYNERGY-1032 - Resolve more code smells

* SYNERGY-1032 - Revert log level change

* SYNERGY-1032 - Resolve merge error
This commit is contained in:
Igor Sikachyna 2021-06-29 18:45:15 +03:00 committed by GitHub
parent 5843230169
commit 2fdde93f3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 416 additions and 226 deletions

View file

@ -15,7 +15,7 @@ Enhancements:
- #7026 Update the way we package OpenSSL for Windows build
- #7035 Add Fedora 34 build
- #7037 Add Ubuntu 21.04 build
- #7030 | #7041 Add user nofication for secure input on Mac
- #7030 | #7041 | #7043 Add user notification for secure input on Mac
===========
v1.14.0-stable

View file

@ -730,7 +730,14 @@ Client::handleHello(const Event&, void*)
// check versions
LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor));
if (major < kProtocolMajorVersion ||
SInt16 helloBackMajor = kProtocolMajorVersion;
SInt16 helloBackMinor = kProtocolMinorVersion;
if (major == kProtocolMajorVersion && minor == 6 && kProtocolMinorVersion == 7) {
//because 1.6 and 1.7 is comptable - downgrading protocol for server
LOG((CLOG_NOTE "Downgrading protocol version for server"));
helloBackMinor = minor;
}
else if (major < kProtocolMajorVersion ||
(major == kProtocolMajorVersion && minor < kProtocolMinorVersion)) {
sendConnectionFailedEvent(XIncompatibleClient(major, minor).what());
cleanupTimer();
@ -739,10 +746,10 @@ Client::handleHello(const Event&, void*)
}
// say hello back
LOG((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion));
LOG((CLOG_DEBUG1 "say hello version %d.%d", helloBackMajor, helloBackMinor));
ProtocolUtil::writef(m_stream, kMsgHelloBack,
kProtocolMajorVersion,
kProtocolMinorVersion, &m_name);
helloBackMajor,
helloBackMinor, & m_name);
// now connected but waiting to complete handshake
setupScreen();

View file

@ -26,6 +26,7 @@
#include "synergy/ProtocolUtil.h"
#include "synergy/option_types.h"
#include "synergy/protocol_types.h"
#include "synergy/AppUtil.h"
#include "io/IStream.h"
#include "base/Log.h"
#include "base/IEventQueue.h"
@ -129,8 +130,10 @@ ServerProxy::handleData(const Event&, void*)
case kUnknown:
LOG((CLOG_ERR "invalid message from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
m_client->disconnect("invalid message from server");
return;
// not possible to determine message boundaries
// read the whole stream to discard unkonwn data
while (m_stream->read(nullptr, 4));
break;
case kDisconnect:
return;
@ -303,6 +306,9 @@ ServerProxy::parseMessage(const UInt8* code)
else if (memcmp(code, kMsgDDragInfo, 4) == 0) {
dragInfoReceived();
}
else if (memcmp(code, kMsgDSecureInputNotification, 4) == 0) {
secureInputNotification();
}
else if (memcmp(code, kMsgCClose, 4) == 0) {
// server wants us to hangup
@ -906,3 +912,19 @@ ServerProxy::sendDragInfo(UInt32 fileCount, const char* info, size_t size)
String data(info, size);
ProtocolUtil::writef(m_stream, kMsgDDragInfo, fileCount, &data);
}
void
ServerProxy::secureInputNotification()
{
String app;
ProtocolUtil::readf(m_stream, kMsgDSecureInputNotification + 4, &app);
String secureInputNotificationBody =
"'Secure input' enabled by " + app + " on the server. " \
"To fix the keyboard, " + app + " must be closed.";
// display this notification on the client
AppUtil::instance().showNotification(
"The keyboard may stop working.",
secureInputNotificationBody);
}

View file

@ -112,6 +112,7 @@ private:
void fileChunkReceived();
void dragInfoReceived();
void handleClipboardSendingEvent(const Event&, void*);
void secureInputNotification();
private:
typedef EResult (ServerProxy::*MessageParser)(const UInt8*);

View file

@ -1988,10 +1988,11 @@ MSWindowsScreen::getDropTarget() const
return m_desktopPath;
}
void
MSWindowsScreen::createNotification(const String& title, const String& content) const
String
MSWindowsScreen::getSecureInputApp() const
{
// TODO: implement notification
// ignore on Windows
return "";
}
bool

View file

@ -139,7 +139,7 @@ public:
virtual String& getDraggingFilename();
virtual const String&
getDropTarget() const;
void createNotification(const String& title, const String& content) const override;
String getSecureInputApp() const override;
protected:
// IPlatformScreen overrides

View file

@ -59,55 +59,55 @@ public:
IEventQueue* getEvents() const { return m_events; }
// IScreen overrides
virtual void* getEventTarget() const;
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
virtual void getCursorPos(SInt32& x, SInt32& y) const;
void* getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard*) const override;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override;
void getCursorPos(SInt32& x, SInt32& y) const override;
// IPrimaryScreen overrides
virtual void reconfigure(UInt32 activeSides);
virtual void warpCursor(SInt32 x, SInt32 y);
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
virtual void unregisterHotKey(UInt32 id);
virtual void fakeInputBegin();
virtual void fakeInputEnd();
virtual SInt32 getJumpZoneSize() const;
virtual bool isAnyMouseButtonDown(UInt32& buttonID) const;
virtual void getCursorCenter(SInt32& x, SInt32& y) const;
void reconfigure(UInt32 activeSides) override;
void warpCursor(SInt32 x, SInt32 y) override;
UInt32 registerHotKey(KeyID key, KeyModifierMask mask) override;
void unregisterHotKey(UInt32 id) override;
void fakeInputBegin() override;
void fakeInputEnd() override;
SInt32 getJumpZoneSize() const override;
bool isAnyMouseButtonDown(UInt32& buttonID) const override;
void getCursorCenter(SInt32& x, SInt32& y) const override;
// ISecondaryScreen overrides
virtual void fakeMouseButton(ButtonID id, bool press);
virtual void fakeMouseMove(SInt32 x, SInt32 y);
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
void fakeMouseButton(ButtonID id, bool press) override;
void fakeMouseMove(SInt32 x, SInt32 y) override;
void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const override;
void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const override;
// IPlatformScreen overrides
virtual void enable();
virtual void disable();
virtual void enter();
virtual bool leave();
virtual bool setClipboard(ClipboardID, const IClipboard*);
virtual void checkClipboards();
virtual void openScreensaver(bool notify);
virtual void closeScreensaver();
virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const OptionsList& options);
virtual void setSequenceNumber(UInt32);
virtual bool isPrimary() const;
virtual void fakeDraggingFiles(DragFileList fileList);
virtual String& getDraggingFilename();
void enable() override;
void disable() override;
void enter() override;
bool leave() override;
bool setClipboard(ClipboardID, const IClipboard*) override;
void checkClipboards() override;
void openScreensaver(bool notify) override;
void closeScreensaver() override;
void screensaver(bool activate) override;
void resetOptions() override;
void setOptions(const OptionsList& options) override;
void setSequenceNumber(UInt32) override;
bool isPrimary() const override;
void fakeDraggingFiles(DragFileList fileList) override;
String& getDraggingFilename() override;
String getSecureInputApp() const override;
const String& getDropTarget() const { return m_dropTarget; }
void waitForCarbonLoop() const;
void createNotification(const String& title, const String& content) const override;
const String& getDropTarget() const override { return m_dropTarget; }
void waitForCarbonLoop() const;
protected:
// IPlatformScreen overrides
virtual void handleSystemEvent(const Event&, void*);
virtual void updateButtons();
virtual IKeyState* getKeyState() const;
void handleSystemEvent(const Event&, void*) override;
void updateButtons() override;
IKeyState* getKeyState() const override;
private:
bool updateScreenShape();
@ -203,8 +203,6 @@ private:
static char* CFStringRefToUTF8String(CFStringRef aString);
void getDropTargetThread(void*);
void createSecureInputNotification();
private:
struct HotKeyItem {

32
src/lib/platform/OSXScreen.mm Executable file → Normal file
View file

@ -59,6 +59,7 @@ enum {
kCarbonLoopWaitTimeout = 10
};
void createSecureInputNotification();
int getSecureInputEventPID();
String getProcessName(int pid);
@ -2158,26 +2159,31 @@ OSXScreen::waitForCarbonLoop() const
}
void
OSXScreen::createNotification(const String& title, const String& content) const
String
OSXScreen::getSecureInputApp() const
{
LOG((CLOG_INFO "OSX Notification: %s|%s", title.c_str(), content.c_str()));
if(IsSecureEventInputEnabled()) {
int secureInputProcessPID = getSecureInputEventPID();
if(secureInputProcessPID == 0) return "unknown";
return getProcessName(secureInputProcessPID);
}
return "";
}
void
OSXScreen::createSecureInputNotification()
createSecureInputNotification()
{
std::string secureInputNotificationBody =
"Secure input was enabled in your system. " \
"Synergy may not be able to send keyboard strokes. ";
int secureInputProcessPID = getSecureInputEventPID();
std::string infringingProcessName = getProcessName(secureInputProcessPID);
if(secureInputProcessPID == 0) infringingProcessName = "unknown";
secureInputNotificationBody += "Infringing process is " + infringingProcessName;
String app = getProcessName(secureInputProcessPID);
if(secureInputProcessPID == 0) app = "unknown";
createNotification(
"Keyboard may not work correctly",
String secureInputNotificationBody =
"'Secure input' enabled by " + app + ". " \
"Close " + app + " to continue using keyboards on the clients.";
// display this notification on the server
AppUtil::instance().showNotification(
"The client keyboards may stop working.",
secureInputNotificationBody);
}

View file

@ -475,10 +475,11 @@ XWindowsScreen::isPrimary() const
return m_isPrimary;
}
void
XWindowsScreen::createNotification(const String& title, const String& content) const
String
XWindowsScreen::getSecureInputApp() const
{
// TODO: implement notification
// ignore on Linux
return "";
}
void*

View file

@ -84,7 +84,7 @@ public:
virtual void setOptions(const OptionsList& options);
virtual void setSequenceNumber(UInt32);
virtual bool isPrimary() const;
void createNotification(const String& title, const String& content) const override;
String getSecureInputApp() const override;
protected:
// IPlatformScreen overrides

View file

@ -89,6 +89,8 @@ public:
virtual void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) = 0;
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
virtual String getSecureInputApp() const = 0;
virtual void secureInputNotification(const String& app) const = 0;
virtual String getName() const;
virtual synergy::IStream*
getStream() const = 0;

View file

@ -56,40 +56,41 @@ public:
/*!
Returns the original stream passed to the c'tor.
*/
synergy::IStream* getStream() const;
synergy::IStream* getStream() const override;
//@}
// IScreen
virtual void* getEventTarget() const;
virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const = 0;
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
void* getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard*) const override = 0;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override = 0;
void getCursorPos(SInt32& x, SInt32& y) const override = 0;
// IClient overrides
virtual void enter(SInt32 xAbs, SInt32 yAbs,
void enter(SInt32 xAbs, SInt32 yAbs,
UInt32 seqNum, KeyModifierMask mask,
bool forScreensaver) = 0;
virtual bool leave() = 0;
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
virtual void grabClipboard(ClipboardID) = 0;
virtual void setClipboardDirty(ClipboardID, bool) = 0;
virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0;
virtual void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) = 0;
virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0;
virtual void mouseDown(ButtonID) = 0;
virtual void mouseUp(ButtonID) = 0;
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0;
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0;
virtual void screensaver(bool activate) = 0;
virtual void resetOptions() = 0;
virtual void setOptions(const OptionsList& options) = 0;
virtual void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) = 0;
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
bool forScreensaver) override = 0;
bool leave() override = 0;
void setClipboard(ClipboardID, const IClipboard*) override = 0;
void grabClipboard(ClipboardID) override = 0;
void setClipboardDirty(ClipboardID, bool) override = 0;
void keyDown(KeyID, KeyModifierMask, KeyButton) override = 0;
void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) override = 0;
void keyUp(KeyID, KeyModifierMask, KeyButton) override = 0;
void mouseDown(ButtonID) override = 0;
void mouseUp(ButtonID) override = 0;
void mouseMove(SInt32 xAbs, SInt32 yAbs) override = 0;
void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override = 0;
void mouseWheel(SInt32 xDelta, SInt32 yDelta) override = 0;
void screensaver(bool activate) override = 0;
void resetOptions() override = 0;
void setOptions(const OptionsList& options) override = 0;
void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) override = 0;
void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override = 0;
void secureInputNotification(const String& app) const override = 0;
private:
synergy::IStream* m_stream;

View file

@ -150,8 +150,9 @@ ClientProxy1_0::handleData(const Event&, void*)
LOG((CLOG_DEBUG2 "msg from \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3]));
if (!(this->*m_parser)(code)) {
LOG((CLOG_ERR "invalid message from client \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3]));
disconnect();
return;
// not possible to determine message boundaries
// read the whole stream to discard unkonwn data
while (getStream()->read(nullptr, 4));
}
// next message
@ -365,6 +366,21 @@ ClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
LOG((CLOG_DEBUG "fileChunkSending not supported"));
}
String
ClientProxy1_0::getSecureInputApp() const
{
// ignore -- not supported on clients
LOG((CLOG_DEBUG "getSecureInputApp not supported"));
return "";
}
void
ClientProxy1_0::secureInputNotification(const String& app) const
{
// ignore -- not supported in protocol 1.0
LOG((CLOG_DEBUG "secureInputNotification not supported"));
}
void
ClientProxy1_0::screensaver(bool on)
{

View file

@ -38,33 +38,35 @@ public:
ClientProxy1_0& operator=(ClientProxy1_0 &&) =delete;
// IScreen
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
virtual void getCursorPos(SInt32& x, SInt32& y) const;
bool getClipboard(ClipboardID id, IClipboard*) const override;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override;
void getCursorPos(SInt32& x, SInt32& y) const override;
// IClient overrides
virtual void enter(SInt32 xAbs, SInt32 yAbs,
void enter(SInt32 xAbs, SInt32 yAbs,
UInt32 seqNum, KeyModifierMask mask,
bool forScreensaver);
virtual bool leave();
virtual void setClipboard(ClipboardID, const IClipboard*);
virtual void grabClipboard(ClipboardID);
virtual void setClipboardDirty(ClipboardID, bool);
virtual void keyDown(KeyID, KeyModifierMask, KeyButton);
virtual void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton);
virtual void keyUp(KeyID, KeyModifierMask, KeyButton);
virtual void mouseDown(ButtonID);
virtual void mouseUp(ButtonID);
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel);
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta);
virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const OptionsList& options);
virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size);
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
bool forScreensaver) override;
bool leave() override;
void setClipboard(ClipboardID, const IClipboard*) override;
void grabClipboard(ClipboardID) override;
void setClipboardDirty(ClipboardID, bool) override;
void keyDown(KeyID, KeyModifierMask, KeyButton) override;
void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) override;
void keyUp(KeyID, KeyModifierMask, KeyButton) override;
void mouseDown(ButtonID) override;
void mouseUp(ButtonID) override;
void mouseMove(SInt32 xAbs, SInt32 yAbs) override;
void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override;
void mouseWheel(SInt32 xDelta, SInt32 yDelta) override;
void screensaver(bool activate) override;
void resetOptions() override;
void setOptions(const OptionsList& options) override;
void sendDragInfo(UInt32 fileCount, const char* info, size_t size) override;
void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override;
String getSecureInputApp() const override;
void secureInputNotification(const String& app) const override;
protected:
virtual bool parseHandshakeMessage(const UInt8* code);

View file

@ -0,0 +1,41 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 <http://www.gnu.org/licenses/>.
*/
#include "server/ClientProxy1_7.h"
#include "server/Server.h"
#include "synergy/AppUtil.h"
#include "synergy/ProtocolUtil.h"
#include "base/TMethodEventJob.h"
#include "base/Log.h"
//
// ClientProxy1_7
//
ClientProxy1_7::ClientProxy1_7(const String& name, synergy::IStream* stream, Server* server, IEventQueue* events) :
ClientProxy1_6(name, stream, server, events),
m_events(events)
{
}
void
ClientProxy1_7::secureInputNotification(const String& app) const
{
LOG((CLOG_DEBUG2 "send secure input notification to \"%s\" %s", getName().c_str(), app.c_str()));
ProtocolUtil::writef(getStream(), kMsgDSecureInputNotification, &app);
}

View file

@ -0,0 +1,33 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "server/ClientProxy1_6.h"
//! Proxy for client implementing protocol version 1.7
class ClientProxy1_7 : public ClientProxy1_6 {
public:
ClientProxy1_7(const String& name, synergy::IStream* adoptedStream, Server* server, IEventQueue* events);
~ClientProxy1_7() override = default;
void secureInputNotification(const String& app) const override;
private:
IEventQueue* m_events;
};

View file

@ -26,6 +26,7 @@
#include "server/ClientProxy1_4.h"
#include "server/ClientProxy1_5.h"
#include "server/ClientProxy1_6.h"
#include "server/ClientProxy1_7.h"
#include "synergy/protocol_types.h"
#include "synergy/ProtocolUtil.h"
#include "synergy/XSynergy.h"
@ -232,6 +233,10 @@ ClientProxyUnknown::handleData(const Event&, void*)
case 6:
m_proxy = new ClientProxy1_6(name, m_stream, m_server, m_events);
break;
case 7:
m_proxy = new ClientProxy1_7(name, m_stream, m_server, m_events);
break;
}
}

View file

@ -261,6 +261,18 @@ PrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
// ignore
}
String
PrimaryClient::getSecureInputApp() const
{
return m_screen->getSecureInputApp();
}
void
PrimaryClient::secureInputNotification(const String& app) const
{
// ignore
}
void
PrimaryClient::resetOptions()
{

View file

@ -117,38 +117,40 @@ public:
virtual void disable();
// IScreen overrides
virtual void* getEventTarget() const;
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
virtual void getCursorPos(SInt32& x, SInt32& y) const;
void* getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard*) const override;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override;
void getCursorPos(SInt32& x, SInt32& y) const override;
// IClient overrides
virtual void enter(SInt32 xAbs, SInt32 yAbs,
void enter(SInt32 xAbs, SInt32 yAbs,
UInt32 seqNum, KeyModifierMask mask,
bool forScreensaver);
virtual bool leave();
virtual void setClipboard(ClipboardID, const IClipboard*);
virtual void grabClipboard(ClipboardID);
virtual void setClipboardDirty(ClipboardID, bool);
virtual void keyDown(KeyID, KeyModifierMask, KeyButton);
virtual void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton);
virtual void keyUp(KeyID, KeyModifierMask, KeyButton);
virtual void mouseDown(ButtonID);
virtual void mouseUp(ButtonID);
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel);
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta);
virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const OptionsList& options);
virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size);
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
bool forScreensaver) override;
bool leave() override;
void setClipboard(ClipboardID, const IClipboard*) override;
void grabClipboard(ClipboardID) override;
void setClipboardDirty(ClipboardID, bool) override;
void keyDown(KeyID, KeyModifierMask, KeyButton) override;
void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) override;
void keyUp(KeyID, KeyModifierMask, KeyButton) override;
void mouseDown(ButtonID) override;
void mouseUp(ButtonID) override;
void mouseMove(SInt32 xAbs, SInt32 yAbs) override;
void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override;
void mouseWheel(SInt32 xDelta, SInt32 yDelta) override;
void screensaver(bool activate) override;
void resetOptions() override;
void setOptions(const OptionsList& options) override;
void sendDragInfo(UInt32 fileCount, const char* info, size_t size) override;
void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override;
String getSecureInputApp() const override;
void secureInputNotification(const String& app) const override;
virtual synergy::IStream*
getStream() const { return NULL; }
bool isPrimary() const { return true; }
synergy::IStream*
getStream() const override { return nullptr; }
bool isPrimary() const override { return true; }
private:
synergy::Screen* m_screen;
bool m_clipboardDirty[kClipboardEnd];

View file

@ -511,6 +511,14 @@ Server::switchScreen(BaseClientProxy* dst,
}
}
#if defined(__APPLE__)
String secureInputApplication = m_active->getSecureInputApp();
if (m_active == m_primaryClient && secureInputApplication != "") {
dst->secureInputNotification(secureInputApplication);
}
#endif
// cut over
m_active = dst;

View file

@ -20,6 +20,7 @@
#include "common/IInterface.h"
#include "synergy/IApp.h"
#include "base/String.h"
class IAppUtil : public IInterface {
public:
@ -28,4 +29,5 @@ public:
virtual int run(int argc, char** argv) = 0;
virtual void beforeAppExit() = 0;
virtual void startNode() = 0;
virtual void showNotification(const String& title, const String& text) const = 0;
};

View file

@ -133,11 +133,11 @@ public:
//! Change dragging status
virtual void setDraggingStarted(bool started) = 0;
//! Send desktop user notification
//! Determine the name of the app causing a secure input state
/*!
Creates a platform dependant user notificaiton using native APIs
On MacOS check which app causes a secure input state to be enabled. No alternative on other platforms
*/
virtual void createNotification(const String& title, const String& content) const = 0;
virtual String getSecureInputApp() const = 0;
//@}
//! @name accessors

View file

@ -522,10 +522,10 @@ Screen::leaveSecondary()
m_screen->fakeAllKeysUp();
}
void
Screen::createNotification(const String& title, const String& content) const
String
Screen::getSecureInputApp() const
{
m_screen->createNotification(title, content);
return m_screen->getSecureInputApp();
}
}

View file

@ -234,11 +234,11 @@ public:
void setEnableDragDrop(bool enabled);
//! Send desktop user notification
//! Determine the name of the app causing a secure input state
/*!
Creates a platform dependant user notificaiton using native APIs
On MacOS check which app causes a secure input state to be enabled. No alternative on other platforms
*/
virtual void createNotification(const String& title, const String& content) const;
String getSecureInputApp() const;
//@}
//! @name accessors

View file

@ -18,36 +18,37 @@
#include "synergy/protocol_types.h"
const char* kMsgHello = "Synergy%2i%2i";
const char* kMsgHelloBack = "Synergy%2i%2i%s";
const char* kMsgCNoop = "CNOP";
const char* kMsgCClose = "CBYE";
const char* kMsgCEnter = "CINN%2i%2i%4i%2i";
const char* kMsgCLeave = "COUT";
const char* kMsgCClipboard = "CCLP%1i%4i";
const char* kMsgCScreenSaver = "CSEC%1i";
const char* kMsgCResetOptions = "CROP";
const char* kMsgCInfoAck = "CIAK";
const char* kMsgCKeepAlive = "CALV";
const char* kMsgDKeyDown = "DKDN%2i%2i%2i";
const char* kMsgDKeyDown1_0 = "DKDN%2i%2i";
const char* kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i";
const char* kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i";
const char* kMsgDKeyUp = "DKUP%2i%2i%2i";
const char* kMsgDKeyUp1_0 = "DKUP%2i%2i";
const char* kMsgDMouseDown = "DMDN%1i";
const char* kMsgDMouseUp = "DMUP%1i";
const char* kMsgDMouseMove = "DMMV%2i%2i";
const char* kMsgDMouseRelMove = "DMRM%2i%2i";
const char* kMsgDMouseWheel = "DMWM%2i%2i";
const char* kMsgDMouseWheel1_0 = "DMWM%2i";
const char* kMsgDClipboard = "DCLP%1i%4i%1i%s";
const char* kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i";
const char* kMsgDSetOptions = "DSOP%4I";
const char* kMsgDFileTransfer = "DFTR%1i%s";
const char* kMsgDDragInfo = "DDRG%2i%s";
const char* kMsgQInfo = "QINF";
const char* kMsgEIncompatible = "EICV%2i%2i";
const char* kMsgEBusy = "EBSY";
const char* kMsgEUnknown = "EUNK";
const char* kMsgEBad = "EBAD";
const char* const kMsgHello = "Synergy%2i%2i";
const char* const kMsgHelloBack = "Synergy%2i%2i%s";
const char* const kMsgCNoop = "CNOP";
const char* const kMsgCClose = "CBYE";
const char* const kMsgCEnter = "CINN%2i%2i%4i%2i";
const char* const kMsgCLeave = "COUT";
const char* const kMsgCClipboard = "CCLP%1i%4i";
const char* const kMsgCScreenSaver = "CSEC%1i";
const char* const kMsgCResetOptions = "CROP";
const char* const kMsgCInfoAck = "CIAK";
const char* const kMsgCKeepAlive = "CALV";
const char* const kMsgDKeyDown = "DKDN%2i%2i%2i";
const char* const kMsgDKeyDown1_0 = "DKDN%2i%2i";
const char* const kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i";
const char* const kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i";
const char* const kMsgDKeyUp = "DKUP%2i%2i%2i";
const char* const kMsgDKeyUp1_0 = "DKUP%2i%2i";
const char* const kMsgDMouseDown = "DMDN%1i";
const char* const kMsgDMouseUp = "DMUP%1i";
const char* const kMsgDMouseMove = "DMMV%2i%2i";
const char* const kMsgDMouseRelMove = "DMRM%2i%2i";
const char* const kMsgDMouseWheel = "DMWM%2i%2i";
const char* const kMsgDMouseWheel1_0 = "DMWM%2i";
const char* const kMsgDClipboard = "DCLP%1i%4i%1i%s";
const char* const kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i";
const char* const kMsgDSetOptions = "DSOP%4I";
const char* const kMsgDFileTransfer = "DFTR%1i%s";
const char* const kMsgDDragInfo = "DDRG%2i%s";
const char* const kMsgDSecureInputNotification = "SECN%s";
const char* const kMsgQInfo = "QINF";
const char* const kMsgEIncompatible = "EICV%2i%2i";
const char* const kMsgEBusy = "EBSY";
const char* const kMsgEUnknown = "EUNK";
const char* const kMsgEBad = "EBAD";

View file

@ -31,7 +31,7 @@
// 1.6: adds clipboard streaming
// NOTE: with new version, synergy minor version should increment
static const SInt16 kProtocolMajorVersion = 1;
static const SInt16 kProtocolMinorVersion = 6;
static const SInt16 kProtocolMinorVersion = 7;
// default contact port number
static const UInt16 kDefaultPort = 24800;
@ -103,13 +103,13 @@ enum EDataReceived {
// say hello to client; primary -> secondary
// $1 = protocol major version number supported by server. $2 =
// protocol minor version number supported by server.
extern const char* kMsgHello;
extern const char* const kMsgHello;
// respond to hello from server; secondary -> primary
// $1 = protocol major version number supported by client. $2 =
// protocol minor version number supported by client. $3 = client
// name.
extern const char* kMsgHelloBack;
extern const char* const kMsgHelloBack;
//
@ -117,10 +117,10 @@ extern const char* kMsgHelloBack;
//
// no operation; secondary -> primary
extern const char* kMsgCNoop;
extern const char* const kMsgCNoop;
// close connection; primary -> secondary
extern const char* kMsgCClose;
extern const char* const kMsgCClose;
// enter screen: primary -> secondary
// entering screen at screen position $1 = x, $2 = y. x,y are
@ -130,7 +130,7 @@ extern const char* kMsgCClose;
// mask. this will have bits set for each toggle modifier key
// that is activated on entry to the screen. the secondary screen
// should adjust its toggle modifiers to reflect that state.
extern const char* kMsgCEnter;
extern const char* const kMsgCEnter;
// leave screen: primary -> secondary
// leaving screen. the secondary screen should send clipboard
@ -139,28 +139,28 @@ extern const char* kMsgCEnter;
// not received a kMsgCClipboard for with a greater sequence
// number) and that were grabbed or have changed since the
// last leave.
extern const char* kMsgCLeave;
extern const char* const kMsgCLeave;
// grab clipboard: primary <-> secondary
// sent by screen when some other app on that screen grabs a
// clipboard. $1 = the clipboard identifier, $2 = sequence number.
// secondary screens must use the sequence number passed in the
// most recent kMsgCEnter. the primary always sends 0.
extern const char* kMsgCClipboard;
extern const char* const kMsgCClipboard;
// screensaver change: primary -> secondary
// screensaver on primary has started ($1 == 1) or closed ($1 == 0)
extern const char* kMsgCScreenSaver;
extern const char* const kMsgCScreenSaver;
// reset options: primary -> secondary
// client should reset all of its options to their defaults.
extern const char* kMsgCResetOptions;
extern const char* const kMsgCResetOptions;
// resolution change acknowledgment: primary -> secondary
// sent by primary in response to a secondary screen's kMsgDInfo.
// this is sent for every kMsgDInfo, whether or not the primary
// had sent a kMsgQInfo.
extern const char* kMsgCInfoAck;
extern const char* const kMsgCInfoAck;
// keep connection alive: primary <-> secondary
// sent by the server periodically to verify that connections are still
@ -170,7 +170,7 @@ extern const char* kMsgCInfoAck;
// client doesn't receive these (or any message) periodically then it
// should disconnect from the server. the appropriate interval is
// defined by an option.
extern const char* kMsgCKeepAlive;
extern const char* const kMsgCKeepAlive;
//
// data codes
@ -187,57 +187,57 @@ extern const char* kMsgCKeepAlive;
// the press. this can happen with combining (dead) keys or if
// the keyboard layouts are not identical and the user releases
// a modifier key before releasing the modified key.
extern const char* kMsgDKeyDown;
extern const char* const kMsgDKeyDown;
// key pressed 1.0: same as above but without KeyButton
extern const char* kMsgDKeyDown1_0;
extern const char* const kMsgDKeyDown1_0;
// key auto-repeat: primary -> secondary
// $1 = KeyID, $2 = KeyModifierMask, $3 = number of repeats, $4 = KeyButton
extern const char* kMsgDKeyRepeat;
extern const char* const kMsgDKeyRepeat;
// key auto-repeat 1.0: same as above but without KeyButton
extern const char* kMsgDKeyRepeat1_0;
extern const char* const kMsgDKeyRepeat1_0;
// key released: primary -> secondary
// $1 = KeyID, $2 = KeyModifierMask, $3 = KeyButton
extern const char* kMsgDKeyUp;
extern const char* const kMsgDKeyUp;
// key released 1.0: same as above but without KeyButton
extern const char* kMsgDKeyUp1_0;
extern const char* const kMsgDKeyUp1_0;
// mouse button pressed: primary -> secondary
// $1 = ButtonID
extern const char* kMsgDMouseDown;
extern const char* const kMsgDMouseDown;
// mouse button released: primary -> secondary
// $1 = ButtonID
extern const char* kMsgDMouseUp;
extern const char* const kMsgDMouseUp;
// mouse moved: primary -> secondary
// $1 = x, $2 = y. x,y are absolute screen coordinates.
extern const char* kMsgDMouseMove;
extern const char* const kMsgDMouseMove;
// relative mouse move: primary -> secondary
// $1 = dx, $2 = dy. dx,dy are motion deltas.
extern const char* kMsgDMouseRelMove;
extern const char* const kMsgDMouseRelMove;
// mouse scroll: primary -> secondary
// $1 = xDelta, $2 = yDelta. the delta should be +120 for one tick forward
// (away from the user) or right and -120 for one tick backward (toward
// the user) or left.
extern const char* kMsgDMouseWheel;
extern const char* const kMsgDMouseWheel;
// mouse vertical scroll: primary -> secondary
// like as kMsgDMouseWheel except only sends $1 = yDelta.
extern const char* kMsgDMouseWheel1_0;
extern const char* const kMsgDMouseWheel1_0;
// clipboard data: primary <-> secondary
// $2 = sequence number, $3 = mark $4 = clipboard data. the sequence number
// is 0 when sent by the primary. secondary screens should use the
// sequence number from the most recent kMsgCEnter. $1 = clipboard
// identifier.
extern const char* kMsgDClipboard;
extern const char* const kMsgDClipboard;
// client data: secondary -> primary
// $1 = coordinate of leftmost pixel on secondary screen,
@ -253,25 +253,30 @@ extern const char* kMsgDClipboard;
// should ignore any kMsgDMouseMove messages until it receives a
// kMsgCInfoAck in order to prevent attempts to move the mouse off
// the new screen area.
extern const char* kMsgDInfo;
extern const char* const kMsgDInfo;
// set options: primary -> secondary
// client should set the given option/value pairs. $1 = option/value
// pairs.
extern const char* kMsgDSetOptions;
extern const char* const kMsgDSetOptions;
// file data: primary <-> secondary
// transfer file data. A mark is used in the first byte.
// 0 means the content followed is the file size.
// 1 means the content followed is the chunk data.
// 2 means the file transfer is finished.
extern const char* kMsgDFileTransfer;
extern const char* const kMsgDFileTransfer;
// drag infomation: primary <-> secondary
// transfer drag infomation. The first 2 bytes are used for storing
// the number of dragging objects. Then the following string consists
// of each object's directory.
extern const char* kMsgDDragInfo;
extern const char* const kMsgDDragInfo;
// secure input notification: primary -> secondary
// $1 = app. app only obtainable on MacOS since that's the only
// platform facing secure input problems
extern const char* const kMsgDSecureInputNotification;
//
// query codes
@ -279,7 +284,7 @@ extern const char* kMsgDDragInfo;
// query screen info: primary -> secondary
// client should reply with a kMsgDInfo.
extern const char* kMsgQInfo;
extern const char* const kMsgQInfo;
//
@ -288,19 +293,19 @@ extern const char* kMsgQInfo;
// incompatible versions: primary -> secondary
// $1 = major version of primary, $2 = minor version of primary.
extern const char* kMsgEIncompatible;
extern const char* const kMsgEIncompatible;
// name provided when connecting is already in use: primary -> secondary
extern const char* kMsgEBusy;
extern const char* const kMsgEBusy;
// unknown client: primary -> secondary
// name provided when connecting is not in primary's screen
// configuration map.
extern const char* kMsgEUnknown;
extern const char* const kMsgEUnknown;
// protocol violation: primary -> secondary
// primary should disconnect after sending this message.
extern const char* kMsgEBad;
extern const char* const kMsgEBad;
//

View file

@ -18,6 +18,8 @@
#include "synergy/unix/AppUtilUnix.h"
#include "synergy/ArgsBase.h"
#include "base/Log.h"
#include "base/log_outputters.h"
AppUtilUnix::AppUtilUnix(IEventQueue* events)
{
@ -44,3 +46,16 @@ AppUtilUnix::startNode()
{
app().startNode();
}
void
AppUtilUnix::showNotification(const String & title, const String & text) const
{
LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
#if WINAPI_XWINDOWS
#elif WINAPI_CARBON
// synergys and synergyc are not allowed to send native notifications on MacOS
// instead ask main synergy process to show them instead
LOG((CLOG_INFO "OSX Notification: %s|%s", title.c_str(), text.c_str()));
#endif
}

View file

@ -31,4 +31,5 @@ public:
int run(int argc, char** argv);
void startNode();
void showNotification(const String& title, const String& text) const override;
};

View file

@ -180,3 +180,9 @@ AppUtilWindows::startNode()
{
app().startNode();
}
void
AppUtilWindows::showNotification(const String & title, const String & text) const
{
LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str()));
}

View file

@ -54,6 +54,8 @@ public:
void startNode();
void showNotification(const String& title, const String& text) const override;
private:
AppExitMode m_exitMode;
IEventQueue* m_events;