Browse Source

Make sure clipboard uses \n line endings

This is required by the protocol so we should make sure it is
enforced. We are tolerant of clients that violate this though and
convert incoming clipboard data.
tags/v1.9.90
Pierre Ossman 5 years ago
parent
commit
546b2ad80a

+ 3
- 3
common/rfb/CMsgReader.cxx View File

@@ -157,10 +157,10 @@ void CMsgReader::readServerCutText()
vlog.error("cut text too long (%d bytes) - ignoring",len);
return;
}
CharArray ca(len+1);
ca.buf[len] = 0;
CharArray ca(len);
is->readBytes(ca.buf, len);
handler->serverCutText(ca.buf, len);
CharArray filtered(convertLF(ca.buf, len));
handler->serverCutText(filtered.buf, strlen(filtered.buf));
}

void CMsgReader::readFence()

+ 3
- 0
common/rfb/CMsgWriter.cxx View File

@@ -181,6 +181,9 @@ void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask)

void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
{
if (memchr(str, '\r', len) != NULL)
throw Exception("Invalid carriage return in clipboard data");

startMsg(msgTypeClientCutText);
os->pad(3);
os->writeU32(len);

+ 3
- 3
common/rfb/SMsgReader.cxx View File

@@ -212,10 +212,10 @@ void SMsgReader::readClientCutText()
vlog.error("Cut text too long (%d bytes) - ignoring", len);
return;
}
CharArray ca(len+1);
ca.buf[len] = 0;
CharArray ca(len);
is->readBytes(ca.buf, len);
handler->clientCutText(ca.buf, len);
CharArray filtered(convertLF(ca.buf, len));
handler->clientCutText(filtered.buf, strlen(filtered.buf));
}

void SMsgReader::readQEMUMessage()

+ 3
- 0
common/rfb/SMsgWriter.cxx View File

@@ -80,6 +80,9 @@ void SMsgWriter::writeBell()

void SMsgWriter::writeServerCutText(const char* str, int len)
{
if (memchr(str, '\r', len) != NULL)
throw Exception("Invalid carriage return in clipboard data");

startMsg(msgTypeServerCutText);
os->pad(3);
os->writeU32(len);

+ 2
- 0
common/rfb/VNCServerST.cxx View File

@@ -342,6 +342,8 @@ void VNCServerST::bell()

void VNCServerST::serverCutText(const char* str, int len)
{
if (memchr(str, '\r', len) != 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++;

+ 56
- 0
common/rfb/util.cxx View File

@@ -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
@@ -107,6 +108,61 @@ namespace rfb {
dest[src ? destlen-1 : 0] = 0;
}

char* convertLF(const char* src, size_t bytes)
{
char* buffer;
size_t sz;

char* out;
const char* in;
size_t in_len;

// Always include space for a NULL
sz = 1;

// Compute output size
in = src;
in_len = bytes;
while ((*in != '\0') && (in_len > 0)) {
if (*in != '\r') {
sz++;
in++;
in_len--;
continue;
}

if ((in_len == 0) || (*(in+1) != '\n'))
sz++;

in++;
in_len--;
}

// Alloc
buffer = new char[sz];
memset(buffer, 0, sz);

// And convert
out = buffer;
in = src;
in_len = bytes;
while ((*in != '\0') && (in_len > 0)) {
if (*in != '\r') {
*out++ = *in++;
in_len--;
continue;
}

if ((in_len == 0) || (*(in+1) != '\n'))
*out++ = '\n';

in++;
in_len--;
}

return buffer;
}

unsigned msBetween(const struct timeval *first,
const struct timeval *second)
{

+ 4
- 0
common/rfb/util.h View File

@@ -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
@@ -83,6 +84,9 @@ namespace rfb {
// Copies src to dest, up to specified length-1, and guarantees termination
void strCopy(char* dest, const char* src, int destlen);

// Makes sure line endings are in a certain format

char* convertLF(const char* src, size_t bytes = (size_t)-1);

// HELPER functions for timeout handling


+ 15
- 1
unix/xserver/hw/vnc/RFBGlue.cc View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2015 Pierre Ossman for Cendio AB
* 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
@@ -210,3 +210,17 @@ int vncIsTCPPortUsed(int port)
}
return 0;
}

char* vncConvertLF(const char* src, size_t bytes)
{
try {
return convertLF(src, bytes);
} catch (...) {
return NULL;
}
}

void vncStrFree(char* str)
{
strFree(str);
}

+ 4
- 1
unix/xserver/hw/vnc/RFBGlue.h View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2015 Pierre Ossman for Cendio AB
* 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
@@ -49,6 +49,9 @@ void vncListParams(int width, int nameWidth);
int vncGetSocketPort(int fd);
int vncIsTCPPortUsed(int port);

char* vncConvertLF(const char* src, size_t bytes);
void vncStrFree(char* str);

#ifdef __cplusplus
}
#endif

+ 18
- 4
unix/xserver/hw/vnc/vncSelection.c View File

@@ -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
@@ -415,13 +415,22 @@ static void vncHandleSelection(Atom selection, Atom target,
else if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
vncSelectionRequest(selection, xaUTF8_STRING);
} else if (target == xaSTRING) {
char* filtered;

if (prop->format != 8)
return;
if (prop->type != xaSTRING)
return;

vncServerCutText(prop->data, prop->size);
filtered = vncConvertLF(prop->data, prop->size);
if (filtered == NULL)
return;

vncServerCutText(filtered, strlen(filtered));

vncStrFree(filtered);
} else if (target == xaUTF8_STRING) {
char *filtered;
unsigned char* buffer;
unsigned char* out;
size_t len;
@@ -470,9 +479,14 @@ static void vncHandleSelection(Atom selection, Atom target,
}
}

vncServerCutText((const char*)buffer, len);

filtered = vncConvertLF(buffer, len);
free(buffer);
if (filtered == NULL)
return;

vncServerCutText(filtered, strlen(filtered));

vncStrFree(filtered);
}
}


+ 10
- 6
vncviewer/Viewport.cxx View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2014 Pierre Ossman for Cendio AB
* 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
@@ -549,7 +549,7 @@ void Viewport::resize(int x, int y, int w, int h)

int Viewport::handle(int event)
{
char *buffer;
char *buffer, *filtered;
int ret;
int buttonMask, wheelMask;
DownMap::const_iterator iter;
@@ -564,22 +564,26 @@ int Viewport::handle(int event)
ret = fl_utf8toa(Fl::event_text(), Fl::event_length(), buffer,
Fl::event_length() + 1);
assert(ret < (Fl::event_length() + 1));
filtered = convertLF(buffer, ret);
delete [] buffer;

if (!hasFocus()) {
pendingClientCutText = buffer;
pendingClientCutText = new char[strlen(filtered) + 1];
strcpy((char*)pendingClientCutText, filtered);
strFree(filtered);
return 1;
}

vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(buffer));
vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(filtered));

try {
cc->writer()->writeClientCutText(buffer, ret);
cc->writer()->writeClientCutText(filtered, strlen(filtered));
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
exit_vncviewer(e.str());
}

delete [] buffer;
strFree(filtered);

return 1;


+ 2
- 14
win/rfb_win32/Clipboard.cxx View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2012-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
@@ -34,18 +35,6 @@ static LogWriter vlog("Clipboard");
// -=- CR/LF handlers
//

char*
dos2unix(const char* text) {
int len = strlen(text)+1;
char* unix = new char[strlen(text)+1];
int i, j=0;
for (i=0; i<len; i++) {
if (text[i] != '\x0d')
unix[j++] = text[i];
}
return unix;
}

char*
unix2dos(const char* text) {
int len = strlen(text)+1;
@@ -126,8 +115,7 @@ Clipboard::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
if (!clipdata) {
notifier->notifyClipboardChanged(0, 0);
} else {
CharArray unix_text;
unix_text.buf = dos2unix(clipdata);
CharArray unix_text(convertLF(clipdata, strlen(clipdata)));
removeNonISOLatin1Chars(unix_text.buf);
notifier->notifyClipboardChanged(unix_text.buf, strlen(unix_text.buf));
}

Loading…
Cancel
Save