Thank you very much, Rohit!pull/1/head
parent
93be927b1c
commit
0a909fde7a
@ -0,0 +1,11 @@
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4);
|
||||
server->frameBuffer=(char*)malloc(400*300*4);
|
||||
rfbRegisterTightVNCFileTransferExtension();
|
||||
rfbInitServer(server);
|
||||
rfbRunEventLoop(server,-1,FALSE);
|
||||
return(0);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
client_test
|
||||
libvncclient.a
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
libvncserver.a
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
@ -0,0 +1,15 @@
|
||||
DEFINES=-g -Wall
|
||||
|
||||
includedir=$(prefix)/include/rfb
|
||||
|
||||
noinst_HEADERS=filelistinfo.h filetransfermsg.h \
|
||||
handlefiletransferrequest.h rfbtightproto.h
|
||||
|
||||
LIB_SRCS = rfbtightserver.c handlefiletransferrequest.c filetransfermsg.c \
|
||||
filelistinfo.c
|
||||
|
||||
tightvnc_filetransfer_a_SOURCES=$(LIB_SRCS)
|
||||
|
||||
lib_LIBRARIES=tightvnc-filetransfer.a
|
||||
|
||||
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Novell, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com
|
||||
*
|
||||
* Author : Rohit Kumar
|
||||
* Email ID : rokumar@novell.com
|
||||
* Date : 14th July 2005
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "rfb/rfb.h"
|
||||
#include "filelistinfo.h"
|
||||
|
||||
|
||||
/* This method is used for debugging purpose */
|
||||
void
|
||||
DisplayFileList(FileListInfo fli)
|
||||
{
|
||||
int i = 0;
|
||||
if((fli.pEntries == NULL) || (fli.numEntries == 0)) return;
|
||||
|
||||
rfbLog("DISPLAYING FILE NAMES IN THE LIST ...START\n\n");
|
||||
rfbLog("Numer of entries:: %d\n", fli.numEntries);
|
||||
for(i = 0; i < fli.numEntries; i++)
|
||||
rfbLog("file[%d]\t<%s>\n", i, fli.pEntries[i].name);
|
||||
rfbLog("DISPLAYING FILE NAMES IN THE LIST ...END\n\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name,
|
||||
unsigned int size, unsigned int data)
|
||||
{
|
||||
FileListItemInfoPtr fileListItemInfoPtr = (FileListItemInfoPtr)
|
||||
calloc((fileListInfoPtr->numEntries + 1),
|
||||
sizeof(FileListItemInfo));
|
||||
if(fileListItemInfoPtr == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: fileListItemInfoPtr is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if(fileListInfoPtr->numEntries != 0) {
|
||||
memcpy(fileListItemInfoPtr, fileListInfoPtr->pEntries,
|
||||
fileListInfoPtr->numEntries * sizeof(FileListItemInfo));
|
||||
}
|
||||
|
||||
strcpy(fileListItemInfoPtr[fileListInfoPtr->numEntries].name, name);
|
||||
fileListItemInfoPtr[fileListInfoPtr->numEntries].size = size;
|
||||
fileListItemInfoPtr[fileListInfoPtr->numEntries].data = data;
|
||||
|
||||
if(fileListInfoPtr->pEntries != NULL) {
|
||||
free(fileListInfoPtr->pEntries);
|
||||
fileListInfoPtr->pEntries = NULL;
|
||||
}
|
||||
|
||||
fileListInfoPtr->pEntries = fileListItemInfoPtr;
|
||||
fileListItemInfoPtr = NULL;
|
||||
fileListInfoPtr->numEntries++;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
GetFileNameAt(FileListInfo fileListInfo, int number)
|
||||
{
|
||||
char* name = NULL;
|
||||
if(number >= 0 && number < fileListInfo.numEntries)
|
||||
name = fileListInfo.pEntries[number].name;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
GetFileSizeAt(FileListInfo fileListInfo, int number)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
if(number >= 0 && number < fileListInfo.numEntries)
|
||||
size = fileListInfo.pEntries[number].size;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
GetFileDataAt(FileListInfo fileListInfo, int number)
|
||||
{
|
||||
unsigned int data = 0;
|
||||
if(number >= 0 && number < fileListInfo.numEntries)
|
||||
data = fileListInfo.pEntries[number].data;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
GetSumOfFileNamesLength(FileListInfo fileListInfo)
|
||||
{
|
||||
int i = 0, sumLen = 0;
|
||||
for(i = 0; i < fileListInfo.numEntries; i++)
|
||||
sumLen += strlen(fileListInfo.pEntries[i].name);
|
||||
return sumLen;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FreeFileListInfo(FileListInfo fileListInfo)
|
||||
{
|
||||
if(fileListInfo.pEntries != NULL) {
|
||||
free(fileListInfo.pEntries);
|
||||
fileListInfo.pEntries = NULL;
|
||||
}
|
||||
fileListInfo.numEntries = 0;
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Novell, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com
|
||||
*
|
||||
* Author : Rohit Kumar
|
||||
* Email ID : rokumar@novell.com
|
||||
* Date : 14th July 2005
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILE_LIST_INFO_H
|
||||
#define FILE_LIST_INFO_H
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#define SUCCESS 1
|
||||
#define FAILURE 0
|
||||
|
||||
typedef struct _FileListItemInfo {
|
||||
char name[NAME_MAX];
|
||||
unsigned int size;
|
||||
unsigned int data;
|
||||
} FileListItemInfo, *FileListItemInfoPtr;
|
||||
|
||||
typedef struct _FileListItemSize {
|
||||
unsigned int size;
|
||||
unsigned int data;
|
||||
} FileListItemSize, *FileListItemSizePtr;
|
||||
|
||||
typedef struct _FileListInfo {
|
||||
FileListItemInfoPtr pEntries;
|
||||
int numEntries;
|
||||
} FileListInfo, *FileListInfoPtr;
|
||||
|
||||
int AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name, unsigned int size, unsigned int data);
|
||||
char* GetFileNameAt(FileListInfo fileListInfo, int number);
|
||||
unsigned int GetFileSizeAt(FileListInfo fileListInfo, int number);
|
||||
unsigned int GetFileDataAt(FileListInfo fileListInfo, int number);
|
||||
unsigned int GetSumOfFileNamesLength(FileListInfo fileListInfo);
|
||||
void FreeFileListInfo(FileListInfo fileListInfo);
|
||||
|
||||
void DisplayFileList(FileListInfo fli);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,632 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Novell, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com
|
||||
*
|
||||
* Author : Rohit Kumar
|
||||
* Email ID : rokumar@novell.com
|
||||
* Date : 14th July 2005
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <utime.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include "rfbtightproto.h"
|
||||
#include "filelistinfo.h"
|
||||
#include "filetransfermsg.h"
|
||||
#include "handlefiletransferrequest.h"
|
||||
|
||||
#define SZ_RFBBLOCKSIZE 8192
|
||||
|
||||
|
||||
void
|
||||
FreeFileTransferMsg(FileTransferMsg ftm)
|
||||
{
|
||||
|
||||
if(ftm.data != NULL) {
|
||||
free(ftm.data);
|
||||
ftm.data = NULL;
|
||||
}
|
||||
|
||||
ftm.length = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to handle file list request.
|
||||
******************************************************************************/
|
||||
|
||||
int CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag);
|
||||
FileTransferMsg CreateFileListErrMsg(char flags);
|
||||
FileTransferMsg CreateFileListMsg(FileListInfo fileListInfo, char flags);
|
||||
|
||||
|
||||
/*
|
||||
* This is the method called by HandleFileListRequest to get the file list
|
||||
*/
|
||||
|
||||
FileTransferMsg
|
||||
GetFileListResponseMsg(char* path, char flags)
|
||||
{
|
||||
FileTransferMsg fileListMsg;
|
||||
FileListInfo fileListInfo;
|
||||
int status = -1;
|
||||
|
||||
memset(&fileListMsg, 0, sizeof(FileTransferMsg));
|
||||
memset(&fileListInfo, 0, sizeof(FileListInfo));
|
||||
|
||||
|
||||
/* fileListInfo can have null data if the folder is Empty
|
||||
or if some error condition has occured.
|
||||
The return value is 'failure' only if some error condition has occured.
|
||||
*/
|
||||
status = CreateFileListInfo(&fileListInfo, path, !(flags & 0x10));
|
||||
|
||||
if(status == FAILURE) {
|
||||
fileListMsg = CreateFileListErrMsg(flags);
|
||||
}
|
||||
else {
|
||||
/* DisplayFileList(fileListInfo); For Debugging */
|
||||
|
||||
fileListMsg = CreateFileListMsg(fileListInfo, flags);
|
||||
FreeFileListInfo(fileListInfo);
|
||||
}
|
||||
|
||||
return fileListMsg;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag)
|
||||
{
|
||||
DIR* pDir = NULL;
|
||||
struct dirent* pDirent = NULL;
|
||||
|
||||
if((path == NULL) || (strlen(path) == 0)) {
|
||||
/* In this case we will send the list of entries in ftp root*/
|
||||
sprintf(path, "%s%s", GetFtpRoot(), "/");
|
||||
}
|
||||
|
||||
if((pDir = opendir(path)) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: not able to open the dir\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while((pDirent = readdir(pDir))) {
|
||||
if(strcmp(pDirent->d_name, ".") && strcmp(pDirent->d_name, "..")) {
|
||||
struct stat stat_buf;
|
||||
/*
|
||||
int fpLen = sizeof(char)*(strlen(pDirent->d_name)+strlen(path)+2);
|
||||
*/
|
||||
char fullpath[PATH_MAX];
|
||||
|
||||
memset(fullpath, 0, PATH_MAX);
|
||||
|
||||
strcpy(fullpath, path);
|
||||
if(path[strlen(path)-1] != '/')
|
||||
strcat(fullpath, "/");
|
||||
strcat(fullpath, pDirent->d_name);
|
||||
|
||||
if(stat(fullpath, &stat_buf) < 0) {
|
||||
rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
|
||||
__FILE__, __FUNCTION__, fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(S_ISDIR(stat_buf.st_mode)) {
|
||||
if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, -1, 0) == 0) {
|
||||
rfbLog("File [%s]: Method [%s]: Add directory %s in the"
|
||||
" list failed\n", __FILE__, __FUNCTION__, fullpath);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(flag) {
|
||||
if(AddFileListItemInfo(pFileListInfo, pDirent->d_name,
|
||||
stat_buf.st_size,
|
||||
stat_buf.st_mtime) == 0) {
|
||||
rfbLog("File [%s]: Method [%s]: Add file %s in the "
|
||||
"list failed\n", __FILE__, __FUNCTION__, fullpath);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(closedir(pDir) < 0) {
|
||||
rfbLog("File [%s]: Method [%s]: ERROR Couldn't close dir\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileListErrMsg(char flags)
|
||||
{
|
||||
FileTransferMsg fileListMsg;
|
||||
rfbFileListDataMsg* pFLD = NULL;
|
||||
char* data = NULL;
|
||||
unsigned int length = 0;
|
||||
|
||||
memset(&fileListMsg, 0, sizeof(FileTransferMsg));
|
||||
|
||||
data = (char*) calloc(sizeof(rfbFileListDataMsg), sizeof(char));
|
||||
if(data == NULL) {
|
||||
return fileListMsg;
|
||||
}
|
||||
length = sizeof(rfbFileListDataMsg) * sizeof(char);
|
||||
pFLD = (rfbFileListDataMsg*) data;
|
||||
|
||||
pFLD->type = rfbFileListData;
|
||||
pFLD->numFiles = Swap16IfLE(0);
|
||||
pFLD->dataSize = Swap16IfLE(0);
|
||||
pFLD->compressedSize = Swap16IfLE(0);
|
||||
pFLD->flags = flags | 0x80;
|
||||
|
||||
fileListMsg.data = data;
|
||||
fileListMsg.length = length;
|
||||
|
||||
return fileListMsg;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileListMsg(FileListInfo fileListInfo, char flags)
|
||||
{
|
||||
FileTransferMsg fileListMsg;
|
||||
rfbFileListDataMsg* pFLD = NULL;
|
||||
char *data = NULL, *pFileNames = NULL;
|
||||
unsigned int length = 0, dsSize = 0, i = 0;
|
||||
FileListItemSizePtr pFileListItemSize = NULL;
|
||||
|
||||
memset(&fileListMsg, 0, sizeof(FileTransferMsg));
|
||||
dsSize = fileListInfo.numEntries * 8;
|
||||
length = sz_rfbFileListDataMsg + dsSize +
|
||||
GetSumOfFileNamesLength(fileListInfo) +
|
||||
fileListInfo.numEntries;
|
||||
|
||||
data = (char*) calloc(length, sizeof(char));
|
||||
if(data == NULL) {
|
||||
return fileListMsg;
|
||||
}
|
||||
pFLD = (rfbFileListDataMsg*) data;
|
||||
pFileListItemSize = (FileListItemSizePtr) &data[sz_rfbFileListDataMsg];
|
||||
pFileNames = &data[sz_rfbFileListDataMsg + dsSize];
|
||||
|
||||
pFLD->type = rfbFileListData;
|
||||
pFLD->flags = flags & 0xF0;
|
||||
pFLD->numFiles = Swap16IfLE(fileListInfo.numEntries);
|
||||
pFLD->dataSize = Swap16IfLE(GetSumOfFileNamesLength(fileListInfo) +
|
||||
fileListInfo.numEntries);
|
||||
pFLD->compressedSize = pFLD->dataSize;
|
||||
|
||||
for(i =0; i <fileListInfo.numEntries; i++) {
|
||||
pFileListItemSize[i].size = Swap32IfLE(GetFileSizeAt(fileListInfo, i));
|
||||
pFileListItemSize[i].data = Swap32IfLE(GetFileDataAt(fileListInfo, i));
|
||||
strcpy(pFileNames, GetFileNameAt(fileListInfo, i));
|
||||
|
||||
if(i+1 < fileListInfo.numEntries)
|
||||
pFileNames += strlen(pFileNames) + 1;
|
||||
}
|
||||
|
||||
fileListMsg.data = data;
|
||||
fileListMsg.length = length;
|
||||
|
||||
return fileListMsg;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to handle File Download Request.
|
||||
******************************************************************************/
|
||||
|
||||
FileTransferMsg CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen);
|
||||
FileTransferMsg CreateFileDownloadZeroSizeDataMsg(unsigned long mTime);
|
||||
FileTransferMsg CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile);
|
||||
|
||||
FileTransferMsg
|
||||
GetFileDownLoadErrMsg()
|
||||
{
|
||||
FileTransferMsg fileDownloadErrMsg;
|
||||
|
||||
char reason[] = "An internal error on the server caused download failure";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
|
||||
fileDownloadErrMsg = CreateFileDownloadErrMsg(reason, reasonLen);
|
||||
|
||||
return fileDownloadErrMsg;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
GetFileDownloadReadDataErrMsg()
|
||||
{
|
||||
char reason[] = "Cannot open file, perhaps it is absent or is a directory";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
return CreateFileDownloadErrMsg(reason, reasonLen);
|
||||
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
GetFileDownloadLengthErrResponseMsg()
|
||||
{
|
||||
char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
return CreateFileDownloadErrMsg(reason, reasonLen);
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
//const unsigned int sz_rfbBlockSize = SZ_RFBBLOCKSIZE;
|
||||
int numOfBytesRead = 0;
|
||||
char pBuf[SZ_RFBBLOCKSIZE];
|
||||
char* path = rtcp->rcft.rcfd.fName;
|
||||
|
||||
memset(pBuf, 0, SZ_RFBBLOCKSIZE);
|
||||
|
||||
if((rtcp->rcft.rcfd.downloadInProgress == FALSE) && (rtcp->rcft.rcfd.downloadFD == -1)) {
|
||||
if((rtcp->rcft.rcfd.downloadFD = open(path, O_RDONLY)) == -1) {
|
||||
rfbLog("File [%s]: Method [%s]: Error: Couldn't open file\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return GetFileDownloadReadDataErrMsg();
|
||||
}
|
||||
rtcp->rcft.rcfd.downloadInProgress = TRUE;
|
||||
}
|
||||
if((rtcp->rcft.rcfd.downloadInProgress == TRUE) && (rtcp->rcft.rcfd.downloadFD != -1)) {
|
||||
if( (numOfBytesRead = read(rtcp->rcft.rcfd.downloadFD, pBuf, SZ_RFBBLOCKSIZE)) <= 0) {
|
||||
close(rtcp->rcft.rcfd.downloadFD);
|
||||
rtcp->rcft.rcfd.downloadFD = -1;
|
||||
rtcp->rcft.rcfd.downloadInProgress = FALSE;
|
||||
if(numOfBytesRead == 0) {
|
||||
return CreateFileDownloadZeroSizeDataMsg(rtcp->rcft.rcfd.mTime);
|
||||
}
|
||||
return GetFileDownloadReadDataErrMsg();
|
||||
}
|
||||
return CreateFileDownloadBlockSizeDataMsg(numOfBytesRead, pBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
FileTransferMsg fileDownloadMsg;
|
||||
struct stat stat_buf;
|
||||
int sz_rfbFileSize = 0;
|
||||
char* path = rtcp->rcft.rcfd.fName;
|
||||
|
||||
memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
|
||||
|
||||
if( (path == NULL) || (strlen(path) == 0) ||
|
||||
(stat(path, &stat_buf) < 0) || (!(S_ISREG(stat_buf.st_mode))) ) {
|
||||
|
||||
char reason[] = "Cannot open file, perhaps it is absent or is not a regular file";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Reading stat for path %s failed\n",
|
||||
__FILE__, __FUNCTION__, path);
|
||||
|
||||
fileDownloadMsg = CreateFileDownloadErrMsg(reason, reasonLen);
|
||||
}
|
||||
else {
|
||||
rtcp->rcft.rcfd.mTime = stat_buf.st_mtime;
|
||||
sz_rfbFileSize = stat_buf.st_size;
|
||||
if(sz_rfbFileSize <= 0) {
|
||||
fileDownloadMsg = CreateFileDownloadZeroSizeDataMsg(stat_buf.st_mtime);
|
||||
}
|
||||
|
||||
}
|
||||
return fileDownloadMsg;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen)
|
||||
{
|
||||
FileTransferMsg fileDownloadErrMsg;
|
||||
int length = sz_rfbFileDownloadFailedMsg + reasonLen + 1;
|
||||
rfbFileDownloadFailedMsg *pFDF = NULL;
|
||||
char *pFollow = NULL;
|
||||
|
||||
char *pData = (char*) calloc(length, sizeof(char));
|
||||
memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
if(pData == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: pData is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return fileDownloadErrMsg;
|
||||
}
|
||||
|
||||
pFDF = (rfbFileDownloadFailedMsg *) pData;
|
||||
pFollow = &pData[sz_rfbFileDownloadFailedMsg];
|
||||
|
||||
pFDF->type = rfbFileDownloadFailed;
|
||||
pFDF->reasonLen = Swap16IfLE(reasonLen);
|
||||
memcpy(pFollow, reason, reasonLen);
|
||||
|
||||
fileDownloadErrMsg.data = pData;
|
||||
fileDownloadErrMsg.length = length;
|
||||
|
||||
return fileDownloadErrMsg;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileDownloadZeroSizeDataMsg(unsigned long mTime)
|
||||
{
|
||||
FileTransferMsg fileDownloadZeroSizeDataMsg;
|
||||
int length = sz_rfbFileDownloadDataMsg + sizeof(int);
|
||||
rfbFileDownloadDataMsg *pFDD = NULL;
|
||||
char *pFollow = NULL;
|
||||
|
||||
char *pData = (char*) calloc(length, sizeof(char));
|
||||
memset(&fileDownloadZeroSizeDataMsg, 0, sizeof(FileTransferMsg));
|
||||
if(pData == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: pData is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return fileDownloadZeroSizeDataMsg;
|
||||
}
|
||||
|
||||
pFDD = (rfbFileDownloadDataMsg *) pData;
|
||||
pFollow = &pData[sz_rfbFileDownloadDataMsg];
|
||||
|
||||
pFDD->type = rfbFileDownloadData;
|
||||
pFDD->compressLevel = 0;
|
||||
pFDD->compressedSize = Swap16IfLE(0);
|
||||
pFDD->realSize = Swap16IfLE(0);
|
||||
|
||||
memcpy(pFollow, &mTime, sizeof(unsigned long));
|
||||
|
||||
fileDownloadZeroSizeDataMsg.data = pData;
|
||||
fileDownloadZeroSizeDataMsg.length = length;
|
||||
|
||||
return fileDownloadZeroSizeDataMsg;
|
||||
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile)
|
||||
{
|
||||
FileTransferMsg fileDownloadBlockSizeDataMsg;
|
||||
int length = sz_rfbFileDownloadDataMsg + sizeFile;
|
||||
rfbFileDownloadDataMsg *pFDD = NULL;
|
||||
char *pFollow = NULL;
|
||||
|
||||
char *pData = (char*) calloc(length, sizeof(char));
|
||||
memset(&fileDownloadBlockSizeDataMsg, 0, sizeof(FileTransferMsg));
|
||||
if(NULL == pData) {
|
||||
rfbLog("File [%s]: Method [%s]: pData is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return fileDownloadBlockSizeDataMsg;
|
||||
}
|
||||
|
||||
pFDD = (rfbFileDownloadDataMsg *) pData;
|
||||
pFollow = &pData[sz_rfbFileDownloadDataMsg];
|
||||
|
||||
pFDD->type = rfbFileDownloadData;
|
||||
pFDD->compressLevel = 0;
|
||||
pFDD->compressedSize = Swap16IfLE(sizeFile);
|
||||
pFDD->realSize = Swap16IfLE(sizeFile);
|
||||
|
||||
memcpy(pFollow, pFile, sizeFile);
|
||||
|
||||
fileDownloadBlockSizeDataMsg.data = pData;
|
||||
fileDownloadBlockSizeDataMsg.length = length;
|
||||
|
||||
return fileDownloadBlockSizeDataMsg;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to handle file upload request
|
||||
******************************************************************************/
|
||||
|
||||
FileTransferMsg CreateFileUploadErrMsg(char* reason, unsigned int reasonLen);
|
||||
|
||||
FileTransferMsg
|
||||
GetFileUploadLengthErrResponseMsg()
|
||||
{
|
||||
char reason [] = "Path length exceeds PATH_MAX (4096) bytes";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
return CreateFileUploadErrMsg(reason, reasonLen);
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
FileTransferMsg fileUploadErrMsg;
|
||||
|
||||
memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
if( (rtcp->rcft.rcfu.fName == NULL) ||
|
||||
(strlen(rtcp->rcft.rcfu.fName) == 0) ||
|
||||
((rtcp->rcft.rcfu.uploadFD = creat(rtcp->rcft.rcfu.fName,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)) {
|
||||
|
||||
char reason[] = "Could not create file";
|
||||
int reasonLen = strlen(reason);
|
||||
fileUploadErrMsg = CreateFileUploadErrMsg(reason, reasonLen);
|
||||
}
|
||||
else
|
||||
rtcp->rcft.rcfu.uploadInProgress = TRUE;
|
||||
|
||||
return fileUploadErrMsg;
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
GetFileUploadCompressedLevelErrMsg()
|
||||
{
|
||||
char reason[] = "Server does not support data compression on upload";
|
||||
int reasonLen = strlen(reason);
|
||||
|
||||
return CreateFileUploadErrMsg(reason, reasonLen);
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
|
||||
{
|
||||
FileTransferMsg ftm;
|
||||
unsigned long numOfBytesWritten = 0;
|
||||
|
||||
memset(&ftm, 0, sizeof(FileTransferMsg));
|
||||
|
||||
numOfBytesWritten = write(rtcp->rcft.rcfu.uploadFD, pBuf, rtcp->rcft.rcfu.fSize);
|
||||
|
||||
if(numOfBytesWritten != rtcp->rcft.rcfu.fSize) {
|
||||
char reason[] = "Error writing file data";
|
||||
int reasonLen = strlen(reason);
|
||||
ftm = CreateFileUploadErrMsg(reason, reasonLen);
|
||||
CloseUndoneFileTransfer(cl, rtcp);
|
||||
}
|
||||
return ftm;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
/* Here we are settimg the modification and access time of the file */
|
||||
/* Windows code stes mod/access/creation time of the file */
|
||||
struct utimbuf utb;
|
||||
|
||||
utb.actime = utb.modtime = rtcp->rcft.rcfu.mTime;
|
||||
if(utime(rtcp->rcft.rcfu.fName, &utb) == -1) {
|
||||
rfbLog("File [%s]: Method [%s]: Setting the modification/access"
|
||||
" time for the file <%s> failed\n", __FILE__,
|
||||
__FUNCTION__, rtcp->rcft.rcfu.fName);
|
||||
}
|
||||
|
||||
if(rtcp->rcft.rcfu.uploadFD != -1) {
|
||||
close(rtcp->rcft.rcfu.uploadFD);
|
||||
rtcp->rcft.rcfu.uploadFD = -1;
|
||||
rtcp->rcft.rcfu.uploadInProgress = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileTransferMsg
|
||||
CreateFileUploadErrMsg(char* reason, unsigned int reasonLen)
|
||||
{
|
||||
FileTransferMsg fileUploadErrMsg;
|
||||
int length = sz_rfbFileUploadCancelMsg + reasonLen;
|
||||
rfbFileUploadCancelMsg *pFDF = NULL;
|
||||
char *pFollow = NULL;
|
||||
|
||||
char *pData = (char*) calloc(length, sizeof(char));
|
||||
memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
if(pData == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: pData is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return fileUploadErrMsg;
|
||||
}
|
||||
|
||||
pFDF = (rfbFileUploadCancelMsg *) pData;
|
||||
pFollow = &pData[sz_rfbFileUploadCancelMsg];
|
||||
|
||||
pFDF->type = rfbFileUploadCancel;
|
||||
pFDF->reasonLen = Swap16IfLE(reasonLen);
|
||||
memcpy(pFollow, reason, reasonLen);
|
||||
|
||||
fileUploadErrMsg.data = pData;
|
||||
fileUploadErrMsg.length = length;
|
||||
|
||||
return fileUploadErrMsg;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Method to cancel File Transfer operation.
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
/* TODO :: File Upload case is not handled currently */
|
||||
/* TODO :: In case of concurrency we need to use Critical Section */
|
||||
|
||||
if(cl == NULL)
|
||||
return;
|
||||
|
||||
|
||||
if(rtcp->rcft.rcfu.uploadInProgress == TRUE) {
|
||||
rtcp->rcft.rcfu.uploadInProgress = FALSE;
|
||||
|
||||
if(rtcp->rcft.rcfu.uploadFD != -1) {
|
||||
close(rtcp->rcft.rcfu.uploadFD);
|
||||
rtcp->rcft.rcfu.uploadFD = -1;
|
||||
}
|
||||
|
||||
if(unlink(rtcp->rcft.rcfu.fName) == -1) {
|
||||
rfbLog("File [%s]: Method [%s]: Delete operation on file <%s> failed\n",
|
||||
__FILE__, __FUNCTION__, rtcp->rcft.rcfu.fName);
|
||||
}
|
||||
|
||||
memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX);
|
||||
}
|
||||
|
||||
if(rtcp->rcft.rcfd.downloadInProgress == TRUE) {
|
||||
rtcp->rcft.rcfd.downloadInProgress = FALSE;
|
||||
|
||||
if(rtcp->rcft.rcfd.downloadFD != -1) {
|
||||
close(rtcp->rcft.rcfd.downloadFD);
|
||||
rtcp->rcft.rcfd.downloadFD = -1;
|
||||
}
|
||||
memset(rtcp->rcft.rcfd.fName, 0 , PATH_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Method to handle create directory request.
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
CreateDirectory(char* dirName)
|
||||
{
|
||||
if(dirName == NULL) return;
|
||||
|
||||
if(mkdir(dirName, 0700) == -1) {
|
||||
rfbLog("File [%s]: Method [%s]: Create operation for directory <%s> failed\n",
|
||||
__FILE__, __FUNCTION__, dirName);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Novell, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com
|
||||
*
|
||||
* Author : Rohit Kumar
|
||||
* Email ID : rokumar@novell.com
|
||||
* Date : 14th July 2005
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FILE_TRANSFER_MSG_H
|
||||
#define FILE_TRANSFER_MSG_H
|
||||
|
||||
typedef struct _FileTransferMsg {
|
||||
char* data;
|
||||
unsigned int length;
|
||||
} FileTransferMsg;
|
||||
|
||||
FileTransferMsg GetFileListResponseMsg(char* path, char flag);
|
||||
|
||||
FileTransferMsg GetFileDownloadResponseMsg(char* path);
|
||||
FileTransferMsg GetFileDownloadLengthErrResponseMsg();
|
||||
FileTransferMsg GetFileDownLoadErrMsg();
|
||||
FileTransferMsg GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
FileTransferMsg ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
|
||||
FileTransferMsg GetFileUploadLengthErrResponseMsg();
|
||||
FileTransferMsg GetFileUploadCompressedLevelErrMsg();
|
||||
FileTransferMsg ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
FileTransferMsg ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr data, char* pBuf);
|
||||
|
||||
void CreateDirectory(char* dirName);
|
||||
void FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
void CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
|
||||
void FreeFileTransferMsg(FileTransferMsg ftm);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,988 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Novell, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com
|
||||
*
|
||||
* Author : Rohit Kumar
|
||||
* Email ID : rokumar@novell.com
|
||||
* Date : 14th July 2005
|
||||
*/
|
||||
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include "rfbtightproto.h"
|
||||
#include "filetransfermsg.h"
|
||||
#include "handlefiletransferrequest.h"
|
||||
|
||||
|
||||
pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
rfbBool fileTransferEnabled = TRUE;
|
||||
rfbBool fileTransferInitted = FALSE;
|
||||
char ftproot[PATH_MAX];
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* File Transfer Init methods. These methods are called for initializating
|
||||
* File Transfer and setting ftproot.
|
||||
******************************************************************************/
|
||||
|
||||
void InitFileTransfer();
|
||||
int SetFtpRoot(char* path);
|
||||
char* GetHomeDir(uid_t uid);
|
||||
void FreeHomeDir(char *homedir);
|
||||
|
||||
/*
|
||||
* InitFileTransfer method is called before parsing the command-line options
|
||||
* for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc
|
||||
* server. In case of error ftproot is set to '\0' char.
|
||||
*/
|
||||
|
||||
void
|
||||
InitFileTransfer()
|
||||
{
|
||||
char* userHome = NULL;
|
||||
uid_t uid = geteuid();
|
||||
|
||||
if(fileTransferInitted)
|
||||
return;
|
||||
|
||||
memset(ftproot, 0, sizeof(ftproot));
|
||||
|
||||
userHome = GetHomeDir(uid);
|
||||
|
||||
if((userHome != NULL) && (strlen(userHome) != 0)) {
|
||||
SetFtpRoot(userHome);
|
||||
FreeHomeDir(userHome);
|
||||
}
|
||||
|
||||
fileTransferEnabled = TRUE;
|
||||
fileTransferInitted = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method is called from InitFileTransfer method and
|
||||
* if the command line option for ftproot is provided.
|
||||
*/
|
||||
int
|
||||
SetFtpRoot(char* path)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
DIR* dir = NULL;
|
||||
|
||||
if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) {
|
||||
rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot"
|
||||
" not changed\n", __FILE__, __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(stat(path, &stat_buf) < 0) {
|
||||
rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n",
|
||||
__FILE__, __FUNCTION__, path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(S_ISDIR(stat_buf.st_mode) == 0) {
|
||||
rfbLog("File [%s]: Method [%s]: path specified is not a directory\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if((dir = opendir(path)) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Not able to open the directory\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
closedir(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
|
||||
|
||||
memset(ftproot, 0, PATH_MAX);
|
||||
if(path[strlen(path)-1] == '/') {
|
||||
memcpy(ftproot, path, strlen(path)-1);
|
||||
}
|
||||
else
|
||||
memcpy(ftproot, path, strlen(path));
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the home directory for the user name
|
||||
* param: username - name of the user for whom the home directory is required.
|
||||
* returns: returns the home directory for the user, or null in case the entry
|
||||
* is not found or any error. The returned string must be freed by calling the
|
||||
* freehomedir function.
|
||||
*/
|
||||
char*
|
||||
GetHomeDir(uid_t uid)
|
||||
{
|
||||
struct passwd *pwEnt = NULL;
|
||||
char *homedir = NULL;
|
||||
|
||||
pwEnt = getpwuid (uid);
|
||||
if (pwEnt == NULL)
|
||||
return NULL;
|
||||
|
||||
if(pwEnt->pw_dir != NULL) {
|
||||
homedir = strdup (pwEnt->pw_dir);
|
||||
}
|
||||
|
||||
return homedir;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free the home directory allocated by a previous call to retrieve the home
|
||||
* directory. param: homedir - the string returned by a previous call to
|
||||
* retrieve home directory for a user.
|
||||
*/
|
||||
void
|
||||
FreeHomeDir(char *homedir)
|
||||
{
|
||||
free (homedir);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* General methods.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* When the console sends the File Transfer Request, it sends the file path with
|
||||
* ftproot as "/". So on Agent, to get the absolute file path we need to prepend
|
||||
* the ftproot to it.
|
||||
*/
|
||||
char*
|
||||
ConvertPath(char* path)
|
||||
{
|
||||
char p[PATH_MAX];
|
||||
memset(p, 0, PATH_MAX);
|
||||
|
||||
if( (path == NULL) ||
|
||||
(strlen(path) == 0) ||
|
||||
(strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(p, path, strlen(path));
|
||||
memset(path, 0, PATH_MAX);
|
||||
sprintf(path, "%s%s", ftproot, p);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EnableFileTransfer(rfbBool enable)
|
||||
{
|
||||
fileTransferEnabled = enable;
|
||||
}
|
||||
|
||||
|
||||
rfbBool
|
||||
IsFileTransferEnabled()
|
||||
{
|
||||
return fileTransferEnabled;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
GetFtpRoot()
|
||||
{
|
||||
return ftproot;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File List Request.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* HandleFileListRequest method is called when the server receives
|
||||
* FileListRequest. In case of success a file list is sent to the client.
|
||||
* For File List Request there is no failure reason sent.So here in case of any
|
||||
* "unexpected" error no information will be sent. As these conditions should
|
||||