Merge pull request #36 from kasmtech/upstreamsync_sans_novnc
Upstream Syncs
@ -4,6 +4,7 @@ services:
|
||||
|
||||
variables:
|
||||
GITLAB_SHARED_DIND_DIR: /builds/$CI_PROJECT_PATH/shared
|
||||
GIT_SUBMODULE_STRATEGY: normal
|
||||
GIT_FETCH_EXTRA_FLAGS: --tags
|
||||
|
||||
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
|
||||
rm *.md
|
||||
rm AUTHORS
|
||||
rm *.yml
|
||||
rm vnc.html
|
||||
rm vnc_lite.html
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define errorNumber WSAGetLastError()
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
#define SHUT_WR SD_SEND
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#else
|
||||
#define errorNumber errno
|
||||
#define closesocket close
|
||||
@ -94,7 +97,7 @@ Socket::~Socket()
|
||||
void Socket::shutdown()
|
||||
{
|
||||
isShutdown_ = true;
|
||||
::shutdown(getFd(), 2);
|
||||
::shutdown(getFd(), SHUT_RDWR);
|
||||
}
|
||||
|
||||
bool Socket::isShutdown() const
|
||||
@ -149,7 +152,7 @@ void SocketListener::shutdown()
|
||||
closesocket(fd);
|
||||
fd = -1;
|
||||
#else
|
||||
::shutdown(fd, 2);
|
||||
::shutdown(fd, SHUT_RDWR);
|
||||
#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})
|
||||
|
||||
add_library(rdr STATIC
|
||||
BufferedInStream.cxx
|
||||
BufferedOutStream.cxx
|
||||
Exception.cxx
|
||||
FdInStream.cxx
|
||||
FdOutStream.cxx
|
||||
|
@ -36,13 +36,6 @@
|
||||
#include <unistd.h>
|
||||
#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 */
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
@ -53,31 +46,22 @@
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 8192,
|
||||
MIN_BULK_SIZE = 1024 };
|
||||
enum { DEFAULT_BUF_SIZE = 8192 };
|
||||
|
||||
FdInStream::FdInStream(int fd_, int timeoutms_, size_t bufSize_,
|
||||
FdInStream::FdInStream(int fd_, int timeoutms_,
|
||||
bool closeWhenDone_)
|
||||
: fd(fd_), closeWhenDone(closeWhenDone_),
|
||||
timeoutms(timeoutms_), blockCallback(0),
|
||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||
timeoutms(timeoutms_), blockCallback(0)
|
||||
{
|
||||
ptr = end = start = new U8[bufSize];
|
||||
}
|
||||
|
||||
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_,
|
||||
size_t bufSize_)
|
||||
: fd(fd_), timeoutms(0), blockCallback(blockCallback_),
|
||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||
FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_)
|
||||
: fd(fd_), timeoutms(0), blockCallback(blockCallback_)
|
||||
{
|
||||
ptr = end = start = new U8[bufSize];
|
||||
}
|
||||
|
||||
FdInStream::~FdInStream()
|
||||
{
|
||||
delete [] start;
|
||||
if (closeWhenDone) close(fd);
|
||||
}
|
||||
|
||||
@ -92,72 +76,15 @@ void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
@ -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)
|
||||
{
|
||||
struct timeval before, after;
|
||||
if (timing)
|
||||
gettimeofday(&before, 0);
|
||||
|
||||
int n;
|
||||
while (true) {
|
||||
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 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;
|
||||
}
|
||||
|
||||
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__
|
||||
#define __RDR_FDINSTREAM_H__
|
||||
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
namespace rdr {
|
||||
|
||||
@ -33,31 +33,21 @@ namespace rdr {
|
||||
virtual ~FdInStreamBlockCallback() {}
|
||||
};
|
||||
|
||||
class FdInStream : public InStream {
|
||||
class FdInStream : public BufferedInStream {
|
||||
|
||||
public:
|
||||
|
||||
FdInStream(int fd, int timeoutms=-1, size_t bufSize=0,
|
||||
bool closeWhenDone_=false);
|
||||
FdInStream(int fd, FdInStreamBlockCallback* blockCallback,
|
||||
size_t bufSize=0);
|
||||
FdInStream(int fd, int timeoutms=-1, bool closeWhenDone_=false);
|
||||
FdInStream(int fd, FdInStreamBlockCallback* blockCallback);
|
||||
virtual ~FdInStream();
|
||||
|
||||
void setTimeout(int timeoutms);
|
||||
void setBlockCallback(FdInStreamBlockCallback* blockCallback);
|
||||
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:
|
||||
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||
|
||||
size_t readWithTimeoutOrCallback(void* buf, size_t len, bool wait=true);
|
||||
|
||||
int fd;
|
||||
@ -65,11 +55,6 @@ namespace rdr {
|
||||
int timeoutms;
|
||||
FdInStreamBlockCallback* blockCallback;
|
||||
|
||||
bool timing;
|
||||
unsigned int timeWaitedIn100us;
|
||||
unsigned int timedKbits;
|
||||
|
||||
size_t bufSize;
|
||||
size_t offset;
|
||||
U8* start;
|
||||
};
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
/* Old systems have select() in sys/time.h */
|
||||
@ -49,26 +51,19 @@
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||
|
||||
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)
|
||||
FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_)
|
||||
: fd(fd_), blocking(blocking_), timeoutms(timeoutms_)
|
||||
{
|
||||
ptr = start = sentUpTo = new U8[bufSize];
|
||||
end = start + bufSize;
|
||||
|
||||
gettimeofday(&lastWrite, NULL);
|
||||
}
|
||||
|
||||
FdOutStream::~FdOutStream()
|
||||
{
|
||||
try {
|
||||
blocking = true;
|
||||
flush();
|
||||
while (sentUpTo != ptr)
|
||||
flushBuffer(true);
|
||||
} catch (Exception&) {
|
||||
}
|
||||
delete [] start;
|
||||
}
|
||||
|
||||
void FdOutStream::setTimeout(int timeoutms_) {
|
||||
@ -79,82 +74,29 @@ void FdOutStream::setBlocking(bool blocking_) {
|
||||
blocking = blocking_;
|
||||
}
|
||||
|
||||
size_t FdOutStream::length()
|
||||
{
|
||||
return offset + ptr - sentUpTo;
|
||||
}
|
||||
|
||||
int FdOutStream::bufferUsage()
|
||||
{
|
||||
return ptr - sentUpTo;
|
||||
}
|
||||
|
||||
unsigned FdOutStream::getIdleTime()
|
||||
{
|
||||
return rfb::msSince(&lastWrite);
|
||||
}
|
||||
|
||||
void FdOutStream::flush()
|
||||
bool FdOutStream::flushBuffer(bool wait)
|
||||
{
|
||||
while (sentUpTo < ptr) {
|
||||
size_t n = writeWithTimeout((const void*) sentUpTo,
|
||||
ptr - sentUpTo,
|
||||
blocking? timeoutms : 0);
|
||||
size_t n = writeWithTimeout((const void*) sentUpTo,
|
||||
ptr - sentUpTo,
|
||||
(blocking || wait)? timeoutms : 0);
|
||||
|
||||
// Timeout?
|
||||
if (n == 0) {
|
||||
// If non-blocking then we're done here
|
||||
if (!blocking)
|
||||
break;
|
||||
// Timeout?
|
||||
if (n == 0) {
|
||||
// If non-blocking then we're done here
|
||||
if (!blocking && !wait)
|
||||
return false;
|
||||
|
||||
throw TimedOut();
|
||||
}
|
||||
|
||||
sentUpTo += n;
|
||||
offset += n;
|
||||
throw TimedOut();
|
||||
}
|
||||
|
||||
// Managed to flush everything?
|
||||
if (sentUpTo == ptr)
|
||||
ptr = sentUpTo = start;
|
||||
}
|
||||
sentUpTo += n;
|
||||
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -26,38 +26,29 @@
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <rdr/OutStream.h>
|
||||
#include <rdr/BufferedOutStream.h>
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class FdOutStream : public OutStream {
|
||||
class FdOutStream : public BufferedOutStream {
|
||||
|
||||
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();
|
||||
|
||||
void setTimeout(int timeoutms);
|
||||
void setBlocking(bool blocking);
|
||||
int getFd() { return fd; }
|
||||
|
||||
void flush();
|
||||
size_t length();
|
||||
|
||||
int bufferUsage();
|
||||
|
||||
unsigned getIdleTime();
|
||||
|
||||
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);
|
||||
int fd;
|
||||
bool blocking;
|
||||
int timeoutms;
|
||||
size_t bufSize;
|
||||
size_t offset;
|
||||
U8* start;
|
||||
U8* sentUpTo;
|
||||
struct timeval lastWrite;
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,6 @@ FileInStream::FileInStream(const char *fileName)
|
||||
file = fopen(fileName, "rb");
|
||||
if (!file)
|
||||
throw SystemException("fopen", errno);
|
||||
ptr = end = b;
|
||||
}
|
||||
|
||||
FileInStream::~FileInStream(void) {
|
||||
@ -40,50 +39,17 @@ FileInStream::~FileInStream(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileInStream::reset(void) {
|
||||
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()
|
||||
bool FileInStream::fillBuffer(size_t maxSize, bool wait)
|
||||
{
|
||||
if (!file)
|
||||
throw Exception("File is not open");
|
||||
|
||||
return ftell(file) + ptr - b;
|
||||
}
|
||||
|
||||
size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait)
|
||||
{
|
||||
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;
|
||||
size_t n = fread((U8 *)end, 1, maxSize, file);
|
||||
if (n == 0) {
|
||||
if (ferror(file))
|
||||
throw SystemException("fread", errno);
|
||||
if (feof(file))
|
||||
throw EndOfStream();
|
||||
return false;
|
||||
}
|
||||
end += n;
|
||||
|
||||
size_t nAvail;
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
|
||||
return nItems;
|
||||
return true;
|
||||
}
|
||||
|
@ -22,26 +22,21 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class FileInStream : public InStream {
|
||||
class FileInStream : public BufferedInStream {
|
||||
|
||||
public:
|
||||
|
||||
FileInStream(const char *fileName);
|
||||
~FileInStream(void);
|
||||
|
||||
void reset(void);
|
||||
|
||||
size_t pos();
|
||||
|
||||
protected:
|
||||
size_t overrun(size_t itemSize, size_t nItems, bool wait = true);
|
||||
private:
|
||||
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||
|
||||
private:
|
||||
U8 b[131072];
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
|
@ -24,18 +24,14 @@
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
const int DEFAULT_BUF_LEN = 16384;
|
||||
|
||||
static inline int min(int a, int b) {return a<b ? a : b;}
|
||||
|
||||
HexInStream::HexInStream(InStream& is, size_t bufSize_)
|
||||
: bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
|
||||
HexInStream::HexInStream(InStream& is)
|
||||
: in_stream(is)
|
||||
{
|
||||
ptr = end = start = new U8[bufSize];
|
||||
}
|
||||
|
||||
HexInStream::~HexInStream() {
|
||||
delete [] start;
|
||||
}
|
||||
|
||||
|
||||
@ -76,44 +72,24 @@ decodeError:
|
||||
}
|
||||
|
||||
|
||||
size_t HexInStream::pos() {
|
||||
return offset + ptr - start;
|
||||
}
|
||||
bool HexInStream::fillBuffer(size_t maxSize, bool wait) {
|
||||
if (!in_stream.check(2, wait))
|
||||
return false;
|
||||
|
||||
size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) {
|
||||
if (itemSize > bufSize)
|
||||
throw Exception("HexInStream overrun: max itemSize exceeded");
|
||||
const U8* iptr = in_stream.getptr();
|
||||
const U8* eptr = in_stream.getend();
|
||||
size_t length = min((eptr - iptr)/2, maxSize);
|
||||
|
||||
if (end - ptr != 0)
|
||||
memmove(start, ptr, end - ptr);
|
||||
|
||||
end -= ptr - start;
|
||||
offset += ptr - start;
|
||||
ptr = start;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
size_t nAvail;
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
in_stream.setptr(iptr + length*2);
|
||||
end += length;
|
||||
|
||||
return nItems;
|
||||
return true;
|
||||
}
|
||||
|
@ -19,29 +19,23 @@
|
||||
#ifndef __RDR_HEX_INSTREAM_H__
|
||||
#define __RDR_HEX_INSTREAM_H__
|
||||
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class HexInStream : public InStream {
|
||||
class HexInStream : public BufferedInStream {
|
||||
public:
|
||||
|
||||
HexInStream(InStream& is, size_t bufSize=0);
|
||||
HexInStream(InStream& is);
|
||||
virtual ~HexInStream();
|
||||
|
||||
size_t pos();
|
||||
|
||||
static bool readHexAndShift(char c, int* v);
|
||||
static bool hexStrToBin(const char* s, char** data, size_t* length);
|
||||
|
||||
protected:
|
||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
||||
private:
|
||||
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||
|
||||
private:
|
||||
size_t bufSize;
|
||||
U8* start;
|
||||
size_t offset;
|
||||
|
||||
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;}
|
||||
|
||||
HexOutStream::HexOutStream(OutStream& os, size_t buflen)
|
||||
: out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
|
||||
HexOutStream::HexOutStream(OutStream& os)
|
||||
: out_stream(os), offset(0), bufSize(DEFAULT_BUF_LEN)
|
||||
{
|
||||
if (bufSize % 2)
|
||||
bufSize--;
|
||||
@ -95,18 +95,10 @@ HexOutStream::flush() {
|
||||
out_stream.flush();
|
||||
}
|
||||
|
||||
size_t
|
||||
HexOutStream::overrun(size_t itemSize, size_t nItems) {
|
||||
if (itemSize > bufSize)
|
||||
throw Exception("HexOutStream overrun: max itemSize exceeded");
|
||||
void HexOutStream::overrun(size_t needed) {
|
||||
if (needed > bufSize)
|
||||
throw Exception("HexOutStream overrun: buffer size exceeded");
|
||||
|
||||
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 {
|
||||
public:
|
||||
|
||||
HexOutStream(OutStream& os, size_t buflen=0);
|
||||
HexOutStream(OutStream& os);
|
||||
virtual ~HexOutStream();
|
||||
|
||||
void flush();
|
||||
@ -37,7 +37,7 @@ namespace rdr {
|
||||
|
||||
private:
|
||||
void writeBuffer();
|
||||
size_t overrun(size_t itemSize, size_t nItems);
|
||||
virtual void overrun(size_t needed);
|
||||
|
||||
OutStream& out_stream;
|
||||
|
||||
|
@ -35,28 +35,25 @@ namespace rdr {
|
||||
|
||||
virtual ~InStream() {}
|
||||
|
||||
// check() ensures there is buffer data for at least one item of size
|
||||
// itemSize bytes. Returns the number of items in the buffer (up to a
|
||||
// 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.
|
||||
// avail() returns the number of bytes that are currenctly directly
|
||||
// available from the stream.
|
||||
|
||||
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)
|
||||
return 0;
|
||||
// check() ensures there is buffer data for at least needed bytes. Returns
|
||||
// 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))
|
||||
return overrun(itemSize, nItems, wait);
|
||||
inline size_t check(size_t needed, bool wait=true)
|
||||
{
|
||||
if (needed > avail())
|
||||
return overrun(needed, wait);
|
||||
|
||||
// itemSize cannot be zero at this point
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
|
||||
return nItems;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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).
|
||||
// If length is zero, checkNoWait() will return true.
|
||||
|
||||
inline bool checkNoWait(size_t length)
|
||||
{
|
||||
return length == 0 || check(length, 1, false) > 0;
|
||||
}
|
||||
inline bool checkNoWait(size_t length) { return check(length, false); }
|
||||
|
||||
// readU/SN() methods read unsigned and signed N-bit integers.
|
||||
|
||||
@ -138,13 +132,12 @@ namespace rdr {
|
||||
private:
|
||||
|
||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||
// It ensures there are at least itemSize bytes of buffer data. Returns
|
||||
// the number of items in the buffer (up to a maximum of nItems). itemSize
|
||||
// is supposed to be "small" (a few bytes). If wait is false, then
|
||||
// instead of blocking to wait for the bytes, zero is returned if the bytes
|
||||
// are not immediately available.
|
||||
// It ensures there are at least needed bytes of buffer data. Returns 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.
|
||||
|
||||
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:
|
||||
|
||||
|
@ -53,7 +53,7 @@ namespace rdr {
|
||||
|
||||
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;
|
||||
bool deleteWhenDone;
|
||||
};
|
||||
|
@ -41,12 +41,6 @@ namespace rdr {
|
||||
delete [] start;
|
||||
}
|
||||
|
||||
void writeBytes(const void* data, size_t length) {
|
||||
check(length);
|
||||
memcpy(ptr, data, length);
|
||||
ptr += length;
|
||||
}
|
||||
|
||||
size_t length() { return ptr - start; }
|
||||
void clear() { ptr = start; };
|
||||
void clearAndZero() { memset(start, 0, ptr-start); clear(); }
|
||||
@ -58,11 +52,11 @@ namespace rdr {
|
||||
|
||||
protected:
|
||||
|
||||
// overrun() either doubles the buffer or adds enough space for nItems of
|
||||
// size itemSize bytes.
|
||||
// overrun() either doubles the buffer or adds enough space for
|
||||
// needed bytes.
|
||||
|
||||
size_t overrun(size_t itemSize, size_t nItems) {
|
||||
size_t len = ptr - start + itemSize * nItems;
|
||||
virtual void overrun(size_t needed) {
|
||||
size_t len = ptr - start + needed;
|
||||
if (len < (size_t)(end - start) * 2)
|
||||
len = (end - start) * 2;
|
||||
|
||||
@ -75,8 +69,6 @@ namespace rdr {
|
||||
delete [] start;
|
||||
start = newStart;
|
||||
end = newStart + len;
|
||||
|
||||
return nItems;
|
||||
}
|
||||
|
||||
U8* start;
|
||||
|
@ -40,22 +40,20 @@ namespace rdr {
|
||||
|
||||
virtual ~OutStream() {}
|
||||
|
||||
// check() ensures there is buffer space for at least one item of size
|
||||
// itemSize bytes. Returns the number of items which fit (up to a maximum
|
||||
// of nItems).
|
||||
// avail() returns the number of bytes that currently be written to the
|
||||
// stream without any risk of blocking.
|
||||
|
||||
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))
|
||||
return overrun(itemSize, nItems);
|
||||
// check() ensures there is buffer space for at least needed bytes.
|
||||
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
|
||||
return nItems;
|
||||
inline void check(size_t needed)
|
||||
{
|
||||
if (needed > avail())
|
||||
overrun(needed);
|
||||
}
|
||||
|
||||
// writeU/SN() methods write unsigned and signed N-bit integers.
|
||||
@ -83,19 +81,14 @@ namespace rdr {
|
||||
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.
|
||||
|
||||
void writeBytes(const void* data, size_t length) {
|
||||
while (length > 0) {
|
||||
size_t n = check(1, length);
|
||||
check(1);
|
||||
size_t n = length;
|
||||
if (length > avail())
|
||||
n = avail();
|
||||
memcpy(ptr, data, n);
|
||||
ptr += n;
|
||||
data = (U8*)data + n;
|
||||
@ -107,7 +100,10 @@ namespace rdr {
|
||||
|
||||
void copyBytes(InStream* is, size_t length) {
|
||||
while (length > 0) {
|
||||
size_t n = check(1, length);
|
||||
check(1);
|
||||
size_t n = length;
|
||||
if (length > avail())
|
||||
n = avail();
|
||||
is->readBytes(ptr, n);
|
||||
ptr += n;
|
||||
length -= n;
|
||||
@ -143,11 +139,9 @@ namespace rdr {
|
||||
private:
|
||||
|
||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
||||
// It ensures there are at least itemSize bytes of buffer space. Returns
|
||||
// the number of items which fit (up to a maximum of nItems). itemSize is
|
||||
// supposed to be "small" (a few bytes).
|
||||
// It ensures there are at least needed bytes of buffer space.
|
||||
|
||||
virtual size_t overrun(size_t itemSize, size_t nItems) = 0;
|
||||
virtual void overrun(size_t needed) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -32,15 +32,10 @@
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
const size_t DEFAULT_BUF_LEN = 256;
|
||||
|
||||
unsigned int RandomStream::seed;
|
||||
|
||||
RandomStream::RandomStream()
|
||||
: offset(0)
|
||||
{
|
||||
ptr = end = start = new U8[DEFAULT_BUF_LEN];
|
||||
|
||||
#ifdef RFB_HAVE_WINCRYPT
|
||||
provider = 0;
|
||||
if (!CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL, 0)) {
|
||||
@ -72,8 +67,6 @@ RandomStream::RandomStream()
|
||||
}
|
||||
|
||||
RandomStream::~RandomStream() {
|
||||
delete [] start;
|
||||
|
||||
#ifdef RFB_HAVE_WINCRYPT
|
||||
if (provider)
|
||||
CryptReleaseContext(provider, 0);
|
||||
@ -83,50 +76,29 @@ RandomStream::~RandomStream() {
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t RandomStream::pos() {
|
||||
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;
|
||||
|
||||
bool RandomStream::fillBuffer(size_t maxSize, bool wait) {
|
||||
#ifdef RFB_HAVE_WINCRYPT
|
||||
if (provider) {
|
||||
if (!CryptGenRandom(provider, length, (U8*)end))
|
||||
if (!CryptGenRandom(provider, maxSize, (U8*)end))
|
||||
throw rdr::SystemException("unable to CryptGenRandom", GetLastError());
|
||||
end += length;
|
||||
end += maxSize;
|
||||
} else {
|
||||
#else
|
||||
#ifndef WIN32
|
||||
if (fp) {
|
||||
size_t n = fread((U8*)end, length, 1, fp);
|
||||
if (n != 1)
|
||||
size_t n = fread((U8*)end, 1, maxSize, fp);
|
||||
if (n <= 0)
|
||||
throw rdr::SystemException("reading /dev/urandom or /dev/random failed",
|
||||
errno);
|
||||
end += length;
|
||||
end += n;
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#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));
|
||||
}
|
||||
|
||||
size_t nAvail;
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
|
||||
return nItems;
|
||||
return true;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define __RDR_RANDOMSTREAM_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
@ -32,22 +32,17 @@
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class RandomStream : public InStream {
|
||||
class RandomStream : public BufferedInStream {
|
||||
|
||||
public:
|
||||
|
||||
RandomStream();
|
||||
virtual ~RandomStream();
|
||||
|
||||
size_t pos();
|
||||
|
||||
protected:
|
||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
||||
private:
|
||||
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||
|
||||
private:
|
||||
U8* start;
|
||||
size_t offset;
|
||||
|
||||
static unsigned int seed;
|
||||
#ifdef RFB_HAVE_WINCRYPT
|
||||
HCRYPTPROV provider;
|
||||
|
@ -30,21 +30,19 @@
|
||||
#ifdef HAVE_GNUTLS
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||
|
||||
ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
|
||||
{
|
||||
TLSInStream* self= (TLSInStream*) str;
|
||||
InStream *in = self->in;
|
||||
|
||||
try {
|
||||
if (!in->check(1, 1, false)) {
|
||||
if (!in->check(1, false)) {
|
||||
gnutls_transport_set_errno(self->session, EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size_t)(in->getend() - in->getptr()) < size)
|
||||
size = in->getend() - in->getptr();
|
||||
if (in->avail() < size)
|
||||
size = in->avail();
|
||||
|
||||
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)
|
||||
: session(_session), in(_in), bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||
: session(_session), in(_in)
|
||||
{
|
||||
gnutls_transport_ptr_t recv, send;
|
||||
|
||||
ptr = end = start = new U8[bufSize];
|
||||
|
||||
gnutls_transport_set_pull_function(session, pull);
|
||||
gnutls_transport_get_ptr2(session, &recv, &send);
|
||||
gnutls_transport_set_ptr2(session, this, send);
|
||||
@ -71,40 +67,16 @@ TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
|
||||
TLSInStream::~TLSInStream()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (gnutls_record_check_pending(session) == 0) {
|
||||
n = in->check(1, 1, wait);
|
||||
n = in->check(1, wait);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,27 +27,22 @@
|
||||
#ifdef HAVE_GNUTLS
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class TLSInStream : public InStream {
|
||||
class TLSInStream : public BufferedInStream {
|
||||
public:
|
||||
TLSInStream(InStream* in, gnutls_session_t session);
|
||||
virtual ~TLSInStream();
|
||||
|
||||
size_t pos();
|
||||
|
||||
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);
|
||||
static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size);
|
||||
|
||||
gnutls_session_t session;
|
||||
InStream* in;
|
||||
size_t bufSize;
|
||||
size_t offset;
|
||||
U8* start;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -93,19 +93,12 @@ void TLSOutStream::flush()
|
||||
out->flush();
|
||||
}
|
||||
|
||||
size_t TLSOutStream::overrun(size_t itemSize, size_t nItems)
|
||||
void TLSOutStream::overrun(size_t needed)
|
||||
{
|
||||
if (itemSize > bufSize)
|
||||
throw Exception("TLSOutStream overrun: max itemSize exceeded");
|
||||
if (needed > bufSize)
|
||||
throw Exception("TLSOutStream overrun: buffer size exceeded");
|
||||
|
||||
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)
|
||||
|
@ -39,7 +39,7 @@ namespace rdr {
|
||||
size_t length();
|
||||
|
||||
protected:
|
||||
size_t overrun(size_t itemSize, size_t nItems);
|
||||
virtual void overrun(size_t needed);
|
||||
|
||||
private:
|
||||
size_t writeTLS(const U8* data, size_t length);
|
||||
|
@ -24,41 +24,30 @@
|
||||
|
||||
using namespace rdr;
|
||||
|
||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
||||
|
||||
ZlibInStream::ZlibInStream(size_t bufSize_)
|
||||
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
|
||||
zs(NULL), bytesIn(0)
|
||||
ZlibInStream::ZlibInStream()
|
||||
: underlying(0), zs(NULL), bytesIn(0)
|
||||
{
|
||||
ptr = end = start = new U8[bufSize];
|
||||
init();
|
||||
}
|
||||
|
||||
ZlibInStream::~ZlibInStream()
|
||||
{
|
||||
deinit();
|
||||
delete [] start;
|
||||
}
|
||||
|
||||
void ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_)
|
||||
{
|
||||
underlying = is;
|
||||
bytesIn = bytesIn_;
|
||||
ptr = end = start;
|
||||
}
|
||||
|
||||
size_t ZlibInStream::pos()
|
||||
{
|
||||
return offset + ptr - start;
|
||||
skip(avail());
|
||||
}
|
||||
|
||||
void ZlibInStream::flushUnderlying()
|
||||
{
|
||||
ptr = end = start;
|
||||
|
||||
while (bytesIn > 0) {
|
||||
decompress(true);
|
||||
end = start; // throw away any data
|
||||
if (!check(1))
|
||||
throw Exception("ZlibInStream: failed to flush remaining stream data");
|
||||
skip(avail());
|
||||
}
|
||||
|
||||
setUnderlying(NULL, 0);
|
||||
@ -96,47 +85,18 @@ void ZlibInStream::deinit()
|
||||
zs = NULL;
|
||||
}
|
||||
|
||||
size_t ZlibInStream::overrun(size_t itemSize, size_t nItems, 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)
|
||||
bool ZlibInStream::fillBuffer(size_t maxSize, bool wait)
|
||||
{
|
||||
if (!underlying)
|
||||
throw Exception("ZlibInStream overrun: no underlying stream");
|
||||
|
||||
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;
|
||||
zs->next_in = (U8*)underlying->getptr();
|
||||
zs->avail_in = underlying->getend() - underlying->getptr();
|
||||
zs->avail_in = underlying->avail();
|
||||
if (zs->avail_in > bytesIn)
|
||||
zs->avail_in = bytesIn;
|
||||
|
||||
|
@ -24,38 +24,32 @@
|
||||
#ifndef __RDR_ZLIBINSTREAM_H__
|
||||
#define __RDR_ZLIBINSTREAM_H__
|
||||
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/BufferedInStream.h>
|
||||
|
||||
struct z_stream_s;
|
||||
|
||||
namespace rdr {
|
||||
|
||||
class ZlibInStream : public InStream {
|
||||
class ZlibInStream : public BufferedInStream {
|
||||
|
||||
public:
|
||||
|
||||
ZlibInStream(size_t bufSize=0);
|
||||
ZlibInStream();
|
||||
virtual ~ZlibInStream();
|
||||
|
||||
void setUnderlying(InStream* is, size_t bytesIn);
|
||||
void flushUnderlying();
|
||||
size_t pos();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
size_t overrun(size_t itemSize, size_t nItems, bool wait);
|
||||
bool decompress(bool wait);
|
||||
virtual bool fillBuffer(size_t maxSize, bool wait);
|
||||
|
||||
private:
|
||||
InStream* underlying;
|
||||
size_t bufSize;
|
||||
size_t offset;
|
||||
z_stream_s* zs;
|
||||
size_t bytesIn;
|
||||
U8* start;
|
||||
};
|
||||
|
||||
} // end of namespace rdr
|
||||
|
@ -30,9 +30,9 @@ using namespace rdr;
|
||||
|
||||
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),
|
||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
||||
bufSize(DEFAULT_BUF_SIZE), offset(0)
|
||||
{
|
||||
zs = new z_stream;
|
||||
zs->zalloc = Z_NULL;
|
||||
@ -95,18 +95,18 @@ void ZlibOutStream::flush()
|
||||
ptr = start;
|
||||
}
|
||||
|
||||
size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems)
|
||||
void ZlibOutStream::overrun(size_t needed)
|
||||
{
|
||||
#ifdef ZLIBOUT_DEBUG
|
||||
fprintf(stderr,"zos overrun\n");
|
||||
#endif
|
||||
|
||||
if (itemSize > bufSize)
|
||||
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
|
||||
if (needed > bufSize)
|
||||
throw Exception("ZlibOutStream overrun: buffer size exceeded");
|
||||
|
||||
checkCompressionLevel();
|
||||
|
||||
while ((size_t)(end - ptr) < itemSize) {
|
||||
while (avail() < needed) {
|
||||
zs->next_in = 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;
|
||||
}
|
||||
}
|
||||
|
||||
size_t nAvail;
|
||||
nAvail = (end - ptr) / itemSize;
|
||||
if (nAvail < nItems)
|
||||
return nAvail;
|
||||
|
||||
return nItems;
|
||||
}
|
||||
|
||||
void ZlibOutStream::deflate(int flush)
|
||||
@ -148,7 +141,7 @@ void ZlibOutStream::deflate(int flush)
|
||||
do {
|
||||
underlying->check(1);
|
||||
zs->next_out = underlying->getptr();
|
||||
zs->avail_out = underlying->getend() - underlying->getptr();
|
||||
zs->avail_out = underlying->avail();
|
||||
|
||||
#ifdef ZLIBOUT_DEBUG
|
||||
fprintf(stderr,"zos: calling deflate, avail_in %d, avail_out %d\n",
|
||||
|
@ -35,7 +35,7 @@ namespace rdr {
|
||||
|
||||
public:
|
||||
|
||||
ZlibOutStream(OutStream* os=0, size_t bufSize=0, int compressionLevel=-1);
|
||||
ZlibOutStream(OutStream* os=0, int compressionLevel=-1);
|
||||
virtual ~ZlibOutStream();
|
||||
|
||||
void setUnderlying(OutStream* os);
|
||||
@ -45,7 +45,7 @@ namespace rdr {
|
||||
|
||||
private:
|
||||
|
||||
size_t overrun(size_t itemSize, size_t nItems);
|
||||
virtual void overrun(size_t needed);
|
||||
void deflate(int flush);
|
||||
void checkCompressionLevel();
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/fenceTypes.h>
|
||||
#include <rfb/CMsgReader.h>
|
||||
#include <rfb/CMsgWriter.h>
|
||||
@ -42,7 +43,8 @@ CConnection::CConnection()
|
||||
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
|
||||
shared(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;
|
||||
delete writer_;
|
||||
writer_ = 0;
|
||||
strFree(serverClipboard);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
@ -364,3 +440,53 @@ void CConnection::fence(rdr::U32 flags, unsigned len, const char 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 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
|
||||
|
||||
@ -121,9 +132,43 @@ namespace rfb {
|
||||
// derived class must call on to CConnection::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
|
||||
|
||||
// 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_; }
|
||||
CMsgWriter* writer() { return writer_; }
|
||||
|
||||
@ -190,6 +235,9 @@ namespace rfb {
|
||||
|
||||
ModifiablePixelBuffer* framebuffer;
|
||||
DecodeManager decoder;
|
||||
|
||||
char* serverClipboard;
|
||||
bool hasLocalClipboard;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -92,3 +92,26 @@ void CMsgHandler::setLEDState(unsigned int 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 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;
|
||||
};
|
||||
}
|
||||
|
@ -18,10 +18,14 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <rdr/OutStream.h>
|
||||
#include <rdr/MemOutStream.h>
|
||||
#include <rdr/ZlibOutStream.h>
|
||||
|
||||
#include <rfb/msgTypes.h>
|
||||
#include <rfb/fenceTypes.h>
|
||||
#include <rfb/encodings.h>
|
||||
#include <rfb/qemuTypes.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/PixelFormat.h>
|
||||
#include <rfb/Rect.h>
|
||||
@ -57,7 +61,7 @@ void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
|
||||
void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
|
||||
{
|
||||
startMsg(msgTypeSetEncodings);
|
||||
os->skip(1);
|
||||
os->pad(1);
|
||||
os->writeU16(nEncodings);
|
||||
for (int i = 0; i < nEncodings; i++)
|
||||
os->writeU32(encodings[i]);
|
||||
@ -265,6 +269,104 @@ void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
|
||||
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)
|
||||
{
|
||||
os->writeU8(type);
|
||||
|
@ -56,6 +56,13 @@ namespace rfb {
|
||||
void writePointerEvent(const Point& pos, int buttonMask);
|
||||
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:
|
||||
void startMsg(int type);
|
||||
void endMsg();
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/encodings.h>
|
||||
#include <rfb/ledStates.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/ConnParams.h>
|
||||
#include <rfb/ServerCore.h>
|
||||
#include <rfb/SMsgHandler.h>
|
||||
@ -36,19 +37,25 @@ ConnParams::ConnParams()
|
||||
width(0), height(0), useCopyRect(false),
|
||||
supportsLocalCursor(false), supportsLocalXCursor(false),
|
||||
supportsLocalCursorWithAlpha(false),
|
||||
supportsCursorPosition(false),
|
||||
supportsDesktopResize(false), supportsExtendedDesktopSize(false),
|
||||
supportsDesktopRename(false), supportsLastRect(false),
|
||||
supportsLEDState(false), supportsQEMUKeyEvent(false),
|
||||
supportsWEBP(false),
|
||||
supportsSetDesktopSize(false), supportsFence(false),
|
||||
supportsContinuousUpdates(false),
|
||||
supportsContinuousUpdates(false), supportsExtendedClipboard(false),
|
||||
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)
|
||||
{
|
||||
memset(kasmPassed, 0, KASM_NUM_SETTINGS);
|
||||
setName("");
|
||||
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()
|
||||
@ -101,6 +108,11 @@ void ConnParams::setCursor(const Cursor& other)
|
||||
cursor_ = new Cursor(other);
|
||||
}
|
||||
|
||||
void ConnParams::setCursorPos(const Point& pos)
|
||||
{
|
||||
cursorPos_ = pos;
|
||||
}
|
||||
|
||||
bool ConnParams::supportsEncoding(rdr::S32 encoding) const
|
||||
{
|
||||
return encodings_.count(encoding) != 0;
|
||||
@ -147,6 +159,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
case pseudoEncodingExtendedDesktopSize:
|
||||
supportsExtendedDesktopSize = true;
|
||||
break;
|
||||
case pseudoEncodingVMwareCursorPosition:
|
||||
supportsCursorPosition = true;
|
||||
break;
|
||||
case pseudoEncodingDesktopName:
|
||||
supportsDesktopRename = true;
|
||||
break;
|
||||
@ -168,6 +183,9 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
case pseudoEncodingContinuousUpdates:
|
||||
supportsContinuousUpdates = true;
|
||||
break;
|
||||
case pseudoEncodingExtendedClipboard:
|
||||
supportsExtendedClipboard = true;
|
||||
break;
|
||||
case pseudoEncodingSubsamp1X:
|
||||
subsampling = subsampleNone;
|
||||
break;
|
||||
@ -259,3 +277,17 @@ void ConnParams::setLEDState(unsigned int 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_; }
|
||||
void setCursor(const Cursor& cursor);
|
||||
|
||||
const Point& cursorPos() const { return cursorPos_; }
|
||||
void setCursorPos(const Point& pos);
|
||||
|
||||
bool supportsEncoding(rdr::S32 encoding) const;
|
||||
|
||||
void setEncodings(int nEncodings, const rdr::S32* encodings);
|
||||
@ -91,11 +94,15 @@ namespace rfb {
|
||||
unsigned int ledState() { return ledState_; }
|
||||
void setLEDState(unsigned int state);
|
||||
|
||||
rdr::U32 clipboardFlags() const { return clipFlags; }
|
||||
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);
|
||||
|
||||
bool useCopyRect;
|
||||
|
||||
bool supportsLocalCursor;
|
||||
bool supportsLocalXCursor;
|
||||
bool supportsLocalCursorWithAlpha;
|
||||
bool supportsCursorPosition;
|
||||
bool supportsDesktopResize;
|
||||
bool supportsExtendedDesktopSize;
|
||||
bool supportsDesktopRename;
|
||||
@ -107,6 +114,7 @@ namespace rfb {
|
||||
bool supportsSetDesktopSize;
|
||||
bool supportsFence;
|
||||
bool supportsContinuousUpdates;
|
||||
bool supportsExtendedClipboard;
|
||||
|
||||
int compressLevel;
|
||||
int qualityLevel;
|
||||
@ -136,11 +144,14 @@ namespace rfb {
|
||||
PixelFormat pf_;
|
||||
char* name_;
|
||||
Cursor* cursor_;
|
||||
Point cursorPos_;
|
||||
std::set<rdr::S32> encodings_;
|
||||
char verStr[13];
|
||||
int verStrPos;
|
||||
unsigned int ledState_;
|
||||
SMsgHandler *shandler;
|
||||
rdr::U32 clipFlags;
|
||||
rdr::U32 clipSizes[16];
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -85,7 +85,7 @@ JpegInitDestination(j_compress_ptr cinfo)
|
||||
|
||||
jc->clear();
|
||||
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
|
||||
@ -95,9 +95,9 @@ JpegEmptyOutputBuffer(j_compress_ptr cinfo)
|
||||
JpegCompressor *jc = dest->instance;
|
||||
|
||||
jc->setptr(jc->getend());
|
||||
jc->overrun(jc->getend() - jc->getstart(), 1);
|
||||
jc->check(jc->length());
|
||||
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;
|
||||
}
|
||||
|
@ -47,12 +47,6 @@ namespace rfb {
|
||||
|
||||
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:
|
||||
|
||||
struct jpeg_compress_struct *cinfo;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/Security.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/msgTypes.h>
|
||||
#include <rfb/fenceTypes.h>
|
||||
#include <rfb/SMsgReader.h>
|
||||
@ -52,7 +53,8 @@ SConnection::SConnection()
|
||||
: readyForSetColourMapEntries(false),
|
||||
is(0), os(0), reader_(0), writer_(0),
|
||||
ssecurity(0), state_(RFBSTATE_UNINITIALISED),
|
||||
preferredEncoding(encodingRaw)
|
||||
preferredEncoding(encodingRaw),
|
||||
clientClipboard(NULL), hasLocalClipboard(false)
|
||||
{
|
||||
defaultMajorVersion = 3;
|
||||
defaultMinorVersion = 8;
|
||||
@ -69,6 +71,7 @@ SConnection::~SConnection()
|
||||
reader_ = 0;
|
||||
delete writer_;
|
||||
writer_ = 0;
|
||||
strFree(clientClipboard);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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()
|
||||
@ -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)
|
||||
{
|
||||
int i;
|
||||
|
@ -73,6 +73,15 @@ namespace rfb {
|
||||
|
||||
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();
|
||||
|
||||
// Methods to be overridden in a derived class
|
||||
@ -118,6 +127,25 @@ namespace rfb {
|
||||
virtual void enableContinuousUpdates(bool enable,
|
||||
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() {}
|
||||
|
||||
// setAccessRights() allows a security package to limit the access rights
|
||||
@ -138,6 +166,22 @@ namespace rfb {
|
||||
|
||||
// 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
|
||||
// successfully.
|
||||
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
|
||||
@ -203,6 +247,9 @@ namespace rfb {
|
||||
SSecurity* ssecurity;
|
||||
stateEnum state_;
|
||||
rdr::S32 preferredEncoding;
|
||||
|
||||
char* clientClipboard;
|
||||
bool hasLocalClipboard;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -77,6 +77,25 @@ namespace rfb {
|
||||
// pointerEvent(), keyEvent() and clientCutText() are called in response to
|
||||
// the relevant RFB protocol messages from clients.
|
||||
// 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:
|
||||
virtual ~SDesktop() {}
|
||||
};
|
||||
|
@ -64,6 +64,29 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
@ -54,6 +54,15 @@ namespace rfb {
|
||||
virtual void enableContinuousUpdates(bool enable,
|
||||
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 bool canChangeKasmSettings() const = 0;
|
||||
|
@ -18,8 +18,11 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <rdr/InStream.h>
|
||||
#include <rdr/ZlibInStream.h>
|
||||
|
||||
#include <rfb/msgTypes.h>
|
||||
#include <rfb/qemuTypes.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/util.h>
|
||||
#include <rfb/SMsgHandler.h>
|
||||
@ -224,11 +227,15 @@ void SMsgReader::readPointerEvent()
|
||||
void SMsgReader::readClientCutText()
|
||||
{
|
||||
is->skip(3);
|
||||
int len = is->readU32();
|
||||
if (len < 0) {
|
||||
throw Exception("Cut text too long.");
|
||||
rdr::U32 len = is->readU32();
|
||||
|
||||
if (len & 0x80000000) {
|
||||
rdr::S32 slen = len;
|
||||
slen = -slen;
|
||||
readExtendedClipboard(slen);
|
||||
return;
|
||||
}
|
||||
if (len > maxCutText) {
|
||||
if (len > (size_t)maxCutText) {
|
||||
is->skip(len);
|
||||
vlog.error("Cut text too long (%d bytes) - ignoring", len);
|
||||
return;
|
||||
@ -239,6 +246,100 @@ void SMsgReader::readClientCutText()
|
||||
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()
|
||||
{
|
||||
is->skip(3);
|
||||
|
@ -55,6 +55,7 @@ namespace rfb {
|
||||
void readKeyEvent();
|
||||
void readPointerEvent();
|
||||
void readClientCutText();
|
||||
void readExtendedClipboard(rdr::S32 len);
|
||||
void readRequestStats();
|
||||
|
||||
void readQEMUMessage();
|
||||
|
@ -19,8 +19,12 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <rdr/OutStream.h>
|
||||
#include <rdr/MemOutStream.h>
|
||||
#include <rdr/ZlibOutStream.h>
|
||||
|
||||
#include <rfb/msgTypes.h>
|
||||
#include <rfb/fenceTypes.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/ConnParams.h>
|
||||
#include <rfb/UpdateTracker.h>
|
||||
@ -39,6 +43,7 @@ SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
|
||||
needSetDesktopSize(false), needExtendedDesktopSize(false),
|
||||
needSetDesktopName(false), needSetCursor(false),
|
||||
needSetXCursor(false), needSetCursorWithAlpha(false),
|
||||
needCursorPos(false),
|
||||
needLEDState(false), needQEMUKeyEvent(false)
|
||||
{
|
||||
}
|
||||
@ -88,6 +93,112 @@ void SMsgWriter::writeServerCutText(const char* str, int len)
|
||||
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)
|
||||
{
|
||||
startMsg(msgTypeStats);
|
||||
@ -204,6 +315,14 @@ bool SMsgWriter::writeSetCursorWithAlpha()
|
||||
return true;
|
||||
}
|
||||
|
||||
void SMsgWriter::writeCursorPos()
|
||||
{
|
||||
if (!cp->supportsEncoding(pseudoEncodingVMwareCursorPosition))
|
||||
throw Exception("Client does not support cursor position");
|
||||
|
||||
needCursorPos = true;
|
||||
}
|
||||
|
||||
bool SMsgWriter::writeLEDState()
|
||||
{
|
||||
if (!cp->supportsLEDState)
|
||||
@ -232,6 +351,8 @@ bool SMsgWriter::needFakeUpdate()
|
||||
return true;
|
||||
if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
|
||||
return true;
|
||||
if (needCursorPos)
|
||||
return true;
|
||||
if (needLEDState)
|
||||
return true;
|
||||
if (needQEMUKeyEvent)
|
||||
@ -284,6 +405,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
|
||||
nRects++;
|
||||
if (needSetCursorWithAlpha)
|
||||
nRects++;
|
||||
if (needCursorPos)
|
||||
nRects++;
|
||||
if (needLEDState)
|
||||
nRects++;
|
||||
if (needQEMUKeyEvent)
|
||||
@ -399,6 +522,18 @@ void SMsgWriter::writePseudoRects()
|
||||
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) {
|
||||
writeSetDesktopNameRect(cp->name());
|
||||
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)
|
||||
{
|
||||
if (!cp->supportsLEDState)
|
||||
|
@ -55,6 +55,14 @@ namespace rfb {
|
||||
// writeBell() and writeServerCutText() do the obvious thing.
|
||||
void writeBell();
|
||||
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);
|
||||
|
||||
// writeFence() sends a new fence request or response to the client.
|
||||
@ -83,6 +91,9 @@ namespace rfb {
|
||||
bool writeSetXCursor();
|
||||
bool writeSetCursorWithAlpha();
|
||||
|
||||
// Notifies the client that the cursor pointer was moved by the server.
|
||||
void writeCursorPos();
|
||||
|
||||
// Same for LED state message
|
||||
bool writeLEDState();
|
||||
|
||||
@ -138,6 +149,7 @@ namespace rfb {
|
||||
void writeSetCursorWithAlphaRect(int width, int height,
|
||||
int hotspotX, int hotspotY,
|
||||
const rdr::U8* data);
|
||||
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);
|
||||
void writeLEDStateRect(rdr::U8 state);
|
||||
void writeQEMUKeyEventRect();
|
||||
|
||||
@ -153,6 +165,7 @@ namespace rfb {
|
||||
bool needSetCursor;
|
||||
bool needSetXCursor;
|
||||
bool needSetCursorWithAlpha;
|
||||
bool needCursorPos;
|
||||
bool needLEDState;
|
||||
bool needQEMUKeyEvent;
|
||||
|
||||
|
@ -35,6 +35,8 @@ namespace rfb {
|
||||
dispatch elapsed Timer callbacks and to determine how long to wait in select() for
|
||||
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 {
|
||||
@ -101,6 +103,19 @@ namespace rfb {
|
||||
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
|
||||
|
@ -155,6 +155,17 @@ void VNCSConnectionST::close(const char* reason)
|
||||
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
|
||||
// calling code will call VNCServerST's removeSocket() method causing us to
|
||||
// be deleted.
|
||||
@ -392,7 +403,31 @@ static void keylog(unsigned keysym, const char *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 {
|
||||
if (!(accessRights & AccessCutText)) return;
|
||||
@ -402,19 +437,19 @@ void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
|
||||
sock->getPeerAddress());
|
||||
return;
|
||||
}
|
||||
int len = strlen(data);
|
||||
const int origlen = len;
|
||||
if (rfb::Server::DLP_ClipSendMax && len > rfb::Server::DLP_ClipSendMax)
|
||||
len = rfb::Server::DLP_ClipSendMax;
|
||||
cliplog(str, len, origlen, "sent", sock->getPeerAddress());
|
||||
if (state() == RFBSTATE_NORMAL)
|
||||
writer()->writeServerCutText(str, len);
|
||||
cliplog(data, len, origlen, "sent", sock->getPeerAddress());
|
||||
if (state() != RFBSTATE_NORMAL) return;
|
||||
sendClipboardData(data, len);
|
||||
gettimeofday(&lastClipboardOp, NULL);
|
||||
} catch(rdr::Exception& e) {
|
||||
close(e.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VNCSConnectionST::setDesktopNameOrClose(const char *name)
|
||||
{
|
||||
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
|
||||
// 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.
|
||||
@ -826,24 +870,6 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool 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)
|
||||
{
|
||||
Rect safeRect;
|
||||
@ -863,7 +889,7 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
|
||||
|
||||
// Just update the requested region.
|
||||
// Framebuffer update will be sent a bit later, see processMessages().
|
||||
Region reqRgn(r);
|
||||
Region reqRgn(safeRect);
|
||||
if (!incremental || !continuousUpdates)
|
||||
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
|
||||
// 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
|
||||
@ -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)
|
||||
{
|
||||
cp.setName(name);
|
||||
|
@ -75,9 +75,11 @@ namespace rfb {
|
||||
void screenLayoutChangeOrClose(rdr::U16 reason);
|
||||
void setCursorOrClose();
|
||||
void bellOrClose();
|
||||
void serverCutTextOrClose(const char *str, int len);
|
||||
void setDesktopNameOrClose(const char *name);
|
||||
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
|
||||
// idle timeout expires. If it has expired, the connection is closed and
|
||||
@ -97,6 +99,11 @@ namespace rfb {
|
||||
// cursor.
|
||||
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
|
||||
// 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.
|
||||
@ -170,13 +177,15 @@ namespace rfb {
|
||||
virtual void setPixelFormat(const PixelFormat& pf);
|
||||
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 clientCutText(const char* str, int len);
|
||||
virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
|
||||
virtual void setDesktopSize(int fb_width, int fb_height,
|
||||
const ScreenSet& layout);
|
||||
virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
|
||||
virtual void enableContinuousUpdates(bool enable,
|
||||
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 supportsFence();
|
||||
virtual void supportsContinuousUpdates();
|
||||
@ -223,6 +232,7 @@ namespace rfb {
|
||||
|
||||
void screenLayoutChange(rdr::U16 reason);
|
||||
void setCursor();
|
||||
void setCursorPos();
|
||||
void setDesktopName(const char *name);
|
||||
void setLEDState(unsigned int state);
|
||||
void setSocketTimeouts();
|
||||
|
@ -52,9 +52,21 @@ namespace rfb {
|
||||
// getPixelBuffer() returns a pointer to the PixelBuffer object.
|
||||
virtual PixelBuffer* getPixelBuffer() const = 0;
|
||||
|
||||
// serverCutText() tells the server that the cut text has changed. This
|
||||
// will normally be sent to all clients.
|
||||
virtual void serverCutText(const char* str, int len) = 0;
|
||||
// requestClipboard() will result in a request to a client to
|
||||
// transfer its clipboard data. A call to
|
||||
// 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.
|
||||
virtual void bell() = 0;
|
||||
@ -69,8 +81,10 @@ namespace rfb {
|
||||
virtual void setCursor(int width, int height, const Point& hotspot,
|
||||
const rdr::U8* cursorData) = 0;
|
||||
|
||||
// setCursorPos() tells the server the current position of the cursor.
|
||||
virtual void setCursorPos(const Point& p) = 0;
|
||||
// setCursorPos() tells the server the current position of the cursor, and
|
||||
// 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
|
||||
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_)
|
||||
: blHosts(&blacklist), desktop(desktop_), desktopStarted(false),
|
||||
blockCounter(0), pb(0), blackedpb(0), ledState(ledUnknown),
|
||||
name(strDup(name_)), pointerClient(0), comparer(0),
|
||||
cursor(new Cursor(0, 0, Point(), NULL)),
|
||||
name(strDup(name_)), pointerClient(0), clipboardClient(0),
|
||||
comparer(0), cursor(new Cursor(0, 0, Point(), NULL)),
|
||||
renderedCursorInvalid(false),
|
||||
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
|
||||
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()
|
||||
{
|
||||
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_)
|
||||
{
|
||||
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)) {
|
||||
cursorPos = pos;
|
||||
renderedCursorInvalid = true;
|
||||
std::list<VNCSConnectionST*>::iterator ci;
|
||||
for (ci = clients.begin(); ci != clients.end(); ci++)
|
||||
for (ci = clients.begin(); ci != clients.end(); ci++) {
|
||||
(*ci)->renderedCursorChange();
|
||||
if (warped)
|
||||
(*ci)->cursorPositionChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1049,3 +1082,32 @@ bool VNCServerST::getComparerState()
|
||||
}
|
||||
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 setScreenLayout(const ScreenSet& layout);
|
||||
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_copied(const Region &dest, const Point &delta);
|
||||
virtual void setCursor(int width, int height, const Point& hotspot,
|
||||
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 bell();
|
||||
@ -189,6 +191,10 @@ namespace rfb {
|
||||
|
||||
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:
|
||||
|
||||
friend class VNCSConnectionST;
|
||||
@ -217,6 +223,8 @@ namespace rfb {
|
||||
|
||||
std::list<VNCSConnectionST*> clients;
|
||||
VNCSConnectionST* pointerClient;
|
||||
VNCSConnectionST* clipboardClient;
|
||||
std::list<VNCSConnectionST*> clipboardRequestors;
|
||||
std::list<network::Socket*> closingSockets;
|
||||
|
||||
static EncCache encCache;
|
||||
|
@ -31,7 +31,7 @@ IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
|
||||
|
||||
ZRLEEncoder::ZRLEEncoder(SConnection* conn)
|
||||
: Encoder(conn, encodingZRLE, EncoderPlain, 127),
|
||||
zos(0,0,zlibLevel), mos(129*1024)
|
||||
zos(0,zlibLevel), mos(129*1024)
|
||||
{
|
||||
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 pseudoEncodingVideoOutTimeLevel100 = -1887;
|
||||
|
||||
// VMware-specific
|
||||
const int pseudoEncodingVMwareCursorPosition = 0x574d5666;
|
||||
|
||||
// UltraVNC-specific
|
||||
const int pseudoEncodingExtendedClipboard = 0xC0A1E5CE;
|
||||
|
||||
int encodingNum(const char* name);
|
||||
const char* encodingName(int num);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2019 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -63,6 +64,10 @@ namespace rfb {
|
||||
delete [] s;
|
||||
}
|
||||
|
||||
void strFree(wchar_t* s) {
|
||||
delete [] s;
|
||||
}
|
||||
|
||||
|
||||
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) {
|
||||
CharArray out1old, out2old;
|
||||
@ -107,6 +112,444 @@ namespace rfb {
|
||||
dest[src ? destlen-1 : 0] = 0;
|
||||
}
|
||||
|
||||
char* convertLF(const char* src, size_t bytes)
|
||||
{
|
||||
char* buffer;
|
||||
size_t sz;
|
||||
|
||||
char* out;
|
||||
const char* in;
|
||||
size_t in_len;
|
||||
|
||||
// Always include space for a NULL
|
||||
sz = 1;
|
||||
|
||||
// Compute output size
|
||||
in = src;
|
||||
in_len = bytes;
|
||||
while ((in_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,
|
||||
const struct timeval *second)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2019 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -67,6 +68,7 @@ namespace rfb {
|
||||
|
||||
char* strDup(const char* s);
|
||||
void strFree(char* s);
|
||||
void strFree(wchar_t* s);
|
||||
|
||||
// Returns true if split successful. Returns false otherwise.
|
||||
// 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
|
||||
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
|
||||
|
||||
|
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 |