/apps/desktop/libvncserver/rfbserver.c

http://ftk.googlecode.com/ · C · 2091 lines · 1533 code · 301 blank · 257 comment · 251 complexity · b001978ce777d800da530f617c17cbc0 MD5 · raw file

Large files are truncated click here to view the full file

  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)