We now filter incoming data, which means we can start assuming the clipboard data is always null terminated. This allows us to clean up a lot of the internal handling.tags/v1.9.90
@@ -70,7 +70,7 @@ namespace rfb { | |||
virtual void setColourMapEntries(int firstColour, int nColours, | |||
rdr::U16* rgbs) = 0; | |||
virtual void bell() = 0; | |||
virtual void serverCutText(const char* str, rdr::U32 len) = 0; | |||
virtual void serverCutText(const char* str) = 0; | |||
virtual void setLEDState(unsigned int state); | |||
@@ -160,7 +160,7 @@ void CMsgReader::readServerCutText() | |||
CharArray ca(len); | |||
is->readBytes(ca.buf, len); | |||
CharArray filtered(convertLF(ca.buf, len)); | |||
handler->serverCutText(filtered.buf, strlen(filtered.buf)); | |||
handler->serverCutText(filtered.buf); | |||
} | |||
void CMsgReader::readFence() |
@@ -179,11 +179,14 @@ void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask) | |||
} | |||
void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len) | |||
void CMsgWriter::writeClientCutText(const char* str) | |||
{ | |||
if (memchr(str, '\r', len) != NULL) | |||
size_t len; | |||
if (strchr(str, '\r') != NULL) | |||
throw Exception("Invalid carriage return in clipboard data"); | |||
len = strlen(str); | |||
startMsg(msgTypeClientCutText); | |||
os->pad(3); | |||
os->writeU32(len); |
@@ -55,7 +55,7 @@ namespace rfb { | |||
void writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); | |||
void writePointerEvent(const Point& pos, int buttonMask); | |||
void writeClientCutText(const char* str, rdr::U32 len); | |||
void writeClientCutText(const char* str); | |||
protected: | |||
void startMsg(int type); |
@@ -37,8 +37,7 @@ namespace rfb { | |||
bool __unused_attr down) { } | |||
virtual void pointerEvent(const Point& __unused_attr pos, | |||
int __unused_attr buttonMask) { } | |||
virtual void clientCutText(const char* __unused_attr str, | |||
int __unused_attr len) { } | |||
virtual void clientCutText(const char* __unused_attr str) { } | |||
}; | |||
} |
@@ -215,7 +215,7 @@ void SMsgReader::readClientCutText() | |||
CharArray ca(len); | |||
is->readBytes(ca.buf, len); | |||
CharArray filtered(convertLF(ca.buf, len)); | |||
handler->clientCutText(filtered.buf, strlen(filtered.buf)); | |||
handler->clientCutText(filtered.buf); | |||
} | |||
void SMsgReader::readQEMUMessage() |
@@ -78,11 +78,14 @@ void SMsgWriter::writeBell() | |||
endMsg(); | |||
} | |||
void SMsgWriter::writeServerCutText(const char* str, int len) | |||
void SMsgWriter::writeServerCutText(const char* str) | |||
{ | |||
if (memchr(str, '\r', len) != NULL) | |||
size_t len; | |||
if (strchr(str, '\r') != NULL) | |||
throw Exception("Invalid carriage return in clipboard data"); | |||
len = strlen(str); | |||
startMsg(msgTypeServerCutText); | |||
os->pad(3); | |||
os->writeU32(len); |
@@ -56,7 +56,7 @@ namespace rfb { | |||
// writeBell() and writeServerCutText() do the obvious thing. | |||
void writeBell(); | |||
void writeServerCutText(const char* str, int len); | |||
void writeServerCutText(const char* str); | |||
// writeFence() sends a new fence request or response to the client. | |||
void writeFence(rdr::U32 flags, unsigned len, const char data[]); |
@@ -282,13 +282,13 @@ void VNCSConnectionST::bellOrClose() | |||
} | |||
} | |||
void VNCSConnectionST::serverCutTextOrClose(const char *str, int len) | |||
void VNCSConnectionST::serverCutTextOrClose(const char *str) | |||
{ | |||
try { | |||
if (!accessCheck(AccessCutText)) return; | |||
if (!rfb::Server::sendCutText) return; | |||
if (state() == RFBSTATE_NORMAL) | |||
writer()->writeServerCutText(str, len); | |||
writer()->writeServerCutText(str); | |||
} catch(rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
@@ -596,11 +596,11 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { | |||
server->keyEvent(keysym, keycode, down); | |||
} | |||
void VNCSConnectionST::clientCutText(const char* str, int len) | |||
void VNCSConnectionST::clientCutText(const char* str) | |||
{ | |||
if (!accessCheck(AccessCutText)) return; | |||
if (!rfb::Server::acceptCutText) return; | |||
server->clientCutText(str, len); | |||
server->clientCutText(str); | |||
} | |||
void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental) |
@@ -72,7 +72,7 @@ namespace rfb { | |||
void screenLayoutChangeOrClose(rdr::U16 reason); | |||
void setCursorOrClose(); | |||
void bellOrClose(); | |||
void serverCutTextOrClose(const char *str, int len); | |||
void serverCutTextOrClose(const char *str); | |||
void setDesktopNameOrClose(const char *name); | |||
void setLEDStateOrClose(unsigned int state); | |||
void approveConnectionOrClose(bool accept, const char* reason); | |||
@@ -115,7 +115,7 @@ namespace rfb { | |||
virtual void setPixelFormat(const PixelFormat& pf); | |||
virtual void pointerEvent(const Point& pos, int buttonMask); | |||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); | |||
virtual void clientCutText(const char* str, int len); | |||
virtual void clientCutText(const char* str); | |||
virtual void framebufferUpdateRequest(const Rect& r, bool incremental); | |||
virtual void setDesktopSize(int fb_width, int fb_height, | |||
const ScreenSet& layout); |
@@ -57,7 +57,7 @@ namespace rfb { | |||
// serverCutText() tells the server that the cut text has changed. This | |||
// will normally be sent to all clients. | |||
virtual void serverCutText(const char* str, int len) = 0; | |||
virtual void serverCutText(const char* str) = 0; | |||
// bell() tells the server that it should make all clients make a bell sound. | |||
virtual void bell() = 0; |
@@ -340,14 +340,14 @@ void VNCServerST::bell() | |||
} | |||
} | |||
void VNCServerST::serverCutText(const char* str, int len) | |||
void VNCServerST::serverCutText(const char* str) | |||
{ | |||
if (memchr(str, '\r', len) != NULL) | |||
if (strchr(str, '\r') != NULL) | |||
throw Exception("Invalid carriage return in clipboard data"); | |||
std::list<VNCSConnectionST*>::iterator ci, ci_next; | |||
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) { | |||
ci_next = ci; ci_next++; | |||
(*ci)->serverCutTextOrClose(str, len); | |||
(*ci)->serverCutTextOrClose(str); | |||
} | |||
} | |||
@@ -461,9 +461,9 @@ void VNCServerST::pointerEvent(VNCSConnectionST* client, | |||
desktop->pointerEvent(pos, buttonMask); | |||
} | |||
void VNCServerST::clientCutText(const char* str, int len) | |||
void VNCServerST::clientCutText(const char* str) | |||
{ | |||
desktop->clientCutText(str, len); | |||
desktop->clientCutText(str); | |||
} | |||
unsigned int VNCServerST::setDesktopSize(VNCSConnectionST* requester, |
@@ -85,7 +85,7 @@ namespace rfb { | |||
virtual void setPixelBuffer(PixelBuffer* pb); | |||
virtual void setScreenLayout(const ScreenSet& layout); | |||
virtual const PixelBuffer* getPixelBuffer() const { return pb; } | |||
virtual void serverCutText(const char* str, int len); | |||
virtual void serverCutText(const char* str); | |||
virtual void approveConnection(network::Socket* sock, bool accept, | |||
const char* reason); | |||
@@ -115,7 +115,7 @@ namespace rfb { | |||
// Event handlers | |||
void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); | |||
void pointerEvent(VNCSConnectionST* client, const Point& pos, int buttonMask); | |||
void clientCutText(const char* str, int len); | |||
void clientCutText(const char* str); | |||
unsigned int setDesktopSize(VNCSConnectionST* requester, | |||
int fb_width, int fb_height, |
@@ -54,7 +54,7 @@ public: | |||
virtual void framebufferUpdateEnd(); | |||
virtual void setColourMapEntries(int, int, rdr::U16*); | |||
virtual void bell(); | |||
virtual void serverCutText(const char*, rdr::U32); | |||
virtual void serverCutText(const char*); | |||
public: | |||
double cpuTime; | |||
@@ -122,7 +122,7 @@ void CConn::bell() | |||
{ | |||
} | |||
void CConn::serverCutText(const char*, rdr::U32) | |||
void CConn::serverCutText(const char*) | |||
{ | |||
} | |||
@@ -96,7 +96,7 @@ public: | |||
virtual void dataRect(const rfb::Rect&, int); | |||
virtual void setColourMapEntries(int, int, rdr::U16*); | |||
virtual void bell(); | |||
virtual void serverCutText(const char*, rdr::U32); | |||
virtual void serverCutText(const char*); | |||
public: | |||
double decodeTime; | |||
@@ -254,7 +254,7 @@ void CConn::bell() | |||
{ | |||
} | |||
void CConn::serverCutText(const char*, rdr::U32) | |||
void CConn::serverCutText(const char*) | |||
{ | |||
} | |||
@@ -406,7 +406,7 @@ void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) { | |||
#endif | |||
} | |||
void XDesktop::clientCutText(const char* str, int len) { | |||
void XDesktop::clientCutText(const char* str) { | |||
} | |||
ScreenSet XDesktop::computeScreenLayout() |
@@ -56,7 +56,7 @@ public: | |||
virtual void pointerEvent(const rfb::Point& pos, int buttonMask); | |||
KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym); | |||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down); | |||
virtual void clientCutText(const char* str, int len); | |||
virtual void clientCutText(const char* str); | |||
virtual unsigned int setScreenLayout(int fb_width, int fb_height, | |||
const rfb::ScreenSet& layout); | |||
@@ -192,10 +192,10 @@ void XserverDesktop::setLEDState(unsigned int state) | |||
server->setLEDState(state); | |||
} | |||
void XserverDesktop::serverCutText(const char* str, int len) | |||
void XserverDesktop::serverCutText(const char* str) | |||
{ | |||
try { | |||
server->serverCutText(str, len); | |||
server->serverCutText(str); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("XserverDesktop::serverCutText: %s",e.str()); | |||
} | |||
@@ -436,9 +436,9 @@ void XserverDesktop::pointerEvent(const Point& pos, int buttonMask) | |||
vncPointerButtonAction(buttonMask); | |||
} | |||
void XserverDesktop::clientCutText(const char* str, int len) | |||
void XserverDesktop::clientCutText(const char* str) | |||
{ | |||
vncClientCutText(str, len); | |||
vncClientCutText(str); | |||
} | |||
unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, |
@@ -61,7 +61,7 @@ public: | |||
void refreshScreenLayout(); | |||
void bell(); | |||
void setLEDState(unsigned int state); | |||
void serverCutText(const char* str, int len); | |||
void serverCutText(const char* str); | |||
void setDesktopName(const char* name); | |||
void setCursor(int width, int height, int hotX, int hotY, | |||
const unsigned char *rgbaData); | |||
@@ -92,7 +92,7 @@ public: | |||
const char* userName); | |||
virtual void pointerEvent(const rfb::Point& pos, int buttonMask); | |||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); | |||
virtual void clientCutText(const char* str, int len); | |||
virtual void clientCutText(const char* str); | |||
virtual unsigned int setScreenLayout(int fb_width, int fb_height, | |||
const rfb::ScreenSet& layout); | |||
@@ -285,10 +285,10 @@ void vncUpdateDesktopName(void) | |||
desktop[scr]->setDesktopName(desktopName); | |||
} | |||
void vncServerCutText(const char *text, size_t len) | |||
void vncServerCutText(const char *text) | |||
{ | |||
for (int scr = 0; scr < vncGetScreenCount(); scr++) | |||
desktop[scr]->serverCutText(text, len); | |||
desktop[scr]->serverCutText(text); | |||
} | |||
int vncConnectClient(const char *addr) |
@@ -53,7 +53,7 @@ int vncGetSendPrimary(void); | |||
void vncUpdateDesktopName(void); | |||
void vncServerCutText(const char *text, size_t len); | |||
void vncServerCutText(const char *text); | |||
int vncConnectClient(const char *addr); | |||
@@ -48,7 +48,6 @@ static WindowPtr pWindow; | |||
static Window wid; | |||
static char* clientCutText; | |||
static int clientCutTextLen; | |||
static int vncCreateSelectionWindow(void); | |||
static int vncOwnSelection(Atom selection); | |||
@@ -82,23 +81,20 @@ void vncSelectionInit(void) | |||
FatalError("Add VNC SelectionCallback failed\n"); | |||
} | |||
void vncClientCutText(const char* str, int len) | |||
void vncClientCutText(const char* str) | |||
{ | |||
int rc; | |||
if (clientCutText != NULL) | |||
free(clientCutText); | |||
clientCutText = malloc(len); | |||
clientCutText = strdup(str); | |||
if (clientCutText == NULL) { | |||
LOG_ERROR("Could not allocate clipboard buffer"); | |||
DeleteWindowFromAnySelections(pWindow); | |||
return; | |||
} | |||
memcpy(clientCutText, str, len); | |||
clientCutTextLen = len; | |||
if (vncGetSetPrimary()) { | |||
rc = vncOwnSelection(xaPRIMARY); | |||
if (rc != Success) | |||
@@ -246,7 +242,7 @@ static int vncConvertSelection(ClientPtr client, Atom selection, | |||
} else if ((target == xaSTRING) || (target == xaTEXT)) { | |||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty, | |||
XA_STRING, 8, PropModeReplace, | |||
clientCutTextLen, clientCutText, | |||
strlen(clientCutText), clientCutText, | |||
TRUE); | |||
if (rc != Success) | |||
return rc; | |||
@@ -258,25 +254,22 @@ static int vncConvertSelection(ClientPtr client, Atom selection, | |||
const unsigned char* in; | |||
size_t in_len; | |||
buffer = malloc(clientCutTextLen*2); | |||
buffer = malloc(strlen(clientCutText)*2); | |||
if (buffer == NULL) | |||
return BadAlloc; | |||
out = buffer; | |||
len = 0; | |||
in = clientCutText; | |||
in_len = clientCutTextLen; | |||
while (in_len > 0) { | |||
while (*in != '\0') { | |||
if (*in & 0x80) { | |||
*out++ = 0xc0 | (*in >> 6); | |||
*out++ = 0x80 | (*in & 0x3f); | |||
len += 2; | |||
in++; | |||
in_len--; | |||
} else { | |||
*out++ = *in++; | |||
len++; | |||
in_len--; | |||
} | |||
} | |||
@@ -426,7 +419,7 @@ static void vncHandleSelection(Atom selection, Atom target, | |||
if (filtered == NULL) | |||
return; | |||
vncServerCutText(filtered, strlen(filtered)); | |||
vncServerCutText(filtered); | |||
vncStrFree(filtered); | |||
} else if (target == xaUTF8_STRING) { | |||
@@ -484,7 +477,7 @@ static void vncHandleSelection(Atom selection, Atom target, | |||
if (filtered == NULL) | |||
return; | |||
vncServerCutText(filtered, strlen(filtered)); | |||
vncServerCutText(filtered); | |||
vncStrFree(filtered); | |||
} |
@@ -1,4 +1,4 @@ | |||
/* Copyright 2016 Pierre Ossman for Cendio AB | |||
/* Copyright 2016-2019 Pierre Ossman for Cendio AB | |||
* | |||
* This is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
@@ -24,7 +24,7 @@ extern "C" { | |||
void vncSelectionInit(void); | |||
void vncClientCutText(const char* str, int len); | |||
void vncClientCutText(const char* str); | |||
#ifdef __cplusplus | |||
} |
@@ -377,9 +377,9 @@ void CConn::bell() | |||
fl_beep(); | |||
} | |||
void CConn::serverCutText(const char* str, rdr::U32 len) | |||
void CConn::serverCutText(const char* str) | |||
{ | |||
desktop->serverCutText(str, len); | |||
desktop->serverCutText(str); | |||
} | |||
void CConn::dataRect(const Rect& r, int encoding) |
@@ -61,7 +61,7 @@ public: | |||
void bell(); | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void serverCutText(const char* str); | |||
void framebufferUpdateStart(); | |||
void framebufferUpdateEnd(); |
@@ -276,9 +276,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) | |||
} | |||
void DesktopWindow::serverCutText(const char* str, rdr::U32 len) | |||
void DesktopWindow::serverCutText(const char* str) | |||
{ | |||
viewport->serverCutText(str, len); | |||
viewport->serverCutText(str); | |||
} | |||
@@ -63,7 +63,7 @@ public: | |||
void resizeFramebuffer(int new_w, int new_h); | |||
// Incoming clipboard from server | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void serverCutText(const char* str); | |||
// New image for the locally rendered cursor | |||
void setCursor(int width, int height, const rfb::Point& hotspot, |
@@ -232,7 +232,7 @@ void Viewport::updateWindow() | |||
damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height()); | |||
} | |||
void Viewport::serverCutText(const char* str, rdr::U32 len) | |||
void Viewport::serverCutText(const char* str) | |||
{ | |||
char *buffer; | |||
int size, ret; | |||
@@ -242,7 +242,7 @@ void Viewport::serverCutText(const char* str, rdr::U32 len) | |||
if (!acceptClipboard) | |||
return; | |||
size = fl_utf8froma(NULL, 0, str, len); | |||
size = fl_utf8froma(NULL, 0, str, strlen(str)); | |||
if (size <= 0) | |||
return; | |||
@@ -250,7 +250,7 @@ void Viewport::serverCutText(const char* str, rdr::U32 len) | |||
buffer = new char[size]; | |||
ret = fl_utf8froma(buffer, size, str, len); | |||
ret = fl_utf8froma(buffer, size, str, strlen(str)); | |||
assert(ret < size); | |||
vlog.debug("Got clipboard data (%d bytes)", (int)strlen(buffer)); | |||
@@ -577,7 +577,7 @@ int Viewport::handle(int event) | |||
vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(filtered)); | |||
try { | |||
cc->writer()->writeClientCutText(filtered, strlen(filtered)); | |||
cc->writer()->writeClientCutText(filtered); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("%s", e.str()); | |||
exit_vncviewer(e.str()); | |||
@@ -768,7 +768,7 @@ void Viewport::flushPendingClipboard() | |||
size_t len = strlen(pendingClientCutText); | |||
vlog.debug("Sending pending clipboard data (%d bytes)", (int)len); | |||
try { | |||
cc->writer()->writeClientCutText(pendingClientCutText, len); | |||
cc->writer()->writeClientCutText(pendingClientCutText); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("%s", e.str()); | |||
exit_vncviewer(e.str()); |
@@ -1,5 +1,5 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB | |||
* Copyright 2011-2019 Pierre Ossman <ossman@cendio.se> for Cendio AB | |||
* | |||
* This is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
@@ -46,7 +46,7 @@ public: | |||
void updateWindow(); | |||
// Incoming clipboard from server | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void serverCutText(const char* str); | |||
// New image for the locally rendered cursor | |||
void setCursor(int width, int height, const rfb::Point& hotspot, |
@@ -113,11 +113,11 @@ Clipboard::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) { | |||
// Notify clients | |||
if (notifier) { | |||
if (!clipdata) { | |||
notifier->notifyClipboardChanged(0, 0); | |||
notifier->notifyClipboardChanged(0); | |||
} else { | |||
CharArray unix_text(convertLF(clipdata, strlen(clipdata))); | |||
removeNonISOLatin1Chars(unix_text.buf); | |||
notifier->notifyClipboardChanged(unix_text.buf, strlen(unix_text.buf)); | |||
notifier->notifyClipboardChanged(unix_text.buf); | |||
} | |||
} else { | |||
vlog.debug("no clipboard notifier registered"); |
@@ -1,4 +1,5 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2016-2019 Pierre Ossman for Cendio AB | |||
* | |||
* This is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
@@ -38,7 +39,7 @@ namespace rfb { | |||
// -=- Abstract base class for callback recipients | |||
class Notifier { | |||
public: | |||
virtual void notifyClipboardChanged(const char* text, int len) = 0; | |||
virtual void notifyClipboardChanged(const char* text) = 0; | |||
virtual ~Notifier() {}; | |||
}; | |||
@@ -1,4 +1,5 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2011-2019 Pierre Ossman for Cendio AB | |||
* | |||
* This is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
@@ -328,19 +329,16 @@ bool SDisplay::checkLedState() { | |||
return false; | |||
} | |||
void SDisplay::clientCutText(const char* text, int len) { | |||
CharArray clip_sz(len+1); | |||
memcpy(clip_sz.buf, text, len); | |||
clip_sz.buf[len] = 0; | |||
clipboard->setClipText(clip_sz.buf); | |||
void SDisplay::clientCutText(const char* text) { | |||
clipboard->setClipText(text); | |||
} | |||
void | |||
SDisplay::notifyClipboardChanged(const char* text, int len) { | |||
SDisplay::notifyClipboardChanged(const char* text) { | |||
vlog.debug("clipboard text changed"); | |||
if (server) | |||
server->serverCutText(text, len); | |||
server->serverCutText(text); | |||
} | |||
@@ -1,4 +1,5 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2011-2019 Pierre Ossman for Cendio AB | |||
* | |||
* This is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
@@ -77,11 +78,11 @@ namespace rfb { | |||
const char* userName); | |||
virtual void pointerEvent(const Point& pos, int buttonmask); | |||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); | |||
virtual void clientCutText(const char* str, int len); | |||
virtual void clientCutText(const char* str); | |||
// -=- Clipboard | |||
virtual void notifyClipboardChanged(const char* text, int len); | |||
virtual void notifyClipboardChanged(const char* text); | |||
// -=- Display events | |||