~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/libvncserver/rfbserver.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

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