Avoid our own custom types in favour of what's already included with C++.pull/1587/head
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||||
* | |||||
* This is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation; either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This software 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 software; if not, write to the Free Software | |||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
* USA. | |||||
*/ | |||||
#ifndef __RDR_TYPES_H__ | |||||
#define __RDR_TYPES_H__ | |||||
#include <stdint.h> | |||||
namespace rdr { | |||||
class U8Array { | |||||
public: | |||||
U8Array() : buf(0) {} | |||||
U8Array(uint8_t* a) : buf(a) {} // note: assumes ownership | |||||
U8Array(int len) : buf(new uint8_t[len]) {} | |||||
~U8Array() { delete [] buf; } | |||||
// Get the buffer pointer & clear it (i.e. caller takes ownership) | |||||
uint8_t* takeBuf() { uint8_t* tmp = buf; buf = 0; return tmp; } | |||||
uint8_t* buf; | |||||
}; | |||||
class U16Array { | |||||
public: | |||||
U16Array() : buf(0) {} | |||||
U16Array(uint16_t* a) : buf(a) {} // note: assumes ownership | |||||
U16Array(int len) : buf(new uint16_t[len]) {} | |||||
~U16Array() { delete [] buf; } | |||||
uint16_t* takeBuf() { uint16_t* tmp = buf; buf = 0; return tmp; } | |||||
uint16_t* buf; | |||||
}; | |||||
class U32Array { | |||||
public: | |||||
U32Array() : buf(0) {} | |||||
U32Array(uint32_t* a) : buf(a) {} // note: assumes ownership | |||||
U32Array(int len) : buf(new uint32_t[len]) {} | |||||
~U32Array() { delete [] buf; } | |||||
uint32_t* takeBuf() { uint32_t* tmp = buf; buf = 0; return tmp; } | |||||
uint32_t* buf; | |||||
}; | |||||
class S32Array { | |||||
public: | |||||
S32Array() : buf(0) {} | |||||
S32Array(int32_t* a) : buf(a) {} // note: assumes ownership | |||||
S32Array(int len) : buf(new int32_t[len]) {} | |||||
~S32Array() { delete [] buf; } | |||||
int32_t* takeBuf() { int32_t* tmp = buf; buf = 0; return tmp; } | |||||
int32_t* buf; | |||||
}; | |||||
} // end of namespace rdr | |||||
#endif |
#include <assert.h> | #include <assert.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <vector> | |||||
#include <rdr/InStream.h> | #include <rdr/InStream.h> | ||||
#include <rdr/ZlibInStream.h> | #include <rdr/ZlibInStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/msgTypes.h> | #include <rfb/msgTypes.h> | ||||
#include <rfb/clipboardTypes.h> | #include <rfb/clipboardTypes.h> | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
rdr::U16Array rgbs(nColours * 3); | |||||
for (int i = 0; i < nColours * 3; i++) | |||||
rgbs.buf[i] = is->readU16(); | |||||
handler->setColourMapEntries(firstColour, nColours, rgbs.buf); | |||||
std::vector<uint16_t> rgbs(nColours * 3); | |||||
for (size_t i = 0; i < rgbs.size(); i++) | |||||
rgbs[i] = is->readU16(); | |||||
handler->setColourMapEntries(firstColour, nColours, rgbs.data()); | |||||
return true; | return true; | ||||
} | } | ||||
if (width > maxCursorSize || height > maxCursorSize) | if (width > maxCursorSize || height > maxCursorSize) | ||||
throw Exception("Too big cursor"); | throw Exception("Too big cursor"); | ||||
rdr::U8Array rgba(width*height*4); | |||||
std::vector<uint8_t> rgba(width*height*4); | |||||
if (width * height > 0) { | if (width * height > 0) { | ||||
uint8_t pr, pg, pb; | uint8_t pr, pg, pb; | ||||
uint8_t sr, sg, sb; | uint8_t sr, sg, sb; | ||||
int data_len = ((width+7)/8) * height; | int data_len = ((width+7)/8) * height; | ||||
int mask_len = ((width+7)/8) * height; | int mask_len = ((width+7)/8) * height; | ||||
rdr::U8Array data(data_len); | |||||
rdr::U8Array mask(mask_len); | |||||
std::vector<uint8_t> data(data_len); | |||||
std::vector<uint8_t> mask(mask_len); | |||||
int x, y; | int x, y; | ||||
uint8_t* out; | uint8_t* out; | ||||
sg = is->readU8(); | sg = is->readU8(); | ||||
sb = is->readU8(); | sb = is->readU8(); | ||||
is->readBytes(data.buf, data_len); | |||||
is->readBytes(mask.buf, mask_len); | |||||
is->readBytes(data.data(), data.size()); | |||||
is->readBytes(mask.data(), mask.size()); | |||||
int maskBytesPerRow = (width+7)/8; | int maskBytesPerRow = (width+7)/8; | ||||
out = rgba.buf; | |||||
out = rgba.data(); | |||||
for (y = 0;y < height;y++) { | for (y = 0;y < height;y++) { | ||||
for (x = 0;x < width;x++) { | for (x = 0;x < width;x++) { | ||||
int byte = y * maskBytesPerRow + x / 8; | int byte = y * maskBytesPerRow + x / 8; | ||||
int bit = 7 - x % 8; | int bit = 7 - x % 8; | ||||
if (data.buf[byte] & (1 << bit)) { | |||||
if (data[byte] & (1 << bit)) { | |||||
out[0] = pr; | out[0] = pr; | ||||
out[1] = pg; | out[1] = pg; | ||||
out[2] = pb; | out[2] = pb; | ||||
out[2] = sb; | out[2] = sb; | ||||
} | } | ||||
if (mask.buf[byte] & (1 << bit)) | |||||
if (mask[byte] & (1 << bit)) | |||||
out[3] = 255; | out[3] = 255; | ||||
else | else | ||||
out[3] = 0; | out[3] = 0; | ||||
} | } | ||||
} | } | ||||
handler->setCursor(width, height, hotspot, rgba.buf); | |||||
handler->setCursor(width, height, hotspot, rgba.data()); | |||||
return true; | return true; | ||||
} | } | ||||
int data_len = width * height * (handler->server.pf().bpp/8); | int data_len = width * height * (handler->server.pf().bpp/8); | ||||
int mask_len = ((width+7)/8) * height; | int mask_len = ((width+7)/8) * height; | ||||
rdr::U8Array data(data_len); | |||||
rdr::U8Array mask(mask_len); | |||||
std::vector<uint8_t> data(data_len); | |||||
std::vector<uint8_t> mask(mask_len); | |||||
int x, y; | int x, y; | ||||
rdr::U8Array rgba(width*height*4); | |||||
std::vector<uint8_t> rgba(width*height*4); | |||||
uint8_t* in; | uint8_t* in; | ||||
uint8_t* out; | uint8_t* out; | ||||
if (!is->hasData(data_len + mask_len)) | if (!is->hasData(data_len + mask_len)) | ||||
return false; | return false; | ||||
is->readBytes(data.buf, data_len); | |||||
is->readBytes(mask.buf, mask_len); | |||||
is->readBytes(data.data(), data.size()); | |||||
is->readBytes(mask.data(), mask.size()); | |||||
int maskBytesPerRow = (width+7)/8; | int maskBytesPerRow = (width+7)/8; | ||||
in = data.buf; | |||||
out = rgba.buf; | |||||
in = data.data(); | |||||
out = rgba.data(); | |||||
for (y = 0;y < height;y++) { | for (y = 0;y < height;y++) { | ||||
for (x = 0;x < width;x++) { | for (x = 0;x < width;x++) { | ||||
int byte = y * maskBytesPerRow + x / 8; | int byte = y * maskBytesPerRow + x / 8; | ||||
handler->server.pf().rgbFromBuffer(out, in, 1); | handler->server.pf().rgbFromBuffer(out, in, 1); | ||||
if (mask.buf[byte] & (1 << bit)) | |||||
if (mask[byte] & (1 << bit)) | |||||
out[3] = 255; | out[3] = 255; | ||||
else | else | ||||
out[3] = 0; | out[3] = 0; | ||||
} | } | ||||
} | } | ||||
handler->setCursor(width, height, hotspot, rgba.buf); | |||||
handler->setCursor(width, height, hotspot, rgba.data()); | |||||
return true; | return true; | ||||
} | } | ||||
if (type == 0) { | if (type == 0) { | ||||
int len = width * height * (handler->server.pf().bpp/8); | int len = width * height * (handler->server.pf().bpp/8); | ||||
rdr::U8Array andMask(len); | |||||
rdr::U8Array xorMask(len); | |||||
std::vector<uint8_t> andMask(len); | |||||
std::vector<uint8_t> xorMask(len); | |||||
rdr::U8Array data(width*height*4); | |||||
std::vector<uint8_t> data(width*height*4); | |||||
uint8_t* andIn; | uint8_t* andIn; | ||||
uint8_t* xorIn; | uint8_t* xorIn; | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
is->readBytes(andMask.buf, len); | |||||
is->readBytes(xorMask.buf, len); | |||||
is->readBytes(andMask.data(), andMask.size()); | |||||
is->readBytes(xorMask.data(), xorMask.size()); | |||||
andIn = andMask.buf; | |||||
xorIn = xorMask.buf; | |||||
out = data.buf; | |||||
andIn = andMask.data(); | |||||
xorIn = xorMask.data(); | |||||
out = data.data(); | |||||
Bpp = handler->server.pf().bpp/8; | Bpp = handler->server.pf().bpp/8; | ||||
for (int y = 0;y < height;y++) { | for (int y = 0;y < height;y++) { | ||||
for (int x = 0;x < width;x++) { | for (int x = 0;x < width;x++) { | ||||
} | } | ||||
} | } | ||||
handler->setCursor(width, height, hotspot, data.buf); | |||||
handler->setCursor(width, height, hotspot, data.data()); | |||||
} else if (type == 1) { | } else if (type == 1) { | ||||
rdr::U8Array data(width*height*4); | |||||
std::vector<uint8_t> data(width*height*4); | |||||
if (!is->hasDataOrRestore(width*height*4)) | if (!is->hasDataOrRestore(width*height*4)) | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
// FIXME: Is alpha premultiplied? | // FIXME: Is alpha premultiplied? | ||||
is->readBytes(data.buf, width*height*4); | |||||
is->readBytes(data.data(), data.size()); | |||||
handler->setCursor(width, height, hotspot, data.buf); | |||||
handler->setCursor(width, height, hotspot, data.data()); | |||||
} else { | } else { | ||||
throw Exception("Unknown cursor type"); | throw Exception("Unknown cursor type"); | ||||
} | } |
#include <rdr/InStream.h> | #include <rdr/InStream.h> | ||||
#include <rdr/OutStream.h> | #include <rdr/OutStream.h> | ||||
#include <rdr/RandomStream.h> | #include <rdr/RandomStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <os/os.h> | #include <os/os.h> | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
mpz_set_ui(g, gen); | mpz_set_ui(g, gen); | ||||
rdr::U8Array pBytes(keyLength); | |||||
rdr::U8Array ABytes(keyLength); | |||||
is->readBytes(pBytes.buf, keyLength); | |||||
is->readBytes(ABytes.buf, keyLength); | |||||
nettle_mpz_set_str_256_u(p, keyLength, pBytes.buf); | |||||
nettle_mpz_set_str_256_u(A, keyLength, ABytes.buf); | |||||
std::vector<uint8_t> pBytes(keyLength); | |||||
std::vector<uint8_t> ABytes(keyLength); | |||||
is->readBytes(pBytes.data(), pBytes.size()); | |||||
is->readBytes(ABytes.data(), ABytes.size()); | |||||
nettle_mpz_set_str_256_u(p, pBytes.size(), pBytes.data()); | |||||
nettle_mpz_set_str_256_u(A, ABytes.size(), ABytes.data()); | |||||
return true; | return true; | ||||
} | } | ||||
rdr::RandomStream rs; | rdr::RandomStream rs; | ||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | ||||
rdr::U8Array bBytes(keyLength); | |||||
std::vector<uint8_t> bBytes(keyLength); | |||||
if (!rs.hasData(keyLength)) | if (!rs.hasData(keyLength)) | ||||
throw ConnFailedException("failed to generate DH private key"); | throw ConnFailedException("failed to generate DH private key"); | ||||
rs.readBytes(bBytes.buf, keyLength); | |||||
nettle_mpz_set_str_256_u(b, keyLength, bBytes.buf); | |||||
rs.readBytes(bBytes.data(), bBytes.size()); | |||||
nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data()); | |||||
mpz_powm(k, A, b, p); | mpz_powm(k, A, b, p); | ||||
mpz_powm(B, g, b, p); | mpz_powm(B, g, b, p); | ||||
rdr::U8Array sharedSecret(keyLength); | |||||
rdr::U8Array BBytes(keyLength); | |||||
nettle_mpz_get_str_256(keyLength, sharedSecret.buf, k); | |||||
nettle_mpz_get_str_256(keyLength, BBytes.buf, B); | |||||
std::vector<uint8_t> sharedSecret(keyLength); | |||||
std::vector<uint8_t> BBytes(keyLength); | |||||
nettle_mpz_get_str_256(sharedSecret.size(), sharedSecret.data(), k); | |||||
nettle_mpz_get_str_256(BBytes.size(), BBytes.data(), B); | |||||
uint8_t key[16]; | uint8_t key[16]; | ||||
struct md5_ctx md5Ctx; | struct md5_ctx md5Ctx; | ||||
md5_init(&md5Ctx); | md5_init(&md5Ctx); | ||||
md5_update(&md5Ctx, keyLength, sharedSecret.buf); | |||||
md5_update(&md5Ctx, sharedSecret.size(), sharedSecret.data()); | |||||
md5_digest(&md5Ctx, 16, key); | md5_digest(&md5Ctx, 16, key); | ||||
struct aes128_ctx aesCtx; | struct aes128_ctx aesCtx; | ||||
aes128_set_encrypt_key(&aesCtx, key); | aes128_set_encrypt_key(&aesCtx, key); | ||||
rdr::OutStream* os = cc->getOutStream(); | rdr::OutStream* os = cc->getOutStream(); | ||||
os->writeBytes(buf, 128); | os->writeBytes(buf, 128); | ||||
os->writeBytes(BBytes.buf, keyLength); | |||||
os->writeBytes(BBytes.data(), BBytes.size()); | |||||
os->flush(); | os->flush(); | ||||
} | } |
#include <rdr/InStream.h> | #include <rdr/InStream.h> | ||||
#include <rdr/OutStream.h> | #include <rdr/OutStream.h> | ||||
#include <rdr/RandomStream.h> | #include <rdr/RandomStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <os/os.h> | #include <os/os.h> | ||||
rdr::RandomStream rs; | rdr::RandomStream rs; | ||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | (CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | ||||
rdr::U8Array bBytes(8); | |||||
std::vector<uint8_t> bBytes(8); | |||||
if (!rs.hasData(8)) | if (!rs.hasData(8)) | ||||
throw ConnFailedException("failed to generate DH private key"); | throw ConnFailedException("failed to generate DH private key"); | ||||
rs.readBytes(bBytes.buf, 8); | |||||
nettle_mpz_set_str_256_u(b, 8, bBytes.buf); | |||||
rs.readBytes(bBytes.data(), bBytes.size()); | |||||
nettle_mpz_set_str_256_u(b, bBytes.size(), bBytes.data()); | |||||
mpz_powm(k, A, b, p); | mpz_powm(k, A, b, p); | ||||
mpz_powm(B, g, b, p); | mpz_powm(B, g, b, p); | ||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | ||||
* Copyright 2014-2017 Pierre Ossman for Cendio AB | |||||
* Copyright 2014-2023 Pierre Ossman for Cendio AB | |||||
* | * | ||||
* This is free software; you can redistribute it and/or modify | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/Cursor.h> | #include <rfb/Cursor.h> | ||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
} | } | ||||
} | } | ||||
uint8_t* Cursor::getBitmap() const | |||||
std::vector<uint8_t> Cursor::getBitmap() const | |||||
{ | { | ||||
// First step is converting to luminance | // First step is converting to luminance | ||||
rdr::S32Array luminance(width()*height()); | |||||
int32_t *lum_ptr = luminance.buf; | |||||
std::vector<int32_t> luminance(width()*height()); | |||||
int32_t *lum_ptr = luminance.data(); | |||||
const uint8_t *data_ptr = data; | const uint8_t *data_ptr = data; | ||||
for (int y = 0; y < height(); y++) { | for (int y = 0; y < height(); y++) { | ||||
for (int x = 0; x < width(); x++) { | for (int x = 0; x < width(); x++) { | ||||
} | } | ||||
// Then diterhing | // Then diterhing | ||||
dither(width(), height(), luminance.buf); | |||||
dither(width(), height(), luminance.data()); | |||||
// Then conversion to a bit mask | // Then conversion to a bit mask | ||||
rdr::U8Array source((width()+7)/8*height()); | |||||
memset(source.buf, 0, (width()+7)/8*height()); | |||||
std::vector<uint8_t> source((width()+7)/8*height()); | |||||
memset(source.data(), 0, source.size()); | |||||
int maskBytesPerRow = (width() + 7) / 8; | int maskBytesPerRow = (width() + 7) / 8; | ||||
lum_ptr = luminance.buf; | |||||
lum_ptr = luminance.data(); | |||||
data_ptr = data; | data_ptr = data; | ||||
for (int y = 0; y < height(); y++) { | for (int y = 0; y < height(); y++) { | ||||
for (int x = 0; x < width(); x++) { | for (int x = 0; x < width(); x++) { | ||||
int byte = y * maskBytesPerRow + x / 8; | int byte = y * maskBytesPerRow + x / 8; | ||||
int bit = 7 - x % 8; | int bit = 7 - x % 8; | ||||
if (*lum_ptr > 32767) | if (*lum_ptr > 32767) | ||||
source.buf[byte] |= (1 << bit); | |||||
source[byte] |= (1 << bit); | |||||
lum_ptr++; | lum_ptr++; | ||||
data_ptr += 4; | data_ptr += 4; | ||||
} | } | ||||
} | } | ||||
return source.takeBuf(); | |||||
return source; | |||||
} | } | ||||
uint8_t* Cursor::getMask() const | |||||
std::vector<uint8_t> Cursor::getMask() const | |||||
{ | { | ||||
// First step is converting to integer array | // First step is converting to integer array | ||||
rdr::S32Array alpha(width()*height()); | |||||
int32_t *alpha_ptr = alpha.buf; | |||||
std::vector<int32_t> alpha(width()*height()); | |||||
int32_t *alpha_ptr = alpha.data(); | |||||
const uint8_t *data_ptr = data; | const uint8_t *data_ptr = data; | ||||
for (int y = 0; y < height(); y++) { | for (int y = 0; y < height(); y++) { | ||||
for (int x = 0; x < width(); x++) { | for (int x = 0; x < width(); x++) { | ||||
} | } | ||||
// Then diterhing | // Then diterhing | ||||
dither(width(), height(), alpha.buf); | |||||
dither(width(), height(), alpha.data()); | |||||
// Then conversion to a bit mask | // Then conversion to a bit mask | ||||
rdr::U8Array mask((width()+7)/8*height()); | |||||
memset(mask.buf, 0, (width()+7)/8*height()); | |||||
std::vector<uint8_t> mask((width()+7)/8*height()); | |||||
memset(mask.data(), 0, mask.size()); | |||||
int maskBytesPerRow = (width() + 7) / 8; | int maskBytesPerRow = (width() + 7) / 8; | ||||
alpha_ptr = alpha.buf; | |||||
alpha_ptr = alpha.data(); | |||||
data_ptr = data; | data_ptr = data; | ||||
for (int y = 0; y < height(); y++) { | for (int y = 0; y < height(); y++) { | ||||
for (int x = 0; x < width(); x++) { | for (int x = 0; x < width(); x++) { | ||||
int byte = y * maskBytesPerRow + x / 8; | int byte = y * maskBytesPerRow + x / 8; | ||||
int bit = 7 - x % 8; | int bit = 7 - x % 8; | ||||
if (*alpha_ptr > 32767) | if (*alpha_ptr > 32767) | ||||
mask.buf[byte] |= (1 << bit); | |||||
mask[byte] |= (1 << bit); | |||||
alpha_ptr++; | alpha_ptr++; | ||||
data_ptr += 4; | data_ptr += 4; | ||||
} | } | ||||
} | } | ||||
return mask.takeBuf(); | |||||
return mask; | |||||
} | } | ||||
// crop() determines the "busy" rectangle for the cursor - the minimum bounding | // crop() determines the "busy" rectangle for the cursor - the minimum bounding |
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | ||||
* Copyright 2014-2017 Pierre Ossman for Cendio AB | |||||
* Copyright 2014-2023 Pierre Ossman for Cendio AB | |||||
* | * | ||||
* This is free software; you can redistribute it and/or modify | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
#ifndef __RFB_CURSOR_H__ | #ifndef __RFB_CURSOR_H__ | ||||
#define __RFB_CURSOR_H__ | #define __RFB_CURSOR_H__ | ||||
#include <vector> | |||||
#include <rfb/PixelBuffer.h> | #include <rfb/PixelBuffer.h> | ||||
namespace rfb { | namespace rfb { | ||||
const uint8_t* getBuffer() const { return data; }; | const uint8_t* getBuffer() const { return data; }; | ||||
// getBitmap() returns a monochrome version of the cursor | // getBitmap() returns a monochrome version of the cursor | ||||
uint8_t* getBitmap() const; | |||||
std::vector<uint8_t> getBitmap() const; | |||||
// getMask() returns a simple mask version of the alpha channel | // getMask() returns a simple mask version of the alpha channel | ||||
uint8_t* getMask() const; | |||||
std::vector<uint8_t> getMask() const; | |||||
// crop() crops the cursor down to the smallest possible size, based on the | // crop() crops the cursor down to the smallest possible size, based on the | ||||
// mask. | // mask. |
#include <stdio.h> | #include <stdio.h> | ||||
#include <vector> | |||||
#include <rdr/InStream.h> | #include <rdr/InStream.h> | ||||
#include <rdr/ZlibInStream.h> | #include <rdr/ZlibInStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/msgTypes.h> | #include <rfb/msgTypes.h> | ||||
#include <rfb/qemuTypes.h> | #include <rfb/qemuTypes.h> | ||||
return false; | return false; | ||||
is->clearRestorePoint(); | is->clearRestorePoint(); | ||||
rdr::S32Array encodings(nEncodings); | |||||
for (int i = 0; i < nEncodings; i++) | |||||
encodings.buf[i] = is->readU32(); | |||||
std::vector<int32_t> encodings(nEncodings); | |||||
for (size_t i = 0; i < encodings.size(); i++) | |||||
encodings[i] = is->readU32(); | |||||
handler->setEncodings(nEncodings, encodings.buf); | |||||
handler->setEncodings(nEncodings, encodings.data()); | |||||
return true; | return true; | ||||
} | } |
#include <rdr/OutStream.h> | #include <rdr/OutStream.h> | ||||
#include <rdr/MemOutStream.h> | #include <rdr/MemOutStream.h> | ||||
#include <rdr/ZlibOutStream.h> | #include <rdr/ZlibOutStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/msgTypes.h> | #include <rfb/msgTypes.h> | ||||
#include <rfb/fenceTypes.h> | #include <rfb/fenceTypes.h> | ||||
cursor.hotspot().x, cursor.hotspot().y, | cursor.hotspot().x, cursor.hotspot().y, | ||||
cursor.getBuffer()); | cursor.getBuffer()); | ||||
} else if (client->supportsEncoding(pseudoEncodingCursor)) { | } else if (client->supportsEncoding(pseudoEncodingCursor)) { | ||||
rdr::U8Array data(cursor.width()*cursor.height() * (client->pf().bpp/8)); | |||||
rdr::U8Array mask(cursor.getMask()); | |||||
size_t data_len = cursor.width()*cursor.height() * | |||||
(client->pf().bpp/8); | |||||
std::vector<uint8_t> data(data_len); | |||||
std::vector<uint8_t> mask(cursor.getMask()); | |||||
const uint8_t* in; | const uint8_t* in; | ||||
uint8_t* out; | uint8_t* out; | ||||
in = cursor.getBuffer(); | in = cursor.getBuffer(); | ||||
out = data.buf; | |||||
out = data.data(); | |||||
for (int i = 0;i < cursor.width()*cursor.height();i++) { | for (int i = 0;i < cursor.width()*cursor.height();i++) { | ||||
client->pf().bufferFromRGB(out, in, 1); | client->pf().bufferFromRGB(out, in, 1); | ||||
in += 4; | in += 4; | ||||
writeSetCursorRect(cursor.width(), cursor.height(), | writeSetCursorRect(cursor.width(), cursor.height(), | ||||
cursor.hotspot().x, cursor.hotspot().y, | cursor.hotspot().x, cursor.hotspot().y, | ||||
data.buf, mask.buf); | |||||
data.data(), mask.data()); | |||||
} else if (client->supportsEncoding(pseudoEncodingXCursor)) { | } else if (client->supportsEncoding(pseudoEncodingXCursor)) { | ||||
rdr::U8Array bitmap(cursor.getBitmap()); | |||||
rdr::U8Array mask(cursor.getMask()); | |||||
std::vector<uint8_t> bitmap(cursor.getBitmap()); | |||||
std::vector<uint8_t> mask(cursor.getMask()); | |||||
writeSetXCursorRect(cursor.width(), cursor.height(), | writeSetXCursorRect(cursor.width(), cursor.height(), | ||||
cursor.hotspot().x, cursor.hotspot().y, | cursor.hotspot().x, cursor.hotspot().y, | ||||
bitmap.buf, mask.buf); | |||||
bitmap.data(), mask.data()); | |||||
} else { | } else { | ||||
throw Exception("Client does not support local cursor"); | throw Exception("Client does not support local cursor"); | ||||
} | } |
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <vector> | |||||
#include <nettle/bignum.h> | #include <nettle/bignum.h> | ||||
#include <nettle/sha1.h> | #include <nettle/sha1.h> | ||||
#include <nettle/sha2.h> | #include <nettle/sha2.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <rdr/AESInStream.h> | #include <rdr/AESInStream.h> | ||||
#include <rdr/AESOutStream.h> | #include <rdr/AESOutStream.h> | ||||
#include <rdr/types.h> | |||||
#if !defined(WIN32) && !defined(__APPLE__) | #if !defined(WIN32) && !defined(__APPLE__) | ||||
#include <rfb/UnixPasswordValidator.h> | #include <rfb/UnixPasswordValidator.h> | ||||
#endif | #endif | ||||
} | } | ||||
static bool loadPEM(uint8_t* data, size_t size, const char *begin, | static bool loadPEM(uint8_t* data, size_t size, const char *begin, | ||||
const char *end, uint8_t** der, size_t *derSize) | |||||
const char *end, std::vector<uint8_t> *der) | |||||
{ | { | ||||
ssize_t pos1 = findSubstr(data, size, begin); | ssize_t pos1 = findSubstr(data, size, begin); | ||||
if (pos1 == -1) | if (pos1 == -1) | ||||
char *derBase64 = (char *)data + pos1; | char *derBase64 = (char *)data + pos1; | ||||
if (!base64Size) | if (!base64Size) | ||||
return false; | return false; | ||||
*der = new uint8_t[BASE64_DECODE_LENGTH(base64Size)]; | |||||
der->resize(BASE64_DECODE_LENGTH(base64Size)); | |||||
struct base64_decode_ctx ctx; | struct base64_decode_ctx ctx; | ||||
size_t derSize; | |||||
base64_decode_init(&ctx); | base64_decode_init(&ctx); | ||||
if (!base64_decode_update(&ctx, derSize, *der, base64Size, derBase64)) | |||||
if (!base64_decode_update(&ctx, &derSize, der->data(), | |||||
base64Size, derBase64)) | |||||
return false; | return false; | ||||
if (!base64_decode_final(&ctx)) | if (!base64_decode_final(&ctx)) | ||||
return false; | return false; | ||||
assert(derSize <= der->size()); | |||||
der->resize(derSize); | |||||
return true; | return true; | ||||
} | } | ||||
throw ConnFailedException("size of key file is zero or too big"); | throw ConnFailedException("size of key file is zero or too big"); | ||||
} | } | ||||
fseek(file, 0, SEEK_SET); | fseek(file, 0, SEEK_SET); | ||||
rdr::U8Array data(size); | |||||
if (fread(data.buf, 1, size, file) != size) { | |||||
std::vector<uint8_t> data(size); | |||||
if (fread(data.data(), 1, data.size(), file) != size) { | |||||
fclose(file); | fclose(file); | ||||
throw ConnFailedException("failed to read key"); | throw ConnFailedException("failed to read key"); | ||||
} | } | ||||
fclose(file); | fclose(file); | ||||
rdr::U8Array der; | |||||
size_t derSize; | |||||
if (loadPEM(data.buf, size, "-----BEGIN RSA PRIVATE KEY-----\n", | |||||
"-----END RSA PRIVATE KEY-----", &der.buf, &derSize)) { | |||||
loadPKCS1Key(der.buf, derSize); | |||||
std::vector<uint8_t> der; | |||||
if (loadPEM(data.data(), data.size(), | |||||
"-----BEGIN RSA PRIVATE KEY-----\n", | |||||
"-----END RSA PRIVATE KEY-----", &der)) { | |||||
loadPKCS1Key(der.data(), der.size()); | |||||
return; | return; | ||||
} | } | ||||
if (der.buf) | |||||
delete[] der.takeBuf(); | |||||
if (loadPEM(data.buf, size, "-----BEGIN PRIVATE KEY-----\n", | |||||
"-----END PRIVATE KEY-----", &der.buf, &derSize)) { | |||||
loadPKCS8Key(der.buf, derSize); | |||||
if (loadPEM(data.data(), data.size(), | |||||
"-----BEGIN PRIVATE KEY-----\n", | |||||
"-----END PRIVATE KEY-----", &der)) { | |||||
loadPKCS8Key(der.data(), der.size()); | |||||
return; | return; | ||||
} | } | ||||
throw ConnFailedException("failed to import key"); | throw ConnFailedException("failed to import key"); |
#include <assert.h> | #include <assert.h> | ||||
#include <vector> | |||||
#include <rdr/InStream.h> | #include <rdr/InStream.h> | ||||
#include <rdr/MemInStream.h> | #include <rdr/MemInStream.h> | ||||
#include <rdr/OutStream.h> | #include <rdr/OutStream.h> | ||||
#include <rdr/types.h> | |||||
#include <rfb/ServerParams.h> | #include <rfb/ServerParams.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
if (pf.is888()) { | if (pf.is888()) { | ||||
size_t len = palSize * 3; | size_t len = palSize * 3; | ||||
rdr::U8Array tightPalette(len); | |||||
std::vector<uint8_t> tightPalette(len); | |||||
assert(buflen >= len); | assert(buflen >= len); | ||||
memcpy(tightPalette.buf, bufptr, len); | |||||
memcpy(tightPalette.data(), bufptr, len); | |||||
bufptr += len; | bufptr += len; | ||||
buflen -= len; | buflen -= len; | ||||
pf.bufferFromRGB(palette, tightPalette.buf, palSize); | |||||
pf.bufferFromRGB(palette, tightPalette.data(), palSize); | |||||
} else { | } else { | ||||
size_t len; | size_t len; | ||||
#endif | #endif | ||||
#include <vector> | #include <vector> | ||||
#include <rdr/types.h> | |||||
#include <rfb_win32/DeviceFrameBuffer.h> | #include <rfb_win32/DeviceFrameBuffer.h> | ||||
#include <rfb_win32/DeviceContext.h> | #include <rfb_win32/DeviceContext.h> | ||||
#include <rfb_win32/IconInfo.h> | #include <rfb_win32/IconInfo.h> | ||||
try { | try { | ||||
int width, height; | int width, height; | ||||
rdr::U8Array buffer; | |||||
std::vector<uint8_t> buffer; | |||||
// - Get the size and other details about the cursor. | // - Get the size and other details about the cursor. | ||||
if (!iconInfo.hbmColor) | if (!iconInfo.hbmColor) | ||||
height /= 2; | height /= 2; | ||||
buffer.buf = new uint8_t[width * height * 4]; | |||||
buffer.resize(width * height * 4); | |||||
Point hotspot = Point(iconInfo.xHotspot, iconInfo.yHotspot); | Point hotspot = Point(iconInfo.xHotspot, iconInfo.yHotspot); | ||||
bi.bV5AlphaMask = 0xFF000000; | bi.bV5AlphaMask = 0xFF000000; | ||||
if (!GetDIBits(dc, iconInfo.hbmColor, 0, height, | if (!GetDIBits(dc, iconInfo.hbmColor, 0, height, | ||||
buffer.buf, (LPBITMAPINFO)&bi, DIB_RGB_COLORS)) | |||||
buffer.data(), (LPBITMAPINFO)&bi, DIB_RGB_COLORS)) | |||||
throw rdr::SystemException("GetDIBits", GetLastError()); | throw rdr::SystemException("GetDIBits", GetLastError()); | ||||
// We may not get the RGBA order we want, so shuffle things around | // We may not get the RGBA order we want, so shuffle things around | ||||
(bi.bV5BlueMask != ((unsigned)0xff << bidx*8))) | (bi.bV5BlueMask != ((unsigned)0xff << bidx*8))) | ||||
throw rdr::Exception("unsupported cursor colour format"); | throw rdr::Exception("unsupported cursor colour format"); | ||||
uint8_t* rwbuffer = buffer.buf; | |||||
uint8_t* rwbuffer = buffer.data(); | |||||
for (int y = 0; y < height; y++) { | for (int y = 0; y < height; y++) { | ||||
for (int x = 0; x < width; x++) { | for (int x = 0; x < width; x++) { | ||||
uint8_t r, g, b, a; | uint8_t r, g, b, a; | ||||
} else { | } else { | ||||
// B/W cursor | // B/W cursor | ||||
rdr::U8Array mask(maskInfo.bmWidthBytes * maskInfo.bmHeight); | |||||
uint8_t* andMask = mask.buf; | |||||
uint8_t* xorMask = mask.buf + height * maskInfo.bmWidthBytes; | |||||
std::vector<uint8_t> mask(maskInfo.bmWidthBytes * maskInfo.bmHeight); | |||||
uint8_t* andMask = mask.data(); | |||||
uint8_t* xorMask = mask.data() + height * maskInfo.bmWidthBytes; | |||||
if (!GetBitmapBits(iconInfo.hbmMask, | if (!GetBitmapBits(iconInfo.hbmMask, | ||||
maskInfo.bmWidthBytes * maskInfo.bmHeight, mask.buf)) | |||||
maskInfo.bmWidthBytes * maskInfo.bmHeight, mask.data())) | |||||
throw rdr::SystemException("GetBitmapBits", GetLastError()); | throw rdr::SystemException("GetBitmapBits", GetLastError()); | ||||
bool doOutline = false; | bool doOutline = false; | ||||
uint8_t* rwbuffer = buffer.buf; | |||||
uint8_t* rwbuffer = buffer.data(); | |||||
for (int y = 0; y < height; y++) { | for (int y = 0; y < height; y++) { | ||||
for (int x = 0; x < width; x++) { | for (int x = 0; x < width; x++) { | ||||
int byte = y * maskInfo.bmWidthBytes + x / 8; | int byte = y * maskInfo.bmWidthBytes + x / 8; | ||||
// The buffer needs to be slightly larger to make sure there | // The buffer needs to be slightly larger to make sure there | ||||
// is room for the outline pixels | // is room for the outline pixels | ||||
rdr::U8Array outline((width + 2)*(height + 2)*4); | |||||
memset(outline.buf, 0, (width + 2)*(height + 2)*4); | |||||
std::vector<uint8_t> outline((width + 2)*(height + 2)*4); | |||||
memset(outline.data(), 0, (width + 2)*(height + 2)*4); | |||||
// Pass 1, outline everything | // Pass 1, outline everything | ||||
uint8_t* in = buffer.buf; | |||||
uint8_t* out = outline.buf + width*4 + 4; | |||||
uint8_t* in = buffer.data(); | |||||
uint8_t* out = outline.data() + width*4 + 4; | |||||
for (int y = 0; y < height; y++) { | for (int y = 0; y < height; y++) { | ||||
for (int x = 0; x < width; x++) { | for (int x = 0; x < width; x++) { | ||||
// Visible pixel? | // Visible pixel? | ||||
} | } | ||||
// Pass 2, overwrite with actual cursor | // Pass 2, overwrite with actual cursor | ||||
in = buffer.buf; | |||||
out = outline.buf + width*4 + 4; | |||||
in = buffer.data(); | |||||
out = outline.data() + width*4 + 4; | |||||
for (int y = 0; y < height; y++) { | for (int y = 0; y < height; y++) { | ||||
for (int x = 0; x < width; x++) { | for (int x = 0; x < width; x++) { | ||||
if (in[3] > 0) | if (in[3] > 0) | ||||
hotspot.x += 1; | hotspot.x += 1; | ||||
hotspot.y += 1; | hotspot.y += 1; | ||||
delete [] buffer.buf; | |||||
buffer.buf = outline.takeBuf(); | |||||
buffer = outline; | |||||
} | } | ||||
} | } | ||||
server->setCursor(width, height, hotspot, buffer.buf); | |||||
server->setCursor(width, height, hotspot, buffer.data()); | |||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
vlog.error("%s", e.str()); | vlog.error("%s", e.str()); |
} | } | ||||
void Sid::setSID(const PSID sid) { | void Sid::setSID(const PSID sid) { | ||||
delete [] buf; | |||||
buf = (uint8_t*)copySID(sid); | |||||
if (!IsValidSid(sid)) | |||||
throw rdr::Exception("invalid SID in copyPSID"); | |||||
resize(GetLengthSid(sid)); | |||||
if (!CopySid(GetLengthSid(sid), data(), sid)) | |||||
throw rdr::SystemException("CopySid failed", GetLastError()); | |||||
} | } | ||||
void Sid::getUserNameAndDomain(TCHAR** name, TCHAR** domain) { | void Sid::getUserNameAndDomain(TCHAR** name, TCHAR** domain) { | ||||
DWORD nameLen = 0; | DWORD nameLen = 0; | ||||
DWORD domainLen = 0; | DWORD domainLen = 0; | ||||
SID_NAME_USE use; | SID_NAME_USE use; | ||||
LookupAccountSid(0, (PSID)buf, 0, &nameLen, 0, &domainLen, &use); | |||||
LookupAccountSid(0, (PSID)*this, 0, &nameLen, 0, &domainLen, &use); | |||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) | ||||
throw rdr::SystemException("Unable to determine SID name lengths", GetLastError()); | throw rdr::SystemException("Unable to determine SID name lengths", GetLastError()); | ||||
vlog.info("nameLen=%lu, domainLen=%lu, use=%d", nameLen, domainLen, use); | vlog.info("nameLen=%lu, domainLen=%lu, use=%d", nameLen, domainLen, use); | ||||
*name = new TCHAR[nameLen]; | *name = new TCHAR[nameLen]; | ||||
*domain = new TCHAR[domainLen]; | *domain = new TCHAR[domainLen]; | ||||
if (!LookupAccountSid(0, (PSID)buf, *name, &nameLen, *domain, &domainLen, &use)) | |||||
if (!LookupAccountSid(0, (PSID)*this, *name, &nameLen, *domain, &domainLen, &use)) | |||||
throw rdr::SystemException("Unable to lookup account SID", GetLastError()); | throw rdr::SystemException("Unable to lookup account SID", GetLastError()); | ||||
} | } | ||||
Sid::FromToken::FromToken(HANDLE h) { | Sid::FromToken::FromToken(HANDLE h) { | ||||
DWORD required = 0; | DWORD required = 0; | ||||
GetTokenInformation(h, TokenUser, 0, 0, &required); | GetTokenInformation(h, TokenUser, 0, 0, &required); | ||||
rdr::U8Array tmp(required); | |||||
if (!GetTokenInformation(h, TokenUser, tmp.buf, required, &required)) | |||||
std::vector<uint8_t> tmp(required); | |||||
if (!GetTokenInformation(h, TokenUser, tmp.data(), tmp.size(), &required)) | |||||
throw rdr::SystemException("GetTokenInformation", GetLastError()); | throw rdr::SystemException("GetTokenInformation", GetLastError()); | ||||
TOKEN_USER* tokenUser = (TOKEN_USER*)tmp.buf; | |||||
TOKEN_USER* tokenUser = (TOKEN_USER*)tmp.data(); | |||||
setSID(tokenUser->User.Sid); | setSID(tokenUser->User.Sid); | ||||
} | } | ||||
#ifndef __RFB_WIN32_SECURITY_H__ | #ifndef __RFB_WIN32_SECURITY_H__ | ||||
#define __RFB_WIN32_SECURITY_H__ | #define __RFB_WIN32_SECURITY_H__ | ||||
#include <rdr/types.h> | |||||
#include <stdint.h> | |||||
#include <vector> | |||||
#include <rfb_win32/LocalMem.h> | #include <rfb_win32/LocalMem.h> | ||||
#include <rfb_win32/TCharArray.h> | #include <rfb_win32/TCharArray.h> | ||||
#include <aclapi.h> | #include <aclapi.h> | ||||
}; | }; | ||||
// Helper class for handling SIDs | // Helper class for handling SIDs | ||||
struct Sid : rdr::U8Array { | |||||
struct Sid : std::vector<uint8_t> { | |||||
Sid() {} | Sid() {} | ||||
operator PSID() const {return (PSID)buf;} | |||||
PSID takePSID() {PSID r = (PSID)buf; buf = 0; return r;} | |||||
operator PSID() const {return (PSID)data();} | |||||
static PSID copySID(const PSID sid); | static PSID copySID(const PSID sid); | ||||