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