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