--- /dev/null
+diff -Nru directvnc-0.7.5/src/caps.c directvnc-0.7.5.new/src/caps.c
+--- directvnc-0.7.5/src/caps.c 1970-01-01 01:00:00.000000000 +0100
++++ directvnc-0.7.5.new/src/caps.c 2007-01-15 14:48:51.000000000 +0100
+@@ -0,0 +1,246 @@
++/*
++ * Copyright (C) 2003 Constantin Kaplinsky. 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.
++ */
++
++/*
++ * caps.c
++ */
++
++#include "caps.h"
++#include "rfbproto.h"
++
++static int CapsIndex(CapsContainer *pcaps, CARD32 code);
++
++/*
++ * The constructor.
++ */
++
++CapsContainer *
++CapsNewContainer(void)
++{
++ CapsContainer *pcaps;
++
++ pcaps = malloc(sizeof(CapsContainer));
++ if (pcaps != NULL) {
++ pcaps->known_count = 0;
++ pcaps->enabled_count = 0;
++ }
++
++ return pcaps;
++}
++
++/*
++ * The destructor.
++ */
++
++void
++CapsDeleteContainer(CapsContainer *pcaps)
++{
++ int i;
++
++ for (i = 0; i < pcaps->known_count; i++) {
++ if (pcaps->descriptions[i] != NULL)
++ free(pcaps->descriptions[i]);
++ }
++
++ free(pcaps);
++}
++
++/*
++ * Add information about a particular capability into the object. There are
++ * two functions to perform this task. These functions overwrite capability
++ * records with the same code.
++ */
++
++void
++CapsAdd(CapsContainer *pcaps,
++ CARD32 code, char *vendor, char *name, char *desc)
++{
++ /* Fill in an rfbCapabilityInfo structure and pass it to CapsAddInfo(). */
++ rfbCapabilityInfo capinfo;
++ capinfo.code = code;
++ memcpy(capinfo.vendorSignature, vendor, sz_rfbCapabilityInfoVendor);
++ memcpy(capinfo.nameSignature, name, sz_rfbCapabilityInfoName);
++ CapsAddInfo(pcaps, &capinfo, desc);
++}
++
++void
++CapsAddInfo(CapsContainer *pcaps,
++ rfbCapabilityInfo *capinfo, char *desc)
++{
++ int i;
++ char *desc_copy;
++
++ i = CapsIndex(pcaps, capinfo->code);
++ if (i == -1) {
++ if (pcaps->known_count >= TIGHTVNC_MAX_CAPS) {
++ return; /* container full */
++ }
++ i = pcaps->known_count++;
++ pcaps->known_list[i] = capinfo->code;
++ pcaps->descriptions[i] = NULL;
++ }
++
++ pcaps->known_info[i] = *capinfo;
++ pcaps->enable_flags[i] = (char)0;
++ if (pcaps->descriptions[i] != NULL) {
++ free(pcaps->descriptions[i]);
++ }
++
++ desc_copy = NULL;
++ if (desc != NULL) {
++ desc_copy = strdup(desc);
++ }
++ pcaps->descriptions[i] = desc_copy;
++}
++
++/*
++ * Check if a capability with the specified code was added earlier.
++ */
++
++static int
++CapsIndex(CapsContainer *pcaps, CARD32 code)
++{
++ int i;
++
++ for (i = 0; i < pcaps->known_count; i++) {
++ if (pcaps->known_list[i] == code)
++ return i;
++ }
++
++ return -1;
++}
++
++int
++CapsIsKnown(CapsContainer *pcaps, CARD32 code)
++{
++ return (CapsIndex(pcaps, code) != -1);
++}
++
++/*
++ * Fill in a rfbCapabilityInfo structure with contents corresponding to the
++ * specified code. Returns True on success, False if the specified code is
++ * not known.
++ */
++
++int
++CapsGetInfo(CapsContainer *pcaps, CARD32 code, rfbCapabilityInfo *capinfo)
++{
++ int i;
++
++ i = CapsIndex(pcaps, code);
++ if (i != -1) {
++ *capinfo = pcaps->known_info[i];
++ return 1;
++ }
++
++ return 0;
++}
++
++/*
++ * Get a description string for the specified capability code. Returns NULL
++ * either if the code is not known, or if there is no description for this
++ * capability.
++ */
++
++char *
++CapsGetDescription(CapsContainer *pcaps, CARD32 code)
++{
++ int i;
++
++ i = CapsIndex(pcaps, code);
++ if (i != -1) {
++ return pcaps->descriptions[i];
++ }
++
++ return NULL;
++}
++
++/*
++ * Mark the specified capability as "enabled". This function checks "vendor"
++ * and "name" signatures in the existing record and in the argument structure
++ * and enables the capability only if both records are the same.
++ */
++
++int
++CapsEnable(CapsContainer *pcaps, rfbCapabilityInfo *capinfo)
++{
++ int i;
++ rfbCapabilityInfo *known;
++
++ i = CapsIndex(pcaps, capinfo->code);
++ if (i == -1)
++ return 0;
++
++ known = &pcaps->known_info[i];
++ if ( memcmp(known->vendorSignature, capinfo->vendorSignature,
++ sz_rfbCapabilityInfoVendor) != 0 ||
++ memcmp(known->nameSignature, capinfo->nameSignature,
++ sz_rfbCapabilityInfoName) != 0 ) {
++ pcaps->enable_flags[i] = (char)0;
++ return 0;
++ }
++
++ /* Cannot happen, but just in case. */
++ if (pcaps->enabled_count >= TIGHTVNC_MAX_CAPS) {
++ pcaps->enable_flags[i] = (char)0;
++ return 0;
++ }
++
++ pcaps->enable_flags[i] = (char)1;
++ pcaps->enabled_list[pcaps->enabled_count++] = capinfo->code;
++ return 1;
++}
++
++/*
++ * Check if the specified capability is known and enabled.
++ */
++
++int
++CapsIsEnabled(CapsContainer *pcaps, CARD32 code)
++{
++ int i;
++
++ i = CapsIndex(pcaps, code);
++ if (i != -1) {
++ return (pcaps->enable_flags[i] != (char)0);
++ }
++
++ return 0;
++}
++
++/*
++ * Return the number of enabled capabilities.
++ */
++
++int CapsNumEnabled(CapsContainer *pcaps)
++{
++ return pcaps->enabled_count;
++}
++
++/*
++ * Return the capability code at the specified index.
++ * If the index is not valid, return 0.
++ */
++
++CARD32
++CapsGetByOrder(CapsContainer *pcaps, int idx)
++{
++ return (idx < pcaps->enabled_count) ? pcaps->enabled_list[idx] : 0;
++}
++
+diff -Nru directvnc-0.7.5/src/caps.h directvnc-0.7.5.new/src/caps.h
+--- directvnc-0.7.5/src/caps.h 1970-01-01 01:00:00.000000000 +0100
++++ directvnc-0.7.5.new/src/caps.h 2007-01-15 14:46:50.000000000 +0100
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (C) 2003 Constantin Kaplinsky. 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.
++ */
++
++/*
++ * caps.h
++ */
++
++#ifndef _VNC_CAPSCONTAINER
++#define _VNC_CAPSCONTAINER
++
++#include "directvnc.h"
++/* FIXME: Don't limit the number of capabilities. */
++#define TIGHTVNC_MAX_CAPS 64
++
++typedef struct _CapsContainer
++{
++ int known_count;
++ CARD32 known_list[TIGHTVNC_MAX_CAPS];
++ rfbCapabilityInfo known_info[TIGHTVNC_MAX_CAPS];
++ char *descriptions[TIGHTVNC_MAX_CAPS];
++ char enable_flags[TIGHTVNC_MAX_CAPS];
++
++ /* These are redundant, but improve the performance. */
++ int enabled_count;
++ CARD32 enabled_list[TIGHTVNC_MAX_CAPS];
++
++} CapsContainer;
++
++CapsContainer *CapsNewContainer(void);
++void CapsDeleteContainer(CapsContainer *pcaps);
++
++void CapsAdd(CapsContainer *pcaps,
++ CARD32 code, char *vendor, char *name, char *desc);
++void CapsAddInfo(CapsContainer *pcaps,
++ rfbCapabilityInfo *capinfo, char *desc);
++
++int CapsIsKnown(CapsContainer *pcaps, CARD32 code);
++int CapsGetInfo(CapsContainer *pcaps, CARD32 code,
++ rfbCapabilityInfo *capinfo);
++char *CapsGetDescription(CapsContainer *pcaps, CARD32 code);
++
++int CapsEnable(CapsContainer *pcaps, rfbCapabilityInfo *capinfo);
++int CapsIsEnabled(CapsContainer *pcaps, CARD32 code);
++int CapsNumEnabled(CapsContainer *pcaps);
++CARD32 CapsGetByOrder(CapsContainer *pcaps, int idx);
++
++#endif /* _VNC_CAPSCONTAINER */
++
+diff -Nru directvnc-0.7.5/src/cursor.c directvnc-0.7.5.new/src/cursor.c
+--- directvnc-0.7.5/src/cursor.c 2003-01-26 19:47:54.000000000 +0100
++++ directvnc-0.7.5.new/src/cursor.c 2007-01-15 19:59:32.000000000 +0100
+@@ -31,6 +31,15 @@
+ #define True 1
+ #define False 0
+
++#define RGB24_TO_PIXEL(bpp,r,g,b) \
++ ((((CARD##bpp)(r) & 0xFF) * opt.client.redmax + 127) / 255 \
++ << opt.client.redshift | \
++ (((CARD##bpp)(g) & 0xFF) * opt.client.greenmax + 127) / 255 \
++ << opt.client.greenshift | \
++ (((CARD##bpp)(b) & 0xFF) * opt.client.bluemax + 127) / 255 \
++ << opt.client.blueshift)
++
++
+
+ /* Data kept for RichCursor encoding support. */
+ static Bool prevRichCursorSet = False;
+@@ -46,7 +55,6 @@
+ static void SoftCursorDraw(void);
+ static void FreeCursors(Bool setDotCursor);
+
+-
+ /*********************************************************************
+ * HandleRichCursor(). RichCursor shape updates support. This
+ * variation of cursor shape updates cannot be supported directly via
+@@ -54,13 +62,17 @@
+ * buffer (that is why we call it "software cursor").
+ ********************************************************************/
+
+-Bool HandleRichCursor(int xhot, int yhot, int width, int height)
++Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc)
+ {
++ int bytesPerPixel;
+ size_t bytesPerRow, bytesMaskData;
++ rfbXCursorColors rgb;
++ CARD32 colors[2];
+ char *buf;
+ CARD8 *ptr;
+ int x, y, b;
+
++ bytesPerPixel = opt.server.bpp / 8;
+ bytesPerRow = (width + 7) / 8;
+ bytesMaskData = bytesPerRow * height;
+
+@@ -75,11 +87,6 @@
+ if (rcSource == NULL)
+ return False;
+
+- if (!read_from_rfb_server(sock, (char *)rcSource,
+- width * height * (opt.client.bpp / 8))) {
+- free(rcSource);
+- return False;
+- }
+
+ /* Read and decode mask data. */
+
+@@ -89,6 +96,64 @@
+ return False;
+ }
+
++ /* Read and decode cursor pixel data, depending on the encoding type. */
++
++ if (enc == rfbEncodingXCursor) {
++
++ /* Read and convert background and foreground colors. */
++ if (!read_from_rfb_server(sock, (char *)&rgb, sz_rfbXCursorColors)) {
++ free(rcSource);
++ free(buf);
++ return False;
++ }
++ colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue);
++ colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue);
++
++ /* Read 1bpp pixel data into a temporary buffer. */
++ if (!read_from_rfb_server(sock, buf, bytesMaskData)) {
++ free(rcSource);
++ free(buf);
++ return False;
++ }
++
++ /* Convert 1bpp data to byte-wide color indices. */
++ ptr = rcSource;
++ for (y = 0; y < height; y++) {
++ for (x = 0; x < width / 8; x++) {
++ for (b = 7; b >= 0; b--) {
++ *ptr = buf[y * bytesPerRow + x] >> b & 1;
++ ptr += bytesPerPixel;
++ }
++ }
++ for (b = 7; b > 7 - width % 8; b--) {
++ *ptr = buf[y * bytesPerRow + x] >> b & 1;
++ ptr += bytesPerPixel;
++ }
++ }
++
++ /* Convert indices into the actual pixel values. */
++ switch (bytesPerPixel) {
++ case 1:
++ for (x = 0; x < width * height; x++)
++ rcSource[x] = (CARD8)colors[rcSource[x]];
++ break;
++ case 2:
++ for (x = 0; x < width * height; x++)
++ ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]];
++ break;
++ case 4:
++ for (x = 0; x < width * height; x++)
++ ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]];
++ break;
++ }
++ } else { /* rfbEncodingRichCursor */
++ if (!read_from_rfb_server(sock, (char *)rcSource,
++ width * height * (opt.client.bpp / 8))) {
++ free(rcSource);
++ return False;
++ }
++ }
++
+ if (!read_from_rfb_server(sock, buf, bytesMaskData)) {
+ free(rcSource);
+ free(buf);
+@@ -201,7 +266,8 @@
+ * SoftCursorUnlock() functions is called.
+ ********************************************************************/
+
+-void SoftCursorMove(int x, int y)
++void
++SoftCursorMove(int x, int y)
+ {
+ if (prevRichCursorSet && !rcCursorHidden) {
+ SoftCursorCopyArea(OPER_RESTORE);
+@@ -303,3 +369,20 @@
+ }
+ }
+
++/*********************************************************************
++ * HandleCursorPos(). Support for the PointerPos pseudo-encoding used
++ * to transmit changes in pointer position from server to clients.
++ * PointerPos encoding is used together with cursor shape updates.
++ ********************************************************************/
++
++int
++HandleCursorPos(int x, int y)
++{
++ if (x >= opt.server.width)
++ x = opt.server.width - 1;
++ if (y >= opt.server.height)
++ y = opt.server.height - 1;
++
++ SoftCursorMove(x, y);
++ return 1;
++}
+diff -Nru directvnc-0.7.5/src/directvnc.h directvnc-0.7.5.new/src/directvnc.h
+--- directvnc-0.7.5/src/directvnc.h 2007-01-15 22:06:18.000000000 +0100
++++ directvnc-0.7.5.new/src/directvnc.h 2007-01-15 20:02:12.000000000 +0100
+@@ -117,6 +117,7 @@
+ {
+ char *servername;
+ int port;
++ char *user;
+ char *password;
+ char *encodings;
+ struct serversettings server;
+@@ -142,6 +143,7 @@
+ int read_from_rfb_server(int sock, char *out, unsigned int n);
+ int write_exact(int sock, char *buf, unsigned int n);
+ int set_non_blocking(int sock);
++int SameMachine(int sock);
+
+ /* dfb.c */
+ void dfb_init(int argc, char *argv[]);
+@@ -157,12 +159,11 @@
+ void dfb_restore_cursor_rect( IDirectFBSurface *surf, int x, int y, int width, int heigth);
+
+ /* cursor.c */
+-int HandleRichCursor(int x, int y, int w, int h);
++int HandleCursorShape(int x, int y, int w, int h, CARD32 enc);
+ void SoftCursorLockArea(int x, int y, int w, int h);
+ void SoftCursorUnlockScreen(void);
+ void SoftCursorMove(int x, int y);
+
+-
+ /* macro for a safe call to DirectFB functions */
+ #define DFBCHECK(x...) \
+ { \
+@@ -174,5 +175,3 @@
+ }
+
+ #endif
+-
+-
+diff -Nru directvnc-0.7.5/src/Makefile.am directvnc-0.7.5.new/src/Makefile.am
+--- directvnc-0.7.5/src/Makefile.am 2003-01-31 10:20:35.000000000 +0100
++++ directvnc-0.7.5.new/src/Makefile.am 2007-01-15 14:07:50.000000000 +0100
+@@ -9,7 +9,7 @@
+ LIBOBJS = @LIBOBJS@
+
+ bin_PROGRAMS = directvnc
+-directvnc_SOURCES = main.c debug.h dfb.c directvnc.h sockets.c args.c\
++directvnc_SOURCES = caps.c caps.h main.c debug.h dfb.c directvnc.h sockets.c args.c\
+ rfb.c getopt.c getopt1.c getopt.h\
+ d3des.c d3des.h vncauth.c vncauth.h jpeg.c jpeg.h\
+ tight.c tight.h rfbproto.h keysym.h keysymdef.h \
+diff -Nru directvnc-0.7.5/src/rfb.c directvnc-0.7.5.new/src/rfb.c
+--- directvnc-0.7.5/src/rfb.c 2003-01-31 09:41:03.000000000 +0100
++++ directvnc-0.7.5.new/src/rfb.c 2007-01-15 21:49:58.000000000 +0100
+@@ -17,7 +17,8 @@
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+-
++#include <pwd.h>
++#include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <errno.h>
+@@ -28,15 +29,25 @@
+ #include <math.h>
+ #include <zlib.h>
+
++#include "caps.h"
+ #include "directvnc.h"
+ #include "tight.h"
+
++static void InitCapabilities(void);
++static int SetupTunneling(void);
++static int ReadSecurityType(void);
++static int SelectSecurityType(void);
++static int PerformAuthenticationTight(void);
++static int AuthenticateVNC(void);
++static int AuthenticateUnixLogin(void);
++static int ReadInteractionCaps(void);
++static int ReadCapabilityList(CapsContainer *caps, int count);
++
+ int _rfb_negotiate_protocol ();
+ int _rfb_authenticate ();
+ int _rfb_initialise_client ();
+ int _rfb_initialise_server ();
+
+-
+ static int _handle_raw_encoded_message(rfbFramebufferUpdateRectHeader rectheader);
+ static int _handle_copyrect_encoded_message(rfbFramebufferUpdateRectHeader rectheader);
+ static int _handle_rre_encoded_message(rfbFramebufferUpdateRectHeader rectheader);
+@@ -44,6 +55,63 @@
+ static int _handle_hextile_encoded_message(rfbFramebufferUpdateRectHeader rectheader);
+ static int _handle_richcursor_message(rfbFramebufferUpdateRectHeader rectheader);
+
++static int tightVncProtocol = 0;
++static CapsContainer *tunnelCaps; /* known tunneling/encryption methods */
++static CapsContainer *authCaps; /* known authentication schemes */
++static CapsContainer *serverMsgCaps; /* known non-standard server messages */
++static CapsContainer *clientMsgCaps; /* known non-standard client messages */
++static CapsContainer *encodingCaps; /* known encodings besides Raw */
++static int tunnelSpecified = 0;
++
++/*
++ * InitCapabilities.
++ */
++
++static void
++InitCapabilities(void)
++{
++ tunnelCaps = CapsNewContainer();
++ authCaps = CapsNewContainer();
++ serverMsgCaps = CapsNewContainer();
++ clientMsgCaps = CapsNewContainer();
++ encodingCaps = CapsNewContainer();
++
++ /* Supported authentication methods */
++ CapsAdd(authCaps, rfbAuthVNC, rfbStandardVendor, sig_rfbAuthVNC,
++ "Standard VNC password authentication");
++ CapsAdd(authCaps, rfbAuthUnixLogin, rfbTightVncVendor, sig_rfbAuthUnixLogin,
++ "Login-style Unix authentication");
++
++ /* Supported encoding types */
++ CapsAdd(encodingCaps, rfbEncodingCopyRect, rfbStandardVendor,
++ sig_rfbEncodingCopyRect, "Standard CopyRect encoding");
++ CapsAdd(encodingCaps, rfbEncodingRRE, rfbStandardVendor,
++ sig_rfbEncodingRRE, "Standard RRE encoding");
++ CapsAdd(encodingCaps, rfbEncodingCoRRE, rfbStandardVendor,
++ sig_rfbEncodingCoRRE, "Standard CoRRE encoding");
++ CapsAdd(encodingCaps, rfbEncodingHextile, rfbStandardVendor,
++ sig_rfbEncodingHextile, "Standard Hextile encoding");
++ CapsAdd(encodingCaps, rfbEncodingZlib, rfbTridiaVncVendor,
++ sig_rfbEncodingZlib, "Zlib encoding from TridiaVNC");
++ CapsAdd(encodingCaps, rfbEncodingTight, rfbTightVncVendor,
++ sig_rfbEncodingTight, "Tight encoding by Constantin Kaplinsky");
++
++ /* Supported "fake" encoding types */
++ CapsAdd(encodingCaps, rfbEncodingCompressLevel0, rfbTightVncVendor,
++ sig_rfbEncodingCompressLevel0, "Compression level");
++ CapsAdd(encodingCaps, rfbEncodingQualityLevel0, rfbTightVncVendor,
++ sig_rfbEncodingQualityLevel0, "JPEG quality level");
++ CapsAdd(encodingCaps, rfbEncodingXCursor, rfbTightVncVendor,
++ sig_rfbEncodingXCursor, "X-style cursor shape update");
++ CapsAdd(encodingCaps, rfbEncodingRichCursor, rfbTightVncVendor,
++ sig_rfbEncodingRichCursor, "Rich-color cursor shape update");
++ CapsAdd(encodingCaps, rfbEncodingPointerPos, rfbTightVncVendor,
++ sig_rfbEncodingPointerPos, "Pointer position update");
++ CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor,
++ sig_rfbEncodingLastRect, "LastRect protocol extension");
++}
++
++
+ /*
+ * ConnectToRFBServer.
+ */
+@@ -100,89 +168,393 @@
+ int
+ rfb_initialise_connection ()
+ {
+- if (!_rfb_negotiate_protocol()) return 0;
+- if (!_rfb_authenticate()) return 0;
+- if (!_rfb_initialise_client()) return 0;
+- if (!_rfb_initialise_server()) return 0;
+-
+- return(1);
++ if (!_rfb_negotiate_protocol()) return 0;
++ if (!_rfb_initialise_client()) return 0;
++ if (!_rfb_initialise_server()) return 0;
++ return 1;
+ }
+
+ int
+ _rfb_negotiate_protocol()
+ {
+ rfbProtocolVersionMsg msg;
++ int server_major, server_minor;
++ int viewer_major, viewer_minor;
++ int secType;
+
+ /* read the protocol version the server uses */
+ if (!read_from_rfb_server(sock, (char*)&msg, sz_rfbProtocolVersionMsg))
+ return 0;
+- /* FIXME actually do something with that information ;) */
+
++ msg[sz_rfbProtocolVersionMsg] = 0;
++
++ if (sscanf(msg, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) {
++ return 0;
++ }
++ viewer_major = rfbProtocolMajorVersion;
++ if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
++ /* the server supports at least the standard protocol 3.7 */
++ viewer_minor = rfbProtocolMinorVersion;
++ } else {
++ /* any other server version, request the standard 3.3 */
++ viewer_minor = rfbProtocolFallbackMinorVersion;
++ }
+ /* send the protocol version we want to use */
+- sprintf(msg, rfbProtocolVersionFormat,
+- rfbProtocolMajorVersion,
+- rfbProtocolMinorVersion);
++ sprintf(msg, rfbProtocolVersionFormat,
++ viewer_major,
++ viewer_minor);
+ if (!write_exact (sock, msg, sz_rfbProtocolVersionMsg))
+ return 0;
+
+- return 1;
++ /* Read or select the security type. */
++ if (viewer_minor == rfbProtocolMinorVersion) {
++ secType = SelectSecurityType();
++ } else {
++ secType = ReadSecurityType();
++ }
++ if (secType == rfbConnFailed)
++ return 0;
++
++ return _rfb_authenticate(secType);
+ }
+
++static int
++ReadSecurityType(void)
++{
++ CARD32 secType;
++ if (!read_from_rfb_server(sock, (char *)&secType, sizeof(secType))) {
++ return rfbConnFailed;
++ }
++ return Swap32IfLE(secType);
++}
+
+-int
+-_rfb_authenticate()
++static int
++SelectSecurityType(void)
+ {
+- CARD32 authscheme;
+-
+- read_from_rfb_server(sock, (char *)&authscheme, 4);
+- authscheme = Swap32IfLE(authscheme);
+- switch (authscheme)
+- {
+- CARD32 reason_length;
+- CARD8 *reason_string;
+- CARD8 challenge_and_response[CHALLENGESIZE];
+- CARD32 auth_result;
+-
+- case rfbConnFailed:
+- fprintf(stderr, "DIRECTVNC: Connection to VNC server failed\n");
+- read_from_rfb_server(sock, (char *)&reason_length, 4);
+- reason_length = Swap32IfLE(reason_length);
+- reason_string = malloc(sizeof(CARD8) * reason_length);
+- read_from_rfb_server(sock, (char *)reason_string, reason_length);
+- fprintf(stderr, "Errormessage: %s\n", reason_string);
+- return (0);
+- case rfbVncAuth:
++ CARD8 nSecTypes;
++ char *secTypeNames[] = {"None", "VncAuth"};
++ CARD8 knownSecTypes[] = {rfbNoAuth, rfbVncAuth};
++ int nKnownSecTypes = sizeof(knownSecTypes);
++ CARD8 *secTypes;
++ CARD8 secType = rfbConnFailed;
++ int i, j;
++
++ /* Read the list of security types. */
++ if (!read_from_rfb_server(sock, (char *)&nSecTypes, sizeof(nSecTypes)))
++ return rfbConnFailed;
++ if (nSecTypes == 0) {
++ return rfbConnFailed;
++ }
++
++ secTypes = malloc(nSecTypes);
++ if (!read_from_rfb_server(sock, (char *)secTypes, nSecTypes))
++ return rfbConnFailed;
++
++ /* Find out if the server supports TightVNC protocol extensions */
++ for (j = 0; j < (int)nSecTypes; j++) {
++ if (secTypes[j] == rfbSecTypeTight) {
++ free(secTypes);
++ secType = rfbSecTypeTight;
++ if (!write_exact(sock, (char *)&secType, sizeof(secType)))
++ return rfbConnFailed;
++ fprintf(stderr, "Enabling TightVNC protocol extensions\n");
++ return rfbSecTypeTight;
++ }
++ }
++ /* Find first supported security type */
++ for (j = 0; j < (int)nSecTypes; j++) {
++ for (i = 0; i < nKnownSecTypes; i++) {
++ if (secTypes[j] == knownSecTypes[i]) {
++ secType = secTypes[j];
++ if (!write_exact(sock, (char *)&secType, sizeof(secType))) {
++ free(secTypes);
++ return rfbConnFailed;
++ }
++ break;
++ }
++ }
++ if (secType != rfbConnFailed) break;
++ }
++ free(secTypes);
++ if (secType == rfbConnFailed)
++ fprintf(stderr, "Server did not offer supported security type\n");
++ return (int)secType;
+
+- /* we didnt get a password on the command line, so go get one */
+- if (!opt.password) opt.password = getpass("Password: ");
++}
+
+- if (!read_from_rfb_server(sock, challenge_and_response, CHALLENGESIZE))
+- return 0;
+- vncEncryptBytes(challenge_and_response, opt.password);
+- if (!write_exact(sock, challenge_and_response, CHALLENGESIZE))
+- return 0;
+- if (!read_from_rfb_server(sock, (char*)&auth_result, 4))
++/*
++ * Standard VNC authentication.
++ */
++
++static int
++AuthenticateVNC(void)
++{
++ CARD32 authScheme, auth_result;
++ CARD8 challenge[CHALLENGESIZE];
++ char *passwd;
++ char buffer[64];
++ char* cstatus;
++ int len;
++
++ fprintf(stderr, "Performing standard VNC authentication\n");
++
++ if (!read_from_rfb_server(sock, (char *)challenge, CHALLENGESIZE))
++ return 0;
++
++
++ /* we get a password on the command line, so go get one */
++ if (!opt.password) opt.password = getpass("Password: ");
++ if (strlen(opt.password) > 8) {
++ opt.password[8] = '\0';
++ }
++
++ vncEncryptBytes(challenge, opt.password);
++ /* Lose the password from memory */
++ memset(opt.password, '\0', strlen(opt.password));
++
++ if (!write_exact(sock, challenge, CHALLENGESIZE))
++ return 0;
++ if (!read_from_rfb_server(sock, (char*)&auth_result, 4))
+ return 0;
+- auth_result = Swap32IfLE(auth_result);
+- switch (auth_result)
+- {
+- case rfbVncAuthFailed:
+- fprintf(stderr, "Authentication Failed\n");
+- return (0);
+- case rfbVncAuthTooMany:
+- fprintf(stderr, "Too many connections\n");
+- return (0);
+- case rfbVncAuthOK:
+- fprintf(stderr, "Authentication OK\n");
+- break;
+- }
+- break;
+- case rfbNoAuth:
+- break;
++ auth_result = Swap32IfLE(auth_result);
++ switch (auth_result) {
++ case rfbVncAuthFailed:
++ fprintf(stderr, "Authentication Failed\n");
++ return 0;
++ case rfbVncAuthTooMany:
++ fprintf(stderr, "Too many connections\n");
++ return 0;
++ case rfbVncAuthOK:
++ fprintf(stderr, "Authentication OK\n");
++ break;
++ }
++ return 1;
++}
++
++
++/*
++ * Read the list of rfbCapabilityInfo structures and enable corresponding
++ * capabilities in the specified container. The count argument specifies how
++ * many records to read from the socket.
++ */
++
++static int
++ReadCapabilityList(CapsContainer *caps, int count)
++{
++ rfbCapabilityInfo msginfo;
++ int i;
++
++ for (i = 0; i < count; i++) {
++ if (!read_from_rfb_server(sock, (char *)&msginfo, sz_rfbCapabilityInfo))
++ return 0;
++ msginfo.code = Swap32IfLE(msginfo.code);
++ CapsEnable(caps, &msginfo);
++ }
++
++ return 1;
++}
++
++/*
++ * Unix login-style authentication.
++ */
++
++static int
++AuthenticateUnixLogin(void)
++{
++ CARD32 loginLen, passwdLen, authResult;
++ char *login;
++ char *passwd;
++ struct passwd *ps;
++
++ fprintf(stderr, "Performing Unix login-style authentication\n");
++
++ if (opt.user) {
++ login = opt.user;
++ } else {
++ ps = getpwuid(getuid());
++ login = ps->pw_name;
++ }
++
++ fprintf(stderr, "Using user name \"%s\"\n", login);
++
++ passwd = getpass("Password: ");
++
++ if (!passwd || strlen(passwd) == 0) {
++ fprintf(stderr, "Reading password failed\n");
++ return 0;
++ }
++
++ loginLen = Swap32IfLE((CARD32)strlen(login));
++ passwdLen = Swap32IfLE((CARD32)strlen(passwd));
++
++ if (!write_exact(sock, (char *)&loginLen, sizeof(loginLen)) ||
++ !write_exact(sock, (char *)&passwdLen, sizeof(passwdLen)))
++ return 0;
++
++ if (!write_exact(sock, login, strlen(login)) ||
++ !write_exact(sock, passwd, strlen(passwd)))
++ return 0;
++
++ /* Lose the password from memory */
++ memset(passwd, '\0', strlen(passwd));
++
++ if (!read_from_rfb_server(sock, (char *)&authResult, sizeof(authResult)))
++ return 0;
++
++ authResult = Swap32IfLE(authResult);
++
++ switch (authResult) {
++ case rfbVncAuthOK:
++ fprintf(stderr, "Authentication succeeded\n");
++ break;
++ case rfbVncAuthFailed:
++ fprintf(stderr, "Authentication failed\n");
++ return 0;
++ case rfbVncAuthTooMany:
++ fprintf(stderr, "Authentication failed - too many tries\n");
++ return 0;
++ default:
++ fprintf(stderr, "Unknown authentication result: %d\n",
++ (int)authResult);
++ return 0;
++ }
++
++ return 1;
++}
++
++
++int
++_rfb_authenticate(CARD32 authscheme)
++{
++ switch (authscheme) {
++ CARD32 reason_length;
++ CARD8 *reason_string;
++ CARD8 challenge_and_response[CHALLENGESIZE];
++ CARD32 auth_result;
++
++ case rfbConnFailed:
++ fprintf(stderr, "DIRECTVNC: Connection to VNC server failed\n");
++ read_from_rfb_server(sock, (char *)&reason_length, 4);
++ reason_length = Swap32IfLE(reason_length);
++ reason_string = malloc(sizeof(CARD8) * reason_length);
++ read_from_rfb_server(sock, (char *)reason_string, reason_length);
++ fprintf(stderr, "Errormessage: %s\n", reason_string);
++ return 0;
++ case rfbVncAuth:
++ return AuthenticateVNC();
++ case rfbNoAuth:
++ break;
++ case rfbSecTypeTight:
++ tightVncProtocol = 1;
++ InitCapabilities();
++ if (!SetupTunneling()) return 0;
++ if (!PerformAuthenticationTight()) return 0;
++ break;
++ default:
++ fprintf(stderr, "Internal error: Invalid security type\n");
++ return 0;
+ }
+ return 1;
+ }
+
++static int
++SetupTunneling(void)
++{
++ rfbTunnelingCapsMsg caps;
++ CARD32 tunnelType;
++
++ /* In the protocol version 3.7t, the server informs us about
++ supported tunneling methods. Here we read this information. */
++
++ if (!read_from_rfb_server(sock, (char *)&caps, sz_rfbTunnelingCapsMsg)) return 0;
++ caps.nTunnelTypes = Swap32IfLE(caps.nTunnelTypes);
++
++ if (caps.nTunnelTypes) {
++ if (!ReadCapabilityList(tunnelCaps, caps.nTunnelTypes)) return 0;
++
++ /* We cannot do tunneling anyway yet. */
++ tunnelType = Swap32IfLE(rfbNoTunneling);
++ if (!write_exact(sock, (char *)&tunnelType, sizeof(tunnelType))) return 0;
++ }
++ return 1;
++}
++
++/* Negotiate authentication scheme (protocol version 3.7t) */
++static int
++PerformAuthenticationTight(void)
++{
++ rfbAuthenticationCapsMsg caps;
++ CARD32 authScheme;
++ int i;
++
++ /* In the protocol version 3.7t, the server informs us about supported
++ authentication schemes. Here we read this infomation. */
++
++ if (!read_from_rfb_server(sock, (char *)&caps, sz_rfbAuthenticationCapsMsg)) return 0;
++
++ caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
++
++ if (!caps.nAuthTypes) {
++ fprintf(stderr, "No authentication needed\n");
++ return 1;
++ }
++
++ if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) return 0;
++
++ /* Prefer Unix login authentication if a user name was given. */
++ if (opt.user && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
++ authScheme = Swap32IfLE(rfbAuthUnixLogin);
++ if (!write_exact(sock, (char *)&authScheme, sizeof(authScheme))) return 0;
++ return AuthenticateUnixLogin();
++ }
++
++ /* Otherwise, try server's preferred authentication scheme. */
++ for (i = 0; i < CapsNumEnabled(authCaps); i++) {
++ authScheme = CapsGetByOrder(authCaps, i);
++ if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) continue; /* unknown scheme - cannot use it */
++ authScheme = Swap32IfLE(authScheme);
++ if (!write_exact(sock, (char *)&authScheme, sizeof(authScheme))) return 0;
++ authScheme = Swap32IfLE(authScheme); /* convert it back */
++
++ if (authScheme == rfbAuthUnixLogin) {
++ return AuthenticateUnixLogin();
++ } else if (authScheme == rfbAuthVNC) {
++ return AuthenticateVNC();
++ } else {
++ fprintf(stderr, "Should never happen\n");
++ /* Should never happen. */
++ return 0;
++ }
++ }
++
++ fprintf(stderr, "No suitable authentication schemes offered by server\n");
++ return 0;
++}
++
++/*
++ * In the protocol version 3.7t, the server informs us about supported
++ * protocol messages and encodings. Here we read this information.
++ */
++
++static int
++ReadInteractionCaps(void)
++{
++ rfbInteractionCapsMsg intr_caps;
++
++ /* Read the counts of list items following */
++ if (!read_from_rfb_server(sock, (char *)&intr_caps, sz_rfbInteractionCapsMsg))
++ return 0;
++ intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
++ intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
++ intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
++
++ /* Read the lists of server- and client-initiated messages */
++ return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
++ ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
++ ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
++}
++
++
+ int
+ _rfb_initialise_client()
+ {
+@@ -220,10 +592,166 @@
+
+ if (!read_from_rfb_server(sock, opt.server.name, len))
+ return 0;
+-
++ if (tightVncProtocol) {
++ /* Read interaction capabilities (protocol 3.7t) */
++ if (!ReadInteractionCaps())
++ return 0;
++ }
+ return 1;
+ }
+
++/*
++ * SetFormatAndEncodings.
++ */
++
++int
++rfb_set_format_and_encodings()
++{
++ rfbSetPixelFormatMsg spf;
++ char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
++ rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
++ CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]);
++ int len = 0;
++ int requestCompressLevel = 0;
++ int requestQualityLevel = 0;
++ int requestLastRectEncoding = 0;
++
++ spf.type = 0;
++ spf.format.bitsPerPixel = opt.client.bpp;
++ spf.format.depth = opt.client.depth;
++ spf.format.bigEndian = opt.client.bigendian;
++ spf.format.trueColour = opt.client.truecolour;
++ spf.format.redMax = Swap16IfLE(opt.client.redmax);
++ spf.format.greenMax = Swap16IfLE(opt.client.greenmax);
++ spf.format.blueMax = Swap16IfLE(opt.client.bluemax);
++ spf.format.redShift =opt.client.redshift;
++ spf.format.greenShift = opt.client.greenshift;
++ spf.format.blueShift = opt.client.blueshift;
++
++ if (!write_exact(sock, (char *)&spf, sz_rfbSetPixelFormatMsg))
++ return 0;
++
++ se->type = rfbSetEncodings;
++ se->nEncodings = 0;
++
++ if (opt.encodings) {
++ char *encStr = opt.encodings;
++ int encStrLen;
++ do {
++ char *nextEncStr = strchr(encStr, ' ');
++ if (nextEncStr) {
++ encStrLen = nextEncStr - encStr;
++ nextEncStr++;
++ } else {
++ encStrLen = strlen(encStr);
++ }
++
++ if (strncasecmp(encStr,"raw",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
++ } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
++ } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
++ requestLastRectEncoding = 1;
++ if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9)
++ requestCompressLevel = 1;
++ requestQualityLevel = 1;
++ } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
++ } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
++ if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9)
++ requestCompressLevel = 1;
++ } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
++ } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
++ } else {
++ fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr);
++ }
++
++ encStr = nextEncStr;
++ } while (encStr && se->nEncodings < MAX_ENCODINGS);
++
++ if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
++ encs[se->nEncodings++] = Swap32IfLE(opt.client.compresslevel +
++ rfbEncodingCompressLevel0);
++ }
++
++ if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
++ if (opt.client.quality < 0 || opt.client.quality > 9)
++ opt.client.quality = 5;
++ encs[se->nEncodings++] = Swap32IfLE(opt.client.quality +
++ rfbEncodingQualityLevel0);
++ }
++
++ if (opt.localcursor) {
++ if (se->nEncodings < MAX_ENCODINGS)
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
++ if (se->nEncodings < MAX_ENCODINGS)
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
++ if (se->nEncodings < MAX_ENCODINGS)
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
++ }
++
++ if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
++ }
++ } else {
++ if (SameMachine(sock)) {
++ if (!tunnelSpecified) {
++ fprintf(stderr,"Same machine: preferring raw encoding\n");
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
++ } else {
++ fprintf(stderr,"Tunneling active: preferring tight encoding\n");
++ }
++ }
++
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
++
++ if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9) {
++ encs[se->nEncodings++] = Swap32IfLE(opt.client.compresslevel +
++ rfbEncodingCompressLevel0);
++ } else if (!tunnelSpecified) {
++ /* If -tunnel option was provided, we assume that server machine is
++ not in the local network so we use default compression level for
++ tight encoding instead of fast compression. Thus we are
++ requesting level 1 compression only if tunneling is not used. */
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1);
++ }
++#if 0
++ if (appData.enableJPEG) {
++ if (appData.qualityLevel < 0 || appData.qualityLevel > 9)
++ appData.qualityLevel = 5;
++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel +
++ rfbEncodingQualityLevel0);
++ }
++#endif
++
++ if (opt.localcursor) {
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
++ }
++
++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
++ }
++
++ len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
++
++ se->nEncodings = Swap16IfLE(se->nEncodings);
++
++ if (!write_exact(sock, buf, len)) return 0;
++
++ return 1;
++}
++
++#if 0
+ int
+ rfb_set_format_and_encodings()
+ {
+@@ -312,7 +840,7 @@
+
+ return(1);
+ }
+-
++#endif
+
+ int
+ rfb_send_update_request(int incremental)
+@@ -347,84 +875,93 @@
+ rfbFramebufferUpdateRectHeader rectheader;
+
+ if (!read_from_rfb_server(sock, (char*)&msg, 1)) return 0;
+- switch (msg.type)
+- {
+- int i;
+- case rfbFramebufferUpdate:
+- read_from_rfb_server(sock, ((char*)&msg.fu)+1, sz_rfbFramebufferUpdateMsg-1);
+- msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
+- for (i=0;i< msg.fu.nRects;i++)
+- {
+- read_from_rfb_server(sock, (char*)&rectheader,
+- sz_rfbFramebufferUpdateRectHeader);
+- rectheader.r.x = Swap16IfLE(rectheader.r.x);
+- rectheader.r.y = Swap16IfLE(rectheader.r.y);
+- rectheader.r.w = Swap16IfLE(rectheader.r.w);
+- rectheader.r.h = Swap16IfLE(rectheader.r.h);
+- rectheader.encoding = Swap32IfLE(rectheader.encoding);
+- SoftCursorLockArea(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h);
+- switch (rectheader.encoding)
+- {
+- case rfbEncodingRaw:
+- _handle_raw_encoded_message(rectheader);
+- break;
+- case rfbEncodingCopyRect:
+- _handle_copyrect_encoded_message(rectheader);
+- break;
+- case rfbEncodingRRE:
+- _handle_rre_encoded_message(rectheader);
+- break;
+- case rfbEncodingCoRRE:
+- _handle_corre_encoded_message(rectheader);
+- break;
+- case rfbEncodingHextile:
+- _handle_hextile_encoded_message(rectheader);
+- break;
+- case rfbEncodingTight:
+- _handle_tight_encoded_message(rectheader);
+- break;
+- case rfbEncodingZlib:
+- _handle_zlib_encoded_message(rectheader);
+- break;
+- case rfbEncodingRichCursor:
+- _handle_richcursor_message(rectheader);
+- break;
++ switch (msg.type) {
++ int i;
++ case rfbFramebufferUpdate:
++ read_from_rfb_server(sock, ((char*)&msg.fu)+1, sz_rfbFramebufferUpdateMsg-1);
++ msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
++
++ for (i=0;i< msg.fu.nRects;i++) {
++ read_from_rfb_server(sock, (char*)&rectheader, sz_rfbFramebufferUpdateRectHeader);
++ rectheader.r.x = Swap16IfLE(rectheader.r.x);
++ rectheader.r.y = Swap16IfLE(rectheader.r.y);
++ rectheader.r.w = Swap16IfLE(rectheader.r.w);
++ rectheader.r.h = Swap16IfLE(rectheader.r.h);
++ rectheader.encoding = Swap32IfLE(rectheader.encoding);
++ if (rectheader.encoding == rfbEncodingLastRect) break;
++
++ if (rectheader.encoding == rfbEncodingPointerPos) {
++ if (!HandleCursorPos(rectheader.r.x, rectheader.r.y)) {
++ return 0;
++ }
++ continue;
++ }
++ SoftCursorLockArea(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h);
++
++ switch (rectheader.encoding) {
++ case rfbEncodingRaw:
++ _handle_raw_encoded_message(rectheader);
++ break;
++ case rfbEncodingCopyRect:
++ _handle_copyrect_encoded_message(rectheader);
++ break;
++ case rfbEncodingRRE:
++ _handle_rre_encoded_message(rectheader);
++ break;
++ case rfbEncodingCoRRE:
++ _handle_corre_encoded_message(rectheader);
++ break;
++ case rfbEncodingHextile:
++ _handle_hextile_encoded_message(rectheader);
++ break;
++ case rfbEncodingTight:
++ _handle_tight_encoded_message(rectheader);
++ break;
++ case rfbEncodingZlib:
++ _handle_zlib_encoded_message(rectheader);
++ break;
++ case rfbEncodingRichCursor:
++ case rfbEncodingXCursor:
++ _handle_richcursor_message(rectheader);
++ break;
++#if 0
+ case rfbEncodingLastRect:
+- printf("LAST\n");
++ fprintf(stderr, "LAST\n");
+ break;
+-
+- default:
+- printf("Unknown encoding\n");
+- return 0;
+- break;
+- }
+- /* Now we may discard "soft cursor locks". */
+- SoftCursorUnlockScreen();
++#endif
++ default:
++ fprintf(stderr, "Unknown encoding: %x\n", rectheader.encoding);
++ return 0;
++ break;
++ }
++ /* Now we may discard "soft cursor locks". */
++ SoftCursorUnlockScreen();
++ }
++ if (!rfb_send_update_request(1)) return 0;
+
+- }
+- break;
+- case rfbSetColourMapEntries:
+- fprintf(stderr, "SetColourMapEntries\n");
+- read_from_rfb_server(sock, ((char*)&msg.scme)+1, sz_rfbSetColourMapEntriesMsg-1);
+- break;
+- case rfbBell:
+- fprintf(stderr, "Bell message. Unimplemented.\n");
+- break;
+- case rfbServerCutText:
+- fprintf(stderr, "ServerCutText. Unimplemented.\n");
+- read_from_rfb_server(sock, ((char*)&msg.sct)+1,
+- sz_rfbServerCutTextMsg-1);
+- size = Swap32IfLE(msg.sct.length);
+- buf = malloc(sizeof(char) * size);
+- read_from_rfb_server(sock, buf, size);
+- buf[size]=0;
+- printf("%s\n", buf);
+- free(buf);
+- break;
+- default:
+- printf("Unknown server message. Type: %i\n", msg.type);
+- return 0;
+- break;
++ break;
++
++ case rfbSetColourMapEntries:
++ fprintf(stderr, "SetColourMapEntries\n");
++ read_from_rfb_server(sock, ((char*)&msg.scme)+1, sz_rfbSetColourMapEntriesMsg-1);
++ break;
++ case rfbBell:
++ fprintf(stderr, "Bell message. Unimplemented.\n");
++ break;
++ case rfbServerCutText:
++ fprintf(stderr, "ServerCutText. Unimplemented.\n");
++ read_from_rfb_server(sock, ((char*)&msg.sct)+1, sz_rfbServerCutTextMsg-1);
++ size = Swap32IfLE(msg.sct.length);
++ buf = malloc(sizeof(char) * size);
++ read_from_rfb_server(sock, buf, size);
++ buf[size]=0;
++ printf("%s\n", buf);
++ free(buf);
++ break;
++ default:
++ printf("Unknown server message. Type: %i\n", msg.type);
++ return 0;
++ break;
+ }
+ return(1);
+ }
+@@ -688,7 +1225,7 @@
+ static int
+ _handle_richcursor_message(rfbFramebufferUpdateRectHeader rectheader)
+ {
+- return HandleRichCursor(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h);
++ return HandleCursorShape(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h, rectheader.encoding);
+ }
+
+ void
+diff -Nru directvnc-0.7.5/src/rfbproto.h directvnc-0.7.5.new/src/rfbproto.h
+--- directvnc-0.7.5/src/rfbproto.h 2002-07-07 18:50:02.000000000 +0200
++++ directvnc-0.7.5.new/src/rfbproto.h 2007-01-15 16:42:12.000000000 +0100
+@@ -1,3 +1,5 @@
++#ifndef VNC_RFBPROTO_H
++#define VNC_RFBPROTO_H
+ /*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+@@ -20,7 +22,7 @@
+ */
+
+ /*
+- * rfbproto.h - header file for the RFB protocol version 3.3
++ * rfbproto.h - header file for the RFB protocol version 3.7
+ *
+ * Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
+ * integer (for n = 8, 16 and 32).
+@@ -155,7 +157,8 @@
+
+ #define rfbProtocolVersionFormat "RFB %03d.%03d\n"
+ #define rfbProtocolMajorVersion 3
+-#define rfbProtocolMinorVersion 3
++#define rfbProtocolMinorVersion 7
++#define rfbProtocolFallbackMinorVersion 3
+
+ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
+
+@@ -163,6 +166,31 @@
+
+
+ /*-----------------------------------------------------------------------------
++ * Structure used to describe protocol options such as tunneling methods,
++ * authentication schemes and message types (protocol version 3.7t).
++ */
++
++typedef struct _rfbCapabilityInfo {
++
++ CARD32 code; /* numeric identifier */
++ CARD8 vendorSignature[4]; /* vendor identification */
++ CARD8 nameSignature[8]; /* abbreviated option name */
++
++} rfbCapabilityInfo;
++
++#define sz_rfbCapabilityInfoVendor 4
++#define sz_rfbCapabilityInfoName 8
++#define sz_rfbCapabilityInfo 16
++
++/*
++ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
++ */
++
++#define rfbStandardVendor "STDV"
++#define rfbTridiaVncVendor "TRDV"
++#define rfbTightVncVendor "TGHT"
++
++/*-----------------------------------------------------------------------------
+ * Authentication
+ *
+ * Once the protocol version has been decided, the server then sends a 32-bit
+@@ -174,6 +202,7 @@
+ #define rfbConnFailed 0
+ #define rfbNoAuth 1
+ #define rfbVncAuth 2
++#define rfbSecTypeTight 16
+
+ /*
+ * rfbConnFailed: For some reason the connection failed (e.g. the server
+@@ -201,6 +230,160 @@
+ #define rfbVncAuthFailed 1
+ #define rfbVncAuthTooMany 2
+
++/*-----------------------------------------------------------------------------
++ * Negotiation of Tunneling Capabilities (protocol version 3.7t)
++ *
++ * If the chosen security type is rfbSecTypeTight, the server sends a list of
++ * supported tunneling methods ("tunneling" refers to any additional layer of
++ * data transformation, such as encryption or external compression.)
++ *
++ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures
++ * that list all supported tunneling methods in the order of preference.
++ *
++ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be
++ * used, and the client should not send a response requesting a tunneling
++ * method.
++ */
++
++typedef struct _rfbTunnelingCapsMsg {
++ CARD32 nTunnelTypes;
++ /* followed by nTunnelTypes * rfbCapabilityInfo structures */
++} rfbTunnelingCapsMsg;
++
++#define sz_rfbTunnelingCapsMsg 4
++
++/*-----------------------------------------------------------------------------
++ * Tunneling Method Request (protocol version 3.7t)
++ *
++ * If the list of tunneling capabilities sent by the server was not empty, the
++ * client should reply with a 32-bit code specifying a particular tunneling
++ * method. The following code should be used for no tunneling.
++ */
++
++#define rfbNoTunneling 0
++#define sig_rfbNoTunneling "NOTUNNEL"
++
++/*-----------------------------------------------------------------------------
++ * Negotiation of Authentication Capabilities (protocol version 3.7t)
++ *
++ * After setting up tunneling, the server sends a list of supported
++ * authentication schemes.
++ *
++ * nAuthTypes specifies the number of following rfbCapabilityInfo structures
++ * that list all supported authentication schemes in the order of preference.
++ *
++ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is
++ * necessary, and the client should not send a response requesting an
++ * authentication scheme.
++ */
++
++typedef struct _rfbAuthenticationCapsMsg {
++ CARD32 nAuthTypes;
++ /* followed by nAuthTypes * rfbCapabilityInfo structures */
++} rfbAuthenticationCapsMsg;
++
++#define sz_rfbAuthenticationCapsMsg 4
++
++/*-----------------------------------------------------------------------------
++ * Authentication Scheme Request (protocol version 3.7t)
++ *
++ * If the list of authentication capabilities sent by the server was not empty,
++ * the client should reply with a 32-bit code specifying a particular
++ * authentication scheme. The following codes are supported.
++ */
++
++#define rfbAuthNone 1
++#define rfbAuthVNC 2
++#define rfbAuthUnixLogin 129
++#define rfbAuthExternal 130
++
++#define sig_rfbAuthNone "NOAUTH__"
++#define sig_rfbAuthVNC "VNCAUTH_"
++#define sig_rfbAuthUnixLogin "ULGNAUTH"
++#define sig_rfbAuthExternal "XTRNAUTH"
++
++/* signatures for basic encoding types */
++#define sig_rfbEncodingRaw "RAW_____"
++#define sig_rfbEncodingCopyRect "COPYRECT"
++#define sig_rfbEncodingRRE "RRE_____"
++#define sig_rfbEncodingCoRRE "CORRE___"
++#define sig_rfbEncodingHextile "HEXTILE_"
++#define sig_rfbEncodingZlib "ZLIB____"
++#define sig_rfbEncodingTight "TIGHT___"
++#define sig_rfbEncodingZlibHex "ZLIBHEX_"
++
++/*
++ * Special encoding numbers:
++ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
++ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data;
++ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions;
++ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet;
++ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor;
++ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet.
++ */
++
++#define rfbEncodingCompressLevel0 0xFFFFFF00
++#define rfbEncodingCompressLevel1 0xFFFFFF01
++#define rfbEncodingCompressLevel2 0xFFFFFF02
++#define rfbEncodingCompressLevel3 0xFFFFFF03
++#define rfbEncodingCompressLevel4 0xFFFFFF04
++#define rfbEncodingCompressLevel5 0xFFFFFF05
++#define rfbEncodingCompressLevel6 0xFFFFFF06
++#define rfbEncodingCompressLevel7 0xFFFFFF07
++#define rfbEncodingCompressLevel8 0xFFFFFF08
++#define rfbEncodingCompressLevel9 0xFFFFFF09
++
++#define rfbEncodingXCursor 0xFFFFFF10
++#define rfbEncodingRichCursor 0xFFFFFF11
++#define rfbEncodingPointerPos 0xFFFFFF18
++
++#define rfbEncodingLastRect 0xFFFFFF20
++#define rfbEncodingNewFBSize 0xFFFFFF21
++
++#define rfbEncodingQualityLevel0 0xFFFFFFE0
++#define rfbEncodingQualityLevel1 0xFFFFFFE1
++#define rfbEncodingQualityLevel2 0xFFFFFFE2
++#define rfbEncodingQualityLevel3 0xFFFFFFE3
++#define rfbEncodingQualityLevel4 0xFFFFFFE4
++#define rfbEncodingQualityLevel5 0xFFFFFFE5
++#define rfbEncodingQualityLevel6 0xFFFFFFE6
++#define rfbEncodingQualityLevel7 0xFFFFFFE7
++#define rfbEncodingQualityLevel8 0xFFFFFFE8
++#define rfbEncodingQualityLevel9 0xFFFFFFE9
++
++/* signatures for "fake" encoding types */
++#define sig_rfbEncodingCompressLevel0 "COMPRLVL"
++#define sig_rfbEncodingXCursor "X11CURSR"
++#define sig_rfbEncodingRichCursor "RCHCURSR"
++#define sig_rfbEncodingPointerPos "POINTPOS"
++#define sig_rfbEncodingLastRect "LASTRECT"
++#define sig_rfbEncodingNewFBSize "NEWFBSIZ"
++#define sig_rfbEncodingQualityLevel0 "JPEGQLVL"
++
++/*-----------------------------------------------------------------------------
++ * Server Interaction Capabilities Message (protocol version 3.7t)
++ *
++ * In the protocol version 3.7t, the server informs the client what message
++ * types it supports in addition to ones defined in the protocol version 3.7.
++ * Also, the server sends the list of all supported encodings (note that it's
++ * not necessary to advertise the "raw" encoding sinse it MUST be supported in
++ * RFB 3.x protocols).
++ *
++ * This data immediately follows the server initialisation message.
++ */
++
++typedef struct _rfbInteractionCapsMsg {
++ CARD16 nServerMessageTypes;
++ CARD16 nClientMessageTypes;
++ CARD16 nEncodingTypes;
++ CARD16 pad; /* reserved, must be 0 */
++ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */
++ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */
++} rfbInteractionCapsMsg;
++
++#define sz_rfbInteractionCapsMsg 8
++
++
+
+ /*-----------------------------------------------------------------------------
+ * Client Initialisation Message
+@@ -783,3 +966,5 @@
+ rfbPointerEventMsg pe;
+ rfbClientCutTextMsg cct;
+ } rfbClientToServerMsg;
++
++#endif /* VNC_RFBPROTO_H */
+diff -Nru directvnc-0.7.5/src/sockets.c directvnc-0.7.5.new/src/sockets.c
+--- directvnc-0.7.5/src/sockets.c 2003-01-31 08:33:02.000000000 +0100
++++ directvnc-0.7.5.new/src/sockets.c 2007-01-15 17:22:15.000000000 +0100
+@@ -273,3 +273,19 @@
+
+ fflush(stderr);
+ }
++
++/*
++ * Test if the other end of a socket is on the same machine.
++ */
++
++int
++SameMachine(int sock)
++{
++ struct sockaddr_in peeraddr, myaddr;
++ int addrlen = sizeof(struct sockaddr_in);
++
++ getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen);
++ getsockname(sock, (struct sockaddr *)&myaddr, &addrlen);
++
++ return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
++}