/* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd * SPDX-FileCopyrightText: (C) 2014 Ryan Chapman * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #include "platform/OSXClipboardBMPConverter.h" #include "base/Log.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; } IClipboard::Format OSXClipboardBMPConverter::getFormat() const { return IClipboard::Format::Bitmap; } CFStringRef OSXClipboardBMPConverter::getOSXFormat() const { // TODO: does this only work with Windows? return CFSTR("com.microsoft.bmp"); } std::string OSXClipboardBMPConverter::fromIClipboard(const std::string &bmp) const { LOG_DEBUG1("getting data from clipboard"); // 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 OSXClipboardBMPConverter::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 uint8_t *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); } }