From c22571658dd41fe9460941d8b8021574416f9719 Mon Sep 17 00:00:00 2001 From: draekko Date: Mon, 20 Feb 2023 16:06:45 -0500 Subject: [PATCH 1/5] fixed X11 clipboard issues, added support for size limit, added image support for webp/tiff/png/jpg --- src/gui/src/ServerConfig.cpp | 19 ++++ src/gui/src/ServerConfig.h | 6 +- src/gui/src/ServerConfigDialog.cpp | 3 + src/gui/src/ServerConfigDialogBase.ui | 107 +++++++++++------- src/lib/barrier/IClipboard.h | 8 +- src/lib/barrier/option_types.h | 1 + src/lib/client/Client.cpp | 22 +++- src/lib/client/Client.h | 1 + src/lib/platform/XWindowsClipboard.cpp | 63 ++++++++--- .../XWindowsClipboardAnyBitmapConverter.cpp | 4 + .../XWindowsClipboardBMPConverter.cpp | 8 ++ .../XWindowsClipboardHTMLConverter.cpp | 4 + .../XWindowsClipboardTextConverter.cpp | 4 + .../XWindowsClipboardUCS2Converter.cpp | 4 + .../XWindowsClipboardUTF8Converter.cpp | 4 + src/lib/platform/XWindowsUtil.cpp | 6 +- src/lib/server/Config.cpp | 9 +- src/lib/server/Server.cpp | 21 +++- src/lib/server/Server.h | 1 + 19 files changed, 229 insertions(+), 66 deletions(-) diff --git a/src/gui/src/ServerConfig.cpp b/src/gui/src/ServerConfig.cpp index 3392572a..ed237b46 100644 --- a/src/gui/src/ServerConfig.cpp +++ b/src/gui/src/ServerConfig.cpp @@ -52,6 +52,7 @@ ServerConfig::ServerConfig(QSettings* settings, int numColumns, int numRows , m_IgnoreAutoConfigClient(false), m_EnableDragAndDrop(false), m_ClipboardSharing(true), + m_ClipboardSharingSize(defaultClipboardSharingSize()), m_pMainWindow(mainWindow) { Q_ASSERT(m_pSettings); @@ -119,6 +120,7 @@ void ServerConfig::saveSettings() settings().setValue("ignoreAutoConfigClient", ignoreAutoConfigClient()); settings().setValue("enableDragAndDrop", enableDragAndDrop()); settings().setValue("clipboardSharing", clipboardSharing()); + settings().setValue("clipboardSharingSize", (int)clipboardSharingSize()); writeSettings(settings(), switchCorners(), "switchCorner"); @@ -164,6 +166,8 @@ void ServerConfig::loadSettings() setIgnoreAutoConfigClient(settings().value("ignoreAutoConfigClient").toBool()); setEnableDragAndDrop(settings().value("enableDragAndDrop", true).toBool()); setClipboardSharing(settings().value("clipboardSharing", true).toBool()); + setClipboardSharingSize(settings().value("clipboardSharingSize", + (int) ServerConfig::defaultClipboardSharingSize()).toULongLong()); readSettings(settings(), switchCorners(), "switchCorner", false, static_cast(SwitchCorner::Count)); @@ -412,3 +416,18 @@ void::ServerConfig::addToFirstEmptyGrid(const QString &clientName) } } } + +size_t ServerConfig::defaultClipboardSharingSize() { + return 100 * 1000 * 1000; // 100 MB +} + +size_t ServerConfig::setClipboardSharingSize(size_t size) { + if (size) { + setClipboardSharing(true); + } else { + setClipboardSharing(false); + } + using std::swap; + swap (size, m_ClipboardSharingSize); + return size; +} diff --git a/src/gui/src/ServerConfig.h b/src/gui/src/ServerConfig.h index 9f3e2db1..d11727fc 100644 --- a/src/gui/src/ServerConfig.h +++ b/src/gui/src/ServerConfig.h @@ -63,7 +63,9 @@ class ServerConfig : public BaseConfig bool ignoreAutoConfigClient() const { return m_IgnoreAutoConfigClient; } bool enableDragAndDrop() const { return m_EnableDragAndDrop; } bool clipboardSharing() const { return m_ClipboardSharing; } - + size_t clipboardSharingSize() const { return m_ClipboardSharingSize; } + static size_t defaultClipboardSharingSize(); + void saveSettings(); void loadSettings(); bool save(const QString& fileName) const; @@ -92,6 +94,7 @@ class ServerConfig : public BaseConfig void setIgnoreAutoConfigClient(bool on) { m_IgnoreAutoConfigClient = on; } void setEnableDragAndDrop(bool on) { m_EnableDragAndDrop = on; } void setClipboardSharing(bool on) { m_ClipboardSharing = on; } + size_t setClipboardSharingSize(size_t size); QList& switchCorners() { return m_SwitchCorners; } std::vector& hotkeys() { return m_Hotkeys; } @@ -125,6 +128,7 @@ class ServerConfig : public BaseConfig bool m_IgnoreAutoConfigClient; bool m_EnableDragAndDrop; bool m_ClipboardSharing; + size_t m_ClipboardSharingSize; MainWindow* m_pMainWindow; }; diff --git a/src/gui/src/ServerConfigDialog.cpp b/src/gui/src/ServerConfigDialog.cpp index 84c20470..60766fab 100644 --- a/src/gui/src/ServerConfigDialog.cpp +++ b/src/gui/src/ServerConfigDialog.cpp @@ -59,6 +59,8 @@ ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, co m_pCheckBoxEnableDragAndDrop->setChecked(serverConfig().enableDragAndDrop()); m_pCheckBoxEnableClipboard->setChecked(serverConfig().clipboardSharing()); + m_pSpinBoxClipboardSizeLimit->setValue(serverConfig().clipboardSharingSize()); + m_pSpinBoxClipboardSizeLimit->setEnabled(serverConfig().clipboardSharing()); for (const Hotkey& hotkey : serverConfig().hotkeys()) { m_pListHotkeys->addItem(hotkey.text()); @@ -108,6 +110,7 @@ void ServerConfigDialog::accept() serverConfig().setIgnoreAutoConfigClient(m_pCheckBoxIgnoreAutoConfigClient->isChecked()); serverConfig().setEnableDragAndDrop(m_pCheckBoxEnableDragAndDrop->isChecked()); serverConfig().setClipboardSharing(m_pCheckBoxEnableClipboard->isChecked()); + serverConfig().setClipboardSharingSize(m_pSpinBoxClipboardSizeLimit->value()); // now that the dialog has been accepted, copy the new server config to the original one, // which is a reference to the one in MainWindow. diff --git a/src/gui/src/ServerConfigDialogBase.ui b/src/gui/src/ServerConfigDialogBase.ui index 9c2e747a..265a7404 100644 --- a/src/gui/src/ServerConfigDialogBase.ui +++ b/src/gui/src/ServerConfigDialogBase.ui @@ -6,8 +6,8 @@ 0 0 - 795 - 534 + 816 + 580 @@ -17,7 +17,7 @@ - 0 + 2 @@ -44,7 +44,7 @@ - :/res/icons/64x64/user-trash.png + :/res/icons/64x64/user-trash.png @@ -82,7 +82,7 @@ - :/res/icons/64x64/video-display.png + :/res/icons/64x64/video-display.png @@ -422,13 +422,27 @@ Double click on a screen to edit its settings. &Options - - + + + + Enable drag and drop file transfers + + + + + + + Ignore auto config clients + + + + + true - Don't take &foreground window on Windows servers + S&ynchronize screen savers @@ -442,13 +456,36 @@ Double click on a screen to edit its settings. - - + + true - S&ynchronize screen savers + Don't take &foreground window on Windows servers + + + + + + + Qt::Vertical + + + + 20 + 16 + + + + + + + + Enable clipboard sharing + + + true @@ -505,41 +542,23 @@ Double click on a screen to edit its settings. - - - - Qt::Vertical - - - - 20 - 16 - - - - - - - - Enable drag and drop file transfers - - - - - - - Ignore auto config clients - - - - - - - Enable clipboard sharing - - + + + true + + 1000000 + + + 1000000000 + + + 1000 + + + 100000000 + diff --git a/src/lib/barrier/IClipboard.h b/src/lib/barrier/IClipboard.h index 436b21bc..9a6bd99c 100644 --- a/src/lib/barrier/IClipboard.h +++ b/src/lib/barrier/IClipboard.h @@ -58,8 +58,12 @@ public: enum EFormat { kText, //!< Text format, UTF-8, newline is LF kHTML, //!< HTML format, HTML fragment, UTF-8, newline is LF - kBitmap, //!< Bitmap format, BMP 24/32bpp, BI_RGB - kNumFormats //!< The number of clipboard formats + kBitmap, //!< Bitmap format, BMP 24/32bpp, BI_RGB + kPNG, //!< PNG format + kJpeg, //!< JPEG format + kTiff, //!< TIFF format + kWebp, //!< WEBP format + kNumFormats //!< The number of clipboard formats }; //! @name manipulators diff --git a/src/lib/barrier/option_types.h b/src/lib/barrier/option_types.h index 42103d41..37bbf6c3 100644 --- a/src/lib/barrier/option_types.h +++ b/src/lib/barrier/option_types.h @@ -68,6 +68,7 @@ static const OptionID kOptionScreenPreserveFocus = OPTION_CODE("SFOC") static const OptionID kOptionRelativeMouseMoves = OPTION_CODE("MDLT"); static const OptionID kOptionWin32KeepForeground = OPTION_CODE("_KFW"); static const OptionID kOptionClipboardSharing = OPTION_CODE("CLPS"); +static const OptionID kOptionClipboardSharingSize = OPTION_CODE("CLSZ"); //@} //! @name Screen switch corner enumeration diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index a7b15cf5..da7f9384 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -70,7 +70,8 @@ Client::Client(IEventQueue* events, const std::string& name, const NetworkAddres m_socket(NULL), m_useSecureNetwork(args.m_enableCrypto), m_args(args), - m_enableClipboard(true) + m_enableClipboard(true), + m_maximumClipboardSize(INT_MAX) { assert(m_socketFactory != NULL); assert(m_screen != NULL); @@ -369,9 +370,20 @@ Client::setOptions(const OptionsList& options) m_enableClipboard = *index; break; + } else if (id == kOptionClipboardSharingSize) { + index++; + if (index != options.end()) { + m_maximumClipboardSize = *index; + } } } + if (m_enableClipboard && !m_maximumClipboardSize) { + m_enableClipboard = false; + LOG((CLOG_NOTE "clipboard sharing is disabled because the server " + "set the maximum clipboard size to 0")); + } + m_screen->setOptions(options); } @@ -406,6 +418,12 @@ Client::sendClipboard(ClipboardID id) // marshall the data std::string data = clipboard.marshall(); + if (data.size() >= m_maximumClipboardSize) { + LOG((CLOG_NOTE "Skipping clipboard transfer because the clipboard" + " contents exceeds the %i MB size limit set by the server", + m_maximumClipboardSize)); + return; + } // save and send data if different or not yet sent if (!m_sentClipboard[id] || data != m_dataClipboard[id]) { @@ -660,7 +678,7 @@ Client::handleShapeChanged(const Event&, void*) void Client::handleClipboardGrabbed(const Event& event, void*) { - if (!m_enableClipboard) { + if (!m_enableClipboard || (m_maximumClipboardSize == 0)) { return; } diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index c172af22..60502a6a 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -224,4 +224,5 @@ private: bool m_useSecureNetwork; ClientArgs m_args; bool m_enableClipboard; + size_t m_maximumClipboardSize; }; diff --git a/src/lib/platform/XWindowsClipboard.cpp b/src/lib/platform/XWindowsClipboard.cpp index 27321e5d..dd3d99fb 100644 --- a/src/lib/platform/XWindowsClipboard.cpp +++ b/src/lib/platform/XWindowsClipboard.cpp @@ -23,6 +23,10 @@ #include "platform/XWindowsClipboardUTF8Converter.h" #include "platform/XWindowsClipboardHTMLConverter.h" #include "platform/XWindowsClipboardBMPConverter.h" +#include "platform/XWindowsClipboardJPGConverter.h" +#include "platform/XWindowsClipboardPNGConverter.h" +#include "platform/XWindowsClipboardTIFConverter.h" +#include "platform/XWindowsClipboardWEBPConverter.h" #include "platform/XWindowsUtil.h" #include "mt/Thread.h" #include "arch/Arch.h" @@ -82,11 +86,15 @@ XWindowsClipboard::XWindowsClipboard(IXWindowsImpl* impl, Display* display, } // add converters, most desired first + m_converters.push_back(new XWindowsClipboardPNGConverter(m_display)); + m_converters.push_back(new XWindowsClipboardWEBPConverter(m_display)); + m_converters.push_back(new XWindowsClipboardJPGConverter(m_display)); + m_converters.push_back(new XWindowsClipboardTIFConverter(m_display)); + m_converters.push_back(new XWindowsClipboardBMPConverter(m_display)); m_converters.push_back(new XWindowsClipboardHTMLConverter(m_display, "text/html")); m_converters.push_back(new XWindowsClipboardHTMLConverter(m_display, "application/x-moz-nativehtml")); - m_converters.push_back(new XWindowsClipboardBMPConverter(m_display)); m_converters.push_back(new XWindowsClipboardUTF8Converter(m_display, "text/plain;charset=UTF-8")); m_converters.push_back(new XWindowsClipboardUTF8Converter(m_display, @@ -545,31 +553,54 @@ XWindowsClipboard::icccmFillCache() // available rather than checking TARGETS. i've seen clipboard // owners that don't report all the targets they support. target = converter->getAtom(); - /* + #if 0 for (UInt32 i = 0; i < numTargets; ++i) { if (converter->getAtom() == targets[i]) { target = targets[i]; break; } } - */ + #endif if (target == None) { continue; } // get the data Atom actualTarget; + IClipboard::EFormat format = converter->getFormat(); std::string targetData; + if (!icccmGetSelection(target, &actualTarget, &targetData)) { LOG((CLOG_DEBUG1 " no data for target %s", XWindowsUtil::atomToString(m_display, target).c_str())); + m_added[format] = false; + continue; + } + + if (actualTarget != target) { + LOG((CLOG_DEBUG1 " target %s not same as actual target %s", + XWindowsUtil::atomToString(m_display, target).c_str(), + XWindowsUtil::atomToString(m_display, actualTarget).c_str())); + m_added[format] = false; + continue; + } + + if (targetData.empty()) { + m_added[format] = false; + LOG((CLOG_DEBUG1 " no targetdata for target %s (actual target %s)", + XWindowsUtil::atomToString(m_display, target).c_str(), + XWindowsUtil::atomToString(m_display, actualTarget).c_str())); continue; } - // add to clipboard and note we've done it - IClipboard::EFormat format = converter->getFormat(); - m_data[format] = converter->toIClipboard(targetData); - m_added[format] = true; - LOG((CLOG_DEBUG "added format %d for target %s (%u %s)", format, XWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes")); + if (!converter->toIClipboard(targetData).empty()) { + // add to clipboard and note we've done it + m_data[format] = converter->toIClipboard(targetData); + m_added[format] = true; + LOG((CLOG_DEBUG " added format %d for target %s (%u %s)", format, XWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes")); + } else { + LOG((CLOG_DEBUG1 " no clipboard data for target %s", XWindowsUtil::atomToString(m_display, target).c_str())); + m_added[format] = false; + } } } @@ -799,17 +830,23 @@ XWindowsClipboard::motifFillCache() // get the data (finally) Atom actualTarget; + IClipboard::EFormat format = converter->getFormat(); std::string targetData; if (!motifGetSelection(&motifFormat, &actualTarget, &targetData)) { LOG((CLOG_DEBUG1 " no data for target %s", XWindowsUtil::atomToString(m_display, target).c_str())); + m_added[format] = false; continue; } - // add to clipboard and note we've done it - IClipboard::EFormat format = converter->getFormat(); - m_data[format] = converter->toIClipboard(targetData); - m_added[format] = true; - LOG((CLOG_DEBUG "added format %d for target %s", format, XWindowsUtil::atomToString(m_display, target).c_str())); + if (!converter->toIClipboard(targetData).empty()) { + // add to clipboard and note we've done it + m_data[format] = converter->toIClipboard(targetData); + m_added[format] = true; + LOG((CLOG_DEBUG " added format %d for target %s (%u %s)", format, XWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes")); + } else { + LOG((CLOG_DEBUG1 " no clipboard data for target %s", XWindowsUtil::atomToString(m_display, target).c_str())); + m_added[format] = false; + } } } diff --git a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp index 0190f1d4..f4bc8484 100644 --- a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp +++ b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp @@ -161,6 +161,10 @@ std::string XWindowsClipboardAnyBitmapConverter::fromIClipboard(const std::strin std::string XWindowsClipboardAnyBitmapConverter::toIClipboard(const std::string& image) const { + if (image.empty()) { + return {}; + } + // convert to raw BMP data UInt32 w, h, depth; std::string rawBMP = doToIClipboard(image, w, h, depth); diff --git a/src/lib/platform/XWindowsClipboardBMPConverter.cpp b/src/lib/platform/XWindowsClipboardBMPConverter.cpp index fd3325e1..0be1a44f 100644 --- a/src/lib/platform/XWindowsClipboardBMPConverter.cpp +++ b/src/lib/platform/XWindowsClipboardBMPConverter.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include "base/Log.h" #include "platform/XWindowsClipboardBMPConverter.h" // BMP file header structure @@ -103,6 +104,11 @@ XWindowsClipboardBMPConverter::getDataSize() const std::string XWindowsClipboardBMPConverter::fromIClipboard(const std::string& bmp) const { + if (bmp.size() <= 14 + 40) { + LOG((CLOG_DEBUG2 "fromIClipboard BMP, sized failed")); + return {}; + } + // create BMP image UInt8 header[14]; UInt8* dst = header; @@ -128,6 +134,8 @@ std::string XWindowsClipboardBMPConverter::toIClipboard(const std::string& bmp) return {}; } + LOG((CLOG_DEBUG2 "Prepare BMP")); + // get offset to image data UInt32 offset = fromLEU32(rawBMPHeader + 10); diff --git a/src/lib/platform/XWindowsClipboardHTMLConverter.cpp b/src/lib/platform/XWindowsClipboardHTMLConverter.cpp index eae032d5..344bf5b9 100644 --- a/src/lib/platform/XWindowsClipboardHTMLConverter.cpp +++ b/src/lib/platform/XWindowsClipboardHTMLConverter.cpp @@ -61,6 +61,10 @@ std::string XWindowsClipboardHTMLConverter::fromIClipboard(const std::string& da std::string XWindowsClipboardHTMLConverter::toIClipboard(const std::string& data) const { + if (data.empty()) { + return {}; + } + // Older Firefox [1] and possibly other applications use UTF-16 for text/html - handle both // [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1497580 if (Unicode::isUTF8(data)) { diff --git a/src/lib/platform/XWindowsClipboardTextConverter.cpp b/src/lib/platform/XWindowsClipboardTextConverter.cpp index ee34f135..3e4516f2 100644 --- a/src/lib/platform/XWindowsClipboardTextConverter.cpp +++ b/src/lib/platform/XWindowsClipboardTextConverter.cpp @@ -61,6 +61,10 @@ std::string XWindowsClipboardTextConverter::fromIClipboard(const std::string& da std::string XWindowsClipboardTextConverter::toIClipboard(const std::string& data) const { + if (data.empty()) { + return {}; + } + // convert to UTF-8 bool errors; std::string utf8 = Unicode::textToUTF8(data, &errors); diff --git a/src/lib/platform/XWindowsClipboardUCS2Converter.cpp b/src/lib/platform/XWindowsClipboardUCS2Converter.cpp index 75dd70ea..56290054 100644 --- a/src/lib/platform/XWindowsClipboardUCS2Converter.cpp +++ b/src/lib/platform/XWindowsClipboardUCS2Converter.cpp @@ -61,5 +61,9 @@ std::string XWindowsClipboardUCS2Converter::fromIClipboard(const std::string& da std::string XWindowsClipboardUCS2Converter::toIClipboard(const std::string& data) const { + if (data.empty()) { + return {}; + } + return Unicode::UCS2ToUTF8(data); } diff --git a/src/lib/platform/XWindowsClipboardUTF8Converter.cpp b/src/lib/platform/XWindowsClipboardUTF8Converter.cpp index a452706e..38106259 100644 --- a/src/lib/platform/XWindowsClipboardUTF8Converter.cpp +++ b/src/lib/platform/XWindowsClipboardUTF8Converter.cpp @@ -59,5 +59,9 @@ std::string XWindowsClipboardUTF8Converter::fromIClipboard(const std::string& da std::string XWindowsClipboardUTF8Converter::toIClipboard(const std::string& data) const { + if (data.empty()) { + return {}; + } + return data; } diff --git a/src/lib/platform/XWindowsUtil.cpp b/src/lib/platform/XWindowsUtil.cpp index 7d4bb638..2bb8e050 100644 --- a/src/lib/platform/XWindowsUtil.cpp +++ b/src/lib/platform/XWindowsUtil.cpp @@ -1812,9 +1812,11 @@ XWindowsUtil::ErrorLock::internalHandler(Display* display, XErrorEvent* event) } void -XWindowsUtil::ErrorLock::ignoreHandler(Display*, XErrorEvent* e, void*) +XWindowsUtil::ErrorLock::ignoreHandler(Display* display, XErrorEvent* e, void*) { - LOG((CLOG_DEBUG1 "ignoring X error: %d", e->error_code)); + char errtxt[1024]; + XGetErrorText(display, e->error_code, errtxt, 1023); + LOG((CLOG_DEBUG1 "ignoring X error: %d - %.1023s", e->error_code, errtxt)); } void diff --git a/src/lib/server/Config.cpp b/src/lib/server/Config.cpp index bcdb88cd..c55fa3d4 100644 --- a/src/lib/server/Config.cpp +++ b/src/lib/server/Config.cpp @@ -744,6 +744,9 @@ Config::readSectionOptions(ConfigReadContext& s) else if (name == "clipboardSharing") { addOption("", kOptionClipboardSharing, s.parseBoolean(value)); } + else if (name == "clipboardSharingSize") { + addOption("", kOptionClipboardSharingSize, s.parseInt(value)); + } else { handled = false; @@ -1360,6 +1363,9 @@ Config::getOptionName(OptionID id) if (id == kOptionClipboardSharing) { return "clipboardSharing"; } + if (id == kOptionClipboardSharingSize) { + return "clipboardSharingSize"; + } return NULL; } @@ -1376,7 +1382,8 @@ std::string Config::getOptionValue(OptionID id, OptionValue value) id == kOptionRelativeMouseMoves || id == kOptionWin32KeepForeground || id == kOptionScreenPreserveFocus || - id == kOptionClipboardSharing) { + id == kOptionClipboardSharing || + id == kOptionClipboardSharingSize) { return (value != 0) ? "true" : "false"; } if (id == kOptionModifierMapForShift || diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index a169db16..16aea973 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -90,6 +90,7 @@ Server::Server( m_writeToDropDirThread(NULL), m_ignoreFileTransfer(false), m_enableClipboard(true), + m_maximumClipboardSize(INT_MAX), m_sendDragInfoThread(NULL), m_waitDragInfoThread(true), m_args(args) @@ -511,6 +512,10 @@ Server::switchScreen(BaseClientProxy* dst, if (m_enableClipboard) { // send the clipboard data to new active screen for (ClipboardID id = 0; id < kClipboardEnd; ++id) { + // Hackity hackity hack + if (m_clipboards[id].m_clipboard.marshall().size() > m_maximumClipboardSize) { + continue; + } m_active->setClipboard(id, &m_clipboards[id].m_clipboard); } } @@ -1177,6 +1182,15 @@ Server::processOptions() LOG((CLOG_NOTE "clipboard sharing is disabled")); } } + else if (id == kOptionClipboardSharingSize) { + if (value <= 0) { + m_maximumClipboardSize = 0; + LOG((CLOG_NOTE "clipboard sharing is disabled because the " + "maximum shared clipboard size is set to 0")); + } else { + m_maximumClipboardSize = static_cast(value); + } + } } if (m_relativeMoves && !newRelativeMoves) { stopRelativeMoves(); @@ -1220,7 +1234,7 @@ Server::handleShapeChanged(const Event&, void* vclient) void Server::handleClipboardGrabbed(const Event& event, void* vclient) { - if (!m_enableClipboard) { + if (!m_enableClipboard || (m_maximumClipboardSize == 0)) { return; } @@ -1553,6 +1567,11 @@ Server::onClipboardChanged(BaseClientProxy* sender, // ignore if data hasn't changed std::string data = clipboard.m_clipboard.marshall(); + if (data.size() > m_maximumClipboardSize) { + LOG((CLOG_NOTE "not updating clipboard because it's over the size limit (%i KB) configured by the server", + m_maximumClipboardSize)); + return; + } if (data == clipboard.m_clipboardData) { LOG((CLOG_DEBUG "ignored screen \"%s\" update of clipboard %d (unchanged)", clipboard.m_clipboardOwner.c_str(), id)); return; diff --git a/src/lib/server/Server.h b/src/lib/server/Server.h index ae8b2bd5..8b05ead1 100644 --- a/src/lib/server/Server.h +++ b/src/lib/server/Server.h @@ -475,6 +475,7 @@ private: std::string m_dragFileExt; bool m_ignoreFileTransfer; bool m_enableClipboard; + size_t m_maximumClipboardSize; Thread* m_sendDragInfoThread; bool m_waitDragInfoThread; From 490e23946454b572c2ea7e78959bba7674461cb0 Mon Sep 17 00:00:00 2001 From: draekko Date: Mon, 20 Feb 2023 16:24:30 -0500 Subject: [PATCH 2/5] add missing converters --- .../platform/XWindowsClipboardJPGConverter.h | 40 ++++++++++ .../XWindowsClipboardPNGConverter.cpp | 72 +++++++++++++++++ .../platform/XWindowsClipboardPNGConverter.h | 40 ++++++++++ .../XWindowsClipboardTIFConverter.cpp | 77 +++++++++++++++++++ .../platform/XWindowsClipboardTIFConverter.h | 40 ++++++++++ .../XWindowsClipboardWEBPConverter.cpp | 73 ++++++++++++++++++ .../platform/XWindowsClipboardWEBPConverter.h | 40 ++++++++++ 7 files changed, 382 insertions(+) create mode 100644 src/lib/platform/XWindowsClipboardJPGConverter.h create mode 100644 src/lib/platform/XWindowsClipboardPNGConverter.cpp create mode 100644 src/lib/platform/XWindowsClipboardPNGConverter.h create mode 100644 src/lib/platform/XWindowsClipboardTIFConverter.cpp create mode 100644 src/lib/platform/XWindowsClipboardTIFConverter.h create mode 100644 src/lib/platform/XWindowsClipboardWEBPConverter.cpp create mode 100644 src/lib/platform/XWindowsClipboardWEBPConverter.h diff --git a/src/lib/platform/XWindowsClipboardJPGConverter.h b/src/lib/platform/XWindowsClipboardJPGConverter.h new file mode 100644 index 00000000..03234a86 --- /dev/null +++ b/src/lib/platform/XWindowsClipboardJPGConverter.h @@ -0,0 +1,40 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#pragma once + +#include "platform/XWindowsClipboard.h" + +//! Convert to/from some text encoding +class XWindowsClipboardJPGConverter : + public IXWindowsClipboardConverter { +public: + XWindowsClipboardJPGConverter(Display* display); + virtual ~XWindowsClipboardJPGConverter(); + + // IXWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual Atom getAtom() const; + virtual int getDataSize() const; + virtual std::string fromIClipboard(const std::string&) const; + virtual std::string toIClipboard(const std::string&) const; + +private: + Atom m_atom; +}; diff --git a/src/lib/platform/XWindowsClipboardPNGConverter.cpp b/src/lib/platform/XWindowsClipboardPNGConverter.cpp new file mode 100644 index 00000000..500deddd --- /dev/null +++ b/src/lib/platform/XWindowsClipboardPNGConverter.cpp @@ -0,0 +1,72 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#include "base/Log.h" +#include "platform/XWindowsClipboardPNGConverter.h" + +// +// XWindowsClipboardPNGConverter +// + +XWindowsClipboardPNGConverter::XWindowsClipboardPNGConverter( + Display* display) : + m_atom(XInternAtom(display, "image/png", False)) +{ + // do nothing +} + +XWindowsClipboardPNGConverter::~XWindowsClipboardPNGConverter() +{ + // do nothing +} + +IClipboard::EFormat +XWindowsClipboardPNGConverter::getFormat() const +{ + return IClipboard::kPNG; +} + +Atom +XWindowsClipboardPNGConverter::getAtom() const +{ + return m_atom; +} + +int +XWindowsClipboardPNGConverter::getDataSize() const +{ + return 8; +} + +std::string XWindowsClipboardPNGConverter::fromIClipboard(const std::string& pngdata) const +{ + return pngdata; +} + +std::string XWindowsClipboardPNGConverter::toIClipboard(const std::string& pngdata) const +{ + // check PNG file header + const UInt8* rawPNGHeader = reinterpret_cast(pngdata.data()); + + if (rawPNGHeader[0] == 0x89 && rawPNGHeader[1] == 0x50 && rawPNGHeader[2] == 0x4e && rawPNGHeader[3] == 0x47) { + LOG((CLOG_DEBUG2 "Prepare PNG")); + return pngdata; + } + + return {}; +} diff --git a/src/lib/platform/XWindowsClipboardPNGConverter.h b/src/lib/platform/XWindowsClipboardPNGConverter.h new file mode 100644 index 00000000..71598855 --- /dev/null +++ b/src/lib/platform/XWindowsClipboardPNGConverter.h @@ -0,0 +1,40 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#pragma once + +#include "platform/XWindowsClipboard.h" + +//! Convert to/from some text encoding +class XWindowsClipboardPNGConverter : + public IXWindowsClipboardConverter { +public: + XWindowsClipboardPNGConverter(Display* display); + virtual ~XWindowsClipboardPNGConverter(); + + // IXWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual Atom getAtom() const; + virtual int getDataSize() const; + virtual std::string fromIClipboard(const std::string&) const; + virtual std::string toIClipboard(const std::string&) const; + +private: + Atom m_atom; +}; diff --git a/src/lib/platform/XWindowsClipboardTIFConverter.cpp b/src/lib/platform/XWindowsClipboardTIFConverter.cpp new file mode 100644 index 00000000..11ea040b --- /dev/null +++ b/src/lib/platform/XWindowsClipboardTIFConverter.cpp @@ -0,0 +1,77 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#include "base/Log.h" +#include "platform/XWindowsClipboardTIFConverter.h" + +// +// XWindowsClipboardTIFConverter +// + +XWindowsClipboardTIFConverter::XWindowsClipboardTIFConverter( + Display* display) : + m_atom(XInternAtom(display, "image/tiff", False)) +{ + // do nothing +} + +XWindowsClipboardTIFConverter::~XWindowsClipboardTIFConverter() +{ + // do nothing +} + +IClipboard::EFormat +XWindowsClipboardTIFConverter::getFormat() const +{ + return IClipboard::kTiff; +} + +Atom +XWindowsClipboardTIFConverter::getAtom() const +{ + return m_atom; +} + +int +XWindowsClipboardTIFConverter::getDataSize() const +{ + return 8; +} + +std::string XWindowsClipboardTIFConverter::fromIClipboard(const std::string& tiffdata) const +{ + return tiffdata; +} + +std::string XWindowsClipboardTIFConverter::toIClipboard(const std::string& tiffdata) const +{ + // check TIFF file header, veirfy if Big or Little Endian + const UInt8* rawTIFHeader = reinterpret_cast(tiffdata.data()); + + if (rawTIFHeader[0] == 0x49 && rawTIFHeader[1] == 0x49 && rawTIFHeader[2] == 0x2a && rawTIFHeader[3] == 0x00) { + LOG((CLOG_DEBUG2 "Prepare Tiff (BE)")); + return tiffdata; + } + + if (rawTIFHeader[0] == 0x4D && rawTIFHeader[1] == 0x4D && rawTIFHeader[2] == 0x00 && rawTIFHeader[3] == 0x2a) { + LOG((CLOG_DEBUG2 "Prepare Tiff (LE)")); + return tiffdata; + } + + return {}; +} diff --git a/src/lib/platform/XWindowsClipboardTIFConverter.h b/src/lib/platform/XWindowsClipboardTIFConverter.h new file mode 100644 index 00000000..3d1621de --- /dev/null +++ b/src/lib/platform/XWindowsClipboardTIFConverter.h @@ -0,0 +1,40 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#pragma once + +#include "platform/XWindowsClipboard.h" + +//! Convert to/from some text encoding +class XWindowsClipboardTIFConverter : + public IXWindowsClipboardConverter { +public: + XWindowsClipboardTIFConverter(Display* display); + virtual ~XWindowsClipboardTIFConverter(); + + // IXWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual Atom getAtom() const; + virtual int getDataSize() const; + virtual std::string fromIClipboard(const std::string&) const; + virtual std::string toIClipboard(const std::string&) const; + +private: + Atom m_atom; +}; diff --git a/src/lib/platform/XWindowsClipboardWEBPConverter.cpp b/src/lib/platform/XWindowsClipboardWEBPConverter.cpp new file mode 100644 index 00000000..72df4ca6 --- /dev/null +++ b/src/lib/platform/XWindowsClipboardWEBPConverter.cpp @@ -0,0 +1,73 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#include "base/Log.h" +#include "platform/XWindowsClipboardWEBPConverter.h" + +// +// XWindowsClipboardWEBPConverter +// + +XWindowsClipboardWEBPConverter::XWindowsClipboardWEBPConverter( + Display* display) : + m_atom(XInternAtom(display, "image/webp", False)) +{ + // do nothing +} + +XWindowsClipboardWEBPConverter::~XWindowsClipboardWEBPConverter() +{ + // do nothing +} + +IClipboard::EFormat +XWindowsClipboardWEBPConverter::getFormat() const +{ + return IClipboard::kWebp; +} + +Atom +XWindowsClipboardWEBPConverter::getAtom() const +{ + return m_atom; +} + +int +XWindowsClipboardWEBPConverter::getDataSize() const +{ + return 8; +} + +std::string XWindowsClipboardWEBPConverter::fromIClipboard(const std::string& webpdata) const +{ + return webpdata; +} + +std::string XWindowsClipboardWEBPConverter::toIClipboard(const std::string& webpdata) const +{ + // check WEBPF file header, veirfy if Big or Little Endian + const UInt8* rawWEBPHeader = reinterpret_cast(webpdata.data()); + + if (rawWEBPHeader[0] == 'R' && rawWEBPHeader[1] == 'I' && rawWEBPHeader[2] == 'F' && rawWEBPHeader[3] == 'F' && + rawWEBPHeader[8] == 'W' && rawWEBPHeader[9] == 'E' && rawWEBPHeader[10] == 'B' && rawWEBPHeader[11] == 'P' ) { + LOG((CLOG_DEBUG2 "Prepare WEBP")); + return webpdata; + } + + return {}; +} diff --git a/src/lib/platform/XWindowsClipboardWEBPConverter.h b/src/lib/platform/XWindowsClipboardWEBPConverter.h new file mode 100644 index 00000000..13983dd9 --- /dev/null +++ b/src/lib/platform/XWindowsClipboardWEBPConverter.h @@ -0,0 +1,40 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * 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 . + */ + +#pragma once + +#include "platform/XWindowsClipboard.h" + +//! Convert to/from some text encoding +class XWindowsClipboardWEBPConverter : + public IXWindowsClipboardConverter { +public: + XWindowsClipboardWEBPConverter(Display* display); + virtual ~XWindowsClipboardWEBPConverter(); + + // IXWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual Atom getAtom() const; + virtual int getDataSize() const; + virtual std::string fromIClipboard(const std::string&) const; + virtual std::string toIClipboard(const std::string&) const; + +private: + Atom m_atom; +}; From 52046298a6e97779a901d86c97a2259bdf4d4b88 Mon Sep 17 00:00:00 2001 From: draekko Date: Tue, 21 Feb 2023 04:59:30 -0500 Subject: [PATCH 3/5] adds missing features doc as per readme for PR --- doc/newsfragments/adds-clipboard-memory-limit.feature | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/newsfragments/adds-clipboard-memory-limit.feature diff --git a/doc/newsfragments/adds-clipboard-memory-limit.feature b/doc/newsfragments/adds-clipboard-memory-limit.feature new file mode 100644 index 00000000..2022dd5d --- /dev/null +++ b/doc/newsfragments/adds-clipboard-memory-limit.feature @@ -0,0 +1,3 @@ +Adds clipboard memory limit for transfers between server/clients, the feature was documented +in wiki but missing in code. The feature can be set by using the spin box under the clipboard +checkbox in advanced settings. From 9c41922b33303de6f6b9b562c89bdc84ee81605d Mon Sep 17 00:00:00 2001 From: draekko Date: Tue, 21 Feb 2023 05:11:59 -0500 Subject: [PATCH 4/5] add missing checks in motif to prevent leaking image data to text targets --- src/lib/platform/XWindowsClipboard.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib/platform/XWindowsClipboard.cpp b/src/lib/platform/XWindowsClipboard.cpp index dd3d99fb..8e81cab3 100644 --- a/src/lib/platform/XWindowsClipboard.cpp +++ b/src/lib/platform/XWindowsClipboard.cpp @@ -838,6 +838,22 @@ XWindowsClipboard::motifFillCache() continue; } + if (actualTarget != target) { + LOG((CLOG_DEBUG1 " target %s not same as actual target %s", + XWindowsUtil::atomToString(m_display, target).c_str(), + XWindowsUtil::atomToString(m_display, actualTarget).c_str())); + m_added[format] = false; + continue; + } + + if (targetData.empty()) { + m_added[format] = false; + LOG((CLOG_DEBUG1 " no targetdata for target %s (actual target %s)", + XWindowsUtil::atomToString(m_display, target).c_str(), + XWindowsUtil::atomToString(m_display, actualTarget).c_str())); + continue; + } + if (!converter->toIClipboard(targetData).empty()) { // add to clipboard and note we've done it m_data[format] = converter->toIClipboard(targetData); From 3c60417c0e532923a126b6086b6bb5a187724ee6 Mon Sep 17 00:00:00 2001 From: draekko Date: Tue, 21 Feb 2023 05:48:37 -0500 Subject: [PATCH 5/5] clarification on setting clipboardSharingSize option --- doc/newsfragments/adds-clipboard-memory-limit.feature | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/newsfragments/adds-clipboard-memory-limit.feature b/doc/newsfragments/adds-clipboard-memory-limit.feature index 2022dd5d..97c709f5 100644 --- a/doc/newsfragments/adds-clipboard-memory-limit.feature +++ b/doc/newsfragments/adds-clipboard-memory-limit.feature @@ -1,3 +1,7 @@ Adds clipboard memory limit for transfers between server/clients, the feature was documented in wiki but missing in code. The feature can be set by using the spin box under the clipboard checkbox in advanced settings. + +The value used to limit clipboard size to transfer between client and sever is set in bytes +and can be set in the UI or throough the config file by setting the value in bytes with the +'clipboardSharingSize' tag.