/apps/desktop/libvncserver/rfbserver.c
C | 2091 lines | 1533 code | 301 blank | 257 comment | 247 complexity | b001978ce777d800da530f617c17cbc0 MD5 | raw file
Possible License(s): LGPL-3.0
- /*
- * rfbserver.c - deal with server-side of the RFB protocol.
- */
- /*
- * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
- * Copyright (C) 2002 RealVNC Ltd.
- * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
- * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
- * All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
- #ifdef __STRICT_ANSI__
- #define _BSD_SOURCE
- #endif
- #include <string.h>
- #include <rfb/rfb.h>
- #include <rfb/rfbregion.h>
- #include "private.h"
- #ifdef LIBVNCSERVER_HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #ifdef WIN32
- #define write(sock,buf,len) send(sock,buf,len,0)
- #else
- #ifdef LIBVNCSERVER_HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <pwd.h>
- #ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
- #include <sys/socket.h>
- #endif
- #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <arpa/inet.h>
- #endif
- #endif
- #ifdef CORBA
- #include <vncserverctrl.h>
- #endif
- #ifdef DEBUGPROTO
- #undef DEBUGPROTO
- #define DEBUGPROTO(x) x
- #else
- #define DEBUGPROTO(x)
- #endif
- #include <stdarg.h>
- #include <scale.h>
- /* stst() */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- /* readdir() */
- #include <dirent.h>
- /* errno */
- #include <errno.h>
- #ifdef __MINGW32__
- static int compat_mkdir(const char *path, int mode)
- {
- return mkdir(path);
- }
- #define mkdir compat_mkdir
- #endif
- static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
- static void rfbProcessClientNormalMessage(rfbClientPtr cl);
- static void rfbProcessClientInitMessage(rfbClientPtr cl);
- #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
- void rfbIncrClientRef(rfbClientPtr cl)
- {
- LOCK(cl->refCountMutex);
- cl->refCount++;
- UNLOCK(cl->refCountMutex);
- }
- void rfbDecrClientRef(rfbClientPtr cl)
- {
- LOCK(cl->refCountMutex);
- cl->refCount--;
- if(cl->refCount<=0) /* just to be sure also < 0 */
- TSIGNAL(cl->deleteCond);
- UNLOCK(cl->refCountMutex);
- }
- #else
- void rfbIncrClientRef(rfbClientPtr cl) {}
- void rfbDecrClientRef(rfbClientPtr cl) {}
- #endif
- #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
- static MUTEX(rfbClientListMutex);
- #endif
- struct rfbClientIterator {
- rfbClientPtr next;
- rfbScreenInfoPtr screen;
- rfbBool closedToo;
- };
- void
- rfbClientListInit(rfbScreenInfoPtr rfbScreen)
- {
- if(sizeof(rfbBool)!=1) {
- /* a sanity check */
- fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool));
- /* we cannot continue, because rfbBool is supposed to be char everywhere */
- exit(1);
- }
- rfbScreen->clientHead = NULL;
- INIT_MUTEX(rfbClientListMutex);
- }
- rfbClientIteratorPtr
- rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
- {
- rfbClientIteratorPtr i =
- (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
- i->next = NULL;
- i->screen = rfbScreen;
- i->closedToo = FALSE;
- return i;
- }
- rfbClientIteratorPtr
- rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen)
- {
- rfbClientIteratorPtr i =
- (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
- i->next = NULL;
- i->screen = rfbScreen;
- i->closedToo = TRUE;
- return i;
- }
- rfbClientPtr
- rfbClientIteratorHead(rfbClientIteratorPtr i)
- {
- #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
- if(i->next != 0) {
- rfbDecrClientRef(i->next);
- rfbIncrClientRef(i->screen->clientHead);
- }
- #endif
- LOCK(rfbClientListMutex);
- i->next = i->screen->clientHead;
- UNLOCK(rfbClientListMutex);
- return i->next;
- }
- rfbClientPtr
- rfbClientIteratorNext(rfbClientIteratorPtr i)
- {
- if(i->next == 0) {
- LOCK(rfbClientListMutex);
- i->next = i->screen->clientHead;
- UNLOCK(rfbClientListMutex);
- } else {
- IF_PTHREADS(rfbClientPtr cl = i->next);
- i->next = i->next->next;
- IF_PTHREADS(rfbDecrClientRef(cl));
- }
- #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
- if(!i->closedToo)
- while(i->next && i->next->sock<0)
- i->next = i->next->next;
- if(i->next)
- rfbIncrClientRef(i->next);
- #endif
- return i->next;
- }
- void
- rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
- {
- IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
- free(iterator);
- }
- /*
- * rfbNewClientConnection is called from sockets.c when a new connection
- * comes in.
- */
- void
- rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
- int sock)
- {
- rfbClientPtr cl;
- cl = rfbNewClient(rfbScreen,sock);
- #ifdef CORBA
- if(cl!=NULL)
- newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
- #endif
- }
- /*
- * rfbReverseConnection is called by the CORBA stuff to make an outward
- * connection to a "listening" RFB client.
- */
- rfbClientPtr
- rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
- char *host,
- int port)
- {
- int sock;
- rfbClientPtr cl;
- if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
- return (rfbClientPtr)NULL;
- cl = rfbNewClient(rfbScreen, sock);
- if (cl) {
- cl->reverseConnection = TRUE;
- }
- return cl;
- }
- void
- rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
- {
- /* Permit the server to set the version to report */
- /* TODO: sanity checking */
- if ((major_==3) && (minor_ > 2 && minor_ < 9))
- {
- rfbScreen->protocolMajorVersion = major_;
- rfbScreen->protocolMinorVersion = minor_;
- }
- else
- rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_);
- }
- /*
- * rfbNewClient is called when a new connection has been made by whatever
- * means.
- */
- static rfbClientPtr
- rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
- int sock,
- rfbBool isUDP)
- {
- rfbProtocolVersionMsg pv;
- rfbClientIteratorPtr iterator;
- rfbClientPtr cl,cl_;
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(struct sockaddr_in);
- rfbProtocolExtension* extension;
- cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
- cl->screen = rfbScreen;
- cl->sock = sock;
- cl->viewOnly = FALSE;
- /* setup pseudo scaling */
- cl->scaledScreen = rfbScreen;
- cl->scaledScreen->scaledScreenRefCount++;
- rfbResetStats(cl);
- cl->clientData = NULL;
- cl->clientGoneHook = rfbDoNothingWithClient;
- if(isUDP) {
- rfbLog(" accepted UDP client\n");
- } else {
- int one=1;
- getpeername(sock, (struct sockaddr *)&addr, &addrlen);
- cl->host = strdup(inet_ntoa(addr.sin_addr));
- rfbLog(" other clients:\n");
- iterator = rfbGetClientIterator(rfbScreen);
- while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
- rfbLog(" %s\n",cl_->host);
- }
- rfbReleaseClientIterator(iterator);
- #ifndef WIN32
- if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
- rfbLogPerror("fcntl failed");
- close(sock);
- return NULL;
- }
- #endif
- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- (char *)&one, sizeof(one)) < 0) {
- rfbLogPerror("setsockopt failed");
- close(sock);
- return NULL;
- }
- FD_SET(sock,&(rfbScreen->allFds));
- rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
- INIT_MUTEX(cl->outputMutex);
- INIT_MUTEX(cl->refCountMutex);
- INIT_COND(cl->deleteCond);
- cl->state = RFB_PROTOCOL_VERSION;
- cl->reverseConnection = FALSE;
- cl->readyForSetColourMapEntries = FALSE;
- cl->useCopyRect = FALSE;
- cl->preferredEncoding = -1;
- cl->correMaxWidth = 48;
- cl->correMaxHeight = 48;
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- cl->zrleData = NULL;
- #endif
- cl->copyRegion = sraRgnCreate();
- cl->copyDX = 0;
- cl->copyDY = 0;
-
- cl->modifiedRegion =
- sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
- INIT_MUTEX(cl->updateMutex);
- INIT_COND(cl->updateCond);
- cl->requestedRegion = sraRgnCreate();
- cl->format = cl->screen->serverFormat;
- cl->translateFn = rfbTranslateNone;
- cl->translateLookupTable = NULL;
- LOCK(rfbClientListMutex);
- IF_PTHREADS(cl->refCount = 0);
- cl->next = rfbScreen->clientHead;
- cl->prev = NULL;
- if (rfbScreen->clientHead)
- rfbScreen->clientHead->prev = cl;
- rfbScreen->clientHead = cl;
- UNLOCK(rfbClientListMutex);
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- #ifdef LIBVNCSERVER_HAVE_LIBJPEG
- cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
- cl->tightQualityLevel = -1;
- {
- int i;
- for (i = 0; i < 4; i++)
- cl->zsActive[i] = FALSE;
- }
- #endif
- #endif
- cl->fileTransfer.fd = -1;
- cl->enableCursorShapeUpdates = FALSE;
- cl->enableCursorPosUpdates = FALSE;
- cl->useRichCursorEncoding = FALSE;
- cl->enableLastRectEncoding = FALSE;
- cl->enableKeyboardLedState = FALSE;
- cl->enableSupportedMessages = FALSE;
- cl->enableSupportedEncodings = FALSE;
- cl->enableServerIdentity = FALSE;
- cl->lastKeyboardLedState = -1;
- cl->cursorX = rfbScreen->cursorX;
- cl->cursorY = rfbScreen->cursorY;
- cl->useNewFBSize = FALSE;
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- cl->compStreamInited = FALSE;
- cl->compStream.total_in = 0;
- cl->compStream.total_out = 0;
- cl->compStream.zalloc = Z_NULL;
- cl->compStream.zfree = Z_NULL;
- cl->compStream.opaque = Z_NULL;
- cl->zlibCompressLevel = 5;
- #endif
- cl->progressiveSliceY = 0;
- cl->extensions = NULL;
- cl->lastPtrX = -1;
- sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion,
- rfbScreen->protocolMinorVersion);
- if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
- rfbLogPerror("rfbNewClient: write");
- rfbCloseClient(cl);
- rfbClientConnectionGone(cl);
- return NULL;
- }
- }
- for(extension = rfbGetExtensionIterator(); extension;
- extension=extension->next) {
- void* data = NULL;
- /* if the extension does not have a newClient method, it wants
- * to be initialized later. */
- if(extension->newClient && extension->newClient(cl, &data))
- rfbEnableExtension(cl, extension, data);
- }
- rfbReleaseExtensionIterator();
- switch (cl->screen->newClientHook(cl)) {
- case RFB_CLIENT_ON_HOLD:
- cl->onHold = TRUE;
- break;
- case RFB_CLIENT_ACCEPT:
- cl->onHold = FALSE;
- break;
- case RFB_CLIENT_REFUSE:
- rfbCloseClient(cl);
- rfbClientConnectionGone(cl);
- cl = NULL;
- break;
- }
- return cl;
- }
- rfbClientPtr
- rfbNewClient(rfbScreenInfoPtr rfbScreen,
- int sock)
- {
- return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
- }
- rfbClientPtr
- rfbNewUDPClient(rfbScreenInfoPtr rfbScreen)
- {
- return((rfbScreen->udpClient=
- rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
- }
- /*
- * rfbClientConnectionGone is called from sockets.c just after a connection
- * has gone away.
- */
- void
- rfbClientConnectionGone(rfbClientPtr cl)
- {
- #ifdef LIBVNCSERVER_HAVE_LIBJPEG
- int i;
- #endif
- LOCK(rfbClientListMutex);
- if (cl->prev)
- cl->prev->next = cl->next;
- else
- cl->screen->clientHead = cl->next;
- if (cl->next)
- cl->next->prev = cl->prev;
- if(cl->sock>0)
- close(cl->sock);
- if (cl->scaledScreen!=NULL)
- cl->scaledScreen->scaledScreenRefCount--;
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- rfbFreeZrleData(cl);
- #endif
- rfbFreeUltraData(cl);
- #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
- if(cl->screen->backgroundLoop != FALSE) {
- int i;
- do {
- LOCK(cl->refCountMutex);
- i=cl->refCount;
- if(i>0)
- WAIT(cl->deleteCond,cl->refCountMutex);
- UNLOCK(cl->refCountMutex);
- } while(i>0);
- }
- #endif
- UNLOCK(rfbClientListMutex);
- if(cl->sock>=0)
- FD_CLR(cl->sock,&(cl->screen->allFds));
- cl->clientGoneHook(cl);
- rfbLog("Client %s gone\n",cl->host);
- free(cl->host);
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- /* Release the compression state structures if any. */
- if ( cl->compStreamInited ) {
- deflateEnd( &(cl->compStream) );
- }
- #ifdef LIBVNCSERVER_HAVE_LIBJPEG
- for (i = 0; i < 4; i++) {
- if (cl->zsActive[i])
- deflateEnd(&cl->zsStruct[i]);
- }
- #endif
- #endif
- if (cl->screen->pointerClient == cl)
- cl->screen->pointerClient = NULL;
- sraRgnDestroy(cl->modifiedRegion);
- sraRgnDestroy(cl->requestedRegion);
- sraRgnDestroy(cl->copyRegion);
- if (cl->translateLookupTable) free(cl->translateLookupTable);
- TINI_COND(cl->updateCond);
- TINI_MUTEX(cl->updateMutex);
- /* make sure outputMutex is unlocked before destroying */
- LOCK(cl->outputMutex);
- UNLOCK(cl->outputMutex);
- TINI_MUTEX(cl->outputMutex);
- #ifdef CORBA
- destroyConnection(cl);
- #endif
- rfbPrintStats(cl);
- free(cl);
- }
- /*
- * rfbProcessClientMessage is called when there is data to read from a client.
- */
- void
- rfbProcessClientMessage(rfbClientPtr cl)
- {
- switch (cl->state) {
- case RFB_PROTOCOL_VERSION:
- rfbProcessClientProtocolVersion(cl);
- return;
- case RFB_SECURITY_TYPE:
- rfbProcessClientSecurityType(cl);
- return;
- case RFB_AUTHENTICATION:
- rfbAuthProcessClientMessage(cl);
- return;
- case RFB_INITIALISATION:
- rfbProcessClientInitMessage(cl);
- return;
- default:
- rfbProcessClientNormalMessage(cl);
- return;
- }
- }
- /*
- * rfbProcessClientProtocolVersion is called when the client sends its
- * protocol version.
- */
- static void
- rfbProcessClientProtocolVersion(rfbClientPtr cl)
- {
- rfbProtocolVersionMsg pv;
- int n, major_, minor_;
- if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
- if (n == 0)
- rfbLog("rfbProcessClientProtocolVersion: client gone\n");
- else
- rfbLogPerror("rfbProcessClientProtocolVersion: read");
- rfbCloseClient(cl);
- return;
- }
- pv[sz_rfbProtocolVersionMsg] = 0;
- if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
- char name[1024];
- if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) {
- rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv);
- rfbCloseClient(cl);
- return;
- }
- free(cl->host);
- cl->host=strdup(name);
- }
- rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
- if (major_ != rfbProtocolMajorVersion) {
- rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
- cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
- major_,minor_);
- rfbCloseClient(cl);
- return;
- }
- /* Check for the minor version use either of the two standard version of RFB */
- /*
- * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
- * 3.4, 3.6, 3.14, 3.16
- * It's a bad method, but it is what they use to enable features...
- * maintaining RFB version compatibility across multiple servers is a pain
- * Should use something like ServerIdentity encoding
- */
- cl->protocolMajorVersion = major_;
- cl->protocolMinorVersion = minor_;
-
- rfbLog("Protocol version sent %d.%d, using %d.%d\n",
- major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion);
- rfbAuthNewClient(cl);
- }
- void
- rfbClientSendString(rfbClientPtr cl, char *reason)
- {
- char *buf;
- int len = strlen(reason);
- rfbLog("rfbClientSendString(\"%s\")\n", reason);
- buf = (char *)malloc(4 + len);
- ((uint32_t *)buf)[0] = Swap32IfLE(len);
- memcpy(buf + 4, reason, len);
- if (rfbWriteExact(cl, buf, 4 + len) < 0)
- rfbLogPerror("rfbClientSendString: write");
- free(buf);
- rfbCloseClient(cl);
- }
- /*
- * rfbClientConnFailed is called when a client connection has failed either
- * because it talks the wrong protocol or it has failed authentication.
- */
- void
- rfbClientConnFailed(rfbClientPtr cl,
- char *reason)
- {
- char *buf;
- int len = strlen(reason);
- rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
- buf = (char *)malloc(8 + len);
- ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
- ((uint32_t *)buf)[1] = Swap32IfLE(len);
- memcpy(buf + 8, reason, len);
- if (rfbWriteExact(cl, buf, 8 + len) < 0)
- rfbLogPerror("rfbClientConnFailed: write");
- free(buf);
- rfbCloseClient(cl);
- }
- /*
- * rfbProcessClientInitMessage is called when the client sends its
- * initialisation message.
- */
- static void
- rfbProcessClientInitMessage(rfbClientPtr cl)
- {
- rfbClientInitMsg ci;
- char buf[256];
- rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
- int len, n;
- rfbClientIteratorPtr iterator;
- rfbClientPtr otherCl;
- rfbExtensionData* extension;
- if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
- if (n == 0)
- rfbLog("rfbProcessClientInitMessage: client gone\n");
- else
- rfbLogPerror("rfbProcessClientInitMessage: read");
- rfbCloseClient(cl);
- return;
- }
- memset(buf,0,sizeof(buf));
- si->framebufferWidth = Swap16IfLE(cl->screen->width);
- si->framebufferHeight = Swap16IfLE(cl->screen->height);
- si->format = cl->screen->serverFormat;
- si->format.redMax = Swap16IfLE(si->format.redMax);
- si->format.greenMax = Swap16IfLE(si->format.greenMax);
- si->format.blueMax = Swap16IfLE(si->format.blueMax);
- strncpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
- len = strlen(buf + sz_rfbServerInitMsg);
- si->nameLength = Swap32IfLE(len);
- if (rfbWriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
- rfbLogPerror("rfbProcessClientInitMessage: write");
- rfbCloseClient(cl);
- return;
- }
- for(extension = cl->extensions; extension;) {
- rfbExtensionData* next = extension->next;
- if(extension->extension->init &&
- !extension->extension->init(cl, extension->data))
- /* extension requested that it be removed */
- rfbDisableExtension(cl, extension->extension);
- extension = next;
- }
- cl->state = RFB_NORMAL;
- if (!cl->reverseConnection &&
- (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) {
- if (cl->screen->dontDisconnect) {
- iterator = rfbGetClientIterator(cl->screen);
- while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
- if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
- rfbLog("-dontdisconnect: Not shared & existing client\n");
- rfbLog(" refusing new client %s\n", cl->host);
- rfbCloseClient(cl);
- rfbReleaseClientIterator(iterator);
- return;
- }
- }
- rfbReleaseClientIterator(iterator);
- } else {
- iterator = rfbGetClientIterator(cl->screen);
- while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
- if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
- rfbLog("Not shared - closing connection to client %s\n",
- otherCl->host);
- rfbCloseClient(otherCl);
- }
- }
- rfbReleaseClientIterator(iterator);
- }
- }
- }
- /* The values come in based on the scaled screen, we need to convert them to
- * values based on the man screen's coordinate system
- */
- static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
- rfbClientPtr cl)
- {
- int x1=Swap16IfLE(*x);
- int y1=Swap16IfLE(*y);
- int w1=Swap16IfLE(*w);
- int h1=Swap16IfLE(*h);
- rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip");
- *x = x1;
- *y = y1;
- *w = w1;
- *h = h1;
- if(*w>cl->screen->width-*x)
- *w=cl->screen->width-*x;
- /* possible underflow */
- if(*w>cl->screen->width-*x)
- return FALSE;
- if(*h>cl->screen->height-*y)
- *h=cl->screen->height-*y;
- if(*h>cl->screen->height-*y)
- return FALSE;
- return TRUE;
- }
- /*
- * Send keyboard state (PointerPos pseudo-encoding).
- */
- rfbBool
- rfbSendKeyboardLedState(rfbClientPtr cl)
- {
- rfbFramebufferUpdateRectHeader rect;
- if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- }
- rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
- rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
- rect.r.y = 0;
- rect.r.w = 0;
- rect.r.h = 0;
- memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
- sz_rfbFramebufferUpdateRectHeader);
- cl->ublen += sz_rfbFramebufferUpdateRectHeader;
- rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- return TRUE;
- }
- #define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8)))
- /*
- * Send rfbEncodingSupportedMessages.
- */
- rfbBool
- rfbSendSupportedMessages(rfbClientPtr cl)
- {
- rfbFramebufferUpdateRectHeader rect;
- rfbSupportedMessages msgs;
- if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
- + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- }
- rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
- rect.r.x = 0;
- rect.r.y = 0;
- rect.r.w = Swap16IfLE(sz_rfbSupportedMessages);
- rect.r.h = 0;
- memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
- sz_rfbFramebufferUpdateRectHeader);
- cl->ublen += sz_rfbFramebufferUpdateRectHeader;
- memset((char *)&msgs, 0, sz_rfbSupportedMessages);
- rfbSetBit(msgs.client2server, rfbSetPixelFormat);
- rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
- rfbSetBit(msgs.client2server, rfbSetEncodings);
- rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
- rfbSetBit(msgs.client2server, rfbKeyEvent);
- rfbSetBit(msgs.client2server, rfbPointerEvent);
- rfbSetBit(msgs.client2server, rfbClientCutText);
- rfbSetBit(msgs.client2server, rfbFileTransfer);
- rfbSetBit(msgs.client2server, rfbSetScale);
- /*rfbSetBit(msgs.client2server, rfbSetServerInput); */
- /*rfbSetBit(msgs.client2server, rfbSetSW); */
- /*rfbSetBit(msgs.client2server, rfbTextChat); */
- /*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */
- rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
- rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
- rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
- rfbSetBit(msgs.server2client, rfbBell);
- rfbSetBit(msgs.server2client, rfbServerCutText);
- rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
- /*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */
- rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
- memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
- cl->ublen += sz_rfbSupportedMessages;
- rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages,
- sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages,
- sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages);
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- return TRUE;
- }
- static void rfbSendSupporteddEncodings_SendEncoding(rfbClientPtr cl, uint32_t enc)
- {
- uint32_t nSwapped=0;
- nSwapped = Swap32IfLE(enc);
- memcpy(&cl->updateBuf[cl->ublen], (char *)&nSwapped, sizeof(nSwapped));
- cl->ublen+=sizeof(nSwapped);
- }
- /*
- * Send rfbEncodingSupportedEncodings.
- */
- rfbBool
- rfbSendSupportedEncodings(rfbClientPtr cl)
- {
- rfbFramebufferUpdateRectHeader rect;
- uint16_t nEncodings=0;
-
- /* think rfbSetEncodingsMsg */
- /* TODO: dynamic way of doing this */
- nEncodings=16;
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- nEncodings += 2;
- #endif
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- nEncodings++;
- #endif
- if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
- + (nEncodings*sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- }
- rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
- rect.r.x = 0;
- rect.r.y = 0;
- rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
- rect.r.h = Swap16IfLE(nEncodings);
- memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
- sz_rfbFramebufferUpdateRectHeader);
- cl->ublen += sz_rfbFramebufferUpdateRectHeader;
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRaw);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCopyRect);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRRE);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCoRRE);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingHextile);
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZlib);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingTight);
- #endif
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZRLE);
- #endif
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltra);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltraZip);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingXCursor);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRichCursor);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingPointerPos);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingLastRect);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingNewFBSize);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingKeyboardLedState);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedMessages);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedEncodings);
- rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingServerIdentity);
- rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings,
- sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)),
- sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)));
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- return TRUE;
- }
- void
- rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
- {
- char buffer[256];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
- va_end(ap);
-
- if (screen->versionString!=NULL) free(screen->versionString);
- screen->versionString = strdup(buffer);
- }
- /*
- * Send rfbEncodingServerIdentity.
- */
- rfbBool
- rfbSendServerIdentity(rfbClientPtr cl)
- {
- rfbFramebufferUpdateRectHeader rect;
- char buffer[512];
- /* tack on our library version */
- snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
- (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
- LIBVNCSERVER_PACKAGE_STRING);
- if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
- + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- }
- rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
- rect.r.x = 0;
- rect.r.y = 0;
- rect.r.w = Swap16IfLE(strlen(buffer)+1);
- rect.r.h = 0;
- memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
- sz_rfbFramebufferUpdateRectHeader);
- cl->ublen += sz_rfbFramebufferUpdateRectHeader;
- memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
- cl->ublen += strlen(buffer)+1;
- rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity,
- sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1,
- sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1);
-
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- return TRUE;
- }
- rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
- {
- rfbTextChatMsg tc;
- int bytesToSend=0;
- memset((char *)&tc, 0, sizeof(tc));
- tc.type = rfbTextChat;
- tc.length = Swap32IfLE(length);
-
- switch(length) {
- case rfbTextChatOpen:
- case rfbTextChatClose:
- case rfbTextChatFinished:
- bytesToSend=0;
- break;
- default:
- bytesToSend=length;
- if (bytesToSend>rfbTextMaxSize)
- bytesToSend=rfbTextMaxSize;
- }
- if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) {
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
- }
-
- memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg);
- cl->ublen += sz_rfbTextChatMsg;
- if (bytesToSend>0) {
- memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend);
- cl->ublen += bytesToSend;
- }
- rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend);
- if (!rfbSendUpdateBuf(cl))
- return FALSE;
-
- return TRUE;
- }
- #define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
- if ((cl->screen->getFileTransferPermission != NULL \
- && cl->screen->getFileTransferPermission(cl) != TRUE) \
- || cl->screen->permitFileTransfer != TRUE) { \
- rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
- rfbCloseClient(cl); \
- return ret; \
- }
- int DB = 1;
- rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer)
- {
- rfbFileTransferMsg ft;
- ft.type = rfbFileTransfer;
- ft.contentType = contentType;
- ft.contentParam = contentParam;
- ft.pad = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */
- ft.size = Swap32IfLE(size);
- ft.length = Swap32IfLE(length);
-
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
- /*
- rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer);
- */
- if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) {
- rfbLogPerror("rfbSendFileTransferMessage: write");
- rfbCloseClient(cl);
- return FALSE;
- }
- if (length>0)
- {
- if (rfbWriteExact(cl, buffer, length) < 0) {
- rfbLogPerror("rfbSendFileTransferMessage: write");
- rfbCloseClient(cl);
- return FALSE;
- }
- }
- rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length);
- return TRUE;
- }
- /*
- * UltraVNC uses Windows Structures
- */
- #define MAX_PATH 260
- typedef struct {
- uint32_t dwLowDateTime;
- uint32_t dwHighDateTime;
- } RFB_FILETIME;
- typedef struct {
- uint32_t dwFileAttributes;
- RFB_FILETIME ftCreationTime;
- RFB_FILETIME ftLastAccessTime;
- RFB_FILETIME ftLastWriteTime;
- uint32_t nFileSizeHigh;
- uint32_t nFileSizeLow;
- uint32_t dwReserved0;
- uint32_t dwReserved1;
- uint8_t cFileName[ MAX_PATH ];
- uint8_t cAlternateFileName[ 14 ];
- } RFB_FIND_DATA;
- #define RFB_FILE_ATTRIBUTE_READONLY 0x1
- #define RFB_FILE_ATTRIBUTE_HIDDEN 0x2
- #define RFB_FILE_ATTRIBUTE_SYSTEM 0x4
- #define RFB_FILE_ATTRIBUTE_DIRECTORY 0x10
- #define RFB_FILE_ATTRIBUTE_ARCHIVE 0x20
- #define RFB_FILE_ATTRIBUTE_NORMAL 0x80
- #define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100
- #define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
- rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath)
- {
- int x;
- char *home=NULL;
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
- /* C: */
- if (path[0]=='C' && path[1]==':')
- strcpy(unixPath, &path[2]);
- else
- {
- home = getenv("HOME");
- if (home!=NULL)
- {
- strcpy(unixPath, home);
- strcat(unixPath,"/");
- strcat(unixPath, path);
- }
- else
- strcpy(unixPath, path);
- }
- for (x=0;x<strlen(unixPath);x++)
- if (unixPath[x]=='\\') unixPath[x]='/';
- return TRUE;
- }
- rfbBool rfbFilenameTranslate2DOS(rfbClientPtr cl, char *unixPath, char *path)
- {
- int x;
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
- sprintf(path,"C:%s", unixPath);
- for (x=2;x<strlen(path);x++)
- if (path[x]=='/') path[x]='\\';
- return TRUE;
- }
- rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
- {
- char retfilename[MAX_PATH];
- char path[MAX_PATH];
- struct stat statbuf;
- RFB_FIND_DATA win32filename;
- int nOptLen = 0, retval=0;
- DIR *dirp=NULL;
- struct dirent *direntp=NULL;
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
- /* Client thinks we are Winblows */
- rfbFilenameTranslate2UNIX(cl, buffer, path);
- if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
- dirp=opendir(path);
- if (dirp==NULL)
- return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);
- /* send back the path name (necessary for links) */
- if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;
- for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
- {
- /* get stats */
- snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
- retval = stat(retfilename, &statbuf);
- if (retval==0)
- {
- memset((char *)&win32filename, 0, sizeof(win32filename));
- win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
- if (S_ISDIR(statbuf.st_mode))
- win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
- win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime); /* Intel Order */
- win32filename.ftCreationTime.dwHighDateTime = 0;
- win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
- win32filename.ftLastAccessTime.dwHighDateTime = 0;
- win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime); /* Intel Order */
- win32filename.ftLastWriteTime.dwHighDateTime = 0;
- win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */
- win32filename.nFileSizeHigh = 0;
- win32filename.dwReserved0 = 0;
- win32filename.dwReserved1 = 0;
- /* If this had the full path, we would need to translate to DOS format ("C:\") */
- /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
- strcpy((char *)win32filename.cFileName, direntp->d_name);
-
- /* Do not show hidden files (but show how to move up the tree) */
- if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.'))
- {
- nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
- /*
- rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
- */
- if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE) return FALSE;
- }
- }
- }
- closedir(dirp);
- /* End of the transfer */
- return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
- }
- char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
- {
- char *buffer=NULL;
- int n=0;
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);
- /*
- rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
- */
- if (length>0) {
- buffer=malloc(length+1);
- if (buffer!=NULL) {
- if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessFileTransferReadBuffer: read");
- rfbCloseClient(cl);
- /* NOTE: don't forget to free(buffer) if you return early! */
- if (buffer!=NULL) free(buffer);
- return NULL;
- }
- /* Null Terminate */
- buffer[length]=0;
- }
- }
- return buffer;
- }
- rfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
- {
- /* Allocate buffer for compression */
- unsigned char readBuf[sz_rfbBlockSize];
- int bytesRead=0;
- int retval=0;
- fd_set wfds;
- struct timeval tv;
- int n;
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- unsigned char compBuf[sz_rfbBlockSize + 1024];
- unsigned long nMaxCompSize = sizeof(compBuf);
- int nRetC = 0;
- #endif
- /*
- * Don't close the client if we get into this one because
- * it is called from many places to service file transfers.
- * Note that permitFileTransfer is checked first.
- */
- if (cl->screen->permitFileTransfer != TRUE ||
- (cl->screen->getFileTransferPermission != NULL
- && cl->screen->getFileTransferPermission(cl) != TRUE)) {
- return TRUE;
- }
- /* If not sending, or no file open... Return as if we sent something! */
- if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
- {
- FD_ZERO(&wfds);
- FD_SET(cl->sock, &wfds);
- /* return immediately */
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- n = select(cl->sock + 1, NULL, &wfds, NULL, &tv);
- if (n<0) {
- rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno));
- }
- /* We have space on the transmit queue */
- if (n > 0)
- {
- bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize);
- switch (bytesRead) {
- case 0:
- /*
- rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
- */
- retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL);
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd = -1;
- cl->fileTransfer.sending = 0;
- cl->fileTransfer.receiving = 0;
- return retval;
- case -1:
- /* TODO : send an error msg to the client... */
- rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno));
- retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL);
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd = -1;
- cl->fileTransfer.sending = 0;
- cl->fileTransfer.receiving = 0;
- return retval;
- default:
- /*
- rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
- */
- if (!cl->fileTransfer.compressionEnabled)
- return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
- else
- {
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead);
- /*
- rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
- */
-
- if ((nRetC==0) && (nMaxCompSize<bytesRead))
- return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 1, nMaxCompSize, (char *)compBuf);
- else
- return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
- #else
- /* We do not support compression of the data stream */
- return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
- #endif
- }
- }
- }
- }
- return TRUE;
- }
- rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length)
- {
- char *buffer=NULL, *p=NULL;
- int retval=0;
- char filename1[MAX_PATH];
- char filename2[MAX_PATH];
- char szFileTime[MAX_PATH];
- struct stat statbuf;
- uint32_t sizeHtmp=0;
- int n=0;
- char timespec[64];
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- unsigned char compBuff[sz_rfbBlockSize];
- unsigned long nRawBytes = sz_rfbBlockSize;
- int nRet = 0;
- #endif
- FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
-
- /*
- rfbLog("rfbProcessFileTransfer(%dtype, %dparam, %dsize, %dlen)\n", contentType, contentParam, size, length);
- */
- switch (contentType) {
- case rfbDirContentRequest:
- switch (contentParam) {
- case rfbRDrivesList: /* Client requests the List of Local Drives */
- /*
- rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDrivesList:\n");
- */
- /* Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>
- *
- * We replace the "\" char following the drive letter and ":"
- * with a char corresponding to the type of drive
- * We obtain something like "C:l<NULL>D:c<NULL>....Z:n\<NULL><NULL>"
- * Isn't it ugly ?
- * DRIVE_FIXED = 'l' (local?)
- * DRIVE_REMOVABLE = 'f' (floppy?)
- * DRIVE_CDROM = 'c'
- * DRIVE_REMOTE = 'n'
- */
-
- /* in unix, there are no 'drives' (We could list mount points though)
- * We fake the root as a "C:" for the Winblows users
- */
- filename2[0]='C';
- filename2[1]=':';
- filename2[2]='l';
- filename2[3]=0;
- filename2[4]=0;
- retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2);
- if (buffer!=NULL) free(buffer);
- return retval;
- break;
- case rfbRDirContent: /* Client requests the content of a directory */
- /*
- rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n");
- */
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
- retval = rfbSendDirContent(cl, length, buffer);
- if (buffer!=NULL) free(buffer);
- return retval;
- }
- break;
- case rfbDirPacket:
- rfbLog("rfbProcessFileTransfer() rfbDirPacket\n");
- break;
- case rfbFileAcceptHeader:
- rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n");
- break;
- case rfbCommandReturn:
- rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n");
- break;
- case rfbFileChecksums:
- /* Destination file already exists - the viewer sends the checksums */
- rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n");
- break;
- case rfbFileTransferAccess:
- rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n");
- break;
- /*
- * sending from the server to the viewer
- */
- case rfbFileTransferRequest:
- /*
- rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n");
- */
- /* add some space to the end of the buffer as we will be adding a timespec to it */
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
- /* The client requests a File */
- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
- cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
- /*
- */
- if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd);
-
- if (cl->fileTransfer.fd!=-1) {
- if (fstat(cl->fileTransfer.fd, &statbuf)!=0) {
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd=-1;
- }
- else
- {
- /* Add the File Time Stamp to the filename */
- strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime));
- buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */
- if (buffer==NULL) {
- rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2);
- return FALSE;
- }
- strcat(buffer,",");
- strcat(buffer, timespec);
- length = strlen(buffer);
- if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer);
- }
- }
- /* The viewer supports compression if size==1 */
- cl->fileTransfer.compressionEnabled = (size==1);
- /*
- rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" <Compression Enabled>":""));
- */
- /* File Size in bytes, 0xFFFFFFFF (-1) means error */
- retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer);
- if (cl->fileTransfer.fd==-1)
- {
- if (buffer!=NULL) free(buffer);
- return retval;
- }
- /* setup filetransfer stuff */
- cl->fileTransfer.fileSize = statbuf.st_size;
- cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize;
- cl->fileTransfer.receiving = 0;
- cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */
- /* TODO: finish 64-bit file size support */
- sizeHtmp = 0;
- if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) {
- rfbLogPerror("rfbProcessFileTransfer: write");
- rfbCloseClient(cl);
- if (buffer!=NULL) free(buffer);
- return FALSE;
- }
- break;
- case rfbFileHeader:
- /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */
- if (size==-1) {
- rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n");
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd=-1;
- return TRUE;
- }
- /*
- rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size);
- */
- /* Starts the transfer! */
- cl->fileTransfer.sending=1;
- return rfbSendFileTransferChunk(cl);
- break;
- /*
- * sending from the viewer to the server
- */
- case rfbFileTransferOffer:
- /* client is sending a file to us */
- /* buffer contains full path name (plus FileTime) */
- /* size contains size of the file */
- /*
- rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n");
- */
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
- /* Parse the FileTime */
- p = strrchr(buffer, ',');
- if (p!=NULL) {
- *p = '\0';
- strcpy(szFileTime, p+1);
- } else
- szFileTime[0]=0;
- /* Need to read in sizeHtmp */
- if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp");
- rfbCloseClient(cl);
- /* NOTE: don't forget to free(buffer) if you return early! */
- if (buffer!=NULL) free(buffer);
- return FALSE;
- }
- sizeHtmp = Swap32IfLE(sizeHtmp);
-
- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
- /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
- /* TODO: Delta Transfer */
- cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744);
- 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);
- /*
- */
-
- /* File Size in bytes, 0xFFFFFFFF (-1) means error */
- retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer);
- if (cl->fileTransfer.fd==-1) {
- free(buffer);
- return retval;
- }
-
- /* setup filetransfer stuff */
- cl->fileTransfer.fileSize = size;
- cl->fileTransfer.numPackets = size / sz_rfbBlockSize;
- cl->fileTransfer.receiving = 1;
- cl->fileTransfer.sending = 0;
- break;
- case rfbFilePacket:
- /*
- rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n");
- */
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
- if (cl->fileTransfer.fd!=-1) {
- /* buffer contains the contents of the file */
- if (size==0)
- retval=write(cl->fileTransfer.fd, buffer, length);
- else
- {
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- /* compressed packet */
- nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length);
- retval=write(cl->fileTransfer.fd, compBuff, nRawBytes);
- #else
- /* Write the file out as received... */
- retval=write(cl->fileTransfer.fd, buffer, length);
- #endif
- }
- if (retval==-1)
- {
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd=-1;
- cl->fileTransfer.sending = 0;
- cl->fileTransfer.receiving = 0;
- }
- }
- break;
- case rfbEndOfFile:
- if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n");
- /*
- */
- if (cl->fileTransfer.fd!=-1)
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd=-1;
- cl->fileTransfer.sending = 0;
- cl->fileTransfer.receiving = 0;
- break;
- case rfbAbortFileTransfer:
- if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n");
- /*
- */
- if (cl->fileTransfer.fd!=-1)
- {
- close(cl->fileTransfer.fd);
- cl->fileTransfer.fd=-1;
- cl->fileTransfer.sending = 0;
- cl->fileTransfer.receiving = 0;
- }
- else
- {
- /* We use this message for FileTransfer rights (<=RC18 versions)
- * The client asks for FileTransfer permission
- */
- if (contentParam == 0)
- {
- rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n");
- /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/
- return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, "");
- }
- /* New method is allowed */
- if (cl->screen->getFileTransferPermission!=NULL)
- {
- if (cl->screen->getFileTransferPermission(cl)==TRUE)
- {
- rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
- return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
- }
- else
- {
- rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n");
- return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */
- }
- }
- else
- {
- if (cl->screen->permitFileTransfer)
- {
- rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
- return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
- }
- else
- {
- rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n");
- return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */
- }
-
- }
- }
- break;
- case rfbCommand:
- /*
- rfbLog("rfbProcessFileTransfer() rfbCommand:\n");
- */
- if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
- switch (contentParam) {
- case rfbCDirCreate: /* Client requests the creation of a directory */
- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
- retval = mkdir(filename1, 0755);
- if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
- /*
- */
- retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer);
- if (buffer!=NULL) free(buffer);
- return retval;
- case rfbCFileDelete: /* Client requests the deletion of a file */
- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
- if (stat(filename1,&statbuf)==0)
- {
- if (S_ISDIR(statbuf.st_mode))
- retval = rmdir(filename1);
- else
- retval = unlink(filename1);
- }
- else retval=-1;
- retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer);
- if (buffer!=NULL) free(buffer);
- return retval;
- case rfbCFileRename: /* Client requests the Renaming of a file/directory */
- p = strrchr(buffer, '*');
- if (p != NULL)
- {
- /* Split into 2 filenames ('*' is a seperator) */
- *p = '\0';
- rfbFilenameTranslate2UNIX(cl, buffer, filename1);
- rfbFilenameTranslate2UNIX(cl, p+1, filename2);
- retval = rename(filename1,filename2);
- if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
- /*
- */
- /* Restore the buffer so the reply is good */
- *p = '*';
- retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer);
- if (buffer!=NULL) free(buffer);
- return retval;
- }
- break;
- }
-
- break;
- }
- /* NOTE: don't forget to free(buffer) if you return early! */
- if (buffer!=NULL) free(buffer);
- return TRUE;
- }
- /*
- * rfbProcessClientNormalMessage is called when the client has sent a normal
- * protocol message.
- */
- static void
- rfbProcessClientNormalMessage(rfbClientPtr cl)
- {
- int n=0;
- rfbClientToServerMsg msg;
- char *str;
- int i;
- uint32_t enc=0;
- uint32_t lastPreferredEncoding = -1;
- char encBuf[64];
- char encBuf2[64];
- if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessClientNormalMessage: read");
- rfbCloseClient(cl);
- return;
- }
- switch (msg.type) {
- case rfbSetPixelFormat:
- if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
- sz_rfbSetPixelFormatMsg - 1)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessClientNormalMessage: read");
- rfbCloseClient(cl);
- return;
- }
- cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
- cl->format.depth = msg.spf.format.depth;
- cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
- cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
- cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
- cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
- cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
- cl->format.redShift = msg.spf.format.redShift;
- cl->format.greenShift = msg.spf.format.greenShift;
- cl->format.blueShift = msg.spf.format.blueShift;
- cl->readyForSetColourMapEntries = TRUE;
- cl->screen->setTranslateFunction(cl);
- rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
- return;
- case rfbFixColourMapEntries:
- if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
- sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessClientNormalMessage: read");
- rfbCloseClient(cl);
- return;
- }
- rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
- rfbLog("rfbProcessClientNormalMessage: %s",
- "FixColourMapEntries unsupported\n");
- rfbCloseClient(cl);
- return;
- /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
- * We may want to look into this...
- * Example:
- * case rfbEncodingXCursor:
- * cl->enableCursorShapeUpdates = TRUE;
- *
- * Currently: cl->enableCursorShapeUpdates can *never* be turned off...
- */
- case rfbSetEncodings:
- {
- if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
- sz_rfbSetEncodingsMsg - 1)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessClientNormalMessage: read");
- rfbCloseClient(cl);
- return;
- }
- msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
- rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4));
- /*
- * UltraVNC Client has the ability to adapt to changing network environments
- * So, let's give it a change to tell us what it wants now!
- */
- if (cl->preferredEncoding!=-1)
- lastPreferredEncoding = cl->preferredEncoding;
- /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
- cl->preferredEncoding=-1;
- cl->useCopyRect = FALSE;
- cl->useNewFBSize = FALSE;
- cl->cursorWasChanged = FALSE;
- cl->useRichCursorEncoding = FALSE;
- cl->enableCursorPosUpdates = FALSE;
- cl->enableCursorShapeUpdates = FALSE;
- cl->enableCursorShapeUpdates = FALSE;
- cl->enableLastRectEncoding = FALSE;
- cl->enableKeyboardLedState = FALSE;
- cl->enableSupportedMessages = FALSE;
- cl->enableSupportedEncodings = FALSE;
- cl->enableServerIdentity = FALSE;
- for (i = 0; i < msg.se.nEncodings; i++) {
- if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) {
- if (n != 0)
- rfbLogPerror("rfbProcessClientNormalMessage: read");
- rfbCloseClient(cl);
- return;
- }
- enc = Swap32IfLE(enc);
- switch (enc) {
- case rfbEncodingCopyRect:
- cl->useCopyRect = TRUE;
- break;
- case rfbEncodingRaw:
- case rfbEncodingRRE:
- case rfbEncodingCoRRE:
- case rfbEncodingHextile:
- case rfbEncodingUltra:
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- case rfbEncodingZlib:
- case rfbEncodingZRLE:
- #ifdef LIBVNCSERVER_HAVE_LIBJPEG
- case rfbEncodingTight:
- #endif
- #endif
- /* The first supported encoding is the 'preferred' encoding */
- if (cl->preferredEncoding == -1)
- cl->preferredEncoding = enc;
- break;
- case rfbEncodingXCursor:
- if(!cl->screen->dontConvertRichCursorToXCursor) {
- rfbLog("Enabling X-style cursor updates for client %s\n",
- cl->host);
- /* if cursor was drawn, hide the cursor */
- if(!cl->enableCursorShapeUpdates)
- rfbRedrawAfterHideCursor(cl,NULL);
- cl->enableCursorShapeUpdates = TRUE;
- cl->cursorWasChanged = TRUE;
- }
- break;
- case rfbEncodingRichCursor:
- rfbLog("Enabling full-color cursor updates for client %s\n",
- cl->host);
- /* if cursor was drawn, hide the cursor */
- if(!cl->enableCursorShapeUpdates)
- rfbRedrawAfterHideCursor(cl,NULL);
- cl->enableCursorShapeUpdates = TRUE;
- cl->useRichCursorEncoding = TRUE;
- cl->cursorWasChanged = TRUE;
- break;
- case rfbEncodingPointerPos:
- if (!cl->enableCursorPosUpdates) {
- rfbLog("Enabling cursor position updates for client %s\n",
- cl->host);
- cl->enableCursorPosUpdates = TRUE;
- cl->cursorWasMoved = TRUE;
- }
- break;
- case rfbEncodingLastRect:
- if (!cl->enableLastRectEncoding) {
- rfbLog("Enabling LastRect protocol extension for client "
- "%s\n", cl->host);
- cl->enableLastRectEncoding = TRUE;
- }
- break;
- case rfbEncodingNewFBSize:
- if (!cl->useNewFBSize) {
- rfbLog("Enabling NewFBSize protocol extension for client "
- "%s\n", cl->host);
- cl->useNewFBSize = TRUE;
- }
- break;
- case rfbEncodingKeyboardLedState:
- if (!cl->enableKeyboardLedState) {
- rfbLog("Enabling KeyboardLedState protocol extension for client "
- "%s\n", cl->host);
- cl->enableKeyboardLedState = TRUE;
- }
- break;
- case rfbEncodingSupportedMessages:
- if (!cl->enableSupportedMessages) {
- rfbLog("Enabling SupportedMessages protocol extension for client "
- "%s\n", cl->host);
- cl->enableSupportedMessages = TRUE;
- }
- break;
- case rfbEncodingSupportedEncodings:
- if (!cl->enableSupportedEncodings) {
- rfbLog("Enabling SupportedEncodings protocol extension for client "
- "%s\n", cl->host);
- cl->enableSupportedEncodings = TRUE;
- }
- break;
- case rfbEncodingServerIdentity:
- if (!cl->enableServerIdentity) {
- rfbLog("Enabling ServerIdentity protocol extension for client "
- "%s\n", cl->host);
- cl->enableServerIdentity = TRUE;
- }
- break;
- default:
- #ifdef LIBVNCSERVER_HAVE_LIBZ
- if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
- enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
- cl->zlibCompressLevel = enc & 0x0F;
- #ifdef LIBVNCSERVER_HAVE_LIBJPEG
- cl->tightCompressLevel = enc & 0x0F;
- rfbLog("Using compression level %d for client %s\n",
- cl->tightCompressLevel, cl->host);
- } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
- enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
- cl->tightQualityLevel = enc & 0x0F;
- rfbLog("Using image quality level %d for client %s\n",
- cl->tightQualityLevel, cl->host);
- #endif
- } else
- #endif
- {
- rfbExtensionData* e;
- for(e = cl->extensions; e;) {
- rfbExtensionData* next = e->next;
- if(e->extension->enablePseudoEncoding &&
- e->extension->enablePseudoEncoding(cl,
- &e->data, (int)enc))
- /* ext handles this encoding */
- break;
- e = next;
- }
- if(e == NULL) {
- rfbBool handled = FALSE;
- /* if the pseudo encoding is not handled by the
- enabled extensions, search through all
- extensions. */
- rfbProtocolExtension* e;
- for(e = rfbGetExtensionIterator(); e;) {
- int* encs = e->pseudoEncodings;
- while(encs && *encs!=0) {
- if(*encs==(int)enc) {
- void* data = NULL;
- if(!e->enablePseudoEncoding(cl, &data, (int)enc)) {
- rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc);
- } else {
- rfbEnableExtension(cl, e, data);
- handled = TRUE;
- e = NULL;
- break;
- }
- }
- encs++;
- }
- if(e)
- e = e->next;
- }
- rfbReleaseExtensionIterator();
- if(!handled)
- rfbLog("rfbProcessClientNormalMessage: "
- "ignoring unsupported encoding type %s\n",
- encodingName(enc,encBuf,sizeof(encBuf)));
- }
- }
- }
- }
- if (cl->preferredEncoding == -1) {
- if (lastPreferredEncoding==-1) {
- cl->preferredEncoding = rfbEncodingRaw;
- rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
- }
- else {
- cl->preferredEncoding = lastPreferredEncoding;
- rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
- }
- }
- else
- {
- if (lastPreferredEncoding==-1) {
- rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
- } else {
- rfbLog("Switching from %s to %s Encoding for client %s\n",
- encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)),
- encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host);
- }
- }
-
- if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
- rfbLog("Disabling cursor position updates for client %s\n",
- cl->host);
- cl->enableCursorPosUpdates = FALSE;
- }
- return;
- }
- case rfbFramebufferUpdat