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