PageRenderTime 330ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/apps/desktop/libvncserver/rfbserver.c

http://ftk.googlecode.com/
C | 2091 lines | 1533 code | 301 blank | 257 comment | 247 complexity | b001978ce777d800da530f617c17cbc0 MD5 | raw file
Possible License(s): LGPL-3.0
  1. /*
  2. * rfbserver.c - deal with server-side of the RFB protocol.
  3. */
  4. /*
  5. * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
  6. * Copyright (C) 2002 RealVNC Ltd.
  7. * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
  8. * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
  9. * All Rights Reserved.
  10. *
  11. * This is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This software is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this software; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  24. * USA.
  25. */
  26. #ifdef __STRICT_ANSI__
  27. #define _BSD_SOURCE
  28. #endif
  29. #include <string.h>
  30. #include <rfb/rfb.h>
  31. #include <rfb/rfbregion.h>
  32. #include "private.h"
  33. #ifdef LIBVNCSERVER_HAVE_FCNTL_H
  34. #include <fcntl.h>
  35. #endif
  36. #ifdef WIN32
  37. #define write(sock,buf,len) send(sock,buf,len,0)
  38. #else
  39. #ifdef LIBVNCSERVER_HAVE_UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42. #include <pwd.h>
  43. #ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H
  44. #include <sys/socket.h>
  45. #endif
  46. #ifdef LIBVNCSERVER_HAVE_NETINET_IN_H
  47. #include <netinet/in.h>
  48. #include <netinet/tcp.h>
  49. #include <arpa/inet.h>
  50. #endif
  51. #endif
  52. #ifdef CORBA
  53. #include <vncserverctrl.h>
  54. #endif
  55. #ifdef DEBUGPROTO
  56. #undef DEBUGPROTO
  57. #define DEBUGPROTO(x) x
  58. #else
  59. #define DEBUGPROTO(x)
  60. #endif
  61. #include <stdarg.h>
  62. #include <scale.h>
  63. /* stst() */
  64. #include <sys/types.h>
  65. #include <sys/stat.h>
  66. #include <unistd.h>
  67. /* readdir() */
  68. #include <dirent.h>
  69. /* errno */
  70. #include <errno.h>
  71. #ifdef __MINGW32__
  72. static int compat_mkdir(const char *path, int mode)
  73. {
  74. return mkdir(path);
  75. }
  76. #define mkdir compat_mkdir
  77. #endif
  78. static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
  79. static void rfbProcessClientNormalMessage(rfbClientPtr cl);
  80. static void rfbProcessClientInitMessage(rfbClientPtr cl);
  81. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  82. void rfbIncrClientRef(rfbClientPtr cl)
  83. {
  84. LOCK(cl->refCountMutex);
  85. cl->refCount++;
  86. UNLOCK(cl->refCountMutex);
  87. }
  88. void rfbDecrClientRef(rfbClientPtr cl)
  89. {
  90. LOCK(cl->refCountMutex);
  91. cl->refCount--;
  92. if(cl->refCount<=0) /* just to be sure also < 0 */
  93. TSIGNAL(cl->deleteCond);
  94. UNLOCK(cl->refCountMutex);
  95. }
  96. #else
  97. void rfbIncrClientRef(rfbClientPtr cl) {}
  98. void rfbDecrClientRef(rfbClientPtr cl) {}
  99. #endif
  100. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  101. static MUTEX(rfbClientListMutex);
  102. #endif
  103. struct rfbClientIterator {
  104. rfbClientPtr next;
  105. rfbScreenInfoPtr screen;
  106. rfbBool closedToo;
  107. };
  108. void
  109. rfbClientListInit(rfbScreenInfoPtr rfbScreen)
  110. {
  111. if(sizeof(rfbBool)!=1) {
  112. /* a sanity check */
  113. fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool));
  114. /* we cannot continue, because rfbBool is supposed to be char everywhere */
  115. exit(1);
  116. }
  117. rfbScreen->clientHead = NULL;
  118. INIT_MUTEX(rfbClientListMutex);
  119. }
  120. rfbClientIteratorPtr
  121. rfbGetClientIterator(rfbScreenInfoPtr rfbScreen)
  122. {
  123. rfbClientIteratorPtr i =
  124. (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
  125. i->next = NULL;
  126. i->screen = rfbScreen;
  127. i->closedToo = FALSE;
  128. return i;
  129. }
  130. rfbClientIteratorPtr
  131. rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen)
  132. {
  133. rfbClientIteratorPtr i =
  134. (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator));
  135. i->next = NULL;
  136. i->screen = rfbScreen;
  137. i->closedToo = TRUE;
  138. return i;
  139. }
  140. rfbClientPtr
  141. rfbClientIteratorHead(rfbClientIteratorPtr i)
  142. {
  143. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  144. if(i->next != 0) {
  145. rfbDecrClientRef(i->next);
  146. rfbIncrClientRef(i->screen->clientHead);
  147. }
  148. #endif
  149. LOCK(rfbClientListMutex);
  150. i->next = i->screen->clientHead;
  151. UNLOCK(rfbClientListMutex);
  152. return i->next;
  153. }
  154. rfbClientPtr
  155. rfbClientIteratorNext(rfbClientIteratorPtr i)
  156. {
  157. if(i->next == 0) {
  158. LOCK(rfbClientListMutex);
  159. i->next = i->screen->clientHead;
  160. UNLOCK(rfbClientListMutex);
  161. } else {
  162. IF_PTHREADS(rfbClientPtr cl = i->next);
  163. i->next = i->next->next;
  164. IF_PTHREADS(rfbDecrClientRef(cl));
  165. }
  166. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  167. if(!i->closedToo)
  168. while(i->next && i->next->sock<0)
  169. i->next = i->next->next;
  170. if(i->next)
  171. rfbIncrClientRef(i->next);
  172. #endif
  173. return i->next;
  174. }
  175. void
  176. rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
  177. {
  178. IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
  179. free(iterator);
  180. }
  181. /*
  182. * rfbNewClientConnection is called from sockets.c when a new connection
  183. * comes in.
  184. */
  185. void
  186. rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,
  187. int sock)
  188. {
  189. rfbClientPtr cl;
  190. cl = rfbNewClient(rfbScreen,sock);
  191. #ifdef CORBA
  192. if(cl!=NULL)
  193. newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
  194. #endif
  195. }
  196. /*
  197. * rfbReverseConnection is called by the CORBA stuff to make an outward
  198. * connection to a "listening" RFB client.
  199. */
  200. rfbClientPtr
  201. rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
  202. char *host,
  203. int port)
  204. {
  205. int sock;
  206. rfbClientPtr cl;
  207. if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
  208. return (rfbClientPtr)NULL;
  209. cl = rfbNewClient(rfbScreen, sock);
  210. if (cl) {
  211. cl->reverseConnection = TRUE;
  212. }
  213. return cl;
  214. }
  215. void
  216. rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
  217. {
  218. /* Permit the server to set the version to report */
  219. /* TODO: sanity checking */
  220. if ((major_==3) && (minor_ > 2 && minor_ < 9))
  221. {
  222. rfbScreen->protocolMajorVersion = major_;
  223. rfbScreen->protocolMinorVersion = minor_;
  224. }
  225. else
  226. rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_);
  227. }
  228. /*
  229. * rfbNewClient is called when a new connection has been made by whatever
  230. * means.
  231. */
  232. static rfbClientPtr
  233. rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
  234. int sock,
  235. rfbBool isUDP)
  236. {
  237. rfbProtocolVersionMsg pv;
  238. rfbClientIteratorPtr iterator;
  239. rfbClientPtr cl,cl_;
  240. struct sockaddr_in addr;
  241. socklen_t addrlen = sizeof(struct sockaddr_in);
  242. rfbProtocolExtension* extension;
  243. cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
  244. cl->screen = rfbScreen;
  245. cl->sock = sock;
  246. cl->viewOnly = FALSE;
  247. /* setup pseudo scaling */
  248. cl->scaledScreen = rfbScreen;
  249. cl->scaledScreen->scaledScreenRefCount++;
  250. rfbResetStats(cl);
  251. cl->clientData = NULL;
  252. cl->clientGoneHook = rfbDoNothingWithClient;
  253. if(isUDP) {
  254. rfbLog(" accepted UDP client\n");
  255. } else {
  256. int one=1;
  257. getpeername(sock, (struct sockaddr *)&addr, &addrlen);
  258. cl->host = strdup(inet_ntoa(addr.sin_addr));
  259. rfbLog(" other clients:\n");
  260. iterator = rfbGetClientIterator(rfbScreen);
  261. while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) {
  262. rfbLog(" %s\n",cl_->host);
  263. }
  264. rfbReleaseClientIterator(iterator);
  265. #ifndef WIN32
  266. if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
  267. rfbLogPerror("fcntl failed");
  268. close(sock);
  269. return NULL;
  270. }
  271. #endif
  272. if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
  273. (char *)&one, sizeof(one)) < 0) {
  274. rfbLogPerror("setsockopt failed");
  275. close(sock);
  276. return NULL;
  277. }
  278. FD_SET(sock,&(rfbScreen->allFds));
  279. rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
  280. INIT_MUTEX(cl->outputMutex);
  281. INIT_MUTEX(cl->refCountMutex);
  282. INIT_COND(cl->deleteCond);
  283. cl->state = RFB_PROTOCOL_VERSION;
  284. cl->reverseConnection = FALSE;
  285. cl->readyForSetColourMapEntries = FALSE;
  286. cl->useCopyRect = FALSE;
  287. cl->preferredEncoding = -1;
  288. cl->correMaxWidth = 48;
  289. cl->correMaxHeight = 48;
  290. #ifdef LIBVNCSERVER_HAVE_LIBZ
  291. cl->zrleData = NULL;
  292. #endif
  293. cl->copyRegion = sraRgnCreate();
  294. cl->copyDX = 0;
  295. cl->copyDY = 0;
  296. cl->modifiedRegion =
  297. sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height);
  298. INIT_MUTEX(cl->updateMutex);
  299. INIT_COND(cl->updateCond);
  300. cl->requestedRegion = sraRgnCreate();
  301. cl->format = cl->screen->serverFormat;
  302. cl->translateFn = rfbTranslateNone;
  303. cl->translateLookupTable = NULL;
  304. LOCK(rfbClientListMutex);
  305. IF_PTHREADS(cl->refCount = 0);
  306. cl->next = rfbScreen->clientHead;
  307. cl->prev = NULL;
  308. if (rfbScreen->clientHead)
  309. rfbScreen->clientHead->prev = cl;
  310. rfbScreen->clientHead = cl;
  311. UNLOCK(rfbClientListMutex);
  312. #ifdef LIBVNCSERVER_HAVE_LIBZ
  313. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  314. cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
  315. cl->tightQualityLevel = -1;
  316. {
  317. int i;
  318. for (i = 0; i < 4; i++)
  319. cl->zsActive[i] = FALSE;
  320. }
  321. #endif
  322. #endif
  323. cl->fileTransfer.fd = -1;
  324. cl->enableCursorShapeUpdates = FALSE;
  325. cl->enableCursorPosUpdates = FALSE;
  326. cl->useRichCursorEncoding = FALSE;
  327. cl->enableLastRectEncoding = FALSE;
  328. cl->enableKeyboardLedState = FALSE;
  329. cl->enableSupportedMessages = FALSE;
  330. cl->enableSupportedEncodings = FALSE;
  331. cl->enableServerIdentity = FALSE;
  332. cl->lastKeyboardLedState = -1;
  333. cl->cursorX = rfbScreen->cursorX;
  334. cl->cursorY = rfbScreen->cursorY;
  335. cl->useNewFBSize = FALSE;
  336. #ifdef LIBVNCSERVER_HAVE_LIBZ
  337. cl->compStreamInited = FALSE;
  338. cl->compStream.total_in = 0;
  339. cl->compStream.total_out = 0;
  340. cl->compStream.zalloc = Z_NULL;
  341. cl->compStream.zfree = Z_NULL;
  342. cl->compStream.opaque = Z_NULL;
  343. cl->zlibCompressLevel = 5;
  344. #endif
  345. cl->progressiveSliceY = 0;
  346. cl->extensions = NULL;
  347. cl->lastPtrX = -1;
  348. sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion,
  349. rfbScreen->protocolMinorVersion);
  350. if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) {
  351. rfbLogPerror("rfbNewClient: write");
  352. rfbCloseClient(cl);
  353. rfbClientConnectionGone(cl);
  354. return NULL;
  355. }
  356. }
  357. for(extension = rfbGetExtensionIterator(); extension;
  358. extension=extension->next) {
  359. void* data = NULL;
  360. /* if the extension does not have a newClient method, it wants
  361. * to be initialized later. */
  362. if(extension->newClient && extension->newClient(cl, &data))
  363. rfbEnableExtension(cl, extension, data);
  364. }
  365. rfbReleaseExtensionIterator();
  366. switch (cl->screen->newClientHook(cl)) {
  367. case RFB_CLIENT_ON_HOLD:
  368. cl->onHold = TRUE;
  369. break;
  370. case RFB_CLIENT_ACCEPT:
  371. cl->onHold = FALSE;
  372. break;
  373. case RFB_CLIENT_REFUSE:
  374. rfbCloseClient(cl);
  375. rfbClientConnectionGone(cl);
  376. cl = NULL;
  377. break;
  378. }
  379. return cl;
  380. }
  381. rfbClientPtr
  382. rfbNewClient(rfbScreenInfoPtr rfbScreen,
  383. int sock)
  384. {
  385. return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
  386. }
  387. rfbClientPtr
  388. rfbNewUDPClient(rfbScreenInfoPtr rfbScreen)
  389. {
  390. return((rfbScreen->udpClient=
  391. rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE)));
  392. }
  393. /*
  394. * rfbClientConnectionGone is called from sockets.c just after a connection
  395. * has gone away.
  396. */
  397. void
  398. rfbClientConnectionGone(rfbClientPtr cl)
  399. {
  400. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  401. int i;
  402. #endif
  403. LOCK(rfbClientListMutex);
  404. if (cl->prev)
  405. cl->prev->next = cl->next;
  406. else
  407. cl->screen->clientHead = cl->next;
  408. if (cl->next)
  409. cl->next->prev = cl->prev;
  410. if(cl->sock>0)
  411. close(cl->sock);
  412. if (cl->scaledScreen!=NULL)
  413. cl->scaledScreen->scaledScreenRefCount--;
  414. #ifdef LIBVNCSERVER_HAVE_LIBZ
  415. rfbFreeZrleData(cl);
  416. #endif
  417. rfbFreeUltraData(cl);
  418. #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
  419. if(cl->screen->backgroundLoop != FALSE) {
  420. int i;
  421. do {
  422. LOCK(cl->refCountMutex);
  423. i=cl->refCount;
  424. if(i>0)
  425. WAIT(cl->deleteCond,cl->refCountMutex);
  426. UNLOCK(cl->refCountMutex);
  427. } while(i>0);
  428. }
  429. #endif
  430. UNLOCK(rfbClientListMutex);
  431. if(cl->sock>=0)
  432. FD_CLR(cl->sock,&(cl->screen->allFds));
  433. cl->clientGoneHook(cl);
  434. rfbLog("Client %s gone\n",cl->host);
  435. free(cl->host);
  436. #ifdef LIBVNCSERVER_HAVE_LIBZ
  437. /* Release the compression state structures if any. */
  438. if ( cl->compStreamInited ) {
  439. deflateEnd( &(cl->compStream) );
  440. }
  441. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  442. for (i = 0; i < 4; i++) {
  443. if (cl->zsActive[i])
  444. deflateEnd(&cl->zsStruct[i]);
  445. }
  446. #endif
  447. #endif
  448. if (cl->screen->pointerClient == cl)
  449. cl->screen->pointerClient = NULL;
  450. sraRgnDestroy(cl->modifiedRegion);
  451. sraRgnDestroy(cl->requestedRegion);
  452. sraRgnDestroy(cl->copyRegion);
  453. if (cl->translateLookupTable) free(cl->translateLookupTable);
  454. TINI_COND(cl->updateCond);
  455. TINI_MUTEX(cl->updateMutex);
  456. /* make sure outputMutex is unlocked before destroying */
  457. LOCK(cl->outputMutex);
  458. UNLOCK(cl->outputMutex);
  459. TINI_MUTEX(cl->outputMutex);
  460. #ifdef CORBA
  461. destroyConnection(cl);
  462. #endif
  463. rfbPrintStats(cl);
  464. free(cl);
  465. }
  466. /*
  467. * rfbProcessClientMessage is called when there is data to read from a client.
  468. */
  469. void
  470. rfbProcessClientMessage(rfbClientPtr cl)
  471. {
  472. switch (cl->state) {
  473. case RFB_PROTOCOL_VERSION:
  474. rfbProcessClientProtocolVersion(cl);
  475. return;
  476. case RFB_SECURITY_TYPE:
  477. rfbProcessClientSecurityType(cl);
  478. return;
  479. case RFB_AUTHENTICATION:
  480. rfbAuthProcessClientMessage(cl);
  481. return;
  482. case RFB_INITIALISATION:
  483. rfbProcessClientInitMessage(cl);
  484. return;
  485. default:
  486. rfbProcessClientNormalMessage(cl);
  487. return;
  488. }
  489. }
  490. /*
  491. * rfbProcessClientProtocolVersion is called when the client sends its
  492. * protocol version.
  493. */
  494. static void
  495. rfbProcessClientProtocolVersion(rfbClientPtr cl)
  496. {
  497. rfbProtocolVersionMsg pv;
  498. int n, major_, minor_;
  499. if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
  500. if (n == 0)
  501. rfbLog("rfbProcessClientProtocolVersion: client gone\n");
  502. else
  503. rfbLogPerror("rfbProcessClientProtocolVersion: read");
  504. rfbCloseClient(cl);
  505. return;
  506. }
  507. pv[sz_rfbProtocolVersionMsg] = 0;
  508. if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
  509. char name[1024];
  510. if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) {
  511. rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv);
  512. rfbCloseClient(cl);
  513. return;
  514. }
  515. free(cl->host);
  516. cl->host=strdup(name);
  517. }
  518. rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
  519. if (major_ != rfbProtocolMajorVersion) {
  520. rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
  521. cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
  522. major_,minor_);
  523. rfbCloseClient(cl);
  524. return;
  525. }
  526. /* Check for the minor version use either of the two standard version of RFB */
  527. /*
  528. * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
  529. * 3.4, 3.6, 3.14, 3.16
  530. * It's a bad method, but it is what they use to enable features...
  531. * maintaining RFB version compatibility across multiple servers is a pain
  532. * Should use something like ServerIdentity encoding
  533. */
  534. cl->protocolMajorVersion = major_;
  535. cl->protocolMinorVersion = minor_;
  536. rfbLog("Protocol version sent %d.%d, using %d.%d\n",
  537. major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion);
  538. rfbAuthNewClient(cl);
  539. }
  540. void
  541. rfbClientSendString(rfbClientPtr cl, char *reason)
  542. {
  543. char *buf;
  544. int len = strlen(reason);
  545. rfbLog("rfbClientSendString(\"%s\")\n", reason);
  546. buf = (char *)malloc(4 + len);
  547. ((uint32_t *)buf)[0] = Swap32IfLE(len);
  548. memcpy(buf + 4, reason, len);
  549. if (rfbWriteExact(cl, buf, 4 + len) < 0)
  550. rfbLogPerror("rfbClientSendString: write");
  551. free(buf);
  552. rfbCloseClient(cl);
  553. }
  554. /*
  555. * rfbClientConnFailed is called when a client connection has failed either
  556. * because it talks the wrong protocol or it has failed authentication.
  557. */
  558. void
  559. rfbClientConnFailed(rfbClientPtr cl,
  560. char *reason)
  561. {
  562. char *buf;
  563. int len = strlen(reason);
  564. rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
  565. buf = (char *)malloc(8 + len);
  566. ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
  567. ((uint32_t *)buf)[1] = Swap32IfLE(len);
  568. memcpy(buf + 8, reason, len);
  569. if (rfbWriteExact(cl, buf, 8 + len) < 0)
  570. rfbLogPerror("rfbClientConnFailed: write");
  571. free(buf);
  572. rfbCloseClient(cl);
  573. }
  574. /*
  575. * rfbProcessClientInitMessage is called when the client sends its
  576. * initialisation message.
  577. */
  578. static void
  579. rfbProcessClientInitMessage(rfbClientPtr cl)
  580. {
  581. rfbClientInitMsg ci;
  582. char buf[256];
  583. rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
  584. int len, n;
  585. rfbClientIteratorPtr iterator;
  586. rfbClientPtr otherCl;
  587. rfbExtensionData* extension;
  588. if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
  589. if (n == 0)
  590. rfbLog("rfbProcessClientInitMessage: client gone\n");
  591. else
  592. rfbLogPerror("rfbProcessClientInitMessage: read");
  593. rfbCloseClient(cl);
  594. return;
  595. }
  596. memset(buf,0,sizeof(buf));
  597. si->framebufferWidth = Swap16IfLE(cl->screen->width);
  598. si->framebufferHeight = Swap16IfLE(cl->screen->height);
  599. si->format = cl->screen->serverFormat;
  600. si->format.redMax = Swap16IfLE(si->format.redMax);
  601. si->format.greenMax = Swap16IfLE(si->format.greenMax);
  602. si->format.blueMax = Swap16IfLE(si->format.blueMax);
  603. strncpy(buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
  604. len = strlen(buf + sz_rfbServerInitMsg);
  605. si->nameLength = Swap32IfLE(len);
  606. if (rfbWriteExact(cl, buf, sz_rfbServerInitMsg + len) < 0) {
  607. rfbLogPerror("rfbProcessClientInitMessage: write");
  608. rfbCloseClient(cl);
  609. return;
  610. }
  611. for(extension = cl->extensions; extension;) {
  612. rfbExtensionData* next = extension->next;
  613. if(extension->extension->init &&
  614. !extension->extension->init(cl, extension->data))
  615. /* extension requested that it be removed */
  616. rfbDisableExtension(cl, extension->extension);
  617. extension = next;
  618. }
  619. cl->state = RFB_NORMAL;
  620. if (!cl->reverseConnection &&
  621. (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) {
  622. if (cl->screen->dontDisconnect) {
  623. iterator = rfbGetClientIterator(cl->screen);
  624. while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
  625. if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
  626. rfbLog("-dontdisconnect: Not shared & existing client\n");
  627. rfbLog(" refusing new client %s\n", cl->host);
  628. rfbCloseClient(cl);
  629. rfbReleaseClientIterator(iterator);
  630. return;
  631. }
  632. }
  633. rfbReleaseClientIterator(iterator);
  634. } else {
  635. iterator = rfbGetClientIterator(cl->screen);
  636. while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
  637. if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
  638. rfbLog("Not shared - closing connection to client %s\n",
  639. otherCl->host);
  640. rfbCloseClient(otherCl);
  641. }
  642. }
  643. rfbReleaseClientIterator(iterator);
  644. }
  645. }
  646. }
  647. /* The values come in based on the scaled screen, we need to convert them to
  648. * values based on the man screen's coordinate system
  649. */
  650. static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
  651. rfbClientPtr cl)
  652. {
  653. int x1=Swap16IfLE(*x);
  654. int y1=Swap16IfLE(*y);
  655. int w1=Swap16IfLE(*w);
  656. int h1=Swap16IfLE(*h);
  657. rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip");
  658. *x = x1;
  659. *y = y1;
  660. *w = w1;
  661. *h = h1;
  662. if(*w>cl->screen->width-*x)
  663. *w=cl->screen->width-*x;
  664. /* possible underflow */
  665. if(*w>cl->screen->width-*x)
  666. return FALSE;
  667. if(*h>cl->screen->height-*y)
  668. *h=cl->screen->height-*y;
  669. if(*h>cl->screen->height-*y)
  670. return FALSE;
  671. return TRUE;
  672. }
  673. /*
  674. * Send keyboard state (PointerPos pseudo-encoding).
  675. */
  676. rfbBool
  677. rfbSendKeyboardLedState(rfbClientPtr cl)
  678. {
  679. rfbFramebufferUpdateRectHeader rect;
  680. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
  681. if (!rfbSendUpdateBuf(cl))
  682. return FALSE;
  683. }
  684. rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
  685. rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
  686. rect.r.y = 0;
  687. rect.r.w = 0;
  688. rect.r.h = 0;
  689. memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
  690. sz_rfbFramebufferUpdateRectHeader);
  691. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  692. rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);
  693. if (!rfbSendUpdateBuf(cl))
  694. return FALSE;
  695. return TRUE;
  696. }
  697. #define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8)))
  698. /*
  699. * Send rfbEncodingSupportedMessages.
  700. */
  701. rfbBool
  702. rfbSendSupportedMessages(rfbClientPtr cl)
  703. {
  704. rfbFramebufferUpdateRectHeader rect;
  705. rfbSupportedMessages msgs;
  706. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
  707. + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
  708. if (!rfbSendUpdateBuf(cl))
  709. return FALSE;
  710. }
  711. rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
  712. rect.r.x = 0;
  713. rect.r.y = 0;
  714. rect.r.w = Swap16IfLE(sz_rfbSupportedMessages);
  715. rect.r.h = 0;
  716. memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
  717. sz_rfbFramebufferUpdateRectHeader);
  718. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  719. memset((char *)&msgs, 0, sz_rfbSupportedMessages);
  720. rfbSetBit(msgs.client2server, rfbSetPixelFormat);
  721. rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
  722. rfbSetBit(msgs.client2server, rfbSetEncodings);
  723. rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
  724. rfbSetBit(msgs.client2server, rfbKeyEvent);
  725. rfbSetBit(msgs.client2server, rfbPointerEvent);
  726. rfbSetBit(msgs.client2server, rfbClientCutText);
  727. rfbSetBit(msgs.client2server, rfbFileTransfer);
  728. rfbSetBit(msgs.client2server, rfbSetScale);
  729. /*rfbSetBit(msgs.client2server, rfbSetServerInput); */
  730. /*rfbSetBit(msgs.client2server, rfbSetSW); */
  731. /*rfbSetBit(msgs.client2server, rfbTextChat); */
  732. /*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */
  733. rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
  734. rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
  735. rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
  736. rfbSetBit(msgs.server2client, rfbBell);
  737. rfbSetBit(msgs.server2client, rfbServerCutText);
  738. rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
  739. /*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */
  740. rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
  741. memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
  742. cl->ublen += sz_rfbSupportedMessages;
  743. rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages,
  744. sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages,
  745. sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages);
  746. if (!rfbSendUpdateBuf(cl))
  747. return FALSE;
  748. return TRUE;
  749. }
  750. static void rfbSendSupporteddEncodings_SendEncoding(rfbClientPtr cl, uint32_t enc)
  751. {
  752. uint32_t nSwapped=0;
  753. nSwapped = Swap32IfLE(enc);
  754. memcpy(&cl->updateBuf[cl->ublen], (char *)&nSwapped, sizeof(nSwapped));
  755. cl->ublen+=sizeof(nSwapped);
  756. }
  757. /*
  758. * Send rfbEncodingSupportedEncodings.
  759. */
  760. rfbBool
  761. rfbSendSupportedEncodings(rfbClientPtr cl)
  762. {
  763. rfbFramebufferUpdateRectHeader rect;
  764. uint16_t nEncodings=0;
  765. /* think rfbSetEncodingsMsg */
  766. /* TODO: dynamic way of doing this */
  767. nEncodings=16;
  768. #ifdef LIBVNCSERVER_HAVE_LIBZ
  769. nEncodings += 2;
  770. #endif
  771. #ifdef LIBVNCSERVER_HAVE_LIBZ
  772. nEncodings++;
  773. #endif
  774. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
  775. + (nEncodings*sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
  776. if (!rfbSendUpdateBuf(cl))
  777. return FALSE;
  778. }
  779. rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
  780. rect.r.x = 0;
  781. rect.r.y = 0;
  782. rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
  783. rect.r.h = Swap16IfLE(nEncodings);
  784. memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
  785. sz_rfbFramebufferUpdateRectHeader);
  786. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  787. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRaw);
  788. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCopyRect);
  789. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRRE);
  790. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCoRRE);
  791. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingHextile);
  792. #ifdef LIBVNCSERVER_HAVE_LIBZ
  793. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZlib);
  794. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingTight);
  795. #endif
  796. #ifdef LIBVNCSERVER_HAVE_LIBZ
  797. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZRLE);
  798. #endif
  799. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltra);
  800. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltraZip);
  801. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingXCursor);
  802. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRichCursor);
  803. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingPointerPos);
  804. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingLastRect);
  805. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingNewFBSize);
  806. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingKeyboardLedState);
  807. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedMessages);
  808. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedEncodings);
  809. rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingServerIdentity);
  810. rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings,
  811. sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)),
  812. sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)));
  813. if (!rfbSendUpdateBuf(cl))
  814. return FALSE;
  815. return TRUE;
  816. }
  817. void
  818. rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
  819. {
  820. char buffer[256];
  821. va_list ap;
  822. va_start(ap, fmt);
  823. vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
  824. va_end(ap);
  825. if (screen->versionString!=NULL) free(screen->versionString);
  826. screen->versionString = strdup(buffer);
  827. }
  828. /*
  829. * Send rfbEncodingServerIdentity.
  830. */
  831. rfbBool
  832. rfbSendServerIdentity(rfbClientPtr cl)
  833. {
  834. rfbFramebufferUpdateRectHeader rect;
  835. char buffer[512];
  836. /* tack on our library version */
  837. snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
  838. (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
  839. LIBVNCSERVER_PACKAGE_STRING);
  840. if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
  841. + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
  842. if (!rfbSendUpdateBuf(cl))
  843. return FALSE;
  844. }
  845. rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
  846. rect.r.x = 0;
  847. rect.r.y = 0;
  848. rect.r.w = Swap16IfLE(strlen(buffer)+1);
  849. rect.r.h = 0;
  850. memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
  851. sz_rfbFramebufferUpdateRectHeader);
  852. cl->ublen += sz_rfbFramebufferUpdateRectHeader;
  853. memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
  854. cl->ublen += strlen(buffer)+1;
  855. rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity,
  856. sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1,
  857. sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1);
  858. if (!rfbSendUpdateBuf(cl))
  859. return FALSE;
  860. return TRUE;
  861. }
  862. rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
  863. {
  864. rfbTextChatMsg tc;
  865. int bytesToSend=0;
  866. memset((char *)&tc, 0, sizeof(tc));
  867. tc.type = rfbTextChat;
  868. tc.length = Swap32IfLE(length);
  869. switch(length) {
  870. case rfbTextChatOpen:
  871. case rfbTextChatClose:
  872. case rfbTextChatFinished:
  873. bytesToSend=0;
  874. break;
  875. default:
  876. bytesToSend=length;
  877. if (bytesToSend>rfbTextMaxSize)
  878. bytesToSend=rfbTextMaxSize;
  879. }
  880. if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) {
  881. if (!rfbSendUpdateBuf(cl))
  882. return FALSE;
  883. }
  884. memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg);
  885. cl->ublen += sz_rfbTextChatMsg;
  886. if (bytesToSend>0) {
  887. memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend);
  888. cl->ublen += bytesToSend;
  889. }
  890. rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend);
  891. if (!rfbSendUpdateBuf(cl))
  892. return FALSE;
  893. return TRUE;
  894. }
  895. #define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
  896. if ((cl->screen->getFileTransferPermission != NULL \
  897. && cl->screen->getFileTransferPermission(cl) != TRUE) \
  898. || cl->screen->permitFileTransfer != TRUE) { \
  899. rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
  900. rfbCloseClient(cl); \
  901. return ret; \
  902. }
  903. int DB = 1;
  904. rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer)
  905. {
  906. rfbFileTransferMsg ft;
  907. ft.type = rfbFileTransfer;
  908. ft.contentType = contentType;
  909. ft.contentParam = contentParam;
  910. ft.pad = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */
  911. ft.size = Swap32IfLE(size);
  912. ft.length = Swap32IfLE(length);
  913. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
  914. /*
  915. rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer);
  916. */
  917. if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) {
  918. rfbLogPerror("rfbSendFileTransferMessage: write");
  919. rfbCloseClient(cl);
  920. return FALSE;
  921. }
  922. if (length>0)
  923. {
  924. if (rfbWriteExact(cl, buffer, length) < 0) {
  925. rfbLogPerror("rfbSendFileTransferMessage: write");
  926. rfbCloseClient(cl);
  927. return FALSE;
  928. }
  929. }
  930. rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length);
  931. return TRUE;
  932. }
  933. /*
  934. * UltraVNC uses Windows Structures
  935. */
  936. #define MAX_PATH 260
  937. typedef struct {
  938. uint32_t dwLowDateTime;
  939. uint32_t dwHighDateTime;
  940. } RFB_FILETIME;
  941. typedef struct {
  942. uint32_t dwFileAttributes;
  943. RFB_FILETIME ftCreationTime;
  944. RFB_FILETIME ftLastAccessTime;
  945. RFB_FILETIME ftLastWriteTime;
  946. uint32_t nFileSizeHigh;
  947. uint32_t nFileSizeLow;
  948. uint32_t dwReserved0;
  949. uint32_t dwReserved1;
  950. uint8_t cFileName[ MAX_PATH ];
  951. uint8_t cAlternateFileName[ 14 ];
  952. } RFB_FIND_DATA;
  953. #define RFB_FILE_ATTRIBUTE_READONLY 0x1
  954. #define RFB_FILE_ATTRIBUTE_HIDDEN 0x2
  955. #define RFB_FILE_ATTRIBUTE_SYSTEM 0x4
  956. #define RFB_FILE_ATTRIBUTE_DIRECTORY 0x10
  957. #define RFB_FILE_ATTRIBUTE_ARCHIVE 0x20
  958. #define RFB_FILE_ATTRIBUTE_NORMAL 0x80
  959. #define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100
  960. #define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800
  961. rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath)
  962. {
  963. int x;
  964. char *home=NULL;
  965. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
  966. /* C: */
  967. if (path[0]=='C' && path[1]==':')
  968. strcpy(unixPath, &path[2]);
  969. else
  970. {
  971. home = getenv("HOME");
  972. if (home!=NULL)
  973. {
  974. strcpy(unixPath, home);
  975. strcat(unixPath,"/");
  976. strcat(unixPath, path);
  977. }
  978. else
  979. strcpy(unixPath, path);
  980. }
  981. for (x=0;x<strlen(unixPath);x++)
  982. if (unixPath[x]=='\\') unixPath[x]='/';
  983. return TRUE;
  984. }
  985. rfbBool rfbFilenameTranslate2DOS(rfbClientPtr cl, char *unixPath, char *path)
  986. {
  987. int x;
  988. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
  989. sprintf(path,"C:%s", unixPath);
  990. for (x=2;x<strlen(path);x++)
  991. if (path[x]=='/') path[x]='\\';
  992. return TRUE;
  993. }
  994. rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
  995. {
  996. char retfilename[MAX_PATH];
  997. char path[MAX_PATH];
  998. struct stat statbuf;
  999. RFB_FIND_DATA win32filename;
  1000. int nOptLen = 0, retval=0;
  1001. DIR *dirp=NULL;
  1002. struct dirent *direntp=NULL;
  1003. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
  1004. /* Client thinks we are Winblows */
  1005. rfbFilenameTranslate2UNIX(cl, buffer, path);
  1006. if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);
  1007. dirp=opendir(path);
  1008. if (dirp==NULL)
  1009. return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);
  1010. /* send back the path name (necessary for links) */
  1011. if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;
  1012. for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
  1013. {
  1014. /* get stats */
  1015. snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
  1016. retval = stat(retfilename, &statbuf);
  1017. if (retval==0)
  1018. {
  1019. memset((char *)&win32filename, 0, sizeof(win32filename));
  1020. win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
  1021. if (S_ISDIR(statbuf.st_mode))
  1022. win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
  1023. win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime); /* Intel Order */
  1024. win32filename.ftCreationTime.dwHighDateTime = 0;
  1025. win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
  1026. win32filename.ftLastAccessTime.dwHighDateTime = 0;
  1027. win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime); /* Intel Order */
  1028. win32filename.ftLastWriteTime.dwHighDateTime = 0;
  1029. win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */
  1030. win32filename.nFileSizeHigh = 0;
  1031. win32filename.dwReserved0 = 0;
  1032. win32filename.dwReserved1 = 0;
  1033. /* If this had the full path, we would need to translate to DOS format ("C:\") */
  1034. /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
  1035. strcpy((char *)win32filename.cFileName, direntp->d_name);
  1036. /* Do not show hidden files (but show how to move up the tree) */
  1037. if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.'))
  1038. {
  1039. nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
  1040. /*
  1041. rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
  1042. */
  1043. if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE) return FALSE;
  1044. }
  1045. }
  1046. }
  1047. closedir(dirp);
  1048. /* End of the transfer */
  1049. return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
  1050. }
  1051. char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
  1052. {
  1053. char *buffer=NULL;
  1054. int n=0;
  1055. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);
  1056. /*
  1057. rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
  1058. */
  1059. if (length>0) {
  1060. buffer=malloc(length+1);
  1061. if (buffer!=NULL) {
  1062. if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
  1063. if (n != 0)
  1064. rfbLogPerror("rfbProcessFileTransferReadBuffer: read");
  1065. rfbCloseClient(cl);
  1066. /* NOTE: don't forget to free(buffer) if you return early! */
  1067. if (buffer!=NULL) free(buffer);
  1068. return NULL;
  1069. }
  1070. /* Null Terminate */
  1071. buffer[length]=0;
  1072. }
  1073. }
  1074. return buffer;
  1075. }
  1076. rfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
  1077. {
  1078. /* Allocate buffer for compression */
  1079. unsigned char readBuf[sz_rfbBlockSize];
  1080. int bytesRead=0;
  1081. int retval=0;
  1082. fd_set wfds;
  1083. struct timeval tv;
  1084. int n;
  1085. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1086. unsigned char compBuf[sz_rfbBlockSize + 1024];
  1087. unsigned long nMaxCompSize = sizeof(compBuf);
  1088. int nRetC = 0;
  1089. #endif
  1090. /*
  1091. * Don't close the client if we get into this one because
  1092. * it is called from many places to service file transfers.
  1093. * Note that permitFileTransfer is checked first.
  1094. */
  1095. if (cl->screen->permitFileTransfer != TRUE ||
  1096. (cl->screen->getFileTransferPermission != NULL
  1097. && cl->screen->getFileTransferPermission(cl) != TRUE)) {
  1098. return TRUE;
  1099. }
  1100. /* If not sending, or no file open... Return as if we sent something! */
  1101. if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
  1102. {
  1103. FD_ZERO(&wfds);
  1104. FD_SET(cl->sock, &wfds);
  1105. /* return immediately */
  1106. tv.tv_sec = 0;
  1107. tv.tv_usec = 0;
  1108. n = select(cl->sock + 1, NULL, &wfds, NULL, &tv);
  1109. if (n<0) {
  1110. rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno));
  1111. }
  1112. /* We have space on the transmit queue */
  1113. if (n > 0)
  1114. {
  1115. bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize);
  1116. switch (bytesRead) {
  1117. case 0:
  1118. /*
  1119. rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
  1120. */
  1121. retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL);
  1122. close(cl->fileTransfer.fd);
  1123. cl->fileTransfer.fd = -1;
  1124. cl->fileTransfer.sending = 0;
  1125. cl->fileTransfer.receiving = 0;
  1126. return retval;
  1127. case -1:
  1128. /* TODO : send an error msg to the client... */
  1129. rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno));
  1130. retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL);
  1131. close(cl->fileTransfer.fd);
  1132. cl->fileTransfer.fd = -1;
  1133. cl->fileTransfer.sending = 0;
  1134. cl->fileTransfer.receiving = 0;
  1135. return retval;
  1136. default:
  1137. /*
  1138. rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
  1139. */
  1140. if (!cl->fileTransfer.compressionEnabled)
  1141. return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
  1142. else
  1143. {
  1144. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1145. nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead);
  1146. /*
  1147. rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
  1148. */
  1149. if ((nRetC==0) && (nMaxCompSize<bytesRead))
  1150. return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 1, nMaxCompSize, (char *)compBuf);
  1151. else
  1152. return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
  1153. #else
  1154. /* We do not support compression of the data stream */
  1155. return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf);
  1156. #endif
  1157. }
  1158. }
  1159. }
  1160. }
  1161. return TRUE;
  1162. }
  1163. rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length)
  1164. {
  1165. char *buffer=NULL, *p=NULL;
  1166. int retval=0;
  1167. char filename1[MAX_PATH];
  1168. char filename2[MAX_PATH];
  1169. char szFileTime[MAX_PATH];
  1170. struct stat statbuf;
  1171. uint32_t sizeHtmp=0;
  1172. int n=0;
  1173. char timespec[64];
  1174. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1175. unsigned char compBuff[sz_rfbBlockSize];
  1176. unsigned long nRawBytes = sz_rfbBlockSize;
  1177. int nRet = 0;
  1178. #endif
  1179. FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);
  1180. /*
  1181. rfbLog("rfbProcessFileTransfer(%dtype, %dparam, %dsize, %dlen)\n", contentType, contentParam, size, length);
  1182. */
  1183. switch (contentType) {
  1184. case rfbDirContentRequest:
  1185. switch (contentParam) {
  1186. case rfbRDrivesList: /* Client requests the List of Local Drives */
  1187. /*
  1188. rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDrivesList:\n");
  1189. */
  1190. /* Format when filled : "C:\<NULL>D:\<NULL>....Z:\<NULL><NULL>
  1191. *
  1192. * We replace the "\" char following the drive letter and ":"
  1193. * with a char corresponding to the type of drive
  1194. * We obtain something like "C:l<NULL>D:c<NULL>....Z:n\<NULL><NULL>"
  1195. * Isn't it ugly ?
  1196. * DRIVE_FIXED = 'l' (local?)
  1197. * DRIVE_REMOVABLE = 'f' (floppy?)
  1198. * DRIVE_CDROM = 'c'
  1199. * DRIVE_REMOTE = 'n'
  1200. */
  1201. /* in unix, there are no 'drives' (We could list mount points though)
  1202. * We fake the root as a "C:" for the Winblows users
  1203. */
  1204. filename2[0]='C';
  1205. filename2[1]=':';
  1206. filename2[2]='l';
  1207. filename2[3]=0;
  1208. filename2[4]=0;
  1209. retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2);
  1210. if (buffer!=NULL) free(buffer);
  1211. return retval;
  1212. break;
  1213. case rfbRDirContent: /* Client requests the content of a directory */
  1214. /*
  1215. rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n");
  1216. */
  1217. if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
  1218. retval = rfbSendDirContent(cl, length, buffer);
  1219. if (buffer!=NULL) free(buffer);
  1220. return retval;
  1221. }
  1222. break;
  1223. case rfbDirPacket:
  1224. rfbLog("rfbProcessFileTransfer() rfbDirPacket\n");
  1225. break;
  1226. case rfbFileAcceptHeader:
  1227. rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n");
  1228. break;
  1229. case rfbCommandReturn:
  1230. rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n");
  1231. break;
  1232. case rfbFileChecksums:
  1233. /* Destination file already exists - the viewer sends the checksums */
  1234. rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n");
  1235. break;
  1236. case rfbFileTransferAccess:
  1237. rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n");
  1238. break;
  1239. /*
  1240. * sending from the server to the viewer
  1241. */
  1242. case rfbFileTransferRequest:
  1243. /*
  1244. rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n");
  1245. */
  1246. /* add some space to the end of the buffer as we will be adding a timespec to it */
  1247. if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
  1248. /* The client requests a File */
  1249. rfbFilenameTranslate2UNIX(cl, buffer, filename1);
  1250. cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744);
  1251. /*
  1252. */
  1253. if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd);
  1254. if (cl->fileTransfer.fd!=-1) {
  1255. if (fstat(cl->fileTransfer.fd, &statbuf)!=0) {
  1256. close(cl->fileTransfer.fd);
  1257. cl->fileTransfer.fd=-1;
  1258. }
  1259. else
  1260. {
  1261. /* Add the File Time Stamp to the filename */
  1262. strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime));
  1263. buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */
  1264. if (buffer==NULL) {
  1265. rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2);
  1266. return FALSE;
  1267. }
  1268. strcat(buffer,",");
  1269. strcat(buffer, timespec);
  1270. length = strlen(buffer);
  1271. if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer);
  1272. }
  1273. }
  1274. /* The viewer supports compression if size==1 */
  1275. cl->fileTransfer.compressionEnabled = (size==1);
  1276. /*
  1277. rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" <Compression Enabled>":""));
  1278. */
  1279. /* File Size in bytes, 0xFFFFFFFF (-1) means error */
  1280. retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer);
  1281. if (cl->fileTransfer.fd==-1)
  1282. {
  1283. if (buffer!=NULL) free(buffer);
  1284. return retval;
  1285. }
  1286. /* setup filetransfer stuff */
  1287. cl->fileTransfer.fileSize = statbuf.st_size;
  1288. cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize;
  1289. cl->fileTransfer.receiving = 0;
  1290. cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */
  1291. /* TODO: finish 64-bit file size support */
  1292. sizeHtmp = 0;
  1293. if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) {
  1294. rfbLogPerror("rfbProcessFileTransfer: write");
  1295. rfbCloseClient(cl);
  1296. if (buffer!=NULL) free(buffer);
  1297. return FALSE;
  1298. }
  1299. break;
  1300. case rfbFileHeader:
  1301. /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */
  1302. if (size==-1) {
  1303. rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n");
  1304. close(cl->fileTransfer.fd);
  1305. cl->fileTransfer.fd=-1;
  1306. return TRUE;
  1307. }
  1308. /*
  1309. rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size);
  1310. */
  1311. /* Starts the transfer! */
  1312. cl->fileTransfer.sending=1;
  1313. return rfbSendFileTransferChunk(cl);
  1314. break;
  1315. /*
  1316. * sending from the viewer to the server
  1317. */
  1318. case rfbFileTransferOffer:
  1319. /* client is sending a file to us */
  1320. /* buffer contains full path name (plus FileTime) */
  1321. /* size contains size of the file */
  1322. /*
  1323. rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n");
  1324. */
  1325. if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
  1326. /* Parse the FileTime */
  1327. p = strrchr(buffer, ',');
  1328. if (p!=NULL) {
  1329. *p = '\0';
  1330. strcpy(szFileTime, p+1);
  1331. } else
  1332. szFileTime[0]=0;
  1333. /* Need to read in sizeHtmp */
  1334. if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) {
  1335. if (n != 0)
  1336. rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp");
  1337. rfbCloseClient(cl);
  1338. /* NOTE: don't forget to free(buffer) if you return early! */
  1339. if (buffer!=NULL) free(buffer);
  1340. return FALSE;
  1341. }
  1342. sizeHtmp = Swap32IfLE(sizeHtmp);
  1343. rfbFilenameTranslate2UNIX(cl, buffer, filename1);
  1344. /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */
  1345. /* TODO: Delta Transfer */
  1346. cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744);
  1347. 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);
  1348. /*
  1349. */
  1350. /* File Size in bytes, 0xFFFFFFFF (-1) means error */
  1351. retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer);
  1352. if (cl->fileTransfer.fd==-1) {
  1353. free(buffer);
  1354. return retval;
  1355. }
  1356. /* setup filetransfer stuff */
  1357. cl->fileTransfer.fileSize = size;
  1358. cl->fileTransfer.numPackets = size / sz_rfbBlockSize;
  1359. cl->fileTransfer.receiving = 1;
  1360. cl->fileTransfer.sending = 0;
  1361. break;
  1362. case rfbFilePacket:
  1363. /*
  1364. rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n");
  1365. */
  1366. if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
  1367. if (cl->fileTransfer.fd!=-1) {
  1368. /* buffer contains the contents of the file */
  1369. if (size==0)
  1370. retval=write(cl->fileTransfer.fd, buffer, length);
  1371. else
  1372. {
  1373. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1374. /* compressed packet */
  1375. nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length);
  1376. retval=write(cl->fileTransfer.fd, compBuff, nRawBytes);
  1377. #else
  1378. /* Write the file out as received... */
  1379. retval=write(cl->fileTransfer.fd, buffer, length);
  1380. #endif
  1381. }
  1382. if (retval==-1)
  1383. {
  1384. close(cl->fileTransfer.fd);
  1385. cl->fileTransfer.fd=-1;
  1386. cl->fileTransfer.sending = 0;
  1387. cl->fileTransfer.receiving = 0;
  1388. }
  1389. }
  1390. break;
  1391. case rfbEndOfFile:
  1392. if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n");
  1393. /*
  1394. */
  1395. if (cl->fileTransfer.fd!=-1)
  1396. close(cl->fileTransfer.fd);
  1397. cl->fileTransfer.fd=-1;
  1398. cl->fileTransfer.sending = 0;
  1399. cl->fileTransfer.receiving = 0;
  1400. break;
  1401. case rfbAbortFileTransfer:
  1402. if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n");
  1403. /*
  1404. */
  1405. if (cl->fileTransfer.fd!=-1)
  1406. {
  1407. close(cl->fileTransfer.fd);
  1408. cl->fileTransfer.fd=-1;
  1409. cl->fileTransfer.sending = 0;
  1410. cl->fileTransfer.receiving = 0;
  1411. }
  1412. else
  1413. {
  1414. /* We use this message for FileTransfer rights (<=RC18 versions)
  1415. * The client asks for FileTransfer permission
  1416. */
  1417. if (contentParam == 0)
  1418. {
  1419. rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n");
  1420. /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/
  1421. return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, "");
  1422. }
  1423. /* New method is allowed */
  1424. if (cl->screen->getFileTransferPermission!=NULL)
  1425. {
  1426. if (cl->screen->getFileTransferPermission(cl)==TRUE)
  1427. {
  1428. rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
  1429. return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
  1430. }
  1431. else
  1432. {
  1433. rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n");
  1434. return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */
  1435. }
  1436. }
  1437. else
  1438. {
  1439. if (cl->screen->permitFileTransfer)
  1440. {
  1441. rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n");
  1442. return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */
  1443. }
  1444. else
  1445. {
  1446. rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n");
  1447. return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */
  1448. }
  1449. }
  1450. }
  1451. break;
  1452. case rfbCommand:
  1453. /*
  1454. rfbLog("rfbProcessFileTransfer() rfbCommand:\n");
  1455. */
  1456. if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE;
  1457. switch (contentParam) {
  1458. case rfbCDirCreate: /* Client requests the creation of a directory */
  1459. rfbFilenameTranslate2UNIX(cl, buffer, filename1);
  1460. retval = mkdir(filename1, 0755);
  1461. if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success"));
  1462. /*
  1463. */
  1464. retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer);
  1465. if (buffer!=NULL) free(buffer);
  1466. return retval;
  1467. case rfbCFileDelete: /* Client requests the deletion of a file */
  1468. rfbFilenameTranslate2UNIX(cl, buffer, filename1);
  1469. if (stat(filename1,&statbuf)==0)
  1470. {
  1471. if (S_ISDIR(statbuf.st_mode))
  1472. retval = rmdir(filename1);
  1473. else
  1474. retval = unlink(filename1);
  1475. }
  1476. else retval=-1;
  1477. retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer);
  1478. if (buffer!=NULL) free(buffer);
  1479. return retval;
  1480. case rfbCFileRename: /* Client requests the Renaming of a file/directory */
  1481. p = strrchr(buffer, '*');
  1482. if (p != NULL)
  1483. {
  1484. /* Split into 2 filenames ('*' is a seperator) */
  1485. *p = '\0';
  1486. rfbFilenameTranslate2UNIX(cl, buffer, filename1);
  1487. rfbFilenameTranslate2UNIX(cl, p+1, filename2);
  1488. retval = rename(filename1,filename2);
  1489. if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success"));
  1490. /*
  1491. */
  1492. /* Restore the buffer so the reply is good */
  1493. *p = '*';
  1494. retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer);
  1495. if (buffer!=NULL) free(buffer);
  1496. return retval;
  1497. }
  1498. break;
  1499. }
  1500. break;
  1501. }
  1502. /* NOTE: don't forget to free(buffer) if you return early! */
  1503. if (buffer!=NULL) free(buffer);
  1504. return TRUE;
  1505. }
  1506. /*
  1507. * rfbProcessClientNormalMessage is called when the client has sent a normal
  1508. * protocol message.
  1509. */
  1510. static void
  1511. rfbProcessClientNormalMessage(rfbClientPtr cl)
  1512. {
  1513. int n=0;
  1514. rfbClientToServerMsg msg;
  1515. char *str;
  1516. int i;
  1517. uint32_t enc=0;
  1518. uint32_t lastPreferredEncoding = -1;
  1519. char encBuf[64];
  1520. char encBuf2[64];
  1521. if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) {
  1522. if (n != 0)
  1523. rfbLogPerror("rfbProcessClientNormalMessage: read");
  1524. rfbCloseClient(cl);
  1525. return;
  1526. }
  1527. switch (msg.type) {
  1528. case rfbSetPixelFormat:
  1529. if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
  1530. sz_rfbSetPixelFormatMsg - 1)) <= 0) {
  1531. if (n != 0)
  1532. rfbLogPerror("rfbProcessClientNormalMessage: read");
  1533. rfbCloseClient(cl);
  1534. return;
  1535. }
  1536. cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
  1537. cl->format.depth = msg.spf.format.depth;
  1538. cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
  1539. cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
  1540. cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
  1541. cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
  1542. cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
  1543. cl->format.redShift = msg.spf.format.redShift;
  1544. cl->format.greenShift = msg.spf.format.greenShift;
  1545. cl->format.blueShift = msg.spf.format.blueShift;
  1546. cl->readyForSetColourMapEntries = TRUE;
  1547. cl->screen->setTranslateFunction(cl);
  1548. rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
  1549. return;
  1550. case rfbFixColourMapEntries:
  1551. if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
  1552. sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
  1553. if (n != 0)
  1554. rfbLogPerror("rfbProcessClientNormalMessage: read");
  1555. rfbCloseClient(cl);
  1556. return;
  1557. }
  1558. rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
  1559. rfbLog("rfbProcessClientNormalMessage: %s",
  1560. "FixColourMapEntries unsupported\n");
  1561. rfbCloseClient(cl);
  1562. return;
  1563. /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
  1564. * We may want to look into this...
  1565. * Example:
  1566. * case rfbEncodingXCursor:
  1567. * cl->enableCursorShapeUpdates = TRUE;
  1568. *
  1569. * Currently: cl->enableCursorShapeUpdates can *never* be turned off...
  1570. */
  1571. case rfbSetEncodings:
  1572. {
  1573. if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
  1574. sz_rfbSetEncodingsMsg - 1)) <= 0) {
  1575. if (n != 0)
  1576. rfbLogPerror("rfbProcessClientNormalMessage: read");
  1577. rfbCloseClient(cl);
  1578. return;
  1579. }
  1580. msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
  1581. rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4));
  1582. /*
  1583. * UltraVNC Client has the ability to adapt to changing network environments
  1584. * So, let's give it a change to tell us what it wants now!
  1585. */
  1586. if (cl->preferredEncoding!=-1)
  1587. lastPreferredEncoding = cl->preferredEncoding;
  1588. /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
  1589. cl->preferredEncoding=-1;
  1590. cl->useCopyRect = FALSE;
  1591. cl->useNewFBSize = FALSE;
  1592. cl->cursorWasChanged = FALSE;
  1593. cl->useRichCursorEncoding = FALSE;
  1594. cl->enableCursorPosUpdates = FALSE;
  1595. cl->enableCursorShapeUpdates = FALSE;
  1596. cl->enableCursorShapeUpdates = FALSE;
  1597. cl->enableLastRectEncoding = FALSE;
  1598. cl->enableKeyboardLedState = FALSE;
  1599. cl->enableSupportedMessages = FALSE;
  1600. cl->enableSupportedEncodings = FALSE;
  1601. cl->enableServerIdentity = FALSE;
  1602. for (i = 0; i < msg.se.nEncodings; i++) {
  1603. if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) {
  1604. if (n != 0)
  1605. rfbLogPerror("rfbProcessClientNormalMessage: read");
  1606. rfbCloseClient(cl);
  1607. return;
  1608. }
  1609. enc = Swap32IfLE(enc);
  1610. switch (enc) {
  1611. case rfbEncodingCopyRect:
  1612. cl->useCopyRect = TRUE;
  1613. break;
  1614. case rfbEncodingRaw:
  1615. case rfbEncodingRRE:
  1616. case rfbEncodingCoRRE:
  1617. case rfbEncodingHextile:
  1618. case rfbEncodingUltra:
  1619. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1620. case rfbEncodingZlib:
  1621. case rfbEncodingZRLE:
  1622. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  1623. case rfbEncodingTight:
  1624. #endif
  1625. #endif
  1626. /* The first supported encoding is the 'preferred' encoding */
  1627. if (cl->preferredEncoding == -1)
  1628. cl->preferredEncoding = enc;
  1629. break;
  1630. case rfbEncodingXCursor:
  1631. if(!cl->screen->dontConvertRichCursorToXCursor) {
  1632. rfbLog("Enabling X-style cursor updates for client %s\n",
  1633. cl->host);
  1634. /* if cursor was drawn, hide the cursor */
  1635. if(!cl->enableCursorShapeUpdates)
  1636. rfbRedrawAfterHideCursor(cl,NULL);
  1637. cl->enableCursorShapeUpdates = TRUE;
  1638. cl->cursorWasChanged = TRUE;
  1639. }
  1640. break;
  1641. case rfbEncodingRichCursor:
  1642. rfbLog("Enabling full-color cursor updates for client %s\n",
  1643. cl->host);
  1644. /* if cursor was drawn, hide the cursor */
  1645. if(!cl->enableCursorShapeUpdates)
  1646. rfbRedrawAfterHideCursor(cl,NULL);
  1647. cl->enableCursorShapeUpdates = TRUE;
  1648. cl->useRichCursorEncoding = TRUE;
  1649. cl->cursorWasChanged = TRUE;
  1650. break;
  1651. case rfbEncodingPointerPos:
  1652. if (!cl->enableCursorPosUpdates) {
  1653. rfbLog("Enabling cursor position updates for client %s\n",
  1654. cl->host);
  1655. cl->enableCursorPosUpdates = TRUE;
  1656. cl->cursorWasMoved = TRUE;
  1657. }
  1658. break;
  1659. case rfbEncodingLastRect:
  1660. if (!cl->enableLastRectEncoding) {
  1661. rfbLog("Enabling LastRect protocol extension for client "
  1662. "%s\n", cl->host);
  1663. cl->enableLastRectEncoding = TRUE;
  1664. }
  1665. break;
  1666. case rfbEncodingNewFBSize:
  1667. if (!cl->useNewFBSize) {
  1668. rfbLog("Enabling NewFBSize protocol extension for client "
  1669. "%s\n", cl->host);
  1670. cl->useNewFBSize = TRUE;
  1671. }
  1672. break;
  1673. case rfbEncodingKeyboardLedState:
  1674. if (!cl->enableKeyboardLedState) {
  1675. rfbLog("Enabling KeyboardLedState protocol extension for client "
  1676. "%s\n", cl->host);
  1677. cl->enableKeyboardLedState = TRUE;
  1678. }
  1679. break;
  1680. case rfbEncodingSupportedMessages:
  1681. if (!cl->enableSupportedMessages) {
  1682. rfbLog("Enabling SupportedMessages protocol extension for client "
  1683. "%s\n", cl->host);
  1684. cl->enableSupportedMessages = TRUE;
  1685. }
  1686. break;
  1687. case rfbEncodingSupportedEncodings:
  1688. if (!cl->enableSupportedEncodings) {
  1689. rfbLog("Enabling SupportedEncodings protocol extension for client "
  1690. "%s\n", cl->host);
  1691. cl->enableSupportedEncodings = TRUE;
  1692. }
  1693. break;
  1694. case rfbEncodingServerIdentity:
  1695. if (!cl->enableServerIdentity) {
  1696. rfbLog("Enabling ServerIdentity protocol extension for client "
  1697. "%s\n", cl->host);
  1698. cl->enableServerIdentity = TRUE;
  1699. }
  1700. break;
  1701. default:
  1702. #ifdef LIBVNCSERVER_HAVE_LIBZ
  1703. if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
  1704. enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
  1705. cl->zlibCompressLevel = enc & 0x0F;
  1706. #ifdef LIBVNCSERVER_HAVE_LIBJPEG
  1707. cl->tightCompressLevel = enc & 0x0F;
  1708. rfbLog("Using compression level %d for client %s\n",
  1709. cl->tightCompressLevel, cl->host);
  1710. } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
  1711. enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
  1712. cl->tightQualityLevel = enc & 0x0F;
  1713. rfbLog("Using image quality level %d for client %s\n",
  1714. cl->tightQualityLevel, cl->host);
  1715. #endif
  1716. } else
  1717. #endif
  1718. {
  1719. rfbExtensionData* e;
  1720. for(e = cl->extensions; e;) {
  1721. rfbExtensionData* next = e->next;
  1722. if(e->extension->enablePseudoEncoding &&
  1723. e->extension->enablePseudoEncoding(cl,
  1724. &e->data, (int)enc))
  1725. /* ext handles this encoding */
  1726. break;
  1727. e = next;
  1728. }
  1729. if(e == NULL) {
  1730. rfbBool handled = FALSE;
  1731. /* if the pseudo encoding is not handled by the
  1732. enabled extensions, search through all
  1733. extensions. */
  1734. rfbProtocolExtension* e;
  1735. for(e = rfbGetExtensionIterator(); e;) {
  1736. int* encs = e->pseudoEncodings;
  1737. while(encs && *encs!=0) {
  1738. if(*encs==(int)enc) {
  1739. void* data = NULL;
  1740. if(!e->enablePseudoEncoding(cl, &data, (int)enc)) {
  1741. rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc);
  1742. } else {
  1743. rfbEnableExtension(cl, e, data);
  1744. handled = TRUE;
  1745. e = NULL;
  1746. break;
  1747. }
  1748. }
  1749. encs++;
  1750. }
  1751. if(e)
  1752. e = e->next;
  1753. }
  1754. rfbReleaseExtensionIterator();
  1755. if(!handled)
  1756. rfbLog("rfbProcessClientNormalMessage: "
  1757. "ignoring unsupported encoding type %s\n",
  1758. encodingName(enc,encBuf,sizeof(encBuf)));
  1759. }
  1760. }
  1761. }
  1762. }
  1763. if (cl->preferredEncoding == -1) {
  1764. if (lastPreferredEncoding==-1) {
  1765. cl->preferredEncoding = rfbEncodingRaw;
  1766. rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
  1767. }
  1768. else {
  1769. cl->preferredEncoding = lastPreferredEncoding;
  1770. rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
  1771. }
  1772. }
  1773. else
  1774. {
  1775. if (lastPreferredEncoding==-1) {
  1776. rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
  1777. } else {
  1778. rfbLog("Switching from %s to %s Encoding for client %s\n",
  1779. encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)),
  1780. encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host);
  1781. }
  1782. }
  1783. if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
  1784. rfbLog("Disabling cursor position updates for client %s\n",
  1785. cl->host);
  1786. cl->enableCursorPosUpdates = FALSE;
  1787. }
  1788. return;
  1789. }
  1790. case rfbFramebufferUpdat