summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/LibVNC/src/libvncclient')
-rw-r--r--3rdParty/LibVNC/src/libvncclient/corre.c70
-rw-r--r--3rdParty/LibVNC/src/libvncclient/cursor.c179
-rw-r--r--3rdParty/LibVNC/src/libvncclient/hextile.c127
-rw-r--r--3rdParty/LibVNC/src/libvncclient/listen.c171
-rw-r--r--3rdParty/LibVNC/src/libvncclient/lzoconf.h451
-rw-r--r--3rdParty/LibVNC/src/libvncclient/minilzo.c2935
-rw-r--r--3rdParty/LibVNC/src/libvncclient/minilzo.h100
-rw-r--r--3rdParty/LibVNC/src/libvncclient/rfbproto.c2123
-rw-r--r--3rdParty/LibVNC/src/libvncclient/rre.c68
-rw-r--r--3rdParty/LibVNC/src/libvncclient/sockets.c616
-rw-r--r--3rdParty/LibVNC/src/libvncclient/tight.c688
-rw-r--r--3rdParty/LibVNC/src/libvncclient/tls.c496
-rw-r--r--3rdParty/LibVNC/src/libvncclient/tls.h51
-rw-r--r--3rdParty/LibVNC/src/libvncclient/ultra.c210
-rw-r--r--3rdParty/LibVNC/src/libvncclient/vncviewer.c375
-rw-r--r--3rdParty/LibVNC/src/libvncclient/zlib.c162
-rw-r--r--3rdParty/LibVNC/src/libvncclient/zrle.c427
17 files changed, 9249 insertions, 0 deletions
diff --git a/3rdParty/LibVNC/src/libvncclient/corre.c b/3rdParty/LibVNC/src/libvncclient/corre.c
new file mode 100644
index 0000000..baf91cc
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/corre.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * corre.c - handle CoRRE encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles a CoRRE
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP)
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+
+static rfbBool
+HandleCoRREBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbRREHeader hdr;
+ int i;
+ CARDBPP pix;
+ uint8_t *ptr;
+ int x, y, w, h;
+
+ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader))
+ return FALSE;
+
+ hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects);
+
+ if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix)))
+ return FALSE;
+
+ FillRectangle(client, rx, ry, rw, rh, pix);
+
+ if (!ReadFromRFBServer(client, client->buffer, hdr.nSubrects * (4 + (BPP / 8))))
+ return FALSE;
+
+ ptr = (uint8_t *)client->buffer;
+
+ for (i = 0; i < hdr.nSubrects; i++) {
+ pix = *(CARDBPP *)ptr;
+ ptr += BPP/8;
+ x = *ptr++;
+ y = *ptr++;
+ w = *ptr++;
+ h = *ptr++;
+
+ FillRectangle(client, rx+x, ry+y, w, h, pix);
+ }
+
+ return TRUE;
+}
+
+#undef CARDBPP
diff --git a/3rdParty/LibVNC/src/libvncclient/cursor.c b/3rdParty/LibVNC/src/libvncclient/cursor.c
new file mode 100644
index 0000000..a48d7c5
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/cursor.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2001,2002 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.
+ */
+
+/*
+ * cursor.c - code to support cursor shape updates (XCursor and
+ * RichCursor preudo-encodings).
+ */
+
+#include <rfb/rfbclient.h>
+
+
+#define OPER_SAVE 0
+#define OPER_RESTORE 1
+
+#define RGB24_TO_PIXEL(bpp,r,g,b) \
+ ((((uint##bpp##_t)(r) & 0xFF) * client->format.redMax + 127) / 255 \
+ << client->format.redShift | \
+ (((uint##bpp##_t)(g) & 0xFF) * client->format.greenMax + 127) / 255 \
+ << client->format.greenShift | \
+ (((uint##bpp##_t)(b) & 0xFF) * client->format.blueMax + 127) / 255 \
+ << client->format.blueShift)
+
+
+/*********************************************************************
+ * HandleCursorShape(). Support for XCursor and RichCursor shape
+ * updates. We emulate cursor operating on the frame buffer (that is
+ * why we call it "software cursor").
+ ********************************************************************/
+
+rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc)
+{
+ int bytesPerPixel;
+ size_t bytesPerRow, bytesMaskData;
+ rfbXCursorColors rgb;
+ uint32_t colors[2];
+ char *buf;
+ uint8_t *ptr;
+ int x, y, b;
+
+ bytesPerPixel = client->format.bitsPerPixel / 8;
+ bytesPerRow = (width + 7) / 8;
+ bytesMaskData = bytesPerRow * height;
+
+ if (width * height == 0)
+ return TRUE;
+
+ /* Allocate memory for pixel data and temporary mask data. */
+ if(client->rcSource)
+ free(client->rcSource);
+
+ client->rcSource = malloc(width * height * bytesPerPixel);
+ if (client->rcSource == NULL)
+ return FALSE;
+
+ buf = malloc(bytesMaskData);
+ if (buf == NULL) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ return FALSE;
+ }
+
+ /* Read and decode cursor pixel data, depending on the encoding type. */
+
+ if (enc == rfbEncodingXCursor) {
+ /* Read and convert background and foreground colors. */
+ if (!ReadFromRFBServer(client, (char *)&rgb, sz_rfbXCursorColors)) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ 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 (!ReadFromRFBServer(client, buf, bytesMaskData)) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ free(buf);
+ return FALSE;
+ }
+
+ /* Convert 1bpp data to byte-wide color indices. */
+ ptr = client->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++)
+ client->rcSource[x] = (uint8_t)colors[client->rcSource[x]];
+ break;
+ case 2:
+ for (x = 0; x < width * height; x++)
+ ((uint16_t *)client->rcSource)[x] = (uint16_t)colors[client->rcSource[x * 2]];
+ break;
+ case 4:
+ for (x = 0; x < width * height; x++)
+ ((uint32_t *)client->rcSource)[x] = colors[client->rcSource[x * 4]];
+ break;
+ }
+
+ } else { /* enc == rfbEncodingRichCursor */
+
+ if (!ReadFromRFBServer(client, (char *)client->rcSource, width * height * bytesPerPixel)) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ free(buf);
+ return FALSE;
+ }
+
+ }
+
+ /* Read and decode mask data. */
+
+ if (!ReadFromRFBServer(client, buf, bytesMaskData)) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ free(buf);
+ return FALSE;
+ }
+
+ client->rcMask = malloc(width * height);
+ if (client->rcMask == NULL) {
+ free(client->rcSource);
+ client->rcSource = NULL;
+ free(buf);
+ return FALSE;
+ }
+
+ ptr = client->rcMask;
+ 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;
+ }
+ }
+ for (b = 7; b > 7 - width % 8; b--) {
+ *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
+ }
+ }
+
+ if (client->GotCursorShape != NULL) {
+ client->GotCursorShape(client, xhot, yhot, width, height, bytesPerPixel);
+ }
+
+ free(buf);
+
+ return TRUE;
+}
+
+
diff --git a/3rdParty/LibVNC/src/libvncclient/hextile.c b/3rdParty/LibVNC/src/libvncclient/hextile.c
new file mode 100644
index 0000000..8698445
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/hextile.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * hextile.c - handle hextile encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles a hextile
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#define HandleHextileBPP CONCAT2E(HandleHextile,BPP)
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+
+static rfbBool
+HandleHextileBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ CARDBPP bg, fg;
+ int i;
+ uint8_t *ptr;
+ int x, y, w, h;
+ int sx, sy, sw, sh;
+ uint8_t subencoding;
+ uint8_t nSubrects;
+
+ for (y = ry; y < ry+rh; y += 16) {
+ for (x = rx; x < rx+rw; x += 16) {
+ w = h = 16;
+ if (rx+rw - x < 16)
+ w = rx+rw - x;
+ if (ry+rh - y < 16)
+ h = ry+rh - y;
+
+ if (!ReadFromRFBServer(client, (char *)&subencoding, 1))
+ return FALSE;
+
+ if (subencoding & rfbHextileRaw) {
+ if (!ReadFromRFBServer(client, client->buffer, w * h * (BPP / 8)))
+ return FALSE;
+
+ CopyRectangle(client, (uint8_t *)client->buffer, x, y, w, h);
+
+ continue;
+ }
+
+ if (subencoding & rfbHextileBackgroundSpecified)
+ if (!ReadFromRFBServer(client, (char *)&bg, sizeof(bg)))
+ return FALSE;
+
+ FillRectangle(client, x, y, w, h, bg);
+
+ if (subencoding & rfbHextileForegroundSpecified)
+ if (!ReadFromRFBServer(client, (char *)&fg, sizeof(fg)))
+ return FALSE;
+
+ if (!(subencoding & rfbHextileAnySubrects)) {
+ continue;
+ }
+
+ if (!ReadFromRFBServer(client, (char *)&nSubrects, 1))
+ return FALSE;
+
+ ptr = (uint8_t*)client->buffer;
+
+ if (subencoding & rfbHextileSubrectsColoured) {
+ if (!ReadFromRFBServer(client, client->buffer, nSubrects * (2 + (BPP / 8))))
+ return FALSE;
+
+ for (i = 0; i < nSubrects; i++) {
+#if BPP==8
+ GET_PIXEL8(fg, ptr);
+#elif BPP==16
+ GET_PIXEL16(fg, ptr);
+#elif BPP==32
+ GET_PIXEL32(fg, ptr);
+#else
+#error "Invalid BPP"
+#endif
+ sx = rfbHextileExtractX(*ptr);
+ sy = rfbHextileExtractY(*ptr);
+ ptr++;
+ sw = rfbHextileExtractW(*ptr);
+ sh = rfbHextileExtractH(*ptr);
+ ptr++;
+
+ FillRectangle(client, x+sx, y+sy, sw, sh, fg);
+ }
+
+ } else {
+ if (!ReadFromRFBServer(client, client->buffer, nSubrects * 2))
+ return FALSE;
+
+ for (i = 0; i < nSubrects; i++) {
+ sx = rfbHextileExtractX(*ptr);
+ sy = rfbHextileExtractY(*ptr);
+ ptr++;
+ sw = rfbHextileExtractW(*ptr);
+ sh = rfbHextileExtractH(*ptr);
+ ptr++;
+
+ FillRectangle(client, x+sx, y+sy, sw, sh, fg);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+#undef CARDBPP
diff --git a/3rdParty/LibVNC/src/libvncclient/listen.c b/3rdParty/LibVNC/src/libvncclient/listen.c
new file mode 100644
index 0000000..637abb1
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/listen.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * listen.c - listen for incoming connections
+ */
+
+#ifdef __STRICT_ANSI__
+#define _BSD_SOURCE
+#endif
+#include <unistd.h>
+#include <sys/types.h>
+#ifdef __MINGW32__
+#define close closesocket
+#include <winsock2.h>
+#else
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#endif
+#include <sys/time.h>
+#include <rfb/rfbclient.h>
+
+/*
+ * listenForIncomingConnections() - listen for incoming connections from
+ * servers, and fork a new process to deal with each connection.
+ */
+
+void
+listenForIncomingConnections(rfbClient* client)
+{
+#ifdef __MINGW32__
+ /* FIXME */
+ rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
+ return;
+#else
+ int listenSocket;
+ fd_set fds;
+
+ client->listenSpecified = TRUE;
+
+ listenSocket = ListenAtTcpPort(client->listenPort);
+
+ if ((listenSocket < 0))
+ return;
+
+ rfbClientLog("%s -listen: Listening on port %d\n",
+ client->programName,client->listenPort);
+ rfbClientLog("%s -listen: Command line errors are not reported until "
+ "a connection comes in.\n", client->programName);
+
+ while (TRUE) {
+
+ /* reap any zombies */
+ int status, pid;
+ while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
+
+ /* TODO: callback for discard any events (like X11 events) */
+
+ FD_ZERO(&fds);
+
+ FD_SET(listenSocket, &fds);
+
+ select(listenSocket+1, &fds, NULL, NULL, NULL);
+
+ if (FD_ISSET(listenSocket, &fds)) {
+ client->sock = AcceptTcpConnection(listenSocket);
+ if (client->sock < 0)
+ return;
+ if (!SetNonBlocking(client->sock))
+ return;
+
+ /* Now fork off a new process to deal with it... */
+
+ switch (fork()) {
+
+ case -1:
+ rfbClientErr("fork\n");
+ return;
+
+ case 0:
+ /* child - return to caller */
+ close(listenSocket);
+ return;
+
+ default:
+ /* parent - go round and listen again */
+ close(client->sock);
+ break;
+ }
+ }
+ }
+#endif
+}
+
+
+
+/*
+ * listenForIncomingConnectionsNoFork() - listen for incoming connections
+ * from servers, but DON'T fork, instead just wait timeout microseconds.
+ * If timeout is negative, block indefinitly.
+ * Returns 1 on success (there was an incoming connection on the listen socket
+ * and we accepted it successfully), -1 on error, 0 on timeout.
+ */
+
+int
+listenForIncomingConnectionsNoFork(rfbClient* client, int timeout)
+{
+ fd_set fds;
+ struct timeval to;
+ int r;
+
+ to.tv_sec= timeout / 1000000;
+ to.tv_usec= timeout % 1000000;
+
+ client->listenSpecified = TRUE;
+
+ if (client->listenSock < 0)
+ {
+ client->listenSock = ListenAtTcpPort(client->listenPort);
+
+ if (client->listenSock < 0)
+ return -1;
+
+ rfbClientLog("%s -listennofork: Listening on port %d\n",
+ client->programName,client->listenPort);
+ rfbClientLog("%s -listennofork: Command line errors are not reported until "
+ "a connection comes in.\n", client->programName);
+ }
+
+ FD_ZERO(&fds);
+
+ FD_SET(client->listenSock, &fds);
+
+ if (timeout < 0)
+ r = select(client->listenSock+1, &fds, NULL, NULL, NULL);
+ else
+ r = select(client->listenSock+1, &fds, NULL, NULL, &to);
+
+ if (r > 0)
+ {
+ client->sock = AcceptTcpConnection(client->listenSock);
+ if (client->sock < 0)
+ return -1;
+ if (!SetNonBlocking(client->sock))
+ return -1;
+
+ close(client->listenSock);
+ return r;
+ }
+
+ /* r is now either 0 (timeout) or -1 (error) */
+ return r;
+}
+
+
diff --git a/3rdParty/LibVNC/src/libvncclient/lzoconf.h b/3rdParty/LibVNC/src/libvncclient/lzoconf.h
new file mode 100644
index 0000000..96db180
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/lzoconf.h
@@ -0,0 +1,451 @@
+/* lzoconf.h -- configuration for the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOCONF_H
+#define __LZOCONF_H
+
+#define LZO_VERSION 0x1080
+#define LZO_VERSION_STRING "1.08"
+#define LZO_VERSION_DATE "Jul 12 2002"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+# error "check your compiler installation"
+#endif
+#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
+# error "your limits.h macros are broken"
+#endif
+
+/* workaround a cpp bug under hpux 10.20 */
+#define LZO_0xffffffffL 4294967295ul
+
+#if !defined(LZO_UINT32_C)
+# if (UINT_MAX < LZO_0xffffffffL)
+# define LZO_UINT32_C(c) c ## UL
+# else
+# define LZO_UINT32_C(c) c ## U
+# endif
+#endif
+
+
+/***********************************************************************
+// architecture defines
+************************************************************************/
+
+#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2)
+# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# define __LZO_WIN
+# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
+# define __LZO_WIN
+# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__)
+# define __LZO_WIN
+# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS)
+# define __LZO_DOS
+# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2)
+# define __LZO_OS2
+# elif defined(__palmos__)
+# define __LZO_PALMOS
+# elif defined(__TOS__) || defined(__atarist__)
+# define __LZO_TOS
+# endif
+#endif
+
+#if (UINT_MAX < LZO_0xffffffffL)
+# if defined(__LZO_WIN)
+# define __LZO_WIN16
+# elif defined(__LZO_DOS)
+# define __LZO_DOS16
+# elif defined(__LZO_PALMOS)
+# define __LZO_PALMOS16
+# elif defined(__LZO_TOS)
+# define __LZO_TOS16
+# elif defined(__C166__)
+# else
+ /* porting hint: for pure 16-bit architectures try compiling
+ * everything with -D__LZO_STRICT_16BIT */
+# error "16-bit target not supported - contact me for porting hints"
+# endif
+#endif
+
+#if !defined(__LZO_i386)
+# if defined(__LZO_DOS) || defined(__LZO_WIN16)
+# define __LZO_i386
+# elif defined(__i386__) || defined(__386__) || defined(_M_IX86)
+# define __LZO_i386
+# endif
+#endif
+
+#if defined(__LZO_STRICT_16BIT)
+# if (UINT_MAX < LZO_0xffffffffL)
+# include <lzo16bit.h>
+# endif
+#endif
+
+/* memory checkers */
+#if !defined(__LZO_CHECKER)
+# if defined(__BOUNDS_CHECKING_ON)
+# define __LZO_CHECKER
+# elif defined(__CHECKER__)
+# define __LZO_CHECKER
+# elif defined(__INSURE__)
+# define __LZO_CHECKER
+# elif defined(__PURIFY__)
+# define __LZO_CHECKER
+# endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* Integral types with 32 bits or more */
+#if !defined(LZO_UINT32_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint32;
+ typedef int lzo_int32;
+# define LZO_UINT32_MAX UINT_MAX
+# define LZO_INT32_MAX INT_MAX
+# define LZO_INT32_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint32;
+ typedef long lzo_int32;
+# define LZO_UINT32_MAX ULONG_MAX
+# define LZO_INT32_MAX LONG_MAX
+# define LZO_INT32_MIN LONG_MIN
+# else
+# error "lzo_uint32"
+# endif
+#endif
+
+/* lzo_uint is used like size_t */
+#if !defined(LZO_UINT_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint;
+ typedef int lzo_int;
+# define LZO_UINT_MAX UINT_MAX
+# define LZO_INT_MAX INT_MAX
+# define LZO_INT_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint;
+ typedef long lzo_int;
+# define LZO_UINT_MAX ULONG_MAX
+# define LZO_INT_MAX LONG_MAX
+# define LZO_INT_MIN LONG_MIN
+# else
+# error "lzo_uint"
+# endif
+#endif
+
+typedef int lzo_bool;
+
+
+/***********************************************************************
+// memory models
+************************************************************************/
+
+/* Memory model for the public code segment. */
+#if !defined(__LZO_CMODEL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_CMODEL __far
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_CMODEL __near
+# else
+# define __LZO_CMODEL
+# endif
+#endif
+
+/* Memory model for the public data segment. */
+#if !defined(__LZO_DMODEL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_DMODEL __far
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_DMODEL __near
+# else
+# define __LZO_DMODEL
+# endif
+#endif
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+# if (LZO_UINT_MAX <= UINT_MAX)
+# define __LZO_MMODEL
+# elif defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_MMODEL __huge
+# define LZO_999_UNSUPPORTED
+# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16)
+# define __LZO_MMODEL
+# else
+# error "__LZO_MMODEL"
+# endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_byte unsigned char __LZO_MMODEL
+#define lzo_bytep unsigned char __LZO_MMODEL *
+#define lzo_charp char __LZO_MMODEL *
+#define lzo_voidp void __LZO_MMODEL *
+#define lzo_shortp short __LZO_MMODEL *
+#define lzo_ushortp unsigned short __LZO_MMODEL *
+#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p lzo_int32 __LZO_MMODEL *
+#define lzo_uintp lzo_uint __LZO_MMODEL *
+#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
+
+#ifndef lzo_sizeof_dict_t
+# define lzo_sizeof_dict_t sizeof(lzo_bytep)
+#endif
+
+
+/***********************************************************************
+// calling conventions and function types
+************************************************************************/
+
+/* linkage */
+#if !defined(__LZO_EXTERN_C)
+# ifdef __cplusplus
+# define __LZO_EXTERN_C extern "C"
+# else
+# define __LZO_EXTERN_C extern
+# endif
+#endif
+
+/* calling convention */
+#if !defined(__LZO_CDECL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# elif defined(__LZO_i386) && defined(_MSC_VER)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# else
+# define __LZO_CDECL __LZO_CMODEL
+# endif
+#endif
+#if !defined(__LZO_ENTRY)
+# define __LZO_ENTRY __LZO_CDECL
+#endif
+
+/* C++ exception specification for extern "C" function types */
+#if !defined(__cplusplus)
+# undef LZO_NOTHROW
+# define LZO_NOTHROW
+#elif !defined(LZO_NOTHROW)
+# define LZO_NOTHROW
+#endif
+
+
+typedef int
+(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+
+/* assembler versions always use __cdecl */
+typedef int
+(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/* a progress indicator callback function */
+typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint);
+
+
+/***********************************************************************
+// export information
+************************************************************************/
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+# define __LZO_EXPORT1
+#endif
+#if !defined(__LZO_EXPORT2)
+# define __LZO_EXPORT2
+#endif
+
+/* exported calling convention for C functions */
+#if !defined(LZO_PUBLIC)
+# define LZO_PUBLIC(_rettype) \
+ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY
+#endif
+#if !defined(LZO_EXTERN)
+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY
+#endif
+
+/* exported __cdecl calling convention for assembler functions */
+#if !defined(LZO_PUBLIC_CDECL)
+# define LZO_PUBLIC_CDECL(_rettype) \
+ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN_CDECL)
+# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype)
+#endif
+
+/* exported global variables (LZO currently uses no static variables and
+ * is fully thread safe) */
+#if !defined(LZO_PUBLIC_VAR)
+# define LZO_PUBLIC_VAR(_type) \
+ __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL
+#endif
+#if !defined(LZO_EXTERN_VAR)
+# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type)
+#endif
+
+
+/***********************************************************************
+// error codes and prototypes
+************************************************************************/
+
+/* Error codes for the compression/decompression functions. Negative
+ * values are errors, positive values will be used for special but
+ * normal events.
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
+#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+
+
+/* lzo_init() should be the first function you call.
+ * Check the return code !
+ *
+ * lzo_init() is a macro to allow checking that the library and the
+ * compiler's view of various types are consistent.
+ */
+#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+ (int)sizeof(lzo_compress_t))
+LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int);
+
+/* version functions (useful for shared libraries) */
+LZO_EXTERN(unsigned) lzo_version(void);
+LZO_EXTERN(const char *) lzo_version_string(void);
+LZO_EXTERN(const char *) lzo_version_date(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
+
+/* string functions */
+LZO_EXTERN(int)
+lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len);
+LZO_EXTERN(lzo_uint32)
+lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len);
+
+/* misc. */
+LZO_EXTERN(lzo_bool) lzo_assert(int _expr);
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t;
+
+/* align a char pointer on a boundary that is a multiple of `size' */
+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size);
+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
+
+/* deprecated - only for backward compatibility */
+#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
diff --git a/3rdParty/LibVNC/src/libvncclient/minilzo.c b/3rdParty/LibVNC/src/libvncclient/minilzo.c
new file mode 100644
index 0000000..85771eb
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/minilzo.c
@@ -0,0 +1,2935 @@
+/* minilzo.c -- mini subset of the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ * the full LZO package can be found at
+ * http://www.oberhumer.com/opensource/lzo/
+ */
+
+#define __LZO_IN_MINILZO
+#define LZO_BUILD
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "minilzo.h"
+
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080)
+# error "version mismatch in miniLZO source files"
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# define LZO_HAVE_CONFIG_H
+#endif
+
+#if !defined(LZO_NO_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+#include <stdio.h>
+
+#ifndef __LZO_CONF_H
+#define __LZO_CONF_H
+
+#if !defined(__LZO_IN_MINILZO)
+# ifndef __LZOCONF_H
+# include <lzoconf.h>
+# endif
+#endif
+
+#if defined(__BOUNDS_CHECKING_ON)
+# include <unchecked.h>
+#else
+# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt
+# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
+#endif
+
+#if !defined(LZO_HAVE_CONFIG_H)
+# include <stddef.h>
+# include <string.h>
+# if !defined(NO_STDLIB_H)
+# include <stdlib.h>
+# endif
+# define HAVE_MEMCMP
+# define HAVE_MEMCPY
+# define HAVE_MEMMOVE
+# define HAVE_MEMSET
+#else
+# include <sys/types.h>
+# if defined(HAVE_STDDEF_H)
+# include <stddef.h>
+# endif
+# if defined(STDC_HEADERS)
+# include <string.h>
+# include <stdlib.h>
+# endif
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define HAVE_MALLOC_H
+# define HAVE_HALLOC
+#endif
+
+#undef NDEBUG
+#if !defined(LZO_DEBUG)
+# define NDEBUG
+#endif
+#if defined(LZO_DEBUG) || !defined(NDEBUG)
+# if !defined(NO_STDIO_H)
+# include <stdio.h>
+# endif
+#endif
+#include <assert.h>
+
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# define LZO_COMPILE_TIME_ASSERT(expr) \
+ { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; }
+#endif
+
+#if !defined(LZO_UNUSED)
+# if 1
+# define LZO_UNUSED(var) ((void)&var)
+# elif 0
+# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; }
+# else
+# define LZO_UNUSED(parm) (parm = parm)
+# endif
+#endif
+
+#if !defined(__inline__) && !defined(__GNUC__)
+# if defined(__cplusplus)
+# define __inline__ inline
+# else
+# define __inline__
+# endif
+#endif
+
+#if defined(NO_MEMCMP)
+# undef HAVE_MEMCMP
+#endif
+
+#if !defined(HAVE_MEMCMP)
+# undef memcmp
+# define memcmp lzo_memcmp
+#endif
+#if !defined(HAVE_MEMCPY)
+# undef memcpy
+# define memcpy lzo_memcpy
+#endif
+#if !defined(HAVE_MEMMOVE)
+# undef memmove
+# define memmove lzo_memmove
+#endif
+#if !defined(HAVE_MEMSET)
+# undef memset
+# define memset lzo_memset
+#endif
+
+#if 0
+# define LZO_BYTE(x) ((unsigned char) (x))
+#else
+# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff))
+#endif
+
+#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
+#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
+#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
+#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
+
+#define lzo_sizeof(type) ((lzo_uint) (sizeof(type)))
+
+#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array))))
+
+#define LZO_SIZE(bits) (1u << (bits))
+#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
+
+#define LZO_LSIZE(bits) (1ul << (bits))
+#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
+
+#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
+#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
+
+#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2)))
+#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1)))
+
+#if !defined(SIZEOF_UNSIGNED)
+# if (UINT_MAX == 0xffff)
+# define SIZEOF_UNSIGNED 2
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED 4
+# elif (UINT_MAX >= LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED 8
+# else
+# error "SIZEOF_UNSIGNED"
+# endif
+#endif
+
+#if !defined(SIZEOF_UNSIGNED_LONG)
+# if (ULONG_MAX == LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED_LONG 4
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED_LONG 8
+# else
+# error "SIZEOF_UNSIGNED_LONG"
+# endif
+#endif
+
+#if !defined(SIZEOF_SIZE_T)
+# define SIZEOF_SIZE_T SIZEOF_UNSIGNED
+#endif
+#if !defined(SIZE_T_MAX)
+# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T)
+#endif
+
+#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL)
+# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff)
+# define LZO_UNALIGNED_OK_2
+# endif
+# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL)
+# define LZO_UNALIGNED_OK_4
+# endif
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4)
+# if !defined(LZO_UNALIGNED_OK)
+# define LZO_UNALIGNED_OK
+# endif
+#endif
+
+#if defined(__LZO_NO_UNALIGNED)
+# undef LZO_UNALIGNED_OK
+# undef LZO_UNALIGNED_OK_2
+# undef LZO_UNALIGNED_OK_4
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff)
+# error "LZO_UNALIGNED_OK_2 must not be defined on this system"
+#endif
+#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL)
+# error "LZO_UNALIGNED_OK_4 must not be defined on this system"
+#endif
+
+#if defined(__LZO_NO_ALIGNED)
+# undef LZO_ALIGNED_OK_4
+#endif
+
+#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL)
+# error "LZO_ALIGNED_OK_4 must not be defined on this system"
+#endif
+
+#define LZO_LITTLE_ENDIAN 1234
+#define LZO_BIG_ENDIAN 4321
+#define LZO_PDP_ENDIAN 3412
+
+#if !defined(LZO_BYTE_ORDER)
+# if defined(MFX_BYTE_ORDER)
+# define LZO_BYTE_ORDER MFX_BYTE_ORDER
+# elif defined(__LZO_i386)
+# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN
+# elif defined(BYTE_ORDER)
+# define LZO_BYTE_ORDER BYTE_ORDER
+# elif defined(__BYTE_ORDER)
+# define LZO_BYTE_ORDER __BYTE_ORDER
+# endif
+#endif
+
+#if defined(LZO_BYTE_ORDER)
+# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \
+ (LZO_BYTE_ORDER != LZO_BIG_ENDIAN)
+# error "invalid LZO_BYTE_ORDER"
+# endif
+#endif
+
+#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER)
+# error "LZO_BYTE_ORDER is not defined"
+#endif
+
+#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY
+
+#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER)
+# if defined(__GNUC__) && defined(__i386__)
+# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY)
+# define LZO_OPTIMIZE_GNUC_i386
+# endif
+# endif
+#endif
+
+__LZO_EXTERN_C int __lzo_init_done;
+__LZO_EXTERN_C const lzo_byte __lzo_copyright[];
+LZO_EXTERN(const lzo_byte *) lzo_copyright(void);
+__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256];
+
+#define _LZO_STRINGIZE(x) #x
+#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x)
+
+#define _LZO_CONCAT2(a,b) a ## b
+#define _LZO_CONCAT3(a,b,c) a ## b ## c
+#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+
+#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b)
+#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c)
+#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d)
+#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e)
+
+#if 0
+
+#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#endif
+
+#ifndef __LZO_PTR_H
+#define __LZO_PTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# include <dos.h>
+# if 1 && defined(__WATCOMC__)
+# include <i86.h>
+ __LZO_EXTERN_C unsigned char _HShift;
+# define __LZO_HShift _HShift
+# elif 1 && defined(_MSC_VER)
+ __LZO_EXTERN_C unsigned short __near _AHSHIFT;
+# define __LZO_HShift ((unsigned) &_AHSHIFT)
+# elif defined(__LZO_WIN16)
+# define __LZO_HShift 3
+# else
+# define __LZO_HShift 12
+# endif
+# if !defined(_FP_SEG) && defined(FP_SEG)
+# define _FP_SEG FP_SEG
+# endif
+# if !defined(_FP_OFF) && defined(FP_OFF)
+# define _FP_OFF FP_OFF
+# endif
+#endif
+
+#if !defined(lzo_ptrdiff_t)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef ptrdiff_t lzo_ptrdiff_t;
+# else
+ typedef long lzo_ptrdiff_t;
+# endif
+#endif
+
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(lzo_ptr_t)
+# define __LZO_HAVE_PTR_T
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG)
+ typedef unsigned long lzo_ptr_t;
+ typedef long lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED)
+ typedef unsigned int lzo_ptr_t;
+ typedef int lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT)
+ typedef unsigned short lzo_ptr_t;
+ typedef short lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P)
+# error "no suitable type for lzo_ptr_t"
+# else
+ typedef unsigned long lzo_ptr_t;
+ typedef long lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+#define PTR(a) ((lzo_bytep) (a))
+#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0)
+#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0)
+#else
+#define PTR(a) ((lzo_ptr_t) (a))
+#define PTR_LINEAR(a) PTR(a)
+#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
+#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
+#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
+#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
+#endif
+
+#define PTR_LT(a,b) (PTR(a) < PTR(b))
+#define PTR_GE(a,b) (PTR(a) >= PTR(b))
+#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
+#define pd(a,b) ((lzo_uint) ((a)-(b)))
+
+LZO_EXTERN(lzo_ptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr);
+
+typedef union
+{
+ char a_char;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long a_long;
+ unsigned long a_ulong;
+ lzo_int a_lzo_int;
+ lzo_uint a_lzo_uint;
+ lzo_int32 a_lzo_int32;
+ lzo_uint32 a_lzo_uint32;
+ ptrdiff_t a_ptrdiff_t;
+ lzo_ptrdiff_t a_lzo_ptrdiff_t;
+ lzo_ptr_t a_lzo_ptr_t;
+ lzo_voidp a_lzo_voidp;
+ void * a_void_p;
+ lzo_bytep a_lzo_bytep;
+ lzo_bytepp a_lzo_bytepp;
+ lzo_uintp a_lzo_uintp;
+ lzo_uint * a_lzo_uint_p;
+ lzo_uint32p a_lzo_uint32p;
+ lzo_uint32 * a_lzo_uint32_p;
+ unsigned char * a_uchar_p;
+ char * a_char_p;
+}
+lzo_full_align_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#define LZO_DETERMINISTIC
+
+#define LZO_DICT_USE_PTR
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT)
+# undef LZO_DICT_USE_PTR
+#endif
+
+#if defined(LZO_DICT_USE_PTR)
+# define lzo_dict_t const lzo_bytep
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#else
+# define lzo_dict_t lzo_uint
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#endif
+
+#if !defined(lzo_moff_t)
+#define lzo_moff_t lzo_uint
+#endif
+
+#endif
+
+LZO_PUBLIC(lzo_ptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr)
+{
+ lzo_ptr_t p;
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+ p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr));
+#else
+ p = PTR_LINEAR(ptr);
+#endif
+
+ return p;
+}
+
+LZO_PUBLIC(unsigned)
+__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+{
+ lzo_ptr_t p, s, n;
+
+ assert(size > 0);
+
+ p = __lzo_ptr_linear(ptr);
+ s = (lzo_ptr_t) (size - 1);
+#if 0
+ assert((size & (size - 1)) == 0);
+ n = ((p + s) & ~s) - p;
+#else
+ n = (((p + s) / size) * size) - p;
+#endif
+
+ assert((long)n >= 0);
+ assert(n <= s);
+
+ return (unsigned)n;
+}
+
+#ifndef __LZO_UTIL_H
+#define __LZO_UTIL_H
+
+#ifndef __LZO_CONF_H
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 1 && defined(HAVE_MEMCPY)
+#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16)
+
+#define MEMCPY8_DS(dest,src,len) \
+ memcpy(dest,src,len); \
+ dest += len; \
+ src += len
+
+#endif
+#endif
+
+#if 0 && !defined(MEMCPY8_DS)
+
+#define MEMCPY8_DS(dest,src,len) \
+ { do { \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ len -= 8; \
+ } while (len > 0); }
+
+#endif
+
+#if !defined(MEMCPY8_DS)
+
+#define MEMCPY8_DS(dest,src,len) \
+ { register lzo_uint __l = (len) / 8; \
+ do { \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ } while (--__l > 0); }
+
+#endif
+
+#define MEMCPY_DS(dest,src,len) \
+ do *dest++ = *src++; \
+ while (--len > 0)
+
+#define MEMMOVE_DS(dest,src,len) \
+ do *dest++ = *src++; \
+ while (--len > 0)
+
+#if 0 && defined(LZO_OPTIMIZE_GNUC_i386)
+
+#define BZERO8_PTR(s,l,n) \
+__asm__ __volatile__( \
+ "movl %0,%%eax \n" \
+ "movl %1,%%edi \n" \
+ "movl %2,%%ecx \n" \
+ "cld \n" \
+ "rep \n" \
+ "stosl %%eax,(%%edi) \n" \
+ : \
+ :"g" (0),"g" (s),"g" (n) \
+ :"eax","edi","ecx", "memory", "cc" \
+)
+
+#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET)
+
+#if 1
+#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n))
+#else
+#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+#endif
+
+#else
+
+#define BZERO8_PTR(s,l,n) \
+ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+
+#endif
+
+#if 0
+#if defined(__GNUC__) && defined(__i386__)
+
+unsigned char lzo_rotr8(unsigned char value, int shift);
+extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift)
+{
+ unsigned char result;
+
+ __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0"
+ : "=a"(result) : "g"(value), "c"(shift));
+ return result;
+}
+
+unsigned short lzo_rotr16(unsigned short value, int shift);
+extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift)
+{
+ unsigned short result;
+
+ __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0"
+ : "=a"(result) : "g"(value), "c"(shift));
+ return result;
+}
+
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+LZO_PUBLIC(lzo_bool)
+lzo_assert(int expr)
+{
+ return (expr) ? 1 : 0;
+}
+
+/* If you use the LZO library in a product, you *must* keep this
+ * copyright string in the executable of your product.
+ */
+
+const lzo_byte __lzo_copyright[] =
+#if !defined(__LZO_IN_MINLZO)
+ LZO_VERSION_STRING;
+#else
+ "\n\n\n"
+ "LZO real-time data compression library.\n"
+ "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n"
+ "<markus.oberhumer@jk.uni-linz.ac.at>\n"
+ "http://www.oberhumer.com/opensource/lzo/\n"
+ "\n"
+ "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n"
+ "LZO build date: " __DATE__ " " __TIME__ "\n\n"
+ "LZO special compilation options:\n"
+#ifdef __cplusplus
+ " __cplusplus\n"
+#endif
+#if defined(__PIC__)
+ " __PIC__\n"
+#elif defined(__pic__)
+ " __pic__\n"
+#endif
+#if (UINT_MAX < LZO_0xffffffffL)
+ " 16BIT\n"
+#endif
+#if defined(__LZO_STRICT_16BIT)
+ " __LZO_STRICT_16BIT\n"
+#endif
+#if (UINT_MAX > LZO_0xffffffffL)
+ " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n"
+#endif
+#if (ULONG_MAX > LZO_0xffffffffL)
+ " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n"
+#endif
+#if defined(LZO_BYTE_ORDER)
+ " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n"
+#endif
+#if defined(LZO_UNALIGNED_OK_2)
+ " LZO_UNALIGNED_OK_2\n"
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+ " LZO_UNALIGNED_OK_4\n"
+#endif
+#if defined(LZO_ALIGNED_OK_4)
+ " LZO_ALIGNED_OK_4\n"
+#endif
+#if defined(LZO_DICT_USE_PTR)
+ " LZO_DICT_USE_PTR\n"
+#endif
+#if defined(__LZO_QUERY_COMPRESS)
+ " __LZO_QUERY_COMPRESS\n"
+#endif
+#if defined(__LZO_QUERY_DECOMPRESS)
+ " __LZO_QUERY_DECOMPRESS\n"
+#endif
+#if defined(__LZO_IN_MINILZO)
+ " __LZO_IN_MINILZO\n"
+#endif
+ "\n\n"
+ "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__
+#if defined(__GNUC__) && defined(__VERSION__)
+ " by gcc " __VERSION__
+#elif defined(__BORLANDC__)
+ " by Borland C " _LZO_MEXPAND(__BORLANDC__)
+#elif defined(_MSC_VER)
+ " by Microsoft C " _LZO_MEXPAND(_MSC_VER)
+#elif defined(__PUREC__)
+ " by Pure C " _LZO_MEXPAND(__PUREC__)
+#elif defined(__SC__)
+ " by Symantec C " _LZO_MEXPAND(__SC__)
+#elif defined(__TURBOC__)
+ " by Turbo C " _LZO_MEXPAND(__TURBOC__)
+#elif defined(__WATCOMC__)
+ " by Watcom C " _LZO_MEXPAND(__WATCOMC__)
+#endif
+ " $\n"
+ "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n";
+#endif
+
+LZO_PUBLIC(const lzo_byte *)
+lzo_copyright(void)
+{
+ return __lzo_copyright;
+}
+
+LZO_PUBLIC(unsigned)
+lzo_version(void)
+{
+ return LZO_VERSION;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const char *)
+lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_string(void)
+{
+ return LZO_VERSION_STRING;
+}
+
+LZO_PUBLIC(const lzo_charp)
+_lzo_version_date(void)
+{
+ return LZO_VERSION_DATE;
+}
+
+#define LZO_BASE 65521u
+#define LZO_NMAX 5552
+
+#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
+
+LZO_PUBLIC(lzo_uint32)
+lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len)
+{
+ lzo_uint32 s1 = adler & 0xffff;
+ lzo_uint32 s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == NULL)
+ return 1;
+
+ while (len > 0)
+ {
+ k = len < LZO_NMAX ? (int) len : LZO_NMAX;
+ len -= k;
+ if (k >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ k -= 16;
+ } while (k >= 16);
+ if (k != 0) do
+ {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k > 0);
+ s1 %= LZO_BASE;
+ s2 %= LZO_BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+LZO_PUBLIC(int)
+lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP)
+ return memcmp(s1,s2,len);
+#else
+ const lzo_byte *p1 = (const lzo_byte *) s1;
+ const lzo_byte *p2 = (const lzo_byte *) s2;
+ int d;
+
+ if (len > 0) do
+ {
+ d = *p1 - *p2;
+ if (d != 0)
+ return d;
+ p1++;
+ p2++;
+ }
+ while (--len > 0);
+ return 0;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY)
+ return memcpy(dest,src,len);
+#else
+ lzo_byte *p1 = (lzo_byte *) dest;
+ const lzo_byte *p2 = (const lzo_byte *) src;
+
+ if (len <= 0 || p1 == p2)
+ return dest;
+ do
+ *p1++ = *p2++;
+ while (--len > 0);
+ return dest;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE)
+ return memmove(dest,src,len);
+#else
+ lzo_byte *p1 = (lzo_byte *) dest;
+ const lzo_byte *p2 = (const lzo_byte *) src;
+
+ if (len <= 0 || p1 == p2)
+ return dest;
+
+ if (p1 < p2)
+ {
+ do
+ *p1++ = *p2++;
+ while (--len > 0);
+ }
+ else
+ {
+ p1 += len;
+ p2 += len;
+ do
+ *--p1 = *--p2;
+ while (--len > 0);
+ }
+ return dest;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memset(lzo_voidp s, int c, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET)
+ return memset(s,c,len);
+#else
+ lzo_byte *p = (lzo_byte *) s;
+
+ if (len > 0) do
+ *p++ = LZO_BYTE(c);
+ while (--len > 0);
+ return s;
+#endif
+}
+
+#if 0
+# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0)
+# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0)
+#else
+# define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
+# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
+#endif
+
+#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+
+static lzo_bool schedule_insns_bug(void);
+static lzo_bool strength_reduce_bug(int *);
+
+#if 0 || defined(LZO_DEBUG)
+#include <stdio.h>
+static lzo_bool __lzo_assert_fail(const char *s, unsigned line)
+{
+#if defined(__palmos__)
+ printf("LZO assertion failed in line %u: '%s'\n",line,s);
+#else
+ fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s);
+#endif
+ return 0;
+}
+# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__))
+#else
+# define __lzo_assert(x) ((x) ? 1 : 0)
+#endif
+
+#undef COMPILE_TIME_ASSERT
+#if 0
+# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr)
+#else
+# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
+#endif
+
+static lzo_bool basic_integral_check(void)
+{
+ lzo_bool r = 1;
+
+ COMPILE_TIME_ASSERT(CHAR_BIT == 8);
+ COMPILE_TIME_ASSERT(sizeof(char) == 1);
+ COMPILE_TIME_ASSERT(sizeof(short) >= 2);
+ COMPILE_TIME_ASSERT(sizeof(long) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short));
+ COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int));
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned));
+#if defined(__LZO_STRICT_16BIT)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2);
+#else
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned));
+#endif
+
+#if (USHRT_MAX == 65535u)
+ COMPILE_TIME_ASSERT(sizeof(short) == 2);
+#elif (USHRT_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(short) == 4);
+#elif (USHRT_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(short) > 4);
+#endif
+#if (UINT_MAX == 65535u)
+ COMPILE_TIME_ASSERT(sizeof(int) == 2);
+#elif (UINT_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(int) == 4);
+#elif (UINT_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(int) > 4);
+#endif
+#if (ULONG_MAX == 65535ul)
+ COMPILE_TIME_ASSERT(sizeof(long) == 2);
+#elif (ULONG_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(long) == 4);
+#elif (ULONG_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(long) > 4);
+#endif
+
+#if defined(SIZEOF_UNSIGNED)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned));
+#endif
+#if defined(SIZEOF_UNSIGNED_LONG)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long));
+#endif
+#if defined(SIZEOF_UNSIGNED_SHORT)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short));
+#endif
+#if !defined(__LZO_IN_MINILZO)
+#if defined(SIZEOF_SIZE_T)
+ COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t));
+#endif
+#endif
+
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long));
+ COMPILE_TIME_ASSERT(IS_SIGNED(short));
+ COMPILE_TIME_ASSERT(IS_SIGNED(int));
+ COMPILE_TIME_ASSERT(IS_SIGNED(long));
+
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int));
+
+ COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int)));
+ COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned)));
+ COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long)));
+ COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long)));
+ COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short)));
+ COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short)));
+ COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32)));
+ COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint)));
+#if !defined(__LZO_IN_MINILZO)
+ COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t)));
+#endif
+
+ r &= __lzo_assert(LZO_BYTE(257) == 1);
+
+ return r;
+}
+
+static lzo_bool basic_ptr_check(void)
+{
+ lzo_bool r = 1;
+
+ COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int));
+ COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t));
+
+ COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint));
+
+#if defined(SIZEOF_CHAR_P)
+ COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *));
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+ COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t));
+#endif
+
+ COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t));
+
+ return r;
+}
+
+static lzo_bool ptr_check(void)
+{
+ lzo_bool r = 1;
+ int i;
+ char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)];
+ lzo_bytep wrkmem;
+ lzo_bytepp dict;
+ unsigned char x[4 * sizeof(lzo_full_align_t)];
+ long d;
+ lzo_full_align_t a;
+ lzo_full_align_t u;
+
+ for (i = 0; i < (int) sizeof(x); i++)
+ x[i] = LZO_BYTE(i);
+
+ wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t));
+
+#if 0
+ dict = (lzo_bytepp) wrkmem;
+#else
+
+ u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp;
+#endif
+
+ d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem);
+ r &= __lzo_assert(d >= 0);
+ r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t));
+
+ memset(&a,0,sizeof(a));
+ r &= __lzo_assert(a.a_lzo_voidp == NULL);
+
+ memset(&a,0xff,sizeof(a));
+ r &= __lzo_assert(a.a_ushort == USHRT_MAX);
+ r &= __lzo_assert(a.a_uint == UINT_MAX);
+ r &= __lzo_assert(a.a_ulong == ULONG_MAX);
+ r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX);
+ r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX);
+
+ if (r == 1)
+ {
+ for (i = 0; i < 8; i++)
+ r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)]));
+ }
+
+ memset(&a,0,sizeof(a));
+ r &= __lzo_assert(a.a_char_p == NULL);
+ r &= __lzo_assert(a.a_lzo_bytep == NULL);
+ r &= __lzo_assert(NULL == (void *)0);
+ if (r == 1)
+ {
+ for (i = 0; i < 10; i++)
+ dict[i] = wrkmem;
+ BZERO8_PTR(dict+1,sizeof(dict[0]),8);
+ r &= __lzo_assert(dict[0] == wrkmem);
+ for (i = 1; i < 9; i++)
+ r &= __lzo_assert(dict[i] == NULL);
+ r &= __lzo_assert(dict[9] == wrkmem);
+ }
+
+ if (r == 1)
+ {
+ unsigned k = 1;
+ const unsigned n = (unsigned) sizeof(lzo_uint32);
+ lzo_byte *p0;
+ lzo_byte *p1;
+
+ k += __lzo_align_gap(&x[k],n);
+ p0 = (lzo_bytep) &x[k];
+#if defined(PTR_LINEAR)
+ r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0);
+#else
+ r &= __lzo_assert(n == 4);
+ r &= __lzo_assert(PTR_ALIGNED_4(p0));
+#endif
+
+ r &= __lzo_assert(k >= 1);
+ p1 = (lzo_bytep) &x[1];
+ r &= __lzo_assert(PTR_GE(p0,p1));
+
+ r &= __lzo_assert(k < 1+n);
+ p1 = (lzo_bytep) &x[1+n];
+ r &= __lzo_assert(PTR_LT(p0,p1));
+
+ if (r == 1)
+ {
+ lzo_uint32 v0, v1;
+#if 0
+ v0 = * (lzo_uint32 *) &x[k];
+ v1 = * (lzo_uint32 *) &x[k+n];
+#else
+
+ u.a_uchar_p = &x[k];
+ v0 = *u.a_lzo_uint32_p;
+ u.a_uchar_p = &x[k+n];
+ v1 = *u.a_lzo_uint32_p;
+#endif
+ r &= __lzo_assert(v0 > 0);
+ r &= __lzo_assert(v1 > 0);
+ }
+ }
+
+ return r;
+}
+
+LZO_PUBLIC(int)
+_lzo_config_check(void)
+{
+ lzo_bool r = 1;
+ int i;
+ union {
+ lzo_uint32 a;
+ unsigned short b;
+ lzo_uint32 aa[4];
+ unsigned char x[4*sizeof(lzo_full_align_t)];
+ } u;
+
+ COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255);
+ COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0);
+
+#if 0
+ r &= __lzo_assert((const void *)&u == (const void *)&u.a);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.b);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]);
+#endif
+
+ r &= basic_integral_check();
+ r &= basic_ptr_check();
+ if (r != 1)
+ return LZO_E_ERROR;
+
+ u.a = 0; u.b = 0;
+ for (i = 0; i < (int) sizeof(u.x); i++)
+ u.x[i] = LZO_BYTE(i);
+
+#if defined(LZO_BYTE_ORDER)
+ if (r == 1)
+ {
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL);
+ unsigned short b = (unsigned short) (u.b & 0xffff);
+ r &= __lzo_assert(a == 0x03020100L);
+ r &= __lzo_assert(b == 0x0100);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32);
+ unsigned short b = u.b >> (8 * sizeof(u.b) - 16);
+ r &= __lzo_assert(a == 0x00010203L);
+ r &= __lzo_assert(b == 0x0001);
+# else
+# error "invalid LZO_BYTE_ORDER"
+# endif
+ }
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2)
+ COMPILE_TIME_ASSERT(sizeof(short) == 2);
+ if (r == 1)
+ {
+ unsigned short b[4];
+
+ for (i = 0; i < 4; i++)
+ b[i] = * (const unsigned short *) &u.x[i];
+
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ r &= __lzo_assert(b[0] == 0x0100);
+ r &= __lzo_assert(b[1] == 0x0201);
+ r &= __lzo_assert(b[2] == 0x0302);
+ r &= __lzo_assert(b[3] == 0x0403);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ r &= __lzo_assert(b[0] == 0x0001);
+ r &= __lzo_assert(b[1] == 0x0102);
+ r &= __lzo_assert(b[2] == 0x0203);
+ r &= __lzo_assert(b[3] == 0x0304);
+# endif
+ }
+#endif
+
+#if defined(LZO_UNALIGNED_OK_4)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4);
+ if (r == 1)
+ {
+ lzo_uint32 a[4];
+
+ for (i = 0; i < 4; i++)
+ a[i] = * (const lzo_uint32 *) &u.x[i];
+
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ r &= __lzo_assert(a[0] == 0x03020100L);
+ r &= __lzo_assert(a[1] == 0x04030201L);
+ r &= __lzo_assert(a[2] == 0x05040302L);
+ r &= __lzo_assert(a[3] == 0x06050403L);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ r &= __lzo_assert(a[0] == 0x00010203L);
+ r &= __lzo_assert(a[1] == 0x01020304L);
+ r &= __lzo_assert(a[2] == 0x02030405L);
+ r &= __lzo_assert(a[3] == 0x03040506L);
+# endif
+ }
+#endif
+
+#if defined(LZO_ALIGNED_OK_4)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4);
+#endif
+
+ COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t));
+
+#if defined(__LZO_IN_MINLZO)
+ if (r == 1)
+ {
+ lzo_uint32 adler;
+ adler = lzo_adler32(0, NULL, 0);
+ adler = lzo_adler32(adler, lzo_copyright(), 200);
+ r &= __lzo_assert(adler == 0xc76f1751L);
+ }
+#endif
+
+ if (r == 1)
+ {
+ r &= __lzo_assert(!schedule_insns_bug());
+ }
+
+ if (r == 1)
+ {
+ static int x[3];
+ static unsigned xn = 3;
+ register unsigned j;
+
+ for (j = 0; j < xn; j++)
+ x[j] = (int)j - 3;
+ r &= __lzo_assert(!strength_reduce_bug(x));
+ }
+
+ if (r == 1)
+ {
+ r &= ptr_check();
+ }
+
+ return r == 1 ? LZO_E_OK : LZO_E_ERROR;
+}
+
+static lzo_bool schedule_insns_bug(void)
+{
+#if defined(__LZO_CHECKER)
+ return 0;
+#else
+ const int clone[] = {1, 2, 0};
+ const int *q;
+ q = clone;
+ return (*q) ? 0 : 1;
+#endif
+}
+
+static lzo_bool strength_reduce_bug(int *x)
+{
+ return x[0] != -3 || x[1] != -2 || x[2] != -1;
+}
+
+#undef COMPILE_TIME_ASSERT
+
+int __lzo_init_done = 0;
+
+LZO_PUBLIC(int)
+__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5,
+ int s6, int s7, int s8, int s9)
+{
+ int r;
+
+ __lzo_init_done = 1;
+
+ if (v == 0)
+ return LZO_E_ERROR;
+
+ r = (s1 == -1 || s1 == (int) sizeof(short)) &&
+ (s2 == -1 || s2 == (int) sizeof(int)) &&
+ (s3 == -1 || s3 == (int) sizeof(long)) &&
+ (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) &&
+ (s5 == -1 || s5 == (int) sizeof(lzo_uint)) &&
+ (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) &&
+ (s7 == -1 || s7 == (int) sizeof(char *)) &&
+ (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) &&
+ (s9 == -1 || s9 == (int) sizeof(lzo_compress_t));
+ if (!r)
+ return LZO_E_ERROR;
+
+ r = _lzo_config_check();
+ if (r != LZO_E_OK)
+ return r;
+
+ return r;
+}
+
+#if !defined(__LZO_IN_MINILZO)
+
+LZO_EXTERN(int)
+__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7);
+
+LZO_PUBLIC(int)
+__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7)
+{
+ if (v == 0 || v > 0x1010)
+ return LZO_E_ERROR;
+ return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7);
+}
+
+#endif
+
+#define do_compress _lzo1x_1_do_compress
+
+#define LZO_NEED_DICT_H
+#define D_BITS 14
+#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+
+#ifndef __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+# define LZO1X
+#endif
+
+#if !defined(__LZO_IN_MINILZO)
+#include <lzo1x.h>
+#endif
+
+#define LZO_EOF_CODE
+#undef LZO_DETERMINISTIC
+
+#define M1_MAX_OFFSET 0x0400
+#ifndef M2_MAX_OFFSET
+#define M2_MAX_OFFSET 0x0800
+#endif
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#ifndef M2_MAX_LEN
+#define M2_MAX_LEN 8
+#endif
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+#ifndef MIN_LOOKAHEAD
+#define MIN_LOOKAHEAD (M2_MAX_LEN + 1)
+#endif
+
+#if defined(LZO_NEED_DICT_H)
+
+#ifndef LZO_HASH
+#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B
+#endif
+#define DL_MIN_LEN M2_MIN_LEN
+
+#ifndef __LZO_DICT_H
+#define __LZO_DICT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(D_BITS) && defined(DBITS)
+# define D_BITS DBITS
+#endif
+#if !defined(D_BITS)
+# error "D_BITS is not defined"
+#endif
+#if (D_BITS < 16)
+# define D_SIZE LZO_SIZE(D_BITS)
+# define D_MASK LZO_MASK(D_BITS)
+#else
+# define D_SIZE LZO_USIZE(D_BITS)
+# define D_MASK LZO_UMASK(D_BITS)
+#endif
+#define D_HIGH ((D_MASK >> 1) + 1)
+
+#if !defined(DD_BITS)
+# define DD_BITS 0
+#endif
+#define DD_SIZE LZO_SIZE(DD_BITS)
+#define DD_MASK LZO_MASK(DD_BITS)
+
+#if !defined(DL_BITS)
+# define DL_BITS (D_BITS - DD_BITS)
+#endif
+#if (DL_BITS < 16)
+# define DL_SIZE LZO_SIZE(DL_BITS)
+# define DL_MASK LZO_MASK(DL_BITS)
+#else
+# define DL_SIZE LZO_USIZE(DL_BITS)
+# define DL_MASK LZO_UMASK(DL_BITS)
+#endif
+
+#if (D_BITS != DL_BITS + DD_BITS)
+# error "D_BITS does not match"
+#endif
+#if (D_BITS < 8 || D_BITS > 18)
+# error "invalid D_BITS"
+#endif
+#if (DL_BITS < 8 || DL_BITS > 20)
+# error "invalid DL_BITS"
+#endif
+#if (DD_BITS < 0 || DD_BITS > 6)
+# error "invalid DD_BITS"
+#endif
+
+#if !defined(DL_MIN_LEN)
+# define DL_MIN_LEN 3
+#endif
+#if !defined(DL_SHIFT)
+# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN)
+#endif
+
+#define LZO_HASH_GZIP 1
+#define LZO_HASH_GZIP_INCREMENTAL 2
+#define LZO_HASH_LZO_INCREMENTAL_A 3
+#define LZO_HASH_LZO_INCREMENTAL_B 4
+
+#if !defined(LZO_HASH)
+# error "choose a hashing strategy"
+#endif
+
+#if (DL_MIN_LEN == 3)
+# define _DV2_A(p,shift1,shift2) \
+ (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2])
+# define _DV2_B(p,shift1,shift2) \
+ (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0])
+# define _DV3_B(p,shift1,shift2,shift3) \
+ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0])
+#elif (DL_MIN_LEN == 2)
+# define _DV2_A(p,shift1,shift2) \
+ (( (lzo_uint32)(p[0]) << shift1) ^ p[1])
+# define _DV2_B(p,shift1,shift2) \
+ (( (lzo_uint32)(p[1]) << shift1) ^ p[2])
+#else
+# error "invalid DL_MIN_LEN"
+#endif
+#define _DV_A(p,shift) _DV2_A(p,shift,shift)
+#define _DV_B(p,shift) _DV2_B(p,shift,shift)
+#define DA2(p,s1,s2) \
+ (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0])
+#define DS2(p,s1,s2) \
+ (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0])
+#define DX2(p,s1,s2) \
+ (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
+#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0])
+#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0])
+#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
+#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
+#define DM(v) DMS(v,0)
+
+#if (LZO_HASH == LZO_HASH_GZIP)
+# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT))
+
+#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL)
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT)
+# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2])
+# define _DINDEX(dv,p) (dv)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A)
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
+# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_B((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5)))
+# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#else
+# error "choose a hashing strategy"
+#endif
+
+#ifndef DINDEX
+#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS)
+#endif
+#if !defined(DINDEX1) && defined(D_INDEX1)
+#define DINDEX1 D_INDEX1
+#endif
+#if !defined(DINDEX2) && defined(D_INDEX2)
+#define DINDEX2 D_INDEX2
+#endif
+
+#if !defined(__LZO_HASH_INCREMENTAL)
+# define DVAL_FIRST(dv,p) ((void) 0)
+# define DVAL_NEXT(dv,p) ((void) 0)
+# define DVAL_LOOKAHEAD 0
+#endif
+
+#if !defined(DVAL_ASSERT)
+#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
+static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p)
+{
+ lzo_uint32 df;
+ DVAL_FIRST(df,(p));
+ assert(DINDEX(dv,p) == DINDEX(df,p));
+}
+#else
+# define DVAL_ASSERT(dv,p) ((void) 0)
+#endif
+#endif
+
+#if defined(LZO_DICT_USE_PTR)
+# define DENTRY(p,in) (p)
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
+#else
+# define DENTRY(p,in) ((lzo_uint) ((p)-(in)))
+# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex]
+#endif
+
+#if (DD_BITS == 0)
+
+# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in)
+# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
+# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in)
+
+#else
+
+# define UPDATE_D(dict,drun,dv,p,in) \
+ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_I(dict,drun,index,p,in) \
+ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK
+# define UPDATE_P(ptr,drun,p,in) \
+ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK
+
+#endif
+
+#if defined(LZO_DICT_USE_PTR)
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset)
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (BOUNDS_CHECKING_OFF_IN_EXPR( \
+ (PTR_LT(m_pos,in) || \
+ (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \
+ m_off > max_offset) ))
+
+#else
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_off == 0 || \
+ ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ ((lzo_moff_t) ((ip)-(in)) <= m_off || \
+ ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#endif
+
+#if defined(LZO_DETERMINISTIC)
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET
+#else
+# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
+
+#endif
+
+#define DO_COMPRESS lzo1x_1_compress
+
+static
+lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+#if 0 && defined(__GNUC__) && defined(__i386__)
+ register const lzo_byte *ip __asm__("%esi");
+#else
+ register const lzo_byte *ip;
+#endif
+ lzo_byte *op;
+ const lzo_byte * const in_end = in + in_len;
+ const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5;
+ const lzo_byte *ii;
+ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
+
+ op = out;
+ ip = in;
+ ii = ip;
+
+ ip += 4;
+ for (;;)
+ {
+#if 0 && defined(__GNUC__) && defined(__i386__)
+ register const lzo_byte *m_pos __asm__("%edi");
+#else
+ register const lzo_byte *m_pos;
+#endif
+ lzo_moff_t m_off;
+ lzo_uint m_len;
+ lzo_uint dindex;
+
+ DINDEX1(dindex,ip);
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+#if 1
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ DINDEX2(dindex,ip);
+#endif
+ GINDEX(m_pos,m_off,dict,dindex,in);
+ if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
+ goto literal;
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+ goto literal;
+
+try_match:
+#if 1 && defined(LZO_UNALIGNED_OK_2)
+ if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
+#else
+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
+#endif
+ {
+ }
+ else
+ {
+ if (m_pos[2] == ip[2])
+ {
+#if 0
+ if (m_off <= M2_MAX_OFFSET)
+ goto match;
+ if (lit <= 3)
+ goto match;
+ if (lit == 3)
+ {
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
+ *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
+ goto code_match;
+ }
+ if (m_pos[3] == ip[3])
+#endif
+ goto match;
+ }
+ else
+ {
+#if 0
+#if 0
+ if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3)
+#else
+ if (m_off <= M1_MAX_OFFSET && lit == 3)
+#endif
+ {
+ register lzo_uint t;
+
+ t = lit;
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(t);
+ do *op++ = *ii++; while (--t > 0);
+ assert(ii == ip);
+ m_off -= 1;
+ *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+ ip += 2;
+ goto match_done;
+ }
+#endif
+ }
+ }
+
+literal:
+ UPDATE_I(dict,0,dindex,ip,in);
+ ++ip;
+ if (ip >= ip_end)
+ break;
+ continue;
+
+match:
+ UPDATE_I(dict,0,dindex,ip,in);
+ if (pd(ip,ii) > 0)
+ {
+ register lzo_uint t = pd(ip,ii);
+
+ if (t <= 3)
+ {
+ assert(op - 2 > out);
+ op[-2] |= LZO_BYTE(t);
+ }
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ register lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ assert(ii == ip);
+ ip += 3;
+ if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ ||
+ m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++
+#ifdef LZO1Y
+ || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++
+ || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++
+#endif
+ )
+ {
+ --ip;
+ m_len = ip - ii;
+ assert(m_len >= 3); assert(m_len <= M2_MAX_LEN);
+
+ if (m_off <= M2_MAX_OFFSET)
+ {
+ m_off -= 1;
+#if defined(LZO1X)
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = LZO_BYTE(m_off >> 3);
+#elif defined(LZO1Y)
+ *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+#endif
+ }
+ else if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ goto m3_m4_offset;
+ }
+ else
+#if defined(LZO1X)
+ {
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ goto m3_m4_offset;
+ }
+#elif defined(LZO1Y)
+ goto m4_match;
+#endif
+ }
+ else
+ {
+ {
+ const lzo_byte *end = in_end;
+ const lzo_byte *m = m_pos + M2_MAX_LEN + 1;
+ while (ip < end && *m == *ip)
+ m++, ip++;
+ m_len = (ip - ii);
+ }
+ assert(m_len > M2_MAX_LEN);
+
+ if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ if (m_len <= 33)
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ else
+ {
+ m_len -= 33;
+ *op++ = M3_MARKER | 0;
+ goto m3_m4_len;
+ }
+ }
+ else
+ {
+#if defined(LZO1Y)
+m4_match:
+#endif
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ else
+ {
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
+m3_m4_len:
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ assert(m_len > 0);
+ *op++ = LZO_BYTE(m_len);
+ }
+ }
+
+m3_m4_offset:
+ *op++ = LZO_BYTE((m_off & 63) << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+ }
+
+#if 0
+match_done:
+#endif
+ ii = ip;
+ if (ip >= ip_end)
+ break;
+ }
+
+ *out_len = op - out;
+ return pd(in_end,ii);
+}
+
+LZO_PUBLIC(int)
+DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ lzo_byte *op = out;
+ lzo_uint t;
+
+#if defined(__LZO_QUERY_COMPRESS)
+ if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t));
+#endif
+
+ if (in_len <= M2_MAX_LEN + 5)
+ t = in_len;
+ else
+ {
+ t = do_compress(in,in_len,op,out_len,wrkmem);
+ op += *out_len;
+ }
+
+ if (t > 0)
+ {
+ const lzo_byte *ii = in + in_len - t;
+
+ if (op == out && t <= 238)
+ *op++ = LZO_BYTE(17 + t);
+ else if (t <= 3)
+ op[-2] |= LZO_BYTE(t);
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = op - out;
+ return LZO_E_OK;
+}
+
+#undef do_compress
+#undef DO_COMPRESS
+#undef LZO_HASH
+
+#undef LZO_TEST_DECOMPRESS_OVERRUN
+#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT
+#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT
+#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN)
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LOOKBEHIND
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
+#else
+# define TEST_LOOKBEHIND(m_pos,op) ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+# define TEST_IP (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+# define HAVE_TEST_IP
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP
+#endif
+
+#undef __COPY4
+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
+
+#undef COPY4
+#if defined(LZO_UNALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4(dst,src)
+#elif defined(LZO_ALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_byte *op;
+ register const lzo_byte *ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_byte *dict_end;
+#else
+ register const lzo_byte *m_pos;
+#endif
+
+ const lzo_byte * const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_byte * const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(__LZO_QUERY_DECOMPRESS)
+ if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0);
+#endif
+
+#if defined(COPY_DICT)
+ if (dict)
+ {
+ if (dict_len > M4_MAX_OFFSET)
+ {
+ dict += dict_len - M4_MAX_OFFSET;
+ dict_len = M4_MAX_OFFSET;
+ }
+ dict_end = dict + dict_len;
+ }
+ else
+ {
+ dict_len = 0;
+ dict_end = NULL;
+ }
+#endif
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ COPY4(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ COPY4(op,ip);
+ op += 4; ip += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *ip++; while (--t > 0);
+ }
+ else
+ do *op++ = *ip++; while (--t > 0);
+ }
+#if !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4)
+ {
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+ do *op++ = *ip++; while (--t > 0);
+ }
+#endif
+
+first_literal_run:
+
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(3);
+ t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ while (TEST_IP && TEST_OP)
+ {
+match:
+ if (t >= 64)
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+ m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ m_off = t & 0x1f;
+ if (m_off >= 0x1c)
+ m_off = last_m_off;
+ else
+ {
+ m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+ }
+ t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ {
+ lzo_uint off = t & 0x1f;
+ m_pos = op;
+ if (off >= 0x1c)
+ {
+ assert(last_m_off > 0);
+ m_pos -= last_m_off;
+ }
+ else
+ {
+ off = 1 + (off << 6) + (*ip++ >> 2);
+ m_pos -= off;
+ last_m_off = off;
+ }
+ }
+ t = (t >> 5) - 1;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+ {
+ lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ m_pos = op - off;
+ last_m_off = off;
+ }
+#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos = op - 1;
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+ ip += 2;
+ }
+ else if (t >= 16)
+ {
+#if defined(COPY_DICT)
+ m_off = (t & 8) << 11;
+#else
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+#endif
+ t &= 7;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+ m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_off == 0)
+ goto eof_found;
+ m_off += 0x4000;
+#if defined(LZO1Z)
+ last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+ m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+#if defined(LZO1Z)
+ last_m_off = op - m_pos;
+#endif
+#endif
+ }
+ else
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(2);
+ t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = 1 + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); NEED_OP(2);
+ *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+ }
+
+#if defined(COPY_DICT)
+
+ NEED_OP(t+3-1);
+ t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+ TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+ {
+ assert((op - m_pos) >= 4);
+#else
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+ {
+#endif
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+ }
+ else
+#endif
+ {
+copy_match:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+ t = ip[-1] & 3;
+#else
+ t = ip[-2] & 3;
+#endif
+ if (t == 0)
+ break;
+
+match_next:
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ t = *ip++;
+ }
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = op - out;
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#define LZO_TEST_DECOMPRESS_OVERRUN
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress_safe
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN)
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LOOKBEHIND
+#undef NEED_IP
+#undef NEED_OP
+#undef HAVE_TEST_IP
+#undef HAVE_TEST_OP
+#undef HAVE_NEED_IP
+#undef HAVE_NEED_OP
+#undef HAVE_ANY_IP
+#undef HAVE_ANY_OP
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
+#else
+# define TEST_LOOKBEHIND(m_pos,op) ((void) 0)
+#endif
+
+#if !defined(LZO_EOF_CODE) && !defined(TEST_IP)
+# define TEST_IP (ip < ip_end)
+#endif
+
+#if defined(TEST_IP)
+# define HAVE_TEST_IP
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP
+#endif
+
+#undef __COPY4
+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
+
+#undef COPY4
+#if defined(LZO_UNALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4(dst,src)
+#elif defined(LZO_ALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_byte *op;
+ register const lzo_byte *ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_byte *dict_end;
+#else
+ register const lzo_byte *m_pos;
+#endif
+
+ const lzo_byte * const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_byte * const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(__LZO_QUERY_DECOMPRESS)
+ if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0);
+#endif
+
+#if defined(COPY_DICT)
+ if (dict)
+ {
+ if (dict_len > M4_MAX_OFFSET)
+ {
+ dict += dict_len - M4_MAX_OFFSET;
+ dict_len = M4_MAX_OFFSET;
+ }
+ dict_end = dict + dict_len;
+ }
+ else
+ {
+ dict_len = 0;
+ dict_end = NULL;
+ }
+#endif
+
+ *out_len = 0;
+
+ op = out;
+ ip = in;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ COPY4(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ COPY4(op,ip);
+ op += 4; ip += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *ip++; while (--t > 0);
+ }
+ else
+ do *op++ = *ip++; while (--t > 0);
+ }
+#if !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4)
+ {
+ *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
+ do *op++ = *ip++; while (--t > 0);
+ }
+#endif
+
+first_literal_run:
+
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(3);
+ t = 3; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ while (TEST_IP && TEST_OP)
+ {
+match:
+ if (t >= 64)
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1X)
+ m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ m_off = t & 0x1f;
+ if (m_off >= 0x1c)
+ m_off = last_m_off;
+ else
+ {
+ m_off = 1 + (m_off << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+ }
+ t = (t >> 5) - 1;
+#endif
+#else
+#if defined(LZO1X)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+#elif defined(LZO1Y)
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 3;
+ m_pos -= *ip++ << 2;
+ t = (t >> 4) - 3;
+#elif defined(LZO1Z)
+ {
+ lzo_uint off = t & 0x1f;
+ m_pos = op;
+ if (off >= 0x1c)
+ {
+ assert(last_m_off > 0);
+ m_pos -= last_m_off;
+ }
+ else
+ {
+ off = 1 + (off << 6) + (*ip++ >> 2);
+ m_pos -= off;
+ last_m_off = off;
+ }
+ }
+ t = (t >> 5) - 1;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#else
+#if defined(LZO1Z)
+ {
+ lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
+ m_pos = op - off;
+ last_m_off = off;
+ }
+#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos = op - 1;
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+#endif
+ ip += 2;
+ }
+ else if (t >= 16)
+ {
+#if defined(COPY_DICT)
+ m_off = (t & 8) << 11;
+#else
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+#endif
+ t &= 7;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off += (ip[0] << 6) + (ip[1] >> 2);
+#else
+ m_off += (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_off == 0)
+ goto eof_found;
+ m_off += 0x4000;
+#if defined(LZO1Z)
+ last_m_off = m_off;
+#endif
+#else
+#if defined(LZO1Z)
+ m_pos -= (ip[0] << 6) + (ip[1] >> 2);
+#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos -= (* (const lzo_ushortp) ip) >> 2;
+#else
+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+#endif
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+#if defined(LZO1Z)
+ last_m_off = op - m_pos;
+#endif
+#endif
+ }
+ else
+ {
+#if defined(COPY_DICT)
+#if defined(LZO1Z)
+ m_off = 1 + (t << 6) + (*ip++ >> 2);
+ last_m_off = m_off;
+#else
+ m_off = 1 + (t >> 2) + (*ip++ << 2);
+#endif
+ NEED_OP(2);
+ t = 2; COPY_DICT(t,m_off)
+#else
+#if defined(LZO1Z)
+ t = 1 + (t << 6) + (*ip++ >> 2);
+ m_pos = op - t;
+ last_m_off = t;
+#else
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+#endif
+ TEST_LOOKBEHIND(m_pos,out); NEED_OP(2);
+ *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+ }
+
+#if defined(COPY_DICT)
+
+ NEED_OP(t+3-1);
+ t += 3-1; COPY_DICT(t,m_off)
+
+#else
+
+ TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
+ {
+ assert((op - m_pos) >= 4);
+#else
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
+ {
+#endif
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ } while (t >= 4);
+ if (t > 0) do *op++ = *m_pos++; while (--t > 0);
+ }
+ else
+#endif
+ {
+copy_match:
+ *op++ = *m_pos++; *op++ = *m_pos++;
+ do *op++ = *m_pos++; while (--t > 0);
+ }
+
+#endif
+
+match_done:
+#if defined(LZO1Z)
+ t = ip[-1] & 3;
+#else
+ t = ip[-2] & 3;
+#endif
+ if (t == 0)
+ break;
+
+match_next:
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ t = *ip++;
+ }
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = op - out;
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+
+#if defined(HAVE_NEED_IP)
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+/***** End of minilzo.c *****/
+
diff --git a/3rdParty/LibVNC/src/libvncclient/minilzo.h b/3rdParty/LibVNC/src/libvncclient/minilzo.h
new file mode 100644
index 0000000..e3270f9
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/minilzo.h
@@ -0,0 +1,100 @@
+/* minilzo.h -- mini subset of the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ * the full LZO package can be found at
+ * http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __MINILZO_H
+#define __MINILZO_H
+
+#define MINILZO_VERSION 0x1080
+
+#ifdef __LZOCONF_H
+# error "you cannot use both LZO and miniLZO"
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "lzoconf.h"
+
+#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
+# error "version mismatch in header files"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+#define LZO1X_MEM_DECOMPRESS (0)
+
+
+/* compression */
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
diff --git a/3rdParty/LibVNC/src/libvncclient/rfbproto.c b/3rdParty/LibVNC/src/libvncclient/rfbproto.c
new file mode 100644
index 0000000..33307d2
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/rfbproto.c
@@ -0,0 +1,2123 @@
+/*
+ * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * rfbproto.c - functions to deal with client side of RFB protocol.
+ */
+
+#ifdef __STRICT_ANSI__
+#define _BSD_SOURCE
+#define _POSIX_SOURCE
+#endif
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#else
+#define strncasecmp _strnicmp
+#endif
+#include <errno.h>
+#ifndef WIN32
+#include <pwd.h>
+#endif
+#include <rfb/rfbclient.h>
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+#include <zlib.h>
+#ifdef __CHECKER__
+#undef Z_NULL
+#define Z_NULL NULL
+#endif
+#endif
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+#include <jpeglib.h>
+#endif
+#include <stdarg.h>
+#include <time.h>
+
+#include "minilzo.h"
+#include "tls.h"
+
+/*
+ * rfbClientLog prints a time-stamped message to the log file (stderr).
+ */
+
+rfbBool rfbEnableClientLogging=TRUE;
+
+static void
+rfbDefaultClientLog(const char *format, ...)
+{
+ va_list args;
+ char buf[256];
+ time_t log_clock;
+
+ if(!rfbEnableClientLogging)
+ return;
+
+ va_start(args, format);
+
+ time(&log_clock);
+ strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
+ fprintf(stderr, "%s", buf);
+
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+
+ va_end(args);
+}
+
+rfbClientLogProc rfbClientLog=rfbDefaultClientLog;
+rfbClientLogProc rfbClientErr=rfbDefaultClientLog;
+
+/* extensions */
+
+rfbClientProtocolExtension* rfbClientExtensions = NULL;
+
+void rfbClientRegisterExtension(rfbClientProtocolExtension* e)
+{
+ e->next = rfbClientExtensions;
+ rfbClientExtensions = e;
+}
+
+/* client data */
+
+void rfbClientSetClientData(rfbClient* client, void* tag, void* data)
+{
+ rfbClientData* clientData = client->clientData;
+
+ while(clientData && clientData->tag != tag)
+ clientData = clientData->next;
+ if(clientData == NULL) {
+ clientData = calloc(sizeof(rfbClientData), 1);
+ clientData->next = client->clientData;
+ client->clientData = clientData;
+ clientData->tag = tag;
+ }
+
+ clientData->data = data;
+}
+
+void* rfbClientGetClientData(rfbClient* client, void* tag)
+{
+ rfbClientData* clientData = client->clientData;
+
+ while(clientData) {
+ if(clientData->tag == tag)
+ return clientData->data;
+ clientData = clientData->next;
+ }
+
+ return NULL;
+}
+
+/* messages */
+
+static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) {
+ int i,j;
+
+#define FILL_RECT(BPP) \
+ for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \
+ for(i=x;i<x+w;i++) \
+ ((uint##BPP##_t*)client->frameBuffer)[j+i]=colour;
+
+ switch(client->format.bitsPerPixel) {
+ case 8: FILL_RECT(8); break;
+ case 16: FILL_RECT(16); break;
+ case 32: FILL_RECT(32); break;
+ default:
+ rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
+ }
+}
+
+static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) {
+ int j;
+
+#define COPY_RECT(BPP) \
+ { \
+ int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \
+ for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \
+ memcpy(client->frameBuffer + j, buffer, rs); \
+ buffer += rs; \
+ } \
+ }
+
+ switch(client->format.bitsPerPixel) {
+ case 8: COPY_RECT(8); break;
+ case 16: COPY_RECT(16); break;
+ case 32: COPY_RECT(32); break;
+ default:
+ rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
+ }
+}
+
+/* TODO: test */
+static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) {
+ int i,j;
+
+#define COPY_RECT_FROM_RECT(BPP) \
+ { \
+ uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \
+ if (dest_y < src_y) { \
+ for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \
+ if (dest_x < src_x) { \
+ for(i = dest_x; i < dest_x+w; i++) { \
+ ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
+ } \
+ } else { \
+ for(i = dest_x+w-1; i >= dest_x; i--) { \
+ ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
+ } \
+ } \
+ } \
+ } else { \
+ for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \
+ if (dest_x < src_x) { \
+ for(i = dest_x; i < dest_x+w; i++) { \
+ ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
+ } \
+ } else { \
+ for(i = dest_x+w-1; i >= dest_x; i--) { \
+ ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \
+ } \
+ } \
+ } \
+ } \
+ }
+
+ switch(client->format.bitsPerPixel) {
+ case 8: COPY_RECT_FROM_RECT(8); break;
+ case 16: COPY_RECT_FROM_RECT(16); break;
+ case 32: COPY_RECT_FROM_RECT(32); break;
+ default:
+ rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel);
+ }
+}
+
+static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh);
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh);
+
+static long ReadCompactLen (rfbClient* client);
+
+static void JpegInitSource(j_decompress_ptr cinfo);
+static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
+static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
+static void JpegTermSource(j_decompress_ptr cinfo);
+static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData,
+ int compressedLen);
+#endif
+static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh);
+static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh);
+#endif
+
+/*
+ * Server Capability Functions
+ */
+rfbBool
+SupportsClient2Server(rfbClient* client, int messageType)
+{
+ return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
+}
+
+rfbBool
+SupportsServer2Client(rfbClient* client, int messageType)
+{
+ return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE);
+}
+
+void
+SetClient2Server(rfbClient* client, int messageType)
+{
+ client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
+}
+
+void
+SetServer2Client(rfbClient* client, int messageType)
+{
+ client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8));
+}
+
+void
+ClearClient2Server(rfbClient* client, int messageType)
+{
+ client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
+}
+
+void
+ClearServer2Client(rfbClient* client, int messageType)
+{
+ client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8)));
+}
+
+
+void
+DefaultSupportedMessages(rfbClient* client)
+{
+ memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages));
+
+ /* Default client supported messages (universal RFB 3.3 protocol) */
+ SetClient2Server(client, rfbSetPixelFormat);
+ /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */
+ SetClient2Server(client, rfbSetEncodings);
+ SetClient2Server(client, rfbFramebufferUpdateRequest);
+ SetClient2Server(client, rfbKeyEvent);
+ SetClient2Server(client, rfbPointerEvent);
+ SetClient2Server(client, rfbClientCutText);
+ /* technically, we only care what we can *send* to the server
+ * but, we set Server2Client Just in case it ever becomes useful
+ */
+ SetServer2Client(client, rfbFramebufferUpdate);
+ SetServer2Client(client, rfbSetColourMapEntries);
+ SetServer2Client(client, rfbBell);
+ SetServer2Client(client, rfbServerCutText);
+}
+
+void
+DefaultSupportedMessagesUltraVNC(rfbClient* client)
+{
+ DefaultSupportedMessages(client);
+ SetClient2Server(client, rfbFileTransfer);
+ SetClient2Server(client, rfbSetScale);
+ SetClient2Server(client, rfbSetServerInput);
+ SetClient2Server(client, rfbSetSW);
+ SetClient2Server(client, rfbTextChat);
+ SetClient2Server(client, rfbPalmVNCSetScaleFactor);
+ /* technically, we only care what we can *send* to the server */
+ SetServer2Client(client, rfbResizeFrameBuffer);
+ SetServer2Client(client, rfbPalmVNCReSizeFrameBuffer);
+ SetServer2Client(client, rfbFileTransfer);
+ SetServer2Client(client, rfbTextChat);
+}
+
+
+void
+DefaultSupportedMessagesTightVNC(rfbClient* client)
+{
+ DefaultSupportedMessages(client);
+ SetClient2Server(client, rfbFileTransfer);
+ SetClient2Server(client, rfbSetServerInput);
+ SetClient2Server(client, rfbSetSW);
+ /* SetClient2Server(client, rfbTextChat); */
+ /* technically, we only care what we can *send* to the server */
+ SetServer2Client(client, rfbFileTransfer);
+ SetServer2Client(client, rfbTextChat);
+}
+
+#ifndef WIN32
+static rfbBool
+IsUnixSocket(const char *name)
+{
+ struct stat sb;
+ if(stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK)
+ return TRUE;
+ return FALSE;
+}
+#endif
+
+/*
+ * ConnectToRFBServer.
+ */
+
+rfbBool
+ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
+{
+ unsigned int host;
+
+ if (client->serverPort==-1) {
+ /* serverHost is a file recorded by vncrec. */
+ const char* magic="vncLog0.0";
+ char buffer[10];
+ rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec));
+ client->vncRec = rec;
+
+ rec->file = fopen(client->serverHost,"rb");
+ rec->tv.tv_sec = 0;
+ rec->readTimestamp = FALSE;
+ rec->doNotSleep = FALSE;
+
+ if (!rec->file) {
+ rfbClientLog("Could not open %s.\n",client->serverHost);
+ return FALSE;
+ }
+ setbuf(rec->file,NULL);
+ fread(buffer,1,strlen(magic),rec->file);
+ if (strncmp(buffer,magic,strlen(magic))) {
+ rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost);
+ fclose(rec->file);
+ return FALSE;
+ }
+ client->sock = -1;
+ return TRUE;
+ }
+
+#ifndef WIN32
+ if(IsUnixSocket(hostname))
+ /* serverHost is a UNIX socket. */
+ client->sock = ConnectClientToUnixSock(hostname);
+ else
+#endif
+ {
+ /* serverHost is a hostname */
+ if (!StringToIPAddr(hostname, &host)) {
+ rfbClientLog("Couldn't convert '%s' to host address\n", hostname);
+ return FALSE;
+ }
+ client->sock = ConnectClientToTcpAddr(host, port);
+ }
+
+ if (client->sock < 0) {
+ rfbClientLog("Unable to connect to VNC server\n");
+ return FALSE;
+ }
+
+ return SetNonBlocking(client->sock);
+}
+
+/*
+ * ConnectToRFBRepeater.
+ */
+
+rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort)
+{
+ unsigned int host;
+ rfbProtocolVersionMsg pv;
+ int major,minor;
+ char tmphost[250];
+
+ if (!StringToIPAddr(repeaterHost, &host)) {
+ rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost);
+ return FALSE;
+ }
+
+ client->sock = ConnectClientToTcpAddr(host, repeaterPort);
+
+ if (client->sock < 0) {
+ rfbClientLog("Unable to connect to VNC repeater\n");
+ return FALSE;
+ }
+
+ if (!SetNonBlocking(client->sock))
+ return FALSE;
+
+ if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg))
+ return FALSE;
+ pv[sz_rfbProtocolVersionMsg] = 0;
+
+ /* UltraVNC repeater always report version 000.000 to identify itself */
+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) {
+ rfbClientLog("Not a valid VNC repeater (%s)\n",pv);
+ return FALSE;
+ }
+
+ rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor);
+
+ snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort);
+ if (!WriteToRFBServer(client, tmphost, sizeof(tmphost)))
+ return FALSE;
+
+ return TRUE;
+}
+
+extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
+extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key);
+
+rfbBool
+rfbHandleAuthResult(rfbClient* client)
+{
+ uint32_t authResult=0, reasonLen=0;
+ char *reason=NULL;
+
+ if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE;
+
+ authResult = rfbClientSwap32IfLE(authResult);
+
+ switch (authResult) {
+ case rfbVncAuthOK:
+ rfbClientLog("VNC authentication succeeded\n");
+ return TRUE;
+ break;
+ case rfbVncAuthFailed:
+ if (client->major==3 && client->minor>7)
+ {
+ /* we have an error following */
+ if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
+ reasonLen = rfbClientSwap32IfLE(reasonLen);
+ reason = malloc(reasonLen+1);
+ if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
+ reason[reasonLen]=0;
+ rfbClientLog("VNC connection failed: %s\n",reason);
+ free(reason);
+ return FALSE;
+ }
+ rfbClientLog("VNC authentication failed\n");
+ return FALSE;
+ case rfbVncAuthTooMany:
+ rfbClientLog("VNC authentication failed - too many tries\n");
+ return FALSE;
+ }
+
+ rfbClientLog("Unknown VNC authentication result: %d\n",
+ (int)authResult);
+ return FALSE;
+}
+
+static void
+ReadReason(rfbClient* client)
+{
+ uint32_t reasonLen;
+ char *reason;
+
+ /* we have an error following */
+ if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return;
+ reasonLen = rfbClientSwap32IfLE(reasonLen);
+ reason = malloc(reasonLen+1);
+ if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return; }
+ reason[reasonLen]=0;
+ rfbClientLog("VNC connection failed: %s\n",reason);
+ free(reason);
+}
+
+static rfbBool
+ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth)
+{
+ uint8_t count=0;
+ uint8_t loop=0;
+ uint8_t flag=0;
+ uint8_t tAuth[256];
+ char buf1[500],buf2[10];
+ uint32_t authScheme;
+
+ if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
+
+ if (count==0)
+ {
+ rfbClientLog("List of security types is ZERO, expecting an error to follow\n");
+ ReadReason(client);
+ return FALSE;
+ }
+ if (count>sizeof(tAuth))
+ {
+ rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth));
+ return FALSE;
+ }
+
+ rfbClientLog("We have %d security types to read\n", count);
+ authScheme=0;
+ /* now, we have a list of available security types to read ( uint8_t[] ) */
+ for (loop=0;loop<count;loop++)
+ {
+ if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE;
+ rfbClientLog("%d) Received security type %d\n", loop, tAuth[loop]);
+ if (flag) continue;
+ if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth || tAuth[loop]==rfbMSLogon ||
+ (!subAuth && (tAuth[loop]==rfbTLS || tAuth[loop]==rfbVeNCrypt)))
+ {
+ if (!subAuth && client->clientAuthSchemes)
+ {
+ int i;
+ for (i=0;client->clientAuthSchemes[i];i++)
+ {
+ if (client->clientAuthSchemes[i]==(uint32_t)tAuth[loop])
+ {
+ flag++;
+ authScheme=tAuth[loop];
+ break;
+ }
+ }
+ }
+ else
+ {
+ flag++;
+ authScheme=tAuth[loop];
+ }
+ if (flag)
+ {
+ rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
+ /* send back a single byte indicating which security type to use */
+ if (!WriteToRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE;
+ }
+ }
+ }
+ if (authScheme==0)
+ {
+ memset(buf1, 0, sizeof(buf1));
+ for (loop=0;loop<count;loop++)
+ {
+ if (strlen(buf1)>=sizeof(buf1)-1) break;
+ snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]);
+ strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1);
+ }
+ rfbClientLog("Unknown authentication scheme from VNC server: %s\n",
+ buf1);
+ return FALSE;
+ }
+ *result = authScheme;
+ return TRUE;
+}
+
+static rfbBool
+HandleVncAuth(rfbClient *client)
+{
+ uint8_t challenge[CHALLENGESIZE];
+ char *passwd=NULL;
+ int i;
+
+ if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
+
+ if (client->serverPort!=-1) { /* if not playing a vncrec file */
+ if (client->GetPassword)
+ passwd = client->GetPassword(client);
+
+ if ((!passwd) || (strlen(passwd) == 0)) {
+ rfbClientLog("Reading password failed\n");
+ return FALSE;
+ }
+ if (strlen(passwd) > 8) {
+ passwd[8] = '\0';
+ }
+
+ rfbClientEncryptBytes(challenge, passwd);
+
+ /* Lose the password from memory */
+ for (i = strlen(passwd); i >= 0; i--) {
+ passwd[i] = '\0';
+ }
+ free(passwd);
+
+ if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
+ }
+
+ /* Handle the SecurityResult message */
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
+ return TRUE;
+}
+
+static void
+FreeUserCredential(rfbCredential *cred)
+{
+ if (cred->userCredential.username) free(cred->userCredential.username);
+ if (cred->userCredential.password) free(cred->userCredential.password);
+ free(cred);
+}
+
+static rfbBool
+HandlePlainAuth(rfbClient *client)
+{
+ uint32_t ulen, ulensw;
+ uint32_t plen, plensw;
+ rfbCredential *cred;
+
+ if (!client->GetCredential)
+ {
+ rfbClientLog("GetCredential callback is not set.\n");
+ return FALSE;
+ }
+ cred = client->GetCredential(client, rfbCredentialTypeUser);
+ if (!cred)
+ {
+ rfbClientLog("Reading credential failed\n");
+ return FALSE;
+ }
+
+ ulen = (cred->userCredential.username ? strlen(cred->userCredential.username) : 0);
+ ulensw = rfbClientSwap32IfLE(ulen);
+ plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0);
+ plensw = rfbClientSwap32IfLE(plen);
+ if (!WriteToRFBServer(client, (char *)&ulensw, 4) ||
+ !WriteToRFBServer(client, (char *)&plensw, 4))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
+ if (ulen > 0)
+ {
+ if (!WriteToRFBServer(client, cred->userCredential.username, ulen))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
+ }
+ if (plen > 0)
+ {
+ if (!WriteToRFBServer(client, cred->userCredential.password, plen))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
+ }
+
+ FreeUserCredential(cred);
+
+ /* Handle the SecurityResult message */
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
+ return TRUE;
+}
+
+/* Simple 64bit big integer arithmetic implementation */
+/* (x + y) % m, works even if (x + y) > 64bit */
+#define rfbAddM64(x,y,m) ((x+y)%m+(x+y<x?(((uint64_t)-1)%m+1)%m:0))
+/* (x * y) % m */
+static uint64_t
+rfbMulM64(uint64_t x, uint64_t y, uint64_t m)
+{
+ uint64_t r;
+ for(r=0;x>0;x>>=1)
+ {
+ if (x&1) r=rfbAddM64(r,y,m);
+ y=rfbAddM64(y,y,m);
+ }
+ return r;
+}
+/* (x ^ y) % m */
+static uint64_t
+rfbPowM64(uint64_t b, uint64_t e, uint64_t m)
+{
+ uint64_t r;
+ for(r=1;e>0;e>>=1)
+ {
+ if(e&1) r=rfbMulM64(r,b,m);
+ b=rfbMulM64(b,b,m);
+ }
+ return r;
+}
+
+static rfbBool
+HandleMSLogonAuth(rfbClient *client)
+{
+ uint64_t gen, mod, resp, priv, pub, key;
+ uint8_t username[256], password[64];
+ rfbCredential *cred;
+
+ if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE;
+ if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE;
+ if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE;
+ gen = rfbClientSwap64IfLE(gen);
+ mod = rfbClientSwap64IfLE(mod);
+ resp = rfbClientSwap64IfLE(resp);
+
+ if (!client->GetCredential)
+ {
+ rfbClientLog("GetCredential callback is not set.\n");
+ return FALSE;
+ }
+ rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\
+ "Use it only with SSH tunnel or trusted network.\n");
+ cred = client->GetCredential(client, rfbCredentialTypeUser);
+ if (!cred)
+ {
+ rfbClientLog("Reading credential failed\n");
+ return FALSE;
+ }
+
+ memset(username, 0, sizeof(username));
+ strncpy((char *)username, cred->userCredential.username, sizeof(username));
+ memset(password, 0, sizeof(password));
+ strncpy((char *)password, cred->userCredential.password, sizeof(password));
+ FreeUserCredential(cred);
+
+ srand(time(NULL));
+ priv = ((uint64_t)rand())<<32;
+ priv |= (uint64_t)rand();
+
+ pub = rfbPowM64(gen, priv, mod);
+ key = rfbPowM64(resp, priv, mod);
+ pub = rfbClientSwap64IfLE(pub);
+ key = rfbClientSwap64IfLE(key);
+
+ rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key);
+ rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key);
+
+ if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE;
+ if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE;
+ if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE;
+
+ /* Handle the SecurityResult message */
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * SetClientAuthSchemes.
+ */
+
+void
+SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size)
+{
+ int i;
+
+ if (client->clientAuthSchemes)
+ {
+ free(client->clientAuthSchemes);
+ client->clientAuthSchemes = NULL;
+ }
+ if (authSchemes)
+ {
+ if (size<0)
+ {
+ /* If size<0 we assume the passed-in list is also 0-terminate, so we
+ * calculate the size here */
+ for (size=0;authSchemes[size];size++) ;
+ }
+ client->clientAuthSchemes = (uint32_t*)malloc(sizeof(uint32_t)*(size+1));
+ for (i=0;i<size;i++)
+ client->clientAuthSchemes[i] = authSchemes[i];
+ client->clientAuthSchemes[size] = 0;
+ }
+}
+
+/*
+ * InitialiseRFBConnection.
+ */
+
+rfbBool
+InitialiseRFBConnection(rfbClient* client)
+{
+ rfbProtocolVersionMsg pv;
+ int major,minor;
+ uint32_t authScheme;
+ uint32_t subAuthScheme;
+ rfbClientInitMsg ci;
+
+ /* if the connection is immediately closed, don't report anything, so
+ that pmw's monitor can make test connections */
+
+ if (client->listenSpecified)
+ errorMessageOnReadFailure = FALSE;
+
+ if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
+ pv[sz_rfbProtocolVersionMsg]=0;
+
+ errorMessageOnReadFailure = TRUE;
+
+ pv[sz_rfbProtocolVersionMsg] = 0;
+
+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {
+ rfbClientLog("Not a valid VNC server (%s)\n",pv);
+ return FALSE;
+ }
+
+
+ DefaultSupportedMessages(client);
+ client->major = major;
+ client->minor = minor;
+
+ /* fall back to viewer supported version */
+ if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion))
+ client->minor = rfbProtocolMinorVersion;
+
+ /* UltraVNC uses minor codes 4 and 6 for the server */
+ if (major==3 && (minor==4 || minor==6)) {
+ rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv);
+ DefaultSupportedMessagesUltraVNC(client);
+ }
+
+ /* TightVNC uses minor codes 5 for the server */
+ if (major==3 && minor==5) {
+ rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv);
+ DefaultSupportedMessagesTightVNC(client);
+ }
+
+ /* we do not support > RFB3.8 */
+ if ((major==3 && minor>8) || major>3)
+ {
+ client->major=3;
+ client->minor=8;
+ }
+
+ rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n",
+ major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
+
+ sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor);
+
+ if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE;
+
+
+ /* 3.7 and onwards sends a # of security types first */
+ if (client->major==3 && client->minor > 6)
+ {
+ if (!ReadSupportedSecurityType(client, &authScheme, FALSE)) return FALSE;
+ }
+ else
+ {
+ if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE;
+ authScheme = rfbClientSwap32IfLE(authScheme);
+ }
+
+ rfbClientLog("Selected Security Scheme %d\n", authScheme);
+ client->authScheme = authScheme;
+
+ switch (authScheme) {
+
+ case rfbConnFailed:
+ ReadReason(client);
+ return FALSE;
+
+ case rfbNoAuth:
+ rfbClientLog("No authentication needed\n");
+
+ /* 3.8 and upwards sends a Security Result for rfbNoAuth */
+ if ((client->major==3 && client->minor > 7) || client->major>3)
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
+ break;
+
+ case rfbVncAuth:
+ if (!HandleVncAuth(client)) return FALSE;
+ break;
+
+ case rfbMSLogon:
+ if (!HandleMSLogonAuth(client)) return FALSE;
+ break;
+
+ case rfbTLS:
+#ifndef LIBVNCSERVER_WITH_CLIENT_TLS
+ rfbClientLog("TLS support was not compiled in\n");
+ return FALSE;
+#else
+ if (!HandleAnonTLSAuth(client)) return FALSE;
+ /* After the TLS session is established, sub auth types are expected.
+ * Note that all following reading/writing are through the TLS session from here.
+ */
+ if (!ReadSupportedSecurityType(client, &subAuthScheme, TRUE)) return FALSE;
+ client->subAuthScheme = subAuthScheme;
+
+ switch (subAuthScheme) {
+
+ case rfbConnFailed:
+ ReadReason(client);
+ return FALSE;
+
+ case rfbNoAuth:
+ rfbClientLog("No sub authentication needed\n");
+ /* 3.8 and upwards sends a Security Result for rfbNoAuth */
+ if ((client->major==3 && client->minor > 7) || client->major>3)
+ if (!rfbHandleAuthResult(client)) return FALSE;
+ break;
+
+ case rfbVncAuth:
+ if (!HandleVncAuth(client)) return FALSE;
+ break;
+
+ default:
+ rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n",
+ (int)subAuthScheme);
+ return FALSE;
+ }
+#endif
+
+ break;
+
+ case rfbVeNCrypt:
+#ifndef LIBVNCSERVER_WITH_CLIENT_TLS
+ rfbClientLog("TLS support was not compiled in\n");
+ return FALSE;
+#else
+ if (!HandleVeNCryptAuth(client)) return FALSE;
+
+ switch (client->subAuthScheme) {
+
+ case rfbVeNCryptTLSNone:
+ case rfbVeNCryptX509None:
+ rfbClientLog("No sub authentication needed\n");
+ if (!rfbHandleAuthResult(client)) return FALSE;
+ break;
+
+ case rfbVeNCryptTLSVNC:
+ case rfbVeNCryptX509VNC:
+ if (!HandleVncAuth(client)) return FALSE;
+ break;
+
+ case rfbVeNCryptTLSPlain:
+ case rfbVeNCryptX509Plain:
+ if (!HandlePlainAuth(client)) return FALSE;
+ break;
+
+ default:
+ rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n",
+ client->subAuthScheme);
+ return FALSE;
+ }
+#endif
+ break;
+
+ default:
+ rfbClientLog("Unknown authentication scheme from VNC server: %d\n",
+ (int)authScheme);
+ return FALSE;
+ }
+
+ ci.shared = (client->appData.shareDesktop ? 1 : 0);
+
+ if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE;
+
+ if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE;
+
+ client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth);
+ client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight);
+ client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax);
+ client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax);
+ client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax);
+ client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength);
+
+ client->desktopName = malloc(client->si.nameLength + 1);
+ if (!client->desktopName) {
+ rfbClientLog("Error allocating memory for desktop name, %lu bytes\n",
+ (unsigned long)client->si.nameLength);
+ return FALSE;
+ }
+
+ if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE;
+
+ client->desktopName[client->si.nameLength] = 0;
+
+ rfbClientLog("Desktop name \"%s\"\n",client->desktopName);
+
+ rfbClientLog("Connected to VNC server, using protocol version %d.%d\n",
+ client->major, client->minor);
+
+ rfbClientLog("VNC server default format:\n");
+ PrintPixelFormat(&client->si.format);
+
+ return TRUE;
+}
+
+
+/*
+ * SetFormatAndEncodings.
+ */
+
+rfbBool
+SetFormatAndEncodings(rfbClient* client)
+{
+ rfbSetPixelFormatMsg spf;
+ char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
+
+ rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
+ uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]);
+ int len = 0;
+ rfbBool requestCompressLevel = FALSE;
+ rfbBool requestQualityLevel = FALSE;
+ rfbBool requestLastRectEncoding = FALSE;
+ rfbClientProtocolExtension* e;
+
+ if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE;
+
+ spf.type = rfbSetPixelFormat;
+ spf.format = client->format;
+ spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax);
+ spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax);
+ spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax);
+
+ if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg))
+ return FALSE;
+
+
+ if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE;
+
+ se->type = rfbSetEncodings;
+ se->nEncodings = 0;
+
+ if (client->appData.encodingsString) {
+ const char *encStr = client->appData.encodingsString;
+ int encStrLen;
+ do {
+ const char *nextEncStr = strchr(encStr, ' ');
+ if (nextEncStr) {
+ encStrLen = nextEncStr - encStr;
+ nextEncStr++;
+ } else {
+ encStrLen = strlen(encStr);
+ }
+
+ if (strncasecmp(encStr,"raw",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
+ } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
+ requestLastRectEncoding = TRUE;
+ if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
+ requestCompressLevel = TRUE;
+ if (client->appData.enableJPEG)
+ requestQualityLevel = TRUE;
+#endif
+#endif
+ } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
+ if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
+ requestCompressLevel = TRUE;
+ } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex);
+ if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9)
+ requestCompressLevel = TRUE;
+ } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
+ } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
+ requestQualityLevel = TRUE;
+#endif
+ } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) {
+ /* There are 2 encodings used in 'ultra' */
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
+ } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
+ } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
+ } else {
+ rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr);
+ }
+
+ encStr = nextEncStr;
+ } while (encStr && se->nEncodings < MAX_ENCODINGS);
+
+ if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel +
+ rfbEncodingCompressLevel0);
+ }
+
+ if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
+ if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
+ client->appData.qualityLevel = 5;
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
+ rfbEncodingQualityLevel0);
+ }
+ }
+ else {
+ if (SameMachine(client->sock)) {
+ /* TODO:
+ if (!tunnelSpecified) {
+ */
+ rfbClientLog("Same machine: preferring raw encoding\n");
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw);
+ /*
+ } else {
+ rfbClientLog("Tunneling active: preferring tight encoding\n");
+ }
+ */
+ }
+
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight);
+ requestLastRectEncoding = TRUE;
+#endif
+#endif
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE);
+#endif
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE);
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE);
+
+ if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.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++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1);
+ }
+
+ if (client->appData.enableJPEG) {
+ if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9)
+ client->appData.qualityLevel = 5;
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel +
+ rfbEncodingQualityLevel0);
+ }
+ }
+
+
+
+ /* Remote Cursor Support (local to viewer) */
+ if (client->appData.useRemoteCursor) {
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor);
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor);
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos);
+ }
+
+ /* Keyboard State Encodings */
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState);
+
+ /* New Frame Buffer Size */
+ if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize);
+
+ /* Last Rect */
+ if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect);
+
+ /* Server Capabilities */
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages);
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings);
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity);
+
+
+ /* client extensions */
+ for(e = rfbClientExtensions; e; e = e->next)
+ if(e->encodings) {
+ int* enc;
+ for(enc = e->encodings; *enc; enc++)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc);
+ }
+
+ len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
+
+ se->nEncodings = rfbClientSwap16IfLE(se->nEncodings);
+
+ if (!WriteToRFBServer(client, buf, len)) return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * SendIncrementalFramebufferUpdateRequest.
+ */
+
+rfbBool
+SendIncrementalFramebufferUpdateRequest(rfbClient* client)
+{
+ return SendFramebufferUpdateRequest(client,
+ client->updateRect.x, client->updateRect.y,
+ client->updateRect.w, client->updateRect.h, TRUE);
+}
+
+
+/*
+ * SendFramebufferUpdateRequest.
+ */
+
+rfbBool
+SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental)
+{
+ rfbFramebufferUpdateRequestMsg fur;
+
+ if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE;
+
+ fur.type = rfbFramebufferUpdateRequest;
+ fur.incremental = incremental ? 1 : 0;
+ fur.x = rfbClientSwap16IfLE(x);
+ fur.y = rfbClientSwap16IfLE(y);
+ fur.w = rfbClientSwap16IfLE(w);
+ fur.h = rfbClientSwap16IfLE(h);
+
+ if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * SendScaleSetting.
+ */
+rfbBool
+SendScaleSetting(rfbClient* client,int scaleSetting)
+{
+ rfbSetScaleMsg ssm;
+
+ ssm.scale = scaleSetting;
+ ssm.pad = 0;
+
+ /* favor UltraVNC SetScale if both are supported */
+ if (SupportsClient2Server(client, rfbSetScale)) {
+ ssm.type = rfbSetScale;
+ if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
+ return FALSE;
+ }
+
+ if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) {
+ ssm.type = rfbPalmVNCSetScaleFactor;
+ if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * TextChatFunctions (UltraVNC)
+ * Extremely bandwidth friendly method of communicating with a user
+ * (Think HelpDesk type applications)
+ */
+
+rfbBool TextChatSend(rfbClient* client, char *text)
+{
+ rfbTextChatMsg chat;
+ int count = strlen(text);
+
+ if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = (uint32_t)count;
+ chat.length = rfbClientSwap32IfLE(chat.length);
+
+ if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg))
+ return FALSE;
+
+ if (count>0) {
+ if (!WriteToRFBServer(client, text, count))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+rfbBool TextChatOpen(rfbClient* client)
+{
+ rfbTextChatMsg chat;
+
+ if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = rfbClientSwap32IfLE(rfbTextChatOpen);
+ return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
+}
+
+rfbBool TextChatClose(rfbClient* client)
+{
+ rfbTextChatMsg chat;
+ if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = rfbClientSwap32IfLE(rfbTextChatClose);
+ return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
+}
+
+rfbBool TextChatFinish(rfbClient* client)
+{
+ rfbTextChatMsg chat;
+ if (!SupportsClient2Server(client, rfbTextChat)) return TRUE;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = rfbClientSwap32IfLE(rfbTextChatFinished);
+ return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE);
+}
+
+/*
+ * UltraVNC Server Input Disable
+ * Apparently, the remote client can *prevent* the local user from interacting with the display
+ * I would think this is extremely helpful when used in a HelpDesk situation
+ */
+rfbBool PermitServerInput(rfbClient* client, int enabled)
+{
+ rfbSetServerInputMsg msg;
+
+ if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE;
+ /* enabled==1, then server input from local keyboard is disabled */
+ msg.type = rfbSetServerInput;
+ msg.status = (enabled ? 1 : 0);
+ msg.pad = 0;
+ return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE);
+}
+
+
+/*
+ * SendPointerEvent.
+ */
+
+rfbBool
+SendPointerEvent(rfbClient* client,int x, int y, int buttonMask)
+{
+ rfbPointerEventMsg pe;
+
+ if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE;
+
+ pe.type = rfbPointerEvent;
+ pe.buttonMask = buttonMask;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
+ pe.x = rfbClientSwap16IfLE(x);
+ pe.y = rfbClientSwap16IfLE(y);
+ return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg);
+}
+
+
+/*
+ * SendKeyEvent.
+ */
+
+rfbBool
+SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down)
+{
+ rfbKeyEventMsg ke;
+
+ if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE;
+
+ ke.type = rfbKeyEvent;
+ ke.down = down ? 1 : 0;
+ ke.key = rfbClientSwap32IfLE(key);
+ return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg);
+}
+
+
+/*
+ * SendClientCutText.
+ */
+
+rfbBool
+SendClientCutText(rfbClient* client, char *str, int len)
+{
+ rfbClientCutTextMsg cct;
+
+ if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE;
+
+ cct.type = rfbClientCutText;
+ cct.length = rfbClientSwap32IfLE(len);
+ return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) &&
+ WriteToRFBServer(client, str, len));
+}
+
+
+
+/*
+ * HandleRFBServerMessage.
+ */
+
+rfbBool
+HandleRFBServerMessage(rfbClient* client)
+{
+ rfbServerToClientMsg msg;
+
+ if (client->serverPort==-1)
+ client->vncRec->readTimestamp = TRUE;
+ if (!ReadFromRFBServer(client, (char *)&msg, 1))
+ return FALSE;
+
+ switch (msg.type) {
+
+ case rfbSetColourMapEntries:
+ {
+ /* TODO:
+ int i;
+ uint16_t rgb[3];
+ XColor xc;
+
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbSetColourMapEntriesMsg - 1))
+ return FALSE;
+
+ msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
+ msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);
+
+ for (i = 0; i < msg.scme.nColours; i++) {
+ if (!ReadFromRFBServer(client, (char *)rgb, 6))
+ return FALSE;
+ xc.pixel = msg.scme.firstColour + i;
+ xc.red = rfbClientSwap16IfLE(rgb[0]);
+ xc.green = rfbClientSwap16IfLE(rgb[1]);
+ xc.blue = rfbClientSwap16IfLE(rgb[2]);
+ xc.flags = DoRed|DoGreen|DoBlue;
+ XStoreColor(dpy, cmap, &xc);
+ }
+ */
+
+ break;
+ }
+
+ case rfbFramebufferUpdate:
+ {
+ rfbFramebufferUpdateRectHeader rect;
+ int linesToRead;
+ int bytesPerLine;
+ int i;
+
+ if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
+ sz_rfbFramebufferUpdateMsg - 1))
+ return FALSE;
+
+ msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);
+
+ for (i = 0; i < msg.fu.nRects; i++) {
+ if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
+ return FALSE;
+
+ rect.encoding = rfbClientSwap32IfLE(rect.encoding);
+ if (rect.encoding == rfbEncodingLastRect)
+ break;
+
+ rect.r.x = rfbClientSwap16IfLE(rect.r.x);
+ rect.r.y = rfbClientSwap16IfLE(rect.r.y);
+ rect.r.w = rfbClientSwap16IfLE(rect.r.w);
+ rect.r.h = rfbClientSwap16IfLE(rect.r.h);
+
+
+ if (rect.encoding == rfbEncodingXCursor ||
+ rect.encoding == rfbEncodingRichCursor) {
+
+ if (!HandleCursorShape(client,
+ rect.r.x, rect.r.y, rect.r.w, rect.r.h,
+ rect.encoding)) {
+ return FALSE;
+ }
+ continue;
+ }
+
+ if (rect.encoding == rfbEncodingPointerPos) {
+ if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
+ return FALSE;
+ }
+ continue;
+ }
+
+ if (rect.encoding == rfbEncodingKeyboardLedState) {
+ /* OK! We have received a keyboard state message!!! */
+ client->KeyboardLedStateEnabled = 1;
+ if (client->HandleKeyboardLedState!=NULL)
+ client->HandleKeyboardLedState(client, rect.r.x, 0);
+ /* stash it for the future */
+ client->CurrentKeyboardLedState = rect.r.x;
+ continue;
+ }
+
+ if (rect.encoding == rfbEncodingNewFBSize) {
+ client->width = rect.r.w;
+ client->height = rect.r.h;
+ client->updateRect.x = client->updateRect.y = 0;
+ client->updateRect.w = client->width;
+ client->updateRect.h = client->height;
+ client->MallocFrameBuffer(client);
+ SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
+ rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
+ continue;
+ }
+
+ /* rect.r.w=byte count */
+ if (rect.encoding == rfbEncodingSupportedMessages) {
+ int loop;
+ if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
+ return FALSE;
+
+ /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
+ /* currently ignored by this library */
+
+ rfbClientLog("client2server supported messages (bit flags)\n");
+ for (loop=0;loop<32;loop+=8)
+ rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
+ client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1],
+ client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
+ client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
+ client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);
+
+ rfbClientLog("server2client supported messages (bit flags)\n");
+ for (loop=0;loop<32;loop+=8)
+ rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
+ client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1],
+ client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
+ client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
+ client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
+ continue;
+ }
+
+ /* rect.r.w=byte count, rect.r.h=# of encodings */
+ if (rect.encoding == rfbEncodingSupportedEncodings) {
+ char *buffer;
+ buffer = malloc(rect.r.w);
+ if (!ReadFromRFBServer(client, buffer, rect.r.w))
+ {
+ free(buffer);
+ return FALSE;
+ }
+
+ /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
+ /* currently ignored by this library */
+ free(buffer);
+ continue;
+ }
+
+ /* rect.r.w=byte count */
+ if (rect.encoding == rfbEncodingServerIdentity) {
+ char *buffer;
+ buffer = malloc(rect.r.w+1);
+ if (!ReadFromRFBServer(client, buffer, rect.r.w))
+ {
+ free(buffer);
+ return FALSE;
+ }
+ buffer[rect.r.w]=0; /* null terminate, just in case */
+ rfbClientLog("Connected to Server \"%s\"\n", buffer);
+ free(buffer);
+ continue;
+ }
+
+ /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */
+ if (rect.encoding != rfbEncodingUltraZip)
+ {
+ if ((rect.r.x + rect.r.w > client->width) ||
+ (rect.r.y + rect.r.h > client->height))
+ {
+ rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
+ rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+ return FALSE;
+ }
+
+ /* UltraVNC with scaling, will send rectangles with a zero W or H
+ *
+ if ((rect.encoding != rfbEncodingTight) &&
+ (rect.r.h * rect.r.w == 0))
+ {
+ rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+ continue;
+ }
+ */
+
+ /* If RichCursor encoding is used, we should prevent collisions
+ between framebuffer updates and cursor drawing operations. */
+ client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+ }
+
+ switch (rect.encoding) {
+
+ case rfbEncodingRaw: {
+ int y=rect.r.y, h=rect.r.h;
+
+ bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
+ linesToRead = RFB_BUFFER_SIZE / bytesPerLine;
+
+ while (h > 0) {
+ if (linesToRead > h)
+ linesToRead = h;
+
+ if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
+ return FALSE;
+
+ CopyRectangle(client, (uint8_t *)client->buffer,
+ rect.r.x, y, rect.r.w,linesToRead);
+
+ h -= linesToRead;
+ y += linesToRead;
+
+ }
+ } break;
+
+ case rfbEncodingCopyRect:
+ {
+ rfbCopyRect cr;
+
+ if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
+ return FALSE;
+
+ cr.srcX = rfbClientSwap16IfLE(cr.srcX);
+ cr.srcY = rfbClientSwap16IfLE(cr.srcY);
+
+ /* If RichCursor encoding is used, we should extend our
+ "cursor lock area" (previously set to destination
+ rectangle) to the source rectangle as well. */
+ client->SoftCursorLockArea(client,
+ cr.srcX, cr.srcY, rect.r.w, rect.r.h);
+
+ if (client->GotCopyRect != NULL) {
+ client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
+ rect.r.x, rect.r.y);
+ } else
+ CopyRectangleFromRectangle(client,
+ cr.srcX, cr.srcY, rect.r.w, rect.r.h,
+ rect.r.x, rect.r.y);
+
+ break;
+ }
+
+ case rfbEncodingRRE:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+
+ case rfbEncodingCoRRE:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+
+ case rfbEncodingHextile:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+
+ case rfbEncodingUltra:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+ case rfbEncodingUltraZip:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ case rfbEncodingZlib:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ case rfbEncodingTight:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 32:
+ if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ break;
+ }
+#endif
+ case rfbEncodingZRLE:
+ /* Fail safe for ZYWRLE unsupport VNC server. */
+ client->appData.qualityLevel = 9;
+ /* fall through */
+ case rfbEncodingZYWRLE:
+ {
+ switch (client->format.bitsPerPixel) {
+ case 8:
+ if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ case 16:
+ if (client->si.format.greenMax > 0x1F) {
+ if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ } else {
+ if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ }
+ break;
+ case 32:
+ {
+ uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
+ (client->format.greenMax<<client->format.greenShift)|
+ (client->format.blueMax<<client->format.blueShift);
+ if ((client->format.bigEndian && (maxColor&0xff)==0) ||
+ (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
+ if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
+ if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
+ if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
+ return FALSE;
+ break;
+ }
+ }
+ break;
+ }
+
+#endif
+
+ default:
+ {
+ rfbBool handled = FALSE;
+ rfbClientProtocolExtension* e;
+
+ for(e = rfbClientExtensions; !handled && e; e = e->next)
+ if(e->handleEncoding && e->handleEncoding(client, &rect))
+ handled = TRUE;
+
+ if(!handled) {
+ rfbClientLog("Unknown rect encoding %d\n",
+ (int)rect.encoding);
+ return FALSE;
+ }
+ }
+ }
+
+ /* Now we may discard "soft cursor locks". */
+ client->SoftCursorUnlockScreen(client);
+
+ client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+ }
+
+ if (!SendIncrementalFramebufferUpdateRequest(client))
+ return FALSE;
+
+ if (client->FinishedFrameBufferUpdate)
+ client->FinishedFrameBufferUpdate(client);
+
+ break;
+ }
+
+ case rfbBell:
+ {
+ client->Bell(client);
+
+ break;
+ }
+
+ case rfbServerCutText:
+ {
+ char *buffer;
+
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbServerCutTextMsg - 1))
+ return FALSE;
+
+ msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);
+
+ buffer = malloc(msg.sct.length+1);
+
+ if (!ReadFromRFBServer(client, buffer, msg.sct.length))
+ return FALSE;
+
+ buffer[msg.sct.length] = 0;
+
+ if (client->GotXCutText)
+ client->GotXCutText(client, buffer, msg.sct.length);
+
+ free(buffer);
+
+ break;
+ }
+
+ case rfbTextChat:
+ {
+ char *buffer=NULL;
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbTextChatMsg- 1))
+ return FALSE;
+ msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
+ switch(msg.tc.length) {
+ case rfbTextChatOpen:
+ rfbClientLog("Received TextChat Open\n");
+ if (client->HandleTextChat!=NULL)
+ client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
+ break;
+ case rfbTextChatClose:
+ rfbClientLog("Received TextChat Close\n");
+ if (client->HandleTextChat!=NULL)
+ client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
+ break;
+ case rfbTextChatFinished:
+ rfbClientLog("Received TextChat Finished\n");
+ if (client->HandleTextChat!=NULL)
+ client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
+ break;
+ default:
+ buffer=malloc(msg.tc.length+1);
+ if (!ReadFromRFBServer(client, buffer, msg.tc.length))
+ {
+ free(buffer);
+ return FALSE;
+ }
+ /* Null Terminate <just in case> */
+ buffer[msg.tc.length]=0;
+ rfbClientLog("Received TextChat \"%s\"\n", buffer);
+ if (client->HandleTextChat!=NULL)
+ client->HandleTextChat(client, (int)msg.tc.length, buffer);
+ free(buffer);
+ break;
+ }
+ break;
+ }
+
+ case rfbResizeFrameBuffer:
+ {
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbResizeFrameBufferMsg -1))
+ return FALSE;
+ client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth);
+ client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth);
+ client->updateRect.x = client->updateRect.y = 0;
+ client->updateRect.w = client->width;
+ client->updateRect.h = client->height;
+ client->MallocFrameBuffer(client);
+ SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
+ rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
+ break;
+ }
+
+ case rfbPalmVNCReSizeFrameBuffer:
+ {
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbPalmVNCReSizeFrameBufferMsg -1))
+ return FALSE;
+ client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
+ client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
+ client->updateRect.x = client->updateRect.y = 0;
+ client->updateRect.w = client->width;
+ client->updateRect.h = client->height;
+ client->MallocFrameBuffer(client);
+ SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
+ rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
+ break;
+ }
+
+ default:
+ {
+ rfbBool handled = FALSE;
+ rfbClientProtocolExtension* e;
+
+ for(e = rfbClientExtensions; !handled && e; e = e->next)
+ if(e->handleMessage && e->handleMessage(client, &msg))
+ handled = TRUE;
+
+ if(!handled) {
+ char buffer[256];
+ rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
+ ReadFromRFBServer(client, buffer, 256);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+#define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++)
+
+#define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
+ ((uint8_t*)&(pix))[1] = *(ptr)++)
+
+#define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \
+ ((uint8_t*)&(pix))[1] = *(ptr)++, \
+ ((uint8_t*)&(pix))[2] = *(ptr)++, \
+ ((uint8_t*)&(pix))[3] = *(ptr)++)
+
+/* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also
+ expands its arguments if they are macros */
+
+#define CONCAT2(a,b) a##b
+#define CONCAT2E(a,b) CONCAT2(a,b)
+#define CONCAT3(a,b,c) a##b##c
+#define CONCAT3E(a,b,c) CONCAT3(a,b,c)
+
+#define BPP 8
+#include "rre.c"
+#include "corre.c"
+#include "hextile.c"
+#include "ultra.c"
+#include "zlib.c"
+#include "tight.c"
+#include "zrle.c"
+#undef BPP
+#define BPP 16
+#include "rre.c"
+#include "corre.c"
+#include "hextile.c"
+#include "ultra.c"
+#include "zlib.c"
+#include "tight.c"
+#include "zrle.c"
+#define REALBPP 15
+#include "zrle.c"
+#undef BPP
+#define BPP 32
+#include "rre.c"
+#include "corre.c"
+#include "hextile.c"
+#include "ultra.c"
+#include "zlib.c"
+#include "tight.c"
+#include "zrle.c"
+#define REALBPP 24
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP 8
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP -8
+#include "zrle.c"
+#undef BPP
+
+
+/*
+ * PrintPixelFormat.
+ */
+
+void
+PrintPixelFormat(rfbPixelFormat *format)
+{
+ if (format->bitsPerPixel == 1) {
+ rfbClientLog(" Single bit per pixel.\n");
+ rfbClientLog(
+ " %s significant bit in each byte is leftmost on the screen.\n",
+ (format->bigEndian ? "Most" : "Least"));
+ } else {
+ rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel);
+ if (format->bitsPerPixel != 8) {
+ rfbClientLog(" %s significant byte first in each pixel.\n",
+ (format->bigEndian ? "Most" : "Least"));
+ }
+ if (format->trueColour) {
+ rfbClientLog(" TRUE colour: max red %d green %d blue %d"
+ ", shift red %d green %d blue %d\n",
+ format->redMax, format->greenMax, format->blueMax,
+ format->redShift, format->greenShift, format->blueShift);
+ } else {
+ rfbClientLog(" Colour map (not true colour).\n");
+ }
+ }
+}
+
+/* avoid name clashes with LibVNCServer */
+
+#define rfbEncryptBytes rfbClientEncryptBytes
+#define rfbEncryptBytes2 rfbClientEncryptBytes2
+#define rfbDes rfbClientDes
+#define rfbDesKey rfbClientDesKey
+#define rfbUseKey rfbClientUseKey
+#define rfbCPKey rfbClientCPKey
+
+#include "../libvncserver/vncauth.c"
+#include "../libvncserver/d3des.c"
diff --git a/3rdParty/LibVNC/src/libvncclient/rre.c b/3rdParty/LibVNC/src/libvncclient/rre.c
new file mode 100644
index 0000000..94158c9
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/rre.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * rre.c - handle RRE encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles an RRE
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#define HandleRREBPP CONCAT2E(HandleRRE,BPP)
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+
+static rfbBool
+HandleRREBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbRREHeader hdr;
+ int i;
+ CARDBPP pix;
+ rfbRectangle subrect;
+
+ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader))
+ return FALSE;
+
+ hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects);
+
+ if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix)))
+ return FALSE;
+
+ FillRectangle(client, rx, ry, rw, rh, pix);
+
+ for (i = 0; i < hdr.nSubrects; i++) {
+ if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix)))
+ return FALSE;
+
+ if (!ReadFromRFBServer(client, (char *)&subrect, sz_rfbRectangle))
+ return FALSE;
+
+ subrect.x = rfbClientSwap16IfLE(subrect.x);
+ subrect.y = rfbClientSwap16IfLE(subrect.y);
+ subrect.w = rfbClientSwap16IfLE(subrect.w);
+ subrect.h = rfbClientSwap16IfLE(subrect.h);
+
+ FillRectangle(client, rx+subrect.x, ry+subrect.y, subrect.w, subrect.h, pix);
+ }
+
+ return TRUE;
+}
+
+#undef CARDBPP
diff --git a/3rdParty/LibVNC/src/libvncclient/sockets.c b/3rdParty/LibVNC/src/libvncclient/sockets.c
new file mode 100644
index 0000000..598dd39
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/sockets.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * sockets.c - functions to deal with sockets.
+ */
+
+#ifdef __STRICT_ANSI__
+#define _BSD_SOURCE
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <rfb/rfbclient.h>
+#ifdef WIN32
+#undef SOCKET
+#include <winsock2.h>
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define close closesocket
+#define read(sock,buf,len) recv(sock,buf,len,0)
+#define write(sock,buf,len) send(sock,buf,len,0)
+#define socklen_t int
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+#include "tls.h"
+
+void PrintInHex(char *buf, int len);
+
+rfbBool errorMessageOnReadFailure = TRUE;
+
+/*
+ * ReadFromRFBServer is called whenever we want to read some data from the RFB
+ * server. It is non-trivial for two reasons:
+ *
+ * 1. For efficiency it performs some intelligent buffering, avoiding invoking
+ * the read() system call too often. For small chunks of data, it simply
+ * copies the data out of an internal buffer. For large amounts of data it
+ * reads directly into the buffer provided by the caller.
+ *
+ * 2. Whenever read() would block, it invokes the Xt event dispatching
+ * mechanism to process X events. In fact, this is the only place these
+ * events are processed, as there is no XtAppMainLoop in the program.
+ */
+
+rfbBool
+ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
+{
+#undef DEBUG_READ_EXACT
+#ifdef DEBUG_READ_EXACT
+ char* oout=out;
+ int nn=n;
+ rfbClientLog("ReadFromRFBServer %d bytes\n",n);
+#endif
+ if (client->serverPort==-1) {
+ /* vncrec playing */
+ rfbVNCRec* rec = client->vncRec;
+ struct timeval tv;
+
+ if (rec->readTimestamp) {
+ rec->readTimestamp = FALSE;
+ if (!fread(&tv,sizeof(struct timeval),1,rec->file))
+ return FALSE;
+
+ tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec);
+ tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec);
+
+ if (rec->tv.tv_sec!=0 && !rec->doNotSleep) {
+ struct timeval diff;
+ diff.tv_sec = tv.tv_sec - rec->tv.tv_sec;
+ diff.tv_usec = tv.tv_usec - rec->tv.tv_usec;
+ if(diff.tv_usec<0) {
+ diff.tv_sec--;
+ diff.tv_usec+=1000000;
+ }
+#ifndef __MINGW32__
+ sleep (diff.tv_sec);
+ usleep (diff.tv_usec);
+#else
+ Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000);
+#endif
+ }
+
+ rec->tv=tv;
+ }
+
+ return (fread(out,1,n,rec->file)<0?FALSE:TRUE);
+ }
+
+ if (n <= client->buffered) {
+ memcpy(out, client->bufoutptr, n);
+ client->bufoutptr += n;
+ client->buffered -= n;
+#ifdef DEBUG_READ_EXACT
+ goto hexdump;
+#endif
+ return TRUE;
+ }
+
+ memcpy(out, client->bufoutptr, client->buffered);
+
+ out += client->buffered;
+ n -= client->buffered;
+
+ client->bufoutptr = client->buf;
+ client->buffered = 0;
+
+ if (n <= RFB_BUF_SIZE) {
+
+ while (client->buffered < n) {
+ int i;
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ if (client->tlsSession) {
+ i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered);
+ } else {
+#endif
+ i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered);
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ }
+#endif
+ if (i <= 0) {
+ if (i < 0) {
+#ifdef WIN32
+ errno=WSAGetLastError();
+#endif
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ /* TODO:
+ ProcessXtEvents();
+ */
+ i = 0;
+ } else {
+ rfbClientErr("read (%d: %s)\n",errno,strerror(errno));
+ return FALSE;
+ }
+ } else {
+ if (errorMessageOnReadFailure) {
+ rfbClientLog("VNC server closed connection\n");
+ }
+ return FALSE;
+ }
+ }
+ client->buffered += i;
+ }
+
+ memcpy(out, client->bufoutptr, n);
+ client->bufoutptr += n;
+ client->buffered -= n;
+
+ } else {
+
+ while (n > 0) {
+ int i;
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ if (client->tlsSession) {
+ i = ReadFromTLS(client, out, n);
+ } else {
+#endif
+ i = read(client->sock, out, n);
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ }
+#endif
+ if (i <= 0) {
+ if (i < 0) {
+#ifdef WIN32
+ errno=WSAGetLastError();
+#endif
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ /* TODO:
+ ProcessXtEvents();
+ */
+ i = 0;
+ } else {
+ rfbClientErr("read (%s)\n",strerror(errno));
+ return FALSE;
+ }
+ } else {
+ if (errorMessageOnReadFailure) {
+ rfbClientLog("VNC server closed connection\n");
+ }
+ return FALSE;
+ }
+ }
+ out += i;
+ n -= i;
+ }
+ }
+
+#ifdef DEBUG_READ_EXACT
+hexdump:
+ { int ii;
+ for(ii=0;ii<nn;ii++)
+ fprintf(stderr,"%02x ",(unsigned char)oout[ii]);
+ fprintf(stderr,"\n");
+ }
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Write an exact number of bytes, and don't return until you've sent them.
+ */
+
+rfbBool
+WriteToRFBServer(rfbClient* client, char *buf, int n)
+{
+ fd_set fds;
+ int i = 0;
+ int j;
+
+ if (client->serverPort==-1)
+ return TRUE; /* vncrec playing */
+
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ if (client->tlsSession) {
+ /* WriteToTLS() will guarantee either everything is written, or error/eof returns */
+ i = WriteToTLS(client, buf, n);
+ if (i <= 0) return FALSE;
+
+ return TRUE;
+ }
+#endif
+
+ while (i < n) {
+ j = write(client->sock, buf + i, (n - i));
+ if (j <= 0) {
+ if (j < 0) {
+ if (errno == EWOULDBLOCK ||
+#ifdef LIBVNCSERVER_ENOENT_WORKAROUND
+ errno == ENOENT ||
+#endif
+ errno == EAGAIN) {
+ FD_ZERO(&fds);
+ FD_SET(client->sock,&fds);
+
+ if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) {
+ rfbClientErr("select\n");
+ return FALSE;
+ }
+ j = 0;
+ } else {
+ rfbClientErr("write\n");
+ return FALSE;
+ }
+ } else {
+ rfbClientLog("write failed\n");
+ return FALSE;
+ }
+ }
+ i += j;
+ }
+ return TRUE;
+}
+
+
+
+static int initSockets() {
+#ifdef WIN32
+ WSADATA trash;
+ static rfbBool WSAinitted=FALSE;
+ if(!WSAinitted) {
+ int i=WSAStartup(MAKEWORD(2,0),&trash);
+ if(i!=0) {
+ rfbClientErr("Couldn't init Windows Sockets\n");
+ return 0;
+ }
+ WSAinitted=TRUE;
+ }
+#endif
+ return 1;
+}
+
+/*
+ * ConnectToTcpAddr connects to the given TCP port.
+ */
+
+int
+ConnectClientToTcpAddr(unsigned int host, int port)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int one = 1;
+
+ if (!initSockets())
+ return -1;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = host;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+#ifdef WIN32
+ errno=WSAGetLastError();
+#endif
+ rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ rfbClientErr("ConnectToTcpAddr: connect\n");
+ close(sock);
+ return -1;
+ }
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbClientErr("ConnectToTcpAddr: setsockopt\n");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int
+ConnectClientToUnixSock(const char *sockFile)
+{
+#ifdef WIN32
+ rfbClientErr("Windows doesn't support UNIX sockets\n");
+ return -1;
+#else
+ int sock;
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, sockFile);
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ rfbClientErr("ConnectToUnixSock: socket (%s)\n",strerror(errno));
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) < 0) {
+ rfbClientErr("ConnectToUnixSock: connect\n");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+#endif
+}
+
+
+
+/*
+ * FindFreeTcpPort tries to find unused TCP port in the range
+ * (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure.
+ */
+
+int
+FindFreeTcpPort(void)
+{
+ int sock, port;
+ struct sockaddr_in addr;
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (!initSockets())
+ return -1;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ rfbClientErr(": FindFreeTcpPort: socket\n");
+ return 0;
+ }
+
+ for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) {
+ addr.sin_port = htons((unsigned short)port);
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
+ close(sock);
+ return port;
+ }
+ }
+
+ close(sock);
+ return 0;
+}
+
+
+/*
+ * ListenAtTcpPort starts listening at the given TCP port.
+ */
+
+int
+ListenAtTcpPort(int port)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int one = 1;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (!initSockets())
+ return -1;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ rfbClientErr("ListenAtTcpPort: socket\n");
+ return -1;
+ }
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&one, sizeof(one)) < 0) {
+ rfbClientErr("ListenAtTcpPort: setsockopt\n");
+ close(sock);
+ return -1;
+ }
+
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ rfbClientErr("ListenAtTcpPort: bind\n");
+ close(sock);
+ return -1;
+ }
+
+ if (listen(sock, 5) < 0) {
+ rfbClientErr("ListenAtTcpPort: listen\n");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/*
+ * AcceptTcpConnection accepts a TCP connection.
+ */
+
+int
+AcceptTcpConnection(int listenSock)
+{
+ int sock;
+ struct sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+ int one = 1;
+
+ sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen);
+ if (sock < 0) {
+ rfbClientErr("AcceptTcpConnection: accept\n");
+ return -1;
+ }
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbClientErr("AcceptTcpConnection: setsockopt\n");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/*
+ * SetNonBlocking sets a socket into non-blocking mode.
+ */
+
+rfbBool
+SetNonBlocking(int sock)
+{
+#ifndef __MINGW32__
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbClientErr("AcceptTcpConnection: fcntl\n");
+ return FALSE;
+ }
+#else
+ rfbClientErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED\n");
+#endif
+ return TRUE;
+}
+
+
+/*
+ * StringToIPAddr - convert a host string to an IP address.
+ */
+
+rfbBool
+StringToIPAddr(const char *str, unsigned int *addr)
+{
+ struct hostent *hp;
+
+ if (strcmp(str,"") == 0) {
+ *addr = htonl(INADDR_LOOPBACK); /* local */
+ return TRUE;
+ }
+
+ *addr = inet_addr(str);
+
+ if (*addr != -1)
+ return TRUE;
+
+ if (!initSockets())
+ return -1;
+
+ hp = gethostbyname(str);
+
+ if (hp) {
+ *addr = *(unsigned int *)hp->h_addr;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Test if the other end of a socket is on the same machine.
+ */
+
+rfbBool
+SameMachine(int sock)
+{
+ struct sockaddr_in peeraddr, myaddr;
+ socklen_t 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);
+}
+
+
+/*
+ * Print out the contents of a packet for debugging.
+ */
+
+void
+PrintInHex(char *buf, int len)
+{
+ int i, j;
+ char c, str[17];
+
+ str[16] = 0;
+
+ rfbClientLog("ReadExact: ");
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16 == 0) && (i != 0)) {
+ rfbClientLog(" ");
+ }
+ c = buf[i];
+ str[i % 16] = (((c > 31) && (c < 127)) ? c : '.');
+ rfbClientLog("%02x ",(unsigned char)c);
+ if ((i % 4) == 3)
+ rfbClientLog(" ");
+ if ((i % 16) == 15)
+ {
+ rfbClientLog("%s\n",str);
+ }
+ }
+ if ((i % 16) != 0)
+ {
+ for (j = i % 16; j < 16; j++)
+ {
+ rfbClientLog(" ");
+ if ((j % 4) == 3) rfbClientLog(" ");
+ }
+ str[i % 16] = 0;
+ rfbClientLog("%s\n",str);
+ }
+
+ fflush(stderr);
+}
+
+int WaitForMessage(rfbClient* client,unsigned int usecs)
+{
+ fd_set fds;
+ struct timeval timeout;
+ int num;
+
+ if (client->serverPort==-1)
+ /* playing back vncrec file */
+ return 1;
+
+ timeout.tv_sec=(usecs/1000000);
+ timeout.tv_usec=(usecs%1000000);
+
+ FD_ZERO(&fds);
+ FD_SET(client->sock,&fds);
+
+ num=select(client->sock+1, &fds, NULL, NULL, &timeout);
+ if(num<0)
+ rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno));
+
+ return num;
+}
+
+
diff --git a/3rdParty/LibVNC/src/libvncclient/tight.c b/3rdParty/LibVNC/src/libvncclient/tight.c
new file mode 100644
index 0000000..2f9fbab
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/tight.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2000, 2001 Const 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.
+ */
+
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+
+/*
+ * tight.c - handle ``tight'' encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple
+ * times by rfbproto.c, each time with a different definition of the
+ * macro BPP. For each value of BPP, this file defines a function
+ * which handles a tight-encoded rectangle with BPP bits per pixel.
+ *
+ */
+
+#define TIGHT_MIN_TO_COMPRESS 12
+
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+#define filterPtrBPP CONCAT2E(filterPtr,BPP)
+
+#define HandleTightBPP CONCAT2E(HandleTight,BPP)
+#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP)
+#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP)
+#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP)
+#define FilterCopyBPP CONCAT2E(FilterCopy,BPP)
+#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP)
+#define FilterGradientBPP CONCAT2E(FilterGradient,BPP)
+
+#if BPP != 8
+#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP)
+#endif
+
+#ifndef RGB_TO_PIXEL
+
+#define RGB_TO_PIXEL(bpp,r,g,b) \
+ (((CARD##bpp)(r) & client->format.redMax) << client->format.redShift | \
+ ((CARD##bpp)(g) & client->format.greenMax) << client->format.greenShift | \
+ ((CARD##bpp)(b) & client->format.blueMax) << client->format.blueShift)
+
+#define RGB24_TO_PIXEL(bpp,r,g,b) \
+ ((((CARD##bpp)(r) & 0xFF) * client->format.redMax + 127) / 255 \
+ << client->format.redShift | \
+ (((CARD##bpp)(g) & 0xFF) * client->format.greenMax + 127) / 255 \
+ << client->format.greenShift | \
+ (((CARD##bpp)(b) & 0xFF) * client->format.blueMax + 127) / 255 \
+ << client->format.blueShift)
+
+#define RGB24_TO_PIXEL32(r,g,b) \
+ (((uint32_t)(r) & 0xFF) << client->format.redShift | \
+ ((uint32_t)(g) & 0xFF) << client->format.greenShift | \
+ ((uint32_t)(b) & 0xFF) << client->format.blueShift)
+
+#endif
+
+/* Type declarations */
+
+typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *);
+
+/* Prototypes */
+
+static int InitFilterCopyBPP (rfbClient* client, int rw, int rh);
+static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh);
+static int InitFilterGradientBPP (rfbClient* client, int rw, int rh);
+static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
+static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
+static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer);
+
+#if BPP != 8
+static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h);
+#endif
+
+/* Definitions */
+
+static rfbBool
+HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ CARDBPP fill_colour;
+ uint8_t comp_ctl;
+ uint8_t filter_id;
+ filterPtrBPP filterFn;
+ z_streamp zs;
+ char *buffer2;
+ int err, stream_id, compressedLen, bitsPixel;
+ int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes;
+
+ if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1))
+ return FALSE;
+
+ /* Flush zlib streams if we are told by the server to do so. */
+ for (stream_id = 0; stream_id < 4; stream_id++) {
+ if ((comp_ctl & 1) && client->zlibStreamActive[stream_id]) {
+ if (inflateEnd (&client->zlibStream[stream_id]) != Z_OK &&
+ client->zlibStream[stream_id].msg != NULL)
+ rfbClientLog("inflateEnd: %s\n", client->zlibStream[stream_id].msg);
+ client->zlibStreamActive[stream_id] = FALSE;
+ }
+ comp_ctl >>= 1;
+ }
+
+ /* Handle solid rectangles. */
+ if (comp_ctl == rfbTightFill) {
+#if BPP == 32
+ if (client->format.depth == 24 && client->format.redMax == 0xFF &&
+ client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) {
+ if (!ReadFromRFBServer(client, client->buffer, 3))
+ return FALSE;
+ fill_colour = RGB24_TO_PIXEL32(client->buffer[0], client->buffer[1], client->buffer[2]);
+ } else {
+ if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour)))
+ return FALSE;
+ }
+#else
+ if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour)))
+ return FALSE;
+#endif
+
+ FillRectangle(client, rx, ry, rw, rh, fill_colour);
+
+ return TRUE;
+ }
+
+#if BPP == 8
+ if (comp_ctl == rfbTightJpeg) {
+ rfbClientLog("Tight encoding: JPEG is not supported in 8 bpp mode.\n");
+ return FALSE;
+ }
+#else
+ if (comp_ctl == rfbTightJpeg) {
+ return DecompressJpegRectBPP(client, rx, ry, rw, rh);
+ }
+#endif
+
+ /* Quit on unsupported subencoding value. */
+ if (comp_ctl > rfbTightMaxSubencoding) {
+ rfbClientLog("Tight encoding: bad subencoding value received.\n");
+ return FALSE;
+ }
+
+ /*
+ * Here primary compression mode handling begins.
+ * Data was processed with optional filter + zlib compression.
+ */
+
+ /* First, we should identify a filter to use. */
+ if ((comp_ctl & rfbTightExplicitFilter) != 0) {
+ if (!ReadFromRFBServer(client, (char*)&filter_id, 1))
+ return FALSE;
+
+ switch (filter_id) {
+ case rfbTightFilterCopy:
+ filterFn = FilterCopyBPP;
+ bitsPixel = InitFilterCopyBPP(client, rw, rh);
+ break;
+ case rfbTightFilterPalette:
+ filterFn = FilterPaletteBPP;
+ bitsPixel = InitFilterPaletteBPP(client, rw, rh);
+ break;
+ case rfbTightFilterGradient:
+ filterFn = FilterGradientBPP;
+ bitsPixel = InitFilterGradientBPP(client, rw, rh);
+ break;
+ default:
+ rfbClientLog("Tight encoding: unknown filter code received.\n");
+ return FALSE;
+ }
+ } else {
+ filterFn = FilterCopyBPP;
+ bitsPixel = InitFilterCopyBPP(client, rw, rh);
+ }
+ if (bitsPixel == 0) {
+ rfbClientLog("Tight encoding: error receiving palette.\n");
+ return FALSE;
+ }
+
+ /* Determine if the data should be decompressed or just copied. */
+ rowSize = (rw * bitsPixel + 7) / 8;
+ if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) {
+ if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize))
+ return FALSE;
+
+ buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4];
+ filterFn(client, rh, (CARDBPP *)buffer2);
+
+ CopyRectangle(client, (uint8_t *)buffer2, rx, ry, rw, rh);
+
+ return TRUE;
+ }
+
+ /* Read the length (1..3 bytes) of compressed data following. */
+ compressedLen = (int)ReadCompactLen(client);
+ if (compressedLen <= 0) {
+ rfbClientLog("Incorrect data received from the server.\n");
+ return FALSE;
+ }
+
+ /* Now let's initialize compression stream if needed. */
+ stream_id = comp_ctl & 0x03;
+ zs = &client->zlibStream[stream_id];
+ if (!client->zlibStreamActive[stream_id]) {
+ zs->zalloc = Z_NULL;
+ zs->zfree = Z_NULL;
+ zs->opaque = Z_NULL;
+ err = inflateInit(zs);
+ if (err != Z_OK) {
+ if (zs->msg != NULL)
+ rfbClientLog("InflateInit error: %s.\n", zs->msg);
+ return FALSE;
+ }
+ client->zlibStreamActive[stream_id] = TRUE;
+ }
+
+ /* Read, decode and draw actual pixel data in a loop. */
+
+ bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC;
+ buffer2 = &client->buffer[bufferSize];
+ if (rowSize > bufferSize) {
+ /* Should be impossible when RFB_BUFFER_SIZE >= 16384 */
+ rfbClientLog("Internal error: incorrect buffer size.\n");
+ return FALSE;
+ }
+
+ rowsProcessed = 0;
+ extraBytes = 0;
+
+ while (compressedLen > 0) {
+ if (compressedLen > ZLIB_BUFFER_SIZE)
+ portionLen = ZLIB_BUFFER_SIZE;
+ else
+ portionLen = compressedLen;
+
+ if (!ReadFromRFBServer(client, (char*)client->zlib_buffer, portionLen))
+ return FALSE;
+
+ compressedLen -= portionLen;
+
+ zs->next_in = (Bytef *)client->zlib_buffer;
+ zs->avail_in = portionLen;
+
+ do {
+ zs->next_out = (Bytef *)&client->buffer[extraBytes];
+ zs->avail_out = bufferSize - extraBytes;
+
+ err = inflate(zs, Z_SYNC_FLUSH);
+ if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */
+ break;
+ if (err != Z_OK && err != Z_STREAM_END) {
+ if (zs->msg != NULL) {
+ rfbClientLog("Inflate error: %s.\n", zs->msg);
+ } else {
+ rfbClientLog("Inflate error: %d.\n", err);
+ }
+ return FALSE;
+ }
+
+ numRows = (bufferSize - zs->avail_out) / rowSize;
+
+ filterFn(client, numRows, (CARDBPP *)buffer2);
+
+ extraBytes = bufferSize - zs->avail_out - numRows * rowSize;
+ if (extraBytes > 0)
+ memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes);
+
+ CopyRectangle(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows);
+
+ rowsProcessed += numRows;
+ }
+ while (zs->avail_out == 0);
+ }
+
+ if (rowsProcessed != rh) {
+ rfbClientLog("Incorrect number of scan lines after decompression.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Filter stuff.
+ *
+ */
+
+static int
+InitFilterCopyBPP (rfbClient* client, int rw, int rh)
+{
+ client->rectWidth = rw;
+
+#if BPP == 32
+ if (client->format.depth == 24 && client->format.redMax == 0xFF &&
+ client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) {
+ client->cutZeros = TRUE;
+ return 24;
+ } else {
+ client->cutZeros = FALSE;
+ }
+#endif
+
+ return BPP;
+}
+
+static void
+FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst)
+{
+
+#if BPP == 32
+ int x, y;
+
+ if (client->cutZeros) {
+ for (y = 0; y < numRows; y++) {
+ for (x = 0; x < client->rectWidth; x++) {
+ dst[y*client->rectWidth+x] =
+ RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3],
+ client->buffer[(y*client->rectWidth+x)*3+1],
+ client->buffer[(y*client->rectWidth+x)*3+2]);
+ }
+ }
+ return;
+ }
+#endif
+
+ memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8));
+}
+
+static int
+InitFilterGradientBPP (rfbClient* client, int rw, int rh)
+{
+ int bits;
+
+ bits = InitFilterCopyBPP(client, rw, rh);
+ if (client->cutZeros)
+ memset(client->tightPrevRow, 0, rw * 3);
+ else
+ memset(client->tightPrevRow, 0, rw * 3 * sizeof(uint16_t));
+
+ return bits;
+}
+
+#if BPP == 32
+
+static void
+FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst)
+{
+ int x, y, c;
+ uint8_t thisRow[2048*3];
+ uint8_t pix[3];
+ int est[3];
+
+ for (y = 0; y < numRows; y++) {
+
+ /* First pixel in a row */
+ for (c = 0; c < 3; c++) {
+ pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c];
+ thisRow[c] = pix[c];
+ }
+ dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
+
+ /* Remaining pixels of a row */
+ for (x = 1; x < client->rectWidth; x++) {
+ for (c = 0; c < 3; c++) {
+ est[c] = (int)client->tightPrevRow[x*3+c] + (int)pix[c] -
+ (int)client->tightPrevRow[(x-1)*3+c];
+ if (est[c] > 0xFF) {
+ est[c] = 0xFF;
+ } else if (est[c] < 0x00) {
+ est[c] = 0x00;
+ }
+ pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c];
+ thisRow[x*3+c] = pix[c];
+ }
+ dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
+ }
+
+ memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3);
+ }
+}
+
+#endif
+
+static void
+FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst)
+{
+ int x, y, c;
+ CARDBPP *src = (CARDBPP *)client->buffer;
+ uint16_t *thatRow = (uint16_t *)client->tightPrevRow;
+ uint16_t thisRow[2048*3];
+ uint16_t pix[3];
+ uint16_t max[3];
+ int shift[3];
+ int est[3];
+
+#if BPP == 32
+ if (client->cutZeros) {
+ FilterGradient24(client, numRows, dst);
+ return;
+ }
+#endif
+
+ max[0] = client->format.redMax;
+ max[1] = client->format.greenMax;
+ max[2] = client->format.blueMax;
+
+ shift[0] = client->format.redShift;
+ shift[1] = client->format.greenShift;
+ shift[2] = client->format.blueShift;
+
+ for (y = 0; y < numRows; y++) {
+
+ /* First pixel in a row */
+ for (c = 0; c < 3; c++) {
+ pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]);
+ thisRow[c] = pix[c];
+ }
+ dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
+
+ /* Remaining pixels of a row */
+ for (x = 1; x < client->rectWidth; x++) {
+ for (c = 0; c < 3; c++) {
+ est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c];
+ if (est[c] > (int)max[c]) {
+ est[c] = (int)max[c];
+ } else if (est[c] < 0) {
+ est[c] = 0;
+ }
+ pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]);
+ thisRow[x*3+c] = pix[c];
+ }
+ dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]);
+ }
+ memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t));
+ }
+}
+
+static int
+InitFilterPaletteBPP (rfbClient* client, int rw, int rh)
+{
+ uint8_t numColors;
+#if BPP == 32
+ int i;
+ CARDBPP *palette = (CARDBPP *)client->tightPalette;
+#endif
+
+ client->rectWidth = rw;
+
+ if (!ReadFromRFBServer(client, (char*)&numColors, 1))
+ return 0;
+
+ client->rectColors = (int)numColors;
+ if (++client->rectColors < 2)
+ return 0;
+
+#if BPP == 32
+ if (client->format.depth == 24 && client->format.redMax == 0xFF &&
+ client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) {
+ if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * 3))
+ return 0;
+ for (i = client->rectColors - 1; i >= 0; i--) {
+ palette[i] = RGB24_TO_PIXEL32(client->tightPalette[i*3],
+ client->tightPalette[i*3+1],
+ client->tightPalette[i*3+2]);
+ }
+ return (client->rectColors == 2) ? 1 : 8;
+ }
+#endif
+
+ if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * (BPP / 8)))
+ return 0;
+
+ return (client->rectColors == 2) ? 1 : 8;
+}
+
+static void
+FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst)
+{
+ int x, y, b, w;
+ uint8_t *src = (uint8_t *)client->buffer;
+ CARDBPP *palette = (CARDBPP *)client->tightPalette;
+
+ if (client->rectColors == 2) {
+ w = (client->rectWidth + 7) / 8;
+ for (y = 0; y < numRows; y++) {
+ for (x = 0; x < client->rectWidth / 8; x++) {
+ for (b = 7; b >= 0; b--)
+ dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
+ }
+ for (b = 7; b >= 8 - client->rectWidth % 8; b--) {
+ dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
+ }
+ }
+ } else {
+ for (y = 0; y < numRows; y++)
+ for (x = 0; x < client->rectWidth; x++)
+ dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]];
+ }
+}
+
+#if BPP != 8
+
+/*----------------------------------------------------------------------------
+ *
+ * JPEG decompression.
+ *
+ */
+
+static rfbBool
+DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ int compressedLen;
+ uint8_t *compressedData;
+ CARDBPP *pixelPtr;
+ JSAMPROW rowPointer[1];
+ int dx, dy;
+
+ compressedLen = (int)ReadCompactLen(client);
+ if (compressedLen <= 0) {
+ rfbClientLog("Incorrect data received from the server.\n");
+ return FALSE;
+ }
+
+ compressedData = malloc(compressedLen);
+ if (compressedData == NULL) {
+ rfbClientLog("Memory allocation error.\n");
+ return FALSE;
+ }
+
+ if (!ReadFromRFBServer(client, (char*)compressedData, compressedLen)) {
+ free(compressedData);
+ return FALSE;
+ }
+
+ cinfo.err = jpeg_std_error(&jerr);
+ cinfo.client_data = client;
+ jpeg_create_decompress(&cinfo);
+
+ JpegSetSrcManager(&cinfo, compressedData, compressedLen);
+
+ jpeg_read_header(&cinfo, TRUE);
+ cinfo.out_color_space = JCS_RGB;
+
+ jpeg_start_decompress(&cinfo);
+ if (cinfo.output_width != w || cinfo.output_height != h ||
+ cinfo.output_components != 3) {
+ rfbClientLog("Tight Encoding: Wrong JPEG data received.\n");
+ jpeg_destroy_decompress(&cinfo);
+ free(compressedData);
+ return FALSE;
+ }
+
+ rowPointer[0] = (JSAMPROW)client->buffer;
+ dy = 0;
+ while (cinfo.output_scanline < cinfo.output_height) {
+ jpeg_read_scanlines(&cinfo, rowPointer, 1);
+ if (client->jpegError) {
+ break;
+ }
+ pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2];
+ for (dx = 0; dx < w; dx++) {
+ *pixelPtr++ =
+ RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]);
+ }
+ CopyRectangle(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1);
+ dy++;
+ }
+
+ if (!client->jpegError)
+ jpeg_finish_decompress(&cinfo);
+
+ jpeg_destroy_decompress(&cinfo);
+ free(compressedData);
+
+ return !client->jpegError;
+}
+
+#else
+
+static long
+ReadCompactLen (rfbClient* client)
+{
+ long len;
+ uint8_t b;
+
+ if (!ReadFromRFBServer(client, (char *)&b, 1))
+ return -1;
+ len = (int)b & 0x7F;
+ if (b & 0x80) {
+ if (!ReadFromRFBServer(client, (char *)&b, 1))
+ return -1;
+ len |= ((int)b & 0x7F) << 7;
+ if (b & 0x80) {
+ if (!ReadFromRFBServer(client, (char *)&b, 1))
+ return -1;
+ len |= ((int)b & 0xFF) << 14;
+ }
+ }
+ return len;
+}
+
+/*
+ * JPEG source manager functions for JPEG decompression in Tight decoder.
+ */
+
+static void
+JpegInitSource(j_decompress_ptr cinfo)
+{
+ rfbClient* client=(rfbClient*)cinfo->client_data;
+ client->jpegError = FALSE;
+}
+
+static boolean
+JpegFillInputBuffer(j_decompress_ptr cinfo)
+{
+ rfbClient* client=(rfbClient*)cinfo->client_data;
+ client->jpegError = TRUE;
+ client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
+ client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr;
+
+ return TRUE;
+}
+
+static void
+JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes)
+{
+ rfbClient* client=(rfbClient*)cinfo->client_data;
+ if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) {
+ client->jpegError = TRUE;
+ client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
+ client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr;
+ } else {
+ client->jpegSrcManager->next_input_byte += (size_t) num_bytes;
+ client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+static void
+JpegTermSource(j_decompress_ptr cinfo)
+{
+ /* nothing to do here. */
+}
+
+static void
+JpegSetSrcManager(j_decompress_ptr cinfo,
+ uint8_t *compressedData,
+ int compressedLen)
+{
+ rfbClient* client=(rfbClient*)cinfo->client_data;
+ client->jpegBufferPtr = compressedData;
+ client->jpegBufferLen = (size_t)compressedLen;
+
+ if(client->jpegSrcManager == NULL)
+ client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr));
+ client->jpegSrcManager->init_source = JpegInitSource;
+ client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer;
+ client->jpegSrcManager->skip_input_data = JpegSkipInputData;
+ client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart;
+ client->jpegSrcManager->term_source = JpegTermSource;
+ client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr;
+ client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen;
+
+ cinfo->src = client->jpegSrcManager;
+}
+
+#endif
+
+#undef CARDBPP
+
+/* LIBVNCSERVER_HAVE_LIBZ and LIBVNCSERVER_HAVE_LIBJPEG */
+#endif
+#endif
+
diff --git a/3rdParty/LibVNC/src/libvncclient/tls.c b/3rdParty/LibVNC/src/libvncclient/tls.c
new file mode 100644
index 0000000..206dbda
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/tls.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2009 Vic Lee.
+ *
+ * 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/rfbclient.h>
+#include <errno.h>
+#include "tls.h"
+
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+
+static const int rfbCertTypePriority[] = { GNUTLS_CRT_X509, 0 };
+static const int rfbProtoPriority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
+static const int rfbKXPriority[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
+static const int rfbKXAnon[] = {GNUTLS_KX_ANON_DH, 0};
+
+#define DH_BITS 1024
+static gnutls_dh_params_t rfbDHParams;
+
+static rfbBool rfbTLSInitialized = FALSE;
+
+static rfbBool
+InitializeTLS(void)
+{
+ int ret;
+
+ if (rfbTLSInitialized) return TRUE;
+ if ((ret = gnutls_global_init()) < 0 ||
+ (ret = gnutls_dh_params_init(&rfbDHParams)) < 0 ||
+ (ret = gnutls_dh_params_generate2(rfbDHParams, DH_BITS)) < 0)
+ {
+ rfbClientLog("Failed to initialized GnuTLS: %s.\n", gnutls_strerror(ret));
+ return FALSE;
+ }
+ rfbClientLog("GnuTLS initialized.\n");
+ rfbTLSInitialized = TRUE;
+ return TRUE;
+}
+
+static ssize_t
+PushTLS(gnutls_transport_ptr_t transport, const void *data, size_t len)
+{
+ rfbClient *client = (rfbClient*)transport;
+ int ret;
+
+ while (1)
+ {
+ ret = write(client->sock, data, len);
+ if (ret < 0)
+ {
+ if (errno == EINTR) continue;
+ return -1;
+ }
+ return ret;
+ }
+}
+
+
+static ssize_t
+PullTLS(gnutls_transport_ptr_t transport, void *data, size_t len)
+{
+ rfbClient *client = (rfbClient*)transport;
+ int ret;
+
+ while (1)
+ {
+ ret = read(client->sock, data, len);
+ if (ret < 0)
+ {
+ if (errno == EINTR) continue;
+ return -1;
+ }
+ return ret;
+ }
+}
+
+static rfbBool
+InitializeTLSSession(rfbClient* client, rfbBool anonTLS)
+{
+ int ret;
+
+ if (client->tlsSession) return TRUE;
+
+ if ((ret = gnutls_init(&client->tlsSession, GNUTLS_CLIENT)) < 0)
+ {
+ rfbClientLog("Failed to initialized TLS session: %s.\n", gnutls_strerror(ret));
+ return FALSE;
+ }
+
+ if ((ret = gnutls_set_default_priority(client->tlsSession)) < 0 ||
+ (ret = gnutls_kx_set_priority(client->tlsSession, anonTLS ? rfbKXAnon : rfbKXPriority)) < 0 ||
+ (ret = gnutls_certificate_type_set_priority(client->tlsSession, rfbCertTypePriority)) < 0 ||
+ (ret = gnutls_protocol_set_priority(client->tlsSession, rfbProtoPriority)) < 0)
+ {
+ FreeTLS(client);
+ rfbClientLog("Failed to set TLS priority: %s.\n", gnutls_strerror(ret));
+ return FALSE;
+ }
+
+ gnutls_transport_set_ptr(client->tlsSession, (gnutls_transport_ptr_t)client);
+ gnutls_transport_set_push_function(client->tlsSession, PushTLS);
+ gnutls_transport_set_pull_function(client->tlsSession, PullTLS);
+
+ rfbClientLog("TLS session initialized.\n");
+
+ return TRUE;
+}
+
+static rfbBool
+SetTLSAnonCredential(rfbClient* client)
+{
+ gnutls_anon_client_credentials anonCred;
+ int ret;
+
+ if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 ||
+ (ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_ANON, anonCred)) < 0)
+ {
+ FreeTLS(client);
+ rfbClientLog("Failed to create anonymous credentials: %s", gnutls_strerror(ret));
+ return FALSE;
+ }
+ rfbClientLog("TLS anonymous credential created.\n");
+ return TRUE;
+}
+
+static rfbBool
+HandshakeTLS(rfbClient* client)
+{
+ int timeout = 15;
+ int ret;
+
+ while (timeout > 0 && (ret = gnutls_handshake(client->tlsSession)) < 0)
+ {
+ if (!gnutls_error_is_fatal(ret))
+ {
+ rfbClientLog("TLS handshake blocking.\n");
+ sleep(1);
+ timeout--;
+ continue;
+ }
+ rfbClientLog("TLS handshake failed: %s.\n", gnutls_strerror(ret));
+ FreeTLS(client);
+ return FALSE;
+ }
+
+ if (timeout <= 0)
+ {
+ rfbClientLog("TLS handshake timeout.\n");
+ FreeTLS(client);
+ return FALSE;
+ }
+
+ rfbClientLog("TLS handshake done.\n");
+ return TRUE;
+}
+
+/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */
+static rfbBool
+ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result)
+{
+ uint8_t count=0;
+ uint8_t loop=0;
+ uint8_t flag=0;
+ uint32_t tAuth[256], t;
+ char buf1[500],buf2[10];
+ uint32_t authScheme;
+
+ if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
+
+ if (count==0)
+ {
+ rfbClientLog("List of security types is ZERO. Giving up.\n");
+ return FALSE;
+ }
+ if (count>sizeof(tAuth))
+ {
+ rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth));
+ return FALSE;
+ }
+
+ rfbClientLog("We have %d security types to read\n", count);
+ authScheme=0;
+ /* now, we have a list of available security types to read ( uint8_t[] ) */
+ for (loop=0;loop<count;loop++)
+ {
+ if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE;
+ t=rfbClientSwap32IfLE(tAuth[loop]);
+ rfbClientLog("%d) Received security type %d\n", loop, t);
+ if (flag) continue;
+ if (t==rfbVeNCryptTLSNone ||
+ t==rfbVeNCryptTLSVNC ||
+ t==rfbVeNCryptTLSPlain ||
+ t==rfbVeNCryptX509None ||
+ t==rfbVeNCryptX509VNC ||
+ t==rfbVeNCryptX509Plain)
+ {
+ flag++;
+ authScheme=t;
+ rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
+ /* send back 4 bytes (in original byte order!) indicating which security type to use */
+ if (!WriteToRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE;
+ }
+ tAuth[loop]=t;
+ }
+ if (authScheme==0)
+ {
+ memset(buf1, 0, sizeof(buf1));
+ for (loop=0;loop<count;loop++)
+ {
+ if (strlen(buf1)>=sizeof(buf1)-1) break;
+ snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]);
+ strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1);
+ }
+ rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n",
+ buf1);
+ return FALSE;
+ }
+ *result = authScheme;
+ return TRUE;
+}
+
+static void
+FreeX509Credential(rfbCredential *cred)
+{
+ if (cred->x509Credential.x509CACertFile) free(cred->x509Credential.x509CACertFile);
+ if (cred->x509Credential.x509CACrlFile) free(cred->x509Credential.x509CACrlFile);
+ if (cred->x509Credential.x509ClientCertFile) free(cred->x509Credential.x509ClientCertFile);
+ if (cred->x509Credential.x509ClientKeyFile) free(cred->x509Credential.x509ClientKeyFile);
+ free(cred);
+}
+
+static gnutls_certificate_credentials_t
+CreateX509CertCredential(rfbCredential *cred)
+{
+ gnutls_certificate_credentials_t x509_cred;
+ int ret;
+
+ if (!cred->x509Credential.x509CACertFile)
+ {
+ rfbClientLog("No CA certificate provided.\n");
+ return NULL;
+ }
+
+ if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0)
+ {
+ rfbClientLog("Cannot allocate credentials: %s.\n", gnutls_strerror(ret));
+ return NULL;
+ }
+ if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
+ cred->x509Credential.x509CACertFile, GNUTLS_X509_FMT_PEM)) < 0)
+ {
+ rfbClientLog("Cannot load CA credentials: %s.\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials (x509_cred);
+ return NULL;
+ }
+ if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile)
+ {
+ if ((ret = gnutls_certificate_set_x509_key_file(x509_cred,
+ cred->x509Credential.x509ClientCertFile, cred->x509Credential.x509ClientKeyFile,
+ GNUTLS_X509_FMT_PEM)) < 0)
+ {
+ rfbClientLog("Cannot load client certificate or key: %s.\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials (x509_cred);
+ return NULL;
+ }
+ } else
+ {
+ rfbClientLog("No client certificate or key provided.\n");
+ }
+ if (cred->x509Credential.x509CACrlFile)
+ {
+ if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
+ cred->x509Credential.x509CACrlFile, GNUTLS_X509_FMT_PEM)) < 0)
+ {
+ rfbClientLog("Cannot load CRL: %s.\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials (x509_cred);
+ return NULL;
+ }
+ } else
+ {
+ rfbClientLog("No CRL provided.\n");
+ }
+ gnutls_certificate_set_dh_params (x509_cred, rfbDHParams);
+ return x509_cred;
+}
+
+#endif
+
+rfbBool
+HandleAnonTLSAuth(rfbClient* client)
+{
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+
+ if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE;
+
+ if (!SetTLSAnonCredential(client)) return FALSE;
+
+ if (!HandshakeTLS(client)) return FALSE;
+
+ return TRUE;
+
+#else
+ rfbClientLog("TLS is not supported.\n");
+ return FALSE;
+#endif
+}
+
+rfbBool
+HandleVeNCryptAuth(rfbClient* client)
+{
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ uint8_t major, minor, status;
+ uint32_t authScheme;
+ rfbBool anonTLS;
+ gnutls_certificate_credentials_t x509_cred = NULL;
+ int ret;
+
+ if (!InitializeTLS()) return FALSE;
+
+ /* Read VeNCrypt version */
+ if (!ReadFromRFBServer(client, (char *)&major, 1) ||
+ !ReadFromRFBServer(client, (char *)&minor, 1))
+ {
+ return FALSE;
+ }
+ rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor);
+
+ if (major != 0 && minor != 2)
+ {
+ rfbClientLog("Unsupported VeNCrypt version.\n");
+ return FALSE;
+ }
+
+ if (!WriteToRFBServer(client, (char *)&major, 1) ||
+ !WriteToRFBServer(client, (char *)&minor, 1) ||
+ !ReadFromRFBServer(client, (char *)&status, 1))
+ {
+ return FALSE;
+ }
+
+ if (status != 0)
+ {
+ rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor);
+ return FALSE;
+ }
+
+ if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE;
+ if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1)
+ {
+ rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status);
+ return FALSE;
+ }
+ client->subAuthScheme = authScheme;
+
+ /* Some VeNCrypt security types are anonymous TLS, others are X509 */
+ switch (authScheme)
+ {
+ case rfbVeNCryptTLSNone:
+ case rfbVeNCryptTLSVNC:
+ case rfbVeNCryptTLSPlain:
+ anonTLS = TRUE;
+ break;
+ default:
+ anonTLS = FALSE;
+ break;
+ }
+
+ /* Get X509 Credentials if it's not anonymous */
+ if (!anonTLS)
+ {
+ rfbCredential *cred;
+
+ if (!client->GetCredential)
+ {
+ rfbClientLog("GetCredential callback is not set.\n");
+ return FALSE;
+ }
+ cred = client->GetCredential(client, rfbCredentialTypeX509);
+ if (!cred)
+ {
+ rfbClientLog("Reading credential failed\n");
+ return FALSE;
+ }
+
+ x509_cred = CreateX509CertCredential(cred);
+ FreeX509Credential(cred);
+ if (!x509_cred) return FALSE;
+ }
+
+ /* Start up the TLS session */
+ if (!InitializeTLSSession(client, anonTLS)) return FALSE;
+
+ if (anonTLS)
+ {
+ if (!SetTLSAnonCredential(client)) return FALSE;
+ }
+ else
+ {
+ if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0)
+ {
+ rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret));
+ FreeTLS(client);
+ return FALSE;
+ }
+ }
+
+ if (!HandshakeTLS(client)) return FALSE;
+
+ /* TODO: validate certificate */
+
+ /* We are done here. The caller should continue with client->subAuthScheme
+ * to do actual sub authentication.
+ */
+ return TRUE;
+
+#else
+ rfbClientLog("TLS is not supported.\n");
+ return FALSE;
+#endif
+}
+
+int
+ReadFromTLS(rfbClient* client, char *out, unsigned int n)
+{
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ ssize_t ret;
+
+ ret = gnutls_record_recv(client->tlsSession, out, n);
+ if (ret >= 0) return ret;
+ if (ret == GNUTLS_E_REHANDSHAKE || ret == GNUTLS_E_AGAIN)
+ {
+ errno = EAGAIN;
+ } else
+ {
+ rfbClientLog("Error reading from TLS: %s.\n", gnutls_strerror(ret));
+ errno = EINTR;
+ }
+ return -1;
+#else
+ rfbClientLog("TLS is not supported.\n");
+ errno = EINTR;
+ return -1;
+#endif
+}
+
+int
+WriteToTLS(rfbClient* client, char *buf, unsigned int n)
+{
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ unsigned int offset = 0;
+ ssize_t ret;
+
+ while (offset < n)
+ {
+ ret = gnutls_record_send(client->tlsSession, buf+offset, (size_t)(n-offset));
+ if (ret == 0) continue;
+ if (ret < 0)
+ {
+ if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) continue;
+ rfbClientLog("Error writing to TLS: %s.\n", gnutls_strerror(ret));
+ return -1;
+ }
+ offset += (unsigned int)ret;
+ }
+ return offset;
+#else
+ rfbClientLog("TLS is not supported.\n");
+ errno = EINTR;
+ return -1;
+#endif
+}
+
+void FreeTLS(rfbClient* client)
+{
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ if (client->tlsSession)
+ {
+ gnutls_deinit(client->tlsSession);
+ client->tlsSession = NULL;
+ }
+#endif
+}
diff --git a/3rdParty/LibVNC/src/libvncclient/tls.h b/3rdParty/LibVNC/src/libvncclient/tls.h
new file mode 100644
index 0000000..48d159b
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/tls.h
@@ -0,0 +1,51 @@
+#ifndef TLS_H
+#define TLS_H
+
+/*
+ * Copyright (C) 2009 Vic Lee.
+ *
+ * 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.
+ */
+
+/* Handle Anonymous TLS Authentication (18) with the server.
+ * After authentication, client->tlsSession will be set.
+ */
+rfbBool HandleAnonTLSAuth(rfbClient* client);
+
+/* Handle VeNCrypt Authentication (19) with the server.
+ * The callback function GetX509Credential will be called.
+ * After authentication, client->tlsSession will be set.
+ */
+rfbBool HandleVeNCryptAuth(rfbClient* client);
+
+/* Read desired bytes from TLS session.
+ * It's a wrapper function over gnutls_record_recv() and return values
+ * are same as read(), that is, >0 for actual bytes read, 0 for EOF,
+ * or EAGAIN, EINTR.
+ * This should be a non-blocking call. Blocking is handled in sockets.c.
+ */
+int ReadFromTLS(rfbClient* client, char *out, unsigned int n);
+
+/* Write desired bytes to TLS session.
+ * It's a wrapper function over gnutls_record_send() and it will be
+ * blocking call, until all bytes are written or error returned.
+ */
+int WriteToTLS(rfbClient* client, char *buf, unsigned int n);
+
+/* Free TLS resources */
+void FreeTLS(rfbClient* client);
+
+#endif /* TLS_H */
diff --git a/3rdParty/LibVNC/src/libvncclient/ultra.c b/3rdParty/LibVNC/src/libvncclient/ultra.c
new file mode 100644
index 0000000..3be150d
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/ultra.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * ultrazip.c - handle ultrazip encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles an zlib
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP)
+#define HandleUltraBPP CONCAT2E(HandleUltra,BPP)
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+
+static rfbBool
+HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbZlibHeader hdr;
+ int toRead=0;
+ int inflateResult=0;
+ int uncompressedBytes = (( rw * rh ) * ( BPP / 8 ));
+
+ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
+ return FALSE;
+
+ toRead = rfbClientSwap32IfLE(hdr.nBytes);
+ if (toRead==0) return TRUE;
+
+ if (uncompressedBytes==0)
+ {
+ rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP);
+ return FALSE;
+ }
+
+ /* First make sure we have a large enough raw buffer to hold the
+ * decompressed data. In practice, with a fixed BPP, fixed frame
+ * buffer size and the first update containing the entire frame
+ * buffer, this buffer allocation should only happen once, on the
+ * first update.
+ */
+ if ( client->raw_buffer_size < uncompressedBytes) {
+ if ( client->raw_buffer != NULL ) {
+ free( client->raw_buffer );
+ }
+ client->raw_buffer_size = uncompressedBytes;
+ /* buffer needs to be aligned on 4-byte boundaries */
+ if ((client->raw_buffer_size % 4)!=0)
+ client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
+ client->raw_buffer = (char*) malloc( client->raw_buffer_size );
+ }
+
+ /* allocate enough space to store the incoming compressed packet */
+ if ( client->ultra_buffer_size < toRead ) {
+ if ( client->ultra_buffer != NULL ) {
+ free( client->ultra_buffer );
+ }
+ client->ultra_buffer_size = toRead;
+ /* buffer needs to be aligned on 4-byte boundaries */
+ if ((client->ultra_buffer_size % 4)!=0)
+ client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4));
+ client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
+ }
+
+ /* Fill the buffer, obtaining data from the server. */
+ if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
+ return FALSE;
+
+ /* uncompress the data */
+ uncompressedBytes = client->raw_buffer_size;
+ inflateResult = lzo1x_decompress(
+ (lzo_byte *)client->ultra_buffer, toRead,
+ (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes,
+ NULL);
+
+
+ if ((rw * rh * (BPP / 8)) != uncompressedBytes)
+ rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes);
+
+ /* Put the uncompressed contents of the update on the screen. */
+ if ( inflateResult == LZO_E_OK )
+ {
+ CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh);
+ }
+ else
+ {
+ rfbClientLog("ultra decompress returned error: %d\n",
+ inflateResult);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* UltraZip is like rre in that it is composed of subrects */
+static rfbBool
+HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbZlibHeader hdr;
+ int i=0;
+ int toRead=0;
+ int inflateResult=0;
+ unsigned char *ptr=NULL;
+ int uncompressedBytes = ry + (rw * 65535);
+ unsigned int numCacheRects = rx;
+
+ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
+ return FALSE;
+
+ toRead = rfbClientSwap32IfLE(hdr.nBytes);
+
+ if (toRead==0) return TRUE;
+
+ if (uncompressedBytes==0)
+ {
+ rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx);
+ return FALSE;
+ }
+
+ /* First make sure we have a large enough raw buffer to hold the
+ * decompressed data. In practice, with a fixed BPP, fixed frame
+ * buffer size and the first update containing the entire frame
+ * buffer, this buffer allocation should only happen once, on the
+ * first update.
+ */
+ if ( client->raw_buffer_size < (uncompressedBytes + 500)) {
+ if ( client->raw_buffer != NULL ) {
+ free( client->raw_buffer );
+ }
+ client->raw_buffer_size = uncompressedBytes + 500;
+ /* buffer needs to be aligned on 4-byte boundaries */
+ if ((client->raw_buffer_size % 4)!=0)
+ client->raw_buffer_size += (4-(client->raw_buffer_size % 4));
+ client->raw_buffer = (char*) malloc( client->raw_buffer_size );
+ }
+
+
+ /* allocate enough space to store the incoming compressed packet */
+ if ( client->ultra_buffer_size < toRead ) {
+ if ( client->ultra_buffer != NULL ) {
+ free( client->ultra_buffer );
+ }
+ client->ultra_buffer_size = toRead;
+ client->ultra_buffer = (char*) malloc( client->ultra_buffer_size );
+ }
+
+ /* Fill the buffer, obtaining data from the server. */
+ if (!ReadFromRFBServer(client, client->ultra_buffer, toRead))
+ return FALSE;
+
+ /* uncompress the data */
+ uncompressedBytes = client->raw_buffer_size;
+ inflateResult = lzo1x_decompress(
+ (lzo_byte *)client->ultra_buffer, toRead,
+ (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, NULL);
+ if ( inflateResult != LZO_E_OK )
+ {
+ rfbClientLog("ultra decompress returned error: %d\n",
+ inflateResult);
+ return FALSE;
+ }
+
+ /* Put the uncompressed contents of the update on the screen. */
+ ptr = (unsigned char *)client->raw_buffer;
+ for (i=0; i<numCacheRects; i++)
+ {
+ unsigned short sx, sy, sw, sh;
+ unsigned int se;
+
+ memcpy((char *)&sx, ptr, 2); ptr += 2;
+ memcpy((char *)&sy, ptr, 2); ptr += 2;
+ memcpy((char *)&sw, ptr, 2); ptr += 2;
+ memcpy((char *)&sh, ptr, 2); ptr += 2;
+ memcpy((char *)&se, ptr, 4); ptr += 4;
+
+ sx = rfbClientSwap16IfLE(sx);
+ sy = rfbClientSwap16IfLE(sy);
+ sw = rfbClientSwap16IfLE(sw);
+ sh = rfbClientSwap16IfLE(sh);
+ se = rfbClientSwap32IfLE(se);
+
+ if (se == rfbEncodingRaw)
+ {
+ CopyRectangle(client, (unsigned char *)ptr, sx, sy, sw, sh);
+ ptr += ((sw * sh) * (BPP / 8));
+ }
+ }
+
+ return TRUE;
+}
+
+#undef CARDBPP
diff --git a/3rdParty/LibVNC/src/libvncclient/vncviewer.c b/3rdParty/LibVNC/src/libvncclient/vncviewer.c
new file mode 100644
index 0000000..094ba34
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/vncviewer.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+/*
+ * vncviewer.c - the Xt-based VNC viewer.
+ */
+
+#ifdef __STRICT_ANSI__
+#define _BSD_SOURCE
+#define _POSIX_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <rfb/rfbclient.h>
+#include "tls.h"
+
+static void Dummy(rfbClient* client) {
+}
+static rfbBool DummyPoint(rfbClient* client, int x, int y) {
+ return TRUE;
+}
+static void DummyRect(rfbClient* client, int x, int y, int w, int h) {
+}
+
+#ifdef __MINGW32__
+static char* NoPassword(rfbClient* client) {
+ return strdup("");
+}
+#undef SOCKET
+#include <winsock2.h>
+#define close closesocket
+#else
+#include <stdio.h>
+#include <termios.h>
+#endif
+
+static char* ReadPassword(rfbClient* client) {
+#ifdef __MINGW32__
+ /* FIXME */
+ rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n");
+ return NoPassword(client);
+#else
+ int i;
+ char* p=malloc(9);
+ struct termios save,noecho;
+ p[0]=0;
+ if(tcgetattr(fileno(stdin),&save)!=0) return p;
+ noecho=save; noecho.c_lflag &= ~ECHO;
+ if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p;
+ fprintf(stderr,"Password: ");
+ i=0;
+ while(1) {
+ int c=fgetc(stdin);
+ if(c=='\n')
+ break;
+ if(i<8) {
+ p[i]=c;
+ i++;
+ p[i]=0;
+ }
+ }
+ tcsetattr(fileno(stdin),TCSAFLUSH,&save);
+ return p;
+#endif
+}
+static rfbBool MallocFrameBuffer(rfbClient* client) {
+ if(client->frameBuffer)
+ free(client->frameBuffer);
+ client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8);
+ return client->frameBuffer?TRUE:FALSE;
+}
+
+static void initAppData(AppData* data) {
+ data->shareDesktop=TRUE;
+ data->viewOnly=FALSE;
+ data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw";
+ data->useBGR233=FALSE;
+ data->nColours=0;
+ data->forceOwnCmap=FALSE;
+ data->forceTrueColour=FALSE;
+ data->requestedDepth=0;
+ data->compressLevel=3;
+ data->qualityLevel=5;
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ data->enableJPEG=TRUE;
+#else
+ data->enableJPEG=FALSE;
+#endif
+ data->useRemoteCursor=FALSE;
+}
+
+rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
+ int bytesPerPixel) {
+ rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1);
+ if(!client) {
+ rfbClientErr("Couldn't allocate client structure!\n");
+ return NULL;
+ }
+ initAppData(&client->appData);
+ client->endianTest = 1;
+ client->programName="";
+ client->serverHost=strdup("");
+ client->serverPort=5900;
+
+ client->destHost = NULL;
+ client->destPort = 5900;
+
+ client->CurrentKeyboardLedState = 0;
+ client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
+
+ /* default: use complete frame buffer */
+ client->updateRect.x = -1;
+
+ client->format.bitsPerPixel = bytesPerPixel*8;
+ client->format.depth = bitsPerSample*samplesPerPixel;
+ client->appData.requestedDepth=client->format.depth;
+ client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE;
+ client->format.trueColour = TRUE;
+
+ if (client->format.bitsPerPixel == 8) {
+ client->format.redMax = 7;
+ client->format.greenMax = 7;
+ client->format.blueMax = 3;
+ client->format.redShift = 0;
+ client->format.greenShift = 3;
+ client->format.blueShift = 6;
+ } else {
+ client->format.redMax = (1 << bitsPerSample) - 1;
+ client->format.greenMax = (1 << bitsPerSample) - 1;
+ client->format.blueMax = (1 << bitsPerSample) - 1;
+ if(!client->format.bigEndian) {
+ client->format.redShift = 0;
+ client->format.greenShift = bitsPerSample;
+ client->format.blueShift = bitsPerSample * 2;
+ } else {
+ if(client->format.bitsPerPixel==8*3) {
+ client->format.redShift = bitsPerSample*2;
+ client->format.greenShift = bitsPerSample*1;
+ client->format.blueShift = 0;
+ } else {
+ client->format.redShift = bitsPerSample*3;
+ client->format.greenShift = bitsPerSample*2;
+ client->format.blueShift = bitsPerSample;
+ }
+ }
+ }
+
+ client->bufoutptr=client->buf;
+ client->buffered=0;
+
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ client->raw_buffer_size = -1;
+ client->decompStreamInited = FALSE;
+
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ memset(client->zlibStreamActive,0,sizeof(rfbBool)*4);
+ client->jpegSrcManager = NULL;
+#endif
+#endif
+
+ client->HandleCursorPos = DummyPoint;
+ client->SoftCursorLockArea = DummyRect;
+ client->SoftCursorUnlockScreen = Dummy;
+ client->GotFrameBufferUpdate = DummyRect;
+ client->FinishedFrameBufferUpdate = NULL;
+ client->GetPassword = ReadPassword;
+ client->MallocFrameBuffer = MallocFrameBuffer;
+ client->Bell = Dummy;
+ client->CurrentKeyboardLedState = 0;
+ client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
+
+ client->authScheme = 0;
+ client->subAuthScheme = 0;
+ client->GetCredential = NULL;
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ client->tlsSession = NULL;
+#endif
+ client->sock = -1;
+ client->listenSock = -1;
+ client->clientAuthSchemes = NULL;
+ return client;
+}
+
+static rfbBool rfbInitConnection(rfbClient* client)
+{
+ /* Unless we accepted an incoming connection, make a TCP connection to the
+ given VNC server */
+
+ if (!client->listenSpecified) {
+ if (!client->serverHost)
+ return FALSE;
+ if (client->destHost) {
+ if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort))
+ return FALSE;
+ } else {
+ if (!ConnectToRFBServer(client,client->serverHost,client->serverPort))
+ return FALSE;
+ }
+ }
+
+ /* Initialise the VNC connection, including reading the password */
+
+ if (!InitialiseRFBConnection(client))
+ return FALSE;
+
+ if (!SetFormatAndEncodings(client))
+ return FALSE;
+
+ client->width=client->si.framebufferWidth;
+ client->height=client->si.framebufferHeight;
+ client->MallocFrameBuffer(client);
+
+ if (client->updateRect.x < 0) {
+ client->updateRect.x = client->updateRect.y = 0;
+ client->updateRect.w = client->width;
+ client->updateRect.h = client->height;
+ }
+
+ if (client->appData.scaleSetting>1)
+ {
+ if (!SendScaleSetting(client, client->appData.scaleSetting))
+ return FALSE;
+ if (!SendFramebufferUpdateRequest(client,
+ client->updateRect.x / client->appData.scaleSetting,
+ client->updateRect.y / client->appData.scaleSetting,
+ client->updateRect.w / client->appData.scaleSetting,
+ client->updateRect.h / client->appData.scaleSetting,
+ FALSE))
+ return FALSE;
+ }
+ else
+ {
+ if (!SendFramebufferUpdateRequest(client,
+ client->updateRect.x, client->updateRect.y,
+ client->updateRect.w, client->updateRect.h,
+ FALSE))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) {
+ int i,j;
+
+ if(argv && argc && *argc) {
+ if(client->programName==0)
+ client->programName=argv[0];
+
+ for (i = 1; i < *argc; i++) {
+ j = i;
+ if (strcmp(argv[i], "-listen") == 0) {
+ listenForIncomingConnections(client);
+ break;
+ } else if (strcmp(argv[i], "-listennofork") == 0) {
+ listenForIncomingConnectionsNoFork(client, -1);
+ break;
+ } else if (strcmp(argv[i], "-play") == 0) {
+ client->serverPort = -1;
+ j++;
+ } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) {
+ client->appData.encodingsString = argv[i+1];
+ j+=2;
+ } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) {
+ client->appData.compressLevel = atoi(argv[i+1]);
+ j+=2;
+ } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) {
+ client->appData.qualityLevel = atoi(argv[i+1]);
+ j+=2;
+ } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) {
+ client->appData.scaleSetting = atoi(argv[i+1]);
+ j+=2;
+ } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) {
+ char* colon=strchr(argv[i+1],':');
+
+ if(client->destHost)
+ free(client->destHost);
+ client->destPort = 5900;
+
+ client->destHost = strdup(argv[i+1]);
+ if(colon) {
+ client->destHost[(int)(colon-argv[i+1])] = '\0';
+ client->destPort = atoi(colon+1);
+ }
+ j+=2;
+ } else {
+ char* colon=strchr(argv[i],':');
+
+ if(client->serverHost)
+ free(client->serverHost);
+
+ if(colon) {
+ client->serverHost = strdup(argv[i]);
+ client->serverHost[(int)(colon-argv[i])] = '\0';
+ client->serverPort = atoi(colon+1);
+ } else {
+ client->serverHost = strdup(argv[i]);
+ }
+ if(client->serverPort >= 0 && client->serverPort < 5900)
+ client->serverPort += 5900;
+ }
+ /* purge arguments */
+ if (j>i) {
+ *argc-=j-i;
+ memmove(argv+i,argv+j,(*argc-i)*sizeof(char*));
+ i--;
+ }
+ }
+ }
+
+ if(!rfbInitConnection(client)) {
+ rfbClientCleanup(client);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void rfbClientCleanup(rfbClient* client) {
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+#ifdef LIBVNCSERVER_HAVE_LIBJPEG
+ int i;
+
+ for ( i = 0; i < 4; i++ ) {
+ if (client->zlibStreamActive[i] == TRUE ) {
+ if (inflateEnd (&client->zlibStream[i]) != Z_OK &&
+ client->zlibStream[i].msg != NULL)
+ rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg);
+ }
+ }
+
+ if ( client->decompStreamInited == TRUE ) {
+ if (inflateEnd (&client->decompStream) != Z_OK &&
+ client->decompStream.msg != NULL)
+ rfbClientLog("inflateEnd: %s\n", client->decompStream.msg );
+ }
+
+ if (client->jpegSrcManager)
+ free(client->jpegSrcManager);
+#endif
+#endif
+
+#ifdef LIBVNCSERVER_WITH_CLIENT_TLS
+ FreeTLS(client);
+#endif
+ if (client->sock >= 0)
+ close(client->sock);
+ if (client->listenSock >= 0)
+ close(client->listenSock);
+ free(client->desktopName);
+ free(client->serverHost);
+ if (client->destHost)
+ free(client->destHost);
+ if (client->clientAuthSchemes)
+ free(client->clientAuthSchemes);
+ free(client);
+}
diff --git a/3rdParty/LibVNC/src/libvncclient/zlib.c b/3rdParty/LibVNC/src/libvncclient/zlib.c
new file mode 100644
index 0000000..e872d40
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/zlib.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. 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.
+ */
+
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+
+/*
+ * zlib.c - handle zlib encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles an zlib
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#define HandleZlibBPP CONCAT2E(HandleZlib,BPP)
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+
+static rfbBool
+HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbZlibHeader hdr;
+ int remaining;
+ int inflateResult;
+ int toRead;
+
+ /* First make sure we have a large enough raw buffer to hold the
+ * decompressed data. In practice, with a fixed BPP, fixed frame
+ * buffer size and the first update containing the entire frame
+ * buffer, this buffer allocation should only happen once, on the
+ * first update.
+ */
+ if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) {
+
+ if ( client->raw_buffer != NULL ) {
+
+ free( client->raw_buffer );
+
+ }
+
+ client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 ));
+ client->raw_buffer = (char*) malloc( client->raw_buffer_size );
+
+ }
+
+ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader))
+ return FALSE;
+
+ remaining = rfbClientSwap32IfLE(hdr.nBytes);
+
+ /* Need to initialize the decompressor state. */
+ client->decompStream.next_in = ( Bytef * )client->buffer;
+ client->decompStream.avail_in = 0;
+ client->decompStream.next_out = ( Bytef * )client->raw_buffer;
+ client->decompStream.avail_out = client->raw_buffer_size;
+ client->decompStream.data_type = Z_BINARY;
+
+ /* Initialize the decompression stream structures on the first invocation. */
+ if ( client->decompStreamInited == FALSE ) {
+
+ inflateResult = inflateInit( &client->decompStream );
+
+ if ( inflateResult != Z_OK ) {
+ rfbClientLog(
+ "inflateInit returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+ }
+
+ client->decompStreamInited = TRUE;
+
+ }
+
+ inflateResult = Z_OK;
+
+ /* Process buffer full of data until no more to process, or
+ * some type of inflater error, or Z_STREAM_END.
+ */
+ while (( remaining > 0 ) &&
+ ( inflateResult == Z_OK )) {
+
+ if ( remaining > RFB_BUFFER_SIZE ) {
+ toRead = RFB_BUFFER_SIZE;
+ }
+ else {
+ toRead = remaining;
+ }
+
+ /* Fill the buffer, obtaining data from the server. */
+ if (!ReadFromRFBServer(client, client->buffer,toRead))
+ return FALSE;
+
+ client->decompStream.next_in = ( Bytef * )client->buffer;
+ client->decompStream.avail_in = toRead;
+
+ /* Need to uncompress buffer full. */
+ inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );
+
+ /* We never supply a dictionary for compression. */
+ if ( inflateResult == Z_NEED_DICT ) {
+ rfbClientLog("zlib inflate needs a dictionary!\n");
+ return FALSE;
+ }
+ if ( inflateResult < 0 ) {
+ rfbClientLog(
+ "zlib inflate returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+ }
+
+ /* Result buffer allocated to be at least large enough. We should
+ * never run out of space!
+ */
+ if (( client->decompStream.avail_in > 0 ) &&
+ ( client->decompStream.avail_out <= 0 )) {
+ rfbClientLog("zlib inflate ran out of space!\n");
+ return FALSE;
+ }
+
+ remaining -= toRead;
+
+ } /* while ( remaining > 0 ) */
+
+ if ( inflateResult == Z_OK ) {
+
+ /* Put the uncompressed contents of the update on the screen. */
+ CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh);
+ }
+ else {
+
+ rfbClientLog(
+ "zlib inflate returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+#undef CARDBPP
+
+#endif
diff --git a/3rdParty/LibVNC/src/libvncclient/zrle.c b/3rdParty/LibVNC/src/libvncclient/zrle.c
new file mode 100644
index 0000000..da2db4b
--- /dev/null
+++ b/3rdParty/LibVNC/src/libvncclient/zrle.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2005 Johannes E. Schindelin. 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.
+ */
+
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+
+/*
+ * zrle.c - handle zrle encoding.
+ *
+ * This file shouldn't be compiled directly. It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP. For
+ * each value of BPP, this file defines a function which handles an zrle
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#ifndef REALBPP
+#define REALBPP BPP
+#endif
+
+#if !defined(UNCOMP) || UNCOMP==0
+#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP)
+#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP)
+#elif UNCOMP>0
+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down)
+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down)
+#else
+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up)
+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up)
+#endif
+#define CARDBPP CONCAT3E(uint,BPP,_t)
+#define CARDREALBPP CONCAT3E(uint,REALBPP,_t)
+
+#define ENDIAN_LITTLE 0
+#define ENDIAN_BIG 1
+#define ENDIAN_NO 2
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+#undef END_FIX
+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
+# define END_FIX LE
+#elif ZYWRLE_ENDIAN == ENDIAN_BIG
+# define END_FIX BE
+#else
+# define END_FIX NE
+#endif
+#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c)
+#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b)
+#undef CPIXEL
+#if REALBPP != BPP
+#if UNCOMP == 0
+#define CPIXEL REALBPP
+#elif UNCOMP>0
+#define CPIXEL CONCAT2E(REALBPP,Down)
+#else
+#define CPIXEL CONCAT2E(REALBPP,Up)
+#endif
+#endif
+#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
+#if BPP!=8
+#define ZYWRLE_DECODE 1
+#include "../libvncserver/zywrletemplate.c"
+#endif
+#undef CPIXEL
+
+static int HandleZRLETile(rfbClient* client,
+ uint8_t* buffer,size_t buffer_length,
+ int x,int y,int w,int h);
+
+static rfbBool
+HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh)
+{
+ rfbZRLEHeader header;
+ int remaining;
+ int inflateResult;
+ int toRead;
+ int min_buffer_size = rw * rh * (REALBPP / 8) * 2;
+
+ /* First make sure we have a large enough raw buffer to hold the
+ * decompressed data. In practice, with a fixed REALBPP, fixed frame
+ * buffer size and the first update containing the entire frame
+ * buffer, this buffer allocation should only happen once, on the
+ * first update.
+ */
+ if ( client->raw_buffer_size < min_buffer_size) {
+
+ if ( client->raw_buffer != NULL ) {
+
+ free( client->raw_buffer );
+
+ }
+
+ client->raw_buffer_size = min_buffer_size;
+ client->raw_buffer = (char*) malloc( client->raw_buffer_size );
+
+ }
+
+ if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader))
+ return FALSE;
+
+ remaining = rfbClientSwap32IfLE(header.length);
+
+ /* Need to initialize the decompressor state. */
+ client->decompStream.next_in = ( Bytef * )client->buffer;
+ client->decompStream.avail_in = 0;
+ client->decompStream.next_out = ( Bytef * )client->raw_buffer;
+ client->decompStream.avail_out = client->raw_buffer_size;
+ client->decompStream.data_type = Z_BINARY;
+
+ /* Initialize the decompression stream structures on the first invocation. */
+ if ( client->decompStreamInited == FALSE ) {
+
+ inflateResult = inflateInit( &client->decompStream );
+
+ if ( inflateResult != Z_OK ) {
+ rfbClientLog(
+ "inflateInit returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+ }
+
+ client->decompStreamInited = TRUE;
+
+ }
+
+ inflateResult = Z_OK;
+
+ /* Process buffer full of data until no more to process, or
+ * some type of inflater error, or Z_STREAM_END.
+ */
+ while (( remaining > 0 ) &&
+ ( inflateResult == Z_OK )) {
+
+ if ( remaining > RFB_BUFFER_SIZE ) {
+ toRead = RFB_BUFFER_SIZE;
+ }
+ else {
+ toRead = remaining;
+ }
+
+ /* Fill the buffer, obtaining data from the server. */
+ if (!ReadFromRFBServer(client, client->buffer,toRead))
+ return FALSE;
+
+ client->decompStream.next_in = ( Bytef * )client->buffer;
+ client->decompStream.avail_in = toRead;
+
+ /* Need to uncompress buffer full. */
+ inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );
+
+ /* We never supply a dictionary for compression. */
+ if ( inflateResult == Z_NEED_DICT ) {
+ rfbClientLog("zlib inflate needs a dictionary!\n");
+ return FALSE;
+ }
+ if ( inflateResult < 0 ) {
+ rfbClientLog(
+ "zlib inflate returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+ }
+
+ /* Result buffer allocated to be at least large enough. We should
+ * never run out of space!
+ */
+ if (( client->decompStream.avail_in > 0 ) &&
+ ( client->decompStream.avail_out <= 0 )) {
+ rfbClientLog("zlib inflate ran out of space!\n");
+ return FALSE;
+ }
+
+ remaining -= toRead;
+
+ } /* while ( remaining > 0 ) */
+
+ if ( inflateResult == Z_OK ) {
+ void* buf=client->raw_buffer;
+ int i,j;
+
+ remaining = client->raw_buffer_size-client->decompStream.avail_out;
+
+ for(j=0; j<rh; j+=rfbZRLETileHeight)
+ for(i=0; i<rw; i+=rfbZRLETileWidth) {
+ int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth;
+ int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight;
+ int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight);
+
+ if(result<0) {
+ rfbClientLog("ZRLE decoding failed (%d)\n",result);
+return TRUE;
+ return FALSE;
+ }
+
+ buf+=result;
+ remaining-=result;
+ }
+ }
+ else {
+
+ rfbClientLog(
+ "zlib inflate returned error: %d, msg: %s\n",
+ inflateResult,
+ client->decompStream.msg);
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0
+#if UNCOMP>0
+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP)
+#else
+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP)))
+#endif
+#else
+#define UncompressCPixel(pointer) (*(CARDBPP*)pointer)
+#endif
+
+static int HandleZRLETile(rfbClient* client,
+ uint8_t* buffer,size_t buffer_length,
+ int x,int y,int w,int h) {
+ uint8_t* buffer_copy = buffer;
+ uint8_t* buffer_end = buffer+buffer_length;
+ uint8_t type;
+#if BPP!=8
+ uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ?
+ 0 : (3 - client->appData.qualityLevel / 3);
+#endif
+
+ if(buffer_length<1)
+ return -2;
+
+ type = *buffer;
+ buffer++;
+ {
+ if( type == 0 ) /* raw */
+#if BPP!=8
+ if( zywrle_level > 0 ){
+ CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x;
+ int ret;
+ client->appData.qualityLevel |= 0x80;
+ ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h);
+ client->appData.qualityLevel &= 0x7F;
+ if( ret < 0 ){
+ return ret;
+ }
+ ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer );
+ buffer += ret;
+ }else
+#endif
+ {
+#if REALBPP!=BPP
+ int i,j;
+
+ if(1+w*h*REALBPP/8>buffer_length) {
+ rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h);
+ return -3;
+ }
+
+ for(j=y*client->width; j<(y+h)*client->width; j+=client->width)
+ for(i=x; i<x+w; i++,buffer+=REALBPP/8)
+ ((CARDBPP*)client->frameBuffer)[j+i] = UncompressCPixel(buffer);
+#else
+ CopyRectangle(client, buffer, x, y, w, h);
+ buffer+=w*h*REALBPP/8;
+#endif
+ }
+ else if( type == 1 ) /* solid */
+ {
+ CARDBPP color = UncompressCPixel(buffer);
+
+ if(1+REALBPP/8>buffer_length)
+ return -4;
+
+ FillRectangle(client, x, y, w, h, color);
+
+ buffer+=REALBPP/8;
+
+ }
+ else if( (type >= 2)&&(type <= 127) ) /* packed Palette */
+ {
+ CARDBPP palette[16];
+ int i,j,shift,
+ bpp=(type>4?(type>16?8:4):(type>2?2:1)),
+ mask=(1<<bpp)-1,
+ divider=(8/bpp);
+
+ if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length)
+ return -5;
+
+ /* read palette */
+ for(i=0; i<type; i++,buffer+=REALBPP/8)
+ palette[i] = UncompressCPixel(buffer);
+
+ /* read palettized pixels */
+ for(j=y*client->width; j<(y+h)*client->width; j+=client->width) {
+ for(i=x,shift=8-bpp; i<x+w; i++) {
+ ((CARDBPP*)client->frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask];
+ shift-=bpp;
+ if(shift<0) {
+ shift=8-bpp;
+ buffer++;
+ }
+ }
+ if(shift<8-bpp)
+ buffer++;
+ }
+
+ }
+ /* case 17 ... 127: not used, but valid */
+ else if( type == 128 ) /* plain RLE */
+ {
+ int i=0,j=0;
+ while(j<h) {
+ int color,length;
+ /* read color */
+ if(buffer+REALBPP/8+1>buffer_end)
+ return -7;
+ color = UncompressCPixel(buffer);
+ buffer+=REALBPP/8;
+ /* read run length */
+ length=1;
+ while(*buffer==0xff) {
+ if(buffer+1>=buffer_end)
+ return -8;
+ length+=*buffer;
+ buffer++;
+ }
+ length+=*buffer;
+ buffer++;
+ while(j<h && length>0) {
+ ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
+ length--;
+ i++;
+ if(i>=w) {
+ i=0;
+ j++;
+ }
+ }
+ if(length>0)
+ rfbClientLog("Warning: possible ZRLE corruption\n");
+ }
+
+ }
+ else if( type == 129 ) /* unused */
+ {
+ return -8;
+ }
+ else if( (type >= 130)&&(type <= 255) ) /* palette RLE */
+ {
+ CARDBPP palette[128];
+ int i,j;
+
+ if(2+(type-128)*REALBPP/8>buffer_length)
+ return -9;
+
+ /* read palette */
+ for(i=0; i<type-128; i++,buffer+=REALBPP/8)
+ palette[i] = UncompressCPixel(buffer);
+ /* read palettized pixels */
+ i=j=0;
+ while(j<h) {
+ int color,length;
+ /* read color */
+ if(buffer>=buffer_end)
+ return -10;
+ color = palette[(*buffer)&0x7f];
+ length=1;
+ if(*buffer&0x80) {
+ if(buffer+1>=buffer_end)
+ return -11;
+ buffer++;
+ /* read run length */
+ while(*buffer==0xff) {
+ if(buffer+1>=buffer_end)
+ return -8;
+ length+=*buffer;
+ buffer++;
+ }
+ length+=*buffer;
+ }
+ buffer++;
+ while(j<h && length>0) {
+ ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
+ length--;
+ i++;
+ if(i>=w) {
+ i=0;
+ j++;
+ }
+ }
+ if(length>0)
+ rfbClientLog("Warning: possible ZRLE corruption\n");
+ }
+ }
+ }
+
+ return buffer-buffer_copy;
+}
+
+#undef CARDBPP
+#undef CARDREALBPP
+#undef HandleZRLE
+#undef HandleZRLETile
+#undef UncompressCPixel
+#undef REALBPP
+
+#endif
+
+#undef UNCOMP