/* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. * SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #include "platform/XWindowsClipboardBMPConverter.h" // BMP file header structure struct CBMPHeader { public: uint16_t type; uint32_t size; uint16_t reserved1; uint16_t reserved2; uint32_t offset; }; // BMP is little-endian static inline uint32_t fromLEU32(const uint8_t *data) { return static_cast(data[0]) | (static_cast(data[1]) << 8) | (static_cast(data[2]) << 16) | (static_cast(data[3]) << 24); } static void toLE(uint8_t *&dst, char src) { dst[0] = static_cast(src); dst += 1; } static void toLE(uint8_t *&dst, uint16_t src) { dst[0] = static_cast(src & 0xffu); dst[1] = static_cast((src >> 8) & 0xffu); dst += 2; } static void toLE(uint8_t *&dst, uint32_t src) { dst[0] = static_cast(src & 0xffu); dst[1] = static_cast((src >> 8) & 0xffu); dst[2] = static_cast((src >> 16) & 0xffu); dst[3] = static_cast((src >> 24) & 0xffu); dst += 4; } // // XWindowsClipboardBMPConverter // XWindowsClipboardBMPConverter::XWindowsClipboardBMPConverter(Display *display) : m_atom(XInternAtom(display, "image/bmp", False)) { // do nothing } IClipboard::Format XWindowsClipboardBMPConverter::getFormat() const { return IClipboard::Format::Bitmap; } Atom XWindowsClipboardBMPConverter::getAtom() const { return m_atom; } int XWindowsClipboardBMPConverter::getDataSize() const { return 8; } std::string XWindowsClipboardBMPConverter::fromIClipboard(const std::string &bmp) const { // create BMP image uint8_t header[14]; uint8_t *dst = header; toLE(dst, 'B'); toLE(dst, 'M'); toLE(dst, static_cast(14 + bmp.size())); toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); toLE(dst, static_cast(14 + 40)); return std::string(reinterpret_cast(header), 14) + bmp; } std::string XWindowsClipboardBMPConverter::toIClipboard(const std::string &bmp) const { // make sure data is big enough for a BMP file if (bmp.size() <= 14 + 40) { return std::string(); } // check BMP file header const auto *rawBMPHeader = reinterpret_cast(bmp.data()); if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { return std::string(); } // get offset to image data uint32_t offset = fromLEU32(rawBMPHeader + 10); // construct BMP if (offset == 14 + 40) { return bmp.substr(14); } else { return bmp.substr(14, 40) + bmp.substr(offset, bmp.size() - offset); } }