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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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