Added the file transfer feature to the server side.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@534 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/rfb/FileManager.cxx b/rfb/FileManager.cxx
index be1d2a8..74cbd45 100644
--- a/rfb/FileManager.cxx
+++ b/rfb/FileManager.cxx
@@ -73,3 +73,9 @@
 {
   if (m_pFile != NULL) return true; else return false;
 }
+
+char *
+FileManager::getFilename()
+{
+  return m_szFilename;
+}
diff --git a/rfb/FileManager.h b/rfb/FileManager.h
index f4e8596..4fd736f 100644
--- a/rfb/FileManager.h
+++ b/rfb/FileManager.h
@@ -39,6 +39,8 @@
     
     bool isCreated();
 
+    char *getFilename();
+
   protected:
     FILE *m_pFile;
     char m_szMode[4];
diff --git a/rfb/SFTMsgReader.cxx b/rfb/SFTMsgReader.cxx
index 2a5d283..b88467b 100644
--- a/rfb/SFTMsgReader.cxx
+++ b/rfb/SFTMsgReader.cxx
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/rfb/SFTMsgReader.h b/rfb/SFTMsgReader.h
index 8eaf429..dff06a4 100644
--- a/rfb/SFTMsgReader.h
+++ b/rfb/SFTMsgReader.h
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/rfb/SFTMsgWriter.cxx b/rfb/SFTMsgWriter.cxx
index dfd0ad5..fa6a82f 100644
--- a/rfb/SFTMsgWriter.cxx
+++ b/rfb/SFTMsgWriter.cxx
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/rfb/SFTMsgWriter.h b/rfb/SFTMsgWriter.h
index dcf2e2d..f6bea9f 100644
--- a/rfb/SFTMsgWriter.h
+++ b/rfb/SFTMsgWriter.h
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/rfb/SFileTransfer.cxx b/rfb/SFileTransfer.cxx
new file mode 100644
index 0000000..e947a74
--- /dev/null
+++ b/rfb/SFileTransfer.cxx
@@ -0,0 +1,334 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *    

+ * Developed by Dennis Syrovatsky

+ *

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransfer.cxx

+

+#include <rfb/msgTypes.h>

+#include <rfb/SFileTransfer.h>

+

+using namespace rfb;

+

+SFileTransfer::SFileTransfer(network::Socket *sock) : 

+  m_pSocket(sock), m_reader(&sock->inStream()), m_writer(&sock->outStream()),

+  m_bUploadStarted(false), m_bDownloadStarted(false)

+{

+}

+

+SFileTransfer::~SFileTransfer()

+{

+}

+

+bool

+SFileTransfer::processMessages(int type)

+{

+  switch(type)

+  {

+    case msgTypeFileListRequest:

+      return processFileListRequest();

+    case msgTypeFileDownloadRequest:

+      return processFileDownloadRequest();

+    case msgTypeFileUploadRequest:

+      return processFileUploadRequest();

+    case msgTypeFileUploadData:

+      return processFileUploadData();

+    case msgTypeFileDownloadCancel:

+      return processFileDownloadCancel();

+    case msgTypeFileUploadFailed:

+      return processFileUploadFailed();

+    case msgTypeFileCreateDirRequest:

+      return processFileCreateDirRequest();

+    case msgTypeFileDirSizeRequest:

+      return processFileDirSizeRequest();

+    case msgTypeFileRenameRequest:

+      return processFileRenameRequest();

+    case msgTypeFileDeleteRequest:

+      return processFileDeleteRequest();

+    default:

+      return false;

+  }

+}

+

+bool 

+SFileTransfer::processFileListRequest()

+{

+  char szDirName[FT_FILENAME_SIZE] = {0};

+  unsigned int dirNameSize = FT_FILENAME_SIZE;

+  unsigned int flags = 0;

+

+  if (!m_reader.readFileListRqst(&dirNameSize, szDirName, &flags)) return false;

+

+  if (!convertPathFromNet(szDirName)) return false;

+

+  bool bDirOnly = false;

+  if (flags & 0x10) bDirOnly = true;

+

+  FileInfo fi;

+  if (!makeFileList(szDirName, &fi, bDirOnly)) return false;

+

+  return m_writer.writeFileListData((unsigned char)flags, &fi);

+}

+

+bool 

+SFileTransfer::processFileDownloadRequest()

+{

+  char szName[FT_FILENAME_SIZE] = {0};

+  unsigned int nameSize = FT_FILENAME_SIZE;

+  unsigned int position = 0;

+

+  if (!m_reader.readFileDownloadRqst(&nameSize, szName, &position)) return false;

+

+  if (!convertPathFromNet(szName)) return false;

+

+  if (m_bDownloadStarted) {

+    char reason[] = "The download is already started";

+    m_writer.writeFileLastRqstFailed(msgTypeFileDownloadRequest, strlen(reason), reason);

+    return false;

+  }

+

+  if (!m_fileReader.create(szName)) return false;

+

+  m_bDownloadStarted = true;

+

+  sendFileDownloadPortion();

+

+  return true;

+}

+

+bool

+SFileTransfer::sendFileDownloadPortion()

+{

+  char buffer[FT_MAX_SENDING_SIZE];

+  unsigned int bytesRead = 0;

+

+  if (m_fileReader.read((void *)buffer, FT_MAX_SENDING_SIZE, &bytesRead)) {

+    if (bytesRead == 0) {

+      m_writer.writeFileDownloadData(m_fileReader.getTime());

+      m_fileReader.close();

+      m_bDownloadStarted = false;

+      return true;

+    } else {

+      m_writer.writeFileDownloadData(bytesRead, buffer);

+      return initDownloadCallback();

+    }

+  } else {

+    char reason[] = "Error while reading from file";

+    m_writer.writeFileDownloadFailed(strlen(reason), reason);

+    m_fileReader.close();

+    m_bDownloadStarted = false;

+    return true;

+  }

+}

+

+bool 

+SFileTransfer::processFileUploadRequest()

+{

+  char szName[FT_FILENAME_SIZE] = {0};

+  unsigned int nameSize = FT_FILENAME_SIZE;

+  unsigned int position = 0;

+

+  if (!m_reader.readFileUploadRqst(&nameSize, szName, &position)) return false;

+

+  if (!convertPathFromNet(szName)) return false;

+

+  if (m_bUploadStarted) {

+    char reason[] = "The upload is already started";

+    m_writer.writeFileLastRqstFailed(msgTypeFileUploadRequest, strlen(reason), reason);

+    return false;

+  }

+

+  if (!m_fileWriter.create(szName)) {

+    char reason[] = "Can't create local file";

+    m_writer.writeFileLastRqstFailed(msgTypeFileUploadRequest, strlen(reason), reason);

+    return true;

+  }

+

+  m_bUploadStarted = true;

+

+  return true;

+}

+

+bool 

+SFileTransfer::processFileUploadData()

+{

+  unsigned int dataSize = 0;

+  unsigned int modTime = 0;

+

+  void *pUploadData = m_reader.readFileUploadData(&dataSize, &modTime);

+

+  if (!m_bUploadStarted) {

+      char reason[] = "Upload is impossible";

+      m_writer.writeFileUploadCancel(strlen(reason), reason);

+  } else {

+    if (pUploadData == NULL) {

+      if (modTime == 0) {

+        char reason[] = "Upload failed";

+        m_writer.writeFileUploadCancel(strlen(reason), reason);

+      } else {

+        m_fileWriter.setTime(modTime);

+      }

+      m_fileWriter.close();

+      m_bUploadStarted = false;

+    } else {

+      unsigned int dataWritten = 0;

+      m_fileWriter.write(pUploadData, dataSize, &dataWritten);

+      if (dataWritten != dataSize) {

+        char reason[] = "Upload failed";

+        m_writer.writeFileUploadCancel(strlen(reason), reason);

+        m_fileWriter.close();

+        m_bUploadStarted = false;

+      }

+    }

+  }

+  delete [] pUploadData;

+  return true;

+}

+

+bool 

+SFileTransfer::processFileDownloadCancel()

+{

+  char szReason[FT_FILENAME_SIZE] = {0};

+  unsigned int reasonSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileDownloadCancel(&reasonSize, szReason)) return false;

+

+  m_fileReader.close();

+  m_bDownloadStarted = false;

+  return true;

+}

+

+bool 

+SFileTransfer::processFileUploadFailed()

+{

+  char szReason[FT_FILENAME_SIZE] = {0};

+  unsigned int reasonSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileUploadFailed(&reasonSize, szReason)) return false;

+

+  deleteIt(m_fileWriter.getFilename());

+  m_fileWriter.close();

+  m_bUploadStarted = false;

+  return true;

+}

+

+bool 

+SFileTransfer::processFileCreateDirRequest()

+{

+  char szName[FT_FILENAME_SIZE] = {0};

+  unsigned int nameSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileCreateDirRqst(&nameSize, szName)) return false;

+

+  if (!convertPathFromNet(szName)) return false;

+

+  return createDir(szName);

+}

+

+bool 

+SFileTransfer::processFileDirSizeRequest()

+{

+  char szName[FT_FILENAME_SIZE] = {0};

+  unsigned int nameSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileDirSizeRqst(&nameSize, szName)) return false;

+

+  if (!convertPathFromNet(szName)) return false;

+

+  unsigned short highSize16 = 0;

+  unsigned int lowSize32 = 0;

+

+  if (!getDirSize(szName, &highSize16, &lowSize32)) return false;

+

+  return m_writer.writeFileDirSizeData(lowSize32, highSize16);

+}

+

+bool 

+SFileTransfer::processFileRenameRequest()

+{

+  char szOldName[FT_FILENAME_SIZE] = {0};

+  char szNewName[FT_FILENAME_SIZE] = {0};

+

+  unsigned int oldNameSize = FT_FILENAME_SIZE;

+  unsigned int newNameSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileRenameRqst(&oldNameSize, &newNameSize, szOldName, szNewName)) return false;

+

+  if ((!convertPathFromNet(szOldName)) || (!convertPathFromNet(szNewName))) return false;

+

+  return renameIt(szOldName, szNewName);

+}

+

+bool 

+SFileTransfer::processFileDeleteRequest()

+{

+  char szName[FT_FILENAME_SIZE] = {0};

+  unsigned int nameSize = FT_FILENAME_SIZE;

+

+  if (!m_reader.readFileDeleteRqst(&nameSize, szName)) return false;

+

+  if (!convertPathFromNet(szName)) return false;

+

+  return deleteIt(szName);

+}

+

+bool 

+SFileTransfer::convertPathFromNet(char *pszPath)

+{

+  return true;

+}

+

+bool 

+SFileTransfer::makeFileList(char *pszPath, FileInfo *pFI, bool bDirOnly)

+{

+  return false;

+}

+

+bool 

+SFileTransfer::deleteIt(char *pszPath)

+{

+  return false;

+}

+

+bool 

+SFileTransfer::renameIt(char *pszOldPath, char *pszNewPath)

+{

+  return false;

+}

+

+bool 

+SFileTransfer::createDir(char *pszPath)

+{

+  return false;

+}

+

+bool 

+SFileTransfer::getDirSize(char *pszName, unsigned short *pHighSize16, 

+                          unsigned int *pLowSize32)

+{

+  return false;

+}

+

+bool

+SFileTransfer::initDownloadCallback()

+{

+  return false;

+}

diff --git a/rfb/SFileTransfer.h b/rfb/SFileTransfer.h
new file mode 100644
index 0000000..9328ead
--- /dev/null
+++ b/rfb/SFileTransfer.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransfer.h

+

+#ifndef __RFB_SFILETRANSFER_H__

+#define __RFB_SFILETRANSFER_H__

+

+#include <network/Socket.h>

+#include <rfb/SFTMsgReader.h>

+#include <rfb/SFTMsgWriter.h>

+#include <rfb/FileWriter.h>

+#include <rfb/FileReader.h>

+#include <rfb/FileInfo.h>

+#include <rfb/fttypes.h>

+

+namespace rfb {

+  class SFileTransfer

+  {

+  public:

+    SFileTransfer(network::Socket *sock);

+    ~SFileTransfer();

+

+	bool processMessages(int type);

+    bool sendFileDownloadPortion();

+

+  protected:

+    bool processFileListRequest();

+    bool processFileDownloadRequest();

+    bool processFileUploadRequest();

+    bool processFileUploadData();

+    bool processFileDownloadCancel();

+    bool processFileUploadFailed();

+    bool processFileCreateDirRequest();

+    bool processFileDirSizeRequest();

+    bool processFileRenameRequest();

+    bool processFileDeleteRequest();

+

+    virtual bool initDownloadCallback();

+    virtual bool makeFileList(char *pszPath, FileInfo *pFI, bool bDirOnly);

+    virtual bool convertPathFromNet(char *pszPath);

+

+    virtual bool deleteIt(char *pszPath);

+    virtual bool renameIt(char *pszOldPath, char *pszNewPath);

+    virtual bool createDir(char *pszPath);

+

+    virtual bool getDirSize(char *pszName, unsigned short *pHighSize16, unsigned int *pLowSize32);

+

+    bool m_bUploadStarted;

+    bool m_bDownloadStarted;

+    

+  private:

+    SFTMsgReader m_reader;

+    SFTMsgWriter m_writer;

+

+    FileWriter m_fileWriter;

+    FileReader m_fileReader;

+

+    network::Socket *m_pSocket;

+  };

+}

+

+#endif // __RFB_SFILETRANSFER_H__

diff --git a/rfb/SFileTransferManager.cxx b/rfb/SFileTransferManager.cxx
new file mode 100644
index 0000000..c13e0c1
--- /dev/null
+++ b/rfb/SFileTransferManager.cxx
@@ -0,0 +1,55 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferManager.cxx

+

+#include <rfb/SFileTransferManager.h>

+

+using namespace rfb;

+

+SFileTransferManager::SFileTransferManager()

+{

+

+}

+

+SFileTransferManager::~SFileTransferManager()

+{

+  destroy();

+}

+

+void

+SFileTransferManager::destroyObject(SFileTransfer *pFT)

+{

+  if (pFT == NULL) return;

+

+  m_lstFTObjects.remove(pFT);

+

+  delete pFT;

+}

+

+void

+SFileTransferManager::destroy()

+{

+  while(!m_lstFTObjects.empty())

+    delete m_lstFTObjects.front();

+}
\ No newline at end of file
diff --git a/rfb/SFileTransferManager.h b/rfb/SFileTransferManager.h
new file mode 100644
index 0000000..107d144
--- /dev/null
+++ b/rfb/SFileTransferManager.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferManager.h

+

+#ifndef __RFB_SFILETRANSFERMANAGER_H__

+#define __RFB_SFILETRANSFERMANAGER_H__

+

+#include <list>

+

+#include <rfb/SFileTransfer.h>

+#include <network/Socket.h>

+

+namespace rfb {

+  class SFileTransferManager

+  {

+  public:

+    SFileTransferManager();

+    ~SFileTransferManager();

+

+    virtual SFileTransfer *createObject(network::Socket *sock) = 0;

+    void destroyObject(SFileTransfer *pFT);

+

+  protected:

+    std::list<SFileTransfer*> m_lstFTObjects;

+

+    void destroy();

+  };

+}

+

+#endif // __RFB_SFILETRANSFERMANAGER_H__

diff --git a/rfb/VNCSConnectionST.cxx b/rfb/VNCSConnectionST.cxx
index 9895761..e7bc09f 100644
--- a/rfb/VNCSConnectionST.cxx
+++ b/rfb/VNCSConnectionST.cxx
@@ -35,7 +35,7 @@
     image_getter(server->useEconomicTranslate),
     drawRenderedCursor(false), removeRenderedCursor(false),
     pointerEventTime(0), accessRights(AccessDefault),
-    startTime(time(0))
+    startTime(time(0)), m_pFileTransfer(0)
 {
   setStreams(&sock->inStream(), &sock->outStream());
   peerEndpoint.buf = sock->getPeerEndpoint();
@@ -56,6 +56,13 @@
     addSecType(*i);
   }
 
+  if (server->m_pFTManager != NULL) {
+    SFileTransfer *pFT = server->m_pFTManager->createObject(sock);
+    if (pFT != NULL) {
+      m_pFileTransfer = pFT;
+    }
+  }
+
   server->clients.push_front(this);
 }
 
@@ -73,8 +80,12 @@
   if (server->pointerClient == this)
     server->pointerClient = 0;
 
+  if (m_pFileTransfer) 
+    server->m_pFTManager->destroyObject(m_pFileTransfer);
+
   // Remove this client from the server
   server->clients.remove(this);
+
 }
 
 
@@ -671,16 +682,13 @@
 
 char* VNCSConnectionST::getStartTime()
 {
-  // FIXME: Using ctime() is not thread-safe.
-  //        Also, it's not good to return the pointer instead of copying.
   char* result = ctime(&startTime);
   result[24] = '\0';
-  return result;
+  return result; 
 }
 
 void VNCSConnectionST::setStatus(int status)
 {
-  // FIXME: What do numbers mean?
   switch (status) {
   case 0:
     accessRights = accessRights | AccessPtrEvents | AccessKeyEvents | AccessView;
@@ -694,10 +702,8 @@
   }
   framebufferUpdateRequest(server->pb->getRect(), false);
 }
-
 int VNCSConnectionST::getStatus()
 {
-  // FIXME: What do numbers mean?
   if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0007)
     return 0;
   if ((accessRights & (AccessPtrEvents | AccessKeyEvents | AccessView)) == 0x0001)
@@ -709,5 +715,8 @@
 
 bool VNCSConnectionST::processFTMsg(int type)
 {
-  return false;
+  if (m_pFileTransfer != NULL) 
+    return m_pFileTransfer->processMessages(type);
+  else 
+    return false;
 }
diff --git a/rfb/VNCSConnectionST.h b/rfb/VNCSConnectionST.h
index 7813c04..99aaf3b 100644
--- a/rfb/VNCSConnectionST.h
+++ b/rfb/VNCSConnectionST.h
@@ -31,6 +31,7 @@
 #include <rfb/SMsgWriter.h>
 #include <rfb/TransImageGetter.h>
 #include <rfb/VNCServerST.h>
+#include <rfb/SFileTransfer.h>
 
 namespace rfb {
   class VNCSConnectionST : public SConnection,
@@ -171,6 +172,8 @@
 
     CharArray closeReason;
     time_t startTime;
+
+    SFileTransfer *m_pFileTransfer;
   };
 }
 #endif
diff --git a/rfb/VNCServerST.h b/rfb/VNCServerST.h
index 3d25fca..9d5fe95 100644
--- a/rfb/VNCServerST.h
+++ b/rfb/VNCServerST.h
@@ -33,6 +33,7 @@
 #include <rfb/Cursor.h>
 #include <network/Socket.h>
 #include <rfb/ListConnInfo.h>
+#include <rfb/SFileTransferManager.h>
 
 namespace rfb {
 
@@ -111,7 +112,6 @@
 
     void addClient(network::Socket* sock, bool reverse);
 
-
     // getSockets() gets a list of sockets.  This can be used to generate an
     // fd_set for calling select().
 
@@ -191,8 +191,10 @@
     void getConnInfo(ListConnInfo * listConn);
     void setConnStatus(ListConnInfo* listConn);
 
-    bool getDisable() { return disableclients; }
-    void setDisable(bool disable) { disableclients = disable; }
+    bool getDisable() { return disableclients;};
+    void setDisable(bool disable) { disableclients = disable;};
+
+    void setFTManager(rfb::SFileTransferManager *pFTManager) { m_pFTManager = pFTManager; };
 
   protected:
 
@@ -208,6 +210,8 @@
     bool desktopStarted;
     PixelBuffer* pb;
 
+    SFileTransferManager *m_pFTManager;
+
     CharArray name;
 
     std::list<VNCSConnectionST*> clients;
diff --git a/rfb/fttypes.h b/rfb/fttypes.h
index 9cfbb29..4404508 100644
--- a/rfb/fttypes.h
+++ b/rfb/fttypes.h
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/rfb/rfb.dsp b/rfb/rfb.dsp
index bac1e00..b38f266 100644
--- a/rfb/rfb.dsp
+++ b/rfb/rfb.dsp
@@ -270,6 +270,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=.\SFileTransfer.cxx

+# End Source File

+# Begin Source File

+

+SOURCE=.\SFileTransferManager.cxx

+# End Source File

+# Begin Source File

+

 SOURCE=.\SFTMsgReader.cxx

 # End Source File

 # Begin Source File

@@ -608,6 +616,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=.\SFileTransfer.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\SFileTransferManager.h

+# End Source File

+# Begin Source File

+

 SOURCE=.\SFTMsgReader.h

 # End Source File

 # Begin Source File

diff --git a/rfb_win32/SFileTransferManagerWin32.cxx b/rfb_win32/SFileTransferManagerWin32.cxx
new file mode 100644
index 0000000..000b372
--- /dev/null
+++ b/rfb_win32/SFileTransferManagerWin32.cxx
@@ -0,0 +1,71 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferManagerWin32.cxx

+

+#include <rfb_win32/SFileTransferManagerWin32.h>

+

+using namespace rfb;

+using namespace win32;

+

+SFileTransferManagerWin32::SFileTransferManagerWin32()

+{

+

+}

+

+SFileTransferManagerWin32::~SFileTransferManagerWin32()

+{

+

+}

+

+SFileTransfer *

+SFileTransferManagerWin32::createObject(network::Socket *sock)

+{

+  rfb::SFileTransfer *pFT = 0;

+  rfb::win32::SFileTransferWin32 *pFTWin32 = 0;

+

+  pFTWin32 = new SFileTransferWin32(sock);

+  if (pFTWin32 == NULL) return NULL;

+

+  pFT = (SFileTransfer *) pFTWin32;

+

+  m_lstFTObjects.push_front(pFT);

+

+  return pFT;

+}

+

+void 

+SFileTransferManagerWin32::processDownloadMsg(MSG msg)

+{

+  SFileTransfer *pFT = (SFileTransfer *)msg.lParam;

+

+  if (pFT != NULL) {

+    std::list<SFileTransfer*>::iterator i;

+    for (i=m_lstFTObjects.begin(); i!=m_lstFTObjects.end(); i++) {

+      if ((*i) == pFT) {

+        (*i)->sendFileDownloadPortion();

+        return;

+      }

+    }

+  }

+}

diff --git a/rfb_win32/SFileTransferManagerWin32.h b/rfb_win32/SFileTransferManagerWin32.h
new file mode 100644
index 0000000..6014f38
--- /dev/null
+++ b/rfb_win32/SFileTransferManagerWin32.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferManagerWin32.h

+

+#ifndef __RFB_WIN32_SFILETRANSFERMANAGERWIN32_H__

+#define __RFB_WIN32_SFILETRANSFERMANAGERWIN32_H__

+

+#include <rfb/SFileTransfer.h>

+#include <rfb/SFileTransferManager.h>

+#include <rfb_win32/SFileTransferWin32.h>

+

+namespace rfb {

+  namespace win32 {

+    class SFileTransferManagerWin32 : public rfb::SFileTransferManager

+    {

+    public:

+      SFileTransferManagerWin32();

+      ~SFileTransferManagerWin32();  

+      

+      void processDownloadMsg(MSG msg);

+

+      virtual SFileTransfer *createObject(network::Socket *sock);

+    };

+  };

+}

+

+#endif // __RFB_WIN32_SFILETRANSFERMANAGERWIN32_H__

diff --git a/rfb_win32/SFileTransferWin32.cxx b/rfb_win32/SFileTransferWin32.cxx
new file mode 100644
index 0000000..5a33a43
--- /dev/null
+++ b/rfb_win32/SFileTransferWin32.cxx
@@ -0,0 +1,125 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferWin32.cxx

+

+#include <rfb/msgTypes.h>

+#include <rfb_win32/FolderManager.h>

+#include <rfb_win32/SFileTransferWin32.h>

+

+using namespace rfb;

+using namespace rfb::win32;

+

+SFileTransferWin32::SFileTransferWin32(network::Socket *sock) : SFileTransfer(sock)

+{

+}

+

+SFileTransferWin32::~SFileTransferWin32()

+{

+}

+

+bool 

+SFileTransferWin32::initDownloadCallback()

+{

+  PostThreadMessage(GetCurrentThreadId(), VNCM_FT_DOWNLOAD, (WPARAM) 0, (LPARAM) this);

+  return true;

+}

+

+bool 

+SFileTransferWin32::processDownloadCallback()

+{

+  return sendFileDownloadPortion();

+}

+

+bool 

+SFileTransferWin32::convertPathFromNet(char *pszPath)

+{

+  int len = strlen(pszPath);

+  if (pszPath[0] == '/') {

+    if (len == 1) { 

+      pszPath[0] = '\0'; 

+      return true; 

+    }

+  } else {

+    return false;

+  }

+

+  for(int i = 0; i < (len - 1); i++) {

+    if(pszPath[i+1] == '/') pszPath[i+1] = '\\';

+    pszPath[i] = pszPath[i+1];

+  }

+

+  pszPath[len-1] = '\0';

+  return true;

+}

+

+bool 

+SFileTransferWin32::makeFileList(char *pszPath, FileInfo *pFI, bool bDirOnly)

+{

+  FolderManager fm;

+  if (fm.getDirInfo(pszPath, pFI, bDirOnly)) 

+    return true; 

+  else 

+    return false;

+}

+

+bool 

+SFileTransferWin32::deleteIt(char *pszPath)

+{

+  FolderManager fm;

+

+  return fm.deleteIt(pszPath);

+}

+

+bool 

+SFileTransferWin32::renameIt(char *pszOldPath, char *pszNewPath)

+{

+  FolderManager fm;

+

+  return fm.renameIt(pszOldPath, pszNewPath);

+}

+

+bool 

+SFileTransferWin32::createDir(char *pszPath)

+{

+  FolderManager fm;

+

+  return fm.createDir(pszPath);

+}

+

+bool 

+SFileTransferWin32::getDirSize(char *pszName, unsigned short *pHighSize16, 

+                               unsigned int *pLowSize32)

+{

+  FolderManager fm;

+  DWORD64 dw64DirSize = 0;

+

+  if (!fm.getDirSize(pszName, &dw64DirSize)) return false;

+

+  if (dw64DirSize & 0xFFFF000000000000) return false;

+

+  *pHighSize16 = ((dw64DirSize & 0x0000FFFF00000000) >> 32);

+  *pLowSize32 = (dw64DirSize & 0x00000000FFFFFFFF);

+

+  return true;

+}

diff --git a/rfb_win32/SFileTransferWin32.h b/rfb_win32/SFileTransferWin32.h
new file mode 100644
index 0000000..b2a5c57
--- /dev/null
+++ b/rfb_win32/SFileTransferWin32.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2006 TightVNC Team.  All Rights Reserved.

+ *

+ * Developed by Dennis Syrovatsky.

+ *    

+ * This is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * This software 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 software; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,

+ * USA.

+ *

+ * TightVNC distribution homepage on the Web: http://www.tightvnc.com/

+ *

+ */

+

+// -=- SFileTransferWin32.h

+

+#ifndef __RFB_SFILETRANSFERWIN32_H__

+#define __RFB_SFILETRANSFERWIN32_H__

+

+#include <windows.h>

+

+#include <rfb/SFileTransfer.h>

+

+const UINT VNCM_FT_DOWNLOAD = WM_USER + 2;

+

+namespace rfb {

+  namespace win32 {

+    class SFileTransferWin32 : public rfb::SFileTransfer

+    {

+    public:

+      SFileTransferWin32(network::Socket *sock);

+      ~SFileTransferWin32();

+

+      bool processDownloadCallback();

+      virtual bool initDownloadCallback();

+

+      virtual bool convertPathFromNet(char *pszPath);

+      virtual bool makeFileList(char *pszPath, FileInfo *pFI, bool bDirOnly);

+  

+      virtual bool deleteIt(char *pszPath);

+      virtual bool renameIt(char *pszOldPath, char *pszNewPath);

+      virtual bool createDir(char *pszPath);

+

+      virtual bool getDirSize(char *pszName, unsigned short *pHighSize16, unsigned int *pLowSize32);

+

+    };

+  };

+}

+

+#endif // __RFB_SFILETRANSFERWIN32_H__

diff --git a/rfb_win32/rfb_win32.dsp b/rfb_win32/rfb_win32.dsp
index de7f840..e9b746c 100644
--- a/rfb_win32/rfb_win32.dsp
+++ b/rfb_win32/rfb_win32.dsp
@@ -190,6 +190,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=.\SFileTransferManagerWin32.cxx

+# End Source File

+# Begin Source File

+

+SOURCE=.\SFileTransferWin32.cxx

+# End Source File

+# Begin Source File

+

 SOURCE=.\SInput.cxx

 # End Source File

 # Begin Source File

@@ -330,6 +338,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=.\SFileTransferManagerWin32.h

+# End Source File

+# Begin Source File

+

+SOURCE=.\SFileTransferWin32.h

+# End Source File

+# Begin Source File

+

 SOURCE=.\SInput.h

 # End Source File

 # Begin Source File

diff --git a/vncviewer/FTListView.h b/vncviewer/FTListView.h
index 5f4fd64..c920fa0 100644
--- a/vncviewer/FTListView.h
+++ b/vncviewer/FTListView.h
@@ -1,4 +1,6 @@
 /* Copyright (C) 2005 TightVNC Team.  All Rights Reserved.
+ *
+ * Developed by Dennis Syrovatsky.
  *    
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/winvnc/VNCServerWin32.cxx b/winvnc/VNCServerWin32.cxx
index 67b3ec5..5b2adbe 100644
--- a/winvnc/VNCServerWin32.cxx
+++ b/winvnc/VNCServerWin32.cxx
@@ -27,6 +27,7 @@
 #include <rfb/SSecurityFactoryStandard.h>
 #include <rfb/Hostname.h>
 #include <rfb/LogWriter.h>
+#include <rfb_win32/SFileTransferWin32.h>
 
 using namespace rfb;
 using namespace win32;
@@ -41,6 +42,8 @@
 const UINT VNCM_REG_CHANGED = WM_USER;
 const UINT VNCM_COMMAND = WM_USER + 1;
 
+extern const UINT VNCM_FT_DOWNLOAD;
+
 
 static IntParameter http_port("HTTPPortNumber",
   "TCP/IP port on which the server will serve the Java applet VNC Viewer ", 5800);
@@ -130,6 +133,8 @@
 
   // Register the desktop's event to be handled
   sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
+
+  vncServer.setFTManager((rfb::SFileTransferManager *)&m_FTManager);
 }
 
 VNCServerWin32::~VNCServerWin32() {
@@ -220,6 +225,8 @@
             break;
           if (msg.message == VNCM_COMMAND)
             doCommand();
+          if (msg.message == VNCM_FT_DOWNLOAD)
+            m_FTManager.processDownloadMsg(msg);
         }
         TranslateMessage(&msg);
         DispatchMessage(&msg);
diff --git a/winvnc/VNCServerWin32.h b/winvnc/VNCServerWin32.h
index 0af5fd5..9cc0f1e 100644
--- a/winvnc/VNCServerWin32.h
+++ b/winvnc/VNCServerWin32.h
@@ -26,6 +26,7 @@
 #include <rfb_win32/SDisplay.h>
 #include <rfb_win32/SocketManager.h>
 #include <rfb_win32/TCharArray.h>
+#include <rfb_win32/SFileTransferManagerWin32.h>
 #include <winvnc/QueryConnectDialog.h>
 #include <winvnc/JavaViewer.h>
 //#include <rfb/ListConnInfo.h>
@@ -97,6 +98,7 @@
     rfb::win32::RegistryReader config;
     rfb::win32::SocketManager sockMgr;
     QueryConnectDialog* queryConnectDialog;
+    rfb::win32::SFileTransferManagerWin32 m_FTManager;
   };
 
 };