Merge branch 'covscan' of https://github.com/grulja/tigervnc
diff --git a/common/network/Socket.h b/common/network/Socket.h
index bfda8a5..d38feba 100644
--- a/common/network/Socket.h
+++ b/common/network/Socket.h
@@ -144,15 +144,6 @@
// This is only necessary if the Socket has been put in non-blocking
// mode and needs this callback to flush the buffer.
virtual void processSocketWriteEvent(network::Socket* sock) = 0;
-
- // checkTimeouts() allows the server to check socket timeouts, etc. The
- // return value is the number of milliseconds to wait before
- // checkTimeouts() should be called again. If this number is zero then
- // there is no timeout and checkTimeouts() should be called the next time
- // an event occurs.
- virtual int checkTimeouts() = 0;
-
- virtual bool getDisable() {return false;};
};
}
diff --git a/common/rdr/SubstitutingInStream.h b/common/rdr/SubstitutingInStream.h
deleted file mode 100644
index 325b01c..0000000
--- a/common/rdr/SubstitutingInStream.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * 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 __RDR_SUBSTITUTINGINSTREAM_H__
-#define __RDR_SUBSTITUTINGINSTREAM_H__
-
-#include <rdr/InStream.h>
-#include <rdr/Exception.h>
-
-namespace rdr {
-
- class Substitutor {
- public:
- virtual char* substitute(const char* varName) = 0;
- };
-
- class SubstitutingInStream : public InStream {
- public:
- SubstitutingInStream(InStream* underlying_, Substitutor* s,
- int maxVarNameLen_)
- : underlying(underlying_), dollar(0), substitutor(s), subst(0),
- maxVarNameLen(maxVarNameLen_)
- {
- ptr = end = underlying->getptr();
- varName = new char[maxVarNameLen+1];
- }
- ~SubstitutingInStream() {
- delete underlying;
- delete [] varName;
- delete [] subst;
- }
-
- int pos() { return underlying->pos(); }
-
- virtual int overrun(int itemSize, int nItems, bool wait=true) {
- if (itemSize != 1)
- throw new rdr::Exception("SubstitutingInStream: itemSize must be 1");
-
- if (subst) {
- delete [] subst;
- subst = 0;
- } else {
- underlying->setptr(ptr);
- }
-
- underlying->check(1);
- ptr = underlying->getptr();
- end = underlying->getend();
- dollar = (const U8*)memchr(ptr, '$', end-ptr);
- if (dollar) {
- if (dollar == ptr) {
- try {
- int i = 0;
- while (i < maxVarNameLen) {
- varName[i++] = underlying->readS8();
- varName[i] = 0;
- subst = substitutor->substitute(varName);
- if (subst) {
- ptr = (U8*)subst;
- end = (U8*)subst + strlen(subst);
- break;
- }
- }
- } catch (EndOfStream&) {
- }
-
- if (!subst)
- dollar = (const U8*)memchr(ptr+1, '$', end-ptr-1);
- }
- if (!subst && dollar) end = dollar;
- }
-
- if (itemSize * nItems > end - ptr)
- nItems = (end - ptr) / itemSize;
-
- return nItems;
- }
-
- InStream* underlying;
- const U8* dollar;
- Substitutor* substitutor;
- char* varName;
- char* subst;
- int maxVarNameLen;
- };
-}
-#endif
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
index 62ef401..b8d0813 100644
--- a/common/rfb/CMakeLists.txt
+++ b/common/rfb/CMakeLists.txt
@@ -21,7 +21,6 @@
d3des.c
EncodeManager.cxx
Encoder.cxx
- HTTPServer.cxx
HextileDecoder.cxx
HextileEncoder.cxx
JpegCompressor.cxx
diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx
index d268202..d6a8d7f 100644
--- a/common/rfb/CSecurityTLS.cxx
+++ b/common/rfb/CSecurityTLS.cxx
@@ -196,6 +196,9 @@
throw AuthFailureException("TLS Handshake failed");
}
+ vlog.debug("TLS handshake completed with %s",
+ gnutls_session_get_desc(session));
+
checkSession();
cc->setStreams(tlsis, tlsos);
diff --git a/common/rfb/HTTPServer.cxx b/common/rfb/HTTPServer.cxx
deleted file mode 100644
index 2895a69..0000000
--- a/common/rfb/HTTPServer.cxx
+++ /dev/null
@@ -1,424 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * 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.
- */
-
-#include <rfb/HTTPServer.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
-#include <rdr/MemOutStream.h>
-
-
-using namespace rfb;
-using namespace rdr;
-
-static LogWriter vlog("HTTPServer");
-
-const int clientWaitTimeMillis = 20000;
-const int idleTimeoutSecs = 5 * 60;
-
-
-//
-// -=- LineReader
-// Helper class which is repeatedly called until a line has been read
-// (lines end in \n or \r\n).
-// Returns true when line complete, and resets internal state so that
-// next read() call will start reading a new line.
-// Only one buffer is kept - process line before reading next line!
-//
-
-class LineReader : public CharArray {
-public:
- LineReader(InStream& is_, int l)
- : CharArray(l), is(is_), pos(0), len(l), bufferOverrun(false) {}
-
- // Returns true if line complete, false otherwise
- bool read() {
- while (is.checkNoWait(1)) {
- char c = is.readU8();
-
- if (c == '\n') {
- if (pos && (buf[pos-1] == '\r'))
- pos--;
- bufferOverrun = false;
- buf[pos++] = 0;
- pos = 0;
- return true;
- }
-
- if (pos == (len-1)) {
- bufferOverrun = true;
- buf[pos] = 0;
- return true;
- }
-
- buf[pos++] = c;
- }
-
- return false;
- }
- bool didBufferOverrun() const {return bufferOverrun;}
-protected:
- InStream& is;
- int pos, len;
- bool bufferOverrun;
-};
-
-
-//
-// -=- HTTPServer::Session
-// Manages the internal state for an HTTP session.
-// processHTTP returns true when request has completed,
-// indicating that socket & session data can be deleted.
-//
-
-class rfb::HTTPServer::Session {
-public:
- Session(network::Socket& s, rfb::HTTPServer& srv)
- : contentType(0), contentLength(-1), lastModified(-1),
- line(s.inStream(), 256), sock(s),
- server(srv), state(ReadRequestLine), lastActive(time(0)) {
- }
- ~Session() {
- }
-
- void writeResponse(int result, const char* text);
- bool writeResponse(int code);
-
- bool processHTTP();
-
- network::Socket* getSock() const {return &sock;}
-
- int checkIdleTimeout();
-protected:
- CharArray uri;
- const char* contentType;
- int contentLength;
- time_t lastModified;
- LineReader line;
- network::Socket& sock;
- rfb::HTTPServer& server;
- enum {ReadRequestLine, ReadHeaders, WriteResponse} state;
- enum {GetRequest, HeadRequest} request;
- time_t lastActive;
-};
-
-
-// - Internal helper routines
-
-void
-copyStream(InStream& is, OutStream& os) {
- try {
- while (1) {
- os.writeU8(is.readU8());
- }
- } catch (rdr::EndOfStream&) {
- }
-}
-
-void writeLine(OutStream& os, const char* text) {
- os.writeBytes(text, strlen(text));
- os.writeBytes("\r\n", 2);
-}
-
-
-// - Write an HTTP-compliant response to the client
-
-
-void
-HTTPServer::Session::writeResponse(int result, const char* text) {
- char buffer[1024];
- if (strlen(text) > 512)
- throw new rdr::Exception("Internal error - HTTP response text too big");
- sprintf(buffer, "%s %d %s", "HTTP/1.1", result, text);
- OutStream& os=sock.outStream();
- writeLine(os, buffer);
- writeLine(os, "Server: TigerVNC/4.0");
- time_t now = time(0);
- struct tm* tm = gmtime(&now);
- strftime(buffer, 1024, "Date: %a, %d %b %Y %H:%M:%S GMT", tm);
- writeLine(os, buffer);
- if (lastModified == (time_t)-1 || lastModified == 0)
- lastModified = now;
- tm = gmtime(&lastModified);
- strftime(buffer, 1024, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT", tm);
- writeLine(os, buffer);
- if (contentLength != -1) {
- sprintf(buffer,"Content-Length: %d",contentLength);
- writeLine(os, buffer);
- }
- writeLine(os, "Connection: close");
- os.writeBytes("Content-Type: ", 14);
- if (result == 200) {
- if (!contentType)
- contentType = guessContentType(uri.buf, "text/html");
- os.writeBytes(contentType, strlen(contentType));
- } else {
- os.writeBytes("text/html", 9);
- }
- os.writeBytes("\r\n", 2);
- writeLine(os, "");
- if (result != 200) {
- writeLine(os, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
- writeLine(os, "<HTML><HEAD>");
- sprintf(buffer, "<TITLE>%d %s</TITLE>", result, text);
- writeLine(os, buffer);
- writeLine(os, "</HEAD><BODY><H1>");
- writeLine(os, text);
- writeLine(os, "</H1></BODY></HTML>");
- sock.outStream().flush();
- }
-}
-
-bool
-HTTPServer::Session::writeResponse(int code) {
- switch (code) {
- case 200: writeResponse(code, "OK"); break;
- case 400: writeResponse(code, "Bad Request"); break;
- case 404: writeResponse(code, "Not Found"); break;
- case 501: writeResponse(code, "Not Implemented"); break;
- default: writeResponse(500, "Unknown Error"); break;
- };
-
- // This return code is passed straight out of processHTTP().
- // true indicates that the request has been completely processed.
- return true;
-}
-
-// - Main HTTP request processing routine
-
-bool
-HTTPServer::Session::processHTTP() {
- lastActive = time(0);
-
- while (sock.inStream().checkNoWait(1)) {
-
- switch (state) {
-
- // Reading the Request-Line
- case ReadRequestLine:
-
- // Either read a line, or run out of incoming data
- if (!line.read())
- return false;
-
- // We have read a line! Skip it if it's blank
- if (strlen(line.buf) == 0)
- continue;
-
- // The line contains a request to process.
- {
- char method[16], path[128], version[16];
- int matched = sscanf(line.buf, "%15s%127s%15s",
- method, path, version);
- if (matched != 3)
- return writeResponse(400);
-
- // Store the required "method"
- if (strcmp(method, "GET") == 0)
- request = GetRequest;
- else if (strcmp(method, "HEAD") == 0)
- request = HeadRequest;
- else
- return writeResponse(501);
-
- // Store the URI to the "document"
- uri.buf = strDup(path);
- }
-
- // Move on to reading the request headers
- state = ReadHeaders;
- break;
-
- // Reading the request headers
- case ReadHeaders:
-
- // Try to read a line
- if (!line.read())
- return false;
-
- // Skip headers until we hit a blank line
- if (strlen(line.buf) != 0)
- continue;
-
- // Headers ended - write the response!
- {
- CharArray address(sock.getPeerAddress());
- vlog.info("getting %s for %s", uri.buf, address.buf);
- contentLength = -1;
- lastModified = -1;
- InStream* data = server.getFile(uri.buf, &contentType, &contentLength,
- &lastModified);
- if (!data)
- return writeResponse(404);
-
- try {
- writeResponse(200);
- if (request == GetRequest)
- copyStream(*data, sock.outStream());
- sock.outStream().flush();
- } catch (rdr::Exception& e) {
- vlog.error("error writing HTTP document:%s", e.str());
- }
- delete data;
- }
-
- // The operation is complete!
- return true;
-
- default:
- throw rdr::Exception("invalid HTTPSession state!");
- };
-
- }
-
- // Indicate that we're still processing the HTTP request.
- return false;
-}
-
-int HTTPServer::Session::checkIdleTimeout() {
- time_t now = time(0);
- int timeout = (lastActive + idleTimeoutSecs) - now;
- if (timeout > 0)
- return secsToMillis(timeout);
- sock.shutdown();
- return 0;
-}
-
-// -=- Constructor / destructor
-
-HTTPServer::HTTPServer() {
-}
-
-HTTPServer::~HTTPServer() {
- std::list<Session*>::iterator i;
- for (i=sessions.begin(); i!=sessions.end(); i++)
- delete *i;
-}
-
-
-// -=- SocketServer interface implementation
-
-void
-HTTPServer::addSocket(network::Socket* sock, bool) {
- Session* s = new Session(*sock, *this);
- if (!s) {
- sock->shutdown();
- } else {
- sock->inStream().setTimeout(clientWaitTimeMillis);
- sock->outStream().setTimeout(clientWaitTimeMillis);
- sessions.push_front(s);
- }
-}
-
-void
-HTTPServer::removeSocket(network::Socket* sock) {
- std::list<Session*>::iterator i;
- for (i=sessions.begin(); i!=sessions.end(); i++) {
- if ((*i)->getSock() == sock) {
- delete *i;
- sessions.erase(i);
- return;
- }
- }
-}
-
-void
-HTTPServer::processSocketReadEvent(network::Socket* sock) {
- std::list<Session*>::iterator i;
- for (i=sessions.begin(); i!=sessions.end(); i++) {
- if ((*i)->getSock() == sock) {
- try {
- if ((*i)->processHTTP()) {
- vlog.info("completed HTTP request");
- sock->shutdown();
- }
- } catch (rdr::Exception& e) {
- vlog.error("untrapped: %s", e.str());
- sock->shutdown();
- }
- return;
- }
- }
- throw rdr::Exception("invalid Socket in HTTPServer");
-}
-
-void
-HTTPServer::processSocketWriteEvent(network::Socket* sock) {
- std::list<Session*>::iterator i;
- for (i=sessions.begin(); i!=sessions.end(); i++) {
- if ((*i)->getSock() == sock) {
- try {
- sock->outStream().flush();
- } catch (rdr::Exception& e) {
- vlog.error("untrapped: %s", e.str());
- sock->shutdown();
- }
- return;
- }
- }
- throw rdr::Exception("invalid Socket in HTTPServer");
-}
-
-void HTTPServer::getSockets(std::list<network::Socket*>* sockets)
-{
- sockets->clear();
- std::list<Session*>::iterator ci;
- for (ci = sessions.begin(); ci != sessions.end(); ci++) {
- sockets->push_back((*ci)->getSock());
- }
-}
-
-int HTTPServer::checkTimeouts() {
- std::list<Session*>::iterator ci;
- int timeout = 0;
- for (ci = sessions.begin(); ci != sessions.end(); ci++) {
- soonestTimeout(&timeout, (*ci)->checkIdleTimeout());
- }
- return timeout;
-}
-
-
-// -=- Default getFile implementation
-
-InStream*
-HTTPServer::getFile(const char* name, const char** contentType,
- int* contentLength, time_t* lastModified)
-{
- return 0;
-}
-
-const char*
-HTTPServer::guessContentType(const char* name, const char* defType) {
- CharArray file, ext;
- if (!strSplit(name, '.', &file.buf, &ext.buf))
- return defType;
- if (strcasecmp(ext.buf, "html") == 0 ||
- strcasecmp(ext.buf, "htm") == 0) {
- return "text/html";
- } else if (strcasecmp(ext.buf, "txt") == 0) {
- return "text/plain";
- } else if (strcasecmp(ext.buf, "gif") == 0) {
- return "image/gif";
- } else if (strcasecmp(ext.buf, "jpg") == 0) {
- return "image/jpeg";
- } else if (strcasecmp(ext.buf, "jar") == 0) {
- return "application/java-archive";
- } else if (strcasecmp(ext.buf, "exe") == 0) {
- return "application/octet-stream";
- }
- return defType;
-}
diff --git a/common/rfb/HTTPServer.h b/common/rfb/HTTPServer.h
deleted file mode 100644
index 04ef499..0000000
--- a/common/rfb/HTTPServer.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * 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.
- */
-
-// -=- HTTPServer.h
-
-// Single-threaded HTTP server implementation.
-// All I/O is handled by the processSocketEvent routine,
-// which is called by the main-loop of the VNC server whenever
-// there is an event on an HTTP socket.
-
-#ifndef __RFB_HTTP_SERVER_H__
-#define __RFB_HTTP_SERVER_H__
-
-#include <rdr/MemInStream.h>
-#include <rfb/UpdateTracker.h>
-#include <rfb/Configuration.h>
-#include <network/Socket.h>
-#include <time.h>
-
-namespace rfb {
-
- class HTTPServer : public network::SocketServer {
- public:
- // -=- Constructors
-
- // - HTTPServer(files)
- // Create an HTTP server which will use the getFile method
- // to satisfy HTTP GET requests.
- HTTPServer();
-
- virtual ~HTTPServer();
-
- // SocketServer interface
-
- // addSocket()
- // This causes the server to perform HTTP protocol on the
- // supplied socket.
- virtual void addSocket(network::Socket* sock, bool outgoing=false);
-
- // removeSocket()
- // Could clean up socket-specific resources here.
- virtual void removeSocket(network::Socket* sock);
-
- // getSockets() gets a list of sockets. This can be used to generate an
- // fd_set for calling select().
- virtual void getSockets(std::list<network::Socket*>* sockets);
-
- // processSocketReadEvent()
- // The platform-specific side of the server implementation calls
- // this method whenever data arrives on one of the active
- // network sockets.
- virtual void processSocketReadEvent(network::Socket* sock);
-
- // processSocketWriteEvent()
- // Similar to processSocketReadEvent(), but called when it is
- // possible to write more data to a socket.
- virtual void processSocketWriteEvent(network::Socket* sock);
-
- // Check for socket timeouts
- virtual int checkTimeouts();
-
-
- // -=- File interface
-
- // - getFile is passed the path portion of a URL and returns an
- // InStream containing the data to return. If the requested
- // file is available then the contentType should be set to the
- // type of the file, or left untouched if the file type is to
- // be determined automatically by HTTPServer.
- // If the file is not available then null is returned.
- // Overridden getFile functions should call the default version
- // if they do not recognise a path name.
- // NB: The caller assumes ownership of the returned InStream.
- // NB: The contentType is statically allocated by the getFile impl.
- // NB: contentType is *guaranteed* to be valid when getFile is called.
-
- virtual rdr::InStream* getFile(const char* name, const char** contentType,
- int* contentLength, time_t* lastModified);
-
- // - guessContentType is passed the name of a file and returns the
- // name of an HTTP content type, based on the file's extension. If
- // the extension isn't recognised then defType is returned. This can
- // be used from getFile to easily default to the supplied contentType,
- // or by passing zero in to determine whether a type is recognised or
- // not.
-
- static const char* guessContentType(const char* name, const char* defType);
-
- protected:
- class Session;
- std::list<Session*> sessions;
- };
-}
-
-#endif
-
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index efc26ac..a79abee 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -260,13 +260,14 @@
throw ConnFailedException(str);
}
-void SConnection::writeConnFailedFromScratch(const char* msg,
- rdr::OutStream* os)
+void SConnection::setAccessRights(AccessRights ar)
{
- os->writeBytes("RFB 003.003\n", 12);
- os->writeU32(0);
- os->writeString(msg);
- os->flush();
+ accessRights = ar;
+}
+
+bool SConnection::accessCheck(AccessRights ar) const
+{
+ return (accessRights & ar) == ar;
}
void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)
@@ -342,6 +343,11 @@
state_ = RFBSTATE_NORMAL;
}
+void SConnection::close(const char* reason)
+{
+ state_ = RFBSTATE_CLOSING;
+}
+
void SConnection::setPixelFormat(const PixelFormat& pf)
{
SMsgHandler::setPixelFormat(pf);
diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h
index 47092e3..2630240 100644
--- a/common/rfb/SConnection.h
+++ b/common/rfb/SConnection.h
@@ -69,6 +69,13 @@
void approveConnection(bool accept, const char* reason=0);
+ // Methods to terminate the connection
+
+ // close() shuts down the connection to the client and awaits
+ // cleanup of the SConnection object by the server
+ virtual void close(const char* reason);
+
+
// Overridden from SMsgHandler
virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
@@ -118,8 +125,10 @@
virtual void enableContinuousUpdates(bool enable,
int x, int y, int w, int h);
+ // Other methods
+
// setAccessRights() allows a security package to limit the access rights
- // of a VNCSConnectionST to the server. How the access rights are treated
+ // of a SConnection to the server. How the access rights are treated
// is up to the derived class.
typedef rdr::U16 AccessRights;
@@ -132,27 +141,14 @@
static const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES
static const AccessRights AccessNoQuery; // Connect without local user accepting
static const AccessRights AccessFull; // All of the available AND FUTURE rights
- virtual void setAccessRights(AccessRights ar) = 0;
-
- // Other methods
+ virtual void setAccessRights(AccessRights ar);
+ virtual bool accessCheck(AccessRights ar) const;
// authenticated() returns true if the client has authenticated
// successfully.
bool authenticated() { return (state_ == RFBSTATE_INITIALISATION ||
state_ == RFBSTATE_NORMAL); }
- // throwConnFailedException() prints a message to the log, sends a conn
- // failed message to the client (if possible) and throws a
- // ConnFailedException.
- void throwConnFailedException(const char* format, ...) __printf_attr(2, 3);
-
- // writeConnFailedFromScratch() sends a conn failed message to an OutStream
- // without the need to negotiate the protocol version first. It actually
- // does this by assuming that the client will understand version 3.3 of the
- // protocol.
- static void writeConnFailedFromScratch(const char* msg,
- rdr::OutStream* os);
-
SMsgReader* reader() { return reader_; }
SMsgWriter* writer() { return writer_; }
@@ -176,6 +172,11 @@
rdr::S32 getPreferredEncoding() { return preferredEncoding; }
protected:
+ // throwConnFailedException() prints a message to the log, sends a conn
+ // failed message to the client (if possible) and throws a
+ // ConnFailedException.
+ void throwConnFailedException(const char* format, ...) __printf_attr(2, 3);
+
void setState(stateEnum s) { state_ = s; }
void setReader(SMsgReader *r) { reader_ = r; }
@@ -201,6 +202,7 @@
SSecurity* ssecurity;
stateEnum state_;
rdr::S32 preferredEncoding;
+ AccessRights accessRights;
};
}
#endif
diff --git a/common/rfb/SDesktop.h b/common/rfb/SDesktop.h
index 717ddbc..0060aa2 100644
--- a/common/rfb/SDesktop.h
+++ b/common/rfb/SDesktop.h
@@ -44,6 +44,8 @@
#include <rfb/screenTypes.h>
#include <rfb/util.h>
+namespace network { class Socket; }
+
namespace rfb {
class VNCServer;
@@ -56,14 +58,28 @@
// set via the VNCServer's setPixelBuffer() method by the time this call
// returns.
- virtual void start(VNCServer* __unused_attr vs) {}
+ virtual void start(VNCServer* vs) = 0;
// stop() is called by the server when there are no longer any
// authenticated clients, and therefore the desktop can cease any
// expensive tasks. No further calls to the VNCServer passed to start()
// can be made once stop has returned.
- virtual void stop() {}
+ virtual void stop() = 0;
+
+ // queryConnection() is called when a connection has been
+ // successfully authenticated. The sock and userName arguments
+ // identify the socket and the name of the authenticated user, if
+ // any. At some point later VNCServer::approveConnection() should
+ // be called to either accept or reject the client.
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) = 0;
+
+ // terminate() is called by the server when it wishes to terminate
+ // itself, e.g. because it was configured to terminate when no one is
+ // using it.
+
+ virtual void terminate() = 0;
// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
@@ -112,6 +128,10 @@
server->setPixelBuffer(0);
server = 0;
}
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) {
+ server->approveConnection(sock, true, NULL);
+ }
protected:
VNCServer* server;
diff --git a/common/rfb/SSecurityTLS.cxx b/common/rfb/SSecurityTLS.cxx
index 49532f5..d5ef47e 100644
--- a/common/rfb/SSecurityTLS.cxx
+++ b/common/rfb/SSecurityTLS.cxx
@@ -163,7 +163,8 @@
throw AuthFailureException("TLS Handshake failed");
}
- vlog.debug("Handshake completed");
+ vlog.debug("TLS handshake completed with %s",
+ gnutls_session_get_desc(session));
sc->setStreams(tlsis, tlsos);
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index f1591f4..8758362 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -51,28 +51,31 @@
fenceDataLen(0), fenceData(NULL), congestionTimer(this),
losslessTimer(this), server(server_), updates(false),
updateRenderedCursor(false), removeRenderedCursor(false),
- continuousUpdates(false), encodeManager(this), pointerEventTime(0),
- clientHasCursor(false),
- accessRights(AccessDefault), startTime(time(0))
+ continuousUpdates(false), encodeManager(this), idleTimer(this),
+ pointerEventTime(0), clientHasCursor(false)
{
setStreams(&sock->inStream(), &sock->outStream());
peerEndpoint.buf = sock->getPeerEndpoint();
- VNCServerST::connectionsLog.write(1,"accepted: %s", peerEndpoint.buf);
// Configure the socket
setSocketTimeouts();
- lastEventTime = time(0);
- server->clients.push_front(this);
+ // Kick off the idle timer
+ if (rfb::Server::idleTimeout) {
+ // minimum of 15 seconds while authenticating
+ if (rfb::Server::idleTimeout < 15)
+ idleTimer.start(secsToMillis(15));
+ else
+ idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ }
}
VNCSConnectionST::~VNCSConnectionST()
{
// If we reach here then VNCServerST is deleting us!
- VNCServerST::connectionsLog.write(1,"closed: %s (%s)",
- peerEndpoint.buf,
- (closeReason.buf) ? closeReason.buf : "");
+ if (closeReason.buf)
+ vlog.info("closing %s: %s", peerEndpoint.buf, closeReason.buf);
// Release any keys the client still had pressed
while (!pressedKeys.empty()) {
@@ -84,19 +87,42 @@
vlog.debug("Releasing key 0x%x / 0x%x on client disconnect",
keysym, keycode);
- server->desktop->keyEvent(keysym, keycode, false);
+ server->keyEvent(keysym, keycode, false);
}
- if (server->pointerClient == this)
- server->pointerClient = 0;
-
- // Remove this client from the server
- server->clients.remove(this);
-
delete [] fenceData;
}
+// SConnection methods
+
+bool VNCSConnectionST::accessCheck(AccessRights ar) const
+{
+ // Reverse connections are user initiated, so they are implicitly
+ // allowed to bypass the query
+ if (reverseConnection)
+ ar &= ~AccessNoQuery;
+
+ return SConnection::accessCheck(ar);
+}
+
+void VNCSConnectionST::close(const char* reason)
+{
+ // Log the reason for the close
+ if (!closeReason.buf)
+ closeReason.buf = strDup(reason);
+ else
+ vlog.debug("second close: %s (%s)", peerEndpoint.buf, reason);
+
+ // 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.
+ sock->shutdown();
+
+ SConnection::close(reason);
+}
+
+
// Methods called from VNCServerST
bool VNCSConnectionST::init()
@@ -110,25 +136,6 @@
return true;
}
-void VNCSConnectionST::close(const char* reason)
-{
- // Log the reason for the close
- if (!closeReason.buf)
- closeReason.buf = strDup(reason);
- else
- vlog.debug("second close: %s (%s)", peerEndpoint.buf, reason);
-
- if (authenticated()) {
- server->lastDisconnectTime = time(0);
- }
-
- // 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.
- sock->shutdown();
- setState(RFBSTATE_CLOSING);
-}
-
void VNCSConnectionST::processMessages()
{
@@ -192,8 +199,9 @@
{
try {
if (!authenticated()) return;
- if (cp.width && cp.height && (server->pb->width() != cp.width ||
- server->pb->height() != cp.height))
+ if (cp.width && cp.height &&
+ (server->getPixelBuffer()->width() != cp.width ||
+ server->getPixelBuffer()->height() != cp.height))
{
// We need to clip the next update to the new size, but also add any
// extra bits if it's bigger. If we wanted to do this exactly, something
@@ -210,11 +218,11 @@
// updates.add_changed(Rect(0, cp.height, cp.width,
// server->pb->height()));
- damagedCursorRegion.assign_intersect(server->pb->getRect());
+ damagedCursorRegion.assign_intersect(server->getPixelBuffer()->getRect());
- cp.width = server->pb->width();
- cp.height = server->pb->height();
- cp.screenLayout = server->screenLayout;
+ cp.width = server->getPixelBuffer()->width();
+ cp.height = server->getPixelBuffer()->height();
+ cp.screenLayout = server->getScreenLayout();
if (state() == RFBSTATE_NORMAL) {
// We should only send EDS to client asking for both
if (!writer()->writeExtendedDesktopSize()) {
@@ -226,12 +234,12 @@
}
// Drop any lossy tracking that is now outside the framebuffer
- encodeManager.pruneLosslessRefresh(Region(server->pb->getRect()));
+ encodeManager.pruneLosslessRefresh(Region(server->getPixelBuffer()->getRect()));
}
// Just update the whole screen at the moment because we're too lazy to
// work out what's actually changed.
updates.clear();
- updates.add_changed(server->pb->getRect());
+ updates.add_changed(server->getPixelBuffer()->getRect());
writeFramebufferUpdate();
} catch(rdr::Exception &e) {
close(e.str());
@@ -269,7 +277,7 @@
void VNCSConnectionST::serverCutTextOrClose(const char *str, int len)
{
try {
- if (!(accessRights & AccessCutText)) return;
+ if (!accessCheck(AccessCutText)) return;
if (!rfb::Server::sendCutText) return;
if (state() == RFBSTATE_NORMAL)
writer()->writeServerCutText(str, len);
@@ -312,36 +320,6 @@
}
-int VNCSConnectionST::checkIdleTimeout()
-{
- int idleTimeout = rfb::Server::idleTimeout;
- if (idleTimeout == 0) return 0;
- if (state() != RFBSTATE_NORMAL && idleTimeout < 15)
- idleTimeout = 15; // minimum of 15 seconds while authenticating
- time_t now = time(0);
- if (now < lastEventTime) {
- // Someone must have set the time backwards. Set lastEventTime so that the
- // idleTimeout will count from now.
- vlog.info("Time has gone backwards - resetting idle timeout");
- lastEventTime = now;
- }
- int timeLeft = lastEventTime + idleTimeout - now;
- if (timeLeft < -60) {
- // Our callback is over a minute late - someone must have set the time
- // forwards. Set lastEventTime so that the idleTimeout will count from
- // now.
- vlog.info("Time has gone forwards - resetting idle timeout");
- lastEventTime = now;
- return secsToMillis(idleTimeout);
- }
- if (timeLeft <= 0) {
- close("Idle timeout");
- return 0;
- }
- return secsToMillis(timeLeft);
-}
-
-
bool VNCSConnectionST::getComparerState()
{
// We interpret a low compression level as an indication that the client
@@ -388,7 +366,7 @@
if (!cp.supportsLocalCursorWithAlpha &&
!cp.supportsLocalCursor && !cp.supportsLocalXCursor)
return true;
- if (!server->cursorPos.equals(pointerEventPos) &&
+ if (!server->getCursorPos().equals(pointerEventPos) &&
(time(0) - pointerEventTime) > 0)
return true;
@@ -412,84 +390,40 @@
void VNCSConnectionST::authSuccess()
{
- lastEventTime = time(0);
-
- server->startDesktop();
+ if (rfb::Server::idleTimeout)
+ idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
// - Set the connection parameters appropriately
- cp.width = server->pb->width();
- cp.height = server->pb->height();
- cp.screenLayout = server->screenLayout;
+ cp.width = server->getPixelBuffer()->width();
+ cp.height = server->getPixelBuffer()->height();
+ cp.screenLayout = server->getScreenLayout();
cp.setName(server->getName());
- cp.setLEDState(server->ledState);
+ cp.setLEDState(server->getLEDState());
// - Set the default pixel format
- cp.setPF(server->pb->getPF());
+ cp.setPF(server->getPixelBuffer()->getPF());
char buffer[256];
cp.pf().print(buffer, 256);
vlog.info("Server default pixel format %s", buffer);
// - Mark the entire display as "dirty"
- updates.add_changed(server->pb->getRect());
- startTime = time(0);
+ updates.add_changed(server->getPixelBuffer()->getRect());
}
void VNCSConnectionST::queryConnection(const char* userName)
{
- // - Authentication succeeded - clear from blacklist
- CharArray name; name.buf = sock->getPeerAddress();
- server->blHosts->clearBlackmark(name.buf);
-
- // - Special case to provide a more useful error message
- if (rfb::Server::neverShared && !rfb::Server::disconnectClients &&
- server->authClientCount() > 0) {
- approveConnection(false, "The server is already in use");
- return;
- }
-
- // - Does the client have the right to bypass the query?
- if (reverseConnection ||
- !(rfb::Server::queryConnect || sock->requiresQuery()) ||
- (accessRights & AccessNoQuery))
- {
- approveConnection(true);
- return;
- }
-
- // - Get the server to display an Accept/Reject dialog, if required
- // If a dialog is displayed, the result will be PENDING, and the
- // server will call approveConnection at a later time
- CharArray reason;
- VNCServerST::queryResult qr = server->queryConnection(sock, userName,
- &reason.buf);
- if (qr == VNCServerST::PENDING)
- return;
-
- // - If server returns ACCEPT/REJECT then pass result to SConnection
- approveConnection(qr == VNCServerST::ACCEPT, reason.buf);
+ server->queryConnection(this, userName);
}
void VNCSConnectionST::clientInit(bool shared)
{
- lastEventTime = time(0);
+ if (rfb::Server::idleTimeout)
+ idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
if (rfb::Server::alwaysShared || reverseConnection) shared = true;
- if (!(accessRights & AccessNonShared)) shared = true;
+ if (!accessCheck(AccessNonShared)) shared = true;
if (rfb::Server::neverShared) shared = false;
- if (!shared) {
- if (rfb::Server::disconnectClients && (accessRights & AccessNonShared)) {
- // - Close all the other connected clients
- vlog.debug("non-shared connection - closing clients");
- server->closeClients("Non-shared connection requested", getSock());
- } else {
- // - Refuse this connection if there are existing clients, in addition to
- // this one
- if (server->authClientCount() > 1) {
- close("Server is already in use");
- return;
- }
- }
- }
SConnection::clientInit(shared);
+ server->clientReady(this, shared);
}
void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)
@@ -503,37 +437,32 @@
void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask)
{
- pointerEventTime = lastEventTime = time(0);
- server->lastUserInputTime = lastEventTime;
- if (!(accessRights & AccessPtrEvents)) return;
+ if (rfb::Server::idleTimeout)
+ idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ pointerEventTime = time(0);
+ if (!accessCheck(AccessPtrEvents)) return;
if (!rfb::Server::acceptPointerEvents) return;
- if (!server->pointerClient || server->pointerClient == this) {
- pointerEventPos = pos;
- if (buttonMask)
- server->pointerClient = this;
- else
- server->pointerClient = 0;
- server->desktop->pointerEvent(pointerEventPos, buttonMask);
- }
+ pointerEventPos = pos;
+ server->pointerEvent(this, pointerEventPos, buttonMask);
}
class VNCSConnectionSTShiftPresser {
public:
- VNCSConnectionSTShiftPresser(SDesktop* desktop_)
- : desktop(desktop_), pressed(false) {}
+ VNCSConnectionSTShiftPresser(VNCServerST* server_)
+ : server(server_), pressed(false) {}
~VNCSConnectionSTShiftPresser() {
if (pressed) {
vlog.debug("Releasing fake Shift_L");
- desktop->keyEvent(XK_Shift_L, 0, false);
+ server->keyEvent(XK_Shift_L, 0, false);
}
}
void press() {
vlog.debug("Pressing fake Shift_L");
- desktop->keyEvent(XK_Shift_L, 0, true);
+ server->keyEvent(XK_Shift_L, 0, true);
pressed = true;
}
- SDesktop* desktop;
+ VNCServerST* server;
bool pressed;
};
@@ -542,9 +471,9 @@
void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
rdr::U32 lookup;
- lastEventTime = time(0);
- server->lastUserInputTime = lastEventTime;
- if (!(accessRights & AccessKeyEvents)) return;
+ if (rfb::Server::idleTimeout)
+ idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
+ if (!accessCheck(AccessKeyEvents)) return;
if (!rfb::Server::acceptKeyEvents) return;
if (down)
@@ -552,18 +481,8 @@
else
vlog.debug("Key released: 0x%x / 0x%x", keysym, keycode);
- // Remap the key if required
- if (server->keyRemapper) {
- rdr::U32 newkey;
- newkey = server->keyRemapper->remapKey(keysym);
- if (newkey != keysym) {
- vlog.debug("Key remapped to 0x%x", newkey);
- keysym = newkey;
- }
- }
-
// Avoid lock keys if we don't know the server state
- if ((server->ledState == ledUnknown) &&
+ if ((server->getLEDState() == ledUnknown) &&
((keysym == XK_Caps_Lock) ||
(keysym == XK_Num_Lock) ||
(keysym == XK_Scroll_Lock))) {
@@ -581,7 +500,7 @@
return;
}
- if (down && (server->ledState != ledUnknown)) {
+ if (down && (server->getLEDState() != ledUnknown)) {
// CapsLock synchronisation heuristic
// (this assumes standard interaction between CapsLock the Shift
// keys and normal characters)
@@ -591,12 +510,12 @@
uppercase = (keysym >= XK_A) && (keysym <= XK_Z);
shift = isShiftPressed();
- lock = server->ledState & ledCapsLock;
+ lock = server->getLEDState() & ledCapsLock;
if (lock == (uppercase == shift)) {
vlog.debug("Inserting fake CapsLock to get in sync with client");
- server->desktop->keyEvent(XK_Caps_Lock, 0, true);
- server->desktop->keyEvent(XK_Caps_Lock, 0, false);
+ server->keyEvent(XK_Caps_Lock, 0, true);
+ server->keyEvent(XK_Caps_Lock, 0, false);
}
}
@@ -611,7 +530,7 @@
number = ((keysym >= XK_KP_0) && (keysym <= XK_KP_9)) ||
(keysym == XK_KP_Separator) || (keysym == XK_KP_Decimal);
shift = isShiftPressed();
- lock = server->ledState & ledNumLock;
+ lock = server->getLEDState() & ledNumLock;
if (shift) {
// We don't know the appropriate NumLock state for when Shift
@@ -625,15 +544,15 @@
//
} else if (lock == (number == shift)) {
vlog.debug("Inserting fake NumLock to get in sync with client");
- server->desktop->keyEvent(XK_Num_Lock, 0, true);
- server->desktop->keyEvent(XK_Num_Lock, 0, false);
+ server->keyEvent(XK_Num_Lock, 0, true);
+ server->keyEvent(XK_Num_Lock, 0, false);
}
}
}
}
// Turn ISO_Left_Tab into shifted Tab.
- VNCSConnectionSTShiftPresser shiftPresser(server->desktop);
+ VNCSConnectionSTShiftPresser shiftPresser(server);
if (keysym == XK_ISO_Left_Tab) {
if (!isShiftPressed())
shiftPresser.press();
@@ -659,21 +578,21 @@
return;
}
- server->desktop->keyEvent(keysym, keycode, down);
+ server->keyEvent(keysym, keycode, down);
}
void VNCSConnectionST::clientCutText(const char* str, int len)
{
- if (!(accessRights & AccessCutText)) return;
+ if (!accessCheck(AccessCutText)) return;
if (!rfb::Server::acceptCutText) return;
- server->desktop->clientCutText(str, len);
+ server->clientCutText(str, len);
}
void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
{
Rect safeRect;
- if (!(accessRights & AccessView)) return;
+ if (!accessCheck(AccessView)) return;
SConnection::framebufferUpdateRequest(r, incremental);
@@ -712,30 +631,12 @@
{
unsigned int result;
- if (!(accessRights & AccessSetDesktopSize)) return;
+ if (!accessCheck(AccessSetDesktopSize)) return;
if (!rfb::Server::acceptSetDesktopSize) return;
- // Don't bother the desktop with an invalid configuration
- if (!layout.validate(fb_width, fb_height)) {
- writer()->writeExtendedDesktopSize(reasonClient, resultInvalid,
- fb_width, fb_height, layout);
- return;
- }
-
- // FIXME: the desktop will call back to VNCServerST and an extra set
- // of ExtendedDesktopSize messages will be sent. This is okay
- // protocol-wise, but unnecessary.
- result = server->desktop->setScreenLayout(fb_width, fb_height, layout);
-
+ result = server->setDesktopSize(this, fb_width, fb_height, layout);
writer()->writeExtendedDesktopSize(reasonClient, result,
fb_width, fb_height, layout);
-
- // Only notify other clients on success
- if (result == resultSuccess) {
- if (server->screenLayout != layout)
- throw Exception("Desktop configured a different screen layout than requested");
- server->notifyScreenLayoutChange(this);
- }
}
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[])
@@ -847,6 +748,9 @@
close(e.str());
}
+ if (t == &idleTimer)
+ close("Idle timeout");
+
return false;
}
@@ -1001,7 +905,7 @@
bogusCopiedCursor = damagedCursorRegion;
bogusCopiedCursor.translate(ui.copy_delta);
- bogusCopiedCursor.assign_intersect(server->pb->getRect());
+ bogusCopiedCursor.assign_intersect(server->getPixelBuffer()->getRect());
if (!ui.copied.intersect(bogusCopiedCursor).is_empty()) {
updates.add_changed(bogusCopiedCursor);
needNewUpdateInfo = true;
@@ -1124,7 +1028,7 @@
if (!authenticated())
return;
- cp.screenLayout = server->screenLayout;
+ cp.screenLayout = server->getScreenLayout();
if (state() != RFBSTATE_NORMAL)
return;
@@ -1148,7 +1052,7 @@
cp.setCursor(emptyCursor);
clientHasCursor = false;
} else {
- cp.setCursor(*server->cursor);
+ cp.setCursor(*server->getCursor());
clientHasCursor = true;
}
@@ -1188,43 +1092,8 @@
void VNCSConnectionST::setSocketTimeouts()
{
int timeoutms = rfb::Server::clientWaitTimeMillis;
- soonestTimeout(&timeoutms, secsToMillis(rfb::Server::idleTimeout));
if (timeoutms == 0)
timeoutms = -1;
sock->inStream().setTimeout(timeoutms);
sock->outStream().setTimeout(timeoutms);
}
-
-char* VNCSConnectionST::getStartTime()
-{
- char* result = ctime(&startTime);
- result[24] = '\0';
- return result;
-}
-
-void VNCSConnectionST::setStatus(int status)
-{
- switch (status) {
- case 0:
- accessRights = accessRights | AccessPtrEvents | AccessKeyEvents | AccessView;
- break;
- case 1:
- accessRights = (accessRights & ~(AccessPtrEvents | AccessKeyEvents)) | AccessView;
- break;
- case 2:
- accessRights = accessRights & ~(AccessPtrEvents | AccessKeyEvents | AccessView);
- break;
- }
- framebufferUpdateRequest(server->pb->getRect(), false);
-}
-int VNCSConnectionST::getStatus()
-{
- if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0007)
- return 0;
- if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0001)
- return 1;
- if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0000)
- return 2;
- return 4;
-}
-
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index dfc8bcb..c992d14 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -43,21 +43,18 @@
VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse);
virtual ~VNCSConnectionST();
+ // SConnection methods
+
+ virtual bool accessCheck(AccessRights ar) const;
+ virtual void close(const char* reason);
+
// Methods called from VNCServerST. None of these methods ever knowingly
// throw an exception.
- // Unless otherwise stated, the SConnectionST may not be valid after any of
- // these methods are called, since they catch exceptions and may have
- // called close() which deletes the object.
-
// init() must be called to initialise the protocol. If it fails it
// returns false, and close() will have been called.
bool init();
- // close() shuts down the socket to the client and deletes the
- // SConnectionST object.
- void close(const char* reason);
-
// processMessages() processes incoming messages from the client, invoking
// various callbacks as a result. It continues to process messages until
// reading might block. shutdown() will be called on the connection's
@@ -78,14 +75,9 @@
void serverCutTextOrClose(const char *str, int len);
void setDesktopNameOrClose(const char *name);
void setLEDStateOrClose(unsigned int state);
+ void approveConnectionOrClose(bool accept, const char* reason);
- // checkIdleTimeout() returns the number of milliseconds left until the
- // idle timeout expires. If it has expired, the connection is closed and
- // zero is returned. Zero is also returned if there is no idle timeout.
- int checkIdleTimeout();
-
- // The following methods never throw exceptions nor do they ever delete the
- // SConnectionST object.
+ // The following methods never throw exceptions
// getComparerState() returns if this client would like the framebuffer
// comparer to be enabled.
@@ -103,32 +95,18 @@
bool needRenderedCursor();
network::Socket* getSock() { return sock; }
+
+ // Change tracking
+
void add_changed(const Region& region) { updates.add_changed(region); }
void add_copied(const Region& dest, const Point& delta) {
updates.add_copied(dest, delta);
}
- const char* getPeerEndpoint() const {return peerEndpoint.buf;}
-
- // approveConnectionOrClose() is called some time after
- // VNCServerST::queryConnection() has returned with PENDING to accept or
- // reject the connection. The accept argument should be true for
- // acceptance, or false for rejection, in which case a string reason may
- // also be given.
-
- void approveConnectionOrClose(bool accept, const char* reason);
-
- char* getStartTime();
-
- void setStatus(int status);
- int getStatus();
-
private:
// SConnection callbacks
- // These methods are invoked as callbacks from processMsg(). Note that
- // none of these methods should call any of the above methods which may
- // delete the SConnectionST object.
+ // These methods are invoked as callbacks from processMsg()
virtual void authSuccess();
virtual void queryConnection(const char* userName);
@@ -148,12 +126,6 @@
virtual void supportsContinuousUpdates();
virtual void supportsLEDState();
- // setAccessRights() allows a security package to limit the access rights
- // of a VNCSConnectioST to the server. These access rights are applied
- // such that the actual rights granted are the minimum of the server's
- // default access settings and the connection's access settings.
- virtual void setAccessRights(AccessRights ar) {accessRights=ar;}
-
// Timer callbacks
virtual bool handleTimeout(Timer* t);
@@ -178,6 +150,7 @@
void setLEDState(unsigned int state);
void setSocketTimeouts();
+ private:
network::Socket* sock;
CharArray peerEndpoint;
bool reverseConnection;
@@ -204,15 +177,13 @@
std::map<rdr::U32, rdr::U32> pressedKeys;
- time_t lastEventTime;
+ Timer idleTimer;
+
time_t pointerEventTime;
Point pointerEventPos;
bool clientHasCursor;
- AccessRights accessRights;
-
CharArray closeReason;
- time_t startTime;
};
}
#endif
diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h
index c5335ad..298326f 100644
--- a/common/rfb/VNCServer.h
+++ b/common/rfb/VNCServer.h
@@ -22,13 +22,16 @@
#ifndef __RFB_VNCSERVER_H__
#define __RFB_VNCSERVER_H__
+#include <network/Socket.h>
+
#include <rfb/UpdateTracker.h>
#include <rfb/SSecurity.h>
#include <rfb/ScreenSet.h>
namespace rfb {
- class VNCServer : public UpdateTracker {
+ class VNCServer : public UpdateTracker,
+ public network::SocketServer {
public:
// blockUpdates()/unblockUpdates() tells the server that the pixel buffer
// is currently in flux and may not be accessed. The attributes of the
@@ -50,7 +53,7 @@
virtual void setScreenLayout(const ScreenSet& layout) = 0;
// getPixelBuffer() returns a pointer to the PixelBuffer object.
- virtual PixelBuffer* getPixelBuffer() const = 0;
+ virtual const PixelBuffer* getPixelBuffer() const = 0;
// serverCutText() tells the server that the cut text has changed. This
// will normally be sent to all clients.
@@ -59,10 +62,22 @@
// bell() tells the server that it should make all clients make a bell sound.
virtual void bell() = 0;
+ // approveConnection() is called some time after
+ // SDesktop::queryConnection() has been called, to accept or reject
+ // the connection. The accept argument should be true for
+ // acceptance, or false for rejection, in which case a string
+ // reason may also be given.
+ virtual void approveConnection(network::Socket* sock, bool accept,
+ const char* reason = NULL) = 0;
+
// - Close all currently-connected clients, by calling
// their close() method with the supplied reason.
virtual void closeClients(const char* reason) = 0;
+ // getConnection() gets the SConnection for a particular Socket. If
+ // the Socket is not recognised then null is returned.
+ virtual SConnection* getConnection(network::Socket* sock) = 0;
+
// setCursor() tells the server that the cursor has changed. The
// cursorData argument contains width*height rgba quadruplets with
// non-premultiplied alpha.
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 8cc04f7..40580b1 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -53,7 +53,7 @@
#include <rfb/ComparingUpdateTracker.h>
#include <rfb/KeyRemapper.h>
-#include <rfb/ListConnInfo.h>
+#include <rfb/LogWriter.h>
#include <rfb/Security.h>
#include <rfb/ServerCore.h>
#include <rfb/VNCServerST.h>
@@ -66,7 +66,7 @@
using namespace rfb;
static LogWriter slog("VNCServerST");
-LogWriter VNCServerST::connectionsLog("Connections");
+static LogWriter connectionsLog("Connections");
//
// -=- VNCServerST Implementation
@@ -80,12 +80,17 @@
name(strDup(name_)), pointerClient(0), comparer(0),
cursor(new Cursor(0, 0, Point(), NULL)),
renderedCursorInvalid(false),
- queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
- lastConnectionTime(0), disableclients(false),
+ keyRemapper(&KeyRemapper::defInstance),
+ idleTimer(this), disconnectTimer(this), connectTimer(this),
frameTimer(this)
{
- lastUserInputTime = lastDisconnectTime = time(0);
slog.debug("creating single-threaded server %s", name.buf);
+
+ // FIXME: Do we really want to kick off these right away?
+ if (rfb::Server::maxIdleTime)
+ idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+ if (rfb::Server::maxDisconnectionTime)
+ disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));
}
VNCServerST::~VNCServerST()
@@ -99,9 +104,11 @@
stopFrameClock();
// Delete all the clients, and their sockets, and any closing sockets
- // NB: Deleting a client implicitly removes it from the clients list
while (!clients.empty()) {
- delete clients.front();
+ VNCSConnectionST* client;
+ client = clients.front();
+ clients.pop_front();
+ delete client;
}
// Stop the desktop object if active, *only* after deleting all clients!
@@ -125,8 +132,13 @@
if (blHosts->isBlackmarked(address.buf)) {
connectionsLog.error("blacklisted: %s", address.buf);
try {
- SConnection::writeConnFailedFromScratch("Too many security failures",
- &sock->outStream());
+ rdr::OutStream& os = sock->outStream();
+
+ // Shortest possible way to tell a client it is not welcome
+ os.writeBytes("RFB 003.003\n", 12);
+ os.writeU32(0);
+ os.writeString("Too many security failures");
+ os.flush();
} catch (rdr::Exception&) {
}
sock->shutdown();
@@ -134,11 +146,17 @@
return;
}
- if (clients.empty()) {
- lastConnectionTime = time(0);
- }
+ CharArray name;
+ name.buf = sock->getPeerEndpoint();
+ connectionsLog.status("accepted: %s", name.buf);
+
+ // Adjust the exit timers
+ if (rfb::Server::maxConnectionTime && clients.empty())
+ connectTimer.start(secsToMillis(rfb::Server::maxConnectionTime));
+ disconnectTimer.stop();
VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing);
+ clients.push_front(client);
client->init();
}
@@ -147,9 +165,24 @@
std::list<VNCSConnectionST*>::iterator ci;
for (ci = clients.begin(); ci != clients.end(); ci++) {
if ((*ci)->getSock() == sock) {
+ clients.remove(*ci);
+
+ // - Release the cursor if this client owns it
+ if (pointerClient == *ci)
+ pointerClient = NULL;
+
+ // Adjust the exit timers
+ connectTimer.stop();
+ if (rfb::Server::maxDisconnectionTime && clients.empty())
+ disconnectTimer.start(secsToMillis(rfb::Server::maxDisconnectionTime));
+
// - Delete the per-Socket resources
delete *ci;
+ CharArray name;
+ name.buf = sock->getPeerEndpoint();
+ connectionsLog.status("closed: %s", name.buf);
+
// - Check that the desktop object is still required
if (authClientCount() == 0)
stopDesktop();
@@ -191,89 +224,6 @@
throw rdr::Exception("invalid Socket in VNCServerST");
}
-int VNCServerST::checkTimeouts()
-{
- int timeout = 0;
- std::list<VNCSConnectionST*>::iterator ci, ci_next;
-
- soonestTimeout(&timeout, Timer::checkTimeouts());
-
- for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
- ci_next = ci; ci_next++;
- soonestTimeout(&timeout, (*ci)->checkIdleTimeout());
- }
-
- int timeLeft;
- time_t now = time(0);
-
- // Check MaxDisconnectionTime
- if (rfb::Server::maxDisconnectionTime && clients.empty()) {
- if (now < lastDisconnectTime) {
- // Someone must have set the time backwards.
- slog.info("Time has gone backwards - resetting lastDisconnectTime");
- lastDisconnectTime = now;
- }
- timeLeft = lastDisconnectTime + rfb::Server::maxDisconnectionTime - now;
- if (timeLeft < -60) {
- // Someone must have set the time forwards.
- slog.info("Time has gone forwards - resetting lastDisconnectTime");
- lastDisconnectTime = now;
- timeLeft = rfb::Server::maxDisconnectionTime;
- }
- if (timeLeft <= 0) {
- slog.info("MaxDisconnectionTime reached, exiting");
- exit(0);
- }
- soonestTimeout(&timeout, timeLeft * 1000);
- }
-
- // Check MaxConnectionTime
- if (rfb::Server::maxConnectionTime && lastConnectionTime && !clients.empty()) {
- if (now < lastConnectionTime) {
- // Someone must have set the time backwards.
- slog.info("Time has gone backwards - resetting lastConnectionTime");
- lastConnectionTime = now;
- }
- timeLeft = lastConnectionTime + rfb::Server::maxConnectionTime - now;
- if (timeLeft < -60) {
- // Someone must have set the time forwards.
- slog.info("Time has gone forwards - resetting lastConnectionTime");
- lastConnectionTime = now;
- timeLeft = rfb::Server::maxConnectionTime;
- }
- if (timeLeft <= 0) {
- slog.info("MaxConnectionTime reached, exiting");
- exit(0);
- }
- soonestTimeout(&timeout, timeLeft * 1000);
- }
-
-
- // Check MaxIdleTime
- if (rfb::Server::maxIdleTime) {
- if (now < lastUserInputTime) {
- // Someone must have set the time backwards.
- slog.info("Time has gone backwards - resetting lastUserInputTime");
- lastUserInputTime = now;
- }
- timeLeft = lastUserInputTime + rfb::Server::maxIdleTime - now;
- if (timeLeft < -60) {
- // Someone must have set the time forwards.
- slog.info("Time has gone forwards - resetting lastUserInputTime");
- lastUserInputTime = now;
- timeLeft = rfb::Server::maxIdleTime;
- }
- if (timeLeft <= 0) {
- slog.info("MaxIdleTime reached, exiting");
- exit(0);
- }
- soonestTimeout(&timeout, timeLeft * 1000);
- }
-
- return timeout;
-}
-
-
// VNCServer methods
void VNCServerST::blockUpdates()
@@ -467,6 +417,83 @@
}
}
+// Event handlers
+
+void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
+{
+ if (rfb::Server::maxIdleTime)
+ idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+
+ // Remap the key if required
+ if (keyRemapper) {
+ rdr::U32 newkey;
+ newkey = keyRemapper->remapKey(keysym);
+ if (newkey != keysym) {
+ slog.debug("Key remapped to 0x%x", newkey);
+ keysym = newkey;
+ }
+ }
+
+ desktop->keyEvent(keysym, keycode, down);
+}
+
+void VNCServerST::pointerEvent(VNCSConnectionST* client,
+ const Point& pos, int buttonMask)
+{
+ if (rfb::Server::maxIdleTime)
+ idleTimer.start(secsToMillis(rfb::Server::maxIdleTime));
+
+ // Let one client own the cursor whilst buttons are pressed in order
+ // to provide a bit more sane user experience
+ if ((pointerClient != NULL) && (pointerClient != client))
+ return;
+
+ if (buttonMask)
+ pointerClient = client;
+ else
+ pointerClient = NULL;
+
+ desktop->pointerEvent(pos, buttonMask);
+}
+
+void VNCServerST::clientCutText(const char* str, int len)
+{
+ desktop->clientCutText(str, len);
+}
+
+unsigned int VNCServerST::setDesktopSize(VNCSConnectionST* requester,
+ int fb_width, int fb_height,
+ const ScreenSet& layout)
+{
+ unsigned int result;
+ std::list<VNCSConnectionST*>::iterator ci, ci_next;
+
+ // Don't bother the desktop with an invalid configuration
+ if (!layout.validate(fb_width, fb_height))
+ return resultInvalid;
+
+ // FIXME: the desktop will call back to VNCServerST and an extra set
+ // of ExtendedDesktopSize messages will be sent. This is okay
+ // protocol-wise, but unnecessary.
+ result = desktop->setScreenLayout(fb_width, fb_height, layout);
+ if (result != resultSuccess)
+ return result;
+
+ // Sanity check
+ if (screenLayout != layout)
+ throw Exception("Desktop configured a different screen layout than requested");
+
+ // Notify other clients
+ for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
+ ci_next = ci; ci_next++;
+ if ((*ci) == requester)
+ continue;
+ (*ci)->screenLayoutChangeOrClose(reasonOtherClient);
+ }
+
+ return resultSuccess;
+}
+
// Other public methods
void VNCServerST::approveConnection(network::Socket* sock, bool accept,
@@ -504,7 +531,7 @@
}
}
-SConnection* VNCServerST::getSConnection(network::Socket* sock) {
+SConnection* VNCServerST::getConnection(network::Socket* sock) {
std::list<VNCSConnectionST*>::iterator ci;
for (ci = clients.begin(); ci != clients.end(); ci++) {
if ((*ci)->getSock() == sock)
@@ -529,11 +556,77 @@
}
return true;
+ } else if (t == &idleTimer) {
+ slog.info("MaxIdleTime reached, exiting");
+ desktop->terminate();
+ } else if (t == &disconnectTimer) {
+ slog.info("MaxDisconnectionTime reached, exiting");
+ desktop->terminate();
+ } else if (t == &connectTimer) {
+ slog.info("MaxConnectionTime reached, exiting");
+ desktop->terminate();
}
return false;
}
+void VNCServerST::queryConnection(VNCSConnectionST* client,
+ const char* userName)
+{
+ // - Authentication succeeded - clear from blacklist
+ CharArray name;
+ name.buf = client->getSock()->getPeerAddress();
+ blHosts->clearBlackmark(name.buf);
+
+ // - Prepare the desktop for that the client will start requiring
+ // resources after this
+ startDesktop();
+
+ // - Special case to provide a more useful error message
+ if (rfb::Server::neverShared &&
+ !rfb::Server::disconnectClients &&
+ authClientCount() > 0) {
+ approveConnection(client->getSock(), false,
+ "The server is already in use");
+ return;
+ }
+
+ // - Are we configured to do queries?
+ if (!rfb::Server::queryConnect &&
+ !client->getSock()->requiresQuery()) {
+ approveConnection(client->getSock(), true, NULL);
+ return;
+ }
+
+ // - Does the client have the right to bypass the query?
+ if (client->accessCheck(SConnection::AccessNoQuery))
+ {
+ approveConnection(client->getSock(), true, NULL);
+ return;
+ }
+
+ desktop->queryConnection(client->getSock(), userName);
+}
+
+void VNCServerST::clientReady(VNCSConnectionST* client, bool shared)
+{
+ if (!shared) {
+ if (rfb::Server::disconnectClients &&
+ client->accessCheck(SConnection::AccessNonShared)) {
+ // - Close all the other connected clients
+ slog.debug("non-shared connection - closing clients");
+ closeClients("Non-shared connection requested", client->getSock());
+ } else {
+ // - Refuse this connection if there are existing clients, in addition to
+ // this one
+ if (authClientCount() > 1) {
+ client->close("Server is already in use");
+ return;
+ }
+ }
+ }
+}
+
// -=- Internal methods
void VNCServerST::startDesktop()
@@ -689,50 +782,6 @@
return &renderedCursor;
}
-void VNCServerST::getConnInfo(ListConnInfo * listConn)
-{
- listConn->Clear();
- listConn->setDisable(getDisable());
- if (clients.empty())
- return;
- std::list<VNCSConnectionST*>::iterator i;
- for (i = clients.begin(); i != clients.end(); i++)
- listConn->addInfo((void*)(*i), (*i)->getSock()->getPeerAddress(),
- (*i)->getStartTime(), (*i)->getStatus());
-}
-
-void VNCServerST::setConnStatus(ListConnInfo* listConn)
-{
- setDisable(listConn->getDisable());
- if (listConn->Empty() || clients.empty()) return;
- for (listConn->iBegin(); !listConn->iEnd(); listConn->iNext()) {
- VNCSConnectionST* conn = (VNCSConnectionST*)listConn->iGetConn();
- std::list<VNCSConnectionST*>::iterator i;
- for (i = clients.begin(); i != clients.end(); i++) {
- if ((*i) == conn) {
- int status = listConn->iGetStatus();
- if (status == 3) {
- (*i)->close(0);
- } else {
- (*i)->setStatus(status);
- }
- break;
- }
- }
- }
-}
-
-void VNCServerST::notifyScreenLayoutChange(VNCSConnectionST* requester)
-{
- std::list<VNCSConnectionST*>::iterator ci, ci_next;
- for (ci=clients.begin();ci!=clients.end();ci=ci_next) {
- ci_next = ci; ci_next++;
- if ((*ci) == requester)
- continue;
- (*ci)->screenLayoutChangeOrClose(reasonOtherClient);
- }
-}
-
bool VNCServerST::getComparerState()
{
if (rfb::Server::compareFB == 0)
diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h
index b7845dd..43a3bb9 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -28,11 +28,9 @@
#include <rfb/SDesktop.h>
#include <rfb/VNCServer.h>
-#include <rfb/LogWriter.h>
#include <rfb/Blacklist.h>
#include <rfb/Cursor.h>
#include <rfb/Timer.h>
-#include <network/Socket.h>
#include <rfb/ScreenSet.h>
namespace rfb {
@@ -44,8 +42,7 @@
class KeyRemapper;
class VNCServerST : public VNCServer,
- public Timer::Callback,
- public network::SocketServer {
+ public Timer::Callback {
public:
// -=- Constructors
@@ -79,12 +76,6 @@
// Flush pending data from the Socket on to the network.
virtual void processSocketWriteEvent(network::Socket* sock);
- // checkTimeouts
- // Returns the number of milliseconds left until the next idle timeout
- // expires. If any have already expired, the corresponding connections
- // are closed. Zero is returned if there is no idle timeout.
- virtual int checkTimeouts();
-
// Methods overridden from VNCServer
@@ -93,102 +84,70 @@
virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout);
virtual void setPixelBuffer(PixelBuffer* pb);
virtual void setScreenLayout(const ScreenSet& layout);
- virtual PixelBuffer* getPixelBuffer() const { return pb; }
+ virtual const PixelBuffer* getPixelBuffer() const { return pb; }
virtual void serverCutText(const char* str, int len);
+
+ virtual void approveConnection(network::Socket* sock, bool accept,
+ const char* reason);
+ virtual void closeClients(const char* reason) {closeClients(reason, 0);}
+ virtual SConnection* getConnection(network::Socket* sock);
+
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 setName(const char* name_);
virtual void setLEDState(unsigned state);
virtual void bell();
- // - Close all currently-connected clients, by calling
- // their close() method with the supplied reason.
- virtual void closeClients(const char* reason) {closeClients(reason, 0);}
-
// VNCServerST-only methods
+ // Methods to get the currently set server state
+
+ const ScreenSet& getScreenLayout() const { return screenLayout; }
+ const Cursor* getCursor() const { return cursor; }
+ const Point& getCursorPos() const { return cursorPos; }
+ const char* getName() const { return name.buf; }
+ unsigned getLEDState() const { return ledState; }
+
+ // Event handlers
+ void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
+ void pointerEvent(VNCSConnectionST* client, const Point& pos, int buttonMask);
+ void clientCutText(const char* str, int len);
+
+ unsigned int setDesktopSize(VNCSConnectionST* requester,
+ int fb_width, int fb_height,
+ const ScreenSet& layout);
+
// closeClients() closes all RFB sessions, except the specified one (if
// any), and logs the specified reason for closure.
void closeClients(const char* reason, network::Socket* sock);
- // getSConnection() gets the SConnection for a particular Socket. If
- // the Socket is not recognised then null is returned.
+ // queryConnection() does some basic checks and then passes on the
+ // request to the desktop.
+ void queryConnection(VNCSConnectionST* client, const char* userName);
- SConnection* getSConnection(network::Socket* sock);
+ // clientReady() is called by a VNCSConnectionST instance when the
+ // client has completed the handshake and is ready for normal
+ // communication.
+ void clientReady(VNCSConnectionST* client, bool shared);
- // getName() returns the name of this VNC Server. NB: The value returned
- // is the server's internal buffer which may change after any other methods
- // are called - take a copy if necessary.
- const char* getName() const {return name.buf;}
+ // Estimated time until the next time new updates will be pushed
+ // to clients
+ int msToNextUpdate();
- // setName() specifies the desktop name that the server should provide to
- // clients
- virtual void setName(const char* name_);
+ // Part of the framebuffer that has been modified but is not yet
+ // ready to be sent to clients
+ Region getPendingRegion();
- // A QueryConnectionHandler, if supplied, is passed details of incoming
- // connections to approve, reject, or query the user about.
- //
- // queryConnection() is called when a connection has been
- // successfully authenticated. The sock and userName arguments identify
- // the socket and the name of the authenticated user, if any. It should
- // return ACCEPT if the connection should be accepted, REJECT if it should
- // be rejected, or PENDING if a decision cannot yet be reached. If REJECT
- // is returned, *reason can be set to a string describing the reason - this
- // will be delete[]ed when it is finished with. If PENDING is returned,
- // approveConnection() must be called some time later to accept or reject
- // the connection.
- enum queryResult { ACCEPT, REJECT, PENDING };
- struct QueryConnectionHandler {
- virtual ~QueryConnectionHandler() {}
- virtual queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason) = 0;
- };
- void setQueryConnectionHandler(QueryConnectionHandler* qch) {
- queryConnectionHandler = qch;
- }
-
- // queryConnection is called as described above, and either passes the
- // request on to the registered handler, or accepts the connection if
- // no handler has been specified.
- virtual queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason) {
- return queryConnectionHandler
- ? queryConnectionHandler->queryConnection(sock, userName, reason)
- : ACCEPT;
- }
-
- // approveConnection() is called by the active QueryConnectionHandler,
- // some time after queryConnection() has returned with PENDING, to accept
- // or reject the connection. The accept argument should be true for
- // acceptance, or false for rejection, in which case a string reason may
- // also be given.
- void approveConnection(network::Socket* sock, bool accept,
- const char* reason);
-
- // setBlacklist() is called to replace the VNCServerST's internal
- // Blacklist instance with another instance. This allows a single
- // Blacklist to be shared by multiple VNCServerST instances.
- void setBlacklist(Blacklist* bl) {blHosts = bl ? bl : &blacklist;}
-
- // setKeyRemapper() replaces the VNCServerST's default key remapper.
- // NB: A null pointer is valid here.
- void setKeyRemapper(KeyRemapper* kr) { keyRemapper = kr; }
-
- void getConnInfo(ListConnInfo * listConn);
- void setConnStatus(ListConnInfo* listConn);
-
- bool getDisable() { return disableclients;};
- void setDisable(bool disable) { disableclients = disable;};
+ // getRenderedCursor() returns an up to date version of the server
+ // side rendered cursor buffer
+ const RenderedCursor* getRenderedCursor();
protected:
- friend class VNCSConnectionST;
-
// Timer callbacks
virtual bool handleTimeout(Timer* t);
@@ -197,7 +156,17 @@
void startDesktop();
void stopDesktop();
- static LogWriter connectionsLog;
+ // - Check how many of the clients are authenticated.
+ int authClientCount();
+
+ bool needRenderedCursor();
+ void startFrameClock();
+ void stopFrameClock();
+ void writeUpdate();
+
+ bool getComparerState();
+
+ protected:
Blacklist blacklist;
Blacklist* blHosts;
@@ -221,29 +190,11 @@
RenderedCursor renderedCursor;
bool renderedCursorInvalid;
- // - Check how many of the clients are authenticated.
- int authClientCount();
-
- bool needRenderedCursor();
- void startFrameClock();
- void stopFrameClock();
- int msToNextUpdate();
- void writeUpdate();
- Region getPendingRegion();
- const RenderedCursor* getRenderedCursor();
-
- void notifyScreenLayoutChange(VNCSConnectionST *requester);
-
- bool getComparerState();
-
- QueryConnectionHandler* queryConnectionHandler;
KeyRemapper* keyRemapper;
- time_t lastUserInputTime;
- time_t lastDisconnectTime;
- time_t lastConnectionTime;
-
- bool disableclients;
+ Timer idleTimer;
+ Timer disconnectTimer;
+ Timer connectTimer;
Timer frameTimer;
};
diff --git a/common/rfb/util.h b/common/rfb/util.h
index b678b89..9e59bd3 100644
--- a/common/rfb/util.h
+++ b/common/rfb/util.h
@@ -50,7 +50,7 @@
CharArray() : buf(0) {}
CharArray(char* str) : buf(str) {} // note: assumes ownership
CharArray(int len) {
- buf = new char[len];
+ buf = new char[len]();
}
~CharArray() {
delete [] buf;
diff --git a/contrib/packages/deb/ubuntu-precise/debian/copyright b/contrib/packages/deb/ubuntu-precise/debian/copyright
index 003dcc4..290fbdf 100644
--- a/contrib/packages/deb/ubuntu-precise/debian/copyright
+++ b/contrib/packages/deb/ubuntu-precise/debian/copyright
@@ -2,7 +2,7 @@
on Tue, 02 Jul 2013 21:33:24 +0500 using the tightvnc package as a base.
It was downloaded from:
- http://www.tigervnc.org/
+ https://www.tigervnc.org/
COPYRIGHT:
==========
diff --git a/contrib/packages/deb/ubuntu-trusty/debian/copyright b/contrib/packages/deb/ubuntu-trusty/debian/copyright
index 003dcc4..290fbdf 100644
--- a/contrib/packages/deb/ubuntu-trusty/debian/copyright
+++ b/contrib/packages/deb/ubuntu-trusty/debian/copyright
@@ -2,7 +2,7 @@
on Tue, 02 Jul 2013 21:33:24 +0500 using the tightvnc package as a base.
It was downloaded from:
- http://www.tigervnc.org/
+ https://www.tigervnc.org/
COPYRIGHT:
==========
diff --git a/contrib/packages/deb/ubuntu-xenial/debian/copyright b/contrib/packages/deb/ubuntu-xenial/debian/copyright
index 003dcc4..290fbdf 100644
--- a/contrib/packages/deb/ubuntu-xenial/debian/copyright
+++ b/contrib/packages/deb/ubuntu-xenial/debian/copyright
@@ -2,7 +2,7 @@
on Tue, 02 Jul 2013 21:33:24 +0500 using the tightvnc package as a base.
It was downloaded from:
- http://www.tigervnc.org/
+ https://www.tigervnc.org/
COPYRIGHT:
==========
diff --git a/contrib/packages/rpm/el5/SPECS/tigervnc.spec b/contrib/packages/rpm/el5/SPECS/tigervnc.spec
index 51388af..f83c15a 100644
--- a/contrib/packages/rpm/el5/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el5/SPECS/tigervnc.spec
@@ -115,7 +115,6 @@
# xorg requires newer versions of automake, & autoconf than are available with el5. Use el6 versions.
BuildRequires: automake >= 1.11, autoconf >= 2.60, libtool >= 1.4, gettext >= 0.14.4, gettext-devel >= 0.14.4, bison-devel, python26
-BuildRequires: java-devel, jpackage-utils
BuildRequires: pam-devel
BuildRequires: cmake28
BuildRequires: pkgconfig >= 0.20
@@ -247,18 +246,6 @@
of TigerVNC server, allowing others to access the desktop on your
machine.
-%package server-applet
-Summary: Java TigerVNC viewer applet for TigerVNC server
-Group: User Interface/X
-Requires: tigervnc-server, java, jpackage-utils
-%if 0%{?fedora} >= 10 || 0%{?rhel} >= 6 || 0%{?centos} >= 6
-BuildArch: noarch
-%endif
-
-%description server-applet
-The Java TigerVNC viewer applet for web browsers. Install this package to allow
-clients to use web browser when connect to the TigerVNC server.
-
%package license
Summary: License of TigerVNC suite
Group: User Interface/X
@@ -885,7 +872,7 @@
--prefix=%{_prefix} --libdir=%{_libdir} --mandir=%{_datadir}/man \
--sysconfdir=%{_sysconfdir} --localstatedir=%{_localstatedir} \
--with-vendor-name="The TigerVNC Project" --with-vendor-name-short="TigerVNC" \
- --with-vendor-web="http://www.tigervnc.org" \
+ --with-vendor-web="https://www.tigervnc.org" \
--disable-xorg --disable-xnest --disable-xvfb --disable-dmx \
--disable-xwin --disable-xephyr --disable-kdrive --disable-wayland \
--with-pic --enable-static --disable-shared --enable-xinerama \
@@ -915,21 +902,6 @@
make
popd
-# Build Java applet
-pushd java
-%{cmake28} \
-%if !%{_self_signed}
- -DJAVA_KEYSTORE=%{_keystore} \
- -DJAVA_KEYSTORE_TYPE=%{_keystore_type} \
- -DJAVA_KEY_ALIAS=%{_key_alias} \
- -DJAVA_STOREPASS=":env STOREPASS" \
- -DJAVA_KEYPASS=":env KEYPASS" \
- -DJAVA_TSA_URL=https://timestamp.geotrust.com/tsa .
-%endif
-
-JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" make
-popd
-
%install
make install DESTDIR=$RPM_BUILD_ROOT
@@ -948,13 +920,6 @@
install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers
-# Install Java applet
-pushd java
-mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m644 com/tigervnc/vncviewer/index.vnc $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-popd
-
%find_lang %{name} %{name}.lang
%if %{_bootstrap}
@@ -1024,11 +989,6 @@
%{_mandir}/man1/vncconfig.1*
%{_libdir}/*
-%files server-applet
-%defattr(-,root,root,-)
-%doc java/com/tigervnc/vncviewer/README
-%{_datadir}/vnc/classes/*
-
%files license
%defattr(-,root,root,-)
%doc LICENCE.TXT
diff --git a/contrib/packages/rpm/el6/SPECS/tigervnc.spec b/contrib/packages/rpm/el6/SPECS/tigervnc.spec
index 09843b2..5019399 100644
--- a/contrib/packages/rpm/el6/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el6/SPECS/tigervnc.spec
@@ -37,7 +37,6 @@
BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel
BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick
BuildRequires: freetype-devel, libXdmcp-devel
-BuildRequires: java-devel, jpackage-utils
BuildRequires: libjpeg-turbo-devel, pam-devel
BuildRequires: cmake >= 2.8
%if !%{_bootstrap}
@@ -120,16 +119,6 @@
to access the desktop on your machine.
%endif
-%package server-applet
-Summary: Java TigerVNC viewer applet for TigerVNC server
-Group: User Interface/X
-Requires: tigervnc-server, java, jpackage-utils
-BuildArch: noarch
-
-%description server-applet
-The Java TigerVNC viewer applet for web browsers. Install this package to allow
-clients to use web browser when connect to the TigerVNC server.
-
%package license
Summary: License of TigerVNC suite
Group: User Interface/X
@@ -326,21 +315,6 @@
make
popd
-# Build Java applet
-pushd java
-%{cmake} \
-%if !%{_self_signed}
- -DJAVA_KEYSTORE=%{_keystore} \
- -DJAVA_KEYSTORE_TYPE=%{_keystore_type} \
- -DJAVA_KEY_ALIAS=%{_key_alias} \
- -DJAVA_STOREPASS=":env STOREPASS" \
- -DJAVA_KEYPASS=":env KEYPASS" \
- -DJAVA_TSA_URL=http://timestamp.geotrust.com/tsa .
-%endif
-
-make
-popd
-
%install
%if %{_bootstrap}
for l in gmp libtasn1 nettle gnutls libpng fltk; do
@@ -364,13 +338,6 @@
install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers
-# Install Java applet
-pushd java
-mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m644 com/tigervnc/vncviewer/index.vnc $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-popd
-
%find_lang %{name} %{name}.lang
# remove unwanted files
@@ -433,11 +400,6 @@
%{_libdir}/xorg/modules/extensions/libvnc.so
%endif
-%files server-applet
-%defattr(-,root,root,-)
-%doc java/com/tigervnc/vncviewer/README
-%{_datadir}/vnc/classes/*
-
%files license
%defattr(-,root,root,-)
%doc LICENCE.TXT
diff --git a/contrib/packages/rpm/el7/SPECS/tigervnc.spec b/contrib/packages/rpm/el7/SPECS/tigervnc.spec
index ec36ccc..1b8630a 100644
--- a/contrib/packages/rpm/el7/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el7/SPECS/tigervnc.spec
@@ -32,7 +32,6 @@
BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel
BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick
BuildRequires: freetype-devel, libXdmcp-devel, libXfont2-devel
-BuildRequires: java-devel, jpackage-utils
BuildRequires: libjpeg-turbo-devel, gnutls-devel, pam-devel
BuildRequires: systemd, cmake
@@ -114,16 +113,6 @@
to access the desktop on your machine.
%endif
-%package server-applet
-Summary: Java TigerVNC viewer applet for TigerVNC server
-Group: User Interface/X
-Requires: tigervnc-server, java, jpackage-utils
-BuildArch: noarch
-
-%description server-applet
-The Java TigerVNC viewer applet for web browsers. Install this package to allow
-clients to use web browser when connect to the TigerVNC server.
-
%package license
Summary: License of TigerVNC suite
Group: User Interface/X
@@ -250,21 +239,6 @@
make
popd
-# Build Java applet
-pushd java
-%{cmake} \
-%if !%{_self_signed}
- -DJAVA_KEYSTORE=%{_keystore} \
- -DJAVA_KEYSTORE_TYPE=%{_keystore_type} \
- -DJAVA_KEY_ALIAS=%{_key_alias} \
- -DJAVA_STOREPASS=":env STOREPASS" \
- -DJAVA_KEYPASS=":env KEYPASS" \
- -DJAVA_TSA_URL=http://timestamp.geotrust.com/tsa .
-%endif
-
-make
-popd
-
%install
%if %{_bootstrap}
for l in fltk; do
@@ -291,13 +265,6 @@
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers
-# Install Java applet
-pushd java
-mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-install -m644 com/tigervnc/vncviewer/index.vnc $RPM_BUILD_ROOT%{_datadir}/vnc/classes
-popd
-
%find_lang %{name} %{name}.lang
# remove unwanted files
@@ -370,11 +337,6 @@
%config %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf
%endif
-%files server-applet
-%defattr(-,root,root,-)
-%doc java/com/tigervnc/vncviewer/README
-%{_datadir}/vnc/classes/*
-
%files license
%doc %{_docdir}/%{name}-%{version}/LICENCE.TXT
diff --git a/doc/keyboard-test.txt b/doc/keyboard-test.txt
index e839177..e5fcbd7 100644
--- a/doc/keyboard-test.txt
+++ b/doc/keyboard-test.txt
@@ -4,9 +4,11 @@
Platform specific tests/issues are marked with [].
These tests are primarily about what is sent over the protocol and some
-may be difficult or impossible to test using normal applications. In
-these cases you can turn on debug logging in either the client or the
-server by specifying "-Log *:stderr:100".
+may be difficult or impossible to test using normal applications. One
+such case is that xev will see fake KeyRelease events on key repeat,
+even when no such events were sent by the client. In these cases you
+can turn on debug logging in either the client or the server by
+specifying "-Log *:stderr:100".
We currently have a limitation in Xvnc where it can run out of symbols,
resulting in nothing being sent to the applications. Just run setxkbmap
@@ -103,7 +105,7 @@
- F1-F24 (FIXME: F14-F15 broken on OS X)
- Tab, Space, Backspace, Return, Esc
- - LeftTab sends Tab [X11?]
+ - LeftTab sends Tab [X11]
- PrntScrn, ScrollLock, Pause [X11, Win]
- Help [X11?, OS X]
- Insert [X11, Win]
@@ -157,6 +159,45 @@
- CapsLock
- NumLock (hidden state on macOS)
- - ScollLock [X11, Win]
+ - ScollLock* [X11, Win]
+
+ * Usually needs to be enabled with: xmodmap -e "add mod3 = Scroll_Lock"
- Virtual keyboard (as much of the above as is possible)
+
+Server
+------
+
+- Fake key events
+
+ An extra press or release should be added before the real key press
+ in order to get the correct state to get the desired symbol. A second
+ fake event should be added after the real key press to restore state.
+ No extra events should be added for a key release.
+
+ Possible fake keys:
+
+ - Shift
+ - AltGr
+
+ - Shift+Tab bypasses this and never fake releases Shift
+
+- Alternative keys
+
+ A semantically equivalent key is sent when the desired key cannot be
+ reached in the current keyboard state:
+
+ - Left modifier <=> Right modifier (e.g. Alt_R for Alt_L)
+ - Keypad key <=> Standard key
+ - ISO_Level3_Shift <=> Mode_Switch
+
+- Meta for Shift+Alt (if server keymap agrees)
+
+- Lock key heuristics (for clients without lock key extension)
+
+ - CapsLock is corrected when A-Z or a-z are pressed
+ - CapsLock is corrected when Shift and A-Z or a-z are pressed*
+ - NumLock is corrected when 0-9 on the keypad are pressed
+
+ * Gives incorrect behaviour if the client doesn't have "Shift cancels
+ CapsLock behaviour", e.g. macOS
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
index 340dec1..23137f7 100644
--- a/java/CMakeLists.txt
+++ b/java/CMakeLists.txt
@@ -177,12 +177,3 @@
-P ${SRCDIR}/cmake/SignJar.cmake)
add_custom_target(java ALL DEPENDS VncViewer.jar)
-
-if(NOT WIN32)
- install(FILES
- ${BINDIR}/VncViewer.jar
- ${SRCDIR}/${CLASSPATH}/README
- ${SRCDIR}/${CLASSPATH}/index.vnc
- ${SRCDIR}/${CLASSPATH}/favicon.ico
- DESTINATION ${DATA_DIR}/vnc/classes)
-endif()
diff --git a/java/com/tigervnc/vncviewer/README b/java/com/tigervnc/vncviewer/README
index d0baa93..3019f8d 100644
--- a/java/com/tigervnc/vncviewer/README
+++ b/java/com/tigervnc/vncviewer/README
@@ -27,86 +27,24 @@
Installation
============
-There are three basic ways to use the TigerVNC Java Viewer:
+The TigerVNC Java Viewer requires installation of either a JRE (Java
+Runtime Environment) or a JDK (Java Development Kit). If VncViewer.jar is
+in the current directory, then the TigerVNC Java Viewer can be launched
+with the following command line:
- 1. Running the applet as part of a TigerVNC Server installation.
+ java -jar VncViewer.jar [parameters]
- Both the Unix and Windows versions of the TigerVNC Server include a small
- built-in HTTP server that can serve the TigerVNC Java Viewer to web
- clients. This enables easy access to the shared desktop without the need
- to install any software on the client machine.
-
- The Unix TigerVNC Server (Xvnc) is able to serve up any set of files that
- are present in a particular directory, which is specified in the -httpd
- argument to Xvnc. The default version of the vncserver script will look
- for a directory called vnc/classes, one level up from the directory
- containing the vncserver script, then it will look for a directory called
- /usr/share/vnc/classes, then /usr/local/vnc/classes. It will set the
- -httpd argument to Xvnc to the first one of these VNC classes directories
- it finds. Thus, one can easily deploy a modified version of the TigerVNC
- Java Viewer by simply copying a new version of VncViewer.jar and/or
- index.vnc into the VNC classes directory.
-
- On Windows and Linux, the embedded applet can be drag-undocked from the
- browser window and converted to a standalone application. The drag
- gesture ALT+drag on Windows, and SHIFT+drag on Linux.
-
- In the case of the Windows TigerVNC Server, VncViewer.jar and index.vnc
- are embedded as resources in the WinVNC executable, so deploying a
- modified version of the TigerVNC Java Viewer on a Windows server requires
- rebuilding WinVNC.
-
- 2. Running the applet from a standalone web server.
-
- Another possibility for using the TigerVNC Java Viewer is to install it
- under a fully-functional HTTP server, such as Apache or IIS. Due to Java
- security restrictions, the applet must be signed in order for it to
- connect to a VNC server running on a different machine from the HTTP
- server.
-
- One can install the TigerVNC Java Viewer by simply copying the .class and
- .jar files into a directory that is under the control of the HTTP server.
- Also, an HTML page should be created to act as a the base document for the
- TigerVNC Java Viewer applet (an example named index.html is provided in
- this directory. Modify this file to suit your specific needs.)
-
- 3. Running the viewer as a standalone application.
-
- Finally, the TigerVNC Java Viewer can be executed locally on the client
- machine, but this method requires installation of either a JRE (Java
- Runtime Environment) or a JDK (Java Development Kit). If VncViewer.jar is
- in the current directory, then the TigerVNC Java Viewer can be launched
- with the following command line:
-
- java -jar VncViewer.jar [parameters]
-
- Add an argument of -? to the above command line to print a list of
- optional parameters supported by VncViewer.
+Add an argument of -? to the above command line to print a list of
+optional parameters supported by VncViewer.
Parameters
==========
The TigerVNC Java Viewer accepts a number of optional parameters, allowing you
-to customize its behavior.
+to customize its behavior. Example:
-Parameters can be specified in one of the two ways, depending on how the
-TigerVNC Java Viewer is used:
-
- 1. When the TigerVNC Java Viewer is run as an applet (embedded within an HTML
- document), parameters should be specified using the <PARAM> HTML tags
- within the appropriate <APPLET> section. Example:
-
- <APPLET CODE=com.tigervnc.vncviewer.VncViewer ARCHIVE=VncViewer.jar
- WIDTH=400 HEIGHT=300>
- <PARAM NAME="PORT" VALUE=5901>
- <PARAM NAME="ScalingFactor" VALUE=50>
- </APPLET>
-
- 2. When run as a standalone application, the TigerVNC Java Viewer reads
- parameters from the command line. Example:
-
- java -jar VncViewer.jar Port=5901 ScalingFactor=50
+ java -jar VncViewer.jar Port=5901 ScalingFactor=50
Both parameter names and their values are case-insensitive.
diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java
index f96e2ec..2ef6bcf 100644
--- a/java/com/tigervnc/vncviewer/VncViewer.java
+++ b/java/com/tigervnc/vncviewer/VncViewer.java
@@ -66,7 +66,7 @@
new String("TigerVNC Java Viewer v%s (%s)%n"+
"Built on %s at %s%n"+
"Copyright (C) 1999-2018 TigerVNC Team and many others (see README.rst)%n"+
- "See http://www.tigervnc.org for information on TigerVNC.");
+ "See https://www.tigervnc.org for information on TigerVNC.");
public static String version = null;
public static String build = null;
diff --git a/java/com/tigervnc/vncviewer/favicon.ico b/java/com/tigervnc/vncviewer/favicon.ico
deleted file mode 100644
index edbd467..0000000
--- a/java/com/tigervnc/vncviewer/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/java/com/tigervnc/vncviewer/index.html b/java/com/tigervnc/vncviewer/index.html
deleted file mode 100644
index ba00e26..0000000
--- a/java/com/tigervnc/vncviewer/index.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
- index.html - an example HTML page for the TigerVNC Java Viewer applet, to
- be used with a standalone web server. Before using this example, please
- MAKE SURE to check the following:
-
- * the CODE and ARCHIVE attributes of the <APPLET> tag should point to
- the correct directory (this example assumes that this page is in the
- same directory as VncViewer.jar);
--->
-
-<HTML>
-<TITLE>
-TigerVNC desktop
-</TITLE>
-<APPLET CODE="com.tigervnc.vncviewer.VncViewer" ARCHIVE="VncViewer.jar"
- WIDTH=500>
-</APPLET>
-<BR>
-<A href="http://www.tigervnc.org/">TigerVNC site</A>
-</HTML>
diff --git a/java/com/tigervnc/vncviewer/index.vnc b/java/com/tigervnc/vncviewer/index.vnc
deleted file mode 100644
index 27bdebc..0000000
--- a/java/com/tigervnc/vncviewer/index.vnc
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- index.vnc - default HTML page for TigerVNC Java viewer applet, to be
- used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
- Xvnc will substitute the following variables when preceded by a dollar:
- USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
- Use two dollar signs ($$) to get a dollar sign in the generated
- HTML page.
--->
-
-<HTML>
-<TITLE>
-$USER's $DESKTOP desktop ($DISPLAY)
-</TITLE>
-<APPLET CODE=com.tigervnc.vncviewer.VncViewer ARCHIVE=VncViewer.jar
- WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
-<param name=PORT value=$PORT>
-<param name="Embed" value="true">
-<param name="draggable" value="true">
-</APPLET>
-<BR>
-<A href="http://www.tigervnc.org/">TigerVNC site</A>
-</HTML>
diff --git a/po/da.po b/po/da.po
index 1859f44..1577051 100644
--- a/po/da.po
+++ b/po/da.po
@@ -1,15 +1,15 @@
# Danish translation of tigervnc.
-# Copyright (C) 2017 the TigerVNC Team (msgids)
+# Copyright (C) 2018 the TigerVNC Team (msgids)
# This file is distributed under the same license as the tigervnc package.
-# Joe Hansen <joedalton2@yahoo.dk>, 2015, 2016, 2017.
+# Joe Hansen <joedalton2@yahoo.dk>, 2015, 2016, 2017, 2018.
#
msgid ""
msgstr ""
-"Project-Id-Version: tigervnc 1.7.90\n"
+"Project-Id-Version: tigervnc 1.8.90\n"
"Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\n"
-"POT-Creation-Date: 2017-04-19 13:05+0000\n"
-"PO-Revision-Date: 2017-05-22 15:00+0000\n"
-"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"POT-Creation-Date: 2018-06-13 14:22+0000\n"
+"PO-Revision-Date: 2018-08-12 13:22+0200\n"
+"Last-Translator: joe Hansen <joedalton2@yahoo.dk>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"Language: da\n"
"MIME-Version: 1.0\n"
@@ -17,133 +17,135 @@
"Content-Transfer-Encoding: 8bit\n"
"X-Bugs: Report translation errors to the Language-Team address.\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.8.11\n"
-#: vncviewer/CConn.cxx:110
+#: vncviewer/CConn.cxx:116
+#, c-format
+msgid "connected to socket %s"
+msgstr "forbundet til soklen %s"
+
+#: vncviewer/CConn.cxx:123
#, c-format
msgid "connected to host %s port %d"
msgstr "forbundet til værten %s på port %d"
-#: vncviewer/CConn.cxx:169
+#: vncviewer/CConn.cxx:184
#, c-format
msgid "Desktop name: %.80s"
msgstr "Skrivebordsnavn: %.80s"
-#: vncviewer/CConn.cxx:174
+#: vncviewer/CConn.cxx:189
#, c-format
msgid "Host: %.80s port: %d"
msgstr "Vært: %.80s port: %d"
-#: vncviewer/CConn.cxx:179
+#: vncviewer/CConn.cxx:194
#, c-format
msgid "Size: %d x %d"
msgstr "Størrelse: %d x %d"
-#: vncviewer/CConn.cxx:187
+#: vncviewer/CConn.cxx:202
#, c-format
msgid "Pixel format: %s"
msgstr "Billedformat: %s"
-#: vncviewer/CConn.cxx:194
+#: vncviewer/CConn.cxx:209
#, c-format
msgid "(server default %s)"
msgstr "(serverstandard %s)"
-#: vncviewer/CConn.cxx:199
+#: vncviewer/CConn.cxx:214
#, c-format
msgid "Requested encoding: %s"
msgstr "Anmodt kodning: %s"
-#: vncviewer/CConn.cxx:204
+#: vncviewer/CConn.cxx:219
#, c-format
msgid "Last used encoding: %s"
msgstr "Sidst anvendt kodning: %s"
-#: vncviewer/CConn.cxx:209
+#: vncviewer/CConn.cxx:224
#, c-format
msgid "Line speed estimate: %d kbit/s"
msgstr "Linjehastighedsestimat: %d kbit/s"
-#: vncviewer/CConn.cxx:214
+#: vncviewer/CConn.cxx:229
#, c-format
msgid "Protocol version: %d.%d"
msgstr "Protokolversion: %d.%d"
-#: vncviewer/CConn.cxx:219
+#: vncviewer/CConn.cxx:234
#, c-format
msgid "Security method: %s"
msgstr "Sikkerhedsmetode: %s"
-#: vncviewer/CConn.cxx:343
+#: vncviewer/CConn.cxx:358
#, c-format
msgid "SetDesktopSize failed: %d"
msgstr "SetDesktopSize fejlede: %d"
-#: vncviewer/CConn.cxx:413
+#: vncviewer/CConn.cxx:428
msgid "Invalid SetColourMapEntries from server!"
msgstr "Ugyldig SetColourMapEntries fra server!"
-#: vncviewer/CConn.cxx:489
+#: vncviewer/CConn.cxx:479
msgid "Enabling continuous updates"
msgstr "Aktiverer fortsættende opdateringer"
-#: vncviewer/CConn.cxx:559
+#: vncviewer/CConn.cxx:556
#, c-format
msgid "Throughput %d kbit/s - changing to quality %d"
msgstr "Gennemløb %d kbit/s - ændrer til kvalitet %d"
-#: vncviewer/CConn.cxx:581
+#: vncviewer/CConn.cxx:578
#, c-format
msgid "Throughput %d kbit/s - full color is now %s"
msgstr "Gennemløb %d kbit/s - fuld farve er nu %s"
-#: vncviewer/CConn.cxx:583
+#: vncviewer/CConn.cxx:580
msgid "disabled"
msgstr "deaktiveret"
-#: vncviewer/CConn.cxx:583
+#: vncviewer/CConn.cxx:580
msgid "enabled"
msgstr "aktiveret"
-#: vncviewer/CConn.cxx:593
+#: vncviewer/CConn.cxx:590
#, c-format
msgid "Using %s encoding"
msgstr "Bruger %s-kodning"
-#: vncviewer/CConn.cxx:640
+#: vncviewer/CConn.cxx:637
#, c-format
msgid "Using pixel format %s"
msgstr "Bruger billedpunktsformat %s"
-#: vncviewer/DesktopWindow.cxx:121
+#: vncviewer/DesktopWindow.cxx:122
msgid "Invalid geometry specified!"
msgstr "Ugyldig geometri angivet!"
-#: vncviewer/DesktopWindow.cxx:434
+#: vncviewer/DesktopWindow.cxx:451
msgid "Adjusting window size to avoid accidental full screen request"
msgstr "Justerer vinduesstørrelse for at undgå utilsigtet anmodning om fuld skærm"
-#: vncviewer/DesktopWindow.cxx:478
+#: vncviewer/DesktopWindow.cxx:495
#, c-format
msgid "Press %s to open the context menu"
msgstr "Tryk %s for at åbne kontekstmenuen"
-#: vncviewer/DesktopWindow.cxx:741 vncviewer/DesktopWindow.cxx:747
-#: vncviewer/DesktopWindow.cxx:760
+#: vncviewer/DesktopWindow.cxx:794 vncviewer/DesktopWindow.cxx:802
+#: vncviewer/DesktopWindow.cxx:822
msgid "Failure grabbing keyboard"
msgstr "Kunne ikke fange tastatur"
-#: vncviewer/DesktopWindow.cxx:772
+#: vncviewer/DesktopWindow.cxx:896
msgid "Failure grabbing mouse"
msgstr "Kunne ikke fange mus"
-#: vncviewer/DesktopWindow.cxx:1002
+#: vncviewer/DesktopWindow.cxx:1120
msgid "Invalid screen layout computed for resize request!"
msgstr "Ugyldig skærmlayout beregnet for anmodning om ny størrelse!"
-#: vncviewer/FLTKPixelBuffer.cxx:33
-msgid "Not enough memory for framebuffer"
-msgstr "Ikke nok hukommelse for framebuffer"
-
#: vncviewer/OptionsDialog.cxx:57
msgid "VNC Viewer: Connection Options"
msgstr "VNC-fremviser: Forbindelsesindstillinger"
@@ -338,220 +340,282 @@
msgid "Connect"
msgstr "Forbind"
-#: vncviewer/UserDialog.cxx:74
+#: vncviewer/ServerDialog.cxx:137 vncviewer/ServerDialog.cxx:171
+msgid "TigerVNC configuration (*.tigervnc)"
+msgstr "TigerVNC-konfiguration (*.tigervnc)"
+
+#: vncviewer/ServerDialog.cxx:138
+msgid "Select a TigerVNC configuration file"
+msgstr "Vælg en TigerVNC-konfigurationsfil"
+
+#: vncviewer/ServerDialog.cxx:172
+msgid "Save the TigerVNC configuration to file"
+msgstr "Gem TigerVNC-konfigurationen til fil"
+
+#: vncviewer/ServerDialog.cxx:197
+#, c-format
+msgid "%s already exists. Do you want to overwrite?"
+msgstr "%s findes allerede. Ønsker du at overskrive?"
+
+#: vncviewer/ServerDialog.cxx:198 vncviewer/vncviewer.cxx:279
+msgid "No"
+msgstr "Nej"
+
+#: vncviewer/ServerDialog.cxx:198
+msgid "Overwrite"
+msgstr "Overskriv"
+
+#: vncviewer/UserDialog.cxx:85
msgid "Opening password file failed"
msgstr "Åbning af adgangskodefil mislykkedes"
-#: vncviewer/UserDialog.cxx:86 vncviewer/UserDialog.cxx:96
+#: vncviewer/UserDialog.cxx:105
msgid "VNC authentication"
msgstr "VNC-godkendelse"
-#: vncviewer/UserDialog.cxx:87 vncviewer/UserDialog.cxx:102
-msgid "Password:"
-msgstr "Adgangskode:"
+#: vncviewer/UserDialog.cxx:112
+msgid "This connection is secure"
+msgstr "Denne forbindelse er sikker"
-#: vncviewer/UserDialog.cxx:89
-msgid "Authentication cancelled"
-msgstr "Godkendelse afbrudt"
+#: vncviewer/UserDialog.cxx:116
+msgid "This connection is not secure"
+msgstr "Denne forbindelse er ikke sikker"
-#: vncviewer/UserDialog.cxx:99
+#: vncviewer/UserDialog.cxx:133
msgid "Username:"
msgstr "Brugernavn:"
-#: vncviewer/Viewport.cxx:586
+#: vncviewer/UserDialog.cxx:140
+msgid "Password:"
+msgstr "Adgangskode:"
+
+#: vncviewer/UserDialog.cxx:179
+msgid "Authentication cancelled"
+msgstr "Godkendelse afbrudt"
+
+#: vncviewer/Viewport.cxx:377
+#, c-format
+msgid "Failed to update keyboard LED state: %lu"
+msgstr "Kunne ikke opdatere tastatur-LED-tilstand: %lu"
+
+#: vncviewer/Viewport.cxx:383 vncviewer/Viewport.cxx:389
+#, c-format
+msgid "Failed to update keyboard LED state: %d"
+msgstr "Kunne ikke opdatere tastatur-LED-tilstand: %d"
+
+#: vncviewer/Viewport.cxx:419
+msgid "Failed to update keyboard LED state"
+msgstr "Kunne ikke opdatere tastatur-LED-tilstand"
+
+#: vncviewer/Viewport.cxx:446 vncviewer/Viewport.cxx:454
+#: vncviewer/Viewport.cxx:471
+#, c-format
+msgid "Failed to get keyboard LED state: %d"
+msgstr "Kunne ikke indhente tastatur-LED-tilstand: %d"
+
+#: vncviewer/Viewport.cxx:817
+msgid "No key code specified on key press"
+msgstr "Ingen nøglekode angivet ved tastaturtryk"
+
+#: vncviewer/Viewport.cxx:959
#, c-format
msgid "No scan code for extended virtual key 0x%02x"
msgstr "Ingen skanningskode for udvidet virtuel nøgle 0x%02x"
-#: vncviewer/Viewport.cxx:588
+#: vncviewer/Viewport.cxx:961
#, c-format
msgid "No scan code for virtual key 0x%02x"
msgstr "Ingen skanningskode for virtuel nøgle 0x%02x"
-#: vncviewer/Viewport.cxx:605
+#: vncviewer/Viewport.cxx:967
+#, c-format
+msgid "Invalid scan code 0x%02x"
+msgstr "Ugyldig skanningskode 0x%02x"
+
+#: vncviewer/Viewport.cxx:997
#, c-format
msgid "No symbol for extended virtual key 0x%02x"
msgstr "Intet symbol for udvidet virtuel nøgle 0x%02x"
-#: vncviewer/Viewport.cxx:607
+#: vncviewer/Viewport.cxx:999
#, c-format
msgid "No symbol for virtual key 0x%02x"
msgstr "Intet symbol for virtuel nøgle 0x%02x"
-#: vncviewer/Viewport.cxx:645
+#: vncviewer/Viewport.cxx:1086
#, c-format
msgid "No symbol for key code 0x%02x (in the current state)"
msgstr "Intet symbol for nøglekode 0x%02x (i den nuværende tilstand)"
-#: vncviewer/Viewport.cxx:671
+#: vncviewer/Viewport.cxx:1119
#, c-format
msgid "No symbol for key code %d (in the current state)"
msgstr "Intet symbol for nøglekode %d (i den nuværende tilstand)"
-#: vncviewer/Viewport.cxx:708
+#: vncviewer/Viewport.cxx:1170
msgctxt "ContextMenu|"
msgid "E&xit viewer"
msgstr "&Afslut fremviser"
-#: vncviewer/Viewport.cxx:711
+#: vncviewer/Viewport.cxx:1173
msgctxt "ContextMenu|"
msgid "&Full screen"
msgstr "&Fuld skærm"
-#: vncviewer/Viewport.cxx:714
+#: vncviewer/Viewport.cxx:1176
msgctxt "ContextMenu|"
msgid "Minimi&ze"
msgstr "&Minimer"
-#: vncviewer/Viewport.cxx:716
+#: vncviewer/Viewport.cxx:1178
msgctxt "ContextMenu|"
msgid "Resize &window to session"
msgstr "Ændr størrelse for &vindue til session"
-#: vncviewer/Viewport.cxx:721
+#: vncviewer/Viewport.cxx:1183
msgctxt "ContextMenu|"
msgid "&Ctrl"
msgstr "&Ctrl"
-#: vncviewer/Viewport.cxx:724
+#: vncviewer/Viewport.cxx:1186
msgctxt "ContextMenu|"
msgid "&Alt"
msgstr "&Alt"
-#: vncviewer/Viewport.cxx:730
+#: vncviewer/Viewport.cxx:1192
#, c-format
msgctxt "ContextMenu|"
msgid "Send %s"
msgstr "Send %s"
-#: vncviewer/Viewport.cxx:736
+#: vncviewer/Viewport.cxx:1198
msgctxt "ContextMenu|"
msgid "Send Ctrl-Alt-&Del"
msgstr "Send Ctrl-Alt-&Slet"
-#: vncviewer/Viewport.cxx:739
+#: vncviewer/Viewport.cxx:1201
msgctxt "ContextMenu|"
msgid "&Refresh screen"
msgstr "&Opdater skærm"
-#: vncviewer/Viewport.cxx:742
+#: vncviewer/Viewport.cxx:1204
msgctxt "ContextMenu|"
msgid "&Options..."
msgstr "&Indstillinger ..."
-#: vncviewer/Viewport.cxx:744
+#: vncviewer/Viewport.cxx:1206
msgctxt "ContextMenu|"
msgid "Connection &info..."
msgstr "Forbindelses&info ..."
-#: vncviewer/Viewport.cxx:746
+#: vncviewer/Viewport.cxx:1208
msgctxt "ContextMenu|"
msgid "About &TigerVNC viewer..."
msgstr "Om &TigerVNC-fremviseren ..."
-#: vncviewer/Viewport.cxx:749
+#: vncviewer/Viewport.cxx:1211
msgctxt "ContextMenu|"
msgid "Dismiss &menu"
msgstr "Fjern %menu"
-#: vncviewer/Viewport.cxx:833
+#: vncviewer/Viewport.cxx:1300
msgid "VNC connection info"
msgstr "VNC-forbindelsesinfo"
-#: vncviewer/parameters.cxx:286 vncviewer/parameters.cxx:320
+#: vncviewer/parameters.cxx:279 vncviewer/parameters.cxx:313
#, c-format
msgid "The name of the parameter %s was too large to write to the registry"
msgstr "Navnet på parameteren %s var for lang til at kunne skrives til registret"
-#: vncviewer/parameters.cxx:292 vncviewer/parameters.cxx:299
+#: vncviewer/parameters.cxx:285 vncviewer/parameters.cxx:292
#, c-format
msgid "The parameter %s was too large to write to the registry"
msgstr "Parameteren %s var for lang til at kunne skrives til registret"
-#: vncviewer/parameters.cxx:305 vncviewer/parameters.cxx:326
+#: vncviewer/parameters.cxx:298 vncviewer/parameters.cxx:319
#, c-format
msgid "Failed to write parameter %s of type %s to the registry: %ld"
msgstr "Kunne ikke skrive parameteren %s af typen %s til registret: %ld"
-#: vncviewer/parameters.cxx:341 vncviewer/parameters.cxx:380
+#: vncviewer/parameters.cxx:334 vncviewer/parameters.cxx:373
#, c-format
msgid "The name of the parameter %s was too large to read from the registry"
msgstr "Navnet for parameteren %s var for lang til at kunne læses fra registret"
-#: vncviewer/parameters.cxx:350 vncviewer/parameters.cxx:389
+#: vncviewer/parameters.cxx:343 vncviewer/parameters.cxx:382
#, c-format
msgid "Failed to read parameter %s from the registry: %ld"
msgstr "Kunne ikke læse parameteren %s fra registret: %ld"
-#: vncviewer/parameters.cxx:359
+#: vncviewer/parameters.cxx:352
#, c-format
msgid "The parameter %s was too large to read from the registry"
msgstr "Parameteren %s var for lang til at kunne læses fra registret"
-#: vncviewer/parameters.cxx:409
+#: vncviewer/parameters.cxx:402
#, c-format
msgid "Failed to create registry key: %ld"
msgstr "Kunne ikke oprette registernøgle: %ld"
-#: vncviewer/parameters.cxx:423 vncviewer/parameters.cxx:472
-#: vncviewer/parameters.cxx:534 vncviewer/parameters.cxx:665
+#: vncviewer/parameters.cxx:416 vncviewer/parameters.cxx:465
+#: vncviewer/parameters.cxx:527 vncviewer/parameters.cxx:660
#, c-format
msgid "Unknown parameter type for parameter %s"
msgstr "Ukendt parametertype for parameteren %s"
-#: vncviewer/parameters.cxx:430 vncviewer/parameters.cxx:479
+#: vncviewer/parameters.cxx:423 vncviewer/parameters.cxx:472
#, c-format
msgid "Failed to close registry key: %ld"
msgstr "Kunne ikke lukke registernøgle: %ld"
-#: vncviewer/parameters.cxx:446
+#: vncviewer/parameters.cxx:439
#, c-format
msgid "Failed to open registry key: %ld"
msgstr "Kunne ikke åbne registernøgle: %ld"
-#: vncviewer/parameters.cxx:503
+#: vncviewer/parameters.cxx:496
msgid "Failed to write configuration file, can't obtain home directory path."
msgstr "Kunne ikke skrive konfigurationsfil, kan ikke indhente hjemmemappens sti."
-#: vncviewer/parameters.cxx:516
+#: vncviewer/parameters.cxx:509
#, c-format
msgid "Failed to write configuration file, can't open %s: %s"
msgstr "Kunne ikke skrive konfigurationsfil, kan ikke åbne %s: %s"
-#: vncviewer/parameters.cxx:559
+#: vncviewer/parameters.cxx:554
msgid "Failed to read configuration file, can't obtain home directory path."
msgstr "Kunne ikke læse konfigurationsfil, kan ikke indhente hjemmemappens sti."
-#: vncviewer/parameters.cxx:572
+#: vncviewer/parameters.cxx:567
#, c-format
msgid "Failed to read configuration file, can't open %s: %s"
msgstr "Kunne ikke læse konfigurationsfil, kan ikke åbne %s: %s"
-#: vncviewer/parameters.cxx:585 vncviewer/parameters.cxx:590
-#: vncviewer/parameters.cxx:615 vncviewer/parameters.cxx:628
-#: vncviewer/parameters.cxx:644
+#: vncviewer/parameters.cxx:580 vncviewer/parameters.cxx:585
+#: vncviewer/parameters.cxx:610 vncviewer/parameters.cxx:623
+#: vncviewer/parameters.cxx:639
#, c-format
msgid "Failed to read line %d in file %s: %s"
msgstr "Kunne ikke læse linje %d i filen %s: %s"
-#: vncviewer/parameters.cxx:591
+#: vncviewer/parameters.cxx:586
msgid "Line too long"
msgstr "Linjen er for lang"
-#: vncviewer/parameters.cxx:598
+#: vncviewer/parameters.cxx:593
#, c-format
msgid "Configuration file %s is in an invalid format"
msgstr "Konfigurationsfilen %s er i et ugyldigt format"
-#: vncviewer/parameters.cxx:616
+#: vncviewer/parameters.cxx:611
msgid "Invalid format"
msgstr "Ugyldigt format"
-#: vncviewer/parameters.cxx:629 vncviewer/parameters.cxx:645
+#: vncviewer/parameters.cxx:624 vncviewer/parameters.cxx:640
msgid "Invalid format or too large value"
msgstr "Ugyldigt format eller for stor værdi"
-#: vncviewer/parameters.cxx:672
+#: vncviewer/parameters.cxx:667
#, c-format
msgid "Unknown parameter %s on line %d in file %s"
msgstr "Ukendt parameter %s på linje %d i filen %s"
@@ -561,12 +625,12 @@
msgid ""
"TigerVNC Viewer %d-bit v%s\n"
"Built on: %s\n"
-"Copyright (C) 1999-%d TigerVNC Team and many others (see README.txt)\n"
+"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\n"
"See http://www.tigervnc.org for information on TigerVNC."
msgstr ""
"TigerVNC-fremviser %d-bit v%s\n"
"Bygget på: %s\n"
-"Ophavsret 1999-%d TigerVNC-holdet og mange andre (se README.txt)\n"
+"Ophavsret 1999-%d TigerVNC-holdet og mange andre (se README.rst)\n"
"Se http://www.tigervnc.org for information om TigerVNC."
#: vncviewer/vncviewer.cxx:127
@@ -587,14 +651,10 @@
msgid "Termination signal %d has been received. TigerVNC Viewer will now exit."
msgstr "Opsigelsessignalet %d er blevet modtaget. TigerVNC-fremviseren vil nu afslutte."
-#: vncviewer/vncviewer.cxx:271
+#: vncviewer/vncviewer.cxx:271 vncviewer/vncviewer.desktop.in.in:3
msgid "TigerVNC Viewer"
msgstr "TigerVNC-fremviser"
-#: vncviewer/vncviewer.cxx:279
-msgid "No"
-msgstr "Nej"
-
#: vncviewer/vncviewer.cxx:280
msgid "Yes"
msgstr "Ja"
@@ -648,15 +708,26 @@
#. TRANSLATORS: "Parameters" are command line arguments, or settings
#. from a file or the Windows registry.
-#: vncviewer/vncviewer.cxx:534 vncviewer/vncviewer.cxx:535
+#: vncviewer/vncviewer.cxx:581 vncviewer/vncviewer.cxx:583
msgid "Parameters -listen and -via are incompatible"
msgstr "Parameterne -listen og -via er ikke kompatible"
-#: vncviewer/vncviewer.cxx:550
+#: vncviewer/vncviewer.cxx:598
#, c-format
msgid "Listening on port %d"
msgstr "Lytter på port %d"
-#: vncviewer/vncviewer.desktop.in.in:6
+#: vncviewer/vncviewer.desktop.in.in:4
+msgid "Remote Desktop Viewer"
+msgstr "Ekstern skrivebordsviser"
+
+#: vncviewer/vncviewer.desktop.in.in:5
msgid "Connect to VNC server and display remote desktop"
-msgstr "Opret forbindelse til VNC-server og vis fjern-skrivebord"
+msgstr "Forbind til VNC-server og vis eksternt skrivebord"
+
+#: vncviewer/vncviewer.desktop.in.in:7
+msgid "tigervnc"
+msgstr "tigervnc"
+
+#~ msgid "Not enough memory for framebuffer"
+#~ msgstr "Ikke nok hukommelse for framebuffer"
diff --git a/release/tigervnc.iss.in b/release/tigervnc.iss.in
index 092345a..5850148 100644
--- a/release/tigervnc.iss.in
+++ b/release/tigervnc.iss.in
@@ -9,7 +9,7 @@
#endif
AppVersion=@VERSION@
AppPublisher=TigerVNC project
-AppPublisherURL=http://tigervnc.org
+AppPublisherURL=https://tigervnc.org
DefaultDirName={pf}\TigerVNC
#ifdef WIN64
DefaultGroupName=TigerVNC 64-bit
diff --git a/unix/vncconfig/vncconfig.man b/unix/vncconfig/vncconfig.man
index 06f9ca9..b685a46 100644
--- a/unix/vncconfig/vncconfig.man
+++ b/unix/vncconfig/vncconfig.man
@@ -114,7 +114,7 @@
.BR vncserver (1),
.BR Xvnc (1)
.br
-http://www.tigervnc.org
+https://www.tigervnc.org
.SH AUTHOR
Tristan Richardson, RealVNC Ltd. and others.
diff --git a/unix/vncpasswd/vncpasswd.man b/unix/vncpasswd/vncpasswd.man
index a62c0ed..9e68181 100644
--- a/unix/vncpasswd/vncpasswd.man
+++ b/unix/vncpasswd/vncpasswd.man
@@ -47,7 +47,7 @@
.BR Xvnc (1)
.BR vncconfig (1),
.br
-http://www.tigervnc.org
+https://www.tigervnc.org
.SH AUTHORS
Tristan Richardson, RealVNC Ltd., Antoine Martin, D. R. Commander and others.
diff --git a/unix/vncserver b/unix/vncserver
index 9e7a6ac..bb4f2fe 100755
--- a/unix/vncserver
+++ b/unix/vncserver
@@ -33,8 +33,6 @@
$exedir = substr($0, 0, $slashndx+1);
}
-$vncClasses = "";
-
&SanityCheck();
#
@@ -44,9 +42,6 @@
$geometry = "1024x768";
#$depth = 16;
-$vncJavaFiles = (((-d "$vncClasses") && "$vncClasses") ||
- ((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") ||
- ((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes"));
$vncUserDir = "$ENV{HOME}/.vnc";
$vncUserConfig = "$vncUserDir/config";
@@ -206,7 +201,6 @@
# We set some reasonable defaults. Config file settings
# override these where present.
$default_opts{desktop} = "edString($desktopName);
-$default_opts{httpd} = $vncJavaFiles if ($vncJavaFiles);
$default_opts{auth} = "edString($xauthorityFile);
$default_opts{geometry} = $geometry if ($geometry);
$default_opts{depth} = $depth if ($depth);
@@ -848,7 +842,6 @@
foreach $cmd ("Xvnc","vncpasswd") {
for (split(/:/,$ENV{PATH})) {
if (-x "$_/$cmd") {
- $vncClasses = "$_/../vnc/classes";
next cmd2;
}
}
@@ -860,7 +853,6 @@
foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") {
for (split(/:/,$ENV{PATH})) {
if (-x "$cmd") {
- $vncClasses = $exedir."../vnc/classes";
next cmd3;
}
}
diff --git a/unix/vncserver.man b/unix/vncserver.man
index 9108683..95f7960 100644
--- a/unix/vncserver.man
+++ b/unix/vncserver.man
@@ -192,7 +192,7 @@
.BR vncconfig (1),
.BR Xvnc (1)
.br
-http://www.tigervnc.org
+https://www.tigervnc.org
.SH AUTHOR
Tristan Richardson, RealVNC Ltd., D. R. Commander and others.
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 5f67f29..1fdc9e2 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -18,6 +18,12 @@
* USA.
*/
+#include <assert.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <rfb/LogWriter.h>
+
#include <x0vncserver/XDesktop.h>
#include <X11/XKBlib.h>
@@ -53,6 +59,10 @@
"Send keyboard events straight through and "
"avoid mapping them to the current keyboard "
"layout", false);
+IntParameter queryConnectTimeout("QueryConnectTimeout",
+ "Number of seconds to show the Accept Connection dialog before "
+ "rejecting the connection",
+ 10);
static rfb::LogWriter vlog("XDesktop");
@@ -63,6 +73,7 @@
XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
: dpy(dpy_), geometry(geometry_), pb(0), server(0),
+ queryConnectDialog(0), queryConnectSock(0),
oldButtonMask(0), haveXtest(false), haveDamage(false),
maxButtons(0), running(false), ledMasks(), ledState(0),
codeMap(0), codeMapLen(0)
@@ -227,7 +238,7 @@
pb = new XPixelBuffer(dpy, factory, geometry->getRect());
vlog.info("Allocated %s", pb->getImage()->classDesc());
- server = (VNCServerST *)vs;
+ server = vs;
server->setPixelBuffer(pb, computeScreenLayout());
#ifdef HAVE_XDAMAGE
@@ -254,6 +265,9 @@
XDamageDestroy(dpy, damage);
#endif
+ delete queryConnectDialog;
+ queryConnectDialog = 0;
+
server->setPixelBuffer(0);
server = 0;
@@ -261,10 +275,38 @@
pb = 0;
}
+void XDesktop::terminate() {
+ kill(getpid(), SIGTERM);
+}
+
bool XDesktop::isRunning() {
return running;
}
+void XDesktop::queryConnection(network::Socket* sock,
+ const char* userName)
+{
+ assert(isRunning());
+
+ if (queryConnectSock) {
+ server->approveConnection(sock, false, "Another connection is currently being queried.");
+ return;
+ }
+
+ if (!userName)
+ userName = "(anonymous)";
+
+ queryConnectSock = sock;
+
+ CharArray address(sock->getPeerAddress());
+ delete queryConnectDialog;
+ queryConnectDialog = new QueryConnectDialog(dpy, address.buf,
+ userName,
+ queryConnectTimeout,
+ this);
+ queryConnectDialog->map();
+}
+
void XDesktop::pointerEvent(const Point& pos, int buttonMask) {
#ifdef HAVE_XTEST
if (!haveXtest) return;
@@ -611,6 +653,8 @@
dev = (XDamageNotifyEvent*)ev;
rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
+ rect = rect.translate(Point(-geometry->offsetLeft(),
+ -geometry->offsetTop()));
server->add_changed(rect);
return true;
@@ -684,6 +728,21 @@
return false;
}
+void XDesktop::queryApproved()
+{
+ assert(isRunning());
+ server->approveConnection(queryConnectSock, true, 0);
+ queryConnectSock = 0;
+}
+
+void XDesktop::queryRejected()
+{
+ assert(isRunning());
+ server->approveConnection(queryConnectSock, false,
+ "Connection rejected by local user");
+ queryConnectSock = 0;
+}
+
bool XDesktop::setCursor()
{
XFixesCursorImage *cim;
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
index ff52c01..3e85aac 100644
--- a/unix/x0vncserver/XDesktop.h
+++ b/unix/x0vncserver/XDesktop.h
@@ -21,7 +21,7 @@
#ifndef __XDESKTOP_H__
#define __XDESKTOP_H__
-#include <rfb/VNCServerST.h>
+#include <rfb/SDesktop.h>
#include <tx/TXWindow.h>
#include <unixcommon.h>
@@ -30,13 +30,17 @@
#include <X11/extensions/Xdamage.h>
#endif
+#include <vncconfig/QueryConnectDialog.h>
+
class Geometry;
class XPixelBuffer;
// number of XKb indicator leds to handle
#define XDESKTOP_N_LEDS 3
-class XDesktop : public rfb::SDesktop, public TXGlobalEventHandler
+class XDesktop : public rfb::SDesktop,
+ public TXGlobalEventHandler,
+ public QueryResultCallback
{
public:
XDesktop(Display* dpy_, Geometry *geometry);
@@ -45,7 +49,10 @@
// -=- SDesktop interface
virtual void start(rfb::VNCServer* vs);
virtual void stop();
+ virtual void terminate();
bool isRunning();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down);
@@ -56,11 +63,17 @@
// -=- TXGlobalEventHandler interface
virtual bool handleGlobalEvent(XEvent* ev);
+ // -=- QueryResultCallback interface
+ virtual void queryApproved();
+ virtual void queryRejected();
+
protected:
Display* dpy;
Geometry* geometry;
XPixelBuffer* pb;
- rfb::VNCServerST* server;
+ rfb::VNCServer* server;
+ QueryConnectDialog* queryConnectDialog;
+ network::Socket* queryConnectSock;
int oldButtonMask;
bool haveXtest;
bool haveDamage;
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index c08572b..cf2c35a 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -33,8 +33,6 @@
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>
-#include <vncconfig/QueryConnectDialog.h>
-
#include <signal.h>
#include <X11/X.h>
#include <X11/Xlib.h>
@@ -61,10 +59,6 @@
IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900);
StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", "");
IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600);
-IntParameter queryConnectTimeout("QueryConnectTimeout",
- "Number of seconds to show the Accept Connection dialog before "
- "rejecting the connection",
- 10);
StringParameter hostsFile("HostsFile", "File with IP access control rules", "");
//
@@ -79,50 +73,6 @@
}
-class QueryConnHandler : public VNCServerST::QueryConnectionHandler,
- public QueryResultCallback {
-public:
- QueryConnHandler(Display* dpy, VNCServerST* vs)
- : display(dpy), server(vs), queryConnectDialog(0), queryConnectSock(0) {}
- ~QueryConnHandler() { delete queryConnectDialog; }
-
- // -=- VNCServerST::QueryConnectionHandler interface
- virtual VNCServerST::queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason) {
- if (queryConnectSock) {
- *reason = strDup("Another connection is currently being queried.");
- return VNCServerST::REJECT;
- }
- if (!userName) userName = "(anonymous)";
- queryConnectSock = sock;
- CharArray address(sock->getPeerAddress());
- delete queryConnectDialog;
- queryConnectDialog = new QueryConnectDialog(display, address.buf,
- userName, queryConnectTimeout,
- this);
- queryConnectDialog->map();
- return VNCServerST::PENDING;
- }
-
- // -=- QueryResultCallback interface
- virtual void queryApproved() {
- server->approveConnection(queryConnectSock, true, 0);
- queryConnectSock = 0;
- }
- virtual void queryRejected() {
- server->approveConnection(queryConnectSock, false,
- "Connection rejected by local user");
- queryConnectSock = 0;
- }
-private:
- Display* display;
- VNCServerST* server;
- QueryConnectDialog* queryConnectDialog;
- network::Socket* queryConnectSock;
-};
-
-
class FileTcpFilter : public TcpFilter
{
@@ -307,8 +257,6 @@
XDesktop desktop(dpy, &geo);
VNCServerST server("x0vncserver", &desktop);
- QueryConnHandler qcHandler(dpy, &server);
- server.setQueryConnectionHandler(&qcHandler);
if (rfbunixpath.getValueStr()[0] != '\0') {
listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode));
@@ -374,7 +322,7 @@
}
}
- soonestTimeout(&wait_ms, server.checkTimeouts());
+ soonestTimeout(&wait_ms, Timer::checkTimeouts());
tv.tv_sec = wait_ms / 1000;
tv.tv_usec = (wait_ms % 1000) * 1000;
@@ -409,7 +357,7 @@
}
}
- server.checkTimeouts();
+ Timer::checkTimeouts();
// Client list could have been changed.
server.getSockets(&sockets);
@@ -439,6 +387,13 @@
TXWindow::handleXEvents(dpy);
+ // Run listener destructors; remove UNIX sockets etc
+ for (std::list<SocketListener*>::iterator i = listeners.begin();
+ i != listeners.end();
+ i++) {
+ delete *i;
+ }
+
vlog.info("Terminated");
return 0;
}
diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man
index 5dc0b05..5f1508c 100644
--- a/unix/x0vncserver/x0vncserver.man
+++ b/unix/x0vncserver/x0vncserver.man
@@ -302,7 +302,7 @@
.BR Xvnc (1),
.BR vncpasswd (1),
.br
-http://www.tigervnc.org/
+https://www.tigervnc.org/
.SH AUTHOR
Constantin Kaplinsky and others.
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 7eaf3f9..d8b3a4d 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -22,6 +22,7 @@
//
#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -35,7 +36,6 @@
#include <network/Socket.h>
#include <rfb/Exception.h>
#include <rfb/VNCServerST.h>
-#include <rfb/HTTPServer.h>
#include <rfb/LogWriter.h>
#include <rfb/Configuration.h>
#include <rfb/ServerCore.h>
@@ -67,54 +67,14 @@
"rejecting the connection",
10);
-class FileHTTPServer : public rfb::HTTPServer {
-public:
- FileHTTPServer(XserverDesktop* d) : desktop(d) {}
- virtual ~FileHTTPServer() {}
-
- virtual rdr::InStream* getFile(const char* name, const char** contentType,
- int* contentLength, time_t* lastModified)
- {
- if (name[0] != '/' || strstr(name, "..") != 0) {
- vlog.info("http request was for invalid file name");
- return 0;
- }
-
- if (strcmp(name, "/") == 0) name = "/index.vnc";
-
- CharArray httpDirStr(httpDir.getData());
- CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
- sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
- int fd = open(fname.buf, O_RDONLY);
- if (fd < 0) return 0;
- rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
- *contentType = guessContentType(name, *contentType);
- if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
- is = new rdr::SubstitutingInStream(is, desktop, 20);
- *contentType = "text/html";
- } else {
- struct stat st;
- if (fstat(fd, &st) == 0) {
- *contentLength = st.st_size;
- *lastModified = st.st_mtime;
- }
- }
- return is;
- }
-
- XserverDesktop* desktop;
-};
-
XserverDesktop::XserverDesktop(int screenIndex_,
std::list<network::SocketListener*> listeners_,
- std::list<network::SocketListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height,
void* fbptr, int stride)
: screenIndex(screenIndex_),
- server(0), httpServer(0),
- listeners(listeners_), httpListeners(httpListeners_),
+ server(0), listeners(listeners_),
directFbptr(true),
queryConnectId(0), queryConnectTimer(this)
{
@@ -122,22 +82,12 @@
server = new VNCServerST(name, this);
setFramebuffer(width, height, fbptr, stride);
- server->setQueryConnectionHandler(this);
-
- if (!httpListeners.empty ())
- httpServer = new FileHTTPServer(this);
for (std::list<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++) {
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
}
-
- for (std::list<SocketListener*>::iterator i = httpListeners.begin();
- i != httpListeners.end();
- i++) {
- vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
- }
}
XserverDesktop::~XserverDesktop()
@@ -147,14 +97,8 @@
delete listeners.back();
listeners.pop_back();
}
- while (!httpListeners.empty()) {
- vncRemoveNotifyFd(listeners.back()->getFd());
- delete httpListeners.back();
- httpListeners.pop_back();
- }
if (!directFbptr)
delete [] data;
- delete httpServer;
delete server;
}
@@ -201,72 +145,31 @@
server->setScreenLayout(::computeScreenLayout(&outputIdMap));
}
-char* XserverDesktop::substitute(const char* varName)
+void XserverDesktop::start(rfb::VNCServer* vs)
{
- if (strcmp(varName, "$$") == 0) {
- return rfb::strDup("$");
- }
- if (strcmp(varName, "$PORT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ())->getMyPort());
- return str;
- }
- if (strcmp(varName, "$WIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", width());
- return str;
- }
- if (strcmp(varName, "$HEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", height());
- return str;
- }
- if (strcmp(varName, "$APPLETWIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", width());
- return str;
- }
- if (strcmp(varName, "$APPLETHEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", height());
- return str;
- }
- if (strcmp(varName, "$DESKTOP") == 0) {
- return rfb::strDup(server->getName());
- }
- if (strcmp(varName, "$DISPLAY") == 0) {
- struct utsname uts;
- uname(&uts);
- char* str = new char[256];
- strncpy(str, uts.nodename, 240);
- str[239] = '\0'; /* Ensure string is zero-terminated */
- strcat(str, ":");
- strncat(str, vncGetDisplay(), 10);
- return str;
- }
- if (strcmp(varName, "$USER") == 0) {
- struct passwd* user = getpwuid(getuid());
- return rfb::strDup(user ? user->pw_name : "?");
- }
- return 0;
+ // We already own the server object, and we always keep it in a
+ // ready state
+ assert(vs == server);
}
-rfb::VNCServerST::queryResult
-XserverDesktop::queryConnection(network::Socket* sock,
- const char* userName,
- char** reason)
+void XserverDesktop::stop()
+{
+}
+
+void XserverDesktop::queryConnection(network::Socket* sock,
+ const char* userName)
{
int count;
if (queryConnectTimer.isStarted()) {
- *reason = strDup("Another connection is currently being queried.");
- return rfb::VNCServerST::REJECT;
+ server->approveConnection(sock, false, "Another connection is currently being queried.");
+ return;
}
count = vncNotifyQueryConnect();
if (count == 0) {
- *reason = strDup("Unable to query the local user to accept the connection.");
- return rfb::VNCServerST::REJECT;
+ server->approveConnection(sock, false, "Unable to query the local user to accept the connection.");
+ return;
}
queryConnectAddress.replaceBuf(sock->getPeerAddress());
@@ -277,8 +180,6 @@
queryConnectSocket = sock;
queryConnectTimer.start(queryConnectTimeout * 1000);
-
- return rfb::VNCServerST::PENDING;
}
void XserverDesktop::bell()
@@ -370,14 +271,10 @@
if (read) {
if (handleListenerEvent(fd, &listeners, server))
return;
- if (handleListenerEvent(fd, &httpListeners, httpServer))
- return;
}
if (handleSocketEvent(fd, server, read, write))
return;
- if (handleSocketEvent(fd, httpServer, read, write))
- return;
vlog.error("Cannot find file descriptor for socket event");
} catch (rdr::Exception& e) {
@@ -458,21 +355,6 @@
vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0);
}
}
- if (httpServer) {
- httpServer->getSockets(&sockets);
- for (i = sockets.begin(); i != sockets.end(); i++) {
- int fd = (*i)->getFd();
- if ((*i)->isShutdown()) {
- vlog.debug("http client gone, sock %d",fd);
- vncRemoveNotifyFd(fd);
- httpServer->removeSocket(*i);
- delete (*i);
- } else {
- /* Update existing NotifyFD to listen for write (or not) */
- vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0);
- }
- }
- }
// We are responsible for propagating mouse movement between clients
int cursorX, cursorY;
@@ -486,7 +368,7 @@
}
// Trigger timers and check when the next will expire
- int nextTimeout = server->checkTimeouts();
+ int nextTimeout = Timer::checkTimeouts();
if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout))
*timeout = nextTimeout;
} catch (rdr::Exception& e) {
@@ -542,6 +424,11 @@
// SDesktop callbacks
+void XserverDesktop::terminate()
+{
+ kill(getpid(), SIGTERM);
+}
+
void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
{
vncPointerMove(pos.x + vncGetScreenX(screenIndex),
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index f866a4c..1253935 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -32,11 +32,9 @@
#include <stdint.h>
#include <rfb/SDesktop.h>
-#include <rfb/HTTPServer.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Configuration.h>
-#include <rfb/VNCServerST.h>
-#include <rdr/SubstitutingInStream.h>
+#include <rfb/Timer.h>
#include <unixcommon.h>
#include "Input.h"
@@ -47,14 +45,11 @@
namespace network { class SocketListener; class Socket; class SocketServer; }
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
- public rdr::Substitutor,
- public rfb::VNCServerST::QueryConnectionHandler,
public rfb::Timer::Callback {
public:
XserverDesktop(int screenIndex,
std::list<network::SocketListener*> listeners_,
- std::list<network::SocketListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height, void* fbptr, int stride);
virtual ~XserverDesktop();
@@ -90,6 +85,11 @@
const char* rejectMsg=0);
// rfb::SDesktop callbacks
+ virtual void start(rfb::VNCServer* vs);
+ virtual void stop();
+ virtual void terminate();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void clientCutText(const char* str, int len);
@@ -99,14 +99,6 @@
// rfb::PixelBuffer callbacks
virtual void grabRegion(const rfb::Region& r);
- // rdr::Substitutor callback
- virtual char* substitute(const char* varName);
-
- // rfb::VNCServerST::QueryConnectionHandler callback
- virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason);
-
protected:
bool handleListenerEvent(int fd,
std::list<network::SocketListener*>* sockets,
@@ -120,10 +112,8 @@
private:
int screenIndex;
- rfb::VNCServerST* server;
- rfb::HTTPServer* httpServer;
+ rfb::VNCServer* server;
std::list<network::SocketListener*> listeners;
- std::list<network::SocketListener*> httpListeners;
bool directFbptr;
uint32_t queryConnectId;
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index 269be9a..9991650 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -107,19 +107,6 @@
mean an update will be aborted after this time. Default is 20000 (20 seconds).
.
.TP
-.B \-httpd \fIdirectory\fP
-Run a mini-HTTP server which serves files from the given directory. Normally
-the directory will contain the classes for the Java viewer. In addition, files
-with a .vnc extension will have certain substitutions made so that a single
-installation of the Java VNC viewer can be served by separate instances of
-Xvnc.
-.
-.TP
-.B \-httpPort \fIport\fP
-Specifies the port on which the mini-HTTP server runs. Default is 5800 plus
-the display number.
-.
-.TP
.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
Password file for VNC authentication. There is no default, you should
specify the password file explicitly. Password file should be created with
@@ -396,7 +383,7 @@
.BR Xserver (1),
.BR inetd (1)
.br
-http://www.tigervnc.org
+https://www.tigervnc.org
.SH AUTHOR
Tristan Richardson, RealVNC Ltd. and others.
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc
index 7ca71d9..20072f4 100644
--- a/unix/xserver/hw/vnc/vncExtInit.cc
+++ b/unix/xserver/hw/vnc/vncExtInit.cc
@@ -73,10 +73,6 @@
typedef std::set<std::string, CaseInsensitiveCompare> ParamSet;
static ParamSet allowOverrideSet;
-rfb::StringParameter httpDir("httpd",
- "Directory containing files to serve via HTTP",
- "");
-rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
&rfb::Server::clientWaitTimeMillis);
rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
@@ -177,7 +173,6 @@
if (!desktop[scr]) {
std::list<network::SocketListener*> listeners;
- std::list<network::SocketListener*> httpListeners;
if (scr == 0 && vncInetdSock != -1) {
if (network::isSocketListening(vncInetdSock))
{
@@ -214,21 +209,6 @@
vlog.info("Listening for VNC connections on %s interface(s), port %d",
localhostOnly ? "local" : (const char*)interface,
port);
-
- CharArray httpDirStr(httpDir.getData());
- if (httpDirStr.buf[0]) {
- port = httpPort;
- if (port == 0) port = 5800 + atoi(vncGetDisplay());
- port += 1000 * scr;
- if (localhostOnly)
- network::createLocalTcpListeners(&httpListeners, port);
- else
- network::createTcpListeners(&httpListeners, addr, port);
-
- vlog.info("Listening for HTTP connections on %s interface(s), port %d",
- localhostOnly ? "local" : (const char*)interface,
- port);
- }
}
CharArray desktopNameStr(desktopName.getData());
@@ -237,7 +217,6 @@
vncSetGlueContext(scr);
desktop[scr] = new XserverDesktop(scr,
listeners,
- httpListeners,
desktopNameStr.buf,
pf,
vncGetScreenWidth(),
diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h
index 9414723..5f97f96 100644
--- a/unix/xserver/hw/vnc/vncExtInit.h
+++ b/unix/xserver/hw/vnc/vncExtInit.h
@@ -23,13 +23,6 @@
#include <stddef.h>
#include <sys/select.h>
-// Only from C++
-#ifdef __cplusplus
-namespace rfb { class StringParameter; };
-
-extern rfb::StringParameter httpDir;
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c
index c845ebc..98c4a15 100644
--- a/unix/xserver/hw/vnc/xvnc.c
+++ b/unix/xserver/hw/vnc/xvnc.c
@@ -89,7 +89,7 @@
#define XVNCVERSION "TigerVNC 1.9.80"
#define XVNCCOPYRIGHT ("Copyright (C) 1999-2018 TigerVNC Team and many others (see README.rst)\n" \
- "See http://www.tigervnc.org for information on TigerVNC.\n")
+ "See https://www.tigervnc.org for information on TigerVNC.\n")
#define VFB_DEFAULT_WIDTH 1024
#define VFB_DEFAULT_HEIGHT 768
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index 166597e..69186c5 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -113,14 +113,14 @@
if (strchr(vncServerName, '/') != NULL) {
sock = new network::UnixSocket(vncServerName);
serverHost = sock->getPeerAddress();
- vlog.info(_("connected to socket %s"), serverHost);
+ vlog.info(_("Connected to socket %s"), serverHost);
} else
#endif
{
getHostAndPort(vncServerName, &serverHost, &serverPort);
sock = new network::TcpSocket(serverHost, serverPort);
- vlog.info(_("connected to host %s port %d"), serverHost, serverPort);
+ vlog.info(_("Connected to host %s port %d"), serverHost, serverPort);
}
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
@@ -575,9 +575,12 @@
// Select best color level
newFullColour = (kbitsPerSecond > 256);
if (newFullColour != fullColour) {
- vlog.info(_("Throughput %d kbit/s - full color is now %s"),
- kbitsPerSecond,
- newFullColour ? _("enabled") : _("disabled"));
+ if (newFullColour)
+ vlog.info(_("Throughput %d kbit/s - full color is now enabled"),
+ kbitsPerSecond);
+ else
+ vlog.info(_("Throughput %d kbit/s - full color is now disabled"),
+ kbitsPerSecond);
fullColour.setParam(newFullColour);
formatChange = true;
}
diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx
index c79b5c1..1e9803e 100644
--- a/vncviewer/PlatformPixelBuffer.cxx
+++ b/vncviewer/PlatformPixelBuffer.cxx
@@ -34,13 +34,8 @@
static rfb::LogWriter vlog("PlatformPixelBuffer");
PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
- FullFramePixelBuffer(rfb::PixelFormat(32, 24,
-#if !defined(WIN32) && !defined(__APPLE__)
- ImageByteOrder(fl_display) == MSBFirst,
-#else
- false,
-#endif
- true, 255, 255, 255, 16, 8, 0),
+ FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
+ 255, 255, 255, 16, 8, 0),
width, height, 0, stride),
Surface(width, height)
#if !defined(WIN32) && !defined(__APPLE__)
@@ -63,6 +58,9 @@
data = (rdr::U8*)xim->data;
stride = xim->bytes_per_line / (getPF().bpp/8);
+
+ // On X11, the Pixmap backing this Surface is uninitialized.
+ clear(0, 0, 0);
#else
FullFramePixelBuffer::data = (rdr::U8*)Surface::data;
stride = width;
@@ -106,6 +104,9 @@
mutex.unlock();
#if !defined(WIN32) && !defined(__APPLE__)
+ if (r.width() == 0 || r.height() == 0)
+ return r;
+
GC gc;
gc = XCreateGC(fl_display, pixmap, 0, NULL);
diff --git a/vncviewer/Surface_X11.cxx b/vncviewer/Surface_X11.cxx
index 3523da3..6562634 100644
--- a/vncviewer/Surface_X11.cxx
+++ b/vncviewer/Surface_X11.cxx
@@ -109,6 +109,7 @@
void Surface::alloc()
{
+ XRenderPictFormat templ;
XRenderPictFormat* format;
// Might not be open at this point
@@ -117,7 +118,37 @@
pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
width(), height(), 32);
- format = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
+ // Our code assumes a BGRA byte order, regardless of what the endian
+ // of the machine is or the native byte order of XImage, so make sure
+ // we find such a format
+ templ.type = PictTypeDirect;
+ templ.depth = 32;
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ templ.direct.alpha = 0;
+ templ.direct.red = 8;
+ templ.direct.green = 16;
+ templ.direct.blue = 24;
+#else
+ templ.direct.alpha = 24;
+ templ.direct.red = 16;
+ templ.direct.green = 8;
+ templ.direct.blue = 0;
+#endif
+ templ.direct.alphaMask = 0xff;
+ templ.direct.redMask = 0xff;
+ templ.direct.greenMask = 0xff;
+ templ.direct.blueMask = 0xff;
+
+ format = XRenderFindFormat(fl_display, PictFormatType | PictFormatDepth |
+ PictFormatRed | PictFormatRedMask |
+ PictFormatGreen | PictFormatGreenMask |
+ PictFormatBlue | PictFormatBlueMask |
+ PictFormatAlpha | PictFormatAlphaMask,
+ &templ, 0);
+
+ if (!format)
+ throw rdr::Exception("XRenderFindFormat");
+
picture = XRenderCreatePicture(fl_display, pixmap, format, 0, NULL);
visFormat = XRenderFindVisualFormat(fl_display, fl_visual->visual);
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 7b5df57..18ed69e 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -936,6 +936,13 @@
keyCode = ((msg->lParam >> 16) & 0xff);
+ // Windows' touch keyboard doesn't set a scan code for the Alt
+ // portion of the AltGr sequence, so we need to help it out
+ if (!isExtended && (keyCode == 0x00) && (vKey == VK_MENU)) {
+ isExtended = true;
+ keyCode = 0x38;
+ }
+
// Windows doesn't have a proper AltGr, but handles it using fake
// Ctrl+Alt. However the remote end might not be Windows, so we need
// to merge those in to a single AltGr event. We detect this case
@@ -1040,6 +1047,12 @@
keyCode = ((msg->lParam >> 16) & 0xff);
+ // Touch keyboard AltGr (see above)
+ if (!isExtended && (keyCode == 0x00) && (vKey == VK_MENU)) {
+ isExtended = true;
+ keyCode = 0x38;
+ }
+
// We can't get a release in the middle of an AltGr sequence, so
// abort that detection
if (self->altGrArmed) {
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
index a9d4dfe..1c6f524 100644
--- a/vncviewer/vncviewer.cxx
+++ b/vncviewer/vncviewer.cxx
@@ -100,7 +100,7 @@
_("TigerVNC Viewer %d-bit v%s\n"
"Built on: %s\n"
"Copyright (C) 1999-%d TigerVNC Team and many others (see README.rst)\n"
- "See http://www.tigervnc.org for information on TigerVNC."),
+ "See https://www.tigervnc.org for information on TigerVNC."),
(int)sizeof(size_t)*8, PACKAGE_VERSION,
BUILD_TIMESTAMP, 2018);
@@ -348,10 +348,19 @@
#endif
fprintf(stderr,
- "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
- " %s [parameters] -listen [port] [parameters]\n"
+ "\n"
+ "usage: %s [parameters] [host][:displayNum]\n"
+ " %s [parameters] [host][::port]\n"
+#ifndef WIN32
+ " %s [parameters] [unix socket]\n"
+#endif
+ " %s [parameters] -listen [port]\n"
" %s [parameters] [.tigervnc file]\n",
- programName, programName, programName);
+ programName, programName,
+#ifndef WIN32
+ programName,
+#endif
+ programName, programName);
fprintf(stderr,"\n"
"Parameters can be turned on with -<param> or off with -<param>=0\n"
"Parameters which take a value can be specified as "
diff --git a/vncviewer/vncviewer.man b/vncviewer/vncviewer.man
index 729c01d..8762dfb 100644
--- a/vncviewer/vncviewer.man
+++ b/vncviewer/vncviewer.man
@@ -11,13 +11,17 @@
.RI [ host ][:: port ]
.br
.B vncviewer
+.RI [ options ]
+.RI [ unix\ socket ]
+.br
+.B vncviewer
.RI [ options ]
.B \-listen
.RI [ port ]
.br
.B vncviewer
.RI [ options ]
-.RI [ .tigervnc file ]
+.RI [ .tigervnc\ file ]
.SH DESCRIPTION
.B vncviewer
is a viewer (client) for Virtual Network Computing. This manual page documents
@@ -316,7 +320,7 @@
.BR vncconfig (1),
.BR vncserver (1)
.br
-http://www.tigervnc.org
+https://www.tigervnc.org
.SH AUTHOR
Tristan Richardson, RealVNC Ltd. and others.
diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx
index ad55d49..2cedc4a 100644
--- a/win/rfb_win32/SDisplay.cxx
+++ b/win/rfb_win32/SDisplay.cxx
@@ -20,6 +20,8 @@
//
// The SDisplay class encapsulates a particular system display.
+#include <assert.h>
+
#include <rfb_win32/SDisplay.h>
#include <rfb_win32/Service.h>
#include <rfb_win32/TsSessions.h>
@@ -66,9 +68,10 @@
: server(0), pb(0), device(0),
core(0), ptr(0), kbd(0), clipboard(0),
inputs(0), monitor(0), cleanDesktop(0), cursor(0),
- statusLocation(0), ledState(0)
+ statusLocation(0), queryConnectionHandler(0), ledState(0)
{
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
+ terminateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
}
SDisplay::~SDisplay()
@@ -138,6 +141,25 @@
if (statusLocation) *statusLocation = false;
}
+void SDisplay::terminate()
+{
+ SetEvent(terminateEvent);
+}
+
+
+void SDisplay::queryConnection(network::Socket* sock,
+ const char* userName)
+{
+ assert(server != NULL);
+
+ if (queryConnectionHandler) {
+ queryConnectionHandler->queryConnection(sock, userName);
+ return;
+ }
+
+ server->approveConnection(sock, true);
+}
+
void SDisplay::startCore() {
@@ -314,21 +336,6 @@
}
-Point SDisplay::getFbSize() {
- bool startAndStop = !core;
-
- // If not started, do minimal initialisation to get desktop size.
- if (startAndStop)
- recreatePixelBuffer();
- Point result = Point(pb->width(), pb->height());
-
- // Destroy the initialised structures.
- if (startAndStop)
- stopCore();
- return result;
-}
-
-
void
SDisplay::notifyClipboardChanged(const char* text, int len) {
vlog.debug("clipboard text changed");
diff --git a/win/rfb_win32/SDisplay.h b/win/rfb_win32/SDisplay.h
index f36b2b7..6dbfabb 100644
--- a/win/rfb_win32/SDisplay.h
+++ b/win/rfb_win32/SDisplay.h
@@ -52,6 +52,13 @@
virtual const char* methodName() const = 0;
};
+ class QueryConnectionHandler {
+ public:
+ virtual ~QueryConnectionHandler() {}
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName) = 0;
+ };
+
class SDisplay : public SDesktop,
WMMonitor::Notifier,
Clipboard::Notifier,
@@ -65,6 +72,9 @@
virtual void start(VNCServer* vs);
virtual void stop();
+ virtual void terminate();
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
virtual void pointerEvent(const Point& pos, int buttonmask);
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
virtual void clientCutText(const char* str, int len);
@@ -80,17 +90,18 @@
// -=- EventHandler interface
HANDLE getUpdateEvent() {return updateEvent;}
+ HANDLE getTerminateEvent() {return terminateEvent;}
virtual void processEvent(HANDLE event);
// -=- Notification of whether or not SDisplay is started
void setStatusLocation(bool* status) {statusLocation = status;}
- // -=- Used (indirectly) by JavaViewer to get desktop size
+ // -=- Set handler for incoming connections
- Point getFbSize();
-
- friend class SDisplayCore;
+ void setQueryConnectionHandler(QueryConnectionHandler* qch) {
+ queryConnectionHandler = qch;
+ }
static IntParameter updateMethod;
static BoolParameter disableLocalInputs;
@@ -152,10 +163,15 @@
// -=- Event signalled to trigger an update to be flushed
Handle updateEvent;
+ // -=- Event signalled to terminate the server
+ Handle terminateEvent;
// -=- Where to write the active/inactive indicator to
bool* statusLocation;
+ // -=- Whom to query incoming connections
+ QueryConnectionHandler* queryConnectionHandler;
+
unsigned ledState;
};
diff --git a/win/rfb_win32/SocketManager.cxx b/win/rfb_win32/SocketManager.cxx
index 5b211a0..0092d94 100644
--- a/win/rfb_win32/SocketManager.cxx
+++ b/win/rfb_win32/SocketManager.cxx
@@ -21,6 +21,7 @@
#include <winsock2.h>
#include <list>
#include <rfb/LogWriter.h>
+#include <rfb/Timer.h>
#include <rfb_win32/SocketManager.h>
using namespace rfb;
@@ -78,6 +79,7 @@
li.sock = sock_;
li.server = srvr;
li.notifier = acn;
+ li.disable = false;
listeners[event] = li;
}
@@ -128,13 +130,39 @@
throw rdr::Exception("Socket not registered");
}
+bool SocketManager::getDisable(network::SocketServer* srvr)
+{
+ std::map<HANDLE,ListenInfo>::iterator i;
+ for (i=listeners.begin(); i!=listeners.end(); i++) {
+ if (i->second.server == srvr) {
+ return i->second.disable;
+ }
+ }
+ throw rdr::Exception("Listener not registered");
+}
+
+void SocketManager::setDisable(network::SocketServer* srvr, bool disable)
+{
+ bool found = false;
+ std::map<HANDLE,ListenInfo>::iterator i;
+ for (i=listeners.begin(); i!=listeners.end(); i++) {
+ if (i->second.server == srvr) {
+ i->second.disable = disable;
+ // There might be multiple sockets for the same server, so
+ // continue iterating
+ found = true;
+ }
+ }
+ if (!found)
+ throw rdr::Exception("Listener not registered");
+}
int SocketManager::checkTimeouts() {
int timeout = EventManager::checkTimeouts();
std::map<HANDLE,ListenInfo>::iterator i;
for (i=listeners.begin(); i!=listeners.end(); i++)
- soonestTimeout(&timeout, i->second.server->checkTimeouts());
+ soonestTimeout(&timeout, Timer::checkTimeouts());
std::list<network::Socket*> shutdownSocks;
std::map<HANDLE,ConnInfo>::iterator j, j_next;
@@ -164,7 +192,7 @@
WSAEnumNetworkEvents(li.sock->getFd(), event, &network_events);
if (network_events.lNetworkEvents & FD_ACCEPT) {
network::Socket* new_sock = li.sock->accept();
- if (new_sock && li.server->getDisable()) {
+ if (new_sock && li.disable) {
delete new_sock;
new_sock = 0;
}
diff --git a/win/rfb_win32/SocketManager.h b/win/rfb_win32/SocketManager.h
index c3c8faf..e5ca02e 100644
--- a/win/rfb_win32/SocketManager.h
+++ b/win/rfb_win32/SocketManager.h
@@ -65,6 +65,9 @@
// the SocketServer.
void addSocket(network::Socket* sock_, network::SocketServer* srvr, bool outgoing=true);
+ bool getDisable(network::SocketServer* srvr);
+ void setDisable(network::SocketServer* srvr, bool disable);
+
protected:
virtual int checkTimeouts();
virtual void processEvent(HANDLE event);
@@ -78,6 +81,7 @@
network::SocketListener* sock;
network::SocketServer* server;
AddressChangeNotifier* notifier;
+ bool disable;
};
std::map<HANDLE, ListenInfo> listeners;
std::map<HANDLE, ConnInfo> connections;
diff --git a/win/vncconfig/Connections.h b/win/vncconfig/Connections.h
index b3402ab..c3d6737 100644
--- a/win/vncconfig/Connections.h
+++ b/win/vncconfig/Connections.h
@@ -27,8 +27,6 @@
#include <rfb/Blacklist.h>
#include <network/TcpSocket.h>
-static rfb::IntParameter http_port("HTTPPortNumber",
- "TCP/IP port on which the server will serve the Java applet VNC Viewer ", 5800);
static rfb::IntParameter port_number("PortNumber",
"TCP/IP port on which the server will accept connections", 5900);
static rfb::StringParameter hosts("Hosts",
@@ -96,10 +94,6 @@
setItemInt(IDC_PORT, port_number ? port_number : 5900);
setItemChecked(IDC_RFB_ENABLE, port_number != 0);
setItemInt(IDC_IDLE_TIMEOUT, rfb::Server::idleTimeout);
- vlog.debug("set IDC_HTTP_PORT %d", (int)http_port);
- setItemInt(IDC_HTTP_PORT, http_port ? http_port : 5800);
- setItemChecked(IDC_HTTP_ENABLE, http_port != 0);
- enableItem(IDC_HTTP_PORT, http_port != 0);
setItemChecked(IDC_LOCALHOST, localHost);
HWND listBox = GetDlgItem(handle, IDC_HOSTS);
@@ -133,26 +127,14 @@
return true;
case IDC_PORT:
- if (cmd == EN_CHANGE) {
- try {
- setItemInt(IDC_HTTP_PORT, rfbPortToHTTP(getItemInt(IDC_PORT)));
- } catch (...) {
- }
- }
- case IDC_HTTP_PORT:
case IDC_IDLE_TIMEOUT:
if (cmd == EN_CHANGE)
setChanged(isChanged());
return false;
- case IDC_HTTP_ENABLE:
case IDC_RFB_ENABLE:
case IDC_LOCALHOST:
{
- // HTTP port
- enableItem(IDC_HTTP_PORT, isItemChecked(IDC_HTTP_ENABLE) && isItemChecked(IDC_RFB_ENABLE));
- enableItem(IDC_HTTP_ENABLE, isItemChecked(IDC_RFB_ENABLE));
-
// RFB port
enableItem(IDC_PORT, isItemChecked(IDC_RFB_ENABLE));
@@ -245,8 +227,6 @@
bool onOk() {
regKey.setInt(_T("PortNumber"), isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0);
regKey.setInt(_T("IdleTimeout"), getItemInt(IDC_IDLE_TIMEOUT));
- regKey.setInt(_T("HTTPPortNumber"), isItemChecked(IDC_HTTP_ENABLE) && isItemChecked(IDC_RFB_ENABLE)
- ? getItemInt(IDC_HTTP_PORT) : 0);
regKey.setInt(_T("LocalHost"), isItemChecked(IDC_LOCALHOST));
regKey.setString(_T("Hosts"), TCharArray(getHosts()).buf);
return true;
@@ -258,8 +238,6 @@
return (strcmp(new_hosts.buf, old_hosts.buf) != 0) ||
(localHost != isItemChecked(IDC_LOCALHOST)) ||
(port_number != getItemInt(IDC_PORT)) ||
- (http_port != getItemInt(IDC_HTTP_PORT)) ||
- ((http_port!=0) != (isItemChecked(IDC_HTTP_ENABLE)!=0)) ||
(rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT));
} catch (rdr::Exception&) {
return false;
@@ -281,15 +259,6 @@
}
return strDup(hosts_str.buf);
}
- int rfbPortToHTTP(int rfbPort) {
- int offset = -100;
- if (http_port)
- offset = http_port - port_number;
- int httpPort = rfbPort + offset;
- if (httpPort <= 0)
- httpPort = rfbPort;
- return httpPort;
- }
protected:
RegKey regKey;
diff --git a/win/vncconfig/Legacy.cxx b/win/vncconfig/Legacy.cxx
index b56eb37..deba0ff 100644
--- a/win/vncconfig/Legacy.cxx
+++ b/win/vncconfig/Legacy.cxx
@@ -192,10 +192,6 @@
void LegacyPage::LoadUserPrefs(const RegKey& key)
{
- if (key.getBool(_T("HTTPConnect"), true))
- regKey.setInt(_T("HTTPPortNumber"), key.getInt(_T("PortNumber"), 5900)-100);
- else
- regKey.setInt(_T("HTTPPortNumber"), 0);
regKey.setInt(_T("PortNumber"), key.getBool(_T("SocketConnect")) ? key.getInt(_T("PortNumber"), 5900) : 0);
if (key.getBool(_T("AutoPortSelect"), false)) {
MsgBox(0, _T("The AutoPortSelect setting is not supported by this release.")
diff --git a/win/vncconfig/resource.h b/win/vncconfig/resource.h
index 16bbc15..7350f5b 100644
--- a/win/vncconfig/resource.h
+++ b/win/vncconfig/resource.h
@@ -52,8 +52,6 @@
#define IDC_BUILDTIME 1040
#define IDC_VERSION 1041
#define IDC_COPYRIGHT 1042
-#define IDC_HTTP_ENABLE 1043
-#define IDC_HTTP_PORT 1044
#define IDC_BL_THRESHOLD 1046
#define IDC_BL_TIMEOUT 1047
#define IDC_AFFECT_SCREENSAVER 1048
diff --git a/win/vncconfig/vncconfig.rc b/win/vncconfig/vncconfig.rc
index 27a8b5d..781277c 100644
--- a/win/vncconfig/vncconfig.rc
+++ b/win/vncconfig/vncconfig.rc
@@ -110,9 +110,6 @@
LTEXT "Disconnect idle clients after (seconds):",IDC_STATIC,7,
25,138,15,SS_CENTERIMAGE
EDITTEXT IDC_IDLE_TIMEOUT,150,25,61,15,ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "Serve Java viewer via HTTP on port:",IDC_HTTP_ENABLE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,138,15
- EDITTEXT IDC_HTTP_PORT,150,40,61,15,ES_AUTOHSCROLL | ES_NUMBER
GROUPBOX "Access Control",IDC_STATIC,7,55,204,135
CONTROL "Only accept connections from the local machine",
IDC_LOCALHOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,
@@ -233,7 +230,7 @@
LTEXT ">version<",IDC_VERSION,165,7,77,18
LTEXT ">buildtime<",IDC_BUILDTIME,40,25,202,15
LTEXT ">copyright<",IDC_COPYRIGHT,40,40,256,15
- LTEXT "See http://www.tigervnc.org for more information on TigerVNC.",
+ LTEXT "See https://www.tigervnc.org for more information on TigerVNC.",
IDC_STATIC,40,55,202,15
END
diff --git a/win/winvnc/CMakeLists.txt b/win/winvnc/CMakeLists.txt
index ac9ae29..113796c 100644
--- a/win/winvnc/CMakeLists.txt
+++ b/win/winvnc/CMakeLists.txt
@@ -1,29 +1,18 @@
include_directories(${CMAKE_BINARY_DIR}/win ${CMAKE_CURRENT_SOURCE_DIR})
-set(VNCVIEWER_JAR_PATH ${CMAKE_BINARY_DIR}/java/VncViewer.jar)
-set(INDEX_VNC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/index.vnc)
-
-configure_file(winvnc.rc.in winvnc.rc)
-
add_executable(winvnc4 WIN32
buildTime.cxx
ControlPanel.cxx
- JavaViewer.cxx
ManagedListener.cxx
QueryConnectDialog.cxx
STrayIcon.cxx
VNCServerService.cxx
VNCServerWin32.cxx
winvnc.cxx
- ${CMAKE_CURRENT_BINARY_DIR}/winvnc.rc)
+ winvnc.rc)
target_link_libraries(winvnc4 rfb rfb_win32 network rdr ws2_32.lib)
-if(BUILD_JAVA)
- set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/winvnc.rc
- PROPERTIES OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/java/VncViewer.jar)
-endif()
-
install(TARGETS winvnc4
RUNTIME DESTINATION ${BIN_DIR}
)
diff --git a/win/winvnc/ControlPanel.cxx b/win/winvnc/ControlPanel.cxx
index ba6cab2..72831e5 100644
--- a/win/winvnc/ControlPanel.cxx
+++ b/win/winvnc/ControlPanel.cxx
@@ -19,10 +19,9 @@
{
TCHAR *ColumnsStrings[] = {
(TCHAR *) "IP address",
- (TCHAR *) "Time connected",
(TCHAR *) "Status"
};
- InitLVColumns(IDC_LIST_CONNECTIONS, handle, 120, 3, ColumnsStrings,
+ InitLVColumns(IDC_LIST_CONNECTIONS, handle, 120, 2, ColumnsStrings,
LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
LVS_EX_FULLROWSELECT, LVCFMT_LEFT);
SendCommand(4, -1);
@@ -74,7 +73,7 @@
}
-void ControlPanel::UpdateListView(rfb::ListConnInfo* LCInfo)
+void ControlPanel::UpdateListView(ListConnInfo* LCInfo)
{
getSelConnInfo();
DeleteAllLVItem(IDC_LIST_CONNECTIONS, handle);
@@ -85,12 +84,12 @@
ListConn.Copy(LCInfo);
- char* ItemString[3];
+ char* ItemString[2];
int i = 0;
for (ListConn.iBegin(); !ListConn.iEnd(); ListConn.iNext()) {
ListConn.iGetCharInfo(ItemString);
- InsertLVItem(IDC_LIST_CONNECTIONS, handle, i, (TCHAR **) ItemString, 3);
+ InsertLVItem(IDC_LIST_CONNECTIONS, handle, i, (TCHAR **) ItemString, 2);
for (ListSelConn.iBegin(); !ListSelConn.iEnd(); ListSelConn.iNext()) {
if (ListSelConn.iGetConn() == ListConn.iGetConn())
SelectLVItem(IDC_LIST_CONNECTIONS, handle, i);
@@ -141,6 +140,8 @@
{
COPYDATASTRUCT copyData;
copyData.dwData = command;
+ copyData.cbData = 0;
+ copyData.lpData = 0;
getSelConnInfo();
if (data != -1) {
ListConnStatus.Copy(&ListSelConn);
@@ -149,8 +150,6 @@
} else {
ListConnStatus.Clear();
}
- copyData.cbData = 0;
- copyData.lpData = &ListConnStatus;
SendMessage(m_hSTIcon, WM_COPYDATA, 0, (LPARAM)©Data);
}
diff --git a/win/winvnc/ControlPanel.h b/win/winvnc/ControlPanel.h
index 73b859f..f64a608 100644
--- a/win/winvnc/ControlPanel.h
+++ b/win/winvnc/ControlPanel.h
@@ -11,10 +11,10 @@
#include <list>
#include <winvnc/resource.h>
+#include <winvnc/ListConnInfo.h>
#include <rfb_win32/Dialog.h>
#include <rfb_win32/ListViewControl.h>
#include <rfb_win32/Win32Util.h>
-#include <rfb/ListConnInfo.h>
namespace winvnc {
@@ -27,19 +27,19 @@
virtual bool showDialog();
virtual void initDialog();
virtual bool onCommand(int cmd);
- void UpdateListView(rfb::ListConnInfo* LCInfo);
+ void UpdateListView(ListConnInfo* LCInfo);
HWND GetHandle() {return handle;};
void SendCommand(DWORD command, int data);
~ControlPanel();
- rfb::ListConnInfo ListConnStatus;
+ ListConnInfo ListConnStatus;
protected:
virtual BOOL dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void getSelConnInfo();
HWND m_hSTIcon;
- rfb::ListConnInfo ListConn;
- rfb::ListConnInfo ListSelConn;
+ ListConnInfo ListConn;
+ ListConnInfo ListSelConn;
bool stop_updating;
};
};
-#endif
\ No newline at end of file
+#endif
diff --git a/win/winvnc/JavaViewer.cxx b/win/winvnc/JavaViewer.cxx
deleted file mode 100644
index e2e307e..0000000
--- a/win/winvnc/JavaViewer.cxx
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * 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.
- */
-
-#include <winvnc/JavaViewer.h>
-#include <winvnc/VNCServerWin32.h>
-#include <winvnc/resource.h>
-#include <rdr/MemInStream.h>
-#include <rfb/LogWriter.h>
-#include <rfb/VNCServerST.h>
-#include <rfb_win32/TCharArray.h>
-
-#include <windows.h>
-
-using namespace winvnc;
-using namespace rfb;
-
-
-static rfb::LogWriter vlog("JavaViewerServer");
-
-JavaViewerServer::JavaViewerServer(VNCServerWin32* svr) : server(svr) {
-}
-
-JavaViewerServer::~JavaViewerServer() {
-}
-
-rdr::InStream* JavaViewerServer::getFile(const char* name,
- const char** contentType,
- int* contentLength,
- time_t* lastModified)
-{
- if (strcmp(name, "/") == 0)
- name = "/index.vnc";
- if (strcmp(name, "/VncViewer.jar") == 0)
- name = "VncViewer.jar";
- if (strcmp(name, "/index.vnc") == 0)
- name = "index.vnc";
-
- HRSRC resource = FindResource(0, TStr(name), _T("HTTPFILE"));
- if (!resource) return 0;
- HGLOBAL handle = LoadResource(0, resource);
- if (!handle) return 0;
- void* buf = LockResource(handle);
- int len = SizeofResource(0, resource);
-
- rdr::InStream* is = new rdr::MemInStream(buf, len);
- if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
- is = new rdr::SubstitutingInStream(is, this, 20);
- *contentType = "text/html";
- }
- return is;
-}
-
-char* JavaViewerServer::substitute(const char* varName)
-{
- if (strcmp(varName, "$$") == 0) {
- return rfb::strDup("$");
- }
- if (strcmp(varName, "$PORT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", rfbPort);
- return str;
- }
- if (strcmp(varName, "$WIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", server->getDesktopSize().x);
- return str;
- }
- if (strcmp(varName, "$HEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", server->getDesktopSize().y);
- return str;
- }
- if (strcmp(varName, "$APPLETWIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", server->getDesktopSize().x);
- return str;
- }
- if (strcmp(varName, "$APPLETHEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", server->getDesktopSize().y);
- return str;
- }
- if (strcmp(varName, "$DESKTOP") == 0) {
- return rfb::strDup(server->getName());
- }
- if (strcmp(varName, "$USER") == 0) {
- char tempStr[256]; DWORD tempStrLen = 256;
- GetUserName(tempStr, &tempStrLen);
- return rfb::strDup(tempStr);
- }
- return 0;
-}
diff --git a/win/winvnc/JavaViewer.h b/win/winvnc/JavaViewer.h
deleted file mode 100644
index 79a3969..0000000
--- a/win/winvnc/JavaViewer.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * 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.
- */
-
-// -=- JavaViewer.h
-
-// Custom HTTPServer-derived class which serves the Java VNC Viewer
-// to clients, using resource files compiled in to the WinVNC executable.
-
-#ifndef WINVNC_JAVA_VIEWER
-#define WINVNC_JAVA_VIEWER
-
-#include <rfb/HTTPServer.h>
-#include <rdr/SubstitutingInStream.h>
-
-namespace winvnc {
-
- class VNCServerWin32;
-
- class JavaViewerServer : public rfb::HTTPServer, public rdr::Substitutor {
- public:
- JavaViewerServer(VNCServerWin32* desktop);
- virtual ~JavaViewerServer();
-
- virtual rdr::InStream* getFile(const char* name, const char** contentType,
- int* contentLength, time_t* lastModified);
-
- // rdr::Substitutor callback
- virtual char* substitute(const char* varName);
-
- void setRFBport(int port) {
- rfbPort = port;
- }
- protected:
- int rfbPort;
- VNCServerWin32* server;
- };
-
-};
-
-#endif
-
diff --git a/common/rfb/ListConnInfo.h b/win/winvnc/ListConnInfo.h
similarity index 80%
rename from common/rfb/ListConnInfo.h
rename to win/winvnc/ListConnInfo.h
index c49947d..6ca5b7c 100644
--- a/common/rfb/ListConnInfo.h
+++ b/win/winvnc/ListConnInfo.h
@@ -24,7 +24,7 @@
#include <rfb/util.h>
-namespace rfb {
+namespace winvnc {
struct ListConnInfo {
ListConnInfo() : disableClients(false) {}
@@ -32,7 +32,6 @@
void Clear() {
conn.clear();
IP_address.clear();
- time_conn.clear();
status.clear();
}
@@ -41,7 +40,6 @@
void iBegin() {
ci = conn.begin();
Ii = IP_address.begin();
- ti = time_conn.begin();
si = status.begin();
}
@@ -50,32 +48,29 @@
void iNext() {
ci++;
Ii++;
- ti++;
si++;
}
- void addInfo(void* Conn, char* IP, char* Time, int Status) {
+ void addInfo(void* Conn, char* IP, int Status) {
conn.push_back(Conn);
- IP_address.push_back(strDup(IP));
- time_conn.push_back(strDup(Time));
+ IP_address.push_back(rfb::strDup(IP));
status.push_back(Status);
}
- void iGetCharInfo(char* buf[3]) {
+ void iGetCharInfo(char* buf[2]) {
buf[0] = *Ii;
- buf[1] = *ti;
switch (*si) {
case 0:
- buf[2] = strDup("Full control");
+ buf[1] = rfb::strDup("Full control");
break;
case 1:
- buf[2] = strDup("View only");
+ buf[1] = rfb::strDup("View only");
break;
case 2:
- buf[2] = strDup("Stop updating");
+ buf[1] = rfb::strDup("Stop updating");
break;
default:
- buf[2] = strDup("Unknown");
+ buf[1] = rfb::strDup("Unknown");
}
}
@@ -95,9 +90,9 @@
}
void iAdd (ListConnInfo* InputList) {
- char* buf[3];
+ char* buf[2];
InputList->iGetCharInfo(buf);
- addInfo(InputList->iGetConn(), buf[0], buf[1], InputList->iGetStatus());
+ addInfo(InputList->iGetConn(), buf[0], InputList->iGetStatus());
}
void setDisable(bool disable) {disableClients = disable;}
@@ -113,11 +108,9 @@
private:
std::list<void*> conn;
std::list<char*> IP_address;
- std::list<char*> time_conn;
std::list<int> status;
std::list<void*>::iterator ci;
std::list<char*>::iterator Ii;
- std::list<char*>::iterator ti;
std::list<int>::iterator si;
bool disableClients;
};
diff --git a/win/winvnc/STrayIcon.cxx b/win/winvnc/STrayIcon.cxx
index 05a38d6..a90819d 100644
--- a/win/winvnc/STrayIcon.cxx
+++ b/win/winvnc/STrayIcon.cxx
@@ -184,7 +184,7 @@
case 2:
return thread.server.disconnectClients("IPC disconnect") ? 1 : 0;
case 3:
- thread.server.setClientsStatus((rfb::ListConnInfo *)command->lpData);
+ thread.server.setClientsStatus(&CPanel->ListConnStatus);
case 4:
thread.server.getClientsInfo(&LCInfo);
CPanel->UpdateListView(&LCInfo);
@@ -230,7 +230,7 @@
LaunchProcess vncConnect;
STrayIconThread& thread;
ControlPanel * CPanel;
- rfb::ListConnInfo LCInfo;
+ ListConnInfo LCInfo;
};
diff --git a/win/winvnc/VNCServerService.cxx b/win/winvnc/VNCServerService.cxx
index 5656de0..f5a4dba 100644
--- a/win/winvnc/VNCServerService.cxx
+++ b/win/winvnc/VNCServerService.cxx
@@ -19,6 +19,7 @@
// -=- WinVNC Version 4.0 Service-Mode implementation
#include <winvnc/VNCServerService.h>
+#include <rfb/LogWriter.h>
#include <rfb_win32/TsSessions.h>
#include <rfb_win32/ModuleFileName.h>
#include <windows.h>
diff --git a/win/winvnc/VNCServerWin32.cxx b/win/winvnc/VNCServerWin32.cxx
index b164c65..e001449 100644
--- a/win/winvnc/VNCServerWin32.cxx
+++ b/win/winvnc/VNCServerWin32.cxx
@@ -20,6 +20,7 @@
#include <winvnc/VNCServerWin32.h>
#include <winvnc/resource.h>
+#include <winvnc/ListConnInfo.h>
#include <winvnc/STrayIcon.h>
#include <os/Mutex.h>
@@ -42,8 +43,6 @@
const TCHAR* winvnc::VNCServerWin32::RegConfigPath = _T("Software\\TigerVNC\\WinVNC4");
-static IntParameter http_port("HTTPPortNumber",
- "TCP/IP port on which the server will serve the Java applet VNC Viewer ", 5800);
static IntParameter port_number("PortNumber",
"TCP/IP port on which the server will accept connections", 5900);
static StringParameter hosts("Hosts",
@@ -63,8 +62,7 @@
CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNC") : 0),
vncServer(CStr(ComputerName().buf), &desktop),
thread_id(-1), runServer(false), isDesktopStarted(false),
- httpServer(this), config(&sockMgr),
- rfbSock(&sockMgr), httpSock(&sockMgr), trayIcon(0),
+ config(&sockMgr), rfbSock(&sockMgr), trayIcon(0),
queryConnectDialog(0)
{
commandLock = new os::Mutex;
@@ -74,12 +72,11 @@
// Initialise the desktop
desktop.setStatusLocation(&isDesktopStarted);
-
- // Initialise the VNC server
- vncServer.setQueryConnectionHandler(this);
+ desktop.setQueryConnectionHandler(this);
// Register the desktop's event to be handled
sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
+ sockMgr.addEvent(desktop.getTerminateEvent(), this);
// Register the queued command event to be handled
sockMgr.addEvent(commandEvent, this);
@@ -148,16 +145,10 @@
// -=- Make sure we're listening on the right ports.
rfbSock.setServer(&vncServer);
rfbSock.setPort(port_number, localHost);
- httpSock.setServer(&httpServer);
- httpSock.setPort(http_port, localHost);
-
- // -=- Update the Java viewer's web page port number.
- httpServer.setRFBport(rfbSock.isListening() ? port_number : 0);
// -=- Update the TCP address filter for both ports, if open.
CharArray pattern(hosts.getData());
rfbSock.setFilter(pattern.buf);
- httpSock.setFilter(pattern.buf);
// -=- Update the tray icon tooltip text with IP addresses
processAddressChange();
@@ -250,27 +241,27 @@
return false;
}
-bool VNCServerWin32::getClientsInfo(rfb::ListConnInfo* LCInfo) {
+bool VNCServerWin32::getClientsInfo(ListConnInfo* LCInfo) {
return queueCommand(GetClientsInfo, LCInfo, 0);
}
-bool VNCServerWin32::setClientsStatus(rfb::ListConnInfo* LCInfo) {
+bool VNCServerWin32::setClientsStatus(ListConnInfo* LCInfo) {
return queueCommand(SetClientsStatus, LCInfo, 0);
}
-VNCServerST::queryResult VNCServerWin32::queryConnection(network::Socket* sock,
- const char* userName,
- char** reason)
+void VNCServerWin32::queryConnection(network::Socket* sock,
+ const char* userName)
{
- if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn())
- return VNCServerST::ACCEPT;
+ if (queryOnlyIfLoggedOn && CurrentUserToken().noUserLoggedOn()) {
+ vncServer.approveConnection(sock, true, NULL);
+ return;
+ }
if (queryConnectDialog) {
- *reason = rfb::strDup("Another connection is currently being queried.");
- return VNCServerST::REJECT;
+ vncServer.approveConnection(sock, false, "Another connection is currently being queried.");
+ return;
}
queryConnectDialog = new QueryConnectDialog(sock, userName, this);
queryConnectDialog->startDialog();
- return VNCServerST::PENDING;
}
void VNCServerWin32::queryConnectionComplete() {
@@ -318,10 +309,10 @@
sockMgr.addSocket((network::Socket*)commandData, &vncServer);
break;
case GetClientsInfo:
- vncServer.getConnInfo((ListConnInfo*)commandData);
+ getConnInfo((ListConnInfo*)commandData);
break;
case SetClientsStatus:
- vncServer.setConnStatus((ListConnInfo*)commandData);
+ setConnStatus((ListConnInfo*)commandData);
break;
case QueryConnectionComplete:
@@ -345,8 +336,88 @@
command = NoCommand;
commandSig->signal();
}
- } else if (event_ == sessionEvent.h) {
+ } else if ((event_ == sessionEvent.h) ||
+ (event_ == desktop.getTerminateEvent())) {
stop();
}
}
+void VNCServerWin32::getConnInfo(ListConnInfo * listConn)
+{
+ std::list<network::Socket*> sockets;
+ std::list<network::Socket*>::iterator i;
+
+ listConn->Clear();
+ listConn->setDisable(sockMgr.getDisable(&vncServer));
+
+ vncServer.getSockets(&sockets);
+
+ for (i = sockets.begin(); i != sockets.end(); i++) {
+ rfb::SConnection* conn;
+ int status;
+
+ conn = vncServer.getConnection(*i);
+ if (!conn)
+ continue;
+
+ if (conn->accessCheck(rfb::SConnection::AccessPtrEvents |
+ rfb::SConnection::AccessKeyEvents |
+ rfb::SConnection::AccessView))
+ status = 0;
+ else if (conn->accessCheck(rfb::SConnection::AccessView))
+ status = 1;
+ else
+ status = 2;
+
+ listConn->addInfo((void*)(*i), (*i)->getPeerAddress(), status);
+ }
+}
+
+void VNCServerWin32::setConnStatus(ListConnInfo* listConn)
+{
+ sockMgr.setDisable(&vncServer, listConn->getDisable());
+
+ if (listConn->Empty())
+ return;
+
+ for (listConn->iBegin(); !listConn->iEnd(); listConn->iNext()) {
+ network::Socket* sock;
+ rfb::SConnection* conn;
+ int status;
+
+ sock = (network::Socket*)listConn->iGetConn();
+
+ conn = vncServer.getConnection(sock);
+ if (!conn)
+ continue;
+
+ status = listConn->iGetStatus();
+ if (status == 3) {
+ conn->close(0);
+ } else {
+ rfb::SConnection::AccessRights ar;
+
+ ar = rfb::SConnection::AccessDefault;
+
+ switch (status) {
+ case 0:
+ ar |= rfb::SConnection::AccessPtrEvents |
+ rfb::SConnection::AccessKeyEvents |
+ rfb::SConnection::AccessView;
+ break;
+ case 1:
+ ar |= rfb::SConnection::AccessView;
+ ar &= ~(rfb::SConnection::AccessPtrEvents |
+ rfb::SConnection::AccessKeyEvents);
+ break;
+ case 2:
+ ar &= ~(rfb::SConnection::AccessPtrEvents |
+ rfb::SConnection::AccessKeyEvents |
+ rfb::SConnection::AccessView);
+ break;
+ }
+ conn->setAccessRights(ar);
+ conn->framebufferUpdateRequest(vncServer.getPixelBuffer()->getRect(), false);
+ }
+ }
+}
diff --git a/win/winvnc/VNCServerWin32.h b/win/winvnc/VNCServerWin32.h
index ed051dc..1a73782 100644
--- a/win/winvnc/VNCServerWin32.h
+++ b/win/winvnc/VNCServerWin32.h
@@ -27,7 +27,6 @@
#include <rfb_win32/SocketManager.h>
#include <rfb_win32/TCharArray.h>
#include <winvnc/QueryConnectDialog.h>
-#include <winvnc/JavaViewer.h>
#include <winvnc/ManagedListener.h>
namespace os {
@@ -38,9 +37,10 @@
namespace winvnc {
+ class ListConnInfo;
class STrayIconThread;
- class VNCServerWin32 : rfb::VNCServerST::QueryConnectionHandler,
+ class VNCServerWin32 : rfb::win32::QueryConnectionHandler,
rfb::win32::SocketManager::AddressChangeNotifier,
rfb::win32::RegConfig::Callback,
rfb::win32::EventHandler {
@@ -74,21 +74,16 @@
// Where to read the configuration settings from
static const TCHAR* RegConfigPath;
- bool getClientsInfo(rfb::ListConnInfo* LCInfo);
+ bool getClientsInfo(ListConnInfo* LCInfo);
- bool setClientsStatus(rfb::ListConnInfo* LCInfo);
-
- // Used by JavaViewerServer
- const char* getName() {return vncServer.getName();}
- rfb::Point getDesktopSize() {return desktop.getFbSize();}
+ bool setClientsStatus(ListConnInfo* LCInfo);
protected:
- // VNCServerST::QueryConnectionHandler interface
+ // QueryConnectionHandler interface
// Callback used to prompt user to accept or reject a connection.
// CALLBACK IN VNCServerST "HOST" THREAD
- virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason);
+ virtual void queryConnection(network::Socket* sock,
+ const char* userName);
// SocketManager::AddressChangeNotifier interface
// Used to keep tray icon up to date
@@ -102,6 +97,9 @@
// Used to perform queued commands
virtual void processEvent(HANDLE event);
+ void getConnInfo(ListConnInfo * listConn);
+ void setConnStatus(ListConnInfo* listConn);
+
protected:
// Perform a particular internal function in the server thread
typedef enum {NoCommand, DisconnectClients, AddClient, QueryConnectionComplete, SetClientsStatus, GetClientsInfo} Command;
@@ -121,12 +119,10 @@
DWORD thread_id;
bool runServer;
bool isDesktopStarted;
- JavaViewerServer httpServer;
rfb::win32::SocketManager sockMgr;
rfb::win32::RegConfig config;
ManagedListener rfbSock;
- ManagedListener httpSock;
STrayIconThread* trayIcon;
QueryConnectDialog* queryConnectDialog;
diff --git a/win/winvnc/index.vnc b/win/winvnc/index.vnc
deleted file mode 100644
index 560fa2e..0000000
--- a/win/winvnc/index.vnc
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
- index.vnc - default HTML page for TigerVNC Java viewer applet, to be
- used with WinVNC. On any file ending in .vnc, the HTTP server embedded in
- WinVNC will substitute the following variables when preceded by a dollar:
- USER, DESKTOP, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
- Use two dollar signs ($$) to get a dollar sign in the generated
- HTML page.
--->
-
-<HTML>
-<TITLE>
-$USER's $DESKTOP desktop
-</TITLE>
-<APPLET CODE=com.tigervnc.vncviewer.VncViewer ARCHIVE=VncViewer.jar
- WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
-<param name=PORT value=$PORT>
-<param name="Embed" value="true">
-<param name="draggable" value="true">
-</APPLET>
-<BR>
-<A href="http://www.tigervnc.org/">TigerVNC site</A>
-</HTML>
diff --git a/win/winvnc/resource.h b/win/winvnc/resource.h
index 68316be..0e52368 100644
--- a/win/winvnc/resource.h
+++ b/win/winvnc/resource.h
@@ -8,7 +8,6 @@
#define IDD_DIALOG1 103
#define IDD_ABOUT 104
#define IDI_CONNECTED 105
-#define IDR_VNCVIEWER_JAR 106
#define IDD_QUERY_CONNECT 107
#define IDD_ADD_NEW_CLIENT 108
#define IDB_BITMAP 109
diff --git a/win/winvnc/winvnc.rc.in b/win/winvnc/winvnc.rc
similarity index 95%
rename from win/winvnc/winvnc.rc.in
rename to win/winvnc/winvnc.rc
index 2b50966..91fc0f4 100644
--- a/win/winvnc/winvnc.rc.in
+++ b/win/winvnc/winvnc.rc
@@ -154,7 +154,7 @@
LTEXT ">version<",IDC_VERSION,170,10,72,15
LTEXT ">buildtime<",IDC_BUILDTIME,45,25,202,15
LTEXT ">copyright<",IDC_COPYRIGHT,45,40,256,15
- LTEXT "See http://www.tigervnc.org for more information on VNC.",
+ LTEXT "See https://www.tigervnc.org for more information on VNC.",
IDC_STATIC,45,55,202,15
END
@@ -217,18 +217,6 @@
/////////////////////////////////////////////////////////////////////////////
//
-// HTTPFILE
-//
-
-#cmakedefine BUILD_JAVA
-
-#ifdef BUILD_JAVA
-VNCVIEWER.JAR HTTPFILE DISCARDABLE "@VNCVIEWER_JAR_PATH@"
-INDEX.VNC HTTPFILE DISCARDABLE "@INDEX_VNC_PATH@"
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-//
// 24
//