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