diff options
-rw-r--r-- | common/rfb/CMsgReader.cxx | 6 | ||||
-rw-r--r-- | common/rfb/CMsgWriter.cxx | 3 | ||||
-rw-r--r-- | common/rfb/SMsgReader.cxx | 6 | ||||
-rw-r--r-- | common/rfb/SMsgWriter.cxx | 3 | ||||
-rw-r--r-- | common/rfb/VNCServerST.cxx | 2 | ||||
-rw-r--r-- | common/rfb/util.cxx | 56 | ||||
-rw-r--r-- | common/rfb/util.h | 4 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/RFBGlue.cc | 16 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/RFBGlue.h | 5 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncSelection.c | 22 | ||||
-rw-r--r-- | vncviewer/Viewport.cxx | 16 | ||||
-rw-r--r-- | win/rfb_win32/Clipboard.cxx | 16 |
12 files changed, 123 insertions, 32 deletions
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx index 2b5b9fbf..a928eb15 100644 --- a/common/rfb/CMsgReader.cxx +++ b/common/rfb/CMsgReader.cxx @@ -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() diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx index d357c976..fed0bd27 100644 --- a/common/rfb/CMsgWriter.cxx +++ b/common/rfb/CMsgWriter.cxx @@ -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); diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx index 200350c1..0c0e8b26 100644 --- a/common/rfb/SMsgReader.cxx +++ b/common/rfb/SMsgReader.cxx @@ -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() diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx index 6a2c2ba0..f0748ff2 100644 --- a/common/rfb/SMsgWriter.cxx +++ b/common/rfb/SMsgWriter.cxx @@ -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); diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index c95c14f0..7820aef5 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -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++; diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx index f52213b3..f43a9453 100644 --- a/common/rfb/util.cxx +++ b/common/rfb/util.cxx @@ -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) { diff --git a/common/rfb/util.h b/common/rfb/util.h index 9e59bd37..de096692 100644 --- a/common/rfb/util.h +++ b/common/rfb/util.h @@ -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 diff --git a/unix/xserver/hw/vnc/RFBGlue.cc b/unix/xserver/hw/vnc/RFBGlue.cc index 160177bd..d9c456e8 100644 --- a/unix/xserver/hw/vnc/RFBGlue.cc +++ b/unix/xserver/hw/vnc/RFBGlue.cc @@ -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); +} diff --git a/unix/xserver/hw/vnc/RFBGlue.h b/unix/xserver/hw/vnc/RFBGlue.h index a63afd07..8e70c680 100644 --- a/unix/xserver/hw/vnc/RFBGlue.h +++ b/unix/xserver/hw/vnc/RFBGlue.h @@ -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 diff --git a/unix/xserver/hw/vnc/vncSelection.c b/unix/xserver/hw/vnc/vncSelection.c index 4f3538d4..5ddcaf00 100644 --- a/unix/xserver/hw/vnc/vncSelection.c +++ b/unix/xserver/hw/vnc/vncSelection.c @@ -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); } } diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index 5df5c796..15a3ec42 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -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; diff --git a/win/rfb_win32/Clipboard.cxx b/win/rfb_win32/Clipboard.cxx index 0e290623..fca6c1df 100644 --- a/win/rfb_win32/Clipboard.cxx +++ b/win/rfb_win32/Clipboard.cxx @@ -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 @@ -35,18 +36,6 @@ static LogWriter vlog("Clipboard"); // 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; char* dos = new char[strlen(text)*2+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)); } |