00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <fcntl.h>
00030 #include <dirent.h>
00031 #include <utime.h>
00032 #include <errno.h>
00033 #include <unistd.h>
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036
00037 #include <rfb/rfb.h>
00038 #include "rfbtightproto.h"
00039 #include "filelistinfo.h"
00040 #include "filetransfermsg.h"
00041 #include "handlefiletransferrequest.h"
00042
00043 #define SZ_RFBBLOCKSIZE 8192
00044
00045
00046 void
00047 FreeFileTransferMsg(FileTransferMsg ftm)
00048 {
00049
00050 if(ftm.data != NULL) {
00051 free(ftm.data);
00052 ftm.data = NULL;
00053 }
00054
00055 ftm.length = 0;
00056
00057 }
00058
00059
00060
00061
00062
00063
00064 int CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag);
00065 FileTransferMsg CreateFileListErrMsg(char flags);
00066 FileTransferMsg CreateFileListMsg(FileListInfo fileListInfo, char flags);
00067
00068
00069
00070
00071
00072
00073 FileTransferMsg
00074 GetFileListResponseMsg(char* path, char flags)
00075 {
00076 FileTransferMsg fileListMsg;
00077 FileListInfo fileListInfo;
00078 int status = -1;
00079
00080 memset(&fileListMsg, 0, sizeof(FileTransferMsg));
00081 memset(&fileListInfo, 0, sizeof(FileListInfo));
00082
00083
00084
00085
00086
00087
00088 status = CreateFileListInfo(&fileListInfo, path, !(flags & 0x10));
00089
00090 if(status == FAILURE) {
00091 fileListMsg = CreateFileListErrMsg(flags);
00092 }
00093 else {
00094
00095
00096 fileListMsg = CreateFileListMsg(fileListInfo, flags);
00097 FreeFileListInfo(fileListInfo);
00098 }
00099
00100 return fileListMsg;
00101 }
00102
00103 #ifndef __GNUC__
00104 #define __FUNCTION__ "unknown"
00105 #endif
00106
00107 int
00108 CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag)
00109 {
00110 DIR* pDir = NULL;
00111 struct dirent* pDirent = NULL;
00112
00113 if((path == NULL) || (strlen(path) == 0)) {
00114
00115 sprintf(path, "%s%s", GetFtpRoot(), "/");
00116 }
00117
00118 if((pDir = opendir(path)) == NULL) {
00119 rfbLog("File [%s]: Method [%s]: not able to open the dir\n",
00120 __FILE__, __FUNCTION__);
00121 return FAILURE;
00122 }
00123
00124 while((pDirent = readdir(pDir))) {
00125 if(strcmp(pDirent->d_name, ".") && strcmp(pDirent->d_name, "..")) {
00126 struct stat stat_buf;
00127
00128
00129
00130 char fullpath[PATH_MAX];
00131
00132 memset(fullpath, 0, PATH_MAX);
00133
00134 strcpy(fullpath, path);
00135 if(path[strlen(path)-1] != '/')
00136 strcat(fullpath, "/");
00137 strcat(fullpath, pDirent->d_name);
00138
00139 if(stat(fullpath, &stat_buf) < 0) {
00140 rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
00141 __FILE__, __FUNCTION__, fullpath);
00142 continue;
00143 }
00144
00145 if(S_ISDIR(stat_buf.st_mode)) {
00146 if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, -1, 0) == 0) {
00147 rfbLog("File [%s]: Method [%s]: Add directory %s in the"
00148 " list failed\n", __FILE__, __FUNCTION__, fullpath);
00149 continue;
00150 }
00151 }
00152 else {
00153 if(flag) {
00154 if(AddFileListItemInfo(pFileListInfo, pDirent->d_name,
00155 stat_buf.st_size,
00156 stat_buf.st_mtime) == 0) {
00157 rfbLog("File [%s]: Method [%s]: Add file %s in the "
00158 "list failed\n", __FILE__, __FUNCTION__, fullpath);
00159 continue;
00160 }
00161 }
00162 }
00163 }
00164 }
00165 if(closedir(pDir) < 0) {
00166 rfbLog("File [%s]: Method [%s]: ERROR Couldn't close dir\n",
00167 __FILE__, __FUNCTION__);
00168 }
00169
00170 return SUCCESS;
00171 }
00172
00173
00174 FileTransferMsg
00175 CreateFileListErrMsg(char flags)
00176 {
00177 FileTransferMsg fileListMsg;
00178 rfbFileListDataMsg* pFLD = NULL;
00179 char* data = NULL;
00180 unsigned int length = 0;
00181
00182 memset(&fileListMsg, 0, sizeof(FileTransferMsg));
00183
00184 data = (char*) calloc(sizeof(rfbFileListDataMsg), sizeof(char));
00185 if(data == NULL) {
00186 return fileListMsg;
00187 }
00188 length = sizeof(rfbFileListDataMsg) * sizeof(char);
00189 pFLD = (rfbFileListDataMsg*) data;
00190
00191 pFLD->type = rfbFileListData;
00192 pFLD->numFiles = Swap16IfLE(0);
00193 pFLD->dataSize = Swap16IfLE(0);
00194 pFLD->compressedSize = Swap16IfLE(0);
00195 pFLD->flags = flags | 0x80;
00196
00197 fileListMsg.data = data;
00198 fileListMsg.length = length;
00199
00200 return fileListMsg;
00201 }
00202
00203
00204 FileTransferMsg
00205 CreateFileListMsg(FileListInfo fileListInfo, char flags)
00206 {
00207 FileTransferMsg fileListMsg;
00208 rfbFileListDataMsg* pFLD = NULL;
00209 char *data = NULL, *pFileNames = NULL;
00210 unsigned int length = 0, dsSize = 0, i = 0;
00211 FileListItemSizePtr pFileListItemSize = NULL;
00212
00213 memset(&fileListMsg, 0, sizeof(FileTransferMsg));
00214 dsSize = fileListInfo.numEntries * 8;
00215 length = sz_rfbFileListDataMsg + dsSize +
00216 GetSumOfFileNamesLength(fileListInfo) +
00217 fileListInfo.numEntries;
00218
00219 data = (char*) calloc(length, sizeof(char));
00220 if(data == NULL) {
00221 return fileListMsg;
00222 }
00223 pFLD = (rfbFileListDataMsg*) data;
00224 pFileListItemSize = (FileListItemSizePtr) &data[sz_rfbFileListDataMsg];
00225 pFileNames = &data[sz_rfbFileListDataMsg + dsSize];
00226
00227 pFLD->type = rfbFileListData;
00228 pFLD->flags = flags & 0xF0;
00229 pFLD->numFiles = Swap16IfLE(fileListInfo.numEntries);
00230 pFLD->dataSize = Swap16IfLE(GetSumOfFileNamesLength(fileListInfo) +
00231 fileListInfo.numEntries);
00232 pFLD->compressedSize = pFLD->dataSize;
00233
00234 for(i =0; i <fileListInfo.numEntries; i++) {
00235 pFileListItemSize[i].size = Swap32IfLE(GetFileSizeAt(fileListInfo, i));
00236 pFileListItemSize[i].data = Swap32IfLE(GetFileDataAt(fileListInfo, i));
00237 strcpy(pFileNames, GetFileNameAt(fileListInfo, i));
00238
00239 if(i+1 < fileListInfo.numEntries)
00240 pFileNames += strlen(pFileNames) + 1;
00241 }
00242
00243 fileListMsg.data = data;
00244 fileListMsg.length = length;
00245
00246 return fileListMsg;
00247 }
00248
00249
00250
00251
00252
00253
00254 FileTransferMsg CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen);
00255 FileTransferMsg CreateFileDownloadZeroSizeDataMsg(unsigned long mTime);
00256 FileTransferMsg CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile);
00257
00258 FileTransferMsg
00259 GetFileDownLoadErrMsg()
00260 {
00261 FileTransferMsg fileDownloadErrMsg;
00262
00263 char reason[] = "An internal error on the server caused download failure";
00264 int reasonLen = strlen(reason);
00265
00266 memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
00267
00268 fileDownloadErrMsg = CreateFileDownloadErrMsg(reason, reasonLen);
00269
00270 return fileDownloadErrMsg;
00271 }
00272
00273
00274 FileTransferMsg
00275 GetFileDownloadReadDataErrMsg()
00276 {
00277 char reason[] = "Cannot open file, perhaps it is absent or is a directory";
00278 int reasonLen = strlen(reason);
00279
00280 return CreateFileDownloadErrMsg(reason, reasonLen);
00281
00282 }
00283
00284
00285 FileTransferMsg
00286 GetFileDownloadLengthErrResponseMsg()
00287 {
00288 char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
00289 int reasonLen = strlen(reason);
00290
00291 return CreateFileDownloadErrMsg(reason, reasonLen);
00292 }
00293
00294
00295 FileTransferMsg
00296 GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr rtcp)
00297 {
00298
00299 int numOfBytesRead = 0;
00300 char pBuf[SZ_RFBBLOCKSIZE];
00301 char* path = rtcp->rcft.rcfd.fName;
00302
00303 memset(pBuf, 0, SZ_RFBBLOCKSIZE);
00304
00305 if((rtcp->rcft.rcfd.downloadInProgress == FALSE) && (rtcp->rcft.rcfd.downloadFD == -1)) {
00306 if((rtcp->rcft.rcfd.downloadFD = open(path, O_RDONLY)) == -1) {
00307 rfbLog("File [%s]: Method [%s]: Error: Couldn't open file\n",
00308 __FILE__, __FUNCTION__);
00309 return GetFileDownloadReadDataErrMsg();
00310 }
00311 rtcp->rcft.rcfd.downloadInProgress = TRUE;
00312 }
00313 if((rtcp->rcft.rcfd.downloadInProgress == TRUE) && (rtcp->rcft.rcfd.downloadFD != -1)) {
00314 if( (numOfBytesRead = read(rtcp->rcft.rcfd.downloadFD, pBuf, SZ_RFBBLOCKSIZE)) <= 0) {
00315 close(rtcp->rcft.rcfd.downloadFD);
00316 rtcp->rcft.rcfd.downloadFD = -1;
00317 rtcp->rcft.rcfd.downloadInProgress = FALSE;
00318 if(numOfBytesRead == 0) {
00319 return CreateFileDownloadZeroSizeDataMsg(rtcp->rcft.rcfd.mTime);
00320 }
00321 return GetFileDownloadReadDataErrMsg();
00322 }
00323 return CreateFileDownloadBlockSizeDataMsg(numOfBytesRead, pBuf);
00324 }
00325 return GetFileDownLoadErrMsg();
00326 }
00327
00328
00329 FileTransferMsg
00330 ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
00331 {
00332 FileTransferMsg fileDownloadMsg;
00333 struct stat stat_buf;
00334 int sz_rfbFileSize = 0;
00335 char* path = rtcp->rcft.rcfd.fName;
00336
00337 memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
00338
00339 if( (path == NULL) || (strlen(path) == 0) ||
00340 (stat(path, &stat_buf) < 0) || (!(S_ISREG(stat_buf.st_mode))) ) {
00341
00342 char reason[] = "Cannot open file, perhaps it is absent or is not a regular file";
00343 int reasonLen = strlen(reason);
00344
00345 rfbLog("File [%s]: Method [%s]: Reading stat for path %s failed\n",
00346 __FILE__, __FUNCTION__, path);
00347
00348 fileDownloadMsg = CreateFileDownloadErrMsg(reason, reasonLen);
00349 }
00350 else {
00351 rtcp->rcft.rcfd.mTime = stat_buf.st_mtime;
00352 sz_rfbFileSize = stat_buf.st_size;
00353 if(sz_rfbFileSize <= 0) {
00354 fileDownloadMsg = CreateFileDownloadZeroSizeDataMsg(stat_buf.st_mtime);
00355 }
00356
00357 }
00358 return fileDownloadMsg;
00359 }
00360
00361
00362 FileTransferMsg
00363 CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen)
00364 {
00365 FileTransferMsg fileDownloadErrMsg;
00366 int length = sz_rfbFileDownloadFailedMsg + reasonLen + 1;
00367 rfbFileDownloadFailedMsg *pFDF = NULL;
00368 char *pFollow = NULL;
00369
00370 char *pData = (char*) calloc(length, sizeof(char));
00371 memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
00372 if(pData == NULL) {
00373 rfbLog("File [%s]: Method [%s]: pData is NULL\n",
00374 __FILE__, __FUNCTION__);
00375 return fileDownloadErrMsg;
00376 }
00377
00378 pFDF = (rfbFileDownloadFailedMsg *) pData;
00379 pFollow = &pData[sz_rfbFileDownloadFailedMsg];
00380
00381 pFDF->type = rfbFileDownloadFailed;
00382 pFDF->reasonLen = Swap16IfLE(reasonLen);
00383 memcpy(pFollow, reason, reasonLen);
00384
00385 fileDownloadErrMsg.data = pData;
00386 fileDownloadErrMsg.length = length;
00387
00388 return fileDownloadErrMsg;
00389 }
00390
00391
00392 FileTransferMsg
00393 CreateFileDownloadZeroSizeDataMsg(unsigned long mTime)
00394 {
00395 FileTransferMsg fileDownloadZeroSizeDataMsg;
00396 int length = sz_rfbFileDownloadDataMsg + sizeof(unsigned long);
00397 rfbFileDownloadDataMsg *pFDD = NULL;
00398 char *pFollow = NULL;
00399
00400 char *pData = (char*) calloc(length, sizeof(char));
00401 memset(&fileDownloadZeroSizeDataMsg, 0, sizeof(FileTransferMsg));
00402 if(pData == NULL) {
00403 rfbLog("File [%s]: Method [%s]: pData is NULL\n",
00404 __FILE__, __FUNCTION__);
00405 return fileDownloadZeroSizeDataMsg;
00406 }
00407
00408 pFDD = (rfbFileDownloadDataMsg *) pData;
00409 pFollow = &pData[sz_rfbFileDownloadDataMsg];
00410
00411 pFDD->type = rfbFileDownloadData;
00412 pFDD->compressLevel = 0;
00413 pFDD->compressedSize = Swap16IfLE(0);
00414 pFDD->realSize = Swap16IfLE(0);
00415
00416 memcpy(pFollow, &mTime, sizeof(unsigned long));
00417
00418 fileDownloadZeroSizeDataMsg.data = pData;
00419 fileDownloadZeroSizeDataMsg.length = length;
00420
00421 return fileDownloadZeroSizeDataMsg;
00422
00423 }
00424
00425
00426 FileTransferMsg
00427 CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile)
00428 {
00429 FileTransferMsg fileDownloadBlockSizeDataMsg;
00430 int length = sz_rfbFileDownloadDataMsg + sizeFile;
00431 rfbFileDownloadDataMsg *pFDD = NULL;
00432 char *pFollow = NULL;
00433
00434 char *pData = (char*) calloc(length, sizeof(char));
00435 memset(&fileDownloadBlockSizeDataMsg, 0, sizeof(FileTransferMsg));
00436 if(NULL == pData) {
00437 rfbLog("File [%s]: Method [%s]: pData is NULL\n",
00438 __FILE__, __FUNCTION__);
00439 return fileDownloadBlockSizeDataMsg;
00440 }
00441
00442 pFDD = (rfbFileDownloadDataMsg *) pData;
00443 pFollow = &pData[sz_rfbFileDownloadDataMsg];
00444
00445 pFDD->type = rfbFileDownloadData;
00446 pFDD->compressLevel = 0;
00447 pFDD->compressedSize = Swap16IfLE(sizeFile);
00448 pFDD->realSize = Swap16IfLE(sizeFile);
00449
00450 memcpy(pFollow, pFile, sizeFile);
00451
00452 fileDownloadBlockSizeDataMsg.data = pData;
00453 fileDownloadBlockSizeDataMsg.length = length;
00454
00455 return fileDownloadBlockSizeDataMsg;
00456
00457 }
00458
00459
00460
00461
00462
00463
00464 FileTransferMsg CreateFileUploadErrMsg(char* reason, unsigned int reasonLen);
00465
00466 FileTransferMsg
00467 GetFileUploadLengthErrResponseMsg()
00468 {
00469 char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
00470 int reasonLen = strlen(reason);
00471
00472 return CreateFileUploadErrMsg(reason, reasonLen);
00473 }
00474
00475
00476 FileTransferMsg
00477 ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
00478 {
00479 FileTransferMsg fileUploadErrMsg;
00480
00481 memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
00482 if( (rtcp->rcft.rcfu.fName == NULL) ||
00483 (strlen(rtcp->rcft.rcfu.fName) == 0) ||
00484 ((rtcp->rcft.rcfu.uploadFD = creat(rtcp->rcft.rcfu.fName,
00485 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)) {
00486
00487 char reason[] = "Could not create file";
00488 int reasonLen = strlen(reason);
00489 fileUploadErrMsg = CreateFileUploadErrMsg(reason, reasonLen);
00490 }
00491 else
00492 rtcp->rcft.rcfu.uploadInProgress = TRUE;
00493
00494 return fileUploadErrMsg;
00495 }
00496
00497
00498 FileTransferMsg
00499 GetFileUploadCompressedLevelErrMsg()
00500 {
00501 char reason[] = "Server does not support data compression on upload";
00502 int reasonLen = strlen(reason);
00503
00504 return CreateFileUploadErrMsg(reason, reasonLen);
00505 }
00506
00507
00508 FileTransferMsg
00509 ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
00510 {
00511 FileTransferMsg ftm;
00512 unsigned long numOfBytesWritten = 0;
00513
00514 memset(&ftm, 0, sizeof(FileTransferMsg));
00515
00516 numOfBytesWritten = write(rtcp->rcft.rcfu.uploadFD, pBuf, rtcp->rcft.rcfu.fSize);
00517
00518 if(numOfBytesWritten != rtcp->rcft.rcfu.fSize) {
00519 char reason[] = "Error writing file data";
00520 int reasonLen = strlen(reason);
00521 ftm = CreateFileUploadErrMsg(reason, reasonLen);
00522 CloseUndoneFileTransfer(cl, rtcp);
00523 }
00524 return ftm;
00525 }
00526
00527
00528 void
00529 FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr rtcp)
00530 {
00531
00532
00533 struct utimbuf utb;
00534
00535 utb.actime = utb.modtime = rtcp->rcft.rcfu.mTime;
00536 if(utime(rtcp->rcft.rcfu.fName, &utb) == -1) {
00537 rfbLog("File [%s]: Method [%s]: Setting the modification/access"
00538 " time for the file <%s> failed\n", __FILE__,
00539 __FUNCTION__, rtcp->rcft.rcfu.fName);
00540 }
00541
00542 if(rtcp->rcft.rcfu.uploadFD != -1) {
00543 close(rtcp->rcft.rcfu.uploadFD);
00544 rtcp->rcft.rcfu.uploadFD = -1;
00545 rtcp->rcft.rcfu.uploadInProgress = FALSE;
00546 }
00547 }
00548
00549
00550 FileTransferMsg
00551 CreateFileUploadErrMsg(char* reason, unsigned int reasonLen)
00552 {
00553 FileTransferMsg fileUploadErrMsg;
00554 int length = sz_rfbFileUploadCancelMsg + reasonLen;
00555 rfbFileUploadCancelMsg *pFDF = NULL;
00556 char *pFollow = NULL;
00557
00558 char *pData = (char*) calloc(length, sizeof(char));
00559 memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
00560 if(pData == NULL) {
00561 rfbLog("File [%s]: Method [%s]: pData is NULL\n",
00562 __FILE__, __FUNCTION__);
00563 return fileUploadErrMsg;
00564 }
00565
00566 pFDF = (rfbFileUploadCancelMsg *) pData;
00567 pFollow = &pData[sz_rfbFileUploadCancelMsg];
00568
00569 pFDF->type = rfbFileUploadCancel;
00570 pFDF->reasonLen = Swap16IfLE(reasonLen);
00571 memcpy(pFollow, reason, reasonLen);
00572
00573 fileUploadErrMsg.data = pData;
00574 fileUploadErrMsg.length = length;
00575
00576 return fileUploadErrMsg;
00577 }
00578
00579
00580
00581
00582
00583
00584 void
00585 CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp)
00586 {
00587
00588
00589
00590 if(cl == NULL)
00591 return;
00592
00593
00594 if(rtcp->rcft.rcfu.uploadInProgress == TRUE) {
00595 rtcp->rcft.rcfu.uploadInProgress = FALSE;
00596
00597 if(rtcp->rcft.rcfu.uploadFD != -1) {
00598 close(rtcp->rcft.rcfu.uploadFD);
00599 rtcp->rcft.rcfu.uploadFD = -1;
00600 }
00601
00602 if(unlink(rtcp->rcft.rcfu.fName) == -1) {
00603 rfbLog("File [%s]: Method [%s]: Delete operation on file <%s> failed\n",
00604 __FILE__, __FUNCTION__, rtcp->rcft.rcfu.fName);
00605 }
00606
00607 memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX);
00608 }
00609
00610 if(rtcp->rcft.rcfd.downloadInProgress == TRUE) {
00611 rtcp->rcft.rcfd.downloadInProgress = FALSE;
00612
00613 if(rtcp->rcft.rcfd.downloadFD != -1) {
00614 close(rtcp->rcft.rcfd.downloadFD);
00615 rtcp->rcft.rcfd.downloadFD = -1;
00616 }
00617 memset(rtcp->rcft.rcfd.fName, 0 , PATH_MAX);
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626 void
00627 CreateDirectory(char* dirName)
00628 {
00629 if(dirName == NULL) return;
00630
00631 if(mkdir(dirName, 0700) == -1) {
00632 rfbLog("File [%s]: Method [%s]: Create operation for directory <%s> failed\n",
00633 __FILE__, __FUNCTION__, dirName);
00634 }
00635 }
00636