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
|
||||
* never come. Lets hope it never arrives :)
|
||||
* In case of dir open failure an empty list will be sent, just the header of
|
||||
* the message filled up. So on console you will get an Empty listing.
|
||||
*/
|
||||
void
|
||||
HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data)
|
||||
{
|
||||
rfbClientToServerTightMsg msg;
|
||||
int n = 0;
|
||||
char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
|
||||
FileTransferMsg fileListMsg;
|
||||
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
memset(path, 0, PATH_MAX);
|
||||
memset(&fileListMsg, 0, sizeof(FileTransferMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Socket error while reading dir name"
|
||||
" length\n", __FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize);
|
||||
if ((msg.flr.dirNameSize == 0) ||
|
||||
(msg.flr.dirNameSize > (PATH_MAX - 1))) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is "
|
||||
"greater that PATH_MAX\n", __FILE__, __FUNCTION__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ConvertPath(path) == NULL) {
|
||||
|
||||
/* The execution should never reach here */
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags));
|
||||
|
||||
if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is "
|
||||
"of Zero length\n", __FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
rfbWriteExact(cl, fileListMsg.data, fileListMsg.length);
|
||||
|
||||
FreeFileTransferMsg(fileListMsg);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File Download Request.
|
||||
******************************************************************************/
|
||||
|
||||
void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize);
|
||||
void SendFileDownloadLengthErrMsg(rfbClientPtr cl);
|
||||
void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
#ifdef TODO
|
||||
void HandleFileDownloadRequest(rfbClientPtr cl);
|
||||
void SendFileDownloadErrMsg(rfbClientPtr cl);
|
||||
void* RunFileDownloadThread(void* client);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HandleFileDownloadRequest method is called when the server receives
|
||||
* rfbFileDownload request message.
|
||||
*/
|
||||
void
|
||||
HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(path, 0, sizeof(path));
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize);
|
||||
msg.fdr.position = Swap16IfLE(msg.fdr.position);
|
||||
|
||||
if ((msg.fdr.fNameSize == 0) ||
|
||||
(msg.fdr.fNameSize > (PATH_MAX - 1))) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Error: path length is greater than"
|
||||
" PATH_MAX\n", __FILE__, __FUNCTION__);
|
||||
|
||||
HandleFileDownloadLengthError(cl, msg.fdr.fNameSize);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0';
|
||||
|
||||
if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
|
||||
/* This condition can come only if the file path is greater than
|
||||
PATH_MAX. So sending file path length error msg back to client.
|
||||
*/
|
||||
|
||||
SendFileDownloadLengthErrMsg(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
HandleFileDownload(cl, rtcp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize)
|
||||
{
|
||||
char *path = NULL;
|
||||
int n = 0;
|
||||
|
||||
if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
|
||||
if(path != NULL) {
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(path != NULL) {
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
SendFileDownloadLengthErrMsg(cl);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SendFileDownloadLengthErrMsg(rfbClientPtr cl)
|
||||
{
|
||||
FileTransferMsg fileDownloadErrMsg;
|
||||
|
||||
memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg));
|
||||
|
||||
fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg();
|
||||
|
||||
if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg "
|
||||
"is null\n", __FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length);
|
||||
|
||||
FreeFileTransferMsg(fileDownloadErrMsg);
|
||||
}
|
||||
|
||||
extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl);
|
||||
|
||||
void*
|
||||
RunFileDownloadThread(void* client)
|
||||
{
|
||||
rfbClientPtr cl = (rfbClientPtr) client;
|
||||
rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
|
||||
FileTransferMsg fileDownloadMsg;
|
||||
|
||||
if(rtcp == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
|
||||
do {
|
||||
pthread_mutex_lock(&fileDownloadMutex);
|
||||
fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp);
|
||||
pthread_mutex_unlock(&fileDownloadMutex);
|
||||
|
||||
if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
|
||||
if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0) {
|
||||
rfbLog("File [%s]: Method [%s]: Error while writing to socket \n"
|
||||
, __FILE__, __FUNCTION__);
|
||||
|
||||
if(cl != NULL) {
|
||||
rfbCloseClient(cl);
|
||||
CloseUndoneFileTransfer(cl, rtcp);
|
||||
}
|
||||
|
||||
FreeFileTransferMsg(fileDownloadMsg);
|
||||
return NULL;
|
||||
}
|
||||
FreeFileTransferMsg(fileDownloadMsg);
|
||||
}
|
||||
} while(rtcp->rcft.rcfd.downloadInProgress == TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
pthread_t fileDownloadThread;
|
||||
FileTransferMsg fileDownloadMsg;
|
||||
|
||||
memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
|
||||
fileDownloadMsg = ChkFileDownloadErr(cl, rtcp);
|
||||
if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
|
||||
rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length);
|
||||
FreeFileTransferMsg(fileDownloadMsg);
|
||||
return;
|
||||
}
|
||||
rtcp->rcft.rcfd.downloadInProgress = FALSE;
|
||||
rtcp->rcft.rcfd.downloadFD = -1;
|
||||
|
||||
if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*)
|
||||
cl) != 0) {
|
||||
FileTransferMsg ftm = GetFileDownLoadErrMsg();
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: Download thread creation failed\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
if((ftm.data != NULL) && (ftm.length != 0)) {
|
||||
rfbWriteExact(cl, ftm.data, ftm.length);
|
||||
FreeFileTransferMsg(ftm);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File Download Cancel Request.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void
|
||||
HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char *reason = NULL;
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading "
|
||||
"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen);
|
||||
|
||||
if(msg.fdc.reasonLen == 0) {
|
||||
rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char));
|
||||
if(reason == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading "
|
||||
"FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:"
|
||||
" reason <%s>\n", __FILE__, __FUNCTION__, reason);
|
||||
|
||||
pthread_mutex_lock(&fileDownloadMutex);
|
||||
CloseUndoneFileTransfer(cl, rtcp);
|
||||
pthread_mutex_unlock(&fileDownloadMutex);
|
||||
|
||||
if(reason != NULL) {
|
||||
free(reason);
|
||||
reason = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File upload request
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef TODO
|
||||
void HandleFileUploadRequest(rfbClientPtr cl);
|
||||
#endif
|
||||
void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data);
|
||||
void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize);
|
||||
void SendFileUploadLengthErrMsg(rfbClientPtr cl);
|
||||
|
||||
|
||||
void
|
||||
HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(path, 0, PATH_MAX);
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize);
|
||||
msg.fupr.position = Swap16IfLE(msg.fupr.position);
|
||||
|
||||
if ((msg.fupr.fNameSize == 0) ||
|
||||
(msg.fupr.fNameSize > (PATH_MAX - 1))) {
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
HandleFileUploadLengthError(cl, msg.fupr.fNameSize);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n"
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0';
|
||||
|
||||
if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
/* This may come if the path length exceeds PATH_MAX.
|
||||
So sending path length error to client
|
||||
*/
|
||||
SendFileUploadLengthErrMsg(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
HandleFileUpload(cl, rtcp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize)
|
||||
{
|
||||
char *path = NULL;
|
||||
int n = 0;
|
||||
|
||||
if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading dir name\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
|
||||
if(path != NULL) {
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: File Upload Length Error occured"
|
||||
"file path requested is <%s>\n", __FILE__, __FUNCTION__, path);
|
||||
|
||||
if(path != NULL) {
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
SendFileUploadLengthErrMsg(cl);
|
||||
}
|
||||
|
||||
void
|
||||
SendFileUploadLengthErrMsg(rfbClientPtr cl)
|
||||
{
|
||||
|
||||
FileTransferMsg fileUploadErrMsg;
|
||||
|
||||
memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
fileUploadErrMsg = GetFileUploadLengthErrResponseMsg();
|
||||
|
||||
if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
|
||||
FreeFileTransferMsg(fileUploadErrMsg);
|
||||
}
|
||||
|
||||
void
|
||||
HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
FileTransferMsg fileUploadErrMsg;
|
||||
|
||||
memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
|
||||
|
||||
rtcp->rcft.rcfu.uploadInProgress = FALSE;
|
||||
rtcp->rcft.rcfu.uploadFD = -1;
|
||||
|
||||
fileUploadErrMsg = ChkFileUploadErr(cl, rtcp);
|
||||
if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) {
|
||||
rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
|
||||
FreeFileTransferMsg(fileUploadErrMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File Upload Data Request
|
||||
*****************************************************************************/
|
||||
|
||||
void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf);
|
||||
|
||||
|
||||
void
|
||||
HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char* pBuf = NULL;
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
|
||||
msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
|
||||
if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
|
||||
if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned
|
||||
long))) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
FileUpdateComplete(cl, rtcp);
|
||||
return;
|
||||
}
|
||||
|
||||
pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char));
|
||||
if(pBuf == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
|
||||
if(pBuf != NULL) {
|
||||
free(pBuf);
|
||||
pBuf = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if(msg.fud.compressedLevel != 0) {
|
||||
FileTransferMsg ftm;
|
||||
memset(&ftm, 0, sizeof(FileTransferMsg));
|
||||
|
||||
ftm = GetFileUploadCompressedLevelErrMsg();
|
||||
|
||||
if((ftm.data != NULL) && (ftm.length != 0)) {
|
||||
rfbWriteExact(cl, ftm.data, ftm.length);
|
||||
FreeFileTransferMsg(ftm);
|
||||
}
|
||||
|
||||
CloseUndoneFileTransfer(cl, rtcp);
|
||||
|
||||
if(pBuf != NULL) {
|
||||
free(pBuf);
|
||||
pBuf = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rtcp->rcft.rcfu.fSize = msg.fud.compressedSize;
|
||||
|
||||
HandleFileUploadWrite(cl, rtcp, pBuf);
|
||||
|
||||
if(pBuf != NULL) {
|
||||
free(pBuf);
|
||||
pBuf = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
|
||||
{
|
||||
FileTransferMsg ftm;
|
||||
memset(&ftm, 0, sizeof(FileTransferMsg));
|
||||
|
||||
ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf);
|
||||
|
||||
if((ftm.data != NULL) && (ftm.length != 0)) {
|
||||
rfbWriteExact(cl, ftm.data, ftm.length);
|
||||
FreeFileTransferMsg(ftm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File Upload Failed Request.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void
|
||||
HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char* reason = NULL;
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen);
|
||||
if(msg.fuf.reasonLen == 0) {
|
||||
rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char));
|
||||
if(reason == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
|
||||
if(reason != NULL) {
|
||||
free(reason);
|
||||
reason = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:"
|
||||
" reason <%s>\n", __FILE__, __FUNCTION__, reason);
|
||||
|
||||
CloseUndoneFileTransfer(cl, rtcp);
|
||||
|
||||
if(reason != NULL) {
|
||||
free(reason);
|
||||
reason = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Methods to Handle File Create Request.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
void
|
||||
HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
|
||||
{
|
||||
int n = 0;
|
||||
char dirName[PATH_MAX];
|
||||
rfbClientToServerTightMsg msg;
|
||||
|
||||
memset(dirName, 0, PATH_MAX);
|
||||
memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
|
||||
|
||||
if(cl == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen);
|
||||
|
||||
/* TODO :: chk if the dNameLen is greater than PATH_MAX */
|
||||
|
||||
if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) {
|
||||
|
||||
if (n < 0)
|
||||
rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ConvertPath(dirName) == NULL) {
|
||||
rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CreateDirectory(dirName);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 HANDLE_FILE_TRANSFER_REQUEST_H
|
||||
#define HANDLE_FILE_TRANSFER_REQUEST_H
|
||||
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
|
||||
void InitFileTransfer();
|
||||
int SetFtpRoot(char* path);
|
||||
void EnableFileTransfer(rfbBool enable);
|
||||
rfbBool IsFileTransferEnabled();
|
||||
char* GetFtpRoot();
|
||||
|
||||
void HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
void HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientRec* data);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,450 @@
|
||||
/*
|
||||
* 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 : 25th August 2005
|
||||
*/
|
||||
|
||||
#ifndef RFBTIGHTPROTO_H
|
||||
#define RFBTIGHTPROTO_H
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define rfbSecTypeTight 16
|
||||
|
||||
void rfbTightUsage(void);
|
||||
int rfbTightProcessArgs(int argc, char *argv[]);
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Negotiation of Tunneling Capabilities (protocol version 3.7t)
|
||||
*
|
||||
* If the chosen security type is rfbSecTypeTight, the server sends a list of
|
||||
* supported tunneling methods ("tunneling" refers to any additional layer of
|
||||
* data transformation, such as encryption or external compression.)
|
||||
*
|
||||
* nTunnelTypes specifies the number of following rfbCapabilityInfo structures
|
||||
* that list all supported tunneling methods in the order of preference.
|
||||
*
|
||||
* NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be
|
||||
* used, and the client should not send a response requesting a tunneling
|
||||
* method.
|
||||
*/
|
||||
|
||||
typedef struct _rfbTunnelingCapsMsg {
|
||||
uint32_t nTunnelTypes;
|
||||
/* followed by nTunnelTypes * rfbCapabilityInfo structures */
|
||||
} rfbTunnelingCapsMsg;
|
||||
|
||||
#define sz_rfbTunnelingCapsMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Tunneling Method Request (protocol version 3.7t)
|
||||
*
|
||||
* If the list of tunneling capabilities sent by the server was not empty, the
|
||||
* client should reply with a 32-bit code specifying a particular tunneling
|
||||
* method. The following code should be used for no tunneling.
|
||||
*/
|
||||
|
||||
#define rfbNoTunneling 0
|
||||
#define sig_rfbNoTunneling "NOTUNNEL"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Negotiation of Authentication Capabilities (protocol version 3.7t)
|
||||
*
|
||||
* After setting up tunneling, the server sends a list of supported
|
||||
* authentication schemes.
|
||||
*
|
||||
* nAuthTypes specifies the number of following rfbCapabilityInfo structures
|
||||
* that list all supported authentication schemes in the order of preference.
|
||||
*
|
||||
* NOTE: If nAuthTypes is 0, that tells the client that no authentication is
|
||||
* necessary, and the client should not send a response requesting an
|
||||
* authentication scheme.
|
||||
*/
|
||||
|
||||
typedef struct _rfbAuthenticationCapsMsg {
|
||||
uint32_t nAuthTypes;
|
||||
/* followed by nAuthTypes * rfbCapabilityInfo structures */
|
||||
} rfbAuthenticationCapsMsg;
|
||||
|
||||
#define sz_rfbAuthenticationCapsMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Authentication Scheme Request (protocol version 3.7t)
|
||||
*
|
||||
* If the list of authentication capabilities sent by the server was not empty,
|
||||
* the client should reply with a 32-bit code specifying a particular
|
||||
* authentication scheme. The following codes are supported.
|
||||
*/
|
||||
|
||||
#define rfbAuthNone 1
|
||||
#define rfbAuthVNC 2
|
||||
#define rfbAuthUnixLogin 129
|
||||
#define rfbAuthExternal 130
|
||||
|
||||
#define sig_rfbAuthNone "NOAUTH__"
|
||||
#define sig_rfbAuthVNC "VNCAUTH_"
|
||||
#define sig_rfbAuthUnixLogin "ULGNAUTH"
|
||||
#define sig_rfbAuthExternal "XTRNAUTH"
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Structure used to describe protocol options such as tunneling methods,
|
||||
* authentication schemes and message types (protocol version 3.7t).
|
||||
*/
|
||||
|
||||
typedef struct _rfbCapabilityInfo {
|
||||
|
||||
uint32_t code; /* numeric identifier */
|
||||
uint8_t vendorSignature[4]; /* vendor identification */
|
||||
uint8_t nameSignature[8]; /* abbreviated option name */
|
||||
|
||||
} rfbCapabilityInfo;
|
||||
|
||||
#define sz_rfbCapabilityInfoVendor 4
|
||||
#define sz_rfbCapabilityInfoName 8
|
||||
#define sz_rfbCapabilityInfo 16
|
||||
|
||||
/*
|
||||
* Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
|
||||
*/
|
||||
|
||||
#define rfbStandardVendor "STDV"
|
||||
#define rfbTridiaVncVendor "TRDV"
|
||||
#define rfbTightVncVendor "TGHT"
|
||||
|
||||
|
||||
/* It's a good idea to keep these values a bit greater than required. */
|
||||
#define MAX_TIGHT_ENCODINGS 10
|
||||
#define MAX_TUNNELING_CAPS 16
|
||||
#define MAX_AUTH_CAPS 16
|
||||
|
||||
typedef struct _rfbClientFileDownload {
|
||||
char fName[PATH_MAX];
|
||||
int downloadInProgress;
|
||||
unsigned long mTime;
|
||||
int downloadFD;
|
||||
} rfbClientFileDownload ;
|
||||
|
||||
typedef struct _rfbClientFileUpload {
|
||||
char fName[PATH_MAX];
|
||||
int uploadInProgress;
|
||||
unsigned long mTime;
|
||||
unsigned long fSize;
|
||||
int uploadFD;
|
||||
} rfbClientFileUpload ;
|
||||
|
||||
typedef struct _rfbClientFileTransfer {
|
||||
rfbClientFileDownload rcfd;
|
||||
rfbClientFileUpload rcfu;
|
||||
} rfbClientFileTransfer;
|
||||
|
||||
|
||||
typedef struct _rfbTightClientRec {
|
||||
|
||||
/* Lists of capability codes sent to clients. We remember these
|
||||
lists to restrict clients from choosing those tunneling and
|
||||
authentication types that were not advertised. */
|
||||
|
||||
int nAuthCaps;
|
||||
uint32_t authCaps[MAX_AUTH_CAPS];
|
||||
|
||||
/* This is not useful while we don't support tunneling:
|
||||
int nTunnelingCaps;
|
||||
uint32_t tunnelingCaps[MAX_TUNNELING_CAPS]; */
|
||||
|
||||
rfbClientFileTransfer rcft;
|
||||
|
||||
} rfbTightClientRec, *rfbTightClientPtr;
|
||||
|
||||
/*
|
||||
* Macro to fill in an rfbCapabilityInfo structure (protocol 3.7t).
|
||||
* Normally, using macros is no good, but this macro saves us from
|
||||
* writing constants twice -- it constructs signature names from codes.
|
||||
* Note that "code_sym" argument should be a single symbol, not an expression.
|
||||
*/
|
||||
|
||||
#define SetCapInfo(cap_ptr, code_sym, vendor) \
|
||||
{ \
|
||||
rfbCapabilityInfo *pcap; \
|
||||
pcap = (cap_ptr); \
|
||||
pcap->code = Swap32IfLE(code_sym); \
|
||||
memcpy(pcap->vendorSignature, (vendor), \
|
||||
sz_rfbCapabilityInfoVendor); \
|
||||
memcpy(pcap->nameSignature, sig_##code_sym, \
|
||||
sz_rfbCapabilityInfoName); \
|
||||
}
|
||||
|
||||
void rfbHandleSecTypeTight(rfbClientPtr cl);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Server Interaction Capabilities Message (protocol version 3.7t)
|
||||
*
|
||||
* In the protocol version 3.7t, the server informs the client what message
|
||||
* types it supports in addition to ones defined in the protocol version 3.7.
|
||||
* Also, the server sends the list of all supported encodings (note that it's
|
||||
* not necessary to advertise the "raw" encoding sinse it MUST be supported in
|
||||
* RFB 3.x protocols).
|
||||
*
|
||||
* This data immediately follows the server initialisation message.
|
||||
*/
|
||||
|
||||
typedef struct _rfbInteractionCapsMsg {
|
||||
uint16_t nServerMessageTypes;
|
||||
uint16_t nClientMessageTypes;
|
||||
uint16_t nEncodingTypes;
|
||||
uint16_t pad; /* reserved, must be 0 */
|
||||
/* followed by nServerMessageTypes * rfbCapabilityInfo structures */
|
||||
/* followed by nClientMessageTypes * rfbCapabilityInfo structures */
|
||||
} rfbInteractionCapsMsg;
|
||||
|
||||
#define sz_rfbInteractionCapsMsg 8
|
||||
|
||||
#define rfbFileListData 130
|
||||
#define rfbFileDownloadData 131
|
||||
#define rfbFileUploadCancel 132
|
||||
#define rfbFileDownloadFailed 133
|
||||
|
||||
/* signatures for non-standard messages */
|
||||
#define sig_rfbFileListData "FTS_LSDT"
|
||||
#define sig_rfbFileDownloadData "FTS_DNDT"
|
||||
#define sig_rfbFileUploadCancel "FTS_UPCN"
|
||||
#define sig_rfbFileDownloadFailed "FTS_DNFL"
|
||||
|
||||
|
||||
|
||||
#define rfbFileListRequest 130
|
||||
#define rfbFileDownloadRequest 131
|
||||
#define rfbFileUploadRequest 132
|
||||
#define rfbFileUploadData 133
|
||||
#define rfbFileDownloadCancel 134
|
||||
#define rfbFileUploadFailed 135
|
||||
#define rfbFileCreateDirRequest 136
|
||||
|
||||
/* signatures for non-standard messages */
|
||||
#define sig_rfbFileListRequest "FTC_LSRQ"
|
||||
#define sig_rfbFileDownloadRequest "FTC_DNRQ"
|
||||
#define sig_rfbFileUploadRequest "FTC_UPRQ"
|
||||
#define sig_rfbFileUploadData "FTC_UPDT"
|
||||
#define sig_rfbFileDownloadCancel "FTC_DNCN"
|
||||
#define sig_rfbFileUploadFailed "FTC_UPFL"
|
||||
#define sig_rfbFileCreateDirRequest "FTC_FCDR"
|
||||
|
||||
|
||||
/* signatures for basic encoding types */
|
||||
#define sig_rfbEncodingRaw "RAW_____"
|
||||
#define sig_rfbEncodingCopyRect "COPYRECT"
|
||||
#define sig_rfbEncodingRRE "RRE_____"
|
||||
#define sig_rfbEncodingCoRRE "CORRE___"
|
||||
#define sig_rfbEncodingHextile "HEXTILE_"
|
||||
#define sig_rfbEncodingZlib "ZLIB____"
|
||||
#define sig_rfbEncodingTight "TIGHT___"
|
||||
#define sig_rfbEncodingZlibHex "ZLIBHEX_"
|
||||
|
||||
|
||||
/* signatures for "fake" encoding types */
|
||||
#define sig_rfbEncodingCompressLevel0 "COMPRLVL"
|
||||
#define sig_rfbEncodingXCursor "X11CURSR"
|
||||
#define sig_rfbEncodingRichCursor "RCHCURSR"
|
||||
#define sig_rfbEncodingPointerPos "POINTPOS"
|
||||
#define sig_rfbEncodingLastRect "LASTRECT"
|
||||
#define sig_rfbEncodingNewFBSize "NEWFBSIZ"
|
||||
#define sig_rfbEncodingQualityLevel0 "JPEGQLVL"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileListRequest
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileListRequestMsg {
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
uint16_t dirNameSize;
|
||||
/* Followed by char Dirname[dirNameSize] */
|
||||
} rfbFileListRequestMsg;
|
||||
|
||||
#define sz_rfbFileListRequestMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileDownloadRequest
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileDownloadRequestMsg {
|
||||
uint8_t type;
|
||||
uint8_t compressedLevel;
|
||||
uint16_t fNameSize;
|
||||
uint32_t position;
|
||||
/* Followed by char Filename[fNameSize] */
|
||||
} rfbFileDownloadRequestMsg;
|
||||
|
||||
#define sz_rfbFileDownloadRequestMsg 8
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileUploadRequest
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileUploadRequestMsg {
|
||||
uint8_t type;
|
||||
uint8_t compressedLevel;
|
||||
uint16_t fNameSize;
|
||||
uint32_t position;
|
||||
/* Followed by char Filename[fNameSize] */
|
||||
} rfbFileUploadRequestMsg;
|
||||
|
||||
#define sz_rfbFileUploadRequestMsg 8
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileUploadData
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileUploadDataMsg {
|
||||
uint8_t type;
|
||||
uint8_t compressedLevel;
|
||||
uint16_t realSize;
|
||||
uint16_t compressedSize;
|
||||
/* Followed by File[compressedSize],
|
||||
but if (realSize = compressedSize = 0) followed by uint32_t modTime */
|
||||
} rfbFileUploadDataMsg;
|
||||
|
||||
#define sz_rfbFileUploadDataMsg 6
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileDownloadCancel
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileDownloadCancelMsg {
|
||||
uint8_t type;
|
||||
uint8_t unused;
|
||||
uint16_t reasonLen;
|
||||
/* Followed by reason[reasonLen] */
|
||||
} rfbFileDownloadCancelMsg;
|
||||
|
||||
#define sz_rfbFileDownloadCancelMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileUploadFailed
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileUploadFailedMsg {
|
||||
uint8_t type;
|
||||
uint8_t unused;
|
||||
uint16_t reasonLen;
|
||||
/* Followed by reason[reasonLen] */
|
||||
} rfbFileUploadFailedMsg;
|
||||
|
||||
#define sz_rfbFileUploadFailedMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileCreateDirRequest
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileCreateDirRequestMsg {
|
||||
uint8_t type;
|
||||
uint8_t unused;
|
||||
uint16_t dNameLen;
|
||||
/* Followed by dName[dNameLen] */
|
||||
} rfbFileCreateDirRequestMsg;
|
||||
|
||||
#define sz_rfbFileCreateDirRequestMsg 4
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Union of all client->server messages.
|
||||
*/
|
||||
|
||||
typedef union _rfbClientToServerTightMsg {
|
||||
rfbFileListRequestMsg flr;
|
||||
rfbFileDownloadRequestMsg fdr;
|
||||
rfbFileUploadRequestMsg fupr;
|
||||
rfbFileUploadDataMsg fud;
|
||||
rfbFileDownloadCancelMsg fdc;
|
||||
rfbFileUploadFailedMsg fuf;
|
||||
rfbFileCreateDirRequestMsg fcdr;
|
||||
} rfbClientToServerTightMsg;
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileListData
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileListDataMsg {
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
uint16_t numFiles;
|
||||
uint16_t dataSize;
|
||||
uint16_t compressedSize;
|
||||
/* Followed by SizeData[numFiles] */
|
||||
/* Followed by Filenames[compressedSize] */
|
||||
} rfbFileListDataMsg;
|
||||
|
||||
#define sz_rfbFileListDataMsg 8
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileDownloadData
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileDownloadDataMsg {
|
||||
uint8_t type;
|
||||
uint8_t compressLevel;
|
||||
uint16_t realSize;
|
||||
uint16_t compressedSize;
|
||||
/* Followed by File[copressedSize],
|
||||
but if (realSize = compressedSize = 0) followed by uint32_t modTime */
|
||||
} rfbFileDownloadDataMsg;
|
||||
|
||||
#define sz_rfbFileDownloadDataMsg 6
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileUploadCancel
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileUploadCancelMsg {
|
||||
uint8_t type;
|
||||
uint8_t unused;
|
||||
uint16_t reasonLen;
|
||||
/* Followed by reason[reasonLen] */
|
||||
} rfbFileUploadCancelMsg;
|
||||
|
||||
#define sz_rfbFileUploadCancelMsg 4
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* FileDownloadFailed
|
||||
*/
|
||||
|
||||
typedef struct _rfbFileDownloadFailedMsg {
|
||||
uint8_t type;
|
||||
uint8_t unused;
|
||||
uint16_t reasonLen;
|
||||
/* Followed by reason[reasonLen] */
|
||||
} rfbFileDownloadFailedMsg;
|
||||
|
||||
#define sz_rfbFileDownloadFailedMsg 4
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -0,0 +1,506 @@
|
||||
/*
|
||||
* 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 : 25th August 2005
|
||||
*/
|
||||
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
#include "rfbtightproto.h"
|
||||
#include "handlefiletransferrequest.h"
|
||||
|
||||
/*
|
||||
* Get my data!
|
||||
*
|
||||
* This gets the extension specific data from the client structure. If
|
||||
* the data is not found, the client connection is closed, a complaint
|
||||
* is logged, and NULL is returned.
|
||||
*/
|
||||
|
||||
extern rfbProtocolExtension tightVncFileTransferExtension;
|
||||
|
||||
rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl)
|
||||
{
|
||||
rfbExtensionData* data = cl->extensions;
|
||||
|
||||
while(data && data->extension != &tightVncFileTransferExtension)
|
||||
data = data->next;
|
||||
|
||||
if(data == NULL) {
|
||||
rfbLog("TightVNC enabled, but client data missing?!\n");
|
||||
rfbCloseClient(cl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (rfbTightClientPtr)data->data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the authentication challenge.
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbVncAuthSendChallenge(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
|
||||
// 4 byte header is alreay sent. Which is rfbSecTypeVncAuth (same as rfbVncAuth). Just send the challenge.
|
||||
rfbRandomBytes(cl->authChallenge);
|
||||
if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
|
||||
rfbLogPerror("rfbAuthNewClient: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbVncAuthProcessResponse. */
|
||||
/* This methos is defined in auth.c file */
|
||||
rfbAuthProcessClientMessage(cl);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Read client's preferred authentication type (protocol 3.7t).
|
||||
*/
|
||||
|
||||
void
|
||||
rfbProcessClientAuthType(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
uint32_t auth_type;
|
||||
int n, i;
|
||||
rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
|
||||
|
||||
if(rtcp == NULL)
|
||||
return;
|
||||
|
||||
/* Read authentication type selected by the client. */
|
||||
n = rfbReadExact(cl, (char *)&auth_type, sizeof(auth_type));
|
||||
if (n <= 0) {
|
||||
if (n == 0)
|
||||
rfbLog("rfbProcessClientAuthType: client gone\n");
|
||||
else
|
||||
rfbLogPerror("rfbProcessClientAuthType: read");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
auth_type = Swap32IfLE(auth_type);
|
||||
|
||||
/* Make sure it was present in the list sent by the server. */
|
||||
for (i = 0; i < rtcp->nAuthCaps; i++) {
|
||||
if (auth_type == rtcp->authCaps[i])
|
||||
break;
|
||||
}
|
||||
if (i >= rtcp->nAuthCaps) {
|
||||
rfbLog("rfbProcessClientAuthType: "
|
||||
"wrong authentication type requested\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (auth_type) {
|
||||
case rfbAuthNone:
|
||||
/* Dispatch client input to rfbProcessClientInitMessage. */
|
||||
cl->state = RFB_INITIALISATION;
|
||||
break;
|
||||
case rfbAuthVNC:
|
||||
rfbVncAuthSendChallenge(cl);
|
||||
break;
|
||||
default:
|
||||
rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n");
|
||||
rfbCloseClient(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read tunneling type requested by the client (protocol 3.7t).
|
||||
* NOTE: Currently, we don't support tunneling, and this function
|
||||
* can never be called.
|
||||
*/
|
||||
|
||||
void
|
||||
rfbProcessClientTunnelingType(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
/* If we were called, then something's really wrong. */
|
||||
rfbLog("rfbProcessClientTunnelingType: not implemented\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send the list of our authentication capabilities to the client
|
||||
* (protocol 3.7t).
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbSendAuthCaps(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
rfbBool authRequired;
|
||||
rfbAuthenticationCapsMsg caps;
|
||||
rfbCapabilityInfo caplist[MAX_AUTH_CAPS];
|
||||
int count = 0;
|
||||
rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
|
||||
|
||||
if(rtcp == NULL)
|
||||
return;
|
||||
|
||||
if (cl->screen->authPasswdData && !cl->reverseConnection) {
|
||||
// chk if this condition is valid or not.
|
||||
SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor);
|
||||
rtcp->authCaps[count++] = rfbAuthVNC;
|
||||
}
|
||||
|
||||
rtcp->nAuthCaps = count;
|
||||
caps.nAuthTypes = Swap32IfLE((uint32_t)count);
|
||||
if (rfbWriteExact(cl, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) {
|
||||
rfbLogPerror("rfbSendAuthCaps: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
if (rfbWriteExact(cl, (char *)&caplist[0],
|
||||
count * sz_rfbCapabilityInfo) < 0) {
|
||||
rfbLogPerror("rfbSendAuthCaps: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
/* Dispatch client input to rfbProcessClientAuthType. */
|
||||
/* Call the function for authentication from here */
|
||||
rfbProcessClientAuthType(cl);
|
||||
} else {
|
||||
/* Dispatch client input to rfbProcessClientInitMessage. */
|
||||
cl->state = RFB_INITIALISATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Send the list of our tunneling capabilities (protocol 3.7t).
|
||||
*/
|
||||
|
||||
static void
|
||||
rfbSendTunnelingCaps(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
rfbTunnelingCapsMsg caps;
|
||||
uint32_t nTypes = 0; /* we don't support tunneling yet */
|
||||
|
||||
caps.nTunnelTypes = Swap32IfLE(nTypes);
|
||||
if (rfbWriteExact(cl, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) {
|
||||
rfbLogPerror("rfbSendTunnelingCaps: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nTypes) {
|
||||
/* Dispatch client input to rfbProcessClientTunnelingType(). */
|
||||
/* The flow should not reach here as tunneling is not implemented. */
|
||||
rfbProcessClientTunnelingType(cl);
|
||||
} else {
|
||||
rfbSendAuthCaps(cl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rfbSendInteractionCaps is called after sending the server
|
||||
* initialisation message, only if TightVNC protocol extensions were
|
||||
* enabled (protocol 3.7t). In this function, we send the lists of
|
||||
* supported protocol messages and encodings.
|
||||
*/
|
||||
|
||||
/* Update these constants on changing capability lists below! */
|
||||
/* Values updated for FTP */
|
||||
#define N_SMSG_CAPS 4
|
||||
#define N_CMSG_CAPS 6
|
||||
#define N_ENC_CAPS 12
|
||||
|
||||
void
|
||||
rfbSendInteractionCaps(cl)
|
||||
rfbClientPtr cl;
|
||||
{
|
||||
rfbInteractionCapsMsg intr_caps;
|
||||
rfbCapabilityInfo smsg_list[N_SMSG_CAPS];
|
||||
rfbCapabilityInfo cmsg_list[N_CMSG_CAPS];
|
||||
rfbCapabilityInfo enc_list[N_ENC_CAPS];
|
||||
int i;
|
||||
|
||||
/* Fill in the header structure sent prior to capability lists. */
|
||||
intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS);
|
||||
intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS);
|
||||
intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS);
|
||||
intr_caps.pad = 0;
|
||||
|
||||
/* Supported server->client message types. */
|
||||
/* For file transfer support: */
|
||||
i = 0;
|
||||
if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) {
|
||||
SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor);
|
||||
SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor);
|
||||
SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor);
|
||||
SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor);
|
||||
if (i != N_SMSG_CAPS) {
|
||||
rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Supported client->server message types. */
|
||||
/* For file transfer support: */
|
||||
i = 0;
|
||||
if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) {
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor);
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor);
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor);
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor);
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor);
|
||||
SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor);
|
||||
if (i != N_CMSG_CAPS) {
|
||||
rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encoding types. */
|
||||
i = 0;
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor);
|
||||
SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor);
|
||||
if (i != N_ENC_CAPS) {
|
||||
rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send header and capability lists */
|
||||
if (rfbWriteExact(cl, (char *)&intr_caps,
|
||||
sz_rfbInteractionCapsMsg) < 0 ||
|
||||
rfbWriteExact(cl, (char *)&smsg_list[0],
|
||||
sz_rfbCapabilityInfo * N_SMSG_CAPS) < 0 ||
|
||||
rfbWriteExact(cl, (char *)&cmsg_list[0],
|
||||
sz_rfbCapabilityInfo * N_CMSG_CAPS) < 0 ||
|
||||
rfbWriteExact(cl, (char *)&enc_list[0],
|
||||
sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) {
|
||||
rfbLogPerror("rfbSendInteractionCaps: write");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dispatch client input to rfbProcessClientNormalMessage(). */
|
||||
cl->state = RFB_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
rfbBool
|
||||
rfbTightExtensionInit(cl, data)
|
||||
rfbClientPtr cl;
|
||||
void** data;
|
||||
{
|
||||
|
||||
rfbSendInteractionCaps(cl);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static rfbBool
|
||||
handleMessage(rfbClientPtr cl,
|
||||
const char* messageName,
|
||||
void (*handler)(rfbClientPtr cl, rfbTightClientPtr data))
|
||||
{
|
||||
rfbTightClientPtr data;
|
||||
|
||||
rfbLog("%s message received\n", messageName);
|
||||
|
||||
if((IsFileTransferEnabled() == FALSE) || ( cl->viewOnly == TRUE)) {
|
||||
rfbCloseClient(cl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data = rfbGetTightClientData(cl);
|
||||
if(data == NULL)
|
||||
return FALSE;
|
||||
|
||||
handler(cl, data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rfbBool
|
||||
rfbTightExtensionMsgHandler(cl, data, msg)
|
||||
struct _rfbClientRec* cl;
|
||||
void* data;
|
||||
const rfbClientToServerMsg* msg;
|
||||
{
|
||||
switch (msg->type) {
|
||||
|
||||
case rfbFileListRequest:
|
||||
|
||||
return handleMessage(cl, "rfbFileListRequest", HandleFileListRequest);
|
||||
|
||||
case rfbFileDownloadRequest:
|
||||
|
||||
return handleMessage(cl, "rfbFileDownloadRequest", HandleFileDownloadRequest);
|
||||
|
||||
case rfbFileUploadRequest:
|
||||
|
||||
return handleMessage(cl, "rfbFileUploadRequest", HandleFileUploadRequest);
|
||||
|
||||
case rfbFileUploadData:
|
||||
|
||||
return handleMessage(cl, "rfbFileUploadDataRequest", HandleFileUploadDataRequest);
|
||||
|
||||
case rfbFileDownloadCancel:
|
||||
|
||||
return handleMessage(cl, "rfbFileDownloadCancelRequest", HandleFileDownloadCancelRequest);
|
||||
|
||||
case rfbFileUploadFailed:
|
||||
|
||||
return handleMessage(cl, "rfbFileUploadFailedRequest", HandleFileUploadFailedRequest);
|
||||
|
||||
case rfbFileCreateDirRequest:
|
||||
|
||||
return handleMessage(cl, "rfbFileCreateDirRequest", HandleFileCreateDirRequest);
|
||||
|
||||
default:
|
||||
|
||||
rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
|
||||
msg->type);
|
||||
|
||||
/*
|
||||
|
||||
// We shouldn't close the connection here for unhandled msg, it should be left to libvncserver.
|
||||
rfbLog(" ... closing connection\n");
|
||||
rfbCloseClient(cl);
|
||||
|
||||
*/
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rfbTightExtensionClientClose(rfbClientPtr cl, void* data) {
|
||||
|
||||
if(data != NULL)
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
rfbTightUsage(void) {
|
||||
fprintf(stderr, "\nlibvncserver-tight-extension options:\n");
|
||||
fprintf(stderr, "-disablefiletransfer disable file transfer\n");
|
||||
fprintf(stderr, "-ftproot string set ftp root\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
int
|
||||
rfbTightProcessArg(int argc, char *argv[]) {
|
||||
|
||||
InitFileTransfer();
|
||||
|
||||
if(argc<1)
|
||||
return 0;
|
||||
|
||||
if (strcmp(argv[0], "-ftproot") == 0) { /* -ftproot string */
|
||||
if (2 > argc) {
|
||||
return 0;
|
||||
}
|
||||
rfbLog("ftproot is set to <%s>\n", argv[1]);
|
||||
if(SetFtpRoot(argv[1]) == FALSE) {
|
||||
rfbLog("ERROR:: Path specified for ftproot in invalid\n");
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
} else if (strcmp(argv[0], "-disablefiletransfer") == 0) {
|
||||
EnableFileTransfer(FALSE);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method should be registered to libvncserver to handle rfbSecTypeTight security type.
|
||||
*/
|
||||
void
|
||||
rfbHandleSecTypeTight(rfbClientPtr cl) {
|
||||
|
||||
rfbTightClientPtr rtcp = (rfbTightClientPtr) malloc(sizeof(rfbTightClientRec));
|
||||
|
||||
if(rtcp == NULL) {
|
||||
// Error condition close socket
|
||||
rfbLog("Memory error has occured while handling Tight security type... closing connection.\n");
|
||||
rfbCloseClient(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(rtcp, 0, sizeof(rfbTightClientRec));
|
||||
rtcp->rcft.rcfd.downloadFD = -1;
|
||||
rtcp->rcft.rcfu.uploadFD = -1;
|
||||
rfbEnableExtension(cl, &tightVncFileTransferExtension, rtcp);
|
||||
|
||||
rfbSendTunnelingCaps(cl);
|
||||
|
||||
}
|
||||
|
||||
rfbProtocolExtension tightVncFileTransferExtension = {
|
||||
NULL,
|
||||
rfbTightExtensionInit,
|
||||
rfbTightExtensionMsgHandler,
|
||||
rfbTightExtensionClientClose,
|
||||
rfbTightUsage,
|
||||
rfbTightProcessArg,
|
||||
NULL
|
||||
};
|
||||
|
||||
static rfbSecurityHandler tightVncSecurityHandler = {
|
||||
rfbSecTypeTight,
|
||||
rfbHandleSecTypeTight,
|
||||
NULL
|
||||
};
|
||||
|
||||
void rfbRegisterTightVNCFileTransferExtension() {
|
||||
rfbRegisterProtocolExtension(&tightVncFileTransferExtension);
|
||||
rfbRegisterSecurityHandler(&tightVncSecurityHandler);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in new issue