• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@novell.com
22  * Date		: 14th July 2005
23  */
24 
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <fcntl.h>
30 
31 #ifdef WIN32
32 #include <io.h>
33 #include <direct.h>
34 #include <sys/utime.h>
35 #ifdef _MSC_VER
36 #define S_ISREG(m)	(((m) & _S_IFMT) == _S_IFREG)
37 #define S_ISDIR(m)	(((m) & S_IFDIR) == S_IFDIR)
38 #define S_IWUSR		S_IWRITE
39 #define S_IRUSR		S_IREAD
40 #define S_IWOTH		0x0000002
41 #define S_IROTH		0x0000004
42 #define S_IWGRP		0x0000010
43 #define S_IRGRP		0x0000020
44 #define mkdir(path, perms) _mkdir(path) /* Match POSIX signature */
45 /* Prevent POSIX deprecation warnings on MSVC */
46 #define creat _creat
47 #define open _open
48 #define read _read
49 #define write _write
50 #define close _close
51 #define unlink _unlink
52 #endif /* _MSC_VER */
53 #else
54 #include <dirent.h>
55 #include <utime.h>
56 #endif
57 
58 #include <errno.h>
59 #include <unistd.h>
60 #include <sys/stat.h>
61 #include <sys/types.h>
62 
63 #include <rfb/rfb.h>
64 #include "rfbtightproto.h"
65 #include "filelistinfo.h"
66 #include "filetransfermsg.h"
67 #include "handlefiletransferrequest.h"
68 
69 #define SZ_RFBBLOCKSIZE 8192
70 
71 
72 void
FreeFileTransferMsg(FileTransferMsg ftm)73 FreeFileTransferMsg(FileTransferMsg ftm)
74 {
75 
76 	if(ftm.data != NULL) {
77 		free(ftm.data);
78 		ftm.data = NULL;
79 	}
80 
81 	ftm.length = 0;
82 
83 }
84 
85 
86 /******************************************************************************
87  * Methods to handle file list request.
88  ******************************************************************************/
89 
90 int CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag);
91 FileTransferMsg CreateFileListErrMsg(char flags);
92 FileTransferMsg CreateFileListMsg(FileListInfo fileListInfo, char flags);
93 
94 
95 /*
96  * This is the method called by HandleFileListRequest to get the file list
97  */
98 
99 FileTransferMsg
GetFileListResponseMsg(char * path,char flags)100 GetFileListResponseMsg(char* path, char flags)
101 {
102 	FileTransferMsg fileListMsg;
103 	FileListInfo fileListInfo;
104 	int status = -1;
105 
106 	memset(&fileListMsg, 0, sizeof(FileTransferMsg));
107 	memset(&fileListInfo, 0, sizeof(FileListInfo));
108 
109 
110 	 /* fileListInfo can have null data if the folder is Empty
111     	or if some error condition has occured.
112     	The return value is 'failure' only if some error condition has occured.
113 	 */
114 	status = CreateFileListInfo(&fileListInfo, path, !(flags  & 0x10));
115 
116 	if(status == FAILURE) {
117 		fileListMsg = CreateFileListErrMsg(flags);
118 	}
119 	else {
120 		/* DisplayFileList(fileListInfo); For Debugging  */
121 
122 		fileListMsg = CreateFileListMsg(fileListInfo, flags);
123 		FreeFileListInfo(fileListInfo);
124 	}
125 
126 	return fileListMsg;
127 }
128 
129 #if !defined(__GNUC__) && !defined(_MSC_VER)
130 #define __FUNCTION__ "unknown"
131 #endif
132 
133 #ifdef WIN32
134 
135 /* Most of the Windows version here is based on https://github.com/danielgindi/FileDir */
136 
137 #define FILETIME_TO_TIME_T(FILETIME) (((((__int64)FILETIME.dwLowDateTime) | (((__int64)FILETIME.dwHighDateTime) << 32)) - 116444736000000000L) / 10000000L)
138 
139 #ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
140 #define IS_REGULAR_FILE_HAS_ATTRIBUTE_INTEGRITY_STREAM(dwFileAttributes) (!!(dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM))
141 #else
142 #define IS_REGULAR_FILE_HAS_ATTRIBUTE_INTEGRITY_STREAM(dwFileAttributes) 0
143 #endif
144 
145 #ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
146 #define IS_REGULAR_FILE_HAS_ATTRIBUTE_NO_SCRUB_DATA(dwFileAttributes) (!!(dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA))
147 #else
148 #define IS_REGULAR_FILE_HAS_ATTRIBUTE_NO_SCRUB_DATA(dwFileAttributes) 0
149 #endif
150 
151 #define IS_REGULAR_FILE(dwFileAttributes) \
152 	( \
153 	!!(dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || \
154 	( \
155 	!(dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && \
156 	!(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && \
157 	!(dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && \
158 	!IS_REGULAR_FILE_HAS_ATTRIBUTE_INTEGRITY_STREAM(dwFileAttributes) && \
159 	!IS_REGULAR_FILE_HAS_ATTRIBUTE_NO_SCRUB_DATA(dwFileAttributes) && \
160 	!(dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && \
161 	!(dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) \
162 	) \
163 	)
164 
165 #define IS_FOLDER(dwFileAttributes) (!!(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
166 
167 int
CreateFileListInfo(FileListInfoPtr pFileListInfo,char * path,int flag)168 CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag)
169 {
170 	int pathLen, basePathLength;
171 	char *basePath, *pChar;
172 	WIN32_FIND_DATAA winFindData;
173 	HANDLE findHandle;
174 
175 	if(path == NULL) {
176 		return FAILURE;
177 	}
178 
179 	if(strlen(path) == 0) {
180 		/* In this case we will send the list of entries in ftp root*/
181 		sprintf(path, "%s%s", GetFtpRoot(), "/");
182 	}
183 
184 	/* Create a search string, like C:\folder\* */
185 
186 	pathLen = strlen(path);
187 	basePath = malloc(pathLen + 3);
188 	memcpy(basePath, path, pathLen);
189 	basePathLength = pathLen;
190 	basePath[basePathLength] = '\\';
191 	basePath[basePathLength + 1] = '*';
192 	basePath[basePathLength + 2] = '\0';
193 
194 	/* Start a search */
195 	memset(&winFindData, 0, sizeof(winFindData));
196 	findHandle = FindFirstFileA(path, &winFindData);
197 
198 	basePath[basePathLength] = '\0'; /* Restore to a basePath + \ */
199 	/* Convert \ to / */
200 	for(pChar = basePath; *pChar; pChar++) {
201 		if (*pChar == '\\') {
202 			*pChar = '/';
203 		}
204 	}
205 
206 	/* While we can find a next file do...
207 	   But ignore \. and '.. entries, which are current folder and parent folder respectively */
208 	while(findHandle != INVALID_HANDLE_VALUE && winFindData.cFileName[0] == '.' &&
209 		(winFindData.cFileName[1] == '\0' ||
210 		(winFindData.cFileName[1] == '.' && winFindData.cFileName[2] == '\0'))) {
211 		char fullpath[PATH_MAX];
212 		fullpath[0] = 0;
213 
214 		strncpy_s(fullpath, PATH_MAX, basePath, basePathLength);
215 		strncpy_s(fullpath + basePathLength, PATH_MAX - basePathLength, winFindData.cFileName, (int)strlen(winFindData.cFileName));
216 
217 		if(IS_FOLDER(winFindData.dwFileAttributes)) {
218 			if (AddFileListItemInfo(pFileListInfo, winFindData.cFileName, -1, 0) == 0) {
219 				rfbLog("File [%s]: Method [%s]: Add directory %s in the"
220 					" list failed\n", __FILE__, __FUNCTION__, fullpath);
221 				continue;
222 			}
223 		}
224 		else if(IS_REGULAR_FILE(winFindData.dwFileAttributes)) {
225 			if(flag) {
226 				unsigned int fileSize = (winFindData.nFileSizeHigh * (MAXDWORD+1)) + winFindData.nFileSizeLow;
227 				if(AddFileListItemInfo(pFileListInfo, winFindData.cFileName, fileSize, FILETIME_TO_TIME_T(winFindData.ftLastWriteTime)) == 0) {
228 					rfbLog("File [%s]: Method [%s]: Add file %s in the "
229 						"list failed\n", __FILE__, __FUNCTION__, fullpath);
230 					continue;
231 				}
232 			}
233 		}
234 
235 		if(FindNextFileA(findHandle, &winFindData) == 0) {
236 			FindClose(findHandle);
237 			findHandle = INVALID_HANDLE_VALUE;
238 		}
239 	}
240 
241 	if(findHandle != INVALID_HANDLE_VALUE) {
242 		FindClose(findHandle);
243 	}
244 
245 	free(basePath);
246 
247 	return SUCCESS;
248 }
249 
250 #else /* WIN32 */
251 
252 int
CreateFileListInfo(FileListInfoPtr pFileListInfo,char * path,int flag)253 CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag)
254 {
255 	DIR* pDir = NULL;
256 	struct dirent* pDirent = NULL;
257 
258 	if(path == NULL) {
259 		return FAILURE;
260 	}
261 
262 	if(strlen(path) == 0) {
263 		/* In this case we will send the list of entries in ftp root*/
264 		sprintf(path, "%s%s", GetFtpRoot(), "/");
265 	}
266 
267 	if((pDir = opendir(path)) == NULL) {
268 		rfbLog("File [%s]: Method [%s]: not able to open the dir\n",
269 				__FILE__, __FUNCTION__);
270 		return FAILURE;
271 	}
272 
273 	while((pDirent = readdir(pDir))) {
274 		if(strcmp(pDirent->d_name, ".") && strcmp(pDirent->d_name, "..")) {
275 			struct stat stat_buf;
276 			/*
277 			int fpLen = sizeof(char)*(strlen(pDirent->d_name)+strlen(path)+2);
278 			*/
279 			char fullpath[PATH_MAX];
280 
281 			memset(fullpath, 0, PATH_MAX);
282 
283 			strcpy(fullpath, path);
284 			if(path[strlen(path)-1] != '/')
285 				strcat(fullpath, "/");
286 			strcat(fullpath, pDirent->d_name);
287 
288 			if(stat(fullpath, &stat_buf) < 0) {
289 				rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
290 						__FILE__, __FUNCTION__, fullpath);
291 				continue;
292 			}
293 
294 			if(S_ISDIR(stat_buf.st_mode)) {
295 				if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, -1, 0) == 0) {
296 					rfbLog("File [%s]: Method [%s]: Add directory %s in the"
297 							" list failed\n", __FILE__, __FUNCTION__, fullpath);
298 					continue;
299 				}
300 			}
301 			else {
302 				if(flag) {
303 					if(AddFileListItemInfo(pFileListInfo, pDirent->d_name,
304 												stat_buf.st_size,
305 												stat_buf.st_mtime) == 0) {
306 						rfbLog("File [%s]: Method [%s]: Add file %s in the "
307 								"list failed\n", __FILE__, __FUNCTION__, fullpath);
308 						continue;
309 					}
310 				}
311 			}
312 		}
313 	}
314 	if(closedir(pDir) < 0) {
315 	    rfbLog("File [%s]: Method [%s]: ERROR Couldn't close dir\n",
316 	    	__FILE__, __FUNCTION__);
317 	}
318 
319 	return SUCCESS;
320 }
321 
322 #endif
323 
324 
325 FileTransferMsg
CreateFileListErrMsg(char flags)326 CreateFileListErrMsg(char flags)
327 {
328 	FileTransferMsg fileListMsg;
329 	rfbFileListDataMsg* pFLD = NULL;
330 	char* data = NULL;
331 	unsigned int length = 0;
332 
333 	memset(&fileListMsg, 0, sizeof(FileTransferMsg));
334 
335 	data = (char*) calloc(sizeof(rfbFileListDataMsg), sizeof(char));
336 	if(data == NULL) {
337 		return fileListMsg;
338 	}
339 	length = sizeof(rfbFileListDataMsg) * sizeof(char);
340 	pFLD = (rfbFileListDataMsg*) data;
341 
342 	pFLD->type = rfbFileListData;
343 	pFLD->numFiles = Swap16IfLE(0);
344 	pFLD->dataSize = Swap16IfLE(0);
345 	pFLD->compressedSize = Swap16IfLE(0);
346 	pFLD->flags = flags | 0x80;
347 
348 	fileListMsg.data = data;
349 	fileListMsg.length = length;
350 
351 	return fileListMsg;
352 }
353 
354 
355 FileTransferMsg
CreateFileListMsg(FileListInfo fileListInfo,char flags)356 CreateFileListMsg(FileListInfo fileListInfo, char flags)
357 {
358 	FileTransferMsg fileListMsg;
359 	rfbFileListDataMsg* pFLD = NULL;
360 	char *data = NULL, *pFileNames = NULL;
361 	unsigned int length = 0, dsSize = 0, i = 0;
362 	FileListItemSizePtr pFileListItemSize = NULL;
363 
364 	memset(&fileListMsg, 0, sizeof(FileTransferMsg));
365 	dsSize = fileListInfo.numEntries * 8;
366 	length = sz_rfbFileListDataMsg + dsSize +
367 			GetSumOfFileNamesLength(fileListInfo) +
368 			fileListInfo.numEntries;
369 
370 	data = (char*) calloc(length, sizeof(char));
371 	if(data == NULL) {
372 		return fileListMsg;
373 	}
374 	pFLD = (rfbFileListDataMsg*) data;
375 	pFileListItemSize = (FileListItemSizePtr) &data[sz_rfbFileListDataMsg];
376 	pFileNames = &data[sz_rfbFileListDataMsg + dsSize];
377 
378 	pFLD->type            = rfbFileListData;
379     pFLD->flags 		  = flags & 0xF0;
380     pFLD->numFiles 		  = Swap16IfLE(fileListInfo.numEntries);
381     pFLD->dataSize 		  = Swap16IfLE(GetSumOfFileNamesLength(fileListInfo) +
382     									fileListInfo.numEntries);
383     pFLD->compressedSize  = pFLD->dataSize;
384 
385 	for(i =0; i <fileListInfo.numEntries; i++) {
386 		pFileListItemSize[i].size = Swap32IfLE(GetFileSizeAt(fileListInfo, i));
387 		pFileListItemSize[i].data = Swap32IfLE(GetFileDataAt(fileListInfo, i));
388 		strcpy(pFileNames, GetFileNameAt(fileListInfo, i));
389 
390 		if(i+1 < fileListInfo.numEntries)
391 			pFileNames += strlen(pFileNames) + 1;
392 	}
393 
394 	fileListMsg.data 	= data;
395 	fileListMsg.length 	= length;
396 
397 	return fileListMsg;
398 }
399 
400 
401 /******************************************************************************
402  * Methods to handle File Download Request.
403  ******************************************************************************/
404 
405 FileTransferMsg CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen);
406 FileTransferMsg CreateFileDownloadZeroSizeDataMsg(unsigned long mTime);
407 FileTransferMsg CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile);
408 
409 FileTransferMsg
GetFileDownLoadErrMsg()410 GetFileDownLoadErrMsg()
411 {
412 	FileTransferMsg fileDownloadErrMsg;
413 
414 	char reason[] = "An internal error on the server caused download failure";
415 	int reasonLen = strlen(reason);
416 
417 	memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
418 
419 	fileDownloadErrMsg = CreateFileDownloadErrMsg(reason, reasonLen);
420 
421 	return fileDownloadErrMsg;
422 }
423 
424 
425 FileTransferMsg
GetFileDownloadReadDataErrMsg()426 GetFileDownloadReadDataErrMsg()
427 {
428 	char reason[] = "Cannot open file, perhaps it is absent or is a directory";
429 	int reasonLen = strlen(reason);
430 
431 	return CreateFileDownloadErrMsg(reason, reasonLen);
432 
433 }
434 
435 
436 FileTransferMsg
GetFileDownloadLengthErrResponseMsg()437 GetFileDownloadLengthErrResponseMsg()
438 {
439 	char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
440 	int reasonLen = strlen(reason);
441 
442 	return CreateFileDownloadErrMsg(reason, reasonLen);
443 }
444 
445 
446 FileTransferMsg
GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl,rfbTightClientPtr rtcp)447 GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr rtcp)
448 {
449 	/* const unsigned int sz_rfbBlockSize = SZ_RFBBLOCKSIZE; */
450     int numOfBytesRead = 0;
451 	char pBuf[SZ_RFBBLOCKSIZE];
452 	char* path = rtcp->rcft.rcfd.fName;
453 
454 	memset(pBuf, 0, SZ_RFBBLOCKSIZE);
455 
456 	if((rtcp->rcft.rcfd.downloadInProgress == FALSE) && (rtcp->rcft.rcfd.downloadFD == -1)) {
457 		if((rtcp->rcft.rcfd.downloadFD = open(path, O_RDONLY)) == -1) {
458 			rfbLog("File [%s]: Method [%s]: Error: Couldn't open file\n",
459 					__FILE__, __FUNCTION__);
460 			return GetFileDownloadReadDataErrMsg();
461 		}
462 		rtcp->rcft.rcfd.downloadInProgress = TRUE;
463 	}
464 	if((rtcp->rcft.rcfd.downloadInProgress == TRUE) && (rtcp->rcft.rcfd.downloadFD != -1)) {
465 		if( (numOfBytesRead = read(rtcp->rcft.rcfd.downloadFD, pBuf, SZ_RFBBLOCKSIZE)) <= 0) {
466 			close(rtcp->rcft.rcfd.downloadFD);
467 			rtcp->rcft.rcfd.downloadFD = -1;
468 			rtcp->rcft.rcfd.downloadInProgress = FALSE;
469 			if(numOfBytesRead == 0) {
470 				return CreateFileDownloadZeroSizeDataMsg(rtcp->rcft.rcfd.mTime);
471 			}
472 			return GetFileDownloadReadDataErrMsg();
473 		}
474 	return CreateFileDownloadBlockSizeDataMsg(numOfBytesRead, pBuf);
475 	}
476 	return GetFileDownLoadErrMsg();
477 }
478 
479 
480 FileTransferMsg
ChkFileDownloadErr(rfbClientPtr cl,rfbTightClientPtr rtcp)481 ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
482 {
483     FileTransferMsg fileDownloadMsg;
484 	struct stat stat_buf;
485 	int sz_rfbFileSize = 0;
486 	char* path = rtcp->rcft.rcfd.fName;
487 
488 	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
489 
490 	if( (path == NULL) || (strlen(path) == 0) ||
491 		(stat(path, &stat_buf) < 0) || (!(S_ISREG(stat_buf.st_mode))) ) {
492 
493 			char reason[] = "Cannot open file, perhaps it is absent or is not a regular file";
494 			int reasonLen = strlen(reason);
495 
496 			rfbLog("File [%s]: Method [%s]: Reading stat for path %s failed\n",
497 					__FILE__, __FUNCTION__, path);
498 
499 			fileDownloadMsg = CreateFileDownloadErrMsg(reason, reasonLen);
500 	}
501 	else {
502 		rtcp->rcft.rcfd.mTime = stat_buf.st_mtime;
503 		sz_rfbFileSize = stat_buf.st_size;
504 		if(sz_rfbFileSize <= 0) {
505 			fileDownloadMsg = CreateFileDownloadZeroSizeDataMsg(stat_buf.st_mtime);
506 		}
507 
508 	}
509 	return fileDownloadMsg;
510 }
511 
512 
513 FileTransferMsg
CreateFileDownloadErrMsg(char * reason,unsigned int reasonLen)514 CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen)
515 {
516 	FileTransferMsg fileDownloadErrMsg;
517 	int length = sz_rfbFileDownloadFailedMsg + reasonLen + 1;
518 	rfbFileDownloadFailedMsg *pFDF = NULL;
519 	char *pFollow = NULL;
520 
521 	char *pData = (char*) calloc(length, sizeof(char));
522 	memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
523 	if(pData == NULL) {
524 		rfbLog("File [%s]: Method [%s]: pData is NULL\n",
525 				__FILE__, __FUNCTION__);
526 		return fileDownloadErrMsg;
527 	}
528 
529 	pFDF = (rfbFileDownloadFailedMsg *) pData;
530 	pFollow = &pData[sz_rfbFileDownloadFailedMsg];
531 
532 	pFDF->type = rfbFileDownloadFailed;
533 	pFDF->reasonLen = Swap16IfLE(reasonLen);
534 	memcpy(pFollow, reason, reasonLen);
535 
536 	fileDownloadErrMsg.data	= pData;
537 	fileDownloadErrMsg.length	= length;
538 
539 	return fileDownloadErrMsg;
540 }
541 
542 
543 FileTransferMsg
CreateFileDownloadZeroSizeDataMsg(unsigned long mTime)544 CreateFileDownloadZeroSizeDataMsg(unsigned long mTime)
545 {
546 	FileTransferMsg fileDownloadZeroSizeDataMsg;
547 	int length = sz_rfbFileDownloadDataMsg + sizeof(unsigned long);
548 	rfbFileDownloadDataMsg *pFDD = NULL;
549 	char *pFollow = NULL;
550 
551 	char *pData = (char*) calloc(length, sizeof(char));
552 	memset(&fileDownloadZeroSizeDataMsg, 0, sizeof(FileTransferMsg));
553 	if(pData == NULL) {
554 		rfbLog("File [%s]: Method [%s]: pData is NULL\n",
555 				__FILE__, __FUNCTION__);
556 		return fileDownloadZeroSizeDataMsg;
557 	}
558 
559 	pFDD = (rfbFileDownloadDataMsg *) pData;
560 	pFollow = &pData[sz_rfbFileDownloadDataMsg];
561 
562 	pFDD->type = rfbFileDownloadData;
563 	pFDD->compressLevel = 0;
564 	pFDD->compressedSize = Swap16IfLE(0);
565 	pFDD->realSize = Swap16IfLE(0);
566 
567 	memcpy(pFollow, &mTime, sizeof(unsigned long));
568 
569 	fileDownloadZeroSizeDataMsg.data	= pData;
570 	fileDownloadZeroSizeDataMsg.length	= length;
571 
572 	return fileDownloadZeroSizeDataMsg;
573 
574 }
575 
576 
577 FileTransferMsg
CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile,char * pFile)578 CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile)
579 {
580 	FileTransferMsg fileDownloadBlockSizeDataMsg;
581 	int length = sz_rfbFileDownloadDataMsg + sizeFile;
582 	rfbFileDownloadDataMsg *pFDD = NULL;
583 	char *pFollow = NULL;
584 
585 	char *pData = (char*) calloc(length, sizeof(char));
586 	memset(&fileDownloadBlockSizeDataMsg, 0, sizeof(FileTransferMsg));
587 	if(NULL == pData) {
588 		rfbLog("File [%s]: Method [%s]: pData is NULL\n",
589 				__FILE__, __FUNCTION__);
590 		return fileDownloadBlockSizeDataMsg;
591 	}
592 
593 	pFDD = (rfbFileDownloadDataMsg *) pData;
594 	pFollow = &pData[sz_rfbFileDownloadDataMsg];
595 
596 	pFDD->type = rfbFileDownloadData;
597 	pFDD->compressLevel = 0;
598 	pFDD->compressedSize = Swap16IfLE(sizeFile);
599 	pFDD->realSize = Swap16IfLE(sizeFile);
600 
601 	memcpy(pFollow, pFile, sizeFile);
602 
603 	fileDownloadBlockSizeDataMsg.data	= pData;
604 	fileDownloadBlockSizeDataMsg.length	= length;
605 
606 	return fileDownloadBlockSizeDataMsg;
607 
608 }
609 
610 
611 /******************************************************************************
612  * Methods to handle file upload request
613  ******************************************************************************/
614 
615 FileTransferMsg CreateFileUploadErrMsg(char* reason, unsigned int reasonLen);
616 
617 FileTransferMsg
GetFileUploadLengthErrResponseMsg()618 GetFileUploadLengthErrResponseMsg()
619 {
620 	char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
621 	int reasonLen = strlen(reason);
622 
623 	return CreateFileUploadErrMsg(reason, reasonLen);
624 }
625 
626 
627 FileTransferMsg
ChkFileUploadErr(rfbClientPtr cl,rfbTightClientPtr rtcp)628 ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
629 {
630     FileTransferMsg fileUploadErrMsg;
631 
632 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
633 	if( (rtcp->rcft.rcfu.fName == NULL) ||
634 		(strlen(rtcp->rcft.rcfu.fName) == 0) ||
635 		((rtcp->rcft.rcfu.uploadFD = creat(rtcp->rcft.rcfu.fName,
636 		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)) {
637 
638 			char reason[] = "Could not create file";
639 			int reasonLen = strlen(reason);
640 			fileUploadErrMsg = CreateFileUploadErrMsg(reason, reasonLen);
641 	}
642 	else
643 		rtcp->rcft.rcfu.uploadInProgress = TRUE;
644 
645 	return fileUploadErrMsg;
646 }
647 
648 
649 FileTransferMsg
GetFileUploadCompressedLevelErrMsg()650 GetFileUploadCompressedLevelErrMsg()
651 {
652 	char reason[] = "Server does not support data compression on upload";
653 	int reasonLen = strlen(reason);
654 
655 	return CreateFileUploadErrMsg(reason, reasonLen);
656 }
657 
658 
659 FileTransferMsg
ChkFileUploadWriteErr(rfbClientPtr cl,rfbTightClientPtr rtcp,char * pBuf)660 ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
661 {
662 	FileTransferMsg ftm;
663 	unsigned long numOfBytesWritten = 0;
664 
665 	memset(&ftm, 0, sizeof(FileTransferMsg));
666 
667 	numOfBytesWritten = write(rtcp->rcft.rcfu.uploadFD, pBuf, rtcp->rcft.rcfu.fSize);
668 
669 	if(numOfBytesWritten != rtcp->rcft.rcfu.fSize) {
670 		char reason[] = "Error writing file data";
671 		int reasonLen = strlen(reason);
672 		ftm = CreateFileUploadErrMsg(reason, reasonLen);
673 		CloseUndoneFileTransfer(cl, rtcp);
674 	}
675 	return ftm;
676 }
677 
678 
679 void
FileUpdateComplete(rfbClientPtr cl,rfbTightClientPtr rtcp)680 FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr rtcp)
681 {
682 	/* Here we are settimg the modification and access time of the file */
683 	/* Windows code stes mod/access/creation time of the file */
684 	struct utimbuf utb;
685 
686 	utb.actime = utb.modtime = rtcp->rcft.rcfu.mTime;
687 	if(utime(rtcp->rcft.rcfu.fName, &utb) == -1) {
688 		rfbLog("File [%s]: Method [%s]: Setting the modification/access"
689 				" time for the file <%s> failed\n", __FILE__,
690 				__FUNCTION__, rtcp->rcft.rcfu.fName);
691 	}
692 
693 	if(rtcp->rcft.rcfu.uploadFD != -1) {
694 		close(rtcp->rcft.rcfu.uploadFD);
695 		rtcp->rcft.rcfu.uploadFD = -1;
696 		rtcp->rcft.rcfu.uploadInProgress = FALSE;
697 	}
698 }
699 
700 
701 FileTransferMsg
CreateFileUploadErrMsg(char * reason,unsigned int reasonLen)702 CreateFileUploadErrMsg(char* reason, unsigned int reasonLen)
703 {
704 	FileTransferMsg fileUploadErrMsg;
705 	int length = sz_rfbFileUploadCancelMsg + reasonLen;
706 	rfbFileUploadCancelMsg *pFDF = NULL;
707 	char *pFollow = NULL;
708 
709 	char *pData = (char*) calloc(length, sizeof(char));
710 	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
711 	if(pData == NULL) {
712 		rfbLog("File [%s]: Method [%s]: pData is NULL\n",
713 				__FILE__, __FUNCTION__);
714 		return fileUploadErrMsg;
715 	}
716 
717 	pFDF = (rfbFileUploadCancelMsg *) pData;
718 	pFollow = &pData[sz_rfbFileUploadCancelMsg];
719 
720 	pFDF->type = rfbFileUploadCancel;
721 	pFDF->reasonLen = Swap16IfLE(reasonLen);
722 	memcpy(pFollow, reason, reasonLen);
723 
724 	fileUploadErrMsg.data		= pData;
725 	fileUploadErrMsg.length		= length;
726 
727 	return fileUploadErrMsg;
728 }
729 
730 
731 /******************************************************************************
732  * Method to cancel File Transfer operation.
733  ******************************************************************************/
734 
735 void
CloseUndoneFileTransfer(rfbClientPtr cl,rfbTightClientPtr rtcp)736 CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp)
737 {
738 	/* TODO :: File Upload case is not handled currently */
739 	/* TODO :: In case of concurrency we need to use Critical Section */
740 
741 	if(cl == NULL)
742 		return;
743 
744 
745 	if(rtcp->rcft.rcfu.uploadInProgress == TRUE) {
746 		rtcp->rcft.rcfu.uploadInProgress = FALSE;
747 
748 		if(rtcp->rcft.rcfu.uploadFD != -1) {
749 			close(rtcp->rcft.rcfu.uploadFD);
750 			rtcp->rcft.rcfu.uploadFD = -1;
751 		}
752 
753 		if(unlink(rtcp->rcft.rcfu.fName) == -1) {
754 			rfbLog("File [%s]: Method [%s]: Delete operation on file <%s> failed\n",
755 					__FILE__, __FUNCTION__, rtcp->rcft.rcfu.fName);
756 		}
757 
758 		memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX);
759 	}
760 
761 	if(rtcp->rcft.rcfd.downloadInProgress == TRUE) {
762 		rtcp->rcft.rcfd.downloadInProgress = FALSE;
763 
764 		if(rtcp->rcft.rcfd.downloadFD != -1) {
765 			close(rtcp->rcft.rcfd.downloadFD);
766 			rtcp->rcft.rcfd.downloadFD = -1;
767 		}
768 		memset(rtcp->rcft.rcfd.fName, 0 , PATH_MAX);
769 	}
770 }
771 
772 
773 /******************************************************************************
774  * Method to handle create directory request.
775  ******************************************************************************/
776 
777 #ifdef _MSC_VER
778 #undef CreateDirectory /* Prevent macro clashes under Windows */
779 #endif /* _MSC_VER */
780 
781 void
CreateDirectory(char * dirName)782 CreateDirectory(char* dirName)
783 {
784 	if(dirName == NULL) return;
785 
786 	if(mkdir(dirName, 0700) == -1) {
787 		rfbLog("File [%s]: Method [%s]: Create operation for directory <%s> failed\n",
788 				__FILE__, __FUNCTION__, dirName);
789 	}
790 }
791