1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbserver.c - deal with server-side of the RFB protocol.
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2011-2012 D. R. Commander
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2002 RealVNC Ltd.
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  All Rights Reserved.
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This is free software; you can redistribute it and/or modify
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  it under the terms of the GNU General Public License as published by
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  the Free Software Foundation; either version 2 of the License, or
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  (at your option) any later version.
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This software is distributed in the hope that it will be useful,
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  GNU General Public License for more details.
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  You should have received a copy of the GNU General Public License
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  along with this software; if not, write to the Free Software
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  USA.
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __STRICT_ANSI__
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define _BSD_SOURCE
311d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define _POSIX_SOURCE
321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define _XOPEN_SOURCE 600
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
341d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
351d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <stdio.h>
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <string.h>
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h>
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfbregion.h>
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "private.h"
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_FCNTL_H
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <fcntl.h>
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32
461d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <winsock2.h>
471d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <ws2tcpip.h>
481d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <io.h>
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define write(sock,buf,len) send(sock,buf,len,0)
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_UNISTD_H
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <unistd.h>
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <pwd.h>
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/socket.h>
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/in.h>
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/tcp.h>
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netdb.h>
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <arpa/inet.h>
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef DEBUGPROTO
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef DEBUGPROTO
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define DEBUGPROTO(x) x
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define DEBUGPROTO(x)
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <stdarg.h>
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <scale.h>
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* stst() */
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/types.h>
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/stat.h>
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <unistd.h>
781d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
791d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifndef WIN32
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* readdir() */
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <dirent.h>
821d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
831d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* errno */
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <errno.h>
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* strftime() */
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <time.h>
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "rfbssl.h"
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
931d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef _MSC_VER
941d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define snprintf _snprintf /* Missing in MSVC */
951d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman/* Prevent POSIX deprecation warnings */
961d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define close _close
971d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define strdup _strdup
981d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
991d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
1001d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __MINGW32__
1021d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */
1031d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else /* MSVC and other windows compilers */
1041d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */
1051d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif /* __MINGW32__ else... */
1061d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#define S_ISDIR(m)	(((m) & S_IFDIR) == S_IFDIR)
1071d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#include <direct.h>
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Map of quality levels to provide compatibility with TightVNC/TigerVNC
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * clients.  This emulates the behavior of the TigerVNC Server.
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic const int tight2turbo_qual[10] = {
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat};
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic const int tight2turbo_subsamp[10] = {
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat};
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void rfbProcessClientProtocolVersion(rfbClientPtr cl);
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void rfbProcessClientNormalMessage(rfbClientPtr cl);
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void rfbProcessClientInitMessage(rfbClientPtr cl);
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbIncrClientRef(rfbClientPtr cl)
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  LOCK(cl->refCountMutex);
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  cl->refCount++;
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  UNLOCK(cl->refCountMutex);
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbDecrClientRef(rfbClientPtr cl)
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  LOCK(cl->refCountMutex);
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  cl->refCount--;
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(cl->refCount<=0) /* just to be sure also < 0 */
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    TSIGNAL(cl->deleteCond);
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  UNLOCK(cl->refCountMutex);
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbIncrClientRef(rfbClientPtr cl) {}
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbDecrClientRef(rfbClientPtr cl) {}
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic MUTEX(rfbClientListMutex);
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstruct rfbClientIterator {
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientPtr next;
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbScreenInfoPtr screen;
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbBool closedToo;
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat};
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientListInit(rfbScreenInfoPtr rfbScreen)
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(sizeof(rfbBool)!=1) {
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* a sanity check */
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool));
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* we cannot continue, because rfbBool is supposed to be char everywhere */
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	exit(1);
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbScreen->clientHead = NULL;
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    INIT_MUTEX(rfbClientListMutex);
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientIteratorPtr
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientIteratorPtr i =
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->next = NULL;
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->screen = rfbScreen;
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->closedToo = FALSE;
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return i;
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientIteratorPtr
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen)
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientIteratorPtr i =
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->next = NULL;
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->screen = rfbScreen;
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->closedToo = TRUE;
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return i;
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientPtr
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientIteratorHead(rfbClientIteratorPtr i)
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(i->next != 0) {
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDecrClientRef(i->next);
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbIncrClientRef(i->screen->clientHead);
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  LOCK(rfbClientListMutex);
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  i->next = i->screen->clientHead;
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  UNLOCK(rfbClientListMutex);
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return i->next;
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientPtr
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientIteratorNext(rfbClientIteratorPtr i)
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(i->next == 0) {
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(rfbClientListMutex);
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    i->next = i->screen->clientHead;
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(rfbClientListMutex);
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  } else {
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    IF_PTHREADS(rfbClientPtr cl = i->next);
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    i->next = i->next->next;
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    IF_PTHREADS(rfbDecrClientRef(cl));
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(!i->closedToo)
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      while(i->next && i->next->sock<0)
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        i->next = i->next->next;
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(i->next)
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbIncrClientRef(i->next);
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return i->next;
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbReleaseClientIterator(rfbClientIteratorPtr iterator)
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  free(iterator);
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbNewClientConnection is called from sockets.c when a new connection
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * comes in.
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int sock)
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbNewClient(rfbScreen,sock);
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbReverseConnection is called to make an outward
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * connection to a "listening" RFB client.
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientPtr
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbReverseConnection(rfbScreenInfoPtr rfbScreen,
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                     char *host,
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                     int port)
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int sock;
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr cl;
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return (rfbClientPtr)NULL;
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl = rfbNewClient(rfbScreen, sock);
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl) {
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->reverseConnection = TRUE;
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return cl;
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Permit the server to set the version to report */
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* TODO: sanity checking */
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((major_==3) && (minor_ > 2 && minor_ < 9))
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScreen->protocolMajorVersion = major_;
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScreen->protocolMinorVersion = minor_;
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    else
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_);
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbNewClient is called when a new connection has been made by whatever
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * means.
298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbClientPtr
301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                     int sock,
303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                     rfbBool isUDP)
304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbProtocolVersionMsg pv;
306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientIteratorPtr iterator;
307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr cl,cl_;
308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6
309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct sockaddr_storage addr;
310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct sockaddr_in addr;
312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    socklen_t addrlen = sizeof(addr);
314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbProtocolExtension* extension;
315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->screen = rfbScreen;
319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->sock = sock;
320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->viewOnly = FALSE;
321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* setup pseudo scaling */
322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->scaledScreen = rfbScreen;
323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->scaledScreen->scaledScreenRefCount++;
324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbResetStats(cl);
326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->clientData = NULL;
328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->clientGoneHook = rfbDoNothingWithClient;
329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(isUDP) {
331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLog(" accepted UDP client\n");
3321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman	} else {
3331d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef LIBVNCSERVER_IPv6
3341d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman		char host[1024];
3351d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      int one=1;
337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      getpeername(sock, (struct sockaddr *)&addr, &addrlen);
339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6
340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLogPerror("rfbNewClient: error in getnameinfo");
342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->host = strdup("");
343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      else
345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->host = strdup(host);
346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->host = strdup(inet_ntoa(addr.sin_addr));
348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLog("  other clients:\n");
351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      iterator = rfbGetClientIterator(rfbScreen);
352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("     %s\n",cl_->host);
354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbReleaseClientIterator(iterator);
356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(!rfbSetNonBlocking(sock)) {
358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(sock);
359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return NULL;
360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		     (char *)&one, sizeof(one)) < 0) {
364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLogPerror("setsockopt failed");
365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(sock);
366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return NULL;
367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      FD_SET(sock,&(rfbScreen->allFds));
370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_MUTEX(cl->outputMutex);
373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_MUTEX(cl->refCountMutex);
374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_MUTEX(cl->sendMutex);
375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_COND(cl->deleteCond);
376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->state = RFB_PROTOCOL_VERSION;
378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->reverseConnection = FALSE;
380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->readyForSetColourMapEntries = FALSE;
381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->useCopyRect = FALSE;
382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->preferredEncoding = -1;
383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->correMaxWidth = 48;
384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->correMaxHeight = 48;
385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->zrleData = NULL;
387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->copyRegion = sraRgnCreate();
390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->copyDX = 0;
391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->copyDY = 0;
392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->modifiedRegion =
394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_MUTEX(cl->updateMutex);
397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      INIT_COND(cl->updateCond);
398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->requestedRegion = sraRgnCreate();
400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->format = cl->screen->serverFormat;
402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->translateFn = rfbTranslateNone;
403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->translateLookupTable = NULL;
404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      LOCK(rfbClientListMutex);
406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      IF_PTHREADS(cl->refCount = 0);
408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->next = rfbScreen->clientHead;
409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->prev = NULL;
410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (rfbScreen->clientHead)
411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbScreen->clientHead->prev = cl;
412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScreen->clientHead = cl;
414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      UNLOCK(rfbClientListMutex);
415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->tightQualityLevel = -1;
418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->turboSubsampLevel = TURBO_DEFAULT_SUBSAMP;
421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      {
422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int i;
423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	for (i = 0; i < 4; i++)
424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          cl->zsActive[i] = FALSE;
425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->fileTransfer.fd = -1;
430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableCursorShapeUpdates = FALSE;
432a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableCursorPosUpdates = FALSE;
433a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->useRichCursorEncoding = FALSE;
434a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableLastRectEncoding = FALSE;
435a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableKeyboardLedState = FALSE;
436a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableSupportedMessages = FALSE;
437a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableSupportedEncodings = FALSE;
438a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->enableServerIdentity = FALSE;
439a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->lastKeyboardLedState = -1;
440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->cursorX = rfbScreen->cursorX;
441a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->cursorY = rfbScreen->cursorY;
442a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->useNewFBSize = FALSE;
443a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
444a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
445a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStreamInited = FALSE;
446a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStream.total_in = 0;
447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStream.total_out = 0;
448a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStream.zalloc = Z_NULL;
449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStream.zfree = Z_NULL;
450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->compStream.opaque = Z_NULL;
451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->zlibCompressLevel = 5;
453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->progressiveSliceY = 0;
456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->extensions = NULL;
458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->lastPtrX = -1;
460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      /*
463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       * Wait a few ms for the client to send one of:
464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       * - Flash policy request
465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       * - WebSockets connection (TLS/SSL or plain)
466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       */
467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (!webSocketsCheck(cl)) {
468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Error reporting handled in webSocketsHandshake */
469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbClientConnectionGone(cl);
471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return NULL;
472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion,
476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              rfbScreen->protocolMinorVersion);
477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbNewClient: write");
480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbClientConnectionGone(cl);
482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return NULL;
483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for(extension = rfbGetExtensionIterator(); extension;
487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    extension=extension->next) {
488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	void* data = NULL;
489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* if the extension does not have a newClient method, it wants
490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 * to be initialized later. */
491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(extension->newClient && extension->newClient(cl, &data))
492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbEnableExtension(cl, extension, data);
493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbReleaseExtensionIterator();
495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (cl->screen->newClientHook(cl)) {
497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_CLIENT_ON_HOLD:
498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->onHold = TRUE;
499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_CLIENT_ACCEPT:
501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->onHold = FALSE;
502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_CLIENT_REFUSE:
504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbClientConnectionGone(cl);
506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl = NULL;
507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return cl;
510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientPtr
513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbNewClient(rfbScreenInfoPtr rfbScreen,
514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             int sock)
515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientPtr
520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbNewUDPClient(rfbScreenInfoPtr rfbScreen)
521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return((rfbScreen->udpClient=
523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbClientConnectionGone is called from sockets.c just after a connection
528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * has gone away.
529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientConnectionGone(rfbClientPtr cl)
533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBZ) && defined(LIBVNCSERVER_HAVE_LIBJPEG)
535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int i;
536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(rfbClientListMutex);
539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->prev)
541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->prev->next = cl->next;
542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    else
543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->screen->clientHead = cl->next;
544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->next)
545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->next->prev = cl->prev;
546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(rfbClientListMutex);
548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->screen->backgroundLoop != FALSE) {
551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      int i;
552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      do {
553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	LOCK(cl->refCountMutex);
554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	i=cl->refCount;
555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(i>0)
556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  WAIT(cl->deleteCond,cl->refCountMutex);
557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	UNLOCK(cl->refCountMutex);
558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      } while(i>0);
559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->sock>=0)
563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(cl->sock);
564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->scaledScreen!=NULL)
566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->scaledScreen->scaledScreenRefCount--;
567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFreeZrleData(cl);
570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFreeUltraData(cl);
573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* free buffers holding pixel data before and after encoding */
575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(cl->beforeEncBuf);
576a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(cl->afterEncBuf);
577a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
578a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->sock>=0)
579a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       FD_CLR(cl->sock,&(cl->screen->allFds));
580a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->clientGoneHook(cl);
582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("Client %s gone\n",cl->host);
584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(cl->host);
585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Release the compression state structures if any. */
588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( cl->compStreamInited ) {
589a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	deflateEnd( &(cl->compStream) );
590a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
591a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
592a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
593a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (i = 0; i < 4; i++) {
594a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (cl->zsActive[i])
595a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    deflateEnd(&cl->zsStruct[i]);
596a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
597a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
598a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
599a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
600a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->screen->pointerClient == cl)
601a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->screen->pointerClient = NULL;
602a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
603a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(cl->modifiedRegion);
604a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(cl->requestedRegion);
605a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(cl->copyRegion);
606a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
607a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->translateLookupTable) free(cl->translateLookupTable);
608a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
609a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    TINI_COND(cl->updateCond);
610a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    TINI_MUTEX(cl->updateMutex);
611a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
612a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* make sure outputMutex is unlocked before destroying */
613a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->outputMutex);
614a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(cl->outputMutex);
615a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    TINI_MUTEX(cl->outputMutex);
616a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
617a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->sendMutex);
618a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(cl->sendMutex);
619a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    TINI_MUTEX(cl->sendMutex);
620a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
621a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbPrintStats(cl);
622a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbResetStats(cl);
623a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
624a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(cl);
625a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
626a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
627a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
628a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
629a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbProcessClientMessage is called when there is data to read from a client.
630a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
631a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
632a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
633a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbProcessClientMessage(rfbClientPtr cl)
634a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
635a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (cl->state) {
636a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_PROTOCOL_VERSION:
637a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbProcessClientProtocolVersion(cl);
638a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
639a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_SECURITY_TYPE:
640a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbProcessClientSecurityType(cl);
641a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
642a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_AUTHENTICATION:
643a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbAuthProcessClientMessage(cl);
644a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
645a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_INITIALISATION:
646a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case RFB_INITIALISATION_SHARED:
647a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbProcessClientInitMessage(cl);
648a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
649a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    default:
650a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbProcessClientNormalMessage(cl);
651a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
652a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
653a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
654a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
655a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
656a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
657a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbProcessClientProtocolVersion is called when the client sends its
658a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * protocol version.
659a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
660a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
661a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void
662a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbProcessClientProtocolVersion(rfbClientPtr cl)
663a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
664a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbProtocolVersionMsg pv;
665a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int n, major_, minor_;
666a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
667a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
668a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (n == 0)
669a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLog("rfbProcessClientProtocolVersion: client gone\n");
670a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        else
671a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbProcessClientProtocolVersion: read");
672a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
673a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
674a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
675a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
676a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    pv[sz_rfbProtocolVersionMsg] = 0;
677a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
678a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv);
679a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbCloseClient(cl);
680a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
681a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
682a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
683a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
684a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (major_ != rfbProtocolMajorVersion) {
685a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
686a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
687a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                major_,minor_);
688a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
689a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
690a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
691a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
692a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Check for the minor version use either of the two standard version of RFB */
693a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
694a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
695a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * 3.4, 3.6, 3.14, 3.16
696a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * It's a bad method, but it is what they use to enable features...
697a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * maintaining RFB version compatibility across multiple servers is a pain
698a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Should use something like ServerIdentity encoding
699a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
700a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->protocolMajorVersion = major_;
701a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->protocolMinorVersion = minor_;
702a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
703a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("Protocol version sent %d.%d, using %d.%d\n",
704a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion);
705a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
706a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbAuthNewClient(cl);
707a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
708a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
709a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
710a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
711a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientSendString(rfbClientPtr cl, const char *reason)
712a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
713a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *buf;
714a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int len = strlen(reason);
715a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
716a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("rfbClientSendString(\"%s\")\n", reason);
717a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
718a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    buf = (char *)malloc(4 + len);
719a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ((uint32_t *)buf)[0] = Swap32IfLE(len);
720a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(buf + 4, reason, len);
721a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
722a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, buf, 4 + len) < 0)
723a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbClientSendString: write");
724a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(buf);
725a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
726a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbCloseClient(cl);
727a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
728a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
729a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
730a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbClientConnFailed is called when a client connection has failed either
731a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * because it talks the wrong protocol or it has failed authentication.
732a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
733a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
734a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
735a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbClientConnFailed(rfbClientPtr cl,
736a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    const char *reason)
737a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
738a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *buf;
739a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int len = strlen(reason);
740a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
741a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
742a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
743a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    buf = (char *)malloc(8 + len);
744a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
745a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ((uint32_t *)buf)[1] = Swap32IfLE(len);
746a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(buf + 8, reason, len);
747a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
748a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, buf, 8 + len) < 0)
749a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbClientConnFailed: write");
750a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    free(buf);
751a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
752a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbCloseClient(cl);
753a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
754a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
755a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
756a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
757a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbProcessClientInitMessage is called when the client sends its
758a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * initialisation message.
759a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
760a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
761a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void
762a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbProcessClientInitMessage(rfbClientPtr cl)
763a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
764a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientInitMsg ci;
765a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    union {
766a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        char buf[256];
767a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbServerInitMsg si;
768a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } u;
769a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int len, n;
770a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientIteratorPtr iterator;
771a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr otherCl;
772a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbExtensionData* extension;
773a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
774a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->state == RFB_INITIALISATION_SHARED) {
775a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* In this case behave as though an implicit ClientInit message has
776a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * already been received with a shared-flag of true. */
777a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        ci.shared = 1;
778a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Avoid the possibility of exposing the RFB_INITIALISATION_SHARED
779a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * state to calling software. */
780a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->state = RFB_INITIALISATION;
781a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
782a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
783a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n == 0)
784a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbProcessClientInitMessage: client gone\n");
785a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else
786a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientInitMessage: read");
787a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
788a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
789a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
790a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
791a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
792a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memset(u.buf,0,sizeof(u.buf));
793a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
794a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.framebufferWidth = Swap16IfLE(cl->screen->width);
795a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.framebufferHeight = Swap16IfLE(cl->screen->height);
796a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.format = cl->screen->serverFormat;
797a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.format.redMax = Swap16IfLE(u.si.format.redMax);
798a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.format.greenMax = Swap16IfLE(u.si.format.greenMax);
799a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.format.blueMax = Swap16IfLE(u.si.format.blueMax);
800a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
801a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    strncpy(u.buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
802a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    len = strlen(u.buf + sz_rfbServerInitMsg);
803a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    u.si.nameLength = Swap32IfLE(len);
804a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
805a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, u.buf, sz_rfbServerInitMsg + len) < 0) {
806a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbProcessClientInitMessage: write");
807a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
808a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
809a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
810a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
811a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for(extension = cl->extensions; extension;) {
812a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbExtensionData* next = extension->next;
813a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(extension->extension->init &&
814a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		!extension->extension->init(cl, extension->data))
815a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    /* extension requested that it be removed */
816a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbDisableExtension(cl, extension->extension);
817a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	extension = next;
818a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
819a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
820a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->state = RFB_NORMAL;
821a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
822a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!cl->reverseConnection &&
823a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                        (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) {
824a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
825a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->screen->dontDisconnect) {
826a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            iterator = rfbGetClientIterator(cl->screen);
827a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
828a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
829a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("-dontdisconnect: Not shared & existing client\n");
830a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("  refusing new client %s\n", cl->host);
831a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbCloseClient(cl);
832a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbReleaseClientIterator(iterator);
833a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return;
834a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
835a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
836a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbReleaseClientIterator(iterator);
837a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        } else {
838a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            iterator = rfbGetClientIterator(cl->screen);
839a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
840a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
841a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("Not shared - closing connection to client %s\n",
842a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           otherCl->host);
843a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbCloseClient(otherCl);
844a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
845a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
846a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbReleaseClientIterator(iterator);
847a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
848a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
849a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
850a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
851a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* The values come in based on the scaled screen, we need to convert them to
852a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * values based on the man screen's coordinate system
853a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
854a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
855a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbClientPtr cl)
856a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
857a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int x1=Swap16IfLE(*x);
858a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int y1=Swap16IfLE(*y);
859a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int w1=Swap16IfLE(*w);
860a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	int h1=Swap16IfLE(*h);
861a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
862a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip");
863a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	*x = x1;
864a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	*y = y1;
865a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	*w = w1;
866a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	*h = h1;
867a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
868a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(*w>cl->screen->width-*x)
869a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		*w=cl->screen->width-*x;
870a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* possible underflow */
871a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(*w>cl->screen->width-*x)
872a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return FALSE;
873a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(*h>cl->screen->height-*y)
874a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		*h=cl->screen->height-*y;
875a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(*h>cl->screen->height-*y)
876a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return FALSE;
877a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
878a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return TRUE;
879a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
880a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
881a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
882a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send keyboard state (PointerPos pseudo-encoding).
883a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
884a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
885a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
886a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendKeyboardLedState(rfbClientPtr cl)
887a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
888a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
889a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
890a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
891a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
892a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
893a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
894a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
895a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
896a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
897a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
898a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = 0;
899a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = 0;
900a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
901a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
902a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader);
903a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
904a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
905a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
906a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
907a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl))
908a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
909a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
910a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
911a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
912a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
913a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
914a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))
915a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
916a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
917a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send rfbEncodingSupportedMessages.
918a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
919a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
920a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
921a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendSupportedMessages(rfbClientPtr cl)
922a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
923a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
924a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSupportedMessages msgs;
925a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
926a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
927a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
928a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
929a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
930a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
931a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
932a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
933a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = 0;
934a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
935a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(sz_rfbSupportedMessages);
936a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = 0;
937a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
938a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
939a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader);
940a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
941a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
942a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memset((char *)&msgs, 0, sz_rfbSupportedMessages);
943a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbSetPixelFormat);
944a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
945a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbSetEncodings);
946a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
947a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbKeyEvent);
948a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbPointerEvent);
949a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbClientCutText);
950a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbFileTransfer);
951a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbSetScale);
952a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*rfbSetBit(msgs.client2server, rfbSetServerInput);  */
953a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*rfbSetBit(msgs.client2server, rfbSetSW);           */
9541d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    /*rfbSetBit(msgs.client2server, rfbTextChat);        */
955a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
956a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.client2server, rfbXvp);
957a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
958a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
959a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
960a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbBell);
961a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbServerCutText);
962a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
963a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
964a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetBit(msgs.server2client, rfbXvp);
965a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
966a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
967a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbSupportedMessages;
968a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
969a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages,
970a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages,
971a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages);
972a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl))
973a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
974a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
975a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
976a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
977a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
978a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
979a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
980a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
981a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send rfbEncodingSupportedEncodings.
982a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
983a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
984a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
985a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendSupportedEncodings(rfbClientPtr cl)
986a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
987a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
988a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    static uint32_t supported[] = {
989a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbEncodingRaw,
990a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingCopyRect,
991a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingRRE,
992a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingCoRRE,
993a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingHextile,
994a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
995a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingZlib,
996a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingZRLE,
997a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingZYWRLE,
998a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
999a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
1000a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingTight,
1001a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1002a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPNG
1003a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingTightPng,
1004a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1005a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingUltra,
1006a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingUltraZip,
1007a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingXCursor,
1008a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingRichCursor,
1009a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingPointerPos,
1010a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingLastRect,
1011a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingNewFBSize,
1012a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingKeyboardLedState,
1013a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingSupportedMessages,
1014a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingSupportedEncodings,
1015a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbEncodingServerIdentity,
1016a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    };
1017a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t nEncodings = sizeof(supported) / sizeof(supported[0]), i;
1018a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1019a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* think rfbSetEncodingsMsg */
1020a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1021a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
1022a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  + (nEncodings * sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
1023a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
1024a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
1025a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1026a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1027a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
1028a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = 0;
1029a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
1030a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
1031a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = Swap16IfLE(nEncodings);
1032a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1033a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1034a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader);
1035a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1036a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1037a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (i = 0; i < nEncodings; i++) {
1038a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        uint32_t encoding = Swap32IfLE(supported[i]);
1039a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	memcpy(&cl->updateBuf[cl->ublen], (char *)&encoding, sizeof(encoding));
1040a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->ublen += sizeof(encoding);
1041a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1042a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1043a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings,
1044a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)),
1045a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)));
1046a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1047a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl))
1048a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
1049a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1050a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1051a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1052a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1053a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1054a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
1055a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
1056a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1057a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char buffer[256];
1058a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    va_list ap;
1059a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1060a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    va_start(ap, fmt);
1061a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
1062a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    va_end(ap);
1063a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1064a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (screen->versionString!=NULL) free(screen->versionString);
1065a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    screen->versionString = strdup(buffer);
1066a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1067a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1068a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
1069a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send rfbEncodingServerIdentity.
1070a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
1071a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1072a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
1073a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendServerIdentity(rfbClientPtr cl)
1074a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1075a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
1076a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char buffer[512];
1077a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1078a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* tack on our library version */
1079a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
1080a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
1081a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        LIBVNCSERVER_PACKAGE_STRING);
1082a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1083a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
1084a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
1085a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
1086a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
1087a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1088a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1089a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
1090a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = 0;
1091a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
1092a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(strlen(buffer)+1);
1093a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = 0;
1094a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1095a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
1096a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader);
1097a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
1098a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1099a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
1100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += strlen(buffer)+1;
1101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity,
1103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1,
1104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1);
1105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl))
1108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
1109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
1114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send an xvp server message
1115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
1116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
1118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendXvp(rfbClientPtr cl, uint8_t version, uint8_t code)
1119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbXvpMsg xvp;
1121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    xvp.type = rfbXvp;
1123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    xvp.pad = 0;
1124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    xvp.version = version;
1125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    xvp.code = code;
1126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->sendMutex);
1128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, (char *)&xvp, sz_rfbXvpMsg) < 0) {
1129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLogPerror("rfbSendXvp: write");
1130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbCloseClient(cl);
1131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(cl->sendMutex);
1133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbXvp, sz_rfbXvpMsg, sz_rfbXvpMsg);
1135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
1141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbTextChatMsg tc;
1143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int bytesToSend=0;
1144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memset((char *)&tc, 0, sizeof(tc));
1146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    tc.type = rfbTextChat;
1147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    tc.length = Swap32IfLE(length);
1148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch(length) {
1150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbTextChatOpen:
1151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbTextChatClose:
1152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbTextChatFinished:
1153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        bytesToSend=0;
1154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    default:
1156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        bytesToSend=length;
1157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (bytesToSend>rfbTextMaxSize)
1158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            bytesToSend=rfbTextMaxSize;
1159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) {
1162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
1163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
1164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg);
1167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbTextChatMsg;
1168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (bytesToSend>0) {
1169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend);
1170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->ublen += bytesToSend;
1171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend);
1173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl))
1175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
1176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
1181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ((cl->screen->getFileTransferPermission != NULL \
1182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
1183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    || cl->screen->permitFileTransfer != TRUE) { \
1184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
1185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbCloseClient(cl); \
1186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return ret; \
1187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
1188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint DB = 1;
1190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, const char *buffer)
1192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFileTransferMsg ft;
1194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.type = rfbFileTransfer;
1195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.contentType = contentType;
1196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.contentParam = contentParam;
1197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.pad          = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */
1198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.size         = Swap32IfLE(size);
1199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    ft.length       = Swap32IfLE(length);
1200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer);
1204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    */
1205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->sendMutex);
1206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) {
1207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbSendFileTransferMessage: write");
1208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
1209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        UNLOCK(cl->sendMutex);
1210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
1211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (length>0)
1214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
1215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (rfbWriteExact(cl, buffer, length) < 0) {
1216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbSendFileTransferMessage: write");
1217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
1218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            UNLOCK(cl->sendMutex);
1219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
1220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(cl->sendMutex);
1223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length);
1225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
1231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * UltraVNC uses Windows Structures
1232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
1233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define MAX_PATH 260
1234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehattypedef struct {
1236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t dwLowDateTime;
1237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t dwHighDateTime;
1238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} RFB_FILETIME;
1239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehattypedef struct {
1241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t dwFileAttributes;
1242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    RFB_FILETIME ftCreationTime;
1243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    RFB_FILETIME ftLastAccessTime;
1244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    RFB_FILETIME ftLastWriteTime;
1245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t nFileSizeHigh;
1246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t nFileSizeLow;
1247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t dwReserved0;
1248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t dwReserved1;
1249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint8_t  cFileName[ MAX_PATH ];
1250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint8_t  cAlternateFileName[ 14 ];
1251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} RFB_FIND_DATA;
1252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_READONLY   0x1
1254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_HIDDEN     0x2
1255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_SYSTEM     0x4
1256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_DIRECTORY  0x10
1257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_ARCHIVE    0x20
1258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_NORMAL     0x80
1259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_TEMPORARY  0x100
1260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
1261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
12621d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg HartmanrfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, /* in */ char *path, /* out */ char *unixPath, size_t unixPathMaxLen)
1263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int x;
1265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *home=NULL;
1266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
12691d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    /*
12701d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman     * Do not use strncpy() - truncating the file name would probably have undesirable side effects
12711d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman     * Instead check if destination buffer is big enough
12721d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman     */
12731d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    if (strlen(path) >= unixPathMaxLen)
12741d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman      return FALSE;
12751d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
1276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* C: */
1277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (path[0]=='C' && path[1]==':')
1278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      strcpy(unixPath, &path[2]);
1279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    else
1280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
1281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      home = getenv("HOME");
1282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (home!=NULL)
1283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      {
12841d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        /* Re-check buffer size */
12851d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        if ((strlen(path) + strlen(home) + 1) >= unixPathMaxLen)
12861d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          return FALSE;
12871d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
1288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        strcpy(unixPath, home);
1289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        strcat(unixPath,"/");
1290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        strcat(unixPath, path);
1291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
1292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      else
1293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        strcpy(unixPath, path);
1294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (x=0;x<strlen(unixPath);x++)
1296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (unixPath[x]=='\\') unixPath[x]='/';
1297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbFilenameTranslate2DOS(rfbClientPtr cl, char *unixPath, char *path)
1301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int x;
1303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sprintf(path,"C:%s", unixPath);
1307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (x=2;x<strlen(path);x++)
1308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (path[x]=='/') path[x]='\\';
1309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
1313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char retfilename[MAX_PATH];
1315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char path[MAX_PATH];
1316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct stat statbuf;
1317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    RFB_FIND_DATA win32filename;
1318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nOptLen = 0, retval=0;
13191d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
13201d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    WIN32_FIND_DATAA winFindData;
13211d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    HANDLE findHandle;
13221d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    int pathLen, basePathLength;
13231d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    char *basePath;
13241d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    DIR *dirp=NULL;
1326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct dirent *direntp=NULL;
13271d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Client thinks we are Winblows */
13321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    if (!rfbFilenameTranslate2UNIX(cl, buffer, path, sizeof(path)))
13331d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        return FALSE;
1334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
1336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
13371d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
13381d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    // Create a search string, like C:\folder\*
13391d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
13401d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    pathLen = strlen(path);
13411d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    basePath = malloc(pathLen + 3);
13421d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    memcpy(basePath, path, pathLen);
13431d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    basePathLength = pathLen;
13441d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    basePath[basePathLength] = '\\';
13451d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    basePath[basePathLength + 1] = '*';
13461d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    basePath[basePathLength + 2] = '\0';
13471d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
13481d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    // Start a search
13491d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    memset(&winFindData, 0, sizeof(winFindData));
13501d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    findHandle = FindFirstFileA(path, &winFindData);
13511d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    free(basePath);
13521d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
13531d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    if (findHandle == INVALID_HANDLE_VALUE)
13541d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    dirp=opendir(path);
1356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (dirp==NULL)
13571d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);
13591d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
1360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* send back the path name (necessary for links) */
1361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;
13621d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
13631d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
13641d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    while (findHandle != INVALID_HANDLE_VALUE)
13651d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
13671d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
1369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* get stats */
13701d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
13711d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, winFindData.cFileName);
13721d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
13731d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
13741d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        retval = stat(retfilename, &statbuf);
1376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (retval==0)
1378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
1379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            memset((char *)&win32filename, 0, sizeof(win32filename));
13801d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
13811d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.dwFileAttributes = winFindData.dwFileAttributes;
13821d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftCreationTime.dwLowDateTime = winFindData.ftCreationTime.dwLowDateTime;
13831d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftCreationTime.dwHighDateTime = winFindData.ftCreationTime.dwHighDateTime;
13841d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftLastAccessTime.dwLowDateTime = winFindData.ftLastAccessTime.dwLowDateTime;
13851d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftLastAccessTime.dwHighDateTime = winFindData.ftLastAccessTime.dwHighDateTime;
13861d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftLastWriteTime.dwLowDateTime = winFindData.ftLastWriteTime.dwLowDateTime;
13871d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.ftLastWriteTime.dwHighDateTime = winFindData.ftLastWriteTime.dwHighDateTime;
13881d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.nFileSizeLow = winFindData.nFileSizeLow;
13891d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.nFileSizeHigh = winFindData.nFileSizeHigh;
13901d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.dwReserved0 = winFindData.dwReserved0;
13911d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            win32filename.dwReserved1 = winFindData.dwReserved1;
13921d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            strcpy((char *)win32filename.cFileName, winFindData.cFileName);
13931d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            strcpy((char *)win32filename.cAlternateFileName, winFindData.cAlternateFileName);
13941d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
1396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (S_ISDIR(statbuf.st_mode))
13971d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
1398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime);   /* Intel Order */
1399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftCreationTime.dwHighDateTime = 0;
1400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
1401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftLastAccessTime.dwHighDateTime = 0;
1402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime);  /* Intel Order */
1403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.ftLastWriteTime.dwHighDateTime = 0;
1404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */
1405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.nFileSizeHigh = 0;
1406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.dwReserved0 = 0;
1407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            win32filename.dwReserved1 = 0;
1408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* If this had the full path, we would need to translate to DOS format ("C:\") */
1410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
1411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            strcpy((char *)win32filename.cFileName, direntp->d_name);
14121d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* Do not show hidden files (but show how to move up the tree) */
14151d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            if ((strcmp((char *)win32filename.cFileName, "..")==0) || (win32filename.cFileName[0]!='.'))
1416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
1418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /*
1419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
1420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                */
1421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE)
1422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
14231d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
14241d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                    FindClose(findHandle);
14251d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    closedir(dirp);
14271d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return FALSE;
1429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
14321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
14331d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
14341d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        if (FindNextFileA(findHandle, &winFindData) == 0)
14351d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        {
14361d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            FindClose(findHandle);
14371d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            findHandle = INVALID_HANDLE_VALUE;
14381d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        }
14391d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
14411d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#ifdef WIN32
14421d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    if (findHandle != INVALID_HANDLE_VALUE)
14431d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    {
14441d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        FindClose(findHandle);
14451d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    }
14461d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#else
1447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    closedir(dirp);
14481d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman#endif
1449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* End of the transfer */
1450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
1451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatchar *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
1455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *buffer=NULL;
1457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int   n=0;
1458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);
1460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
1462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    */
1463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (length>0) {
1464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        buffer=malloc(length+1);
1465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (buffer!=NULL) {
1466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
1467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (n != 0)
1468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLogPerror("rfbProcessFileTransferReadBuffer: read");
1469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbCloseClient(cl);
1470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* NOTE: don't forget to free(buffer) if you return early! */
1471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (buffer!=NULL) free(buffer);
1472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return NULL;
1473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* Null Terminate */
1475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            buffer[length]=0;
1476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return buffer;
1479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
1483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Allocate buffer for compression */
1485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned char readBuf[sz_rfbBlockSize];
1486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int bytesRead=0;
1487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int retval=0;
1488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    fd_set wfds;
1489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct timeval tv;
1490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int n;
1491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
1492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned char compBuf[sz_rfbBlockSize + 1024];
1493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned long nMaxCompSize = sizeof(compBuf);
1494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nRetC = 0;
1495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Don't close the client if we get into this one because
1499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * it is called from many places to service file transfers.
1500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Note that permitFileTransfer is checked first.
1501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
1502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->screen->permitFileTransfer != TRUE ||
1503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       (cl->screen->getFileTransferPermission != NULL
1504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        && cl->screen->getFileTransferPermission(cl) != TRUE)) {
1505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return TRUE;
1506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* If not sending, or no file open...   Return as if we sent something! */
1509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
1510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
1511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	FD_ZERO(&wfds);
1512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        FD_SET(cl->sock, &wfds);
1513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* return immediately */
1515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	tv.tv_sec = 0;
1516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	tv.tv_usec = 0;
1517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	n = select(cl->sock + 1, NULL, &wfds, NULL, &tv);
1518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (n<0) {
1520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32
1521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    errno=WSAGetLastError();
1522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno));
1524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
1525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* We have space on the transmit queue */
1526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (n > 0)
1527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	{
1528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize);
1529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            switch (bytesRead) {
1530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case 0:
1531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /*
1532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
1533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                */
1534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL);
1535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                close(cl->fileTransfer.fd);
1536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.fd = -1;
1537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.sending   = 0;
1538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.receiving = 0;
1539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return retval;
1540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case -1:
1541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* TODO : send an error msg to the client... */
1542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32
1543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        errno=WSAGetLastError();
1544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno));
1546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL);
1547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                close(cl->fileTransfer.fd);
1548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.fd = -1;
1549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.sending   = 0;
1550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.receiving = 0;
1551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return retval;
1552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            default:
1553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /*
1554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
1555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                */
1556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (!cl->fileTransfer.compressionEnabled)
1557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                else
1559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
1560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
1561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead);
1562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    /*
1563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
1564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    */
1565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    if ((nRetC==0) && (nMaxCompSize<bytesRead))
1567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                        return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 1, nMaxCompSize, (char *)compBuf);
1568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    else
1569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                        return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
1571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    /* We do not support compression of the data stream */
1572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
1573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1576a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1577a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1578a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
1579a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1580a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length)
1582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *buffer=NULL, *p=NULL;
1584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int retval=0;
1585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char filename1[MAX_PATH];
1586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char filename2[MAX_PATH];
1587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char szFileTime[MAX_PATH];
1588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    struct stat statbuf;
1589a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t sizeHtmp=0;
1590a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int n=0;
1591a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char timespec[64];
1592a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
1593a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned char compBuff[sz_rfbBlockSize];
1594a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    unsigned long nRawBytes = sz_rfbBlockSize;
1595a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nRet = 0;
1596a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1597a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1598a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
1599a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1600a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1601a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbLog("rfbProcessFileTransfer(%dtype, %dparam, %dsize, %dlen)\n", contentType, contentParam, size, length);
1602a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    */
1603a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1604a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (contentType) {
1605a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbDirContentRequest:
1606a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        switch (contentParam) {
1607a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbRDrivesList: /* Client requests the List of Local Drives */
1608a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /*
1609a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDrivesList:\n");
1610a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            */
1611a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>
1612a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             *
1613a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * We replace the "\" char following the drive letter and ":"
1614a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * with a char corresponding to the type of drive
1615a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * We obtain something like "C:l<NULL>D:c<NULL>....Z:n\<NULL><NULL>"
1616a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             *  Isn't it ugly ?
1617a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * DRIVE_FIXED = 'l'     (local?)
1618a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * DRIVE_REMOVABLE = 'f' (floppy?)
1619a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * DRIVE_CDROM = 'c'
1620a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * DRIVE_REMOTE = 'n'
1621a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             */
1622a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1623a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* in unix, there are no 'drives'  (We could list mount points though)
1624a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * We fake the root as a "C:" for the Winblows users
1625a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             */
1626a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            filename2[0]='C';
1627a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            filename2[1]=':';
1628a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            filename2[2]='l';
1629a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            filename2[3]=0;
1630a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            filename2[4]=0;
1631a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2);
1632a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1633a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1634a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
1635a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbRDirContent: /* Client requests the content of a directory */
1636a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /*
1637a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n");
1638a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            */
1639a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1640a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            retval = rfbSendDirContent(cl, length, buffer);
1641a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1642a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1643a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1644a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1645a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1646a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbDirPacket:
1647a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbDirPacket\n");
1648a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1649a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileAcceptHeader:
1650a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n");
1651a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1652a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbCommandReturn:
1653a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n");
1654a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1655a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileChecksums:
1656a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Destination file already exists - the viewer sends the checksums */
1657a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n");
1658a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1659a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileTransferAccess:
1660a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n");
1661a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1662a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1663a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1664a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * sending from the server to the viewer
1665a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
1666a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1667a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileTransferRequest:
1668a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1669a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n");
1670a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1671a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* add some space to the end of the buffer as we will be adding a timespec to it */
1672a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1673a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* The client requests a File */
16741d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
16751d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            goto fail;
1676a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
1677a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1678a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1679a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1680a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd);
1681a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1682a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd!=-1) {
1683a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (fstat(cl->fileTransfer.fd, &statbuf)!=0) {
1684a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                close(cl->fileTransfer.fd);
1685a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.fd=-1;
1686a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1687a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else
1688a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1689a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              /* Add the File Time Stamp to the filename */
1690a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime));
1691a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */
1692a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              if (buffer==NULL) {
1693a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2);
1694a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  return FALSE;
1695a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              }
1696a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              strcat(buffer,",");
1697a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              strcat(buffer, timespec);
1698a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              length = strlen(buffer);
1699a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer);
1700a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1701a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1702a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1703a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* The viewer supports compression if size==1 */
1704a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.compressionEnabled = (size==1);
1705a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1706a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1707a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" <Compression Enabled>":""));
1708a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1709a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1710a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* File Size in bytes, 0xFFFFFFFF (-1) means error */
1711a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer);
1712a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1713a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd==-1)
1714a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
1715a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1716a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1717a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1718a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* setup filetransfer stuff */
1719a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.fileSize = statbuf.st_size;
1720a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize;
1721a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.receiving = 0;
1722a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */
1723a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1724a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* TODO: finish 64-bit file size support */
1725a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sizeHtmp = 0;
1726a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        LOCK(cl->sendMutex);
1727a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) {
1728a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          rfbLogPerror("rfbProcessFileTransfer: write");
1729a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          rfbCloseClient(cl);
1730a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          UNLOCK(cl->sendMutex);
1731a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if (buffer!=NULL) free(buffer);
1732a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          return FALSE;
1733a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1734a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        UNLOCK(cl->sendMutex);
1735a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1736a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1737a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileHeader:
1738a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */
1739a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (size==-1) {
1740a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n");
1741a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            close(cl->fileTransfer.fd);
1742a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->fileTransfer.fd=-1;
1743a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return TRUE;
1744a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1745a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1746a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1747a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size);
1748a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1749a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1750a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Starts the transfer! */
1751a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.sending=1;
1752a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return rfbSendFileTransferChunk(cl);
1753a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1754a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1755a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1756a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
1757a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * sending from the viewer to the server
1758a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
1759a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1760a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileTransferOffer:
1761a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* client is sending a file to us */
1762a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* buffer contains full path name (plus FileTime) */
1763a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* size contains size of the file */
1764a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1765a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n");
1766a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1767a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1768a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1769a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Parse the FileTime */
1770a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        p = strrchr(buffer, ',');
1771a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (p!=NULL) {
1772a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            *p = '\0';
17731d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            strncpy(szFileTime, p+1, sizeof(szFileTime));
17741d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            szFileTime[sizeof(szFileTime)-1] = '\x00'; /* ensure NULL terminating byte is present, even if copy overflowed */
1775a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        } else
1776a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            szFileTime[0]=0;
1777a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1778a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1779a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1780a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Need to read in sizeHtmp */
1781a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
1782a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
1783a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp");
1784a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
1785a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* NOTE: don't forget to free(buffer) if you return early! */
1786a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1787a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
1788a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1789a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sizeHtmp = Swap32IfLE(sizeHtmp);
1790a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
17911d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman        if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
17921d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            goto fail;
1793a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1794a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
1795a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* TODO: Delta Transfer */
1796a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1797a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744);
1798a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer(\"%s\"->\"%s\") %s %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), (cl->fileTransfer.fd==-1?strerror(errno):""), cl->fileTransfer.fd);
1799a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1800a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1801a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1802a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* File Size in bytes, 0xFFFFFFFF (-1) means error */
1803a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer);
1804a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd==-1) {
1805a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            free(buffer);
1806a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1807a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1808a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1809a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* setup filetransfer stuff */
1810a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.fileSize = size;
1811a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.numPackets = size / sz_rfbBlockSize;
1812a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.receiving = 1;
1813a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.sending = 0;
1814a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1815a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1816a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFilePacket:
1817a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1818a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n");
1819a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1820a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1821a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd!=-1) {
1822a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* buffer contains the contents of the file */
1823a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (size==0)
1824a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval=write(cl->fileTransfer.fd, buffer, length);
1825a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else
1826a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1827a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
1828a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* compressed packet */
1829a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length);
1830a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(nRet == Z_OK)
1831a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		  retval=write(cl->fileTransfer.fd, (char*)compBuff, nRawBytes);
1832a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		else
1833a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		  retval = -1;
1834a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
1835a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* Write the file out as received... */
1836a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval=write(cl->fileTransfer.fd, buffer, length);
1837a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
1838a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1839a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (retval==-1)
1840a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1841a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                close(cl->fileTransfer.fd);
1842a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.fd=-1;
1843a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.sending   = 0;
1844a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->fileTransfer.receiving = 0;
1845a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1846a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1847a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1848a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1849a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbEndOfFile:
1850a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n");
1851a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1852a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1853a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd!=-1)
1854a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            close(cl->fileTransfer.fd);
1855a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.fd=-1;
1856a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.sending   = 0;
1857a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->fileTransfer.receiving = 0;
1858a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1859a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1860a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbAbortFileTransfer:
1861a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n");
1862a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1863a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1864a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->fileTransfer.fd!=-1)
1865a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
1866a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            close(cl->fileTransfer.fd);
1867a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->fileTransfer.fd=-1;
1868a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->fileTransfer.sending   = 0;
1869a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->fileTransfer.receiving = 0;
1870a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1871a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        else
1872a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
1873a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We use this message for FileTransfer rights (<=RC18 versions)
1874a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             * The client asks for FileTransfer permission
1875a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat             */
1876a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (contentParam == 0)
1877a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1878a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n");
1879a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/
1880a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, "");
1881a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1882a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* New method is allowed */
1883a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen->getFileTransferPermission!=NULL)
1884a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1885a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (cl->screen->getFileTransferPermission(cl)==TRUE)
1886a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
1887a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
1888a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
1889a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1890a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                else
1891a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
1892a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n");
1893a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */
1894a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1895a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1896a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else
1897a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1898a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (cl->screen->permitFileTransfer)
1899a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
1900a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
1901a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
1902a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1903a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                else
1904a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
1905a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n");
1906a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */
1907a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
1908a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1909a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1910a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1911a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1912a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1913a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1914a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbCommand:
1915a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
1916a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessFileTransfer() rfbCommand:\n");
1917a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        */
1918a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
1919a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        switch (contentParam) {
1920a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbCDirCreate:  /* Client requests the creation of a directory */
19211d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
19221d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                goto fail;
1923a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            retval = mkdir(filename1, 0755);
1924a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
1925a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /*
1926a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            */
1927a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer);
1928a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1929a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1930a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbCFileDelete: /* Client requests the deletion of a file */
19311d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman            if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
19321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                goto fail;
1933a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (stat(filename1,&statbuf)==0)
1934a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1935a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (S_ISDIR(statbuf.st_mode))
1936a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    retval = rmdir(filename1);
1937a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                else
1938a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    retval = unlink(filename1);
1939a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1940a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else retval=-1;
1941a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer);
1942a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (buffer!=NULL) free(buffer);
1943a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return retval;
1944a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbCFileRename: /* Client requests the Renaming of a file/directory */
1945a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            p = strrchr(buffer, '*');
1946a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (p != NULL)
1947a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
1948a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* Split into 2 filenames ('*' is a seperator) */
1949a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                *p = '\0';
19501d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                if (!rfbFilenameTranslate2UNIX(cl, buffer, filename1, sizeof(filename1)))
19511d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                    goto fail;
19521d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                if (!rfbFilenameTranslate2UNIX(cl, p+1,    filename2, sizeof(filename2)))
19531d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman                    goto fail;
1954a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval = rename(filename1,filename2);
1955a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
1956a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /*
1957a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                */
1958a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* Restore the buffer so the reply is good */
1959a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                *p = '*';
1960a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer);
1961a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (buffer!=NULL) free(buffer);
1962a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return retval;
1963a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
1964a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
1965a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
1966a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1967a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        break;
1968a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
1969a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1970a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* NOTE: don't forget to free(buffer) if you return early! */
1971a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (buffer!=NULL) free(buffer);
1972a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
19731d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
19741d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartmanfail:
19751d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    if (buffer!=NULL) free(buffer);
19761d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman    return FALSE;
1977a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
1978a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1979a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
1980a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbProcessClientNormalMessage is called when the client has sent a normal
1981a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * protocol message.
1982a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
1983a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1984a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void
1985a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbProcessClientNormalMessage(rfbClientPtr cl)
1986a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
1987a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int n=0;
1988a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientToServerMsg msg;
1989a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *str;
1990a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int i;
1991a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t enc=0;
1992a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint32_t lastPreferredEncoding = -1;
1993a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char encBuf[64];
1994a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char encBuf2[64];
1995a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
1996a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
1997a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->wsctx && webSocketCheckDisconnect(cl))
1998a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
1999a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2000a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2001a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) {
2002a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (n != 0)
2003a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbProcessClientNormalMessage: read");
2004a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
2005a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2006a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2007a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2008a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (msg.type) {
2009a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2010a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbSetPixelFormat:
2011a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2012a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2013a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           sz_rfbSetPixelFormatMsg - 1)) <= 0) {
2014a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2015a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2016a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2017a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2018a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2019a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2020a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
2021a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.depth = msg.spf.format.depth;
2022a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
2023a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
2024a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
2025a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
2026a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
2027a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.redShift = msg.spf.format.redShift;
2028a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.greenShift = msg.spf.format.greenShift;
2029a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->format.blueShift = msg.spf.format.blueShift;
2030a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2031a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->readyForSetColourMapEntries = TRUE;
2032a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->screen->setTranslateFunction(cl);
2033a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2034a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
2035a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2036a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2037a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2038a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2039a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFixColourMapEntries:
2040a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2041a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
2042a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2043a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2044a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2045a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2046a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2047a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
2048a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("rfbProcessClientNormalMessage: %s",
2049a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                "FixColourMapEntries unsupported\n");
2050a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
2051a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2052a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2053a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2054a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
2055a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * We may want to look into this...
2056a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Example:
2057a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     *     case rfbEncodingXCursor:
2058a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     *         cl->enableCursorShapeUpdates = TRUE;
2059a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     *
2060a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Currently: cl->enableCursorShapeUpdates can *never* be turned off...
2061a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2062a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbSetEncodings:
2063a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2064a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2065a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2066a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           sz_rfbSetEncodingsMsg - 1)) <= 0) {
2067a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2068a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2069a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2070a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2071a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2072a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2073a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
2074a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2075a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4));
2076a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2077a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /*
2078a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * UltraVNC Client has the ability to adapt to changing network environments
2079a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * So, let's give it a change to tell us what it wants now!
2080a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2081a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->preferredEncoding!=-1)
2082a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            lastPreferredEncoding = cl->preferredEncoding;
2083a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2084a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
2085a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->preferredEncoding=-1;
2086a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->useCopyRect              = FALSE;
2087a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->useNewFBSize             = FALSE;
2088a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->cursorWasChanged         = FALSE;
2089a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->useRichCursorEncoding    = FALSE;
2090a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableCursorPosUpdates   = FALSE;
2091a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableCursorShapeUpdates = FALSE;
2092a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableCursorShapeUpdates = FALSE;
2093a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableLastRectEncoding   = FALSE;
2094a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableKeyboardLedState   = FALSE;
2095a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableSupportedMessages  = FALSE;
2096a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableSupportedEncodings = FALSE;
2097a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableServerIdentity     = FALSE;
2098a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
2099a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->tightQualityLevel        = -1;
2100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->tightCompressLevel       = TIGHT_DEFAULT_COMPRESSION;
2102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->turboSubsampLevel        = TURBO_DEFAULT_SUBSAMP;
2103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->turboQualityLevel        = -1;
2104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for (i = 0; i < msg.se.nEncodings; i++) {
2109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) {
2110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (n != 0)
2111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLogPerror("rfbProcessClientNormalMessage: read");
2112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbCloseClient(cl);
2113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return;
2114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            enc = Swap32IfLE(enc);
2116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            switch (enc) {
2118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingCopyRect:
2120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->useCopyRect = TRUE;
2121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingRaw:
2123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingRRE:
2124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingCoRRE:
2125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingHextile:
2126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingUltra:
2127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
2128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingZlib:
2129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingZRLE:
2130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingZYWRLE:
2131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingTight:
2133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPNG
2136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingTightPng:
2137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* The first supported encoding is the 'preferred' encoding */
2139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (cl->preferredEncoding == -1)
2140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    cl->preferredEncoding = enc;
2141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingXCursor:
2145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(!cl->screen->dontConvertRichCursorToXCursor) {
2146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Enabling X-style cursor updates for client %s\n",
2147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->host);
2148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    /* if cursor was drawn, hide the cursor */
2149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    if(!cl->enableCursorShapeUpdates)
2150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		        rfbRedrawAfterHideCursor(cl,NULL);
2151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->enableCursorShapeUpdates = TRUE;
2153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->cursorWasChanged = TRUE;
2154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		break;
2156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingRichCursor:
2157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        rfbLog("Enabling full-color cursor updates for client %s\n",
2158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		       cl->host);
2159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		/* if cursor was drawn, hide the cursor */
2160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(!cl->enableCursorShapeUpdates)
2161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbRedrawAfterHideCursor(cl,NULL);
2162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        cl->enableCursorShapeUpdates = TRUE;
2164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        cl->useRichCursorEncoding = TRUE;
2165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        cl->cursorWasChanged = TRUE;
2166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        break;
2167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingPointerPos:
2168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!cl->enableCursorPosUpdates) {
2169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Enabling cursor position updates for client %s\n",
2170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->host);
2171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->enableCursorPosUpdates = TRUE;
2172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->cursorWasMoved = TRUE;
2173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        break;
2175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingLastRect:
2176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!cl->enableLastRectEncoding) {
2177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Enabling LastRect protocol extension for client "
2178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   "%s\n", cl->host);
2179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->enableLastRectEncoding = TRUE;
2180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		break;
2182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingNewFBSize:
2183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!cl->useNewFBSize) {
2184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Enabling NewFBSize protocol extension for client "
2185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   "%s\n", cl->host);
2186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->useNewFBSize = TRUE;
2187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		break;
2189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingKeyboardLedState:
2190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (!cl->enableKeyboardLedState) {
2191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  rfbLog("Enabling KeyboardLedState protocol extension for client "
2192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                          "%s\n", cl->host);
2193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  cl->enableKeyboardLedState = TRUE;
2194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingSupportedMessages:
2197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (!cl->enableSupportedMessages) {
2198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  rfbLog("Enabling SupportedMessages protocol extension for client "
2199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                          "%s\n", cl->host);
2200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  cl->enableSupportedMessages = TRUE;
2201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingSupportedEncodings:
2204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (!cl->enableSupportedEncodings) {
2205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  rfbLog("Enabling SupportedEncodings protocol extension for client "
2206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                          "%s\n", cl->host);
2207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  cl->enableSupportedEncodings = TRUE;
2208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            case rfbEncodingServerIdentity:
2211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (!cl->enableServerIdentity) {
2212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  rfbLog("Enabling ServerIdentity protocol extension for client "
2213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                          "%s\n", cl->host);
2214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  cl->enableServerIdentity = TRUE;
2215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    case rfbEncodingXvp:
2218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        rfbLog("Enabling Xvp protocol extension for client "
2219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		        "%s\n", cl->host);
2220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!rfbSendXvp(cl, 1, rfbXvp_Init)) {
2221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		  rfbCloseClient(cl);
2222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		  return;
2223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                break;
2225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            default:
2226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
2227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
2228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		     enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
2229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->zlibCompressLevel = enc & 0x0F;
2230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->tightCompressLevel = enc & 0x0F;
2232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Using compression level %d for client %s\n",
2233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->tightCompressLevel, cl->host);
2234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
2236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			    enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
2237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->tightQualityLevel = enc & 0x0F;
2238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Using image quality level %d for client %s\n",
2239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->tightQualityLevel, cl->host);
2240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->turboQualityLevel = tight2turbo_qual[enc & 0x0F];
2242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->turboSubsampLevel = tight2turbo_subsamp[enc & 0x0F];
2243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Using JPEG subsampling %d, Q%d for client %s\n",
2244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->turboSubsampLevel, cl->turboQualityLevel, cl->host);
2245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if ( enc >= (uint32_t)rfbEncodingFineQualityLevel0 + 1 &&
2246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			    enc <= (uint32_t)rfbEncodingFineQualityLevel100 ) {
2247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->turboQualityLevel = enc & 0xFF;
2248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Using fine quality level %d for client %s\n",
2249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->turboQualityLevel, cl->host);
2250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else if ( enc >= (uint32_t)rfbEncodingSubsamp1X &&
2251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			    enc <= (uint32_t)rfbEncodingSubsampGray ) {
2252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->turboSubsampLevel = enc & 0xFF;
2253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    rfbLog("Using subsampling level %d for client %s\n",
2254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   cl->turboSubsampLevel, cl->host);
2255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		} else
2257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		{
2259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			rfbExtensionData* e;
2260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			for(e = cl->extensions; e;) {
2261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbExtensionData* next = e->next;
2262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(e->extension->enablePseudoEncoding &&
2263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					e->extension->enablePseudoEncoding(cl,
2264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						&e->data, (int)enc))
2265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					/* ext handles this encoding */
2266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					break;
2267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				e = next;
2268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
2269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			if(e == NULL) {
2270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbBool handled = FALSE;
2271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				/* if the pseudo encoding is not handled by the
2272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				   enabled extensions, search through all
2273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				   extensions. */
2274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbProtocolExtension* e;
2275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				for(e = rfbGetExtensionIterator(); e;) {
2277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					int* encs = e->pseudoEncodings;
2278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					while(encs && *encs!=0) {
2279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						if(*encs==(int)enc) {
2280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							void* data = NULL;
2281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							if(!e->enablePseudoEncoding(cl, &data, (int)enc)) {
2282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat								rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc);
2283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							} else {
2284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat								rfbEnableExtension(cl, e, data);
2285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat								handled = TRUE;
2286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat								e = NULL;
2287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat								break;
2288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat							}
2289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						}
2290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						encs++;
2291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					}
2292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					if(e)
2294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat						e = e->next;
2295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				}
2296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				rfbReleaseExtensionIterator();
2297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat				if(!handled)
2299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					rfbLog("rfbProcessClientNormalMessage: "
2300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					    "ignoring unsupported encoding type %s\n",
2301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					    encodingName(enc,encBuf,sizeof(encBuf)));
2302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			}
2303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->preferredEncoding == -1) {
2310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (lastPreferredEncoding==-1) {
2311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->preferredEncoding = rfbEncodingRaw;
2312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else {
2315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                cl->preferredEncoding = lastPreferredEncoding;
2316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        else
2320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
2321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if (lastPreferredEncoding==-1) {
2322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
2323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          } else {
2324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat              rfbLog("Switching from %s to %s Encoding for client %s\n",
2325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)),
2326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host);
2327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          }
2328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
2331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rfbLog("Disabling cursor position updates for client %s\n",
2332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 cl->host);
2333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  cl->enableCursorPosUpdates = FALSE;
2334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFramebufferUpdateRequest:
2341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sraRegionPtr tmpRegion;
2343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
2346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbFramebufferUpdateRequestMsg,sz_rfbFramebufferUpdateRequestMsg);
2353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* The values come in based on the scaled screen, we need to convert them to
2355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * values based on the main screen's coordinate system
2356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl))
2358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	{
2359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: %dXx%dY-%dWx%dH\n",msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h);
2360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		return;
2361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	tmpRegion =
2365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  sraRgnCreateRect(msg.fur.x,
2366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   msg.fur.y,
2367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   msg.fur.x+msg.fur.w,
2368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   msg.fur.y+msg.fur.h);
2369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        LOCK(cl->updateMutex);
2371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnOr(cl->requestedRegion,tmpRegion);
2372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!cl->readyForSetColourMapEntries) {
2374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    /* client hasn't sent a SetPixelFormat so is using server's */
2375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->readyForSetColourMapEntries = TRUE;
2376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (!cl->format.trueColour) {
2377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if (!rfbSetClientColourMap(cl, 0, 0)) {
2378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    sraRgnDestroy(tmpRegion);
2379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    TSIGNAL(cl->updateCond);
2380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    UNLOCK(cl->updateMutex);
2381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    return;
2382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		}
2383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
2384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       if (!msg.fur.incremental) {
2387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRgnOr(cl->modifiedRegion,tmpRegion);
2388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRgnSubtract(cl->copyRegion,tmpRegion);
2389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       }
2390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       TSIGNAL(cl->updateCond);
2391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       UNLOCK(cl->updateMutex);
2392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       sraRgnDestroy(tmpRegion);
2394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       return;
2396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbKeyEvent:
2399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   sz_rfbKeyEventMsg - 1)) <= 0) {
2402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n != 0)
2403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("rfbProcessClientNormalMessage: read");
2404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
2405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbKeyEventMsg, sz_rfbKeyEventMsg);
2409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(!cl->viewOnly) {
2411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
2412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbPointerEvent:
2418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   sz_rfbPointerEventMsg - 1)) <= 0) {
2421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n != 0)
2422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("rfbProcessClientNormalMessage: read");
2423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
2424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbPointerEventMsg, sz_rfbPointerEventMsg);
2428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (cl->screen->pointerClient && cl->screen->pointerClient != cl)
2430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2432a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (msg.pe.buttonMask == 0)
2433a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->screen->pointerClient = NULL;
2434a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	else
2435a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->screen->pointerClient = cl;
2436a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2437a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(!cl->viewOnly) {
2438a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (msg.pe.buttonMask != cl->lastPtrButtons ||
2439a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    cl->screen->deferPtrUpdateTime == 0) {
2440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->screen->ptrAddEvent(msg.pe.buttonMask,
2441a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)),
2442a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)),
2443a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			cl);
2444a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->lastPtrButtons = msg.pe.buttonMask;
2445a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    } else {
2446a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->lastPtrX = ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x));
2447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y));
2448a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		cl->lastPtrButtons = msg.pe.buttonMask;
2449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
2450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
2452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbFileTransfer:
2455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbFileTransferMsg - 1)) <= 0) {
2457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.ft.size         = Swap32IfLE(msg.ft.size);
2463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.ft.length       = Swap32IfLE(msg.ft.length);
2464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */
2465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbProcessFileTransfer(cl, msg.ft.contentType, msg.ft.contentParam, msg.ft.size, msg.ft.length);
2466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbSetSW:
2469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbSetSWMsg - 1)) <= 0) {
2471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.sw.x = Swap16IfLE(msg.sw.x);
2477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.sw.y = Swap16IfLE(msg.sw.y);
2478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetSWMsg, sz_rfbSetSWMsg);
2479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */
2480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("Received a rfbSetSingleWindow(%d x, %d y)\n", msg.sw.x, msg.sw.y);
2482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->screen->setSingleWindow!=NULL)
2483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->screen->setSingleWindow(cl, msg.sw.x, msg.sw.y);
2484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbSetServerInput:
2487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbSetServerInputMsg - 1)) <= 0) {
2489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetServerInputMsg, sz_rfbSetServerInputMsg);
2495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */
2497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* msg.sim.pad = Swap16IfLE(msg.sim.pad); */
2498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("Received a rfbSetServerInput(%d status)\n", msg.sim.status);
2500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->screen->setServerInput!=NULL)
2501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->screen->setServerInput(cl, msg.sim.status);
2502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbTextChat:
2505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                              sz_rfbTextChatMsg - 1)) <= 0) {
2507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (n != 0)
2508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLogPerror("rfbProcessClientNormalMessage: read");
2509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
2510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return;
2511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.tc.pad2   = Swap16IfLE(msg.tc.pad2);
2514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        msg.tc.length = Swap32IfLE(msg.tc.length);
2515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        switch (msg.tc.length) {
2517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbTextChatOpen:
2518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbTextChatClose:
2519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbTextChatFinished:
2520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* commands do not have text following */
2521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* Why couldn't they have used the pad byte??? */
2522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            str=NULL;
2523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg, sz_rfbTextChatMsg);
2524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
2525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        default:
2526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if ((msg.tc.length>0) && (msg.tc.length<rfbTextMaxSize))
2527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
2528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                str = (char *)malloc(msg.tc.length);
2529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if (str==NULL)
2530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
2531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbLog("Unable to malloc %d bytes for a TextChat Message\n", msg.tc.length);
2532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbCloseClient(cl);
2533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return;
2534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                if ((n = rfbReadExact(cl, str, msg.tc.length)) <= 0) {
2536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    if (n != 0)
2537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                        rfbLogPerror("rfbProcessClientNormalMessage: read");
2538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    free(str);
2539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbCloseClient(cl);
2540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    return;
2541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg+msg.tc.length, sz_rfbTextChatMsg+msg.tc.length);
2543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            else
2545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            {
2546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                /* This should never happen */
2547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbLog("client sent us a Text Message that is too big %d>%d\n", msg.tc.length, rfbTextMaxSize);
2548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbCloseClient(cl);
2549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                return;
2550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            }
2551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished
2554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * at which point, the str is NULL (as it is not sent)
2555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->screen->setTextChat!=NULL)
2557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->screen->setTextChat(cl, msg.tc.length, str);
2558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        free(str);
2560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbClientCutText:
2564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   sz_rfbClientCutTextMsg - 1)) <= 0) {
2567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n != 0)
2568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		rfbLogPerror("rfbProcessClientNormalMessage: read");
2569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
2570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	msg.cct.length = Swap32IfLE(msg.cct.length);
2574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	str = (char *)malloc(msg.cct.length);
25761d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman	if (str == NULL) {
25771d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman		rfbLogPerror("rfbProcessClientNormalMessage: not enough memory");
25781d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman		rfbCloseClient(cl);
25791d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman		return;
25801d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman	}
2581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) {
2583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n != 0)
2584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        rfbLogPerror("rfbProcessClientNormalMessage: read");
2585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    free(str);
2586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
2587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2589a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length);
2590a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(!cl->viewOnly) {
2591a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->screen->setXCutText(str, msg.cct.length, cl);
2592a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2593a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	free(str);
2594a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2595a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return;
2596a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2597a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbPalmVNCSetScaleFactor:
2598a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->PalmVNC = TRUE;
2599a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2600a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          sz_rfbSetScaleMsg - 1)) <= 0) {
2601a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if (n != 0)
2602a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbProcessClientNormalMessage: read");
2603a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          rfbCloseClient(cl);
2604a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          return;
2605a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
26061d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
26071d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman      if (msg.ssc.scale == 0) {
26081d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero");
26091d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          rfbCloseClient(cl);
26101d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          return;
26111d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman      }
26121d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
2613a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
2614a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
2615a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);
2616a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2617a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSendNewScaleSize(cl);
2618a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
2619a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2620a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbSetScale:
2621a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2622a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2623a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          sz_rfbSetScaleMsg - 1)) <= 0) {
2624a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if (n != 0)
2625a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbProcessClientNormalMessage: read");
2626a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          rfbCloseClient(cl);
2627a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          return;
2628a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
26291d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
26301d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman      if (msg.ssc.scale == 0) {
26311d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero");
26321d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          rfbCloseClient(cl);
26331d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman          return;
26341d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman      }
26351d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman
2636a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
2637a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
2638a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);
2639a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2640a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSendNewScaleSize(cl);
2641a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
2642a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2643a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbXvp:
2644a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2645a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
2646a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          sz_rfbXvpMsg - 1)) <= 0) {
2647a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          if (n != 0)
2648a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbProcessClientNormalMessage: read");
2649a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          rfbCloseClient(cl);
2650a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          return;
2651a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2652a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbXvpMsg, sz_rfbXvpMsg);
2653a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2654a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      /* only version when is defined, so echo back a fail */
2655a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(msg.xvp.version != 1) {
2656a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbSendXvp(cl, msg.xvp.version, rfbXvp_Fail);
2657a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2658a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      else {
2659a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* if the hook exists and fails, send a fail msg */
2660a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(cl->screen->xvpHook && !cl->screen->xvpHook(cl, msg.xvp.version, msg.xvp.code))
2661a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rfbSendXvp(cl, 1, rfbXvp_Fail);
2662a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2663a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
2664a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2665a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    default:
2666a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	{
2667a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbExtensionData *e,*next;
2668a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2669a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    for(e=cl->extensions; e;) {
2670a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		next = e->next;
2671a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(e->extension->handleMessage &&
2672a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			e->extension->handleMessage(cl, e->data, &msg))
2673a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                {
2674a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    rfbStatRecordMessageRcvd(cl, msg.type, 0, 0); /* Extension should handle this */
2675a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    return;
2676a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                }
2677a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		e = next;
2678a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
2679a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2680a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
2681a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    msg.type);
2682a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbLog(" ... closing connection\n");
2683a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
2684a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
2685a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2686a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2687a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
2688a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2689a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2690a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2691a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2692a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
2693a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * the RFB client.
2694a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * givenUpdateRegion is not changed.
2695a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
2696a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2697a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
2698a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendFramebufferUpdate(rfbClientPtr cl,
2699a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                         sraRegionPtr givenUpdateRegion)
2700a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
2701a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRectangleIterator* i=NULL;
2702a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRect rect;
2703a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nUpdateRegionRects;
2704a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf;
2705a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRegionPtr updateRegion,updateCopyRegion,tmpRegion;
2706a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int dx, dy;
2707a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendCursorShape = FALSE;
2708a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendCursorPos = FALSE;
2709a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendKeyboardLedState = FALSE;
2710a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendSupportedMessages = FALSE;
2711a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendSupportedEncodings = FALSE;
2712a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool sendServerIdentity = FALSE;
2713a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBool result = TRUE;
2714a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2715a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2716a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->screen->displayHook)
2717a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->screen->displayHook(cl);
2718a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2719a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2720a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * If framebuffer size was changed and the client supports NewFBSize
2721a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * encoding, just send NewFBSize marker and return.
2722a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2723a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2724a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->useNewFBSize && cl->newFBSizePending) {
2725a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      LOCK(cl->updateMutex);
2726a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->newFBSizePending = FALSE;
2727a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      UNLOCK(cl->updateMutex);
2728a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      fu->type = rfbFramebufferUpdate;
2729a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      fu->nRects = Swap16IfLE(1);
2730a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->ublen = sz_rfbFramebufferUpdateMsg;
2731a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (!rfbSendNewFBSize(cl, cl->scaledScreen->width, cl->scaledScreen->height)) {
2732a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(cl->screen->displayFinishedHook)
2733a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  cl->screen->displayFinishedHook(cl, FALSE);
2734a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
2735a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2736a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      result = rfbSendUpdateBuf(cl);
2737a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(cl->screen->displayFinishedHook)
2738a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->screen->displayFinishedHook(cl, result);
2739a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return result;
2740a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2741a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2742a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2743a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * If this client understands cursor shape updates, cursor should be
2744a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * removed from the framebuffer. Otherwise, make sure it's put up.
2745a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2746a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2747a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->enableCursorShapeUpdates) {
2748a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (cl->cursorWasChanged && cl->readyForSetColourMapEntries)
2749a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  sendCursorShape = TRUE;
2750a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2751a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2752a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2753a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Do we plan to send cursor position update?
2754a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2755a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2756a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
2757a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      sendCursorPos = TRUE;
2758a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2759a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2760a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Do we plan to send a keyboard state update?
2761a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2762a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((cl->enableKeyboardLedState) &&
2763a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	(cl->screen->getKeyboardLedStateHook!=NULL))
2764a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2765a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int x;
2766a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        x=cl->screen->getKeyboardLedStateHook(cl->screen);
2767a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (x!=cl->lastKeyboardLedState)
2768a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        {
2769a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            sendKeyboardLedState = TRUE;
2770a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            cl->lastKeyboardLedState=x;
2771a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2772a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2773a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2774a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2775a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Do we plan to send a rfbEncodingSupportedMessages?
2776a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2777a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->enableSupportedMessages)
2778a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2779a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sendSupportedMessages = TRUE;
2780a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* We only send this message ONCE <per setEncodings message received>
2781a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * (We disable it here)
2782a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2783a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableSupportedMessages = FALSE;
2784a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2785a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2786a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Do we plan to send a rfbEncodingSupportedEncodings?
2787a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2788a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->enableSupportedEncodings)
2789a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2790a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sendSupportedEncodings = TRUE;
2791a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* We only send this message ONCE <per setEncodings message received>
2792a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * (We disable it here)
2793a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2794a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableSupportedEncodings = FALSE;
2795a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2796a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2797a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Do we plan to send a rfbEncodingServerIdentity?
2798a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2799a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->enableServerIdentity)
2800a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
2801a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sendServerIdentity = TRUE;
2802a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* We only send this message ONCE <per setEncodings message received>
2803a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         * (We disable it here)
2804a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat         */
2805a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->enableServerIdentity = FALSE;
2806a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2807a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2808a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->updateMutex);
2809a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2810a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2811a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * The modifiedRegion may overlap the destination copyRegion.  We remove
2812a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * any overlapping bits from the copyRegion (since they'd only be
2813a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * overwritten anyway).
2814a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2815a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2816a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnSubtract(cl->copyRegion,cl->modifiedRegion);
2817a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2818a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2819a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * The client is interested in the region requestedRegion.  The region
2820a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * which should be updated now is the intersection of requestedRegion
2821a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * and the union of modifiedRegion and copyRegion.  If it's empty then
2822a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * no update is needed.
2823a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2824a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2825a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    updateRegion = sraRgnCreateRgn(givenUpdateRegion);
2826a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->screen->progressiveSliceHeight>0) {
2827a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    int height=cl->screen->progressiveSliceHeight,
2828a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    	y=cl->progressiveSliceY;
2829a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRegionPtr bbox=sraRgnBBox(updateRegion);
2830a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRect rect;
2831a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if(sraRgnPopRect(bbox,&rect,0)) {
2832a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		sraRegionPtr slice;
2833a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		if(y<rect.y1 || y>=rect.y2)
2834a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    y=rect.y1;
2835a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    	slice=sraRgnCreateRect(0,y,cl->screen->width,y+height);
2836a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		sraRgnAnd(updateRegion,slice);
2837a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		sraRgnDestroy(slice);
2838a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
2839a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRgnDestroy(bbox);
2840a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    y+=height;
2841a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if(y>=cl->screen->height)
2842a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    y=0;
2843a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    cl->progressiveSliceY=y;
2844a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2845a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2846a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnOr(updateRegion,cl->copyRegion);
2847a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
2848a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       sraRgnEmpty(updateRegion) &&
2849a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       (cl->enableCursorShapeUpdates ||
2850a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	(cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) &&
2851a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       !sendCursorShape && !sendCursorPos && !sendKeyboardLedState &&
2852a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       !sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) {
2853a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      sraRgnDestroy(updateRegion);
2854a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      UNLOCK(cl->updateMutex);
2855a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(cl->screen->displayFinishedHook)
2856a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->screen->displayFinishedHook(cl, TRUE);
2857a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return TRUE;
2858a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2859a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2860a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2861a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * We assume that the client doesn't have any pixel data outside the
2862a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * requestedRegion.  In other words, both the source and destination of a
2863a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * copy must lie within requestedRegion.  So the region we can send as a
2864a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * copy is the intersection of the copyRegion with both the requestedRegion
2865a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * and the requestedRegion translated by the amount of the copy.  We set
2866a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * updateCopyRegion to this.
2867a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2868a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2869a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    updateCopyRegion = sraRgnCreateRgn(cl->copyRegion);
2870a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnAnd(updateCopyRegion,cl->requestedRegion);
2871a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    tmpRegion = sraRgnCreateRgn(cl->requestedRegion);
2872a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY);
2873a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnAnd(updateCopyRegion,tmpRegion);
2874a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(tmpRegion);
2875a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    dx = cl->copyDX;
2876a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    dy = cl->copyDY;
2877a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2878a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2879a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Next we remove updateCopyRegion from updateRegion so that updateRegion
2880a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * is the part of this update which is sent as ordinary pixel data (i.e not
2881a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * a copy).
2882a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2883a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2884a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnSubtract(updateRegion,updateCopyRegion);
2885a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2886a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2887a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Finally we leave modifiedRegion to be the remainder (if any) of parts of
2888a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * the screen which are modified but outside the requestedRegion.  We also
2889a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * empty both the requestedRegion and the copyRegion - note that we never
2890a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * carry over a copyRegion for a future update.
2891a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2892a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2893a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     sraRgnOr(cl->modifiedRegion,cl->copyRegion);
2894a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     sraRgnSubtract(cl->modifiedRegion,updateRegion);
2895a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     sraRgnSubtract(cl->modifiedRegion,updateCopyRegion);
2896a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2897a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     sraRgnMakeEmpty(cl->requestedRegion);
2898a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     sraRgnMakeEmpty(cl->copyRegion);
2899a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     cl->copyDX = 0;
2900a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     cl->copyDY = 0;
2901a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2902a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     UNLOCK(cl->updateMutex);
2903a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2904a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!cl->enableCursorShapeUpdates) {
2905a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(cl->cursorX != cl->screen->cursorX || cl->cursorY != cl->screen->cursorY) {
2906a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbRedrawAfterHideCursor(cl,updateRegion);
2907a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	LOCK(cl->screen->cursorMutex);
2908a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->cursorX = cl->screen->cursorX;
2909a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->cursorY = cl->screen->cursorY;
2910a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	UNLOCK(cl->screen->cursorMutex);
2911a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbRedrawAfterHideCursor(cl,updateRegion);
2912a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
2913a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbShowCursor(cl);
2914a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
2915a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2916a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /*
2917a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     * Now send the update.
2918a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     */
2919a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2920a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbFramebufferUpdate, 0, 0);
2921a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->preferredEncoding == rfbEncodingCoRRE) {
2922a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nUpdateRegionRects = 0;
2923a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2924a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2925a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int x = rect.x1;
2926a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int y = rect.y1;
2927a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int w = rect.x2 - x;
2928a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int h = rect.y2 - y;
2929a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    int rectsPerRow, rows;
2930a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We need to count the number of rects in the scaled screen */
2931a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen!=cl->scaledScreen)
2932a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2933a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rectsPerRow = (w-1)/cl->correMaxWidth+1;
2934a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rows = (h-1)/cl->correMaxHeight+1;
2935a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    nUpdateRegionRects += rectsPerRow*rows;
2936a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
2937a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnReleaseIterator(i); i=NULL;
2938a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if (cl->preferredEncoding == rfbEncodingUltra) {
2939a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nUpdateRegionRects = 0;
2940a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2941a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2942a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int x = rect.x1;
2943a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int y = rect.y1;
2944a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int w = rect.x2 - x;
2945a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int h = rect.y2 - y;
2946a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We need to count the number of rects in the scaled screen */
2947a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen!=cl->scaledScreen)
2948a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2949a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            nUpdateRegionRects += (((h-1) / (ULTRA_MAX_SIZE( w ) / w)) + 1);
2950a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          }
2951a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sraRgnReleaseIterator(i); i=NULL;
2952a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
2953a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if (cl->preferredEncoding == rfbEncodingZlib) {
2954a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	nUpdateRegionRects = 0;
2955a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2956a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2957a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int x = rect.x1;
2958a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int y = rect.y1;
2959a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int w = rect.x2 - x;
2960a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int h = rect.y2 - y;
2961a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We need to count the number of rects in the scaled screen */
2962a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen!=cl->scaledScreen)
2963a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2964a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
2965a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2966a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnReleaseIterator(i); i=NULL;
2967a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
2968a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if (cl->preferredEncoding == rfbEncodingTight) {
2969a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	nUpdateRegionRects = 0;
2970a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2971a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2972a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int x = rect.x1;
2973a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int y = rect.y1;
2974a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int w = rect.x2 - x;
2975a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int h = rect.y2 - y;
2976a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int n;
2977a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We need to count the number of rects in the scaled screen */
2978a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen!=cl->scaledScreen)
2979a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
2980a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    n = rfbNumCodedRectsTight(cl, x, y, w, h);
2981a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n == 0) {
2982a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		nUpdateRegionRects = 0xFFFF;
2983a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		break;
2984a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
2985a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    nUpdateRegionRects += n;
2986a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
2987a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnReleaseIterator(i); i=NULL;
2988a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2989a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
2990a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBJPEG) && defined(LIBVNCSERVER_HAVE_LIBPNG)
2991a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if (cl->preferredEncoding == rfbEncodingTightPng) {
2992a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	nUpdateRegionRects = 0;
2993a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
2994a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
2995a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int x = rect.x1;
2996a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int y = rect.y1;
2997a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int w = rect.x2 - x;
2998a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int h = rect.y2 - y;
2999a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            int n;
3000a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            /* We need to count the number of rects in the scaled screen */
3001a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (cl->screen!=cl->scaledScreen)
3002a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
3003a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    n = rfbNumCodedRectsTight(cl, x, y, w, h);
3004a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (n == 0) {
3005a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		nUpdateRegionRects = 0xFFFF;
3006a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		break;
3007a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    }
3008a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    nUpdateRegionRects += n;
3009a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3010a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	sraRgnReleaseIterator(i); i=NULL;
3011a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3012a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
3013a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nUpdateRegionRects = sraRgnCountRects(updateRegion);
3014a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3015a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3016a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    fu->type = rfbFramebufferUpdate;
3017a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (nUpdateRegionRects != 0xFFFF) {
3018a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(cl->screen->maxRectsPerUpdate>0
3019a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   /* CoRRE splits the screen into smaller squares */
3020a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   && cl->preferredEncoding != rfbEncodingCoRRE
3021a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   /* Ultra encoding splits rectangles up into smaller chunks */
3022a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           && cl->preferredEncoding != rfbEncodingUltra
3023a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
3024a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   /* Zlib encoding splits rectangles up into smaller chunks */
3025a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   && cl->preferredEncoding != rfbEncodingZlib
3026a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBJPEG
3027a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   /* Tight encoding counts the rectangles differently */
3028a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   && cl->preferredEncoding != rfbEncodingTight
3029a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3030a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3031a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPNG
3032a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   /* Tight encoding counts the rectangles differently */
3033a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   && cl->preferredEncoding != rfbEncodingTightPng
3034a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3035a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	   && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
3036a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
3037a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    sraRgnDestroy(updateRegion);
3038a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    updateRegion = newUpdateRegion;
3039a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    nUpdateRegionRects = sraRgnCountRects(updateRegion);
3040a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3041a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
3042a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					   nUpdateRegionRects +
3043a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					   !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState +
3044a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat					   !!sendSupportedMessages + !!sendSupportedEncodings + !!sendServerIdentity));
3045a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
3046a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	fu->nRects = 0xFFFF;
3047a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3048a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen = sz_rfbFramebufferUpdateMsg;
3049a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3050a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendCursorShape) {
3051a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->cursorWasChanged = FALSE;
3052a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!rfbSendCursorShape(cl))
3053a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    goto updateFailed;
3054a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3055a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3056a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendCursorPos) {
3057a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->cursorWasMoved = FALSE;
3058a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!rfbSendCursorPos(cl))
3059a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3060a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   }
3061a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3062a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendKeyboardLedState) {
3063a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       if (!rfbSendKeyboardLedState(cl))
3064a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           goto updateFailed;
3065a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   }
3066a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3067a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendSupportedMessages) {
3068a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       if (!rfbSendSupportedMessages(cl))
3069a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           goto updateFailed;
3070a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   }
3071a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendSupportedEncodings) {
3072a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       if (!rfbSendSupportedEncodings(cl))
3073a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           goto updateFailed;
3074a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   }
3075a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if (sendServerIdentity) {
3076a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       if (!rfbSendServerIdentity(cl))
3077a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           goto updateFailed;
3078a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   }
3079a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3080a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!sraRgnEmpty(updateCopyRegion)) {
3081a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
3082a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3083a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3084a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3085a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){
3086a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int x = rect.x1;
3087a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int y = rect.y1;
3088a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int w = rect.x2 - x;
3089a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        int h = rect.y2 - y;
3090a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3091a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* We need to count the number of rects in the scaled screen */
3092a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (cl->screen!=cl->scaledScreen)
3093a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate");
3094a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3095a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        switch (cl->preferredEncoding) {
3096a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	case -1:
3097a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbEncodingRaw:
3098a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendRectEncodingRaw(cl, x, y, w, h))
3099a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
3101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbEncodingRRE:
3102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendRectEncodingRRE(cl, x, y, w, h))
3103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
3105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbEncodingCoRRE:
3106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h))
3107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
3109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbEncodingHextile:
3110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendRectEncodingHextile(cl, x, y, w, h))
3111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
3113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        case rfbEncodingUltra:
3114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            if (!rfbSendRectEncodingUltra(cl, x, y, w, h))
3115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                goto updateFailed;
3116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            break;
3117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBZ
3118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	case rfbEncodingZlib:
3119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (!rfbSendRectEncodingZlib(cl, x, y, w, h))
3120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
3122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       case rfbEncodingZRLE:
3123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       case rfbEncodingZYWRLE:
3124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           if (!rfbSendRectEncodingZRLE(cl, x, y, w, h))
3125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	       goto updateFailed;
3126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           break;
3127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#if defined(LIBVNCSERVER_HAVE_LIBJPEG) && (defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG))
3129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	case rfbEncodingTight:
3130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (!rfbSendRectEncodingTight(cl, x, y, w, h))
3131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
3133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_LIBPNG
3134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	case rfbEncodingTightPng:
3135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    if (!rfbSendRectEncodingTightPng(cl, x, y, w, h))
3136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	        goto updateFailed;
3137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    break;
3138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
3140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
3141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (i) {
3143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sraRgnReleaseIterator(i);
3144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        i = NULL;
3145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ( nUpdateRegionRects == 0xFFFF &&
3148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	 !rfbSendLastRectMarker(cl) )
3149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    goto updateFailed;
3150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!rfbSendUpdateBuf(cl)) {
3152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatupdateFailed:
3153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	result = FALSE;
3154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (!cl->enableCursorShapeUpdates) {
3157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbHideCursor(cl);
3158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(i)
3161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sraRgnReleaseIterator(i);
3162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(updateRegion);
3163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnDestroy(updateCopyRegion);
3164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->screen->displayFinishedHook)
3166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->screen->displayFinishedHook(cl, result);
3167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return result;
3168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send the copy region as a string of CopyRect encoded rectangles.
3173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * The only slightly tricky thing is that we should send the messages in
3174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * the correct order so that an earlier CopyRect will not corrupt the source
3175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * of a later one.
3176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendCopyRegion(rfbClientPtr cl,
3180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  sraRegionPtr reg,
3181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  int dx,
3182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                  int dy)
3183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int x, y, w, h;
3185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
3186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbCopyRect cr;
3187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRectangleIterator* i;
3188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRect rect1;
3189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
3191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    i = sraRgnGetReverseIterator(reg,dx>0,dy>0);
3192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* correct for the scale of the screen */
3194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    dx = ScaleX(cl->screen, cl->scaledScreen, dx);
3195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    dy = ScaleX(cl->screen, cl->scaledScreen, dy);
3196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    while(sraRgnIteratorNext(i,&rect1)) {
3198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      x = rect1.x1;
3199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      y = rect1.y1;
3200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      w = rect1.x2 - x;
3201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      h = rect1.y2 - y;
3202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      /* correct for scaling (if necessary) */
3204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "copyrect");
3205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rect.r.x = Swap16IfLE(x);
3207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rect.r.y = Swap16IfLE(y);
3208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rect.r.w = Swap16IfLE(w);
3209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rect.r.h = Swap16IfLE(h);
3210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
3211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
3213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	     sz_rfbFramebufferUpdateRectHeader);
3214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cr.srcX = Swap16IfLE(x - dx);
3217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cr.srcY = Swap16IfLE(y - dy);
3218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
3220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      cl->ublen += sz_rfbCopyRect;
3221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbStatRecordEncodingSent(cl, rfbEncodingCopyRect, sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect,
3223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat          w * h  * (cl->scaledScreen->bitsPerPixel / 8));
3224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    sraRgnReleaseIterator(i);
3226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
3228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send a given rectangle in raw encoding (rfbEncodingRaw).
3232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendRectEncodingRaw(rfbClientPtr cl,
3236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int x,
3237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int y,
3238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int w,
3239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       int h)
3240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
3242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int nlines;
3243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
3244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
3245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                   + (x * (cl->scaledScreen->bitsPerPixel / 8)));
3246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* Flush the buffer to guarantee correct alignment for translateFn(). */
3248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen > 0) {
3249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
3250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
3251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = Swap16IfLE(x);
3254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = Swap16IfLE(y);
3255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(w);
3256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = Swap16IfLE(h);
3257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingRaw);
3258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
3260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingRaw, sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h,
3264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h);
3265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
3267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    while (TRUE) {
3269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (nlines > h)
3270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            nlines = h;
3271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        (*cl->translateFn)(cl->translateLookupTable,
3273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			   &(cl->screen->serverFormat),
3274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           &cl->format, fbptr, &cl->updateBuf[cl->ublen],
3275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           cl->scaledScreen->paddedWidthInBytes, w, nlines);
3276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        cl->ublen += nlines * bytesPerLine;
3278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        h -= nlines;
3279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (h == 0)     /* rect fitted in buffer, do next one */
3281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return TRUE;
3282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        /* buffer full - flush partial rect and do another nlines */
3284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (!rfbSendUpdateBuf(cl))
3286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
3287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        fbptr += (cl->scaledScreen->paddedWidthInBytes * nlines);
3289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
3291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (nlines == 0) {
3292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
3293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                   "bytes per line\n", bytesPerLine);
3294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
3295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            return FALSE;
3296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
3297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send an empty rectangle with encoding field set to value of
3304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbEncodingLastRect to notify client that this is the last
3305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rectangle in framebuffer update ("LastRect" extension of RFB
3306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * protocol).
3307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendLastRectMarker(rfbClientPtr cl)
3311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
3313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
3315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!rfbSendUpdateBuf(cl))
3316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return FALSE;
3317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingLastRect);
3320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = 0;
3321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
3322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = 0;
3323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = 0;
3324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
3326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingLastRect, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
3330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
3332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send NewFBSize pseudo-rectangle. This tells the client to change
3337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * its framebuffer size.
3338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendNewFBSize(rfbClientPtr cl,
3342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                 int w,
3343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                 int h)
3344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFramebufferUpdateRectHeader rect;
3346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
3348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (!rfbSendUpdateBuf(cl))
3349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return FALSE;
3350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (cl->PalmVNC==TRUE)
3353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("Sending rfbEncodingNewFBSize in response to a PalmVNC style framebuffer resize (%dx%d)\n", w, h);
3354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    else
3355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLog("Sending rfbEncodingNewFBSize for resize to (%dx%d)\n", w, h);
3356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
3358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.x = 0;
3359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.y = 0;
3360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.w = Swap16IfLE(w);
3361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rect.r.h = Swap16IfLE(h);
3362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
3364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat           sz_rfbFramebufferUpdateRectHeader);
3365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
3366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordEncodingSent(cl, rfbEncodingNewFBSize, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
3368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
3370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Send the contents of cl->updateBuf.  Returns 1 if successful, -1 if
3375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * not (errno should be set).
3376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendUpdateBuf(rfbClientPtr cl)
3380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(cl->sock<0)
3382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return FALSE;
3383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, cl->updateBuf, cl->ublen) < 0) {
3385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbLogPerror("rfbSendUpdateBuf: write");
3386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbCloseClient(cl);
3387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        return FALSE;
3388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    cl->ublen = 0;
3391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
3392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
3396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * client, using values from the currently installed colormap.
3397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbBool
3400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendSetColourMapEntries(rfbClientPtr cl,
3401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           int firstColour,
3402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                           int nColours)
3403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
3405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    char *wbuf = buf;
3406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbSetColourMapEntriesMsg *scme;
3407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    uint16_t *rgb;
3408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbColourMap* cm = &cl->screen->colourMap;
3409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int i, len;
3410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (nColours > 256) {
3412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* some rare hardware has, e.g., 4096 colors cells: PseudoColor:12 */
3413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    	wbuf = (char *) malloc(sz_rfbSetColourMapEntriesMsg + nColours * 3 * 2);
3414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    scme = (rfbSetColourMapEntriesMsg *)wbuf;
3417a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rgb = (uint16_t *)(&wbuf[sz_rfbSetColourMapEntriesMsg]);
3418a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3419a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    scme->type = rfbSetColourMapEntries;
3420a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3421a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    scme->firstColour = Swap16IfLE(firstColour);
3422a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    scme->nColours = Swap16IfLE(nColours);
3423a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3424a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    len = sz_rfbSetColourMapEntriesMsg;
3425a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3426a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for (i = 0; i < nColours; i++) {
3427a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(i<(int)cm->count) {
3428a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(cm->is16) {
3429a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
3430a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
3431a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
3432a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else {
3433a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3] = Swap16IfLE((unsigned short)cm->data.bytes[i*3]);
3434a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3+1] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+1]);
3435a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  rgb[i*3+2] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+2]);
3436a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3437a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
3438a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3439a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3440a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    len += nColours * 3 * 2;
3441a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3442a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    LOCK(cl->sendMutex);
3443a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (rfbWriteExact(cl, wbuf, len) < 0) {
3444a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLogPerror("rfbSendSetColourMapEntries: write");
3445a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbCloseClient(cl);
3446a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (wbuf != buf) free(wbuf);
3447a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        UNLOCK(cl->sendMutex);
3448a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return FALSE;
3449a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3450a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    UNLOCK(cl->sendMutex);
3451a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3452a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbSetColourMapEntries, len, len);
3453a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (wbuf != buf) free(wbuf);
3454a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return TRUE;
3455a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3456a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3457a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3458a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbSendBell sends a Bell message to all the clients.
3459a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3460a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3461a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
3462a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendBell(rfbScreenInfoPtr rfbScreen)
3463a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3464a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientIteratorPtr i;
3465a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr cl;
3466a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbBellMsg b;
3467a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3468a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    i = rfbGetClientIterator(rfbScreen);
3469a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    while((cl=rfbClientIteratorNext(i))) {
3470a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	b.type = rfbBell;
3471a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        LOCK(cl->sendMutex);
3472a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (rfbWriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) {
3473a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbLogPerror("rfbSendBell: write");
3474a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbCloseClient(cl);
3475a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3476a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        UNLOCK(cl->sendMutex);
3477a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3478a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbStatRecordMessageSent(cl, rfbBell, sz_rfbBellMsg, sz_rfbBellMsg);
3479a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbReleaseClientIterator(i);
3480a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3481a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3482a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3483a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3484a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbSendServerCutText sends a ServerCutText message to all the clients.
3485a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3486a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3487a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
3488a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
3489a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3490a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr cl;
3491a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbServerCutTextMsg sct;
3492a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientIteratorPtr iterator;
3493a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3494a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    iterator = rfbGetClientIterator(rfbScreen);
3495a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
3496a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sct.type = rfbServerCutText;
3497a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        sct.length = Swap32IfLE(len);
3498a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        LOCK(cl->sendMutex);
3499a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (rfbWriteExact(cl, (char *)&sct,
3500a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                       sz_rfbServerCutTextMsg) < 0) {
3501a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbSendServerCutText: write");
3502a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
3503a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            UNLOCK(cl->sendMutex);
3504a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            continue;
3505a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
3506a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        if (rfbWriteExact(cl, str, len) < 0) {
3507a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbLogPerror("rfbSendServerCutText: write");
3508a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat            rfbCloseClient(cl);
3509a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        }
3510a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        UNLOCK(cl->sendMutex);
3511a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat        rfbStatRecordMessageSent(cl, rfbServerCutText, sz_rfbServerCutTextMsg+len, sz_rfbServerCutTextMsg+len);
3512a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3513a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbReleaseClientIterator(iterator);
3514a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3515a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3516a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*****************************************************************************
3517a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
3518a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * UDP can be used for keyboard and pointer events when the underlying
3519a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * network is highly reliable.  This is really here to support ORL's
3520a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * videotile, whose TCP implementation doesn't like sending lots of small
3521a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * packets (such as 100s of pen readings per second!).
3522a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3523a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3524a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic unsigned char ptrAcceleration = 50;
3525a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3526a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
3527a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,
3528a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat                    int sock)
3529a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3530a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (write(sock, (char*) &ptrAcceleration, 1) < 0) {
3531a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbLogPerror("rfbNewUDPConnection: write");
3532a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3533a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3534a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3535a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
3536a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Because UDP is a message based service, we can't read the first byte and
3537a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * then the rest of the packet separately like we do with TCP.  We will always
3538a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * get a whole packet delivered in one go, so we ask read() for the maximum
3539a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * number of bytes we can possibly get.
3540a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
3541a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3542a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
3543a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbProcessUDPInput(rfbScreenInfoPtr rfbScreen)
3544a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
3545a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int n;
3546a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientPtr cl=rfbScreen->udpClient;
3547a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbClientToServerMsg msg;
3548a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3549a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if((!cl) || cl->onHold)
3550a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return;
3551a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3552a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) {
3553a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (n < 0) {
3554a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbLogPerror("rfbProcessUDPInput: read");
3555a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3556a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbDisconnectUDPSock(rfbScreen);
3557a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
3558a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3559a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3560a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    switch (msg.type) {
3561a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3562a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbKeyEvent:
3563a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (n != sz_rfbKeyEventMsg) {
3564a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbErr("rfbProcessUDPInput: key event incorrect length\n");
3565a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbDisconnectUDPSock(rfbScreen);
3566a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
3567a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3568a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
3569a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	break;
3570a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3571a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    case rfbPointerEvent:
3572a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if (n != sz_rfbPointerEventMsg) {
3573a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbErr("rfbProcessUDPInput: ptr event incorrect length\n");
3574a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbDisconnectUDPSock(rfbScreen);
3575a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    return;
3576a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
3577a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	cl->screen->ptrAddEvent(msg.pe.buttonMask,
3578a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
3579a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	break;
3580a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3581a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    default:
3582a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbErr("rfbProcessUDPInput: unknown message type %d\n",
3583a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	       msg.type);
3584a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbDisconnectUDPSock(rfbScreen);
3585a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
3586a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
3587a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3588a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
3589