Home | History | Annotate | Download | only in tightvnc-filetransfer
      1 /*
      2  * Copyright (c) 2005 Novell, Inc.
      3  * All Rights Reserved.
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, contact Novell, Inc.
     16  *
     17  * To contact Novell about this file by physical or electronic mail,
     18  * you may find current contact information at www.novell.com
     19  *
     20  * Author		: Rohit Kumar
     21  * Email ID	: rokumar (at) novell.com
     22  * Date		: 14th July 2005
     23  */
     24 
     25 #ifndef _MSC_VER
     26 #include <pwd.h>
     27 #endif /* _MSC_VER */
     28 
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <unistd.h>
     33 #ifndef _MSC_VER
     34 #include <dirent.h>
     35 #include <pthread.h>
     36 #endif /* _MSC_VER */
     37 #include <sys/stat.h>
     38 #include <sys/types.h>
     39 #include <limits.h>
     40 
     41 #include <rfb/rfb.h>
     42 #include "rfbtightproto.h"
     43 #include "filetransfermsg.h"
     44 #include "handlefiletransferrequest.h"
     45 
     46 
     47 pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER;
     48 
     49 rfbBool fileTransferEnabled = TRUE;
     50 rfbBool fileTransferInitted = FALSE;
     51 char ftproot[PATH_MAX];
     52 
     53 
     54 /******************************************************************************
     55  * File Transfer Init methods. These methods are called for initializating
     56  * File Transfer and setting ftproot.
     57  ******************************************************************************/
     58 
     59 void InitFileTransfer();
     60 int SetFtpRoot(char* path);
     61 char* GetHomeDir(uid_t uid);
     62 void FreeHomeDir(char *homedir);
     63 
     64 /*
     65  * InitFileTransfer method is called before parsing the command-line options
     66  * for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc
     67  * server. In case of error ftproot is set to '\0' char.
     68  */
     69 
     70 void
     71 InitFileTransfer()
     72 {
     73 	char* userHome = NULL;
     74 	uid_t uid = geteuid();
     75 
     76 	if(fileTransferInitted)
     77 		return;
     78 
     79 	rfbLog("tightvnc-filetransfer/InitFileTransfer\n");
     80 
     81 	memset(ftproot, 0, sizeof(ftproot));
     82 
     83 	userHome = GetHomeDir(uid);
     84 
     85 	if((userHome != NULL) && (strlen(userHome) != 0)) {
     86 		SetFtpRoot(userHome);
     87 		FreeHomeDir(userHome);
     88 	}
     89 
     90 	fileTransferEnabled = TRUE;
     91 	fileTransferInitted = TRUE;
     92 }
     93 
     94 #ifndef __GNUC__
     95 #define __FUNCTION__ "unknown"
     96 #endif
     97 
     98 /*
     99  *  This method is called from InitFileTransfer method and
    100  *  if the command line option for ftproot is provided.
    101  */
    102 int
    103 SetFtpRoot(char* path)
    104 {
    105 	struct stat stat_buf;
    106 	DIR* dir = NULL;
    107 
    108 	rfbLog("tightvnc-filetransfer/SetFtpRoot\n");
    109 
    110 	if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) {
    111 		rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot"
    112 				" not changed\n", __FILE__, __FUNCTION__);
    113 		return FALSE;
    114 	}
    115 
    116 	if(stat(path, &stat_buf) < 0) {
    117 		rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
    118 				__FILE__, __FUNCTION__, path);
    119 		return FALSE;
    120 	}
    121 
    122 	if(S_ISDIR(stat_buf.st_mode) == 0) {
    123 		rfbLog("File [%s]: Method [%s]: path specified is not a directory\n",
    124 				__FILE__, __FUNCTION__);
    125 		return FALSE;
    126 	}
    127 
    128 	if((dir = opendir(path)) == NULL) {
    129 		rfbLog("File [%s]: Method [%s]: Not able to open the directory\n",
    130 				__FILE__, __FUNCTION__);
    131 		return FALSE;
    132 	}
    133 	else {
    134 		closedir(dir);
    135 		dir = NULL;
    136 	}
    137 
    138 
    139 	memset(ftproot, 0, PATH_MAX);
    140 	if(path[strlen(path)-1] == '/') {
    141 		memcpy(ftproot, path, strlen(path)-1);
    142 	}
    143 	else
    144 		memcpy(ftproot, path, strlen(path));
    145 
    146 
    147 	return TRUE;
    148 }
    149 
    150 
    151 /*
    152  * Get the home directory for the user name
    153  * param: username - name of the user for whom the home directory is required.
    154  * returns: returns the home directory for the user, or null in case the entry
    155  * is not found or any error. The returned string must be freed by calling the
    156  * freehomedir function.
    157 */
    158 char*
    159 GetHomeDir(uid_t uid)
    160 {
    161 	struct passwd *pwEnt = NULL;
    162 	char *homedir = NULL;
    163 
    164 	pwEnt = getpwuid (uid);
    165 	if (pwEnt == NULL)
    166 		return NULL;
    167 
    168 	if(pwEnt->pw_dir != NULL) {
    169 		homedir = strdup (pwEnt->pw_dir);
    170 	}
    171 
    172 	return homedir;
    173 }
    174 
    175 
    176 /*
    177  * Free the home directory allocated by a previous call to retrieve the home
    178  * directory. param: homedir - the string returned by a previous call to
    179  * retrieve home directory for a user.
    180  */
    181 void
    182 FreeHomeDir(char *homedir)
    183 {
    184     free (homedir);
    185 }
    186 
    187 
    188 /******************************************************************************
    189  * General methods.
    190  ******************************************************************************/
    191 
    192 /*
    193  * When the console sends the File Transfer Request, it sends the file path with
    194  * ftproot as "/". So on Agent, to get the absolute file path we need to prepend
    195  * the ftproot to it.
    196  */
    197 char*
    198 ConvertPath(char* path)
    199 {
    200 	char p[PATH_MAX];
    201 	memset(p, 0, PATH_MAX);
    202 
    203 	if( (path == NULL) ||
    204 		(strlen(path) == 0) ||
    205 		(strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) {
    206 
    207 		rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n",
    208 				__FILE__, __FUNCTION__);
    209 		return NULL;
    210 	}
    211 
    212 	memcpy(p, path, strlen(path));
    213 	memset(path, 0, PATH_MAX);
    214 	sprintf(path, "%s%s", ftproot, p);
    215 
    216 	return path;
    217 }
    218 
    219 
    220 void
    221 EnableFileTransfer(rfbBool enable)
    222 {
    223 	fileTransferEnabled = enable;
    224 }
    225 
    226 
    227 rfbBool
    228 IsFileTransferEnabled()
    229 {
    230 	return fileTransferEnabled;
    231 }
    232 
    233 
    234 char*
    235 GetFtpRoot()
    236 {
    237 	return ftproot;
    238 }
    239 
    240 
    241 /******************************************************************************
    242  * Methods to Handle File List Request.
    243  ******************************************************************************/
    244 
    245 /*
    246  *  HandleFileListRequest method is called when the server receives
    247  *  FileListRequest. In case of success a file list is sent to the client.
    248  *  For File List Request there is no failure reason sent.So here in case of any
    249  *  "unexpected" error no information will be sent. As these conditions should
    250  *  never come. Lets hope it never arrives :)
    251  *  In case of dir open failure an empty list will be sent, just the header of
    252  *  the message filled up. So on console you will get an Empty listing.
    253  */
    254 void
    255 HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data)
    256 {
    257 	rfbClientToServerTightMsg msg;
    258 	int n = 0;
    259 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
    260 	FileTransferMsg fileListMsg;
    261 
    262 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    263 	memset(path, 0, PATH_MAX);
    264 	memset(&fileListMsg, 0, sizeof(FileTransferMsg));
    265 
    266 	if(cl == NULL) {
    267 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
    268 				__FILE__, __FUNCTION__);
    269 		return;
    270 	}
    271 
    272 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) {
    273 
    274 		if (n < 0)
    275 			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name"
    276 					" length\n", __FILE__, __FUNCTION__);
    277 
    278 	    rfbCloseClient(cl);
    279 	    return;
    280 	}
    281 
    282 	msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize);
    283 	if ((msg.flr.dirNameSize == 0) ||
    284 		(msg.flr.dirNameSize > (PATH_MAX - 1))) {
    285 
    286 		rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is "
    287 				"greater that PATH_MAX\n", __FILE__, __FUNCTION__);
    288 
    289 		return;
    290 	}
    291 
    292 	if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) {
    293 
    294 		if (n < 0)
    295 			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n",
    296 							__FILE__, __FUNCTION__);
    297 
    298 	    rfbCloseClient(cl);
    299 	    return;
    300 	}
    301 
    302 	if(ConvertPath(path) == NULL) {
    303 
    304 		/* The execution should never reach here */
    305     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
    306     			__FILE__, __FUNCTION__);
    307     	return;
    308 	}
    309 
    310     fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags));
    311 
    312     if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) {
    313 
    314     	rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is "
    315     		"of Zero length\n",	__FILE__, __FUNCTION__);
    316     	return;
    317 	}
    318 
    319     rfbWriteExact(cl, fileListMsg.data, fileListMsg.length);
    320 
    321     FreeFileTransferMsg(fileListMsg);
    322 }
    323 
    324 
    325 /******************************************************************************
    326  * Methods to Handle File Download Request.
    327  ******************************************************************************/
    328 
    329 void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize);
    330 void SendFileDownloadLengthErrMsg(rfbClientPtr cl);
    331 void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data);
    332 #ifdef TODO
    333 void HandleFileDownloadRequest(rfbClientPtr cl);
    334 void SendFileDownloadErrMsg(rfbClientPtr cl);
    335 void* RunFileDownloadThread(void* client);
    336 #endif
    337 
    338 /*
    339  * HandleFileDownloadRequest method is called when the server receives
    340  * rfbFileDownload request message.
    341  */
    342 void
    343 HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    344 {
    345 	int n = 0;
    346 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
    347 	rfbClientToServerTightMsg msg;
    348 
    349  	memset(path, 0, sizeof(path));
    350 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    351 
    352 	if(cl == NULL) {
    353 
    354 		rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n",
    355 				__FILE__, __FUNCTION__);
    356 		return;
    357 	}
    358 
    359 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) {
    360 
    361 		if (n < 0)
    362 			rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
    363 					__FILE__, __FUNCTION__);
    364 
    365 	    rfbCloseClient(cl);
    366 	    return;
    367 	}
    368 
    369 	msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize);
    370 	msg.fdr.position = Swap16IfLE(msg.fdr.position);
    371 
    372 	if ((msg.fdr.fNameSize == 0) ||
    373 		(msg.fdr.fNameSize > (PATH_MAX - 1))) {
    374 
    375 		rfbLog("File [%s]: Method [%s]: Error: path length is greater than"
    376 				" PATH_MAX\n", __FILE__, __FUNCTION__);
    377 
    378 		HandleFileDownloadLengthError(cl, msg.fdr.fNameSize);
    379 		return;
    380 	}
    381 
    382 	if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) {
    383 
    384 		if (n < 0)
    385 			rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
    386 							__FILE__, __FUNCTION__);
    387 
    388 	    rfbCloseClient(cl);
    389 	    return;
    390 	}
    391 	rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0';
    392 
    393 	if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) {
    394 
    395     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
    396     			__FILE__, __FUNCTION__);
    397 
    398 
    399 		 /* This condition can come only if the file path is greater than
    400 		    PATH_MAX. So sending file path length error msg back to client.
    401 		 */
    402 
    403     	SendFileDownloadLengthErrMsg(cl);
    404 	return;
    405 	}
    406 
    407 	HandleFileDownload(cl, rtcp);
    408 
    409 }
    410 
    411 
    412 void
    413 HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize)
    414 {
    415 	char *path = NULL;
    416 	int n = 0;
    417 
    418 	if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
    419 		rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
    420 				__FILE__, __FUNCTION__);
    421 		return;
    422 	}
    423 	if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
    424 
    425 		if (n < 0)
    426 			rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
    427 							__FILE__, __FUNCTION__);
    428 
    429 	    rfbCloseClient(cl);
    430 
    431 	    if(path != NULL) {
    432 			free(path);
    433 			path = NULL;
    434 		}
    435 
    436 	    return;
    437 	}
    438 
    439     if(path != NULL) {
    440 		free(path);
    441 		path = NULL;
    442 	}
    443 
    444 	SendFileDownloadLengthErrMsg(cl);
    445 }
    446 
    447 
    448 void
    449 SendFileDownloadLengthErrMsg(rfbClientPtr cl)
    450 {
    451 	FileTransferMsg fileDownloadErrMsg;
    452 
    453 	memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg));
    454 
    455 	fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg();
    456 
    457 	if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) {
    458 		rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg "
    459 				"is null\n", __FILE__, __FUNCTION__);
    460 		return;
    461 	}
    462 
    463 	rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length);
    464 
    465 	FreeFileTransferMsg(fileDownloadErrMsg);
    466 }
    467 
    468 extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl);
    469 
    470 void*
    471 RunFileDownloadThread(void* client)
    472 {
    473 	rfbClientPtr cl = (rfbClientPtr) client;
    474 	rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
    475 	FileTransferMsg fileDownloadMsg;
    476 
    477 	if(rtcp == NULL)
    478 		return NULL;
    479 
    480 	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
    481 	do {
    482 		pthread_mutex_lock(&fileDownloadMutex);
    483 		fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp);
    484 		pthread_mutex_unlock(&fileDownloadMutex);
    485 
    486 		if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
    487 			if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0)  {
    488 				rfbLog("File [%s]: Method [%s]: Error while writing to socket \n"
    489 						, __FILE__, __FUNCTION__);
    490 
    491 				if(cl != NULL) {
    492 			    	rfbCloseClient(cl);
    493 				CloseUndoneFileTransfer(cl, rtcp);
    494 				}
    495 
    496 				FreeFileTransferMsg(fileDownloadMsg);
    497 				return NULL;
    498 			}
    499 			FreeFileTransferMsg(fileDownloadMsg);
    500 		}
    501 	} while(rtcp->rcft.rcfd.downloadInProgress == TRUE);
    502 	return NULL;
    503 }
    504 
    505 
    506 void
    507 HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp)
    508 {
    509 	pthread_t fileDownloadThread;
    510 	FileTransferMsg fileDownloadMsg;
    511 
    512 	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
    513 	fileDownloadMsg = ChkFileDownloadErr(cl, rtcp);
    514 	if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
    515 		rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length);
    516 		FreeFileTransferMsg(fileDownloadMsg);
    517 		return;
    518 	}
    519 	rtcp->rcft.rcfd.downloadInProgress = FALSE;
    520 	rtcp->rcft.rcfd.downloadFD = -1;
    521 
    522 	if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*)
    523 	cl) != 0) {
    524 		FileTransferMsg ftm = GetFileDownLoadErrMsg();
    525 
    526 		rfbLog("File [%s]: Method [%s]: Download thread creation failed\n",
    527 				__FILE__, __FUNCTION__);
    528 
    529 		if((ftm.data != NULL) && (ftm.length != 0)) {
    530 			rfbWriteExact(cl, ftm.data, ftm.length);
    531 			FreeFileTransferMsg(ftm);
    532 			return;
    533 		}
    534 
    535 	}
    536 
    537 }
    538 
    539 
    540 /******************************************************************************
    541  * Methods to Handle File Download Cancel Request.
    542  ******************************************************************************/
    543 
    544 
    545 void
    546 HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    547 {
    548 	int n = 0;
    549 	char *reason = NULL;
    550 	rfbClientToServerTightMsg msg;
    551 
    552 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    553 
    554 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) {
    555 
    556 		if (n < 0)
    557 			rfbLog("File [%s]: Method [%s]: Error while reading "
    558 					"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
    559 
    560 	    rfbCloseClient(cl);
    561 	    return;
    562 	}
    563 
    564 	msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen);
    565 
    566 	if(msg.fdc.reasonLen == 0) {
    567 		rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
    568 				__FILE__, __FUNCTION__);
    569 		return;
    570 	}
    571 
    572 	reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char));
    573 	if(reason == NULL) {
    574 		rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n",
    575 				__FILE__, __FUNCTION__);
    576 		return;
    577 	}
    578 
    579 	if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) {
    580 
    581 		if (n < 0)
    582 			rfbLog("File [%s]: Method [%s]: Error while reading "
    583 					"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
    584 
    585 	    rfbCloseClient(cl);
    586 	}
    587 
    588 	rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:"
    589 					" reason <%s>\n", __FILE__, __FUNCTION__, reason);
    590 
    591 	pthread_mutex_lock(&fileDownloadMutex);
    592 	CloseUndoneFileTransfer(cl, rtcp);
    593 	pthread_mutex_unlock(&fileDownloadMutex);
    594 
    595 	if(reason != NULL) {
    596 		free(reason);
    597 		reason = NULL;
    598 	}
    599 
    600 }
    601 
    602 
    603 /******************************************************************************
    604  * Methods to Handle File upload request
    605  ******************************************************************************/
    606 
    607 #ifdef TODO
    608 void HandleFileUploadRequest(rfbClientPtr cl);
    609 #endif
    610 void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data);
    611 void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize);
    612 void SendFileUploadLengthErrMsg(rfbClientPtr cl);
    613 
    614 
    615 void
    616 HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    617 {
    618 	int n = 0;
    619 	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
    620 	rfbClientToServerTightMsg msg;
    621 
    622 	memset(path, 0, PATH_MAX);
    623 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    624 
    625 	if(cl == NULL) {
    626 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
    627 				__FILE__, __FUNCTION__);
    628 		return;
    629 	}
    630 
    631 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) {
    632 
    633 		if (n < 0)
    634 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
    635 					__FILE__, __FUNCTION__);
    636 
    637 	    rfbCloseClient(cl);
    638 	    return;
    639 	}
    640 
    641 	msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize);
    642 	msg.fupr.position = Swap16IfLE(msg.fupr.position);
    643 
    644 	if ((msg.fupr.fNameSize == 0) ||
    645 		(msg.fupr.fNameSize > (PATH_MAX - 1))) {
    646 
    647 		rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n",
    648 				__FILE__, __FUNCTION__);
    649 		HandleFileUploadLengthError(cl, msg.fupr.fNameSize);
    650 		return;
    651 	}
    652 
    653 	if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) {
    654 
    655 		if (n < 0)
    656 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n"
    657 					__FILE__, __FUNCTION__);
    658 
    659 	    rfbCloseClient(cl);
    660 	    return;
    661 	}
    662 	rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0';
    663 
    664 	if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) {
    665     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
    666     			__FILE__, __FUNCTION__);
    667 
    668     	/* This may come if the path length exceeds PATH_MAX.
    669     	   So sending path length error to client
    670     	 */
    671     	 SendFileUploadLengthErrMsg(cl);
    672     	return;
    673 	}
    674 
    675 	HandleFileUpload(cl, rtcp);
    676 }
    677 
    678 
    679 void
    680 HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize)
    681 {
    682 	char *path = NULL;
    683 	int n = 0;
    684 
    685 	if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
    686 		rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
    687 				__FILE__, __FUNCTION__);
    688 		return;
    689 	}
    690 	if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
    691 
    692 		if (n < 0)
    693 			rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
    694 							__FILE__, __FUNCTION__);
    695 
    696 	    rfbCloseClient(cl);
    697 
    698 	    if(path != NULL) {
    699 			free(path);
    700 			path = NULL;
    701 		}
    702 
    703 	    return;
    704 	}
    705 
    706 	rfbLog("File [%s]: Method [%s]: File Upload Length Error occured"
    707 			"file path requested is <%s>\n", __FILE__, __FUNCTION__, path);
    708 
    709     if(path != NULL) {
    710 		free(path);
    711 		path = NULL;
    712 	}
    713 
    714     SendFileUploadLengthErrMsg(cl);
    715 }
    716 
    717 void
    718 SendFileUploadLengthErrMsg(rfbClientPtr cl)
    719 {
    720 
    721 	FileTransferMsg fileUploadErrMsg;
    722 
    723 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
    724 	fileUploadErrMsg = GetFileUploadLengthErrResponseMsg();
    725 
    726 	if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) {
    727 		rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n",
    728 				__FILE__, __FUNCTION__);
    729 		return;
    730 	}
    731 
    732 	rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
    733 	FreeFileTransferMsg(fileUploadErrMsg);
    734 }
    735 
    736 void
    737 HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp)
    738 {
    739 	FileTransferMsg fileUploadErrMsg;
    740 
    741 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
    742 
    743 	rtcp->rcft.rcfu.uploadInProgress = FALSE;
    744 	rtcp->rcft.rcfu.uploadFD = -1;
    745 
    746 	fileUploadErrMsg = ChkFileUploadErr(cl, rtcp);
    747 	if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) {
    748 		rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
    749 		FreeFileTransferMsg(fileUploadErrMsg);
    750 	}
    751 }
    752 
    753 
    754 /******************************************************************************
    755  * Methods to Handle File Upload Data Request
    756  *****************************************************************************/
    757 
    758 void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf);
    759 
    760 
    761 void
    762 HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    763 {
    764 	int n = 0;
    765 	char* pBuf = NULL;
    766 	rfbClientToServerTightMsg msg;
    767 
    768 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    769 
    770 	if(cl == NULL) {
    771 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
    772 				__FILE__, __FUNCTION__);
    773 		return;
    774 	}
    775 
    776 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) {
    777 
    778 		if (n < 0)
    779 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
    780 					__FILE__, __FUNCTION__);
    781 
    782 	    rfbCloseClient(cl);
    783 	    return;
    784 	}
    785 
    786 	msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
    787 	msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
    788 	if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
    789 		if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned
    790 		long))) <= 0) {
    791 
    792 			if (n < 0)
    793 				rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
    794 						__FILE__, __FUNCTION__);
    795 
    796 		    rfbCloseClient(cl);
    797 		    return;
    798 		}
    799 
    800 		FileUpdateComplete(cl, rtcp);
    801 		return;
    802 	}
    803 
    804 	pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char));
    805 	if(pBuf == NULL) {
    806 		rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
    807 		return;
    808 	}
    809 	if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) {
    810 
    811 		if (n < 0)
    812 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
    813 					__FILE__, __FUNCTION__);
    814 
    815 	    rfbCloseClient(cl);
    816 
    817 	    if(pBuf != NULL) {
    818 	    	free(pBuf);
    819 	    	pBuf = NULL;
    820 		}
    821 
    822 	    return;
    823 	}
    824 	if(msg.fud.compressedLevel != 0) {
    825 		FileTransferMsg ftm;
    826 		memset(&ftm, 0, sizeof(FileTransferMsg));
    827 
    828 		ftm = GetFileUploadCompressedLevelErrMsg();
    829 
    830 		if((ftm.data != NULL) && (ftm.length != 0)) {
    831 			rfbWriteExact(cl, ftm.data, ftm.length);
    832 			FreeFileTransferMsg(ftm);
    833 		}
    834 
    835 		CloseUndoneFileTransfer(cl, rtcp);
    836 
    837 	    if(pBuf != NULL) {
    838 	    	free(pBuf);
    839 	    	pBuf = NULL;
    840 		}
    841 
    842 		return;
    843 	}
    844 
    845 	rtcp->rcft.rcfu.fSize = msg.fud.compressedSize;
    846 
    847 	HandleFileUploadWrite(cl, rtcp, pBuf);
    848 
    849     if(pBuf != NULL) {
    850     	free(pBuf);
    851     	pBuf = NULL;
    852 	}
    853 
    854 }
    855 
    856 
    857 void
    858 HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
    859 {
    860 	FileTransferMsg ftm;
    861 	memset(&ftm, 0, sizeof(FileTransferMsg));
    862 
    863 	ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf);
    864 
    865 	if((ftm.data != NULL) && (ftm.length != 0)) {
    866 		rfbWriteExact(cl, ftm.data, ftm.length);
    867 		FreeFileTransferMsg(ftm);
    868 	}
    869 }
    870 
    871 
    872 /******************************************************************************
    873  * Methods to Handle File Upload Failed Request.
    874  ******************************************************************************/
    875 
    876 
    877 void
    878 HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    879 {
    880 	int n = 0;
    881 	char* reason = NULL;
    882 	rfbClientToServerTightMsg msg;
    883 
    884 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    885 
    886 	if(cl == NULL) {
    887 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
    888 				__FILE__, __FUNCTION__);
    889 		return;
    890 	}
    891 
    892 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) {
    893 
    894 		if (n < 0)
    895 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
    896 					__FILE__, __FUNCTION__);
    897 
    898 	    rfbCloseClient(cl);
    899 	    return;
    900 	}
    901 
    902 	msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen);
    903 	if(msg.fuf.reasonLen  == 0) {
    904 		rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
    905 				__FILE__, __FUNCTION__);
    906 		return;
    907 	}
    908 
    909 
    910 	reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char));
    911 	if(reason == NULL) {
    912 		rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
    913 		return;
    914 	}
    915 
    916 	if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) {
    917 
    918 		if (n < 0)
    919 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
    920 					__FILE__, __FUNCTION__);
    921 
    922 	    rfbCloseClient(cl);
    923 
    924 		if(reason != NULL) {
    925 			free(reason);
    926 			reason = NULL;
    927 		}
    928 
    929 	    return;
    930 	}
    931 
    932 	rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:"
    933 				" reason <%s>\n", __FILE__, __FUNCTION__, reason);
    934 
    935 	CloseUndoneFileTransfer(cl, rtcp);
    936 
    937 	if(reason != NULL) {
    938 		free(reason);
    939 		reason = NULL;
    940 	}
    941 
    942 }
    943 
    944 
    945 /******************************************************************************
    946  * Methods to Handle File Create Request.
    947  ******************************************************************************/
    948 
    949 
    950 void
    951 HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
    952 {
    953 	int n = 0;
    954 	char dirName[PATH_MAX];
    955 	rfbClientToServerTightMsg msg;
    956 
    957 	memset(dirName, 0, PATH_MAX);
    958 	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
    959 
    960 	if(cl == NULL) {
    961 		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
    962 				__FILE__, __FUNCTION__);
    963 		return;
    964 	}
    965 
    966 	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) {
    967 
    968 		if (n < 0)
    969 			rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n",
    970 					__FILE__, __FUNCTION__);
    971 
    972 	    rfbCloseClient(cl);
    973 	    return;
    974 	}
    975 
    976 	msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen);
    977 
    978 	/* TODO :: chk if the dNameLen is greater than PATH_MAX */
    979 
    980 	if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) {
    981 
    982 		if (n < 0)
    983 			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
    984 					__FILE__, __FUNCTION__);
    985 
    986 	    rfbCloseClient(cl);
    987 	    return;
    988 	}
    989 
    990 	if(ConvertPath(dirName) == NULL) {
    991     	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
    992     			__FILE__, __FUNCTION__);
    993 
    994     	return;
    995 	}
    996 
    997 	CreateDirectory(dirName);
    998 }
    999