Applets don't work anymore so remove everything that has to do with serving them.tags/v1.9.90
/* 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 |
d3des.c | d3des.c | ||||
EncodeManager.cxx | EncodeManager.cxx | ||||
Encoder.cxx | Encoder.cxx | ||||
HTTPServer.cxx | |||||
HextileDecoder.cxx | HextileDecoder.cxx | ||||
HextileEncoder.cxx | HextileEncoder.cxx | ||||
JpegCompressor.cxx | JpegCompressor.cxx |
/* 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; | |||||
} |
/* 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 | |||||
# xorg requires newer versions of automake, & autoconf than are available with el5. Use el6 versions. | # 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: 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: pam-devel | ||||
BuildRequires: cmake28 | BuildRequires: cmake28 | ||||
BuildRequires: pkgconfig >= 0.20 | BuildRequires: pkgconfig >= 0.20 | ||||
of TigerVNC server, allowing others to access the desktop on your | of TigerVNC server, allowing others to access the desktop on your | ||||
machine. | 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 | %package license | ||||
Summary: License of TigerVNC suite | Summary: License of TigerVNC suite | ||||
Group: User Interface/X | Group: User Interface/X | ||||
make | make | ||||
popd | 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 | %install | ||||
make install DESTDIR=$RPM_BUILD_ROOT | make install DESTDIR=$RPM_BUILD_ROOT | ||||
install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver | install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver | ||||
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers | 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 | %find_lang %{name} %{name}.lang | ||||
%if %{_bootstrap} | %if %{_bootstrap} | ||||
%{_mandir}/man1/vncconfig.1* | %{_mandir}/man1/vncconfig.1* | ||||
%{_libdir}/* | %{_libdir}/* | ||||
%files server-applet | |||||
%defattr(-,root,root,-) | |||||
%doc java/com/tigervnc/vncviewer/README | |||||
%{_datadir}/vnc/classes/* | |||||
%files license | %files license | ||||
%defattr(-,root,root,-) | %defattr(-,root,root,-) | ||||
%doc LICENCE.TXT | %doc LICENCE.TXT |
BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel | BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel | ||||
BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick | BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick | ||||
BuildRequires: freetype-devel, libXdmcp-devel | BuildRequires: freetype-devel, libXdmcp-devel | ||||
BuildRequires: java-devel, jpackage-utils | |||||
BuildRequires: libjpeg-turbo-devel, pam-devel | BuildRequires: libjpeg-turbo-devel, pam-devel | ||||
BuildRequires: cmake >= 2.8 | BuildRequires: cmake >= 2.8 | ||||
%if !%{_bootstrap} | %if !%{_bootstrap} | ||||
to access the desktop on your machine. | to access the desktop on your machine. | ||||
%endif | %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 | %package license | ||||
Summary: License of TigerVNC suite | Summary: License of TigerVNC suite | ||||
Group: User Interface/X | Group: User Interface/X | ||||
make | make | ||||
popd | 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 | %install | ||||
%if %{_bootstrap} | %if %{_bootstrap} | ||||
for l in gmp libtasn1 nettle gnutls libpng fltk; do | for l in gmp libtasn1 nettle gnutls libpng fltk; do | ||||
install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver | install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/vncserver | ||||
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers | 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 | %find_lang %{name} %{name}.lang | ||||
# remove unwanted files | # remove unwanted files | ||||
%{_libdir}/xorg/modules/extensions/libvnc.so | %{_libdir}/xorg/modules/extensions/libvnc.so | ||||
%endif | %endif | ||||
%files server-applet | |||||
%defattr(-,root,root,-) | |||||
%doc java/com/tigervnc/vncviewer/README | |||||
%{_datadir}/vnc/classes/* | |||||
%files license | %files license | ||||
%defattr(-,root,root,-) | %defattr(-,root,root,-) | ||||
%doc LICENCE.TXT | %doc LICENCE.TXT |
BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel | BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel | ||||
BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick | BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick | ||||
BuildRequires: freetype-devel, libXdmcp-devel, libXfont2-devel | BuildRequires: freetype-devel, libXdmcp-devel, libXfont2-devel | ||||
BuildRequires: java-devel, jpackage-utils | |||||
BuildRequires: libjpeg-turbo-devel, gnutls-devel, pam-devel | BuildRequires: libjpeg-turbo-devel, gnutls-devel, pam-devel | ||||
BuildRequires: systemd, cmake | BuildRequires: systemd, cmake | ||||
to access the desktop on your machine. | to access the desktop on your machine. | ||||
%endif | %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 | %package license | ||||
Summary: License of TigerVNC suite | Summary: License of TigerVNC suite | ||||
Group: User Interface/X | Group: User Interface/X | ||||
make | make | ||||
popd | 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 | %install | ||||
%if %{_bootstrap} | %if %{_bootstrap} | ||||
for l in fltk; do | for l in fltk; do | ||||
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig | mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig | ||||
install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers | 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 | %find_lang %{name} %{name}.lang | ||||
# remove unwanted files | # remove unwanted files | ||||
%config %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf | %config %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf | ||||
%endif | %endif | ||||
%files server-applet | |||||
%defattr(-,root,root,-) | |||||
%doc java/com/tigervnc/vncviewer/README | |||||
%{_datadir}/vnc/classes/* | |||||
%files license | %files license | ||||
%doc %{_docdir}/%{name}-%{version}/LICENCE.TXT | %doc %{_docdir}/%{name}-%{version}/LICENCE.TXT | ||||
-P ${SRCDIR}/cmake/SignJar.cmake) | -P ${SRCDIR}/cmake/SignJar.cmake) | ||||
add_custom_target(java ALL DEPENDS VncViewer.jar) | 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() |
Installation | 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 | Parameters | ||||
========== | ========== | ||||
The TigerVNC Java Viewer accepts a number of optional parameters, allowing you | The TigerVNC Java Viewer accepts a number of optional parameters, allowing you | ||||
to customize its behavior. | |||||
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: | |||||
to customize its behavior. 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. | Both parameter names and their values are case-insensitive. | ||||
<!-- | |||||
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> |
<!-- | |||||
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> |
$exedir = substr($0, 0, $slashndx+1); | $exedir = substr($0, 0, $slashndx+1); | ||||
} | } | ||||
$vncClasses = ""; | |||||
&SanityCheck(); | &SanityCheck(); | ||||
# | # | ||||
$geometry = "1024x768"; | $geometry = "1024x768"; | ||||
#$depth = 16; | #$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"; | $vncUserDir = "$ENV{HOME}/.vnc"; | ||||
$vncUserConfig = "$vncUserDir/config"; | $vncUserConfig = "$vncUserDir/config"; | ||||
# We set some reasonable defaults. Config file settings | # We set some reasonable defaults. Config file settings | ||||
# override these where present. | # override these where present. | ||||
$default_opts{desktop} = "edString($desktopName); | $default_opts{desktop} = "edString($desktopName); | ||||
$default_opts{httpd} = $vncJavaFiles if ($vncJavaFiles); | |||||
$default_opts{auth} = "edString($xauthorityFile); | $default_opts{auth} = "edString($xauthorityFile); | ||||
$default_opts{geometry} = $geometry if ($geometry); | $default_opts{geometry} = $geometry if ($geometry); | ||||
$default_opts{depth} = $depth if ($depth); | $default_opts{depth} = $depth if ($depth); | ||||
foreach $cmd ("Xvnc","vncpasswd") { | foreach $cmd ("Xvnc","vncpasswd") { | ||||
for (split(/:/,$ENV{PATH})) { | for (split(/:/,$ENV{PATH})) { | ||||
if (-x "$_/$cmd") { | if (-x "$_/$cmd") { | ||||
$vncClasses = "$_/../vnc/classes"; | |||||
next cmd2; | next cmd2; | ||||
} | } | ||||
} | } | ||||
foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") { | foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") { | ||||
for (split(/:/,$ENV{PATH})) { | for (split(/:/,$ENV{PATH})) { | ||||
if (-x "$cmd") { | if (-x "$cmd") { | ||||
$vncClasses = $exedir."../vnc/classes"; | |||||
next cmd3; | next cmd3; | ||||
} | } | ||||
} | } |
#include <network/Socket.h> | #include <network/Socket.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
#include <rfb/VNCServerST.h> | #include <rfb/VNCServerST.h> | ||||
#include <rfb/HTTPServer.h> | |||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/Configuration.h> | #include <rfb/Configuration.h> | ||||
#include <rfb/ServerCore.h> | #include <rfb/ServerCore.h> | ||||
"rejecting the connection", | "rejecting the connection", | ||||
10); | 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_, | XserverDesktop::XserverDesktop(int screenIndex_, | ||||
std::list<network::SocketListener*> listeners_, | std::list<network::SocketListener*> listeners_, | ||||
std::list<network::SocketListener*> httpListeners_, | |||||
const char* name, const rfb::PixelFormat &pf, | const char* name, const rfb::PixelFormat &pf, | ||||
int width, int height, | int width, int height, | ||||
void* fbptr, int stride) | void* fbptr, int stride) | ||||
: screenIndex(screenIndex_), | : screenIndex(screenIndex_), | ||||
server(0), httpServer(0), | |||||
listeners(listeners_), httpListeners(httpListeners_), | |||||
server(0), listeners(listeners_), | |||||
directFbptr(true), | directFbptr(true), | ||||
queryConnectId(0), queryConnectTimer(this) | queryConnectId(0), queryConnectTimer(this) | ||||
{ | { | ||||
setFramebuffer(width, height, fbptr, stride); | setFramebuffer(width, height, fbptr, stride); | ||||
server->setQueryConnectionHandler(this); | server->setQueryConnectionHandler(this); | ||||
if (!httpListeners.empty ()) | |||||
httpServer = new FileHTTPServer(this); | |||||
for (std::list<SocketListener*>::iterator i = listeners.begin(); | for (std::list<SocketListener*>::iterator i = listeners.begin(); | ||||
i != listeners.end(); | i != listeners.end(); | ||||
i++) { | i++) { | ||||
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false); | 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() | XserverDesktop::~XserverDesktop() | ||||
delete listeners.back(); | delete listeners.back(); | ||||
listeners.pop_back(); | listeners.pop_back(); | ||||
} | } | ||||
while (!httpListeners.empty()) { | |||||
vncRemoveNotifyFd(listeners.back()->getFd()); | |||||
delete httpListeners.back(); | |||||
httpListeners.pop_back(); | |||||
} | |||||
if (!directFbptr) | if (!directFbptr) | ||||
delete [] data; | delete [] data; | ||||
delete httpServer; | |||||
delete server; | delete server; | ||||
} | } | ||||
server->setScreenLayout(::computeScreenLayout(&outputIdMap)); | server->setScreenLayout(::computeScreenLayout(&outputIdMap)); | ||||
} | } | ||||
char* XserverDesktop::substitute(const char* varName) | |||||
{ | |||||
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; | |||||
} | |||||
rfb::VNCServerST::queryResult | rfb::VNCServerST::queryResult | ||||
XserverDesktop::queryConnection(network::Socket* sock, | XserverDesktop::queryConnection(network::Socket* sock, | ||||
const char* userName, | const char* userName, | ||||
if (read) { | if (read) { | ||||
if (handleListenerEvent(fd, &listeners, server)) | if (handleListenerEvent(fd, &listeners, server)) | ||||
return; | return; | ||||
if (handleListenerEvent(fd, &httpListeners, httpServer)) | |||||
return; | |||||
} | } | ||||
if (handleSocketEvent(fd, server, read, write)) | if (handleSocketEvent(fd, server, read, write)) | ||||
return; | return; | ||||
if (handleSocketEvent(fd, httpServer, read, write)) | |||||
return; | |||||
vlog.error("Cannot find file descriptor for socket event"); | vlog.error("Cannot find file descriptor for socket event"); | ||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0); | 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 | // We are responsible for propagating mouse movement between clients | ||||
int cursorX, cursorY; | int cursorX, cursorY; |
#include <stdint.h> | #include <stdint.h> | ||||
#include <rfb/SDesktop.h> | #include <rfb/SDesktop.h> | ||||
#include <rfb/HTTPServer.h> | |||||
#include <rfb/PixelBuffer.h> | #include <rfb/PixelBuffer.h> | ||||
#include <rfb/Configuration.h> | #include <rfb/Configuration.h> | ||||
#include <rfb/VNCServerST.h> | #include <rfb/VNCServerST.h> | ||||
#include <rdr/SubstitutingInStream.h> | |||||
#include <unixcommon.h> | #include <unixcommon.h> | ||||
#include "Input.h" | #include "Input.h" | ||||
namespace network { class SocketListener; class Socket; class SocketServer; } | namespace network { class SocketListener; class Socket; class SocketServer; } | ||||
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, | class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, | ||||
public rdr::Substitutor, | |||||
public rfb::VNCServerST::QueryConnectionHandler, | public rfb::VNCServerST::QueryConnectionHandler, | ||||
public rfb::Timer::Callback { | public rfb::Timer::Callback { | ||||
public: | public: | ||||
XserverDesktop(int screenIndex, | XserverDesktop(int screenIndex, | ||||
std::list<network::SocketListener*> listeners_, | std::list<network::SocketListener*> listeners_, | ||||
std::list<network::SocketListener*> httpListeners_, | |||||
const char* name, const rfb::PixelFormat &pf, | const char* name, const rfb::PixelFormat &pf, | ||||
int width, int height, void* fbptr, int stride); | int width, int height, void* fbptr, int stride); | ||||
virtual ~XserverDesktop(); | virtual ~XserverDesktop(); | ||||
// rfb::PixelBuffer callbacks | // rfb::PixelBuffer callbacks | ||||
virtual void grabRegion(const rfb::Region& r); | virtual void grabRegion(const rfb::Region& r); | ||||
// rdr::Substitutor callback | |||||
virtual char* substitute(const char* varName); | |||||
// rfb::VNCServerST::QueryConnectionHandler callback | // rfb::VNCServerST::QueryConnectionHandler callback | ||||
virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock, | virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock, | ||||
const char* userName, | const char* userName, | ||||
int screenIndex; | int screenIndex; | ||||
rfb::VNCServerST* server; | rfb::VNCServerST* server; | ||||
rfb::HTTPServer* httpServer; | |||||
std::list<network::SocketListener*> listeners; | std::list<network::SocketListener*> listeners; | ||||
std::list<network::SocketListener*> httpListeners; | |||||
bool directFbptr; | bool directFbptr; | ||||
uint32_t queryConnectId; | uint32_t queryConnectId; |
mean an update will be aborted after this time. Default is 20000 (20 seconds). | mean an update will be aborted after this time. Default is 20000 (20 seconds). | ||||
. | . | ||||
.TP | .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 | .B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP | ||||
Password file for VNC authentication. There is no default, you should | Password file for VNC authentication. There is no default, you should | ||||
specify the password file explicitly. Password file should be created with | specify the password file explicitly. Password file should be created with |
typedef std::set<std::string, CaseInsensitiveCompare> ParamSet; | typedef std::set<std::string, CaseInsensitiveCompare> ParamSet; | ||||
static ParamSet allowOverrideSet; | 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::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis", | ||||
&rfb::Server::clientWaitTimeMillis); | &rfb::Server::clientWaitTimeMillis); | ||||
rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0); | rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0); | ||||
if (!desktop[scr]) { | if (!desktop[scr]) { | ||||
std::list<network::SocketListener*> listeners; | std::list<network::SocketListener*> listeners; | ||||
std::list<network::SocketListener*> httpListeners; | |||||
if (scr == 0 && vncInetdSock != -1) { | if (scr == 0 && vncInetdSock != -1) { | ||||
if (network::isSocketListening(vncInetdSock)) | if (network::isSocketListening(vncInetdSock)) | ||||
{ | { | ||||
vlog.info("Listening for VNC connections on %s interface(s), port %d", | vlog.info("Listening for VNC connections on %s interface(s), port %d", | ||||
localhostOnly ? "local" : (const char*)interface, | localhostOnly ? "local" : (const char*)interface, | ||||
port); | 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()); | CharArray desktopNameStr(desktopName.getData()); | ||||
vncSetGlueContext(scr); | vncSetGlueContext(scr); | ||||
desktop[scr] = new XserverDesktop(scr, | desktop[scr] = new XserverDesktop(scr, | ||||
listeners, | listeners, | ||||
httpListeners, | |||||
desktopNameStr.buf, | desktopNameStr.buf, | ||||
pf, | pf, | ||||
vncGetScreenWidth(), | vncGetScreenWidth(), |
#include <stddef.h> | #include <stddef.h> | ||||
#include <sys/select.h> | #include <sys/select.h> | ||||
// Only from C++ | |||||
#ifdef __cplusplus | |||||
namespace rfb { class StringParameter; }; | |||||
extern rfb::StringParameter httpDir; | |||||
#endif | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
#endif | #endif |
} | } | ||||
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 | void | ||||
SDisplay::notifyClipboardChanged(const char* text, int len) { | SDisplay::notifyClipboardChanged(const char* text, int len) { | ||||
vlog.debug("clipboard text changed"); | vlog.debug("clipboard text changed"); |
void setStatusLocation(bool* status) {statusLocation = status;} | void setStatusLocation(bool* status) {statusLocation = status;} | ||||
// -=- Used (indirectly) by JavaViewer to get desktop size | |||||
Point getFbSize(); | |||||
friend class SDisplayCore; | |||||
static IntParameter updateMethod; | static IntParameter updateMethod; | ||||
static BoolParameter disableLocalInputs; | static BoolParameter disableLocalInputs; | ||||
static StringParameter disconnectAction; | static StringParameter disconnectAction; |
#include <rfb/Blacklist.h> | #include <rfb/Blacklist.h> | ||||
#include <network/TcpSocket.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", | static rfb::IntParameter port_number("PortNumber", | ||||
"TCP/IP port on which the server will accept connections", 5900); | "TCP/IP port on which the server will accept connections", 5900); | ||||
static rfb::StringParameter hosts("Hosts", | static rfb::StringParameter hosts("Hosts", | ||||
setItemInt(IDC_PORT, port_number ? port_number : 5900); | setItemInt(IDC_PORT, port_number ? port_number : 5900); | ||||
setItemChecked(IDC_RFB_ENABLE, port_number != 0); | setItemChecked(IDC_RFB_ENABLE, port_number != 0); | ||||
setItemInt(IDC_IDLE_TIMEOUT, rfb::Server::idleTimeout); | 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); | setItemChecked(IDC_LOCALHOST, localHost); | ||||
HWND listBox = GetDlgItem(handle, IDC_HOSTS); | HWND listBox = GetDlgItem(handle, IDC_HOSTS); | ||||
return true; | return true; | ||||
case IDC_PORT: | 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: | case IDC_IDLE_TIMEOUT: | ||||
if (cmd == EN_CHANGE) | if (cmd == EN_CHANGE) | ||||
setChanged(isChanged()); | setChanged(isChanged()); | ||||
return false; | return false; | ||||
case IDC_HTTP_ENABLE: | |||||
case IDC_RFB_ENABLE: | case IDC_RFB_ENABLE: | ||||
case IDC_LOCALHOST: | 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 | // RFB port | ||||
enableItem(IDC_PORT, isItemChecked(IDC_RFB_ENABLE)); | enableItem(IDC_PORT, isItemChecked(IDC_RFB_ENABLE)); | ||||
bool onOk() { | bool onOk() { | ||||
regKey.setInt(_T("PortNumber"), isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0); | regKey.setInt(_T("PortNumber"), isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0); | ||||
regKey.setInt(_T("IdleTimeout"), getItemInt(IDC_IDLE_TIMEOUT)); | 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.setInt(_T("LocalHost"), isItemChecked(IDC_LOCALHOST)); | ||||
regKey.setString(_T("Hosts"), TCharArray(getHosts()).buf); | regKey.setString(_T("Hosts"), TCharArray(getHosts()).buf); | ||||
return true; | return true; | ||||
return (strcmp(new_hosts.buf, old_hosts.buf) != 0) || | return (strcmp(new_hosts.buf, old_hosts.buf) != 0) || | ||||
(localHost != isItemChecked(IDC_LOCALHOST)) || | (localHost != isItemChecked(IDC_LOCALHOST)) || | ||||
(port_number != getItemInt(IDC_PORT)) || | (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)); | (rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT)); | ||||
} catch (rdr::Exception&) { | } catch (rdr::Exception&) { | ||||
return false; | return false; | ||||
} | } | ||||
return strDup(hosts_str.buf); | 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: | protected: | ||||
RegKey regKey; | RegKey regKey; |
void LegacyPage::LoadUserPrefs(const RegKey& key) | 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); | regKey.setInt(_T("PortNumber"), key.getBool(_T("SocketConnect")) ? key.getInt(_T("PortNumber"), 5900) : 0); | ||||
if (key.getBool(_T("AutoPortSelect"), false)) { | if (key.getBool(_T("AutoPortSelect"), false)) { | ||||
MsgBox(0, _T("The AutoPortSelect setting is not supported by this release.") | MsgBox(0, _T("The AutoPortSelect setting is not supported by this release.") |
#define IDC_BUILDTIME 1040 | #define IDC_BUILDTIME 1040 | ||||
#define IDC_VERSION 1041 | #define IDC_VERSION 1041 | ||||
#define IDC_COPYRIGHT 1042 | #define IDC_COPYRIGHT 1042 | ||||
#define IDC_HTTP_ENABLE 1043 | |||||
#define IDC_HTTP_PORT 1044 | |||||
#define IDC_BL_THRESHOLD 1046 | #define IDC_BL_THRESHOLD 1046 | ||||
#define IDC_BL_TIMEOUT 1047 | #define IDC_BL_TIMEOUT 1047 | ||||
#define IDC_AFFECT_SCREENSAVER 1048 | #define IDC_AFFECT_SCREENSAVER 1048 |
LTEXT "Disconnect idle clients after (seconds):",IDC_STATIC,7, | LTEXT "Disconnect idle clients after (seconds):",IDC_STATIC,7, | ||||
25,138,15,SS_CENTERIMAGE | 25,138,15,SS_CENTERIMAGE | ||||
EDITTEXT IDC_IDLE_TIMEOUT,150,25,61,15,ES_AUTOHSCROLL | ES_NUMBER | 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 | GROUPBOX "Access Control",IDC_STATIC,7,55,204,135 | ||||
CONTROL "Only accept connections from the local machine", | CONTROL "Only accept connections from the local machine", | ||||
IDC_LOCALHOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15, | IDC_LOCALHOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15, |
include_directories(${CMAKE_BINARY_DIR}/win ${CMAKE_CURRENT_SOURCE_DIR}) | 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 | add_executable(winvnc4 WIN32 | ||||
buildTime.cxx | buildTime.cxx | ||||
ControlPanel.cxx | ControlPanel.cxx | ||||
JavaViewer.cxx | |||||
ManagedListener.cxx | ManagedListener.cxx | ||||
QueryConnectDialog.cxx | QueryConnectDialog.cxx | ||||
STrayIcon.cxx | STrayIcon.cxx | ||||
VNCServerService.cxx | VNCServerService.cxx | ||||
VNCServerWin32.cxx | VNCServerWin32.cxx | ||||
winvnc.cxx | winvnc.cxx | ||||
${CMAKE_CURRENT_BINARY_DIR}/winvnc.rc) | |||||
winvnc.rc) | |||||
target_link_libraries(winvnc4 rfb rfb_win32 network rdr ws2_32.lib) | 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 | install(TARGETS winvnc4 | ||||
RUNTIME DESTINATION ${BIN_DIR} | RUNTIME DESTINATION ${BIN_DIR} | ||||
) | ) |
/* 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; | |||||
} |
/* 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 | |||||
const TCHAR* winvnc::VNCServerWin32::RegConfigPath = _T("Software\\TigerVNC\\WinVNC4"); | 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", | static IntParameter port_number("PortNumber", | ||||
"TCP/IP port on which the server will accept connections", 5900); | "TCP/IP port on which the server will accept connections", 5900); | ||||
static StringParameter hosts("Hosts", | static StringParameter hosts("Hosts", | ||||
CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNC") : 0), | CreateEvent(0, FALSE, FALSE, "Global\\SessionEventTigerVNC") : 0), | ||||
vncServer(CStr(ComputerName().buf), &desktop), | vncServer(CStr(ComputerName().buf), &desktop), | ||||
thread_id(-1), runServer(false), isDesktopStarted(false), | 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) | queryConnectDialog(0) | ||||
{ | { | ||||
commandLock = new os::Mutex; | commandLock = new os::Mutex; | ||||
// -=- Make sure we're listening on the right ports. | // -=- Make sure we're listening on the right ports. | ||||
rfbSock.setServer(&vncServer); | rfbSock.setServer(&vncServer); | ||||
rfbSock.setPort(port_number, localHost); | 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. | // -=- Update the TCP address filter for both ports, if open. | ||||
CharArray pattern(hosts.getData()); | CharArray pattern(hosts.getData()); | ||||
rfbSock.setFilter(pattern.buf); | rfbSock.setFilter(pattern.buf); | ||||
httpSock.setFilter(pattern.buf); | |||||
// -=- Update the tray icon tooltip text with IP addresses | // -=- Update the tray icon tooltip text with IP addresses | ||||
processAddressChange(); | processAddressChange(); |
#include <rfb_win32/SocketManager.h> | #include <rfb_win32/SocketManager.h> | ||||
#include <rfb_win32/TCharArray.h> | #include <rfb_win32/TCharArray.h> | ||||
#include <winvnc/QueryConnectDialog.h> | #include <winvnc/QueryConnectDialog.h> | ||||
#include <winvnc/JavaViewer.h> | |||||
#include <winvnc/ManagedListener.h> | #include <winvnc/ManagedListener.h> | ||||
namespace os { | namespace os { | ||||
bool setClientsStatus(rfb::ListConnInfo* LCInfo); | bool setClientsStatus(rfb::ListConnInfo* LCInfo); | ||||
// Used by JavaViewerServer | |||||
const char* getName() {return vncServer.getName();} | |||||
rfb::Point getDesktopSize() {return desktop.getFbSize();} | |||||
protected: | protected: | ||||
// VNCServerST::QueryConnectionHandler interface | // VNCServerST::QueryConnectionHandler interface | ||||
// Callback used to prompt user to accept or reject a connection. | // Callback used to prompt user to accept or reject a connection. | ||||
DWORD thread_id; | DWORD thread_id; | ||||
bool runServer; | bool runServer; | ||||
bool isDesktopStarted; | bool isDesktopStarted; | ||||
JavaViewerServer httpServer; | |||||
rfb::win32::SocketManager sockMgr; | rfb::win32::SocketManager sockMgr; | ||||
rfb::win32::RegConfig config; | rfb::win32::RegConfig config; | ||||
ManagedListener rfbSock; | ManagedListener rfbSock; | ||||
ManagedListener httpSock; | |||||
STrayIconThread* trayIcon; | STrayIconThread* trayIcon; | ||||
QueryConnectDialog* queryConnectDialog; | QueryConnectDialog* queryConnectDialog; |
<!-- | |||||
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> |
#define IDD_DIALOG1 103 | #define IDD_DIALOG1 103 | ||||
#define IDD_ABOUT 104 | #define IDD_ABOUT 104 | ||||
#define IDI_CONNECTED 105 | #define IDI_CONNECTED 105 | ||||
#define IDR_VNCVIEWER_JAR 106 | |||||
#define IDD_QUERY_CONNECT 107 | #define IDD_QUERY_CONNECT 107 | ||||
#define IDD_ADD_NEW_CLIENT 108 | #define IDD_ADD_NEW_CLIENT 108 | ||||
#define IDB_BITMAP 109 | #define IDB_BITMAP 109 |
END | END | ||||
///////////////////////////////////////////////////////////////////////////// | |||||
// | |||||
// HTTPFILE | |||||
// | |||||
#cmakedefine BUILD_JAVA | |||||
#ifdef BUILD_JAVA | |||||
VNCVIEWER.JAR HTTPFILE DISCARDABLE "@VNCVIEWER_JAR_PATH@" | |||||
INDEX.VNC HTTPFILE DISCARDABLE "@INDEX_VNC_PATH@" | |||||
#endif | |||||
///////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////// | ||||
// | // | ||||
// 24 | // 24 |