void CConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
+ unsolicitedClipboardAttempt = false;
+
+ // Attempt an unsolicited transfer?
+ if (available &&
+ (server.clipboardSize(rfb::clipboardUTF8) > 0) &&
+ (server.clipboardFlags() & rfb::clipboardProvide)) {
+ vlog.debug("Attempting unsolicited clipboard transfer...");
+ unsolicitedClipboardAttempt = true;
+ handleClipboardRequest();
+ return;
+ }
- if (server.clipboardFlags() & rfb::clipboardNotify)
+ if (server.clipboardFlags() & rfb::clipboardNotify) {
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
- else {
- if (available)
- handleClipboardRequest();
+ return;
}
+
+ if (available)
+ handleClipboardRequest();
}
void CConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
+
+ if (unsolicitedClipboardAttempt) {
+ unsolicitedClipboardAttempt = false;
+ if (sizes[0] > server.clipboardSize(rfb::clipboardUTF8)) {
+ vlog.debug("Clipboard was too large for unsolicited clipboard transfer");
+ if (server.clipboardFlags() & rfb::clipboardNotify)
+ writer()->writeClipboardNotify(rfb::clipboardUTF8);
+ return;
+ }
+ }
+
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
char* serverClipboard;
bool hasLocalClipboard;
+ bool unsolicitedClipboardAttempt;
};
}
#endif
ledState_ = state;
}
+rdr::U32 ClientParams::clipboardSize(unsigned int format) const
+{
+ int i;
+
+ for (i = 0;i < 16;i++) {
+ if (((unsigned)1 << i) == format)
+ return clipSizes[i];
+ }
+
+ throw Exception("Invalid clipboard format 0x%x", format);
+}
+
void ClientParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i, num;
void setLEDState(unsigned int state);
rdr::U32 clipboardFlags() const { return clipFlags; }
+ rdr::U32 clipboardSize(unsigned int format) const;
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
// Wrappers to check for functionality rather than specific
is(0), os(0), reader_(0), writer_(0),
ssecurity(0), state_(RFBSTATE_UNINITIALISED),
preferredEncoding(encodingRaw),
- clientClipboard(NULL), hasLocalClipboard(false)
+ clientClipboard(NULL), hasLocalClipboard(false),
+ unsolicitedClipboardAttempt(false)
{
defaultMajorVersion = 3;
defaultMinorVersion = 8;
void SConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
+ unsolicitedClipboardAttempt = false;
- if (client.supportsEncoding(pseudoEncodingExtendedClipboard) &&
- (client.clipboardFlags() & rfb::clipboardNotify))
- writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
- else {
- if (available)
+ if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) {
+ // Attempt an unsolicited transfer?
+ if (available &&
+ (client.clipboardSize(rfb::clipboardUTF8) > 0) &&
+ (client.clipboardFlags() & rfb::clipboardProvide)) {
+ vlog.debug("Attempting unsolicited clipboard transfer...");
+ unsolicitedClipboardAttempt = true;
handleClipboardRequest();
+ return;
+ }
+
+ if (client.clipboardFlags() & rfb::clipboardNotify) {
+ writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
+ return;
+ }
}
+
+ if (available)
+ handleClipboardRequest();
}
void SConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
+
+ if (unsolicitedClipboardAttempt) {
+ unsolicitedClipboardAttempt = false;
+ if (sizes[0] > client.clipboardSize(rfb::clipboardUTF8)) {
+ vlog.debug("Clipboard was too large for unsolicited clipboard transfer");
+ if (client.clipboardFlags() & rfb::clipboardNotify)
+ writer()->writeClipboardNotify(rfb::clipboardUTF8);
+ return;
+ }
+ }
+
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));
char* clientClipboard;
bool hasLocalClipboard;
+ bool unsolicitedClipboardAttempt;
};
}
#endif
ledState_ = state;
}
+rdr::U32 ServerParams::clipboardSize(unsigned int format) const
+{
+ int i;
+
+ for (i = 0;i < 16;i++) {
+ if (((unsigned)1 << i) == format)
+ return clipSizes[i];
+ }
+
+ throw Exception("Invalid clipboard format 0x%x", format);
+}
+
void ServerParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i, num;
void setLEDState(unsigned int state);
rdr::U32 clipboardFlags() const { return clipFlags; }
+ rdr::U32 clipboardSize(unsigned int format) const;
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
bool supportsQEMUKeyEvent;