Merge pull request #36 from kasmtech/upstreamsync_sans_novnc
Upstream Syncs
@ -4,6 +4,7 @@ services:
|
|||||||
|
|
||||||
variables:
|
variables:
|
||||||
GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared
|
GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared
|
||||||
|
GIT_SUBMODULE_STRATEGY: normal
|
||||||
GIT_FETCH_EXTRA_FLAGS: --tags
|
GIT_FETCH_EXTRA_FLAGS: --tags
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[submodule "kasmweb"]
|
||||||
|
path = kasmweb
|
||||||
|
url = https://github.com/kasmtech/noVNC.git
|
||||||
|
branch = master
|
@ -14,6 +14,5 @@ cp -R ./* /build/
|
|||||||
cd /build
|
cd /build
|
||||||
rm *.md
|
rm *.md
|
||||||
rm AUTHORS
|
rm AUTHORS
|
||||||
rm *.yml
|
|
||||||
rm vnc.html
|
rm vnc.html
|
||||||
rm vnc_lite.html
|
rm vnc_lite.html
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#define errorNumber WSAGetLastError()
|
#define errorNumber WSAGetLastError()
|
||||||
|
#define SHUT_RD SD_RECEIVE
|
||||||
|
#define SHUT_WR SD_SEND
|
||||||
|
#define SHUT_RDWR SD_BOTH
|
||||||
#else
|
#else
|
||||||
#define errorNumber errno
|
#define errorNumber errno
|
||||||
#define closesocket close
|
#define closesocket close
|
||||||
@ -94,7 +97,7 @@ Socket::~Socket()
|
|||||||
void Socket::shutdown()
|
void Socket::shutdown()
|
||||||
{
|
{
|
||||||
isShutdown_ = true;
|
isShutdown_ = true;
|
||||||
::shutdown(getFd(), 2);
|
::shutdown(getFd(), SHUT_RDWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::isShutdown() const
|
bool Socket::isShutdown() const
|
||||||
@ -149,7 +152,7 @@ void SocketListener::shutdown()
|
|||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
#else
|
#else
|
||||||
::shutdown(fd, 2);
|
::shutdown(fd, SHUT_RDWR);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
69
common/rdr/BufferedInStream.cxx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2020 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/BufferedInStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
static const size_t DEFAULT_BUF_SIZE = 8192;
|
||||||
|
|
||||||
|
BufferedInStream::BufferedInStream()
|
||||||
|
: bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
ptr = end = start = new U8[bufSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedInStream::~BufferedInStream()
|
||||||
|
{
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BufferedInStream::pos()
|
||||||
|
{
|
||||||
|
return offset + ptr - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BufferedInStream::overrun(size_t needed, bool wait)
|
||||||
|
{
|
||||||
|
if (needed > bufSize)
|
||||||
|
throw Exception("BufferedInStream overrun: "
|
||||||
|
"requested size of %lu bytes exceeds maximum of %lu bytes",
|
||||||
|
(long unsigned)needed, (long unsigned)bufSize);
|
||||||
|
|
||||||
|
// Do we need to shuffle things around?
|
||||||
|
if ((bufSize - (ptr - start)) < needed) {
|
||||||
|
memmove(start, ptr, end - ptr);
|
||||||
|
|
||||||
|
offset += ptr - start;
|
||||||
|
end -= ptr - start;
|
||||||
|
ptr = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (avail() < needed) {
|
||||||
|
if (!fillBuffer(start + bufSize - end, wait))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
54
common/rdr/BufferedInStream.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2020 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Base class for input streams with a buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_BUFFEREDINSTREAM_H__
|
||||||
|
#define __RDR_BUFFEREDINSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/InStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class BufferedInStream : public InStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~BufferedInStream();
|
||||||
|
|
||||||
|
virtual size_t pos();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool fillBuffer(size_t maxSize, bool wait) = 0;
|
||||||
|
|
||||||
|
virtual bool overrun(size_t needed, bool wait);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t bufSize;
|
||||||
|
size_t offset;
|
||||||
|
U8* start;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BufferedInStream();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace rdr
|
||||||
|
|
||||||
|
#endif
|
108
common/rdr/BufferedOutStream.cxx
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011-2020 Pierre Ossman for Cendio AB
|
||||||
|
* Copyright 2017 Peter Astrand <astrand@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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rdr/BufferedOutStream.h>
|
||||||
|
#include <rdr/Exception.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace rdr;
|
||||||
|
|
||||||
|
static const size_t DEFAULT_BUF_SIZE = 16384;
|
||||||
|
|
||||||
|
BufferedOutStream::BufferedOutStream()
|
||||||
|
: bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||||
|
{
|
||||||
|
ptr = start = sentUpTo = new U8[bufSize];
|
||||||
|
end = start + bufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedOutStream::~BufferedOutStream()
|
||||||
|
{
|
||||||
|
// FIXME: Complain about non-flushed buffer?
|
||||||
|
delete [] start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BufferedOutStream::length()
|
||||||
|
{
|
||||||
|
return offset + ptr - sentUpTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BufferedOutStream::bufferUsage()
|
||||||
|
{
|
||||||
|
return ptr - sentUpTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferedOutStream::flush()
|
||||||
|
{
|
||||||
|
while (sentUpTo < ptr) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = bufferUsage();
|
||||||
|
|
||||||
|
if (!flushBuffer(false))
|
||||||
|
break;
|
||||||
|
|
||||||
|
offset += len - bufferUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Managed to flush everything?
|
||||||
|
if (sentUpTo == ptr)
|
||||||
|
ptr = sentUpTo = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferedOutStream::overrun(size_t needed)
|
||||||
|
{
|
||||||
|
if (needed > bufSize)
|
||||||
|
throw Exception("BufferedOutStream overrun: "
|
||||||
|
"requested size of %lu bytes exceeds maximum of %lu bytes",
|
||||||
|
(long unsigned)needed, (long unsigned)bufSize);
|
||||||
|
|
||||||
|
// First try to get rid of the data we have
|
||||||
|
flush();
|
||||||
|
|
||||||
|
// Still not enough space?
|
||||||
|
while (needed > avail()) {
|
||||||
|
// Can we shuffle things around?
|
||||||
|
// (don't do this if it gains us less than 25%)
|
||||||
|
if (((size_t)(sentUpTo - start) > bufSize / 4) &&
|
||||||
|
(needed < bufSize - (ptr - sentUpTo))) {
|
||||||
|
memmove(start, sentUpTo, ptr - sentUpTo);
|
||||||
|
ptr = start + (ptr - sentUpTo);
|
||||||
|
sentUpTo = start;
|
||||||
|
} else {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = bufferUsage();
|
||||||
|
|
||||||
|
// Have to get rid of more data, so allow the flush to wait...
|
||||||
|
flushBuffer(true);
|
||||||
|
|
||||||
|
offset += len - bufferUsage();
|
||||||
|
|
||||||
|
// Managed to flush everything?
|
||||||
|
if (sentUpTo == ptr)
|
||||||
|
ptr = sentUpTo = start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
common/rdr/BufferedOutStream.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||||
|
* Copyright 2011-2020 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Base class for output streams with a buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __RDR_BUFFEREDOUTSTREAM_H__
|
||||||
|
#define __RDR_BUFFEREDOUTSTREAM_H__
|
||||||
|
|
||||||
|
#include <rdr/OutStream.h>
|
||||||
|
|
||||||
|
namespace rdr {
|
||||||
|
|
||||||
|
class BufferedOutStream : public OutStream {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~BufferedOutStream();
|
||||||
|
|
||||||
|
virtual size_t length();
|
||||||
|
virtual void flush();
|
||||||
|
|
||||||
|
size_t bufferUsage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// flushBuffer() requests that the stream be flushed. Returns true if it is
|
||||||
|
// able to progress the output (which might still not mean any bytes
|
||||||
|
// actually moved) and can be called again. If wait is true then it will
|
||||||
|
// block until all data has been written.
|
||||||
|
|
||||||
|
virtual bool flushBuffer(bool wait) = 0;
|
||||||
|
|
||||||
|
virtual void overrun(size_t needed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t bufSize;
|
||||||
|
size_t offset;
|
||||||
|
U8* start;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
U8* sentUpTo;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BufferedOutStream();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
include_directories(${CMAKE_SOURCE_DIR}/common ${ZLIB_INCLUDE_DIRS})
|
include_directories(${CMAKE_SOURCE_DIR}/common ${ZLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_library(rdr STATIC
|
add_library(rdr STATIC
|
||||||
|
BufferedInStream.cxx
|
||||||
|
BufferedOutStream.cxx
|
||||||
Exception.cxx
|
Exception.cxx
|
||||||
FdInStream.cxx
|
FdInStream.cxx
|
||||||
FdOutStream.cxx
|
FdOutStream.cxx
|
||||||
|
@ -36,13 +36,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef vncmin
|
|
||||||
#define vncmin(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef vncmax
|
|
||||||
#define vncmax(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Old systems have select() in sys/time.h */
|
/* Old systems have select() in sys/time.h */
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
@ -53,31 +46,22 @@
|
|||||||
|
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 8192,
|
enum { DEFAULT_BUF_SIZE = 8192 };
|
||||||
MIN_BULK_SIZE = 1024 };
|
|
||||||
|
|
||||||
FdInStream::FdInStream(int fd_, int timeoutms_, size_t bufSize_,
|
FdInStream::FdInStream(int fd_, int timeoutms_,
|
||||||
bool closeWhenDone_)
|
bool closeWhenDone_)
|
||||||
: fd(fd_), closeWhenDone(closeWhenDone_),
|
: fd(fd_), closeWhenDone(closeWhenDone_),
|
||||||
timeoutms(timeoutms_), blockCallback(0),
|
timeoutms(timeoutms_), blockCallback(0)
|
||||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
{
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_,
|
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_)
|
||||||
size_t bufSize_)
|
: fd(fd_), timeoutms(0), blockCallback(blockCallback_)
|
||||||
: fd(fd_), timeoutms(0), blockCallback(blockCallback_),
|
|
||||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
{
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FdInStream::~FdInStream()
|
FdInStream::~FdInStream()
|
||||||
{
|
{
|
||||||
delete [] start;
|
|
||||||
if (closeWhenDone) close(fd);
|
if (closeWhenDone) close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,72 +76,15 @@ void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_)
|
|||||||
timeoutms = 0;
|
timeoutms = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FdInStream::pos()
|
|
||||||
|
bool FdInStream::fillBuffer(size_t maxSize, bool wait)
|
||||||
{
|
{
|
||||||
return offset + ptr - start;
|
size_t n = readWithTimeoutOrCallback((U8*)end, maxSize, wait);
|
||||||
}
|
if (n == 0)
|
||||||
|
return false;
|
||||||
|
end += n;
|
||||||
|
|
||||||
void FdInStream::readBytes(void* data, size_t length)
|
return true;
|
||||||
{
|
|
||||||
if (length < MIN_BULK_SIZE) {
|
|
||||||
InStream::readBytes(data, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
U8* dataPtr = (U8*)data;
|
|
||||||
|
|
||||||
size_t n = end - ptr;
|
|
||||||
if (n > length) n = length;
|
|
||||||
|
|
||||||
memcpy(dataPtr, ptr, n);
|
|
||||||
dataPtr += n;
|
|
||||||
length -= n;
|
|
||||||
ptr += n;
|
|
||||||
|
|
||||||
while (length > 0) {
|
|
||||||
n = readWithTimeoutOrCallback(dataPtr, length);
|
|
||||||
dataPtr += n;
|
|
||||||
length -= n;
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("FdInStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
end -= ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
size_t bytes_to_read;
|
|
||||||
while ((size_t)(end - start) < itemSize) {
|
|
||||||
bytes_to_read = start + bufSize - end;
|
|
||||||
if (!timing) {
|
|
||||||
// When not timing, we must be careful not to read too much
|
|
||||||
// extra data into the buffer. Otherwise, the line speed
|
|
||||||
// estimation might stay at zero for a long time: All reads
|
|
||||||
// during timing=1 can be satisfied without calling
|
|
||||||
// readWithTimeoutOrCallback. However, reading only 1 or 2 bytes
|
|
||||||
// bytes is ineffecient.
|
|
||||||
bytes_to_read = vncmin(bytes_to_read, vncmax(itemSize*nItems, 8));
|
|
||||||
}
|
|
||||||
size_t n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait);
|
|
||||||
if (n == 0) return 0;
|
|
||||||
end += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -175,10 +102,6 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
|||||||
|
|
||||||
size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait)
|
size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait)
|
||||||
{
|
{
|
||||||
struct timeval before, after;
|
|
||||||
if (timing)
|
|
||||||
gettimeofday(&before, 0);
|
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
while (true) {
|
while (true) {
|
||||||
do {
|
do {
|
||||||
@ -215,48 +138,5 @@ size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait)
|
|||||||
if (n < 0) throw SystemException("read",errno);
|
if (n < 0) throw SystemException("read",errno);
|
||||||
if (n == 0) throw EndOfStream();
|
if (n == 0) throw EndOfStream();
|
||||||
|
|
||||||
if (timing) {
|
|
||||||
gettimeofday(&after, 0);
|
|
||||||
int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 +
|
|
||||||
(after.tv_usec - before.tv_usec) / 100);
|
|
||||||
int newKbits = n * 8 / 1000;
|
|
||||||
|
|
||||||
// limit rate to between 10kbit/s and 40Mbit/s
|
|
||||||
|
|
||||||
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
|
|
||||||
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
|
|
||||||
|
|
||||||
timeWaitedIn100us += newTimeWaited;
|
|
||||||
timedKbits += newKbits;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FdInStream::startTiming()
|
|
||||||
{
|
|
||||||
timing = true;
|
|
||||||
|
|
||||||
// Carry over up to 1s worth of previous rate for smoothing.
|
|
||||||
|
|
||||||
if (timeWaitedIn100us > 10000) {
|
|
||||||
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
|
|
||||||
timeWaitedIn100us = 10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FdInStream::stopTiming()
|
|
||||||
{
|
|
||||||
timing = false;
|
|
||||||
if (timeWaitedIn100us < timedKbits/2)
|
|
||||||
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FdInStream::kbitsPerSecond()
|
|
||||||
{
|
|
||||||
// The following calculation will overflow 32-bit arithmetic if we have
|
|
||||||
// received more than about 50Mbytes (400Mbits) since we started timing, so
|
|
||||||
// it should be OK for a single RFB update.
|
|
||||||
|
|
||||||
return timedKbits * 10000 / timeWaitedIn100us;
|
|
||||||
}
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#ifndef __RDR_FDINSTREAM_H__
|
#ifndef __RDR_FDINSTREAM_H__
|
||||||
#define __RDR_FDINSTREAM_H__
|
#define __RDR_FDINSTREAM_H__
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
@ -33,31 +33,21 @@ namespace rdr {
|
|||||||
virtual ~FdInStreamBlockCallback() {}
|
virtual ~FdInStreamBlockCallback() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FdInStream : public InStream {
|
class FdInStream : public BufferedInStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FdInStream(int fd, int timeoutms=-1, size_t bufSize=0,
|
FdInStream(int fd, int timeoutms=-1, bool closeWhenDone_=false);
|
||||||
bool closeWhenDone_=false);
|
FdInStream(int fd, FdInStreamBlockCallback* blockCallback);
|
||||||
FdInStream(int fd, FdInStreamBlockCallback* blockCallback,
|
|
||||||
size_t bufSize=0);
|
|
||||||
virtual ~FdInStream();
|
virtual ~FdInStream();
|
||||||
|
|
||||||
void setTimeout(int timeoutms);
|
void setTimeout(int timeoutms);
|
||||||
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
|
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
|
||||||
int getFd() { return fd; }
|
int getFd() { return fd; }
|
||||||
size_t pos();
|
|
||||||
void readBytes(void* data, size_t length);
|
|
||||||
|
|
||||||
void startTiming();
|
|
||||||
void stopTiming();
|
|
||||||
unsigned int kbitsPerSecond();
|
|
||||||
unsigned int timeWaited() { return timeWaitedIn100us; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
|
|
||||||
size_t readWithTimeoutOrCallback(void* buf, size_t len, bool wait=true);
|
size_t readWithTimeoutOrCallback(void* buf, size_t len, bool wait=true);
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
@ -65,11 +55,6 @@ namespace rdr {
|
|||||||
int timeoutms;
|
int timeoutms;
|
||||||
FdInStreamBlockCallback* blockCallback;
|
FdInStreamBlockCallback* blockCallback;
|
||||||
|
|
||||||
bool timing;
|
|
||||||
unsigned int timeWaitedIn100us;
|
|
||||||
unsigned int timedKbits;
|
|
||||||
|
|
||||||
size_t bufSize;
|
|
||||||
size_t offset;
|
size_t offset;
|
||||||
U8* start;
|
U8* start;
|
||||||
};
|
};
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Old systems have select() in sys/time.h */
|
/* Old systems have select() in sys/time.h */
|
||||||
@ -49,26 +51,19 @@
|
|||||||
|
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_)
|
||||||
|
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_)
|
||||||
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, size_t bufSize_)
|
|
||||||
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_),
|
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
{
|
||||||
ptr = start = sentUpTo = new U8[bufSize];
|
|
||||||
end = start + bufSize;
|
|
||||||
|
|
||||||
gettimeofday(&lastWrite, NULL);
|
gettimeofday(&lastWrite, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FdOutStream::~FdOutStream()
|
FdOutStream::~FdOutStream()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
blocking = true;
|
while (sentUpTo != ptr)
|
||||||
flush();
|
flushBuffer(true);
|
||||||
} catch (Exception&) {
|
} catch (Exception&) {
|
||||||
}
|
}
|
||||||
delete [] start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FdOutStream::setTimeout(int timeoutms_) {
|
void FdOutStream::setTimeout(int timeoutms_) {
|
||||||
@ -79,82 +74,29 @@ void FdOutStream::setBlocking(bool blocking_) {
|
|||||||
blocking = blocking_;
|
blocking = blocking_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FdOutStream::length()
|
|
||||||
{
|
|
||||||
return offset + ptr - sentUpTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FdOutStream::bufferUsage()
|
|
||||||
{
|
|
||||||
return ptr - sentUpTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned FdOutStream::getIdleTime()
|
unsigned FdOutStream::getIdleTime()
|
||||||
{
|
{
|
||||||
return rfb::msSince(&lastWrite);
|
return rfb::msSince(&lastWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FdOutStream::flush()
|
bool FdOutStream::flushBuffer(bool wait)
|
||||||
{
|
{
|
||||||
while (sentUpTo < ptr) {
|
size_t n = writeWithTimeout((const void*) sentUpTo,
|
||||||
size_t n = writeWithTimeout((const void*) sentUpTo,
|
ptr - sentUpTo,
|
||||||
ptr - sentUpTo,
|
(blocking || wait)? timeoutms : 0);
|
||||||
blocking? timeoutms : 0);
|
|
||||||
|
|
||||||
// Timeout?
|
// Timeout?
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// If non-blocking then we're done here
|
// If non-blocking then we're done here
|
||||||
if (!blocking)
|
if (!blocking && !wait)
|
||||||
break;
|
return false;
|
||||||
|
|
||||||
throw TimedOut();
|
throw TimedOut();
|
||||||
}
|
|
||||||
|
|
||||||
sentUpTo += n;
|
|
||||||
offset += n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Managed to flush everything?
|
sentUpTo += n;
|
||||||
if (sentUpTo == ptr)
|
|
||||||
ptr = sentUpTo = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
size_t FdOutStream::overrun(size_t itemSize, size_t nItems)
|
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("FdOutStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
// First try to get rid of the data we have
|
|
||||||
flush();
|
|
||||||
|
|
||||||
// Still not enough space?
|
|
||||||
if (itemSize > (size_t)(end - ptr)) {
|
|
||||||
// Can we shuffle things around?
|
|
||||||
// (don't do this if it gains us less than 25%)
|
|
||||||
if (((size_t)(sentUpTo - start) > bufSize / 4) &&
|
|
||||||
(itemSize < bufSize - (ptr - sentUpTo))) {
|
|
||||||
memmove(start, sentUpTo, ptr - sentUpTo);
|
|
||||||
ptr = start + (ptr - sentUpTo);
|
|
||||||
sentUpTo = start;
|
|
||||||
} else {
|
|
||||||
// Have to get rid of more data, so turn off non-blocking
|
|
||||||
// for a bit...
|
|
||||||
bool realBlocking;
|
|
||||||
|
|
||||||
realBlocking = blocking;
|
|
||||||
blocking = true;
|
|
||||||
flush();
|
|
||||||
blocking = realBlocking;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -26,38 +26,29 @@
|
|||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
#include <rdr/BufferedOutStream.h>
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class FdOutStream : public OutStream {
|
class FdOutStream : public BufferedOutStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FdOutStream(int fd, bool blocking=true, int timeoutms=-1, size_t bufSize=0);
|
FdOutStream(int fd, bool blocking=true, int timeoutms=-1);
|
||||||
virtual ~FdOutStream();
|
virtual ~FdOutStream();
|
||||||
|
|
||||||
void setTimeout(int timeoutms);
|
void setTimeout(int timeoutms);
|
||||||
void setBlocking(bool blocking);
|
void setBlocking(bool blocking);
|
||||||
int getFd() { return fd; }
|
int getFd() { return fd; }
|
||||||
|
|
||||||
void flush();
|
|
||||||
size_t length();
|
|
||||||
|
|
||||||
int bufferUsage();
|
|
||||||
|
|
||||||
unsigned getIdleTime();
|
unsigned getIdleTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t overrun(size_t itemSize, size_t nItems);
|
virtual bool flushBuffer(bool wait);
|
||||||
size_t writeWithTimeout(const void* data, size_t length, int timeoutms);
|
size_t writeWithTimeout(const void* data, size_t length, int timeoutms);
|
||||||
int fd;
|
int fd;
|
||||||
bool blocking;
|
bool blocking;
|
||||||
int timeoutms;
|
int timeoutms;
|
||||||
size_t bufSize;
|
|
||||||
size_t offset;
|
|
||||||
U8* start;
|
|
||||||
U8* sentUpTo;
|
|
||||||
struct timeval lastWrite;
|
struct timeval lastWrite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ FileInStream::FileInStream(const char *fileName)
|
|||||||
file = fopen(fileName, "rb");
|
file = fopen(fileName, "rb");
|
||||||
if (!file)
|
if (!file)
|
||||||
throw SystemException("fopen", errno);
|
throw SystemException("fopen", errno);
|
||||||
ptr = end = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInStream::~FileInStream(void) {
|
FileInStream::~FileInStream(void) {
|
||||||
@ -40,50 +39,17 @@ FileInStream::~FileInStream(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileInStream::reset(void) {
|
bool FileInStream::fillBuffer(size_t maxSize, bool wait)
|
||||||
if (!file)
|
|
||||||
throw Exception("File is not open");
|
|
||||||
if (fseek(file, 0, SEEK_SET) != 0)
|
|
||||||
throw SystemException("fseek", errno);
|
|
||||||
ptr = end = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FileInStream::pos()
|
|
||||||
{
|
{
|
||||||
if (!file)
|
size_t n = fread((U8 *)end, 1, maxSize, file);
|
||||||
throw Exception("File is not open");
|
if (n == 0) {
|
||||||
|
if (ferror(file))
|
||||||
return ftell(file) + ptr - b;
|
throw SystemException("fread", errno);
|
||||||
}
|
if (feof(file))
|
||||||
|
throw EndOfStream();
|
||||||
size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
return false;
|
||||||
{
|
|
||||||
if (itemSize > sizeof(b))
|
|
||||||
throw Exception("FileInStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(b, ptr, end - ptr);
|
|
||||||
|
|
||||||
end -= ptr - b;
|
|
||||||
ptr = b;
|
|
||||||
|
|
||||||
|
|
||||||
while ((size_t)(end - b) < itemSize) {
|
|
||||||
size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file);
|
|
||||||
if (n == 0) {
|
|
||||||
if (ferror(file))
|
|
||||||
throw SystemException("fread", errno);
|
|
||||||
if (feof(file))
|
|
||||||
throw EndOfStream();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
end += b + sizeof(b) - end;
|
|
||||||
}
|
}
|
||||||
|
end += n;
|
||||||
|
|
||||||
size_t nAvail;
|
return true;
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
@ -22,26 +22,21 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class FileInStream : public InStream {
|
class FileInStream : public BufferedInStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FileInStream(const char *fileName);
|
FileInStream(const char *fileName);
|
||||||
~FileInStream(void);
|
~FileInStream(void);
|
||||||
|
|
||||||
void reset(void);
|
private:
|
||||||
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
size_t pos();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait = true);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
U8 b[131072];
|
|
||||||
FILE *file;
|
FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,18 +24,14 @@
|
|||||||
|
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
const int DEFAULT_BUF_LEN = 16384;
|
|
||||||
|
|
||||||
static inline int min(int a, int b) {return a<b ? a : b;}
|
static inline int min(int a, int b) {return a<b ? a : b;}
|
||||||
|
|
||||||
HexInStream::HexInStream(InStream& is, size_t bufSize_)
|
HexInStream::HexInStream(InStream& is)
|
||||||
: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
|
: in_stream(is)
|
||||||
{
|
{
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HexInStream::~HexInStream() {
|
HexInStream::~HexInStream() {
|
||||||
delete [] start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -76,44 +72,24 @@ decodeError:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t HexInStream::pos() {
|
bool HexInStream::fillBuffer(size_t maxSize, bool wait) {
|
||||||
return offset + ptr - start;
|
if (!in_stream.check(2, wait))
|
||||||
}
|
return false;
|
||||||
|
|
||||||
size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) {
|
const U8* iptr = in_stream.getptr();
|
||||||
if (itemSize > bufSize)
|
const U8* eptr = in_stream.getend();
|
||||||
throw Exception("HexInStream overrun: max itemSize exceeded");
|
size_t length = min((eptr - iptr)/2, maxSize);
|
||||||
|
|
||||||
if (end - ptr != 0)
|
U8* optr = (U8*) end;
|
||||||
memmove(start, ptr, end - ptr);
|
for (size_t i=0; i<length; i++) {
|
||||||
|
int v = 0;
|
||||||
end -= ptr - start;
|
readHexAndShift(iptr[i*2], &v);
|
||||||
offset += ptr - start;
|
readHexAndShift(iptr[i*2+1], &v);
|
||||||
ptr = start;
|
optr[i] = v;
|
||||||
|
|
||||||
while ((size_t)(end - ptr) < itemSize) {
|
|
||||||
size_t n = in_stream.check(2, 1, wait);
|
|
||||||
if (n == 0) return 0;
|
|
||||||
const U8* iptr = in_stream.getptr();
|
|
||||||
const U8* eptr = in_stream.getend();
|
|
||||||
size_t length = min((eptr - iptr)/2, start + bufSize - end);
|
|
||||||
|
|
||||||
U8* optr = (U8*) end;
|
|
||||||
for (size_t i=0; i<length; i++) {
|
|
||||||
int v = 0;
|
|
||||||
readHexAndShift(iptr[i*2], &v);
|
|
||||||
readHexAndShift(iptr[i*2+1], &v);
|
|
||||||
optr[i] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
in_stream.setptr(iptr + length*2);
|
|
||||||
end += length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nAvail;
|
in_stream.setptr(iptr + length*2);
|
||||||
nAvail = (end - ptr) / itemSize;
|
end += length;
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -19,29 +19,23 @@
|
|||||||
#ifndef __RDR_HEX_INSTREAM_H__
|
#ifndef __RDR_HEX_INSTREAM_H__
|
||||||
#define __RDR_HEX_INSTREAM_H__
|
#define __RDR_HEX_INSTREAM_H__
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class HexInStream : public InStream {
|
class HexInStream : public BufferedInStream {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HexInStream(InStream& is, size_t bufSize=0);
|
HexInStream(InStream& is);
|
||||||
virtual ~HexInStream();
|
virtual ~HexInStream();
|
||||||
|
|
||||||
size_t pos();
|
|
||||||
|
|
||||||
static bool readHexAndShift(char c, int* v);
|
static bool readHexAndShift(char c, int* v);
|
||||||
static bool hexStrToBin(const char* s, char** data, size_t* length);
|
static bool hexStrToBin(const char* s, char** data, size_t* length);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t bufSize;
|
|
||||||
U8* start;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
InStream& in_stream;
|
InStream& in_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ const int DEFAULT_BUF_LEN = 16384;
|
|||||||
|
|
||||||
static inline size_t min(size_t a, size_t b) {return a<b ? a : b;}
|
static inline size_t min(size_t a, size_t b) {return a<b ? a : b;}
|
||||||
|
|
||||||
HexOutStream::HexOutStream(OutStream& os, size_t buflen)
|
HexOutStream::HexOutStream(OutStream& os)
|
||||||
: out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
|
: out_stream(os), offset(0), bufSize(DEFAULT_BUF_LEN)
|
||||||
{
|
{
|
||||||
if (bufSize % 2)
|
if (bufSize % 2)
|
||||||
bufSize--;
|
bufSize--;
|
||||||
@ -95,18 +95,10 @@ HexOutStream::flush() {
|
|||||||
out_stream.flush();
|
out_stream.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void HexOutStream::overrun(size_t needed) {
|
||||||
HexOutStream::overrun(size_t itemSize, size_t nItems) {
|
if (needed > bufSize)
|
||||||
if (itemSize > bufSize)
|
throw Exception("HexOutStream overrun: buffer size exceeded");
|
||||||
throw Exception("HexOutStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
writeBuffer();
|
writeBuffer();
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace rdr {
|
|||||||
class HexOutStream : public OutStream {
|
class HexOutStream : public OutStream {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HexOutStream(OutStream& os, size_t buflen=0);
|
HexOutStream(OutStream& os);
|
||||||
virtual ~HexOutStream();
|
virtual ~HexOutStream();
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
@ -37,7 +37,7 @@ namespace rdr {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void writeBuffer();
|
void writeBuffer();
|
||||||
size_t overrun(size_t itemSize, size_t nItems);
|
virtual void overrun(size_t needed);
|
||||||
|
|
||||||
OutStream& out_stream;
|
OutStream& out_stream;
|
||||||
|
|
||||||
|
@ -35,28 +35,25 @@ namespace rdr {
|
|||||||
|
|
||||||
virtual ~InStream() {}
|
virtual ~InStream() {}
|
||||||
|
|
||||||
// check() ensures there is buffer data for at least one item of size
|
// avail() returns the number of bytes that are currenctly directly
|
||||||
// itemSize bytes. Returns the number of items in the buffer (up to a
|
// available from the stream.
|
||||||
// maximum of nItems). If wait is false, then instead of blocking to wait
|
|
||||||
// for the bytes, zero is returned if the bytes are not immediately
|
|
||||||
// available. If itemSize or nItems is zero, check() will return zero.
|
|
||||||
|
|
||||||
inline size_t check(size_t itemSize, size_t nItems=1, bool wait=true)
|
inline size_t avail()
|
||||||
{
|
{
|
||||||
size_t nAvail;
|
return end - ptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (itemSize == 0 || nItems == 0)
|
// check() ensures there is buffer data for at least needed bytes. Returns
|
||||||
return 0;
|
// true once the data is available. If wait is false, then instead of
|
||||||
|
// blocking to wait for the bytes, false is returned if the bytes are not
|
||||||
|
// immediately available.
|
||||||
|
|
||||||
if (itemSize > (size_t)(end - ptr))
|
inline size_t check(size_t needed, bool wait=true)
|
||||||
return overrun(itemSize, nItems, wait);
|
{
|
||||||
|
if (needed > avail())
|
||||||
|
return overrun(needed, wait);
|
||||||
|
|
||||||
// itemSize cannot be zero at this point
|
return true;
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkNoWait() tries to make sure that the given number of bytes can
|
// checkNoWait() tries to make sure that the given number of bytes can
|
||||||
@ -64,10 +61,7 @@ namespace rdr {
|
|||||||
// otherwise. The length must be "small" (less than the buffer size).
|
// otherwise. The length must be "small" (less than the buffer size).
|
||||||
// If length is zero, checkNoWait() will return true.
|
// If length is zero, checkNoWait() will return true.
|
||||||
|
|
||||||
inline bool checkNoWait(size_t length)
|
inline bool checkNoWait(size_t length) { return check(length, false); }
|
||||||
{
|
|
||||||
return length == 0 || check(length, 1, false) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// readU/SN() methods read unsigned and signed N-bit integers.
|
// readU/SN() methods read unsigned and signed N-bit integers.
|
||||||
|
|
||||||
@ -138,13 +132,12 @@ namespace rdr {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||||
// It ensures there are at least itemSize bytes of buffer data. Returns
|
// It ensures there are at least needed bytes of buffer data. Returns true
|
||||||
// the number of items in the buffer (up to a maximum of nItems). itemSize
|
// once the data is available. If wait is false, then instead of blocking
|
||||||
// is supposed to be "small" (a few bytes). If wait is false, then
|
// to wait for the bytes, false is returned if the bytes are not
|
||||||
// instead of blocking to wait for the bytes, zero is returned if the bytes
|
// immediately available.
|
||||||
// are not immediately available.
|
|
||||||
|
|
||||||
virtual size_t overrun(size_t itemSize, size_t nItems, bool wait=true) = 0;
|
virtual bool overrun(size_t needed, bool wait=true) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace rdr {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait) { throw EndOfStream(); }
|
bool overrun(size_t needed, bool wait) { throw EndOfStream(); }
|
||||||
const U8* start;
|
const U8* start;
|
||||||
bool deleteWhenDone;
|
bool deleteWhenDone;
|
||||||
};
|
};
|
||||||
|
@ -41,12 +41,6 @@ namespace rdr {
|
|||||||
delete [] start;
|
delete [] start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBytes(const void* data, size_t length) {
|
|
||||||
check(length);
|
|
||||||
memcpy(ptr, data, length);
|
|
||||||
ptr += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t length() { return ptr - start; }
|
size_t length() { return ptr - start; }
|
||||||
void clear() { ptr = start; };
|
void clear() { ptr = start; };
|
||||||
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
|
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
|
||||||
@ -58,11 +52,11 @@ namespace rdr {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// overrun() either doubles the buffer or adds enough space for nItems of
|
// overrun() either doubles the buffer or adds enough space for
|
||||||
// size itemSize bytes.
|
// needed bytes.
|
||||||
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems) {
|
virtual void overrun(size_t needed) {
|
||||||
size_t len = ptr - start + itemSize * nItems;
|
size_t len = ptr - start + needed;
|
||||||
if (len < (size_t)(end - start) * 2)
|
if (len < (size_t)(end - start) * 2)
|
||||||
len = (end - start) * 2;
|
len = (end - start) * 2;
|
||||||
|
|
||||||
@ -75,8 +69,6 @@ namespace rdr {
|
|||||||
delete [] start;
|
delete [] start;
|
||||||
start = newStart;
|
start = newStart;
|
||||||
end = newStart + len;
|
end = newStart + len;
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U8* start;
|
U8* start;
|
||||||
|
@ -40,22 +40,20 @@ namespace rdr {
|
|||||||
|
|
||||||
virtual ~OutStream() {}
|
virtual ~OutStream() {}
|
||||||
|
|
||||||
// check() ensures there is buffer space for at least one item of size
|
// avail() returns the number of bytes that currently be written to the
|
||||||
// itemSize bytes. Returns the number of items which fit (up to a maximum
|
// stream without any risk of blocking.
|
||||||
// of nItems).
|
|
||||||
|
|
||||||
inline size_t check(size_t itemSize, size_t nItems=1)
|
inline size_t avail()
|
||||||
{
|
{
|
||||||
size_t nAvail;
|
return end - ptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (itemSize > (size_t)(end - ptr))
|
// check() ensures there is buffer space for at least needed bytes.
|
||||||
return overrun(itemSize, nItems);
|
|
||||||
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
inline void check(size_t needed)
|
||||||
if (nAvail < nItems)
|
{
|
||||||
return nAvail;
|
if (needed > avail())
|
||||||
|
overrun(needed);
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeU/SN() methods write unsigned and signed N-bit integers.
|
// writeU/SN() methods write unsigned and signed N-bit integers.
|
||||||
@ -83,19 +81,14 @@ namespace rdr {
|
|||||||
while (bytes-- > 0) writeU8(0);
|
while (bytes-- > 0) writeU8(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void skip(size_t bytes) {
|
|
||||||
while (bytes > 0) {
|
|
||||||
size_t n = check(1, bytes);
|
|
||||||
ptr += n;
|
|
||||||
bytes -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeBytes() writes an exact number of bytes.
|
// writeBytes() writes an exact number of bytes.
|
||||||
|
|
||||||
void writeBytes(const void* data, size_t length) {
|
void writeBytes(const void* data, size_t length) {
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
size_t n = check(1, length);
|
check(1);
|
||||||
|
size_t n = length;
|
||||||
|
if (length > avail())
|
||||||
|
n = avail();
|
||||||
memcpy(ptr, data, n);
|
memcpy(ptr, data, n);
|
||||||
ptr += n;
|
ptr += n;
|
||||||
data = (U8*)data + n;
|
data = (U8*)data + n;
|
||||||
@ -107,7 +100,10 @@ namespace rdr {
|
|||||||
|
|
||||||
void copyBytes(InStream* is, size_t length) {
|
void copyBytes(InStream* is, size_t length) {
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
size_t n = check(1, length);
|
check(1);
|
||||||
|
size_t n = length;
|
||||||
|
if (length > avail())
|
||||||
|
n = avail();
|
||||||
is->readBytes(ptr, n);
|
is->readBytes(ptr, n);
|
||||||
ptr += n;
|
ptr += n;
|
||||||
length -= n;
|
length -= n;
|
||||||
@ -143,11 +139,9 @@ namespace rdr {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||||
// It ensures there are at least itemSize bytes of buffer space. Returns
|
// It ensures there are at least needed bytes of buffer space.
|
||||||
// the number of items which fit (up to a maximum of nItems). itemSize is
|
|
||||||
// supposed to be "small" (a few bytes).
|
|
||||||
|
|
||||||
virtual size_t overrun(size_t itemSize, size_t nItems) = 0;
|
virtual void overrun(size_t needed) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -32,15 +32,10 @@
|
|||||||
|
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
const size_t DEFAULT_BUF_LEN = 256;
|
|
||||||
|
|
||||||
unsigned int RandomStream::seed;
|
unsigned int RandomStream::seed;
|
||||||
|
|
||||||
RandomStream::RandomStream()
|
RandomStream::RandomStream()
|
||||||
: offset(0)
|
|
||||||
{
|
{
|
||||||
ptr = end = start = new U8[DEFAULT_BUF_LEN];
|
|
||||||
|
|
||||||
#ifdef RFB_HAVE_WINCRYPT
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
provider = 0;
|
provider = 0;
|
||||||
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
|
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
|
||||||
@ -72,8 +67,6 @@ RandomStream::RandomStream()
|
|||||||
}
|
}
|
||||||
|
|
||||||
RandomStream::~RandomStream() {
|
RandomStream::~RandomStream() {
|
||||||
delete [] start;
|
|
||||||
|
|
||||||
#ifdef RFB_HAVE_WINCRYPT
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
if (provider)
|
if (provider)
|
||||||
CryptReleaseContext(provider, 0);
|
CryptReleaseContext(provider, 0);
|
||||||
@ -83,50 +76,29 @@ RandomStream::~RandomStream() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RandomStream::pos() {
|
bool RandomStream::fillBuffer(size_t maxSize, bool wait) {
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t RandomStream::overrun(size_t itemSize, size_t nItems, bool wait) {
|
|
||||||
if (itemSize > DEFAULT_BUF_LEN)
|
|
||||||
throw Exception("RandomStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
end -= ptr - start;
|
|
||||||
offset += ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
size_t length = start + DEFAULT_BUF_LEN - end;
|
|
||||||
|
|
||||||
#ifdef RFB_HAVE_WINCRYPT
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
if (provider) {
|
if (provider) {
|
||||||
if (!CryptGenRandom(provider, length, (U8*)end))
|
if (!CryptGenRandom(provider, maxSize, (U8*)end))
|
||||||
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
|
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
|
||||||
end += length;
|
end += maxSize;
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (fp) {
|
if (fp) {
|
||||||
size_t n = fread((U8*)end, length, 1, fp);
|
size_t n = fread((U8*)end, 1, maxSize, fp);
|
||||||
if (n != 1)
|
if (n <= 0)
|
||||||
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
|
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
|
||||||
errno);
|
errno);
|
||||||
end += length;
|
end += n;
|
||||||
} else {
|
} else {
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
for (size_t i=0; i<length; i++)
|
for (size_t i=0; i<maxSize; i++)
|
||||||
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
|
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nAvail;
|
return true;
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define __RDR_RANDOMSTREAM_H__
|
#define __RDR_RANDOMSTREAM_H__
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -32,22 +32,17 @@
|
|||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class RandomStream : public InStream {
|
class RandomStream : public BufferedInStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RandomStream();
|
RandomStream();
|
||||||
virtual ~RandomStream();
|
virtual ~RandomStream();
|
||||||
|
|
||||||
size_t pos();
|
private:
|
||||||
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
protected:
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
U8* start;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
static unsigned int seed;
|
static unsigned int seed;
|
||||||
#ifdef RFB_HAVE_WINCRYPT
|
#ifdef RFB_HAVE_WINCRYPT
|
||||||
HCRYPTPROV provider;
|
HCRYPTPROV provider;
|
||||||
|
@ -30,21 +30,19 @@
|
|||||||
#ifdef HAVE_GNUTLS
|
#ifdef HAVE_GNUTLS
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
|
||||||
|
|
||||||
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
|
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
|
||||||
{
|
{
|
||||||
TLSInStream* self= (TLSInStream*) str;
|
TLSInStream* self= (TLSInStream*) str;
|
||||||
InStream *in = self->in;
|
InStream *in = self->in;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!in->check(1, 1, false)) {
|
if (!in->check(1, false)) {
|
||||||
gnutls_transport_set_errno(self->session, EAGAIN);
|
gnutls_transport_set_errno(self->session, EAGAIN);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size_t)(in->getend() - in->getptr()) < size)
|
if (in->avail() < size)
|
||||||
size = in->getend() - in->getptr();
|
size = in->avail();
|
||||||
|
|
||||||
in->readBytes(data, size);
|
in->readBytes(data, size);
|
||||||
|
|
||||||
@ -57,12 +55,10 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
|
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
|
||||||
: session(_session), in(_in), bufSize(DEFAULT_BUF_SIZE), offset(0)
|
: session(_session), in(_in)
|
||||||
{
|
{
|
||||||
gnutls_transport_ptr_t recv, send;
|
gnutls_transport_ptr_t recv, send;
|
||||||
|
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
|
|
||||||
gnutls_transport_set_pull_function(session, pull);
|
gnutls_transport_set_pull_function(session, pull);
|
||||||
gnutls_transport_get_ptr2(session, &recv, &send);
|
gnutls_transport_get_ptr2(session, &recv, &send);
|
||||||
gnutls_transport_set_ptr2(session, this, send);
|
gnutls_transport_set_ptr2(session, this, send);
|
||||||
@ -71,40 +67,16 @@ TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
|
|||||||
TLSInStream::~TLSInStream()
|
TLSInStream::~TLSInStream()
|
||||||
{
|
{
|
||||||
gnutls_transport_set_pull_function(session, NULL);
|
gnutls_transport_set_pull_function(session, NULL);
|
||||||
|
|
||||||
delete[] start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TLSInStream::pos()
|
bool TLSInStream::fillBuffer(size_t maxSize, bool wait)
|
||||||
{
|
{
|
||||||
return offset + ptr - start;
|
size_t n = readTLS((U8*) end, maxSize, wait);
|
||||||
}
|
if (!wait && n == 0)
|
||||||
|
return false;
|
||||||
|
end += n;
|
||||||
|
|
||||||
size_t TLSInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
return true;
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("TLSInStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
end -= ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
while ((size_t)(end - start) < itemSize) {
|
|
||||||
size_t n = readTLS((U8*) end, start + bufSize - end, wait);
|
|
||||||
if (!wait && n == 0)
|
|
||||||
return 0;
|
|
||||||
end += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait)
|
size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait)
|
||||||
@ -112,7 +84,7 @@ size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (gnutls_record_check_pending(session) == 0) {
|
if (gnutls_record_check_pending(session) == 0) {
|
||||||
n = in->check(1, 1, wait);
|
n = in->check(1, wait);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -27,27 +27,22 @@
|
|||||||
#ifdef HAVE_GNUTLS
|
#ifdef HAVE_GNUTLS
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class TLSInStream : public InStream {
|
class TLSInStream : public BufferedInStream {
|
||||||
public:
|
public:
|
||||||
TLSInStream(InStream* in, gnutls_session_t session);
|
TLSInStream(InStream* in, gnutls_session_t session);
|
||||||
virtual ~TLSInStream();
|
virtual ~TLSInStream();
|
||||||
|
|
||||||
size_t pos();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
size_t readTLS(U8* buf, size_t len, bool wait);
|
size_t readTLS(U8* buf, size_t len, bool wait);
|
||||||
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
|
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
|
||||||
|
|
||||||
gnutls_session_t session;
|
gnutls_session_t session;
|
||||||
InStream* in;
|
InStream* in;
|
||||||
size_t bufSize;
|
|
||||||
size_t offset;
|
|
||||||
U8* start;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,19 +93,12 @@ void TLSOutStream::flush()
|
|||||||
out->flush();
|
out->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TLSOutStream::overrun(size_t itemSize, size_t nItems)
|
void TLSOutStream::overrun(size_t needed)
|
||||||
{
|
{
|
||||||
if (itemSize > bufSize)
|
if (needed > bufSize)
|
||||||
throw Exception("TLSOutStream overrun: max itemSize exceeded");
|
throw Exception("TLSOutStream overrun: buffer size exceeded");
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TLSOutStream::writeTLS(const U8* data, size_t length)
|
size_t TLSOutStream::writeTLS(const U8* data, size_t length)
|
||||||
|
@ -39,7 +39,7 @@ namespace rdr {
|
|||||||
size_t length();
|
size_t length();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t overrun(size_t itemSize, size_t nItems);
|
virtual void overrun(size_t needed);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t writeTLS(const U8* data, size_t length);
|
size_t writeTLS(const U8* data, size_t length);
|
||||||
|
@ -24,41 +24,30 @@
|
|||||||
|
|
||||||
using namespace rdr;
|
using namespace rdr;
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
ZlibInStream::ZlibInStream()
|
||||||
|
: underlying(0), zs(NULL), bytesIn(0)
|
||||||
ZlibInStream::ZlibInStream(size_t bufSize_)
|
|
||||||
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
|
|
||||||
zs(NULL), bytesIn(0)
|
|
||||||
{
|
{
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZlibInStream::~ZlibInStream()
|
ZlibInStream::~ZlibInStream()
|
||||||
{
|
{
|
||||||
deinit();
|
deinit();
|
||||||
delete [] start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_)
|
void ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_)
|
||||||
{
|
{
|
||||||
underlying = is;
|
underlying = is;
|
||||||
bytesIn = bytesIn_;
|
bytesIn = bytesIn_;
|
||||||
ptr = end = start;
|
skip(avail());
|
||||||
}
|
|
||||||
|
|
||||||
size_t ZlibInStream::pos()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZlibInStream::flushUnderlying()
|
void ZlibInStream::flushUnderlying()
|
||||||
{
|
{
|
||||||
ptr = end = start;
|
|
||||||
|
|
||||||
while (bytesIn > 0) {
|
while (bytesIn > 0) {
|
||||||
decompress(true);
|
if (!check(1))
|
||||||
end = start; // throw away any data
|
throw Exception("ZlibInStream: failed to flush remaining stream data");
|
||||||
|
skip(avail());
|
||||||
}
|
}
|
||||||
|
|
||||||
setUnderlying(NULL, 0);
|
setUnderlying(NULL, 0);
|
||||||
@ -96,47 +85,18 @@ void ZlibInStream::deinit()
|
|||||||
zs = NULL;
|
zs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZlibInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
bool ZlibInStream::fillBuffer(size_t maxSize, bool wait)
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("ZlibInStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
end -= ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
while ((size_t)(end - ptr) < itemSize) {
|
|
||||||
if (!decompress(wait))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decompress() calls the decompressor once. Note that this won't necessarily
|
|
||||||
// generate any output data - it may just consume some input data. Returns
|
|
||||||
// false if wait is false and we would block on the underlying stream.
|
|
||||||
|
|
||||||
bool ZlibInStream::decompress(bool wait)
|
|
||||||
{
|
{
|
||||||
if (!underlying)
|
if (!underlying)
|
||||||
throw Exception("ZlibInStream overrun: no underlying stream");
|
throw Exception("ZlibInStream overrun: no underlying stream");
|
||||||
|
|
||||||
zs->next_out = (U8*)end;
|
zs->next_out = (U8*)end;
|
||||||
zs->avail_out = start + bufSize - end;
|
zs->avail_out = maxSize;
|
||||||
|
|
||||||
size_t n = underlying->check(1, 1, wait);
|
size_t n = underlying->check(1, wait);
|
||||||
if (n == 0) return false;
|
if (n == 0) return false;
|
||||||
zs->next_in = (U8*)underlying->getptr();
|
zs->next_in = (U8*)underlying->getptr();
|
||||||
zs->avail_in = underlying->getend() - underlying->getptr();
|
zs->avail_in = underlying->avail();
|
||||||
if (zs->avail_in > bytesIn)
|
if (zs->avail_in > bytesIn)
|
||||||
zs->avail_in = bytesIn;
|
zs->avail_in = bytesIn;
|
||||||
|
|
||||||
|
@ -24,38 +24,32 @@
|
|||||||
#ifndef __RDR_ZLIBINSTREAM_H__
|
#ifndef __RDR_ZLIBINSTREAM_H__
|
||||||
#define __RDR_ZLIBINSTREAM_H__
|
#define __RDR_ZLIBINSTREAM_H__
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/BufferedInStream.h>
|
||||||
|
|
||||||
struct z_stream_s;
|
struct z_stream_s;
|
||||||
|
|
||||||
namespace rdr {
|
namespace rdr {
|
||||||
|
|
||||||
class ZlibInStream : public InStream {
|
class ZlibInStream : public BufferedInStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ZlibInStream();
|
||||||
ZlibInStream(size_t bufSize=0);
|
|
||||||
virtual ~ZlibInStream();
|
virtual ~ZlibInStream();
|
||||||
|
|
||||||
void setUnderlying(InStream* is, size_t bytesIn);
|
void setUnderlying(InStream* is, size_t bytesIn);
|
||||||
void flushUnderlying();
|
void flushUnderlying();
|
||||||
size_t pos();
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void deinit();
|
void deinit();
|
||||||
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||||
bool decompress(bool wait);
|
|
||||||
|
|
||||||
|
private:
|
||||||
InStream* underlying;
|
InStream* underlying;
|
||||||
size_t bufSize;
|
|
||||||
size_t offset;
|
|
||||||
z_stream_s* zs;
|
z_stream_s* zs;
|
||||||
size_t bytesIn;
|
size_t bytesIn;
|
||||||
U8* start;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace rdr
|
} // end of namespace rdr
|
||||||
|
@ -30,9 +30,9 @@ using namespace rdr;
|
|||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||||
|
|
||||||
ZlibOutStream::ZlibOutStream(OutStream* os, size_t bufSize_, int compressLevel)
|
ZlibOutStream::ZlibOutStream(OutStream* os, int compressLevel)
|
||||||
: underlying(os), compressionLevel(compressLevel), newLevel(compressLevel),
|
: underlying(os), compressionLevel(compressLevel), newLevel(compressLevel),
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||||
{
|
{
|
||||||
zs = new z_stream;
|
zs = new z_stream;
|
||||||
zs->zalloc = Z_NULL;
|
zs->zalloc = Z_NULL;
|
||||||
@ -95,18 +95,18 @@ void ZlibOutStream::flush()
|
|||||||
ptr = start;
|
ptr = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems)
|
void ZlibOutStream::overrun(size_t needed)
|
||||||
{
|
{
|
||||||
#ifdef ZLIBOUT_DEBUG
|
#ifdef ZLIBOUT_DEBUG
|
||||||
fprintf(stderr,"zos overrun\n");
|
fprintf(stderr,"zos overrun\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (itemSize > bufSize)
|
if (needed > bufSize)
|
||||||
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
|
throw Exception("ZlibOutStream overrun: buffer size exceeded");
|
||||||
|
|
||||||
checkCompressionLevel();
|
checkCompressionLevel();
|
||||||
|
|
||||||
while ((size_t)(end - ptr) < itemSize) {
|
while (avail() < needed) {
|
||||||
zs->next_in = start;
|
zs->next_in = start;
|
||||||
zs->avail_in = ptr - start;
|
zs->avail_in = ptr - start;
|
||||||
|
|
||||||
@ -126,13 +126,6 @@ size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems)
|
|||||||
ptr -= zs->next_in - start;
|
ptr -= zs->next_in - start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nAvail;
|
|
||||||
nAvail = (end - ptr) / itemSize;
|
|
||||||
if (nAvail < nItems)
|
|
||||||
return nAvail;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZlibOutStream::deflate(int flush)
|
void ZlibOutStream::deflate(int flush)
|
||||||
@ -148,7 +141,7 @@ void ZlibOutStream::deflate(int flush)
|
|||||||
do {
|
do {
|
||||||
underlying->check(1);
|
underlying->check(1);
|
||||||
zs->next_out = underlying->getptr();
|
zs->next_out = underlying->getptr();
|
||||||
zs->avail_out = underlying->getend() - underlying->getptr();
|
zs->avail_out = underlying->avail();
|
||||||
|
|
||||||
#ifdef ZLIBOUT_DEBUG
|
#ifdef ZLIBOUT_DEBUG
|
||||||
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",
|
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",
|
||||||
|
@ -35,7 +35,7 @@ namespace rdr {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ZlibOutStream(OutStream* os=0, size_t bufSize=0, int compressionLevel=-1);
|
ZlibOutStream(OutStream* os=0, int compressionLevel=-1);
|
||||||
virtual ~ZlibOutStream();
|
virtual ~ZlibOutStream();
|
||||||
|
|
||||||
void setUnderlying(OutStream* os);
|
void setUnderlying(OutStream* os);
|
||||||
@ -45,7 +45,7 @@ namespace rdr {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
size_t overrun(size_t itemSize, size_t nItems);
|
virtual void overrun(size_t needed);
|
||||||
void deflate(int flush);
|
void deflate(int flush);
|
||||||
void checkCompressionLevel();
|
void checkCompressionLevel();
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/fenceTypes.h>
|
#include <rfb/fenceTypes.h>
|
||||||
#include <rfb/CMsgReader.h>
|
#include <rfb/CMsgReader.h>
|
||||||
#include <rfb/CMsgWriter.h>
|
#include <rfb/CMsgWriter.h>
|
||||||
@ -42,7 +43,8 @@ CConnection::CConnection()
|
|||||||
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
|
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
|
||||||
shared(false),
|
shared(false),
|
||||||
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
|
state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
|
||||||
framebuffer(NULL), decoder(this)
|
framebuffer(NULL), decoder(this),
|
||||||
|
serverClipboard(NULL), hasLocalClipboard(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +56,7 @@ CConnection::~CConnection()
|
|||||||
reader_ = 0;
|
reader_ = 0;
|
||||||
delete writer_;
|
delete writer_;
|
||||||
writer_ = 0;
|
writer_ = 0;
|
||||||
|
strFree(serverClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
||||||
@ -342,6 +345,79 @@ void CConnection::dataRect(const Rect& r, int encoding)
|
|||||||
decoder.decodeRect(r, encoding, framebuffer);
|
decoder.decodeRect(r, encoding, framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CConnection::serverCutText(const char* str)
|
||||||
|
{
|
||||||
|
hasLocalClipboard = false;
|
||||||
|
|
||||||
|
strFree(serverClipboard);
|
||||||
|
serverClipboard = NULL;
|
||||||
|
|
||||||
|
serverClipboard = latin1ToUTF8(str);
|
||||||
|
|
||||||
|
handleClipboardAnnounce(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardCaps(rdr::U32 flags,
|
||||||
|
const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
rdr::U32 sizes[] = { 0 };
|
||||||
|
|
||||||
|
CMsgHandler::handleClipboardCaps(flags, lengths);
|
||||||
|
|
||||||
|
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
|
||||||
|
rfb::clipboardRequest |
|
||||||
|
rfb::clipboardPeek |
|
||||||
|
rfb::clipboardNotify |
|
||||||
|
rfb::clipboardProvide,
|
||||||
|
sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!(flags & rfb::clipboardUTF8))
|
||||||
|
return;
|
||||||
|
if (!hasLocalClipboard)
|
||||||
|
return;
|
||||||
|
handleClipboardRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!hasLocalClipboard)
|
||||||
|
return;
|
||||||
|
if (cp.clipboardFlags() & rfb::clipboardNotify)
|
||||||
|
writer()->writeClipboardNotify(rfb::clipboardUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
strFree(serverClipboard);
|
||||||
|
serverClipboard = NULL;
|
||||||
|
|
||||||
|
if (flags & rfb::clipboardUTF8) {
|
||||||
|
hasLocalClipboard = false;
|
||||||
|
handleClipboardAnnounce(true);
|
||||||
|
} else {
|
||||||
|
handleClipboardAnnounce(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
if (!(flags & rfb::clipboardUTF8))
|
||||||
|
return;
|
||||||
|
|
||||||
|
strFree(serverClipboard);
|
||||||
|
serverClipboard = NULL;
|
||||||
|
|
||||||
|
serverClipboard = convertLF((const char*)data[0], lengths[0]);
|
||||||
|
|
||||||
|
// FIXME: Should probably verify that this data was actually requested
|
||||||
|
handleClipboardData(serverClipboard);
|
||||||
|
}
|
||||||
|
|
||||||
void CConnection::authSuccess()
|
void CConnection::authSuccess()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -364,3 +440,53 @@ void CConnection::fence(rdr::U32 flags, unsigned len, const char data[])
|
|||||||
|
|
||||||
writer()->writeFence(flags, len, data);
|
writer()->writeFence(flags, len, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardAnnounce(bool available)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::handleClipboardData(const char* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::requestClipboard()
|
||||||
|
{
|
||||||
|
if (serverClipboard != NULL) {
|
||||||
|
handleClipboardData(serverClipboard);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp.clipboardFlags() & rfb::clipboardRequest)
|
||||||
|
writer()->writeClipboardRequest(rfb::clipboardUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::announceClipboard(bool available)
|
||||||
|
{
|
||||||
|
hasLocalClipboard = available;
|
||||||
|
|
||||||
|
if (cp.clipboardFlags() & rfb::clipboardNotify)
|
||||||
|
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
|
||||||
|
else {
|
||||||
|
if (available)
|
||||||
|
handleClipboardRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConnection::sendClipboardData(const char* data)
|
||||||
|
{
|
||||||
|
if (cp.clipboardFlags() & rfb::clipboardProvide) {
|
||||||
|
CharArray filtered(convertCRLF(data));
|
||||||
|
size_t sizes[1] = { strlen(filtered.buf) + 1 };
|
||||||
|
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
|
||||||
|
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
|
||||||
|
} else {
|
||||||
|
CharArray latin1(utf8ToLatin1(data));
|
||||||
|
|
||||||
|
writer()->writeClientCutText(latin1.buf, strlen(latin1.buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,17 @@ namespace rfb {
|
|||||||
virtual void framebufferUpdateEnd();
|
virtual void framebufferUpdateEnd();
|
||||||
virtual void dataRect(const Rect& r, int encoding);
|
virtual void dataRect(const Rect& r, int encoding);
|
||||||
|
|
||||||
|
virtual void serverCutText(const char* str);
|
||||||
|
|
||||||
|
virtual void handleClipboardCaps(rdr::U32 flags,
|
||||||
|
const rdr::U32* lengths);
|
||||||
|
virtual void handleClipboardRequest(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardPeek(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardNotify(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
|
|
||||||
// Methods to be overridden in a derived class
|
// Methods to be overridden in a derived class
|
||||||
|
|
||||||
@ -121,9 +132,43 @@ namespace rfb {
|
|||||||
// derived class must call on to CConnection::serverInit().
|
// derived class must call on to CConnection::serverInit().
|
||||||
virtual void serverInit();
|
virtual void serverInit();
|
||||||
|
|
||||||
|
// handleClipboardRequest() is called whenever the server requests
|
||||||
|
// the client to send over its clipboard data. It will only be
|
||||||
|
// called after the client has first announced a clipboard change
|
||||||
|
// via announceClipboard().
|
||||||
|
virtual void handleClipboardRequest();
|
||||||
|
|
||||||
|
// handleClipboardAnnounce() is called to indicate a change in the
|
||||||
|
// clipboard on the server. Call requestClipboard() to access the
|
||||||
|
// actual data.
|
||||||
|
virtual void handleClipboardAnnounce(bool available);
|
||||||
|
|
||||||
|
// handleClipboardData() is called when the server has sent over
|
||||||
|
// the clipboard data as a result of a previous call to
|
||||||
|
// requestClipboard(). Note that this function might never be
|
||||||
|
// called if the clipboard data was no longer available when the
|
||||||
|
// server received the request.
|
||||||
|
virtual void handleClipboardData(const char* data);
|
||||||
|
|
||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
|
|
||||||
|
// requestClipboard() will result in a request to the server to
|
||||||
|
// transfer its clipboard data. A call to handleClipboardData()
|
||||||
|
// will be made once the data is available.
|
||||||
|
virtual void requestClipboard();
|
||||||
|
|
||||||
|
// announceClipboard() informs the server of changes to the
|
||||||
|
// clipboard on the client. The server may later request the
|
||||||
|
// clipboard data via handleClipboardRequest().
|
||||||
|
virtual void announceClipboard(bool available);
|
||||||
|
|
||||||
|
// sendClipboardData() transfers the clipboard data to the server
|
||||||
|
// and should be called whenever the server has requested the
|
||||||
|
// clipboard via handleClipboardRequest().
|
||||||
|
virtual void sendClipboardData(const char* data);
|
||||||
|
|
||||||
|
|
||||||
CMsgReader* reader() { return reader_; }
|
CMsgReader* reader() { return reader_; }
|
||||||
CMsgWriter* writer() { return writer_; }
|
CMsgWriter* writer() { return writer_; }
|
||||||
|
|
||||||
@ -190,6 +235,9 @@ namespace rfb {
|
|||||||
|
|
||||||
ModifiablePixelBuffer* framebuffer;
|
ModifiablePixelBuffer* framebuffer;
|
||||||
DecodeManager decoder;
|
DecodeManager decoder;
|
||||||
|
|
||||||
|
char* serverClipboard;
|
||||||
|
bool hasLocalClipboard;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,3 +92,26 @@ void CMsgHandler::setLEDState(unsigned int state)
|
|||||||
{
|
{
|
||||||
cp.setLEDState(state);
|
cp.setLEDState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
cp.setClipboardCaps(flags, lengths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::handleClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::handleClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::handleClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgHandler::handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -72,6 +72,15 @@ namespace rfb {
|
|||||||
|
|
||||||
virtual void setLEDState(unsigned int state);
|
virtual void setLEDState(unsigned int state);
|
||||||
|
|
||||||
|
virtual void handleClipboardCaps(rdr::U32 flags,
|
||||||
|
const rdr::U32* lengths);
|
||||||
|
virtual void handleClipboardRequest(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardPeek(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardNotify(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
ConnParams cp;
|
ConnParams cp;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <rdr/OutStream.h>
|
#include <rdr/OutStream.h>
|
||||||
|
#include <rdr/MemOutStream.h>
|
||||||
|
#include <rdr/ZlibOutStream.h>
|
||||||
|
|
||||||
#include <rfb/msgTypes.h>
|
#include <rfb/msgTypes.h>
|
||||||
#include <rfb/fenceTypes.h>
|
#include <rfb/fenceTypes.h>
|
||||||
#include <rfb/encodings.h>
|
#include <rfb/encodings.h>
|
||||||
#include <rfb/qemuTypes.h>
|
#include <rfb/qemuTypes.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
#include <rfb/PixelFormat.h>
|
#include <rfb/PixelFormat.h>
|
||||||
#include <rfb/Rect.h>
|
#include <rfb/Rect.h>
|
||||||
@ -57,7 +61,7 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
|
|||||||
void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
|
void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
|
||||||
{
|
{
|
||||||
startMsg(msgTypeSetEncodings);
|
startMsg(msgTypeSetEncodings);
|
||||||
os->skip(1);
|
os->pad(1);
|
||||||
os->writeU16(nEncodings);
|
os->writeU16(nEncodings);
|
||||||
for (int i = 0; i < nEncodings; i++)
|
for (int i = 0; i < nEncodings; i++)
|
||||||
os->writeU32(encodings[i]);
|
os->writeU32(encodings[i]);
|
||||||
@ -265,6 +269,104 @@ void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
|
|||||||
endMsg();
|
endMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClipboardCaps(rdr::U32 caps,
|
||||||
|
const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
size_t i, count;
|
||||||
|
|
||||||
|
if (!(cp->clipboardFlags() & clipboardCaps))
|
||||||
|
throw Exception("Server does not support clipboard \"caps\" action");
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (caps & (1 << i))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-(4 + 4 * count));
|
||||||
|
|
||||||
|
os->writeU32(caps | clipboardCaps);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (caps & (1 << i))
|
||||||
|
os->writeU32(lengths[count++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!(cp->clipboardFlags() & clipboardRequest))
|
||||||
|
throw Exception("Server does not support clipboard \"request\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardRequest);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!(cp->clipboardFlags() & clipboardPeek))
|
||||||
|
throw Exception("Server does not support clipboard \"peek\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardPeek);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!(cp->clipboardFlags() & clipboardNotify))
|
||||||
|
throw Exception("Server does not support clipboard \"notify\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardNotify);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMsgWriter::writeClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
rdr::MemOutStream mos;
|
||||||
|
rdr::ZlibOutStream zos;
|
||||||
|
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
if (!(cp->clipboardFlags() & clipboardProvide))
|
||||||
|
throw Exception("Server does not support clipboard \"provide\" action");
|
||||||
|
|
||||||
|
zos.setUnderlying(&mos);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (!(flags & (1 << i)))
|
||||||
|
continue;
|
||||||
|
zos.writeU32(lengths[count]);
|
||||||
|
zos.writeBytes(data[count], lengths[count]);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zos.flush();
|
||||||
|
|
||||||
|
startMsg(msgTypeClientCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-(4 + mos.length()));
|
||||||
|
os->writeU32(flags | clipboardProvide);
|
||||||
|
os->writeBytes(mos.data(), mos.length());
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
void CMsgWriter::startMsg(int type)
|
void CMsgWriter::startMsg(int type)
|
||||||
{
|
{
|
||||||
os->writeU8(type);
|
os->writeU8(type);
|
||||||
|
@ -56,6 +56,13 @@ namespace rfb {
|
|||||||
void writePointerEvent(const Point& pos, int buttonMask);
|
void writePointerEvent(const Point& pos, int buttonMask);
|
||||||
void writeClientCutText(const char* str, rdr::U32 len);
|
void writeClientCutText(const char* str, rdr::U32 len);
|
||||||
|
|
||||||
|
void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
|
||||||
|
void writeClipboardRequest(rdr::U32 flags);
|
||||||
|
void writeClipboardPeek(rdr::U32 flags);
|
||||||
|
void writeClipboardNotify(rdr::U32 flags);
|
||||||
|
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startMsg(int type);
|
void startMsg(int type);
|
||||||
void endMsg();
|
void endMsg();
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
#include <rfb/encodings.h>
|
#include <rfb/encodings.h>
|
||||||
#include <rfb/ledStates.h>
|
#include <rfb/ledStates.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/ConnParams.h>
|
#include <rfb/ConnParams.h>
|
||||||
#include <rfb/ServerCore.h>
|
#include <rfb/ServerCore.h>
|
||||||
#include <rfb/SMsgHandler.h>
|
#include <rfb/SMsgHandler.h>
|
||||||
@ -36,19 +37,25 @@ ConnParams::ConnParams()
|
|||||||
width(0), height(0), useCopyRect(false),
|
width(0), height(0), useCopyRect(false),
|
||||||
supportsLocalCursor(false), supportsLocalXCursor(false),
|
supportsLocalCursor(false), supportsLocalXCursor(false),
|
||||||
supportsLocalCursorWithAlpha(false),
|
supportsLocalCursorWithAlpha(false),
|
||||||
|
supportsCursorPosition(false),
|
||||||
supportsDesktopResize(false), supportsExtendedDesktopSize(false),
|
supportsDesktopResize(false), supportsExtendedDesktopSize(false),
|
||||||
supportsDesktopRename(false), supportsLastRect(false),
|
supportsDesktopRename(false), supportsLastRect(false),
|
||||||
supportsLEDState(false), supportsQEMUKeyEvent(false),
|
supportsLEDState(false), supportsQEMUKeyEvent(false),
|
||||||
supportsWEBP(false),
|
supportsWEBP(false),
|
||||||
supportsSetDesktopSize(false), supportsFence(false),
|
supportsSetDesktopSize(false), supportsFence(false),
|
||||||
supportsContinuousUpdates(false),
|
supportsContinuousUpdates(false), supportsExtendedClipboard(false),
|
||||||
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
|
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
|
||||||
subsampling(subsampleUndefined), name_(0), verStrPos(0),
|
subsampling(subsampleUndefined), name_(0), cursorPos_(0, 0), verStrPos(0),
|
||||||
ledState_(ledUnknown), shandler(NULL)
|
ledState_(ledUnknown), shandler(NULL)
|
||||||
{
|
{
|
||||||
memset(kasmPassed, 0, KASM_NUM_SETTINGS);
|
memset(kasmPassed, 0, KASM_NUM_SETTINGS);
|
||||||
setName("");
|
setName("");
|
||||||
cursor_ = new Cursor(0, 0, Point(), NULL);
|
cursor_ = new Cursor(0, 0, Point(), NULL);
|
||||||
|
|
||||||
|
clipFlags = clipboardUTF8 | clipboardRTF | clipboardHTML |
|
||||||
|
clipboardRequest | clipboardNotify | clipboardProvide;
|
||||||
|
memset(clipSizes, 0, sizeof(clipSizes));
|
||||||
|
clipSizes[0] = 20 * 1024 * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnParams::~ConnParams()
|
ConnParams::~ConnParams()
|
||||||
@ -101,6 +108,11 @@ void ConnParams::setCursor(const Cursor& other)
|
|||||||
cursor_ = new Cursor(other);
|
cursor_ = new Cursor(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnParams::setCursorPos(const Point& pos)
|
||||||
|
{
|
||||||
|
cursorPos_ = pos;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConnParams::supportsEncoding(rdr::S32 encoding) const
|
bool ConnParams::supportsEncoding(rdr::S32 encoding) const
|
||||||
{
|
{
|
||||||
return encodings_.count(encoding) != 0;
|
return encodings_.count(encoding) != 0;
|
||||||
@ -147,6 +159,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
|||||||
case pseudoEncodingExtendedDesktopSize:
|
case pseudoEncodingExtendedDesktopSize:
|
||||||
supportsExtendedDesktopSize = true;
|
supportsExtendedDesktopSize = true;
|
||||||
break;
|
break;
|
||||||
|
case pseudoEncodingVMwareCursorPosition:
|
||||||
|
supportsCursorPosition = true;
|
||||||
|
break;
|
||||||
case pseudoEncodingDesktopName:
|
case pseudoEncodingDesktopName:
|
||||||
supportsDesktopRename = true;
|
supportsDesktopRename = true;
|
||||||
break;
|
break;
|
||||||
@ -168,6 +183,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
|||||||
case pseudoEncodingContinuousUpdates:
|
case pseudoEncodingContinuousUpdates:
|
||||||
supportsContinuousUpdates = true;
|
supportsContinuousUpdates = true;
|
||||||
break;
|
break;
|
||||||
|
case pseudoEncodingExtendedClipboard:
|
||||||
|
supportsExtendedClipboard = true;
|
||||||
|
break;
|
||||||
case pseudoEncodingSubsamp1X:
|
case pseudoEncodingSubsamp1X:
|
||||||
subsampling = subsampleNone;
|
subsampling = subsampleNone;
|
||||||
break;
|
break;
|
||||||
@ -259,3 +277,17 @@ void ConnParams::setLEDState(unsigned int state)
|
|||||||
{
|
{
|
||||||
ledState_ = state;
|
ledState_ = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
int i, num;
|
||||||
|
|
||||||
|
clipFlags = flags;
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (!(flags & (1 << i)))
|
||||||
|
continue;
|
||||||
|
clipSizes[i] = lengths[num++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -84,6 +84,9 @@ namespace rfb {
|
|||||||
const Cursor& cursor() const { return *cursor_; }
|
const Cursor& cursor() const { return *cursor_; }
|
||||||
void setCursor(const Cursor& cursor);
|
void setCursor(const Cursor& cursor);
|
||||||
|
|
||||||
|
const Point& cursorPos() const { return cursorPos_; }
|
||||||
|
void setCursorPos(const Point& pos);
|
||||||
|
|
||||||
bool supportsEncoding(rdr::S32 encoding) const;
|
bool supportsEncoding(rdr::S32 encoding) const;
|
||||||
|
|
||||||
void setEncodings(int nEncodings, const rdr::S32* encodings);
|
void setEncodings(int nEncodings, const rdr::S32* encodings);
|
||||||
@ -91,11 +94,15 @@ namespace rfb {
|
|||||||
unsigned int ledState() { return ledState_; }
|
unsigned int ledState() { return ledState_; }
|
||||||
void setLEDState(unsigned int state);
|
void setLEDState(unsigned int state);
|
||||||
|
|
||||||
|
rdr::U32 clipboardFlags() const { return clipFlags; }
|
||||||
|
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
|
||||||
|
|
||||||
bool useCopyRect;
|
bool useCopyRect;
|
||||||
|
|
||||||
bool supportsLocalCursor;
|
bool supportsLocalCursor;
|
||||||
bool supportsLocalXCursor;
|
bool supportsLocalXCursor;
|
||||||
bool supportsLocalCursorWithAlpha;
|
bool supportsLocalCursorWithAlpha;
|
||||||
|
bool supportsCursorPosition;
|
||||||
bool supportsDesktopResize;
|
bool supportsDesktopResize;
|
||||||
bool supportsExtendedDesktopSize;
|
bool supportsExtendedDesktopSize;
|
||||||
bool supportsDesktopRename;
|
bool supportsDesktopRename;
|
||||||
@ -107,6 +114,7 @@ namespace rfb {
|
|||||||
bool supportsSetDesktopSize;
|
bool supportsSetDesktopSize;
|
||||||
bool supportsFence;
|
bool supportsFence;
|
||||||
bool supportsContinuousUpdates;
|
bool supportsContinuousUpdates;
|
||||||
|
bool supportsExtendedClipboard;
|
||||||
|
|
||||||
int compressLevel;
|
int compressLevel;
|
||||||
int qualityLevel;
|
int qualityLevel;
|
||||||
@ -136,11 +144,14 @@ namespace rfb {
|
|||||||
PixelFormat pf_;
|
PixelFormat pf_;
|
||||||
char* name_;
|
char* name_;
|
||||||
Cursor* cursor_;
|
Cursor* cursor_;
|
||||||
|
Point cursorPos_;
|
||||||
std::set<rdr::S32> encodings_;
|
std::set<rdr::S32> encodings_;
|
||||||
char verStr[13];
|
char verStr[13];
|
||||||
int verStrPos;
|
int verStrPos;
|
||||||
unsigned int ledState_;
|
unsigned int ledState_;
|
||||||
SMsgHandler *shandler;
|
SMsgHandler *shandler;
|
||||||
|
rdr::U32 clipFlags;
|
||||||
|
rdr::U32 clipSizes[16];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,7 +85,7 @@ JpegInitDestination(j_compress_ptr cinfo)
|
|||||||
|
|
||||||
jc->clear();
|
jc->clear();
|
||||||
dest->pub.next_output_byte = jc->getptr();
|
dest->pub.next_output_byte = jc->getptr();
|
||||||
dest->pub.free_in_buffer = jc->getend() - jc->getptr();
|
dest->pub.free_in_buffer = jc->avail();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
@ -95,9 +95,9 @@ JpegEmptyOutputBuffer(j_compress_ptr cinfo)
|
|||||||
JpegCompressor *jc = dest->instance;
|
JpegCompressor *jc = dest->instance;
|
||||||
|
|
||||||
jc->setptr(jc->getend());
|
jc->setptr(jc->getend());
|
||||||
jc->overrun(jc->getend() - jc->getstart(), 1);
|
jc->check(jc->length());
|
||||||
dest->pub.next_output_byte = jc->getptr();
|
dest->pub.next_output_byte = jc->getptr();
|
||||||
dest->pub.free_in_buffer = jc->getend() - jc->getptr();
|
dest->pub.free_in_buffer = jc->avail();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,6 @@ namespace rfb {
|
|||||||
|
|
||||||
void writeBytes(const void*, int);
|
void writeBytes(const void*, int);
|
||||||
|
|
||||||
inline rdr::U8* getstart() { return start; }
|
|
||||||
|
|
||||||
virtual inline size_t overrun(size_t itemSize, size_t nItems) {
|
|
||||||
return MemOutStream::overrun(itemSize, nItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct jpeg_compress_struct *cinfo;
|
struct jpeg_compress_struct *cinfo;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
#include <rfb/Security.h>
|
#include <rfb/Security.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/msgTypes.h>
|
#include <rfb/msgTypes.h>
|
||||||
#include <rfb/fenceTypes.h>
|
#include <rfb/fenceTypes.h>
|
||||||
#include <rfb/SMsgReader.h>
|
#include <rfb/SMsgReader.h>
|
||||||
@ -52,7 +53,8 @@ SConnection::SConnection()
|
|||||||
: readyForSetColourMapEntries(false),
|
: readyForSetColourMapEntries(false),
|
||||||
is(0), os(0), reader_(0), writer_(0),
|
is(0), os(0), reader_(0), writer_(0),
|
||||||
ssecurity(0), state_(RFBSTATE_UNINITIALISED),
|
ssecurity(0), state_(RFBSTATE_UNINITIALISED),
|
||||||
preferredEncoding(encodingRaw)
|
preferredEncoding(encodingRaw),
|
||||||
|
clientClipboard(NULL), hasLocalClipboard(false)
|
||||||
{
|
{
|
||||||
defaultMajorVersion = 3;
|
defaultMajorVersion = 3;
|
||||||
defaultMinorVersion = 8;
|
defaultMinorVersion = 8;
|
||||||
@ -69,6 +71,7 @@ SConnection::~SConnection()
|
|||||||
reader_ = 0;
|
reader_ = 0;
|
||||||
delete writer_;
|
delete writer_;
|
||||||
writer_ = 0;
|
writer_ = 0;
|
||||||
|
strFree(clientClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
|
||||||
@ -281,6 +284,73 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SMsgHandler::setEncodings(nEncodings, encodings);
|
SMsgHandler::setEncodings(nEncodings, encodings);
|
||||||
|
|
||||||
|
if (cp.supportsExtendedClipboard) {
|
||||||
|
rdr::U32 sizes[] = { 0 };
|
||||||
|
writer()->writeClipboardCaps(rfb::clipboardUTF8 |
|
||||||
|
rfb::clipboardRequest |
|
||||||
|
rfb::clipboardPeek |
|
||||||
|
rfb::clipboardNotify |
|
||||||
|
rfb::clipboardProvide,
|
||||||
|
sizes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::clientCutText(const char* str, int len)
|
||||||
|
{
|
||||||
|
hasLocalClipboard = false;
|
||||||
|
|
||||||
|
strFree(clientClipboard);
|
||||||
|
clientClipboard = NULL;
|
||||||
|
|
||||||
|
clientClipboard = latin1ToUTF8(str);
|
||||||
|
|
||||||
|
handleClipboardAnnounce(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!(flags & rfb::clipboardUTF8))
|
||||||
|
return;
|
||||||
|
if (!hasLocalClipboard)
|
||||||
|
return;
|
||||||
|
handleClipboardRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!hasLocalClipboard)
|
||||||
|
return;
|
||||||
|
if (cp.clipboardFlags() & rfb::clipboardNotify)
|
||||||
|
writer()->writeClipboardNotify(rfb::clipboardUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
strFree(clientClipboard);
|
||||||
|
clientClipboard = NULL;
|
||||||
|
|
||||||
|
if (flags & rfb::clipboardUTF8) {
|
||||||
|
handleClipboardAnnounce(true);
|
||||||
|
hasLocalClipboard = false;
|
||||||
|
} else {
|
||||||
|
handleClipboardAnnounce(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
if (!(flags & rfb::clipboardUTF8))
|
||||||
|
return;
|
||||||
|
|
||||||
|
strFree(clientClipboard);
|
||||||
|
clientClipboard = NULL;
|
||||||
|
|
||||||
|
clientClipboard = convertLF((const char*)data[0], lengths[0]);
|
||||||
|
|
||||||
|
handleClipboardData(clientClipboard, strlen(clientClipboard));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SConnection::supportsQEMUKeyEvent()
|
void SConnection::supportsQEMUKeyEvent()
|
||||||
@ -375,6 +445,58 @@ void SConnection::enableContinuousUpdates(bool enable,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardAnnounce(bool available)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::handleClipboardData(const char* data, int len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::requestClipboard()
|
||||||
|
{
|
||||||
|
if (clientClipboard != NULL) {
|
||||||
|
handleClipboardData(clientClipboard, strlen(clientClipboard));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp.supportsExtendedClipboard &&
|
||||||
|
(cp.clipboardFlags() & rfb::clipboardRequest))
|
||||||
|
writer()->writeClipboardRequest(rfb::clipboardUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::announceClipboard(bool available)
|
||||||
|
{
|
||||||
|
hasLocalClipboard = available;
|
||||||
|
|
||||||
|
if (cp.supportsExtendedClipboard &&
|
||||||
|
(cp.clipboardFlags() & rfb::clipboardNotify))
|
||||||
|
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
|
||||||
|
else {
|
||||||
|
if (available)
|
||||||
|
handleClipboardRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SConnection::sendClipboardData(const char* data, int len)
|
||||||
|
{
|
||||||
|
if (cp.supportsExtendedClipboard &&
|
||||||
|
(cp.clipboardFlags() & rfb::clipboardProvide)) {
|
||||||
|
CharArray filtered(convertCRLF(data));
|
||||||
|
size_t sizes[1] = { strlen(filtered.buf) + 1 };
|
||||||
|
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };
|
||||||
|
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
|
||||||
|
} else {
|
||||||
|
CharArray latin1(utf8ToLatin1(data));
|
||||||
|
|
||||||
|
writer()->writeServerCutText(latin1.buf, strlen(latin1.buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SConnection::writeFakeColourMap(void)
|
void SConnection::writeFakeColourMap(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -73,6 +73,15 @@ namespace rfb {
|
|||||||
|
|
||||||
virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
|
virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
|
||||||
|
|
||||||
|
virtual void clientCutText(const char* str, int len);
|
||||||
|
|
||||||
|
virtual void handleClipboardRequest(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardPeek(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardNotify(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
virtual void supportsQEMUKeyEvent();
|
virtual void supportsQEMUKeyEvent();
|
||||||
|
|
||||||
// Methods to be overridden in a derived class
|
// Methods to be overridden in a derived class
|
||||||
@ -118,6 +127,25 @@ namespace rfb {
|
|||||||
virtual void enableContinuousUpdates(bool enable,
|
virtual void enableContinuousUpdates(bool enable,
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
|
|
||||||
|
// handleClipboardRequest() is called whenever the client requests
|
||||||
|
// the server to send over its clipboard data. It will only be
|
||||||
|
// called after the server has first announced a clipboard change
|
||||||
|
// via announceClipboard().
|
||||||
|
virtual void handleClipboardRequest();
|
||||||
|
|
||||||
|
// handleClipboardAnnounce() is called to indicate a change in the
|
||||||
|
// clipboard on the client. Call requestClipboard() to access the
|
||||||
|
// actual data.
|
||||||
|
virtual void handleClipboardAnnounce(bool available);
|
||||||
|
|
||||||
|
// handleClipboardData() is called when the client has sent over
|
||||||
|
// the clipboard data as a result of a previous call to
|
||||||
|
// requestClipboard(). Note that this function might never be
|
||||||
|
// called if the clipboard data was no longer available when the
|
||||||
|
// client received the request.
|
||||||
|
virtual void handleClipboardData(const char* data, int len);
|
||||||
|
|
||||||
|
|
||||||
virtual void add_changed_all() {}
|
virtual void add_changed_all() {}
|
||||||
|
|
||||||
// setAccessRights() allows a security package to limit the access rights
|
// setAccessRights() allows a security package to limit the access rights
|
||||||
@ -138,6 +166,22 @@ namespace rfb {
|
|||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
|
|
||||||
|
// requestClipboard() will result in a request to the client to
|
||||||
|
// transfer its clipboard data. A call to handleClipboardData()
|
||||||
|
// will be made once the data is available.
|
||||||
|
virtual void requestClipboard();
|
||||||
|
|
||||||
|
// announceClipboard() informs the client of changes to the
|
||||||
|
// clipboard on the server. The client may later request the
|
||||||
|
// clipboard data via handleClipboardRequest().
|
||||||
|
virtual void announceClipboard(bool available);
|
||||||
|
|
||||||
|
// sendClipboardData() transfers the clipboard data to the client
|
||||||
|
// and should be called whenever the client has requested the
|
||||||
|
// clipboard via handleClipboardRequest().
|
||||||
|
virtual void sendClipboardData(const char* data, int len);
|
||||||
|
|
||||||
|
|
||||||
// authenticated() returns true if the client has authenticated
|
// authenticated() returns true if the client has authenticated
|
||||||
// successfully.
|
// successfully.
|
||||||
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
|
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
|
||||||
@ -203,6 +247,9 @@ namespace rfb {
|
|||||||
SSecurity* ssecurity;
|
SSecurity* ssecurity;
|
||||||
stateEnum state_;
|
stateEnum state_;
|
||||||
rdr::S32 preferredEncoding;
|
rdr::S32 preferredEncoding;
|
||||||
|
|
||||||
|
char* clientClipboard;
|
||||||
|
bool hasLocalClipboard;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,6 +77,25 @@ namespace rfb {
|
|||||||
// pointerEvent(), keyEvent() and clientCutText() are called in response to
|
// pointerEvent(), keyEvent() and clientCutText() are called in response to
|
||||||
// the relevant RFB protocol messages from clients.
|
// the relevant RFB protocol messages from clients.
|
||||||
// See InputHandler for method signatures.
|
// See InputHandler for method signatures.
|
||||||
|
|
||||||
|
// handleClipboardRequest() is called whenever a client requests
|
||||||
|
// the server to send over its clipboard data. It will only be
|
||||||
|
// called after the server has first announced a clipboard change
|
||||||
|
// via VNCServer::announceClipboard().
|
||||||
|
virtual void handleClipboardRequest() {}
|
||||||
|
|
||||||
|
// handleClipboardAnnounce() is called to indicate a change in the
|
||||||
|
// clipboard on a client. Call VNCServer::requestClipboard() to
|
||||||
|
// access the actual data.
|
||||||
|
virtual void handleClipboardAnnounce(bool __unused_attr available) {}
|
||||||
|
|
||||||
|
// handleClipboardData() is called when a client has sent over
|
||||||
|
// the clipboard data as a result of a previous call to
|
||||||
|
// VNCServer::requestClipboard(). Note that this function might
|
||||||
|
// never be called if the clipboard data was no longer available
|
||||||
|
// when the client received the request.
|
||||||
|
virtual void handleClipboardData(const char* __unused_attr data, int len __unused_attr) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~SDesktop() {}
|
virtual ~SDesktop() {}
|
||||||
};
|
};
|
||||||
|
@ -64,6 +64,29 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
|
|||||||
supportsQEMUKeyEvent();
|
supportsQEMUKeyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
cp.setClipboardCaps(flags, lengths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgHandler::handleClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgHandler::handleClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgHandler::handleClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgHandler::handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void SMsgHandler::supportsLocalCursor()
|
void SMsgHandler::supportsLocalCursor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,15 @@ namespace rfb {
|
|||||||
virtual void enableContinuousUpdates(bool enable,
|
virtual void enableContinuousUpdates(bool enable,
|
||||||
int x, int y, int w, int h) = 0;
|
int x, int y, int w, int h) = 0;
|
||||||
|
|
||||||
|
virtual void handleClipboardCaps(rdr::U32 flags,
|
||||||
|
const rdr::U32* lengths);
|
||||||
|
virtual void handleClipboardRequest(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardPeek(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardNotify(rdr::U32 flags);
|
||||||
|
virtual void handleClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
virtual void sendStats() = 0;
|
virtual void sendStats() = 0;
|
||||||
|
|
||||||
virtual bool canChangeKasmSettings() const = 0;
|
virtual bool canChangeKasmSettings() const = 0;
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <rdr/InStream.h>
|
#include <rdr/InStream.h>
|
||||||
|
#include <rdr/ZlibInStream.h>
|
||||||
|
|
||||||
#include <rfb/msgTypes.h>
|
#include <rfb/msgTypes.h>
|
||||||
#include <rfb/qemuTypes.h>
|
#include <rfb/qemuTypes.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
#include <rfb/util.h>
|
#include <rfb/util.h>
|
||||||
#include <rfb/SMsgHandler.h>
|
#include <rfb/SMsgHandler.h>
|
||||||
@ -224,11 +227,15 @@ void SMsgReader::readPointerEvent()
|
|||||||
void SMsgReader::readClientCutText()
|
void SMsgReader::readClientCutText()
|
||||||
{
|
{
|
||||||
is->skip(3);
|
is->skip(3);
|
||||||
int len = is->readU32();
|
rdr::U32 len = is->readU32();
|
||||||
if (len < 0) {
|
|
||||||
throw Exception("Cut text too long.");
|
if (len & 0x80000000) {
|
||||||
|
rdr::S32 slen = len;
|
||||||
|
slen = -slen;
|
||||||
|
readExtendedClipboard(slen);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (len > maxCutText) {
|
if (len > (size_t)maxCutText) {
|
||||||
is->skip(len);
|
is->skip(len);
|
||||||
vlog.error("Cut text too long (%d bytes) - ignoring", len);
|
vlog.error("Cut text too long (%d bytes) - ignoring", len);
|
||||||
return;
|
return;
|
||||||
@ -239,6 +246,100 @@ void SMsgReader::readClientCutText()
|
|||||||
handler->clientCutText(ca.buf, len);
|
handler->clientCutText(ca.buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMsgReader::readExtendedClipboard(rdr::S32 len)
|
||||||
|
{
|
||||||
|
rdr::U32 flags;
|
||||||
|
rdr::U32 action;
|
||||||
|
|
||||||
|
if (len < 4)
|
||||||
|
throw Exception("Invalid extended clipboard message");
|
||||||
|
if (len > maxCutText) {
|
||||||
|
vlog.error("Extended clipboard message too long (%d bytes) - ignoring", len);
|
||||||
|
is->skip(len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = is->readU32();
|
||||||
|
action = flags & clipboardActionMask;
|
||||||
|
|
||||||
|
if (action & clipboardCaps) {
|
||||||
|
int i;
|
||||||
|
size_t num;
|
||||||
|
rdr::U32 lengths[16];
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (flags & (1 << i))
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < (rdr::S32)(4 + 4*num))
|
||||||
|
throw Exception("Invalid extended clipboard message");
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (flags & (1 << i))
|
||||||
|
lengths[num++] = is->readU32();
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->handleClipboardCaps(flags, lengths);
|
||||||
|
} else if (action == clipboardProvide) {
|
||||||
|
rdr::ZlibInStream zis;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
size_t num;
|
||||||
|
size_t lengths[16];
|
||||||
|
rdr::U8* buffers[16];
|
||||||
|
|
||||||
|
zis.setUnderlying(is, len - 4);
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (!(flags & 1 << i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lengths[num] = zis.readU32();
|
||||||
|
if (lengths[num] > (size_t)maxCutText) {
|
||||||
|
vlog.error("Extended clipboard data too long (%d bytes) - ignoring",
|
||||||
|
(unsigned)lengths[num]);
|
||||||
|
zis.skip(lengths[num]);
|
||||||
|
flags &= ~(1 << i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffers[num] = new rdr::U8[lengths[num]];
|
||||||
|
zis.readBytes(buffers[num], lengths[num]);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zis.flushUnderlying();
|
||||||
|
zis.setUnderlying(NULL, 0);
|
||||||
|
|
||||||
|
handler->handleClipboardProvide(flags, lengths, buffers);
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (!(flags & 1 << i))
|
||||||
|
continue;
|
||||||
|
delete [] buffers[num++];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (action) {
|
||||||
|
case clipboardRequest:
|
||||||
|
handler->handleClipboardRequest(flags);
|
||||||
|
break;
|
||||||
|
case clipboardPeek:
|
||||||
|
handler->handleClipboardPeek(flags);
|
||||||
|
break;
|
||||||
|
case clipboardNotify:
|
||||||
|
handler->handleClipboardNotify(flags);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Exception("Invalid extended clipboard action");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SMsgReader::readRequestStats()
|
void SMsgReader::readRequestStats()
|
||||||
{
|
{
|
||||||
is->skip(3);
|
is->skip(3);
|
||||||
|
@ -55,6 +55,7 @@ namespace rfb {
|
|||||||
void readKeyEvent();
|
void readKeyEvent();
|
||||||
void readPointerEvent();
|
void readPointerEvent();
|
||||||
void readClientCutText();
|
void readClientCutText();
|
||||||
|
void readExtendedClipboard(rdr::S32 len);
|
||||||
void readRequestStats();
|
void readRequestStats();
|
||||||
|
|
||||||
void readQEMUMessage();
|
void readQEMUMessage();
|
||||||
|
@ -19,8 +19,12 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <rdr/OutStream.h>
|
#include <rdr/OutStream.h>
|
||||||
|
#include <rdr/MemOutStream.h>
|
||||||
|
#include <rdr/ZlibOutStream.h>
|
||||||
|
|
||||||
#include <rfb/msgTypes.h>
|
#include <rfb/msgTypes.h>
|
||||||
#include <rfb/fenceTypes.h>
|
#include <rfb/fenceTypes.h>
|
||||||
|
#include <rfb/clipboardTypes.h>
|
||||||
#include <rfb/Exception.h>
|
#include <rfb/Exception.h>
|
||||||
#include <rfb/ConnParams.h>
|
#include <rfb/ConnParams.h>
|
||||||
#include <rfb/UpdateTracker.h>
|
#include <rfb/UpdateTracker.h>
|
||||||
@ -39,6 +43,7 @@ SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
|
|||||||
needSetDesktopSize(false), needExtendedDesktopSize(false),
|
needSetDesktopSize(false), needExtendedDesktopSize(false),
|
||||||
needSetDesktopName(false), needSetCursor(false),
|
needSetDesktopName(false), needSetCursor(false),
|
||||||
needSetXCursor(false), needSetCursorWithAlpha(false),
|
needSetXCursor(false), needSetCursorWithAlpha(false),
|
||||||
|
needCursorPos(false),
|
||||||
needLEDState(false), needQEMUKeyEvent(false)
|
needLEDState(false), needQEMUKeyEvent(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -88,6 +93,112 @@ void SMsgWriter::writeServerCutText(const char* str, int len)
|
|||||||
endMsg();
|
endMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeClipboardCaps(rdr::U32 caps,
|
||||||
|
const rdr::U32* lengths)
|
||||||
|
{
|
||||||
|
size_t i, count;
|
||||||
|
|
||||||
|
if (!cp->supportsExtendedClipboard)
|
||||||
|
throw Exception("Client does not support extended clipboard");
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (caps & (1 << i))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
startMsg(msgTypeServerCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-(4 + 4 * count));
|
||||||
|
|
||||||
|
os->writeU32(caps | clipboardCaps);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (caps & (1 << i))
|
||||||
|
os->writeU32(lengths[count++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeClipboardRequest(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!cp->supportsExtendedClipboard)
|
||||||
|
throw Exception("Client does not support extended clipboard");
|
||||||
|
if (!(cp->clipboardFlags() & clipboardRequest))
|
||||||
|
throw Exception("Client does not support clipboard \"request\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeServerCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardRequest);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeClipboardPeek(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!cp->supportsExtendedClipboard)
|
||||||
|
throw Exception("Client does not support extended clipboard");
|
||||||
|
if (!(cp->clipboardFlags() & clipboardPeek))
|
||||||
|
throw Exception("Client does not support clipboard \"peek\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeServerCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardPeek);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeClipboardNotify(rdr::U32 flags)
|
||||||
|
{
|
||||||
|
if (!cp->supportsExtendedClipboard)
|
||||||
|
throw Exception("Client does not support extended clipboard");
|
||||||
|
if (!(cp->clipboardFlags() & clipboardNotify))
|
||||||
|
throw Exception("Client does not support clipboard \"notify\" action");
|
||||||
|
|
||||||
|
startMsg(msgTypeServerCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-4);
|
||||||
|
os->writeU32(flags | clipboardNotify);
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeClipboardProvide(rdr::U32 flags,
|
||||||
|
const size_t* lengths,
|
||||||
|
const rdr::U8* const* data)
|
||||||
|
{
|
||||||
|
rdr::MemOutStream mos;
|
||||||
|
rdr::ZlibOutStream zos;
|
||||||
|
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
if (!cp->supportsExtendedClipboard)
|
||||||
|
throw Exception("Client does not support extended clipboard");
|
||||||
|
if (!(cp->clipboardFlags() & clipboardProvide))
|
||||||
|
throw Exception("Client does not support clipboard \"provide\" action");
|
||||||
|
|
||||||
|
zos.setUnderlying(&mos);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0;i < 16;i++) {
|
||||||
|
if (!(flags & (1 << i)))
|
||||||
|
continue;
|
||||||
|
zos.writeU32(lengths[count]);
|
||||||
|
zos.writeBytes(data[count], lengths[count]);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zos.flush();
|
||||||
|
|
||||||
|
startMsg(msgTypeServerCutText);
|
||||||
|
os->pad(3);
|
||||||
|
os->writeS32(-(4 + mos.length()));
|
||||||
|
os->writeU32(flags | clipboardProvide);
|
||||||
|
os->writeBytes(mos.data(), mos.length());
|
||||||
|
endMsg();
|
||||||
|
}
|
||||||
|
|
||||||
void SMsgWriter::writeStats(const char* str, int len)
|
void SMsgWriter::writeStats(const char* str, int len)
|
||||||
{
|
{
|
||||||
startMsg(msgTypeStats);
|
startMsg(msgTypeStats);
|
||||||
@ -204,6 +315,14 @@ bool SMsgWriter::writeSetCursorWithAlpha()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeCursorPos()
|
||||||
|
{
|
||||||
|
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
|
||||||
|
throw Exception("Client does not support cursor position");
|
||||||
|
|
||||||
|
needCursorPos = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SMsgWriter::writeLEDState()
|
bool SMsgWriter::writeLEDState()
|
||||||
{
|
{
|
||||||
if (!cp->supportsLEDState)
|
if (!cp->supportsLEDState)
|
||||||
@ -232,6 +351,8 @@ bool SMsgWriter::needFakeUpdate()
|
|||||||
return true;
|
return true;
|
||||||
if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
|
if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
|
||||||
return true;
|
return true;
|
||||||
|
if (needCursorPos)
|
||||||
|
return true;
|
||||||
if (needLEDState)
|
if (needLEDState)
|
||||||
return true;
|
return true;
|
||||||
if (needQEMUKeyEvent)
|
if (needQEMUKeyEvent)
|
||||||
@ -284,6 +405,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
|
|||||||
nRects++;
|
nRects++;
|
||||||
if (needSetCursorWithAlpha)
|
if (needSetCursorWithAlpha)
|
||||||
nRects++;
|
nRects++;
|
||||||
|
if (needCursorPos)
|
||||||
|
nRects++;
|
||||||
if (needLEDState)
|
if (needLEDState)
|
||||||
nRects++;
|
nRects++;
|
||||||
if (needQEMUKeyEvent)
|
if (needQEMUKeyEvent)
|
||||||
@ -399,6 +522,18 @@ void SMsgWriter::writePseudoRects()
|
|||||||
needSetCursorWithAlpha = false;
|
needSetCursorWithAlpha = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needCursorPos) {
|
||||||
|
const Point& cursorPos = cp->cursorPos();
|
||||||
|
|
||||||
|
if (cp->supportsEncoding(pseudoEncodingVMwareCursorPosition)) {
|
||||||
|
writeSetVMwareCursorPositionRect(cursorPos.x, cursorPos.y);
|
||||||
|
} else {
|
||||||
|
throw Exception("Client does not support cursor position");
|
||||||
|
}
|
||||||
|
|
||||||
|
needCursorPos = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (needSetDesktopName) {
|
if (needSetDesktopName) {
|
||||||
writeSetDesktopNameRect(cp->name());
|
writeSetDesktopNameRect(cp->name());
|
||||||
needSetDesktopName = false;
|
needSetDesktopName = false;
|
||||||
@ -577,6 +712,20 @@ void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY)
|
||||||
|
{
|
||||||
|
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
|
||||||
|
throw Exception("Client does not support cursor position");
|
||||||
|
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
|
||||||
|
throw Exception("SMsgWriter::writeSetVMwareCursorRect: nRects out of sync");
|
||||||
|
|
||||||
|
os->writeS16(hotspotX);
|
||||||
|
os->writeS16(hotspotY);
|
||||||
|
os->writeU16(0);
|
||||||
|
os->writeU16(0);
|
||||||
|
os->writeU32(pseudoEncodingVMwareCursorPosition);
|
||||||
|
}
|
||||||
|
|
||||||
void SMsgWriter::writeLEDStateRect(rdr::U8 state)
|
void SMsgWriter::writeLEDStateRect(rdr::U8 state)
|
||||||
{
|
{
|
||||||
if (!cp->supportsLEDState)
|
if (!cp->supportsLEDState)
|
||||||
|
@ -55,6 +55,14 @@ namespace rfb {
|
|||||||
// writeBell() and writeServerCutText() do the obvious thing.
|
// writeBell() and writeServerCutText() do the obvious thing.
|
||||||
void writeBell();
|
void writeBell();
|
||||||
void writeServerCutText(const char* str, int len);
|
void writeServerCutText(const char* str, int len);
|
||||||
|
|
||||||
|
void writeClipboardCaps(rdr::U32 caps, const rdr::U32* lengths);
|
||||||
|
void writeClipboardRequest(rdr::U32 flags);
|
||||||
|
void writeClipboardPeek(rdr::U32 flags);
|
||||||
|
void writeClipboardNotify(rdr::U32 flags);
|
||||||
|
void writeClipboardProvide(rdr::U32 flags, const size_t* lengths,
|
||||||
|
const rdr::U8* const* data);
|
||||||
|
|
||||||
void writeStats(const char* str, int len);
|
void writeStats(const char* str, int len);
|
||||||
|
|
||||||
// writeFence() sends a new fence request or response to the client.
|
// writeFence() sends a new fence request or response to the client.
|
||||||
@ -83,6 +91,9 @@ namespace rfb {
|
|||||||
bool writeSetXCursor();
|
bool writeSetXCursor();
|
||||||
bool writeSetCursorWithAlpha();
|
bool writeSetCursorWithAlpha();
|
||||||
|
|
||||||
|
// Notifies the client that the cursor pointer was moved by the server.
|
||||||
|
void writeCursorPos();
|
||||||
|
|
||||||
// Same for LED state message
|
// Same for LED state message
|
||||||
bool writeLEDState();
|
bool writeLEDState();
|
||||||
|
|
||||||
@ -138,6 +149,7 @@ namespace rfb {
|
|||||||
void writeSetCursorWithAlphaRect(int width, int height,
|
void writeSetCursorWithAlphaRect(int width, int height,
|
||||||
int hotspotX, int hotspotY,
|
int hotspotX, int hotspotY,
|
||||||
const rdr::U8* data);
|
const rdr::U8* data);
|
||||||
|
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);
|
||||||
void writeLEDStateRect(rdr::U8 state);
|
void writeLEDStateRect(rdr::U8 state);
|
||||||
void writeQEMUKeyEventRect();
|
void writeQEMUKeyEventRect();
|
||||||
|
|
||||||
@ -153,6 +165,7 @@ namespace rfb {
|
|||||||
bool needSetCursor;
|
bool needSetCursor;
|
||||||
bool needSetXCursor;
|
bool needSetXCursor;
|
||||||
bool needSetCursorWithAlpha;
|
bool needSetCursorWithAlpha;
|
||||||
|
bool needCursorPos;
|
||||||
bool needLEDState;
|
bool needLEDState;
|
||||||
bool needQEMUKeyEvent;
|
bool needQEMUKeyEvent;
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ namespace rfb {
|
|||||||
dispatch elapsed Timer callbacks and to determine how long to wait in select() for
|
dispatch elapsed Timer callbacks and to determine how long to wait in select() for
|
||||||
the next timeout to occur.
|
the next timeout to occur.
|
||||||
|
|
||||||
|
For classes that can be derived it's best to use MethodTimer which can call a specific
|
||||||
|
method on the class, thus avoiding conflicts when subclassing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Timer {
|
struct Timer {
|
||||||
@ -101,6 +103,19 @@ namespace rfb {
|
|||||||
static std::list<Timer*> pending;
|
static std::list<Timer*> pending;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T> class MethodTimer
|
||||||
|
: public Timer, public Timer::Callback {
|
||||||
|
public:
|
||||||
|
MethodTimer(T* obj_, bool (T::*cb_)(Timer*))
|
||||||
|
: Timer(this), obj(obj_), cb(cb_) {}
|
||||||
|
|
||||||
|
virtual bool handleTimeout(Timer* t) { return (obj->*cb)(t); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* obj;
|
||||||
|
bool (T::*cb)(Timer*);
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -155,6 +155,17 @@ void VNCSConnectionST::close(const char* reason)
|
|||||||
server->lastDisconnectTime = time(0);
|
server->lastDisconnectTime = time(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sock->outStream().bufferUsage() > 0) {
|
||||||
|
sock->cork(false);
|
||||||
|
sock->outStream().flush();
|
||||||
|
if (sock->outStream().bufferUsage() > 0)
|
||||||
|
vlog.error("Failed to flush remaining socket data on close");
|
||||||
|
}
|
||||||
|
} catch (rdr::Exception& e) {
|
||||||
|
vlog.error("Failed to flush remaining socket data on close: %s", e.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Just shutdown the socket and mark our state as closing. Eventually the
|
// Just shutdown the socket and mark our state as closing. Eventually the
|
||||||
// calling code will call VNCServerST's removeSocket() method causing us to
|
// calling code will call VNCServerST's removeSocket() method causing us to
|
||||||
// be deleted.
|
// be deleted.
|
||||||
@ -392,7 +403,31 @@ static void keylog(unsigned keysym, const char *client) {
|
|||||||
flushKeylog(client);
|
flushKeylog(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
|
void VNCSConnectionST::requestClipboardOrClose()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!(accessRights & AccessCutText)) return;
|
||||||
|
if (!rfb::Server::acceptCutText) return;
|
||||||
|
if (state() != RFBSTATE_NORMAL) return;
|
||||||
|
requestClipboard();
|
||||||
|
} catch(rdr::Exception& e) {
|
||||||
|
close(e.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCSConnectionST::announceClipboardOrClose(bool available)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!(accessRights & AccessCutText)) return;
|
||||||
|
if (!rfb::Server::sendCutText) return;
|
||||||
|
if (state() != RFBSTATE_NORMAL) return;
|
||||||
|
announceClipboard(available);
|
||||||
|
} catch(rdr::Exception& e) {
|
||||||
|
close(e.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCSConnectionST::sendClipboardDataOrClose(const char* data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (!(accessRights & AccessCutText)) return;
|
if (!(accessRights & AccessCutText)) return;
|
||||||
@ -402,19 +437,19 @@ void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
|
|||||||
sock->getPeerAddress());
|
sock->getPeerAddress());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int len = strlen(data);
|
||||||
const int origlen = len;
|
const int origlen = len;
|
||||||
if (rfb::Server::DLP_ClipSendMax && len > rfb::Server::DLP_ClipSendMax)
|
if (rfb::Server::DLP_ClipSendMax && len > rfb::Server::DLP_ClipSendMax)
|
||||||
len = rfb::Server::DLP_ClipSendMax;
|
len = rfb::Server::DLP_ClipSendMax;
|
||||||
cliplog(str, len, origlen, "sent", sock->getPeerAddress());
|
cliplog(data, len, origlen, "sent", sock->getPeerAddress());
|
||||||
if (state() == RFBSTATE_NORMAL)
|
if (state() != RFBSTATE_NORMAL) return;
|
||||||
writer()->writeServerCutText(str, len);
|
sendClipboardData(data, len);
|
||||||
gettimeofday(&lastClipboardOp, NULL);
|
gettimeofday(&lastClipboardOp, NULL);
|
||||||
} catch(rdr::Exception& e) {
|
} catch(rdr::Exception& e) {
|
||||||
close(e.str());
|
close(e.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VNCSConnectionST::setDesktopNameOrClose(const char *name)
|
void VNCSConnectionST::setDesktopNameOrClose(const char *name)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -506,6 +541,15 @@ void VNCSConnectionST::renderedCursorChange()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cursorPositionChange() is called whenever the cursor has changed position by
|
||||||
|
// the server. If the client supports being informed about these changes then
|
||||||
|
// it will arrange for the new cursor position to be sent to the client.
|
||||||
|
|
||||||
|
void VNCSConnectionST::cursorPositionChange()
|
||||||
|
{
|
||||||
|
setCursorPos();
|
||||||
|
}
|
||||||
|
|
||||||
// needRenderedCursor() returns true if this client needs the server-side
|
// needRenderedCursor() returns true if this client needs the server-side
|
||||||
// rendered cursor. This may be because it does not support local cursor or
|
// rendered cursor. This may be because it does not support local cursor or
|
||||||
// because the current cursor position has not been set by this client.
|
// because the current cursor position has not been set by this client.
|
||||||
@ -826,24 +870,6 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
|
|||||||
server->desktop->keyEvent(keysym, keycode, down);
|
server->desktop->keyEvent(keysym, keycode, down);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNCSConnectionST::clientCutText(const char* str, int len)
|
|
||||||
{
|
|
||||||
if (!(accessRights & AccessCutText)) return;
|
|
||||||
if (!rfb::Server::acceptCutText) return;
|
|
||||||
if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
|
|
||||||
vlog.info("DLP: client %s: refused to receive clipboard, too soon",
|
|
||||||
sock->getPeerAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int origlen = len;
|
|
||||||
if (rfb::Server::DLP_ClipAcceptMax && len > rfb::Server::DLP_ClipAcceptMax)
|
|
||||||
len = rfb::Server::DLP_ClipAcceptMax;
|
|
||||||
cliplog(str, len, origlen, "received", sock->getPeerAddress());
|
|
||||||
|
|
||||||
gettimeofday(&lastClipboardOp, NULL);
|
|
||||||
server->desktop->clientCutText(str, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
|
void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
|
||||||
{
|
{
|
||||||
Rect safeRect;
|
Rect safeRect;
|
||||||
@ -863,7 +889,7 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
|
|||||||
|
|
||||||
// Just update the requested region.
|
// Just update the requested region.
|
||||||
// Framebuffer update will be sent a bit later, see processMessages().
|
// Framebuffer update will be sent a bit later, see processMessages().
|
||||||
Region reqRgn(r);
|
Region reqRgn(safeRect);
|
||||||
if (!incremental || !continuousUpdates)
|
if (!incremental || !continuousUpdates)
|
||||||
requested.assign_union(reqRgn);
|
requested.assign_union(reqRgn);
|
||||||
|
|
||||||
@ -977,6 +1003,38 @@ void VNCSConnectionST::enableContinuousUpdates(bool enable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VNCSConnectionST::handleClipboardRequest()
|
||||||
|
{
|
||||||
|
if (!(accessRights & AccessCutText)) return;
|
||||||
|
server->handleClipboardRequest(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCSConnectionST::handleClipboardAnnounce(bool available)
|
||||||
|
{
|
||||||
|
if (!(accessRights & AccessCutText)) return;
|
||||||
|
if (!rfb::Server::acceptCutText) return;
|
||||||
|
server->handleClipboardAnnounce(this, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCSConnectionST::handleClipboardData(const char* data, int len)
|
||||||
|
{
|
||||||
|
if (!(accessRights & AccessCutText)) return;
|
||||||
|
if (!rfb::Server::acceptCutText) return;
|
||||||
|
if (msSince(&lastClipboardOp) < (unsigned) rfb::Server::DLP_ClipDelay) {
|
||||||
|
vlog.info("DLP: client %s: refused to receive clipboard, too soon",
|
||||||
|
sock->getPeerAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int origlen = len;
|
||||||
|
if (rfb::Server::DLP_ClipAcceptMax && len > rfb::Server::DLP_ClipAcceptMax)
|
||||||
|
len = rfb::Server::DLP_ClipAcceptMax;
|
||||||
|
cliplog(data, len, origlen, "received", sock->getPeerAddress());
|
||||||
|
|
||||||
|
gettimeofday(&lastClipboardOp, NULL);
|
||||||
|
server->handleClipboardData(this, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// supportsLocalCursor() is called whenever the status of
|
// supportsLocalCursor() is called whenever the status of
|
||||||
// cp.supportsLocalCursor has changed. If the client does now support local
|
// cp.supportsLocalCursor has changed. If the client does now support local
|
||||||
// cursor, we make sure that the old server-side rendered cursor is cleaned up
|
// cursor, we make sure that the old server-side rendered cursor is cleaned up
|
||||||
@ -1471,6 +1529,21 @@ void VNCSConnectionST::setCursor()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setCursorPos() is called whenever the cursor has changed position by the
|
||||||
|
// server. If the client supports being informed about these changes then it
|
||||||
|
// will arrange for the new cursor position to be sent to the client.
|
||||||
|
|
||||||
|
void VNCSConnectionST::setCursorPos()
|
||||||
|
{
|
||||||
|
if (state() != RFBSTATE_NORMAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cp.supportsCursorPosition) {
|
||||||
|
cp.setCursorPos(server->cursorPos);
|
||||||
|
writer()->writeCursorPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VNCSConnectionST::setDesktopName(const char *name)
|
void VNCSConnectionST::setDesktopName(const char *name)
|
||||||
{
|
{
|
||||||
cp.setName(name);
|
cp.setName(name);
|
||||||
|
@ -75,9 +75,11 @@ namespace rfb {
|
|||||||
void screenLayoutChangeOrClose(rdr::U16 reason);
|
void screenLayoutChangeOrClose(rdr::U16 reason);
|
||||||
void setCursorOrClose();
|
void setCursorOrClose();
|
||||||
void bellOrClose();
|
void bellOrClose();
|
||||||
void serverCutTextOrClose(const char *str, int len);
|
|
||||||
void setDesktopNameOrClose(const char *name);
|
void setDesktopNameOrClose(const char *name);
|
||||||
void setLEDStateOrClose(unsigned int state);
|
void setLEDStateOrClose(unsigned int state);
|
||||||
|
void requestClipboardOrClose();
|
||||||
|
void announceClipboardOrClose(bool available);
|
||||||
|
void sendClipboardDataOrClose(const char* data);
|
||||||
|
|
||||||
// checkIdleTimeout() returns the number of milliseconds left until the
|
// checkIdleTimeout() returns the number of milliseconds left until the
|
||||||
// idle timeout expires. If it has expired, the connection is closed and
|
// idle timeout expires. If it has expired, the connection is closed and
|
||||||
@ -97,6 +99,11 @@ namespace rfb {
|
|||||||
// cursor.
|
// cursor.
|
||||||
void renderedCursorChange();
|
void renderedCursorChange();
|
||||||
|
|
||||||
|
// cursorPositionChange() is called whenever the cursor has changed position by
|
||||||
|
// the server. If the client supports being informed about these changes then
|
||||||
|
// it will arrange for the new cursor position to be sent to the client.
|
||||||
|
void cursorPositionChange();
|
||||||
|
|
||||||
// needRenderedCursor() returns true if this client needs the server-side
|
// needRenderedCursor() returns true if this client needs the server-side
|
||||||
// rendered cursor. This may be because it does not support local cursor
|
// rendered cursor. This may be because it does not support local cursor
|
||||||
// or because the current cursor position has not been set by this client.
|
// or because the current cursor position has not been set by this client.
|
||||||
@ -170,13 +177,15 @@ namespace rfb {
|
|||||||
virtual void setPixelFormat(const PixelFormat& pf);
|
virtual void setPixelFormat(const PixelFormat& pf);
|
||||||
virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease);
|
virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease);
|
||||||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
|
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
|
||||||
virtual void clientCutText(const char* str, int len);
|
|
||||||
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
|
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
|
||||||
virtual void setDesktopSize(int fb_width, int fb_height,
|
virtual void setDesktopSize(int fb_width, int fb_height,
|
||||||
const ScreenSet& layout);
|
const ScreenSet& layout);
|
||||||
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
|
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
|
||||||
virtual void enableContinuousUpdates(bool enable,
|
virtual void enableContinuousUpdates(bool enable,
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
|
virtual void handleClipboardRequest();
|
||||||
|
virtual void handleClipboardAnnounce(bool available);
|
||||||
|
virtual void handleClipboardData(const char* data, int len);
|
||||||
virtual void supportsLocalCursor();
|
virtual void supportsLocalCursor();
|
||||||
virtual void supportsFence();
|
virtual void supportsFence();
|
||||||
virtual void supportsContinuousUpdates();
|
virtual void supportsContinuousUpdates();
|
||||||
@ -223,6 +232,7 @@ namespace rfb {
|
|||||||
|
|
||||||
void screenLayoutChange(rdr::U16 reason);
|
void screenLayoutChange(rdr::U16 reason);
|
||||||
void setCursor();
|
void setCursor();
|
||||||
|
void setCursorPos();
|
||||||
void setDesktopName(const char *name);
|
void setDesktopName(const char *name);
|
||||||
void setLEDState(unsigned int state);
|
void setLEDState(unsigned int state);
|
||||||
void setSocketTimeouts();
|
void setSocketTimeouts();
|
||||||
|
@ -52,9 +52,21 @@ namespace rfb {
|
|||||||
// getPixelBuffer() returns a pointer to the PixelBuffer object.
|
// getPixelBuffer() returns a pointer to the PixelBuffer object.
|
||||||
virtual PixelBuffer* getPixelBuffer() const = 0;
|
virtual PixelBuffer* getPixelBuffer() const = 0;
|
||||||
|
|
||||||
// serverCutText() tells the server that the cut text has changed. This
|
// requestClipboard() will result in a request to a client to
|
||||||
// will normally be sent to all clients.
|
// transfer its clipboard data. A call to
|
||||||
virtual void serverCutText(const char* str, int len) = 0;
|
// SDesktop::handleClipboardData() will be made once the data is
|
||||||
|
// available.
|
||||||
|
virtual void requestClipboard() = 0;
|
||||||
|
|
||||||
|
// announceClipboard() informs all clients of changes to the
|
||||||
|
// clipboard on the server. A client may later request the
|
||||||
|
// clipboard data via SDesktop::handleClipboardRequest().
|
||||||
|
virtual void announceClipboard(bool available) = 0;
|
||||||
|
|
||||||
|
// sendClipboardData() transfers the clipboard data to a client
|
||||||
|
// and should be called whenever a client has requested the
|
||||||
|
// clipboard via SDesktop::handleClipboardRequest().
|
||||||
|
virtual void sendClipboardData(const char* data) = 0;
|
||||||
|
|
||||||
// bell() tells the server that it should make all clients make a bell sound.
|
// bell() tells the server that it should make all clients make a bell sound.
|
||||||
virtual void bell() = 0;
|
virtual void bell() = 0;
|
||||||
@ -69,8 +81,10 @@ namespace rfb {
|
|||||||
virtual void setCursor(int width, int height, const Point& hotspot,
|
virtual void setCursor(int width, int height, const Point& hotspot,
|
||||||
const rdr::U8* cursorData) = 0;
|
const rdr::U8* cursorData) = 0;
|
||||||
|
|
||||||
// setCursorPos() tells the server the current position of the cursor.
|
// setCursorPos() tells the server the current position of the cursor, and
|
||||||
virtual void setCursorPos(const Point& p) = 0;
|
// whether the server initiated that change (e.g. through another X11
|
||||||
|
// client calling XWarpPointer()).
|
||||||
|
virtual void setCursorPos(const Point& p, bool warped) = 0;
|
||||||
|
|
||||||
// setName() tells the server what desktop title to supply to clients
|
// setName() tells the server what desktop title to supply to clients
|
||||||
virtual void setName(const char* name) = 0;
|
virtual void setName(const char* name) = 0;
|
||||||
|
@ -123,8 +123,8 @@ static void parseRegionPart(const bool percents, rdr::U16 &pcdest, int &dest,
|
|||||||
VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
|
VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
|
||||||
: blHosts(&blacklist), desktop(desktop_), desktopStarted(false),
|
: blHosts(&blacklist), desktop(desktop_), desktopStarted(false),
|
||||||
blockCounter(0), pb(0), blackedpb(0), ledState(ledUnknown),
|
blockCounter(0), pb(0), blackedpb(0), ledState(ledUnknown),
|
||||||
name(strDup(name_)), pointerClient(0), comparer(0),
|
name(strDup(name_)), pointerClient(0), clipboardClient(0),
|
||||||
cursor(new Cursor(0, 0, Point(), NULL)),
|
comparer(0), cursor(new Cursor(0, 0, Point(), NULL)),
|
||||||
renderedCursorInvalid(false),
|
renderedCursorInvalid(false),
|
||||||
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
|
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
|
||||||
lastConnectionTime(0), disableclients(false),
|
lastConnectionTime(0), disableclients(false),
|
||||||
@ -502,6 +502,45 @@ void VNCServerST::setScreenLayout(const ScreenSet& layout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VNCServerST::requestClipboard()
|
||||||
|
{
|
||||||
|
if (clipboardClient == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clipboardClient->requestClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCServerST::announceClipboard(bool available)
|
||||||
|
{
|
||||||
|
std::list<VNCSConnectionST*>::iterator ci, ci_next;
|
||||||
|
|
||||||
|
if (available)
|
||||||
|
clipboardClient = NULL;
|
||||||
|
|
||||||
|
clipboardRequestors.clear();
|
||||||
|
|
||||||
|
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
|
||||||
|
ci_next = ci; ci_next++;
|
||||||
|
(*ci)->announceClipboard(available);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCServerST::sendClipboardData(const char* data)
|
||||||
|
{
|
||||||
|
std::list<VNCSConnectionST*>::iterator ci, ci_next;
|
||||||
|
|
||||||
|
if (strchr(data, '\r') != NULL)
|
||||||
|
throw Exception("Invalid carriage return in clipboard data");
|
||||||
|
|
||||||
|
for (ci = clipboardRequestors.begin();
|
||||||
|
ci != clipboardRequestors.end(); ci = ci_next) {
|
||||||
|
ci_next = ci; ci_next++;
|
||||||
|
(*ci)->sendClipboardDataOrClose(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
clipboardRequestors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void VNCServerST::bell()
|
void VNCServerST::bell()
|
||||||
{
|
{
|
||||||
std::list<VNCSConnectionST*>::iterator ci, ci_next;
|
std::list<VNCSConnectionST*>::iterator ci, ci_next;
|
||||||
@ -511,15 +550,6 @@ void VNCServerST::bell()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNCServerST::serverCutText(const char* str, int len)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VNCServerST::setName(const char* name_)
|
void VNCServerST::setName(const char* name_)
|
||||||
{
|
{
|
||||||
name.replaceBuf(strDup(name_));
|
name.replaceBuf(strDup(name_));
|
||||||
@ -565,14 +595,17 @@ void VNCServerST::setCursor(int width, int height, const Point& newHotspot,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VNCServerST::setCursorPos(const Point& pos)
|
void VNCServerST::setCursorPos(const Point& pos, bool warped)
|
||||||
{
|
{
|
||||||
if (!cursorPos.equals(pos)) {
|
if (!cursorPos.equals(pos)) {
|
||||||
cursorPos = pos;
|
cursorPos = pos;
|
||||||
renderedCursorInvalid = true;
|
renderedCursorInvalid = true;
|
||||||
std::list<VNCSConnectionST*>::iterator ci;
|
std::list<VNCSConnectionST*>::iterator ci;
|
||||||
for (ci = clients.begin(); ci != clients.end(); ci++)
|
for (ci = clients.begin(); ci != clients.end(); ci++) {
|
||||||
(*ci)->renderedCursorChange();
|
(*ci)->renderedCursorChange();
|
||||||
|
if (warped)
|
||||||
|
(*ci)->cursorPositionChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,3 +1082,32 @@ bool VNCServerST::getComparerState()
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VNCServerST::handleClipboardRequest(VNCSConnectionST* client)
|
||||||
|
{
|
||||||
|
clipboardRequestors.push_back(client);
|
||||||
|
if (clipboardRequestors.size() == 1)
|
||||||
|
desktop->handleClipboardRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,
|
||||||
|
bool available)
|
||||||
|
{
|
||||||
|
if (available)
|
||||||
|
clipboardClient = client;
|
||||||
|
else {
|
||||||
|
if (client != clipboardClient)
|
||||||
|
return;
|
||||||
|
clipboardClient = NULL;
|
||||||
|
}
|
||||||
|
desktop->handleClipboardAnnounce(available);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VNCServerST::handleClipboardData(VNCSConnectionST* client,
|
||||||
|
const char* data, int len)
|
||||||
|
{
|
||||||
|
if (client != clipboardClient)
|
||||||
|
return;
|
||||||
|
desktop->handleClipboardData(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -96,12 +96,14 @@ namespace rfb {
|
|||||||
virtual void setPixelBuffer(PixelBuffer* pb);
|
virtual void setPixelBuffer(PixelBuffer* pb);
|
||||||
virtual void setScreenLayout(const ScreenSet& layout);
|
virtual void setScreenLayout(const ScreenSet& layout);
|
||||||
virtual PixelBuffer* getPixelBuffer() const { if (DLPRegion.enabled && blackedpb) return blackedpb; else return pb; }
|
virtual PixelBuffer* getPixelBuffer() const { if (DLPRegion.enabled && blackedpb) return blackedpb; else return pb; }
|
||||||
virtual void serverCutText(const char* str, int len);
|
virtual void requestClipboard();
|
||||||
|
virtual void announceClipboard(bool available);
|
||||||
|
virtual void sendClipboardData(const char* data);
|
||||||
virtual void add_changed(const Region ®ion);
|
virtual void add_changed(const Region ®ion);
|
||||||
virtual void add_copied(const Region &dest, const Point &delta);
|
virtual void add_copied(const Region &dest, const Point &delta);
|
||||||
virtual void setCursor(int width, int height, const Point& hotspot,
|
virtual void setCursor(int width, int height, const Point& hotspot,
|
||||||
const rdr::U8* data);
|
const rdr::U8* data);
|
||||||
virtual void setCursorPos(const Point& p);
|
virtual void setCursorPos(const Point& p, bool warped);
|
||||||
virtual void setLEDState(unsigned state);
|
virtual void setLEDState(unsigned state);
|
||||||
|
|
||||||
virtual void bell();
|
virtual void bell();
|
||||||
@ -189,6 +191,10 @@ namespace rfb {
|
|||||||
|
|
||||||
void setAPIMessager(network::GetAPIMessager *msgr) { apimessager = msgr; }
|
void setAPIMessager(network::GetAPIMessager *msgr) { apimessager = msgr; }
|
||||||
|
|
||||||
|
void handleClipboardRequest(VNCSConnectionST* client);
|
||||||
|
void handleClipboardAnnounce(VNCSConnectionST* client, bool available);
|
||||||
|
void handleClipboardData(VNCSConnectionST* client, const char* data, int len);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
friend class VNCSConnectionST;
|
friend class VNCSConnectionST;
|
||||||
@ -217,6 +223,8 @@ namespace rfb {
|
|||||||
|
|
||||||
std::list<VNCSConnectionST*> clients;
|
std::list<VNCSConnectionST*> clients;
|
||||||
VNCSConnectionST* pointerClient;
|
VNCSConnectionST* pointerClient;
|
||||||
|
VNCSConnectionST* clipboardClient;
|
||||||
|
std::list<VNCSConnectionST*> clipboardRequestors;
|
||||||
std::list<network::Socket*> closingSockets;
|
std::list<network::Socket*> closingSockets;
|
||||||
|
|
||||||
static EncCache encCache;
|
static EncCache encCache;
|
||||||
|
@ -31,7 +31,7 @@ IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
|
|||||||
|
|
||||||
ZRLEEncoder::ZRLEEncoder(SConnection* conn)
|
ZRLEEncoder::ZRLEEncoder(SConnection* conn)
|
||||||
: Encoder(conn, encodingZRLE, EncoderPlain, 127),
|
: Encoder(conn, encodingZRLE, EncoderPlain, 127),
|
||||||
zos(0,0,zlibLevel), mos(129*1024)
|
zos(0,zlibLevel), mos(129*1024)
|
||||||
{
|
{
|
||||||
zos.setUnderlying(&mos);
|
zos.setUnderlying(&mos);
|
||||||
}
|
}
|
||||||
|
41
common/rfb/clipboardTypes.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* Copyright 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
|
||||||
|
* 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 __RFB_CLIPBOARDTYPES_H__
|
||||||
|
#define __RFB_CLIPBOARDTYPES_H__
|
||||||
|
|
||||||
|
namespace rfb {
|
||||||
|
|
||||||
|
// Formats
|
||||||
|
const unsigned int clipboardUTF8 = 1 << 0;
|
||||||
|
const unsigned int clipboardRTF = 1 << 1;
|
||||||
|
const unsigned int clipboardHTML = 1 << 2;
|
||||||
|
const unsigned int clipboardDIB = 1 << 3;
|
||||||
|
const unsigned int clipboardFiles = 1 << 4;
|
||||||
|
|
||||||
|
const unsigned int clipboardFormatMask = 0x0000ffff;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
const unsigned int clipboardCaps = 1 << 24;
|
||||||
|
const unsigned int clipboardRequest = 1 << 25;
|
||||||
|
const unsigned int clipboardPeek = 1 << 26;
|
||||||
|
const unsigned int clipboardNotify = 1 << 27;
|
||||||
|
const unsigned int clipboardProvide = 1 << 28;
|
||||||
|
|
||||||
|
const unsigned int clipboardActionMask = 0xff000000;
|
||||||
|
}
|
||||||
|
#endif
|
@ -85,6 +85,12 @@ namespace rfb {
|
|||||||
const int pseudoEncodingVideoOutTimeLevel1 = -1986;
|
const int pseudoEncodingVideoOutTimeLevel1 = -1986;
|
||||||
const int pseudoEncodingVideoOutTimeLevel100 = -1887;
|
const int pseudoEncodingVideoOutTimeLevel100 = -1887;
|
||||||
|
|
||||||
|
// VMware-specific
|
||||||
|
const int pseudoEncodingVMwareCursorPosition = 0x574d5666;
|
||||||
|
|
||||||
|
// UltraVNC-specific
|
||||||
|
const int pseudoEncodingExtendedClipboard = 0xC0A1E5CE;
|
||||||
|
|
||||||
int encodingNum(const char* name);
|
int encodingNum(const char* name);
|
||||||
const char* encodingName(int num);
|
const char* encodingName(int num);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
/* 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
|
* 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
|
||||||
@ -63,6 +64,10 @@ namespace rfb {
|
|||||||
delete [] s;
|
delete [] s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void strFree(wchar_t* s) {
|
||||||
|
delete [] s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) {
|
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) {
|
||||||
CharArray out1old, out2old;
|
CharArray out1old, out2old;
|
||||||
@ -107,6 +112,444 @@ namespace rfb {
|
|||||||
dest[src ? destlen-1 : 0] = 0;
|
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_len > 0) && (*in != '\0')) {
|
||||||
|
if (*in != '\r') {
|
||||||
|
sz++;
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((in_len < 2) || (*(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_len > 0) && (*in != '\0')) {
|
||||||
|
if (*in != '\r') {
|
||||||
|
*out++ = *in++;
|
||||||
|
in_len--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((in_len < 2) || (*(in+1) != '\n'))
|
||||||
|
*out++ = '\n';
|
||||||
|
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* convertCRLF(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_len > 0) && (*in != '\0')) {
|
||||||
|
sz++;
|
||||||
|
|
||||||
|
if (*in == '\r') {
|
||||||
|
if ((in_len < 2) || (*(in+1) != '\n'))
|
||||||
|
sz++;
|
||||||
|
} else if (*in == '\n') {
|
||||||
|
if ((in == src) || (*(in-1) != '\r'))
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
buffer = new char[sz];
|
||||||
|
memset(buffer, 0, sz);
|
||||||
|
|
||||||
|
// And convert
|
||||||
|
out = buffer;
|
||||||
|
in = src;
|
||||||
|
in_len = bytes;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
if (*in == '\n') {
|
||||||
|
if ((in == src) || (*(in-1) != '\r'))
|
||||||
|
*out++ = '\r';
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = *in;
|
||||||
|
|
||||||
|
if (*in == '\r') {
|
||||||
|
if ((in_len < 2) || (*(in+1) != '\n')) {
|
||||||
|
out++;
|
||||||
|
*out = '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out++;
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ucs4ToUTF8(unsigned src, char* dst) {
|
||||||
|
if (src < 0x80) {
|
||||||
|
*dst++ = src;
|
||||||
|
*dst++ = '\0';
|
||||||
|
return 1;
|
||||||
|
} else if (src < 0x800) {
|
||||||
|
*dst++ = 0xc0 | (src >> 6);
|
||||||
|
*dst++ = 0x80 | (src & 0x3f);
|
||||||
|
*dst++ = '\0';
|
||||||
|
return 2;
|
||||||
|
} else if (src < 0x10000) {
|
||||||
|
*dst++ = 0xe0 | (src >> 12);
|
||||||
|
*dst++ = 0x80 | ((src >> 6) & 0x3f);
|
||||||
|
*dst++ = 0x80 | (src & 0x3f);
|
||||||
|
*dst++ = '\0';
|
||||||
|
return 3;
|
||||||
|
} else if (src < 0x110000) {
|
||||||
|
*dst++ = 0xf0 | (src >> 18);
|
||||||
|
*dst++ = 0x80 | ((src >> 12) & 0x3f);
|
||||||
|
*dst++ = 0x80 | ((src >> 6) & 0x3f);
|
||||||
|
*dst++ = 0x80 | (src & 0x3f);
|
||||||
|
*dst++ = '\0';
|
||||||
|
return 4;
|
||||||
|
} else {
|
||||||
|
return ucs4ToUTF8(0xfffd, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst) {
|
||||||
|
size_t count, consumed;
|
||||||
|
|
||||||
|
*dst = 0xfffd;
|
||||||
|
|
||||||
|
if (max == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
consumed = 1;
|
||||||
|
|
||||||
|
if ((*src & 0x80) == 0) {
|
||||||
|
*dst = *src;
|
||||||
|
count = 0;
|
||||||
|
} else if ((*src & 0xe0) == 0xc0) {
|
||||||
|
*dst = *src & 0x1f;
|
||||||
|
count = 1;
|
||||||
|
} else if ((*src & 0xf0) == 0xe0) {
|
||||||
|
*dst = *src & 0x0f;
|
||||||
|
count = 2;
|
||||||
|
} else if ((*src & 0xf8) == 0xf0) {
|
||||||
|
*dst = *src & 0x07;
|
||||||
|
count = 3;
|
||||||
|
} else {
|
||||||
|
// Invalid sequence, consume all continuation characters
|
||||||
|
src++;
|
||||||
|
max--;
|
||||||
|
while ((max-- > 0) && ((*src++ & 0xc0) == 0x80))
|
||||||
|
consumed++;
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
src++;
|
||||||
|
max--;
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
consumed++;
|
||||||
|
|
||||||
|
// Invalid or truncated sequence?
|
||||||
|
if ((max == 0) || ((*src & 0xc0) != 0x80)) {
|
||||||
|
*dst = 0xfffd;
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst <<= 6;
|
||||||
|
*dst |= *src & 0x3f;
|
||||||
|
|
||||||
|
src++;
|
||||||
|
max--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ucs4ToUTF16(unsigned src, wchar_t* dst) {
|
||||||
|
if ((src < 0xd800) || ((src >= 0xe000) && (src < 0x10000))) {
|
||||||
|
*dst++ = src;
|
||||||
|
*dst++ = L'\0';
|
||||||
|
return 1;
|
||||||
|
} else if ((src >= 0x10000) && (src < 0x110000)) {
|
||||||
|
src -= 0x10000;
|
||||||
|
*dst++ = 0xd800 | ((src >> 10) & 0x03ff);
|
||||||
|
*dst++ = 0xdc00 | (src & 0x03ff);
|
||||||
|
*dst++ = L'\0';
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return ucs4ToUTF16(0xfffd, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst) {
|
||||||
|
*dst = 0xfffd;
|
||||||
|
|
||||||
|
if (max == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((*src < 0xd800) || (*src >= 0xe000)) {
|
||||||
|
*dst = *src;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*src & 0x0400) {
|
||||||
|
size_t consumed;
|
||||||
|
|
||||||
|
// Invalid sequence, consume all continuation characters
|
||||||
|
consumed = 0;
|
||||||
|
while ((max > 0) && (*src & 0x0400)) {
|
||||||
|
src++;
|
||||||
|
max--;
|
||||||
|
consumed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = *src++;
|
||||||
|
max--;
|
||||||
|
|
||||||
|
// Invalid or truncated sequence?
|
||||||
|
if ((max == 0) || ((*src & 0xfc00) != 0xdc00)) {
|
||||||
|
*dst = 0xfffd;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = 0x10000 + ((*dst & 0x03ff) << 10);
|
||||||
|
*dst |= *src & 0x3ff;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* latin1ToUTF8(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_len > 0) && (*in != '\0')) {
|
||||||
|
char buf[5];
|
||||||
|
sz += ucs4ToUTF8(*(const unsigned char*)in, buf);
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
buffer = new char[sz];
|
||||||
|
memset(buffer, 0, sz);
|
||||||
|
|
||||||
|
// And convert
|
||||||
|
out = buffer;
|
||||||
|
in = src;
|
||||||
|
in_len = bytes;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
out += ucs4ToUTF8(*(const unsigned char*)in, out);
|
||||||
|
in++;
|
||||||
|
in_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* utf8ToLatin1(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_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
|
||||||
|
len = utf8ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
sz++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
buffer = new char[sz];
|
||||||
|
memset(buffer, 0, sz);
|
||||||
|
|
||||||
|
// And convert
|
||||||
|
out = buffer;
|
||||||
|
in = src;
|
||||||
|
in_len = bytes;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
|
||||||
|
len = utf8ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
|
||||||
|
if (ucs > 0xff)
|
||||||
|
*out++ = '?';
|
||||||
|
else
|
||||||
|
*out++ = (unsigned char)ucs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* utf16ToUTF8(const wchar_t* src, size_t units)
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
char* out;
|
||||||
|
const wchar_t* in;
|
||||||
|
size_t in_len;
|
||||||
|
|
||||||
|
// Always include space for a NULL
|
||||||
|
sz = 1;
|
||||||
|
|
||||||
|
// Compute output size
|
||||||
|
in = src;
|
||||||
|
in_len = units;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
char buf[5];
|
||||||
|
|
||||||
|
len = utf16ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
|
||||||
|
sz += ucs4ToUTF8(ucs, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
buffer = new char[sz];
|
||||||
|
memset(buffer, 0, sz);
|
||||||
|
|
||||||
|
// And convert
|
||||||
|
out = buffer;
|
||||||
|
in = src;
|
||||||
|
in_len = units;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
|
||||||
|
len = utf16ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
|
||||||
|
out += ucs4ToUTF8(ucs, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t* utf8ToUTF16(const char* src, size_t bytes)
|
||||||
|
{
|
||||||
|
wchar_t* buffer;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
wchar_t* 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_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
wchar_t buf[3];
|
||||||
|
|
||||||
|
len = utf8ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
|
||||||
|
sz += ucs4ToUTF16(ucs, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
buffer = new wchar_t[sz];
|
||||||
|
memset(buffer, 0, sz * sizeof(wchar_t));
|
||||||
|
|
||||||
|
// And convert
|
||||||
|
out = buffer;
|
||||||
|
in = src;
|
||||||
|
in_len = bytes;
|
||||||
|
while ((in_len > 0) && (*in != '\0')) {
|
||||||
|
size_t len;
|
||||||
|
unsigned ucs;
|
||||||
|
|
||||||
|
len = utf8ToUCS4(in, in_len, &ucs);
|
||||||
|
in += len;
|
||||||
|
in_len -= len;
|
||||||
|
|
||||||
|
out += ucs4ToUTF16(ucs, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned msBetween(const struct timeval *first,
|
unsigned msBetween(const struct timeval *first,
|
||||||
const struct timeval *second)
|
const struct timeval *second)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
/* 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
|
* 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
|
||||||
@ -67,6 +68,7 @@ namespace rfb {
|
|||||||
|
|
||||||
char* strDup(const char* s);
|
char* strDup(const char* s);
|
||||||
void strFree(char* s);
|
void strFree(char* s);
|
||||||
|
void strFree(wchar_t* s);
|
||||||
|
|
||||||
// Returns true if split successful. Returns false otherwise.
|
// Returns true if split successful. Returns false otherwise.
|
||||||
// ALWAYS *copies* first part of string to out1 buffer.
|
// ALWAYS *copies* first part of string to out1 buffer.
|
||||||
@ -83,6 +85,25 @@ namespace rfb {
|
|||||||
// Copies src to dest, up to specified length-1, and guarantees termination
|
// Copies src to dest, up to specified length-1, and guarantees termination
|
||||||
void strCopy(char* dest, const char* src, int destlen);
|
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);
|
||||||
|
char* convertCRLF(const char* src, size_t bytes = (size_t)-1);
|
||||||
|
|
||||||
|
// Convertions between various Unicode formats. The returned strings are
|
||||||
|
// always null terminated and must be freed using strFree().
|
||||||
|
|
||||||
|
size_t ucs4ToUTF8(unsigned src, char* dst);
|
||||||
|
size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst);
|
||||||
|
|
||||||
|
size_t ucs4ToUTF16(unsigned src, wchar_t* dst);
|
||||||
|
size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst);
|
||||||
|
|
||||||
|
char* latin1ToUTF8(const char* src, size_t bytes = (size_t)-1);
|
||||||
|
char* utf8ToLatin1(const char* src, size_t bytes = (size_t)-1);
|
||||||
|
|
||||||
|
char* utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1);
|
||||||
|
wchar_t* utf8ToUTF16(const char* src, size_t bytes = (size_t)-1);
|
||||||
|
|
||||||
// HELPER functions for timeout handling
|
// HELPER functions for timeout handling
|
||||||
|
|
||||||
|
1
kasmweb
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 10a7fcb91d9ca149262e94e39c216fc2b4f02e10
|
@ -1 +0,0 @@
|
|||||||
**/xtscancodes.js
|
|
@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"rules": {
|
|
||||||
// Unsafe or confusing stuff that we forbid
|
|
||||||
|
|
||||||
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
|
|
||||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
|
||||||
"no-var": "error",
|
|
||||||
"no-useless-constructor": "error",
|
|
||||||
"object-shorthand": ["error", "methods", { "avoidQuotes": true }],
|
|
||||||
"prefer-arrow-callback": "error",
|
|
||||||
"arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ],
|
|
||||||
"arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }],
|
|
||||||
"arrow-spacing": ["error"],
|
|
||||||
"no-confusing-arrow": ["error", { "allowParens": true }],
|
|
||||||
|
|
||||||
// Enforced coding style
|
|
||||||
|
|
||||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
|
||||||
"indent": ["error", 4, { "SwitchCase": 1,
|
|
||||||
"CallExpression": { "arguments": "first" },
|
|
||||||
"ArrayExpression": "first",
|
|
||||||
"ObjectExpression": "first",
|
|
||||||
"ignoreComments": true }],
|
|
||||||
"comma-spacing": ["error"],
|
|
||||||
"comma-style": ["error"],
|
|
||||||
"curly": ["error", "multi-line"],
|
|
||||||
"func-call-spacing": ["error"],
|
|
||||||
"func-names": ["error"],
|
|
||||||
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
|
|
||||||
"key-spacing": ["error"],
|
|
||||||
"keyword-spacing": ["error"],
|
|
||||||
"no-trailing-spaces": ["error"],
|
|
||||||
"semi": ["error"],
|
|
||||||
"space-before-blocks": ["error"],
|
|
||||||
"space-before-function-paren": ["error", { "anonymous": "always",
|
|
||||||
"named": "never",
|
|
||||||
"asyncArrow": "always" }],
|
|
||||||
"switch-colon-spacing": ["error"],
|
|
||||||
}
|
|
||||||
}
|
|
14
kasmweb/.gitignore
vendored
@ -1,14 +0,0 @@
|
|||||||
*.pyc
|
|
||||||
*.o
|
|
||||||
tests/data_*.js
|
|
||||||
utils/rebind.so
|
|
||||||
utils/websockify
|
|
||||||
/node_modules
|
|
||||||
/build
|
|
||||||
/lib
|
|
||||||
recordings
|
|
||||||
*.swp
|
|
||||||
*~
|
|
||||||
noVNC-*.tgz
|
|
||||||
/dist
|
|
||||||
index.html
|
|
0
kasmweb/.gitmodules
vendored
@ -1,53 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
sudo: false
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
||||||
node_js:
|
|
||||||
- 6
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Windows 10'
|
|
||||||
# FIXME Skip tests in Linux since Sauce Labs browser versions are ancient.
|
|
||||||
# - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Linux'
|
|
||||||
- TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='OS X 10.11'
|
|
||||||
- TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Windows 10'
|
|
||||||
# - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Linux'
|
|
||||||
- TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='OS X 10.11'
|
|
||||||
- TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 10'
|
|
||||||
- TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 7'
|
|
||||||
- TEST_BROWSER_NAME=microsoftedge TEST_BROWSER_OS='Windows 10'
|
|
||||||
- TEST_BROWSER_NAME=safari TEST_BROWSER_OS='OS X 10.13'
|
|
||||||
before_script: npm install -g karma-cli
|
|
||||||
addons:
|
|
||||||
sauce_connect:
|
|
||||||
username: "directxman12"
|
|
||||||
jwt:
|
|
||||||
secure: "d3ekMYslpn6R4f0ajtRMt9SUFmNGDiItHpqaXC5T4KI0KMEsxgvEOfJot5PiFFJWg1DSpJZH6oaW2UxGZ3duJLZrXIEd/JePY8a6NtT35BNgiDPgcp+eu2Bu3rhrSNg7/HEsD1ma+JeUTnv18Ai5oMFfCCQJx2J6osIxyl/ZVxA="
|
|
||||||
stages:
|
|
||||||
- lint
|
|
||||||
- test
|
|
||||||
- name: deploy
|
|
||||||
if: tag is PRESENT
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: lint
|
|
||||||
env:
|
|
||||||
addons:
|
|
||||||
before_script:
|
|
||||||
script: npm run lint
|
|
||||||
- stage: deploy
|
|
||||||
env:
|
|
||||||
addons:
|
|
||||||
script: skip
|
|
||||||
before_script: skip
|
|
||||||
deploy:
|
|
||||||
provider: npm
|
|
||||||
email: ossman@cendio.se
|
|
||||||
api_key:
|
|
||||||
secure: "Qq2Mi9xQawO2zlAigzshzMu2QMHvu1IaN9l0ZIivE99wHJj7eS5f4miJ9wB+/mWRRgb3E8uj9ZRV24+Oc36drlBTU9sz+lHhH0uFMfAIseceK64wZV9sLAZm472fmPp2xdUeTCCqPaRy7g1XBqiJ0LyZvEFLsRijqcLjPBF+b8w="
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
repo: novnc/noVNC
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
maintainers:
|
|
||||||
- Joel Martin (@kanaka)
|
|
||||||
- Solly Ross (@directxman12)
|
|
||||||
- Samuel Mannehed for Cendio AB (@samhed)
|
|
||||||
- Pierre Ossman for Cendio AB (@CendioOssman)
|
|
||||||
maintainersEmeritus:
|
|
||||||
- @astrand
|
|
||||||
contributors:
|
|
||||||
# There are a bunch of people that should be here.
|
|
||||||
# If you want to be on this list, feel free send a PR
|
|
||||||
# to add yourself.
|
|
||||||
- jalf <git@jalf.dk>
|
|
||||||
- NTT corp.
|
|
@ -1,68 +0,0 @@
|
|||||||
noVNC is Copyright (C) 2018 The noVNC Authors
|
|
||||||
(./AUTHORS)
|
|
||||||
|
|
||||||
The noVNC core library files are licensed under the MPL 2.0 (Mozilla
|
|
||||||
Public License 2.0). The noVNC core library is composed of the
|
|
||||||
Javascript code necessary for full noVNC operation. This includes (but
|
|
||||||
is not limited to):
|
|
||||||
|
|
||||||
core/**/*.js
|
|
||||||
app/*.js
|
|
||||||
test/playback.js
|
|
||||||
|
|
||||||
The HTML, CSS, font and images files that included with the noVNC
|
|
||||||
source distibution (or repository) are not considered part of the
|
|
||||||
noVNC core library and are licensed under more permissive licenses.
|
|
||||||
The intent is to allow easy integration of noVNC into existing web
|
|
||||||
sites and web applications.
|
|
||||||
|
|
||||||
The HTML, CSS, font and image files are licensed as follows:
|
|
||||||
|
|
||||||
*.html : 2-Clause BSD license
|
|
||||||
|
|
||||||
app/styles/*.css : 2-Clause BSD license
|
|
||||||
|
|
||||||
app/styles/Orbitron* : SIL Open Font License 1.1
|
|
||||||
(Copyright 2009 Matt McInerney)
|
|
||||||
|
|
||||||
app/images/ : Creative Commons Attribution-ShareAlike
|
|
||||||
http://creativecommons.org/licenses/by-sa/3.0/
|
|
||||||
|
|
||||||
Some portions of noVNC are copyright to their individual authors.
|
|
||||||
Please refer to the individual source files and/or to the noVNC commit
|
|
||||||
history: https://github.com/novnc/noVNC/commits/master
|
|
||||||
|
|
||||||
The are several files and projects that have been incorporated into
|
|
||||||
the noVNC core library. Here is a list of those files and the original
|
|
||||||
licenses (all MPL 2.0 compatible):
|
|
||||||
|
|
||||||
core/base64.js : MPL 2.0
|
|
||||||
|
|
||||||
core/des.js : Various BSD style licenses
|
|
||||||
|
|
||||||
vendor/pako/ : MIT
|
|
||||||
|
|
||||||
vendor/browser-es-module-loader/src/ : MIT
|
|
||||||
|
|
||||||
vendor/browser-es-module-loader/dist/ : Various BSD style licenses
|
|
||||||
|
|
||||||
vendor/promise.js : MIT
|
|
||||||
|
|
||||||
Any other files not mentioned above are typically marked with
|
|
||||||
a copyright/license header at the top of the file. The default noVNC
|
|
||||||
license is MPL-2.0.
|
|
||||||
|
|
||||||
The following license texts are included:
|
|
||||||
|
|
||||||
docs/LICENSE.MPL-2.0
|
|
||||||
docs/LICENSE.OFL-1.1
|
|
||||||
docs/LICENSE.BSD-3-Clause (New BSD)
|
|
||||||
docs/LICENSE.BSD-2-Clause (Simplified BSD / FreeBSD)
|
|
||||||
vendor/pako/LICENSE (MIT)
|
|
||||||
|
|
||||||
Or alternatively the license texts may be found here:
|
|
||||||
|
|
||||||
http://www.mozilla.org/MPL/2.0/
|
|
||||||
http://scripts.sil.org/OFL
|
|
||||||
http://en.wikipedia.org/wiki/BSD_licenses
|
|
||||||
https://opensource.org/licenses/MIT
|
|
@ -1,151 +0,0 @@
|
|||||||
## noVNC: HTML VNC Client Library and Application
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/novnc/noVNC.svg?branch=master)](https://travis-ci.org/novnc/noVNC)
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
noVNC is both a HTML VNC client JavaScript library and an application built on
|
|
||||||
top of that library. noVNC runs well in any modern browser including mobile
|
|
||||||
browsers (iOS and Android).
|
|
||||||
|
|
||||||
Many companies, projects and products have integrated noVNC including
|
|
||||||
[OpenStack](http://www.openstack.org),
|
|
||||||
[OpenNebula](http://opennebula.org/),
|
|
||||||
[LibVNCServer](http://libvncserver.sourceforge.net), and
|
|
||||||
[ThinLinc](https://cendio.com/thinlinc). See
|
|
||||||
[the Projects and Companies wiki page](https://github.com/novnc/noVNC/wiki/Projects-and-companies-using-noVNC)
|
|
||||||
for a more complete list with additional info and links.
|
|
||||||
|
|
||||||
### Table of Contents
|
|
||||||
|
|
||||||
- [News/help/contact](#newshelpcontact)
|
|
||||||
- [Features](#features)
|
|
||||||
- [Screenshots](#screenshots)
|
|
||||||
- [Browser Requirements](#browser-requirements)
|
|
||||||
- [Server Requirements](#server-requirements)
|
|
||||||
- [Quick Start](#quick-start)
|
|
||||||
- [Integration and Deployment](#integration-and-deployment)
|
|
||||||
- [Authors/Contributors](#authorscontributors)
|
|
||||||
|
|
||||||
### News/help/contact
|
|
||||||
|
|
||||||
The project website is found at [novnc.com](http://novnc.com).
|
|
||||||
Notable commits, announcements and news are posted to
|
|
||||||
[@noVNC](http://www.twitter.com/noVNC).
|
|
||||||
|
|
||||||
If you are a noVNC developer/integrator/user (or want to be) please join the
|
|
||||||
[noVNC discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc).
|
|
||||||
|
|
||||||
Bugs and feature requests can be submitted via
|
|
||||||
[github issues](https://github.com/novnc/noVNC/issues). If you have questions
|
|
||||||
about using noVNC then please first use the
|
|
||||||
[discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc).
|
|
||||||
We also have a [wiki](https://github.com/novnc/noVNC/wiki/) with lots of
|
|
||||||
helpful information.
|
|
||||||
|
|
||||||
If you are looking for a place to start contributing to noVNC, a good place to
|
|
||||||
start would be the issues that are marked as
|
|
||||||
["patchwelcome"](https://github.com/novnc/noVNC/issues?labels=patchwelcome).
|
|
||||||
Please check our
|
|
||||||
[contribution guide](https://github.com/novnc/noVNC/wiki/Contributing) though.
|
|
||||||
|
|
||||||
If you want to show appreciation for noVNC you could donate to a great non-
|
|
||||||
profits such as:
|
|
||||||
[Compassion International](http://www.compassion.com/),
|
|
||||||
[SIL](http://www.sil.org),
|
|
||||||
[Habitat for Humanity](http://www.habitat.org),
|
|
||||||
[Electronic Frontier Foundation](https://www.eff.org/),
|
|
||||||
[Against Malaria Foundation](http://www.againstmalaria.com/),
|
|
||||||
[Nothing But Nets](http://www.nothingbutnets.net/), etc.
|
|
||||||
Please tweet [@noVNC](http://www.twitter.com/noVNC) if you do.
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* Supports all modern browsers including mobile (iOS, Android)
|
|
||||||
* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG
|
|
||||||
* Supports scaling, clipping and resizing the desktop
|
|
||||||
* Local cursor rendering
|
|
||||||
* Clipboard copy/paste
|
|
||||||
* Licensed mainly under the [MPL 2.0](http://www.mozilla.org/MPL/2.0/), see
|
|
||||||
[the license document](LICENSE.txt) for details
|
|
||||||
|
|
||||||
### Screenshots
|
|
||||||
|
|
||||||
Running in Firefox before and after connecting:
|
|
||||||
|
|
||||||
<img src="http://novnc.com/img/noVNC-1-login.png" width=400>
|
|
||||||
<img src="http://novnc.com/img/noVNC-3-connected.png" width=400>
|
|
||||||
|
|
||||||
See more screenshots
|
|
||||||
[here](http://novnc.com/screenshots.html).
|
|
||||||
|
|
||||||
|
|
||||||
### Browser Requirements
|
|
||||||
|
|
||||||
noVNC uses many modern web technologies so a formal requirement list is
|
|
||||||
not available. However these are the minimum versions we are currently
|
|
||||||
aware of:
|
|
||||||
|
|
||||||
* Chrome 49, Firefox 44, Safari 10, Opera 36, IE 11, Edge 12
|
|
||||||
|
|
||||||
|
|
||||||
### Server Requirements
|
|
||||||
|
|
||||||
noVNC follows the standard VNC protocol, but unlike other VNC clients it does
|
|
||||||
require WebSockets support. Many servers include support (e.g.
|
|
||||||
[x11vnc/libvncserver](http://libvncserver.sourceforge.net/),
|
|
||||||
[QEMU](http://www.qemu.org/), and
|
|
||||||
[MobileVNC](http://www.smartlab.at/mobilevnc/)), but for the others you need to
|
|
||||||
use a WebSockets to TCP socket proxy. noVNC has a sister project
|
|
||||||
[websockify](https://github.com/novnc/websockify) that provides a simple such
|
|
||||||
proxy.
|
|
||||||
|
|
||||||
|
|
||||||
### Quick Start
|
|
||||||
|
|
||||||
* Use the launch script to automatically download and start websockify, which
|
|
||||||
includes a mini-webserver and the WebSockets proxy. The `--vnc` option is
|
|
||||||
used to specify the location of a running VNC server:
|
|
||||||
|
|
||||||
`./utils/launch.sh --vnc localhost:5901`
|
|
||||||
|
|
||||||
* Point your browser to the cut-and-paste URL that is output by the launch
|
|
||||||
script. Hit the Connect button, enter a password if the VNC server has one
|
|
||||||
configured, and enjoy!
|
|
||||||
|
|
||||||
|
|
||||||
### Integration and Deployment
|
|
||||||
|
|
||||||
Please see our other documents for how to integrate noVNC in your own software,
|
|
||||||
or deploying the noVNC application in production environments:
|
|
||||||
|
|
||||||
* [Embedding](docs/EMBEDDING.md) - For the noVNC application
|
|
||||||
* [Library](docs/LIBRARY.md) - For the noVNC JavaScript library
|
|
||||||
|
|
||||||
|
|
||||||
### Authors/Contributors
|
|
||||||
|
|
||||||
See [AUTHORS](AUTHORS) for a (full-ish) list of authors. If you're not on
|
|
||||||
that list and you think you should be, feel free to send a PR to fix that.
|
|
||||||
|
|
||||||
* Core team:
|
|
||||||
* [Joel Martin](https://github.com/kanaka)
|
|
||||||
* [Samuel Mannehed](https://github.com/samhed) (Cendio)
|
|
||||||
* [Peter Åstrand](https://github.com/astrand) (Cendio)
|
|
||||||
* [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack)
|
|
||||||
* [Pierre Ossman](https://github.com/CendioOssman) (Cendio)
|
|
||||||
|
|
||||||
* Notable contributions:
|
|
||||||
* UI and Icons : Pierre Ossman, Chris Gordon
|
|
||||||
* Original Logo : Michael Sersen
|
|
||||||
* tight encoding : Michael Tinglof (Mercuri.ca)
|
|
||||||
|
|
||||||
* Included libraries:
|
|
||||||
* base64 : Martijn Pieters (Digital Creations 2), Samuel Sieb (sieb.net)
|
|
||||||
* DES : Dave Zimmerman (Widget Workshop), Jef Poskanzer (ACME Labs)
|
|
||||||
* Pako : Vitaly Puzrin (https://github.com/nodeca/pako)
|
|
||||||
|
|
||||||
Do you want to be on this list? Check out our
|
|
||||||
[contribution guide](https://github.com/novnc/noVNC/wiki/Contributing) and
|
|
||||||
start hacking!
|
|
@ -1 +0,0 @@
|
|||||||
1.0.0
|
|
@ -1,58 +0,0 @@
|
|||||||
// NB: this should *not* be included as a module until we have
|
|
||||||
// native support in the browsers, so that our error handler
|
|
||||||
// can catch script-loading errors.
|
|
||||||
|
|
||||||
// No ES6 can be used in this file since it's used for the translation
|
|
||||||
/* eslint-disable prefer-arrow-callback */
|
|
||||||
|
|
||||||
(function _scope() {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Fallback for all uncaught errors
|
|
||||||
function handleError(event, err) {
|
|
||||||
try {
|
|
||||||
const msg = document.getElementById('noVNC_fallback_errormsg');
|
|
||||||
|
|
||||||
// Only show the initial error
|
|
||||||
if (msg.hasChildNodes()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let div = document.createElement("div");
|
|
||||||
div.classList.add('noVNC_message');
|
|
||||||
div.appendChild(document.createTextNode(event.message));
|
|
||||||
msg.appendChild(div);
|
|
||||||
|
|
||||||
if (event.filename) {
|
|
||||||
div = document.createElement("div");
|
|
||||||
div.className = 'noVNC_location';
|
|
||||||
let text = event.filename;
|
|
||||||
if (event.lineno !== undefined) {
|
|
||||||
text += ":" + event.lineno;
|
|
||||||
if (event.colno !== undefined) {
|
|
||||||
text += ":" + event.colno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
div.appendChild(document.createTextNode(text));
|
|
||||||
msg.appendChild(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err && err.stack) {
|
|
||||||
div = document.createElement("div");
|
|
||||||
div.className = 'noVNC_stack';
|
|
||||||
div.appendChild(document.createTextNode(err.stack));
|
|
||||||
msg.appendChild(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('noVNC_fallback_error')
|
|
||||||
.classList.add("noVNC_open");
|
|
||||||
} catch (exc) {
|
|
||||||
document.write("Kasm has encountered an error.");
|
|
||||||
}
|
|
||||||
// Don't return true since this would prevent the error
|
|
||||||
// from being printed to the browser console.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
window.addEventListener('error', function onerror(evt) { handleError(evt, evt.error); });
|
|
||||||
window.addEventListener('unhandledrejection', function onreject(evt) { handleError(evt.reason, evt.reason); });
|
|
||||||
})();
|
|
@ -1,92 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="alt.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="16"
|
|
||||||
inkscape:cx="18.205425"
|
|
||||||
inkscape:cy="17.531398"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<g
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="text5290">
|
|
||||||
<path
|
|
||||||
d="m 9.9560547,1042.3329 -2.9394531,0 -0.4638672,1.3281 -1.8896485,0 2.7001953,-7.29 2.241211,0 2.7001958,7.29 -1.889649,0 -0.4589843,-1.3281 z m -2.4707031,-1.3526 1.9970703,0 -0.9960938,-2.9003 -1.0009765,2.9003 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5340" />
|
|
||||||
<path
|
|
||||||
d="m 13.188477,1036.0634 1.748046,0 0,7.5976 -1.748046,0 0,-7.5976 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5342" />
|
|
||||||
<path
|
|
||||||
d="m 18.535156,1036.6395 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151367,0.5176 0.151368,0.1318 0.600586,0.1318 l 0.898438,0 0,1.25 -1.499024,0 q -1.035156,0 -1.469726,-0.4297 -0.429688,-0.4345 -0.429688,-1.4697 l 0,-2.3193 -0.86914,0 0,-1.25 0.86914,0 0,-1.5528 1.748047,0 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5344" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.5 KiB |
@ -1,106 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="clipboard.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="15.366606"
|
|
||||||
inkscape:cy="16.42981"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="M 9,6 6,6 C 5.4459889,6 5,6.4459889 5,7 l 0,13 c 0,0.554011 0.4459889,1 1,1 l 13,0 c 0.554011,0 1,-0.445989 1,-1 L 20,7 C 20,6.4459889 19.554011,6 19,6 l -3,0"
|
|
||||||
transform="translate(0,1027.3622)"
|
|
||||||
id="rect6083"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cssssssssc" />
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect6085"
|
|
||||||
width="7"
|
|
||||||
height="4"
|
|
||||||
x="9"
|
|
||||||
y="1031.3622"
|
|
||||||
ry="1.00002" />
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
|
|
||||||
d="m 8.5071212,1038.8622 7.9999998,0"
|
|
||||||
id="path6087"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
|
|
||||||
d="m 8.5071212,1041.8622 3.9999998,0"
|
|
||||||
id="path6089"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
|
|
||||||
d="m 8.5071212,1044.8622 5.9999998,0"
|
|
||||||
id="path6091"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.9 KiB |
@ -1,96 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="connect.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="37.14834"
|
|
||||||
inkscape:cy="1.9525926"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<g
|
|
||||||
id="g5103"
|
|
||||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-729.15757,315.8823)">
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="cssssc"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="rect5096"
|
|
||||||
d="m 11,1040.3622 -5,0 c -1.108,0 -2,-0.892 -2,-2 l 0,-4 c 0,-1.108 0.892,-2 2,-2 l 5,0"
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="m 14,1032.3622 5,0 c 1.108,0 2,0.892 2,2 l 0,4 c 0,1.108 -0.892,2 -2,2 l -5,0"
|
|
||||||
id="path5099"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cssssc" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path5101"
|
|
||||||
d="m 9,1036.3622 7,0"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.3 KiB |
@ -1,96 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="ctrl.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="16"
|
|
||||||
inkscape:cx="18.205425"
|
|
||||||
inkscape:cy="17.531398"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<g
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="text5290">
|
|
||||||
<path
|
|
||||||
d="m 9.1210938,1043.1898 q -0.5175782,0.2686 -1.0791016,0.4053 -0.5615235,0.1367 -1.171875,0.1367 -1.8212891,0 -2.8857422,-1.0156 -1.0644531,-1.0205 -1.0644531,-2.7637 0,-1.748 1.0644531,-2.7637 1.0644531,-1.0205 2.8857422,-1.0205 0.6103515,0 1.171875,0.1368 0.5615234,0.1367 1.0791016,0.4052 l 0,1.5088 q -0.522461,-0.3564 -1.0302735,-0.5224 -0.5078125,-0.1661 -1.0693359,-0.1661 -1.0058594,0 -1.5820313,0.6446 -0.5761719,0.6445 -0.5761719,1.7773 0,1.1279 0.5761719,1.7725 0.5761719,0.6445 1.5820313,0.6445 0.5615234,0 1.0693359,-0.166 0.5078125,-0.166 1.0302735,-0.5225 l 0,1.5088 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5370" />
|
|
||||||
<path
|
|
||||||
d="m 12.514648,1036.5687 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151368,0.5176 0.151367,0.1318 0.600586,0.1318 l 0.898437,0 0,1.25 -1.499023,0 q -1.035157,0 -1.469727,-0.4297 -0.429687,-0.4345 -0.429687,-1.4697 l 0,-2.3193 -0.8691411,0 0,-1.25 0.8691411,0 0,-1.5528 1.748046,0 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5372" />
|
|
||||||
<path
|
|
||||||
d="m 19.453125,1039.6107 q -0.229492,-0.1074 -0.458984,-0.1562 -0.22461,-0.054 -0.454102,-0.054 -0.673828,0 -1.040039,0.4345 -0.361328,0.4297 -0.361328,1.2354 l 0,2.5195 -1.748047,0 0,-5.4687 1.748047,0 0,0.8984 q 0.336914,-0.5371 0.771484,-0.7813 0.439453,-0.249 1.049805,-0.249 0.08789,0 0.19043,0.01 0.102539,0 0.297851,0.029 l 0.0049,1.582 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5374" />
|
|
||||||
<path
|
|
||||||
d="m 20.332031,1035.9926 1.748047,0 0,7.5976 -1.748047,0 0,-7.5976 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5376" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.3 KiB |
@ -1,100 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="ctrlaltdel.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="8"
|
|
||||||
inkscape:cx="11.135667"
|
|
||||||
inkscape:cy="16.407428"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect5253"
|
|
||||||
width="5"
|
|
||||||
height="5.0000172"
|
|
||||||
x="16"
|
|
||||||
y="1031.3622"
|
|
||||||
ry="1.0000174" />
|
|
||||||
<rect
|
|
||||||
y="1043.3622"
|
|
||||||
x="4"
|
|
||||||
height="5.0000172"
|
|
||||||
width="5"
|
|
||||||
id="rect5255"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
ry="1.0000174" />
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect5257"
|
|
||||||
width="5"
|
|
||||||
height="5.0000172"
|
|
||||||
x="13"
|
|
||||||
y="1043.3622"
|
|
||||||
ry="1.0000174" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.2 KiB |
@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="disconnect.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="16"
|
|
||||||
inkscape:cx="25.05707"
|
|
||||||
inkscape:cy="11.594858"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<g
|
|
||||||
id="g5171"
|
|
||||||
transform="translate(-24.062499,-6.15775e-4)">
|
|
||||||
<path
|
|
||||||
id="path5110"
|
|
||||||
transform="translate(0,1027.3622)"
|
|
||||||
d="m 39.744141,3.4960938 c -0.769923,0 -1.539607,0.2915468 -2.121094,0.8730468 l -2.566406,2.5664063 1.414062,1.4140625 2.566406,-2.5664063 c 0.403974,-0.404 1.010089,-0.404 1.414063,0 l 2.828125,2.828125 c 0.40398,0.4039 0.403907,1.0101621 0,1.4140629 l -2.566406,2.566406 1.414062,1.414062 2.566406,-2.566406 c 1.163041,-1.1629 1.162968,-3.0791874 0,-4.2421874 L 41.865234,4.3691406 C 41.283747,3.7876406 40.514063,3.4960937 39.744141,3.4960938 Z M 39.017578,9.015625 a 1.0001,1.0001 0 0 0 -0.6875,0.3027344 l -0.445312,0.4453125 1.414062,1.4140621 0.445313,-0.445312 A 1.0001,1.0001 0 0 0 39.017578,9.015625 Z m -6.363281,0.7070312 a 1.0001,1.0001 0 0 0 -0.6875,0.3027348 L 28.431641,13.5625 c -1.163042,1.163 -1.16297,3.079187 0,4.242188 l 2.828125,2.828124 c 1.162974,1.163101 3.079213,1.163101 4.242187,0 l 3.535156,-3.535156 a 1.0001,1.0001 0 1 0 -1.414062,-1.414062 l -3.535156,3.535156 c -0.403974,0.404 -1.010089,0.404 -1.414063,0 l -2.828125,-2.828125 c -0.403981,-0.404 -0.403908,-1.010162 0,-1.414063 l 3.535156,-3.537109 A 1.0001,1.0001 0 0 0 32.654297,9.7226562 Z m 3.109375,2.1621098 -2.382813,2.384765 a 1.0001,1.0001 0 1 0 1.414063,1.414063 l 2.382812,-2.384766 -1.414062,-1.414062 z"
|
|
||||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<rect
|
|
||||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"
|
|
||||||
y="752.29541"
|
|
||||||
x="-712.31262"
|
|
||||||
height="18.000017"
|
|
||||||
width="3"
|
|
||||||
id="rect5116"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 123 B |
@ -1,76 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="drag.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="22.627417"
|
|
||||||
inkscape:cx="9.8789407"
|
|
||||||
inkscape:cy="9.5008608"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="m 7.039733,1049.3037 c -0.4309106,-0.1233 -0.7932634,-0.4631 -0.9705434,-0.9103 -0.04922,-0.1241 -0.057118,-0.2988 -0.071321,-1.5771 l -0.015972,-1.4375 -0.328125,-0.082 c -0.7668138,-0.1927 -1.1897046,-0.4275 -1.7031253,-0.9457 -0.4586773,-0.4629 -0.6804297,-0.8433 -0.867034,-1.4875 -0.067215,-0.232 -0.068001,-0.2642 -0.078682,-3.2188 -0.012078,-3.341 -0.020337,-3.2012 0.2099452,-3.5555 0.2246623,-0.3458 0.5798271,-0.5892 0.9667343,-0.6626 0.092506,-0.017 0.531898,-0.032 0.9764271,-0.032 l 0.8082347,0 1.157e-4,1.336 c 1.125e-4,1.2779 0.00281,1.3403 0.062214,1.4378 0.091785,0.1505 0.2357707,0.226 0.4314082,0.2261 0.285389,2e-4 0.454884,-0.1352 0.5058962,-0.4042 0.019355,-0.102 0.031616,-0.982 0.031616,-2.269 0,-1.9756 0.00357,-2.1138 0.059205,-2.2926 0.1645475,-0.5287 0.6307616,-0.9246 1.19078,-1.0113 0.8000572,-0.1238 1.5711277,0.4446 1.6860387,1.2429 0.01732,0.1203 0.03177,0.8248 0.03211,1.5657 6.19e-4,1.3449 7.22e-4,1.347 0.07093,1.4499 0.108355,0.1587 0.255268,0.2248 0.46917,0.2108 0.204069,-0.013 0.316116,-0.08 0.413642,-0.2453 0.06028,-0.1024 0.06307,-0.1778 0.07862,-2.1218 0.01462,-1.8283 0.02124,-2.0285 0.07121,-2.1549 0.260673,-0.659 0.934894,-1.0527 1.621129,-0.9465 0.640523,0.099 1.152269,0.6104 1.243187,1.2421 0.01827,0.1269 0.03175,0.9943 0.03211,2.0657 l 6.19e-4,1.8469 0.07031,0.103 c 0.108355,0.1587 0.255267,0.2248 0.46917,0.2108 0.204069,-0.013 0.316115,-0.08 0.413642,-0.2453 0.05951,-0.1011 0.06329,-0.1786 0.07907,-1.6218 0.01469,-1.3438 0.02277,-1.5314 0.07121,-1.6549 0.257975,-0.6576 0.934425,-1.0527 1.620676,-0.9465 0.640522,0.099 1.152269,0.6104 1.243186,1.2421 0.0186,0.1292 0.03179,1.0759 0.03222,2.3125 7.15e-4,2.0335 0.0025,2.0966 0.06283,2.1956 0.09178,0.1505 0.235771,0.226 0.431409,0.2261 0.285388,2e-4 0.454884,-0.1352 0.505897,-0.4042 0.01874,-0.099 0.03161,-0.8192 0.03161,-1.769 0,-1.4848 0.0043,-1.6163 0.0592,-1.7926 0.164548,-0.5287 0.630762,-0.9246 1.19078,-1.0113 0.800057,-0.1238 1.571128,0.4446 1.686039,1.2429 0.04318,0.2999 0.04372,9.1764 5.78e-4,9.4531 -0.04431,0.2841 -0.217814,0.6241 -0.420069,0.8232 -0.320102,0.315 -0.63307,0.4268 -1.194973,0.4268 l -0.35281,0 -2.51e-4,1.2734 c -1.25e-4,0.7046 -0.01439,1.3642 -0.03191,1.4766 -0.06665,0.4274 -0.372966,0.8704 -0.740031,1.0702 -0.349999,0.1905 0.01748,0.18 -6.242199,0.1776 -5.3622439,0 -5.7320152,-0.01 -5.9121592,-0.057 l 1.4e-5,0 z"
|
|
||||||
id="path4379"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.6 KiB |
@ -1,81 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="error.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="14.00357"
|
|
||||||
inkscape:cy="12.443398"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="M 7 3 C 4.7839905 3 3 4.7839905 3 7 L 3 18 C 3 20.21601 4.7839905 22 7 22 L 18 22 C 20.21601 22 22 20.21601 22 18 L 22 7 C 22 4.7839905 20.21601 3 18 3 L 7 3 z M 7.6992188 6 A 1.6916875 1.6924297 0 0 1 8.9121094 6.5117188 L 12.5 10.101562 L 16.087891 6.5117188 A 1.6916875 1.6924297 0 0 1 17.251953 6 A 1.6916875 1.6924297 0 0 1 18.480469 8.90625 L 14.892578 12.496094 L 18.480469 16.085938 A 1.6916875 1.6924297 0 1 1 16.087891 18.478516 L 12.5 14.888672 L 8.9121094 18.478516 A 1.6916875 1.6924297 0 1 1 6.5214844 16.085938 L 10.109375 12.496094 L 6.5214844 8.90625 A 1.6916875 1.6924297 0 0 1 7.6992188 6 z "
|
|
||||||
transform="translate(0,1027.3622)"
|
|
||||||
id="rect4135" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.0 KiB |
@ -1,92 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="esc.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="16"
|
|
||||||
inkscape:cx="18.205425"
|
|
||||||
inkscape:cy="17.531398"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="text5290"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<g
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="text5290">
|
|
||||||
<path
|
|
||||||
d="m 3.9331055,1036.1464 5.0732422,0 0,1.4209 -3.1933594,0 0,1.3574 3.0029297,0 0,1.4209 -3.0029297,0 0,1.6699 3.3007812,0 0,1.4209 -5.180664,0 0,-7.29 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5314" />
|
|
||||||
<path
|
|
||||||
d="m 14.963379,1038.1385 0,1.3282 q -0.561524,-0.2344 -1.083984,-0.3516 -0.522461,-0.1172 -0.986329,-0.1172 -0.498046,0 -0.742187,0.127 -0.239258,0.122 -0.239258,0.3808 0,0.21 0.180664,0.3223 0.185547,0.1123 0.65918,0.166 l 0.307617,0.044 q 1.342773,0.1709 1.806641,0.5615 0.463867,0.3906 0.463867,1.2256 0,0.874 -0.644531,1.3134 -0.644532,0.4395 -1.923829,0.4395 -0.541992,0 -1.123046,-0.088 -0.576172,-0.083 -1.186524,-0.2539 l 0,-1.3281 q 0.522461,0.2539 1.069336,0.3808 0.551758,0.127 1.118164,0.127 0.512695,0 0.771485,-0.1416 0.258789,-0.1416 0.258789,-0.4199 0,-0.2344 -0.180664,-0.3467 -0.175782,-0.1172 -0.708008,-0.1807 l -0.307617,-0.039 q -1.166993,-0.1465 -1.635743,-0.542 -0.46875,-0.3955 -0.46875,-1.2012 0,-0.8691 0.595703,-1.2891 0.595704,-0.4199 1.826172,-0.4199 0.483399,0 1.015625,0.073 0.532227,0.073 1.157227,0.2294 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5316" />
|
|
||||||
<path
|
|
||||||
d="m 21.066895,1038.1385 0,1.4258 q -0.356446,-0.2441 -0.717774,-0.3613 -0.356445,-0.1172 -0.742187,-0.1172 -0.732422,0 -1.142579,0.4297 -0.405273,0.4248 -0.405273,1.1914 0,0.7666 0.405273,1.1963 0.410157,0.4248 1.142579,0.4248 0.410156,0 0.776367,-0.1221 0.371094,-0.122 0.683594,-0.3613 l 0,1.4307 q -0.410157,0.1513 -0.834961,0.2246 -0.419922,0.078 -0.844727,0.078 -1.479492,0 -2.314453,-0.7568 -0.834961,-0.7618 -0.834961,-2.1143 0,-1.3525 0.834961,-2.1094 0.834961,-0.7617 2.314453,-0.7617 0.429688,0 0.844727,0.078 0.419921,0.073 0.834961,0.2246 z"
|
|
||||||
style="font-size:10px;fill:#ffffff;fill-opacity:1"
|
|
||||||
id="path5318" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,69 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="9"
|
|
||||||
height="10"
|
|
||||||
viewBox="0 0 9 10"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="expander.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="45.254834"
|
|
||||||
inkscape:cx="9.8737281"
|
|
||||||
inkscape:cy="6.4583132"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-object-midpoints="false"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1042.3622)">
|
|
||||||
<path
|
|
||||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
|
||||||
d="M 2.0800781,1042.3633 A 2.0002,2.0002 0 0 0 0,1044.3613 l 0,6 a 2.0002,2.0002 0 0 0 3.0292969,1.7168 l 5,-3 a 2.0002,2.0002 0 0 0 0,-3.4316 l -5,-3 a 2.0002,2.0002 0 0 0 -0.9492188,-0.2832 z"
|
|
||||||
id="path4138"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.0 KiB |
@ -1,93 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="25"
|
|
||||||
height="25"
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="fullscreen.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="16.400723"
|
|
||||||
inkscape:cy="15.083758"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1027.3622)">
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect5006"
|
|
||||||
width="17"
|
|
||||||
height="17.000017"
|
|
||||||
x="4"
|
|
||||||
y="1031.3622"
|
|
||||||
ry="3.0000174" />
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="m 7.5,1044.8622 4,0 -1.5,-1.5 1.5,-1.5 -1,-1 -1.5,1.5 -1.5,-1.5 0,4 z"
|
|
||||||
id="path5017"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path5025"
|
|
||||||
d="m 17.5,1034.8622 -4,0 1.5,1.5 -1.5,1.5 1,1 1.5,-1.5 1.5,1.5 0,-4 z"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.1 KiB |
@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="5"
|
|
||||||
height="6"
|
|
||||||
viewBox="0 0 5 6"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="handle.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="32"
|
|
||||||
inkscape:cx="1.3551778"
|
|
||||||
inkscape:cy="8.7800329"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1046.3622)">
|
|
||||||
<path
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="m 4.0000803,1049.3622 -3,-2 0,4 z"
|
|
||||||
id="path4247"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cccc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.5 KiB |
@ -1,172 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="15"
|
|
||||||
height="50"
|
|
||||||
viewBox="0 0 15 50"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="handle_bg.svg"
|
|
||||||
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-ydpi="90">
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#959595"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="16"
|
|
||||||
inkscape:cx="-10.001409"
|
|
||||||
inkscape:cy="24.512566"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="true"
|
|
||||||
units="px"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
inkscape:bbox-paths="true"
|
|
||||||
inkscape:bbox-nodes="true"
|
|
||||||
inkscape:snap-bbox-edge-midpoints="true"
|
|
||||||
inkscape:object-paths="true"
|
|
||||||
showguides="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="1920"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:snap-smooth-nodes="true"
|
|
||||||
inkscape:object-nodes="true"
|
|
||||||
inkscape:snap-intersection-paths="true"
|
|
||||||
inkscape:snap-nodes="true"
|
|
||||||
inkscape:snap-global="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid4136" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata7">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-1002.3622)">
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4249"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="9.5"
|
|
||||||
y="1008.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1013.8622"
|
|
||||||
x="9.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4255"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1008.8622"
|
|
||||||
x="4.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4261"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4263"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="4.5"
|
|
||||||
y="1013.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1039.8622"
|
|
||||||
x="9.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4265"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4267"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="9.5"
|
|
||||||
y="1044.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4269"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="4.5"
|
|
||||||
y="1039.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1044.8622"
|
|
||||||
x="4.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4271"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4273"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="9.5"
|
|
||||||
y="1018.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1018.8622"
|
|
||||||
x="4.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4275"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4277"
|
|
||||||
width="1"
|
|
||||||
height="1.0000174"
|
|
||||||
x="9.5"
|
|
||||||
y="1034.8622"
|
|
||||||
ry="1.7382812e-05" />
|
|
||||||
<rect
|
|
||||||
ry="1.7382812e-05"
|
|
||||||
y="1034.8622"
|
|
||||||
x="4.5"
|
|
||||||
height="1.0000174"
|
|
||||||
width="1"
|
|
||||||
id="rect4279"
|
|
||||||
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 5.1 KiB |