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