protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(500, string.Format("{0} needs a paramter", Command)));
            }

            string dirToMake = GetPath(FileNameHelpers.AppendDirTag(sMessage));

            // check directory name
            if (!FileNameHelpers.IsValid(dirToMake))
            {
                FtpServer.LogWrite(this, sMessage, 553, 0);
                return(GetMessage(553, string.Format("\"{0}\": Invalid directory name", sMessage)));
            }
            // check whether directory already exists
            if (ConnectionObject.FileSystemObject.DirectoryExists(dirToMake))
            {
                FtpServer.LogWrite(this, sMessage, 553, 0);
                return(GetMessage(553, string.Format("Directory \"{0}\" already exists", sMessage)));
            }
            // create directory
            if (!ConnectionObject.FileSystemObject.CreateDirectory(dirToMake))
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("Couldn't create directory. ({0})", sMessage)));
            }

            FtpServer.LogWrite(this, sMessage, 257, 0);
            return(GetMessage(257, string.Format("{0} successful \"{1}\".", Command, dirToMake)));
        }
예제 #2
0
        protected override string OnProcess(string sMessage)
        {
            string sDirectory = ConnectionObject.CurrentDirectory;

            FtpServer.LogWrite(this, sMessage, 257, 0);
            return(GetMessage(257, string.Format("\"{0}\" {1} Successful.", sDirectory, Command)));
        }
        public IFileSystem Create(string sUser, string sPassword)
        {
            if ((sUser == null) || (sPassword == null))
            {
                return(null);
            }

            FtpAccount account;

            if (!m_accountManager.CheckAccount(sUser, sPassword, out account))
            {
                return(null);
            }

            if (!account.WriteAccess && !account.ReadAccess)
            {
                FtpServer.LogWrite($"user {sUser} has neither read nor write permissions");
                return(null);
            }

            IFileSystem system = new AzureFileSystem(account.RootFolder ?? sUser);

            if (!account.WriteAccess)
            {
                system = new ReadOnlyFileSystem(system);
            }

            return(system);
        }
예제 #4
0
        protected override string OnProcess(string sMessage)
        {
            string[] args = sMessage.Split(' ');

            if (args.Length > 2 || args.Length < 1)
            {
                return(GetMessage(501, string.Format("Invalid TYPE parameter: {0}", sMessage)));
            }

            switch (args[0].ToUpper())
            {
            case "A":
                ConnectionObject.DataType = DataType.Ascii;
                if (args.Length == 1)
                {
                    FtpServer.LogWrite(this, sMessage, 200, 0);
                    return(GetMessage(200, string.Format("{0} command succeeded, data type is Ascii", Command)));
                }
                else
                {
                    switch (args[1].ToUpper())
                    {
                    case "N":
                        ConnectionObject.FormatControl = FormatControl.NonPrint;
                        FtpServer.LogWrite(this, sMessage, 200, 0);
                        return(GetMessage(200, string.Format("{0} command succeeded, data type is Ascii, format is NonPrint", Command)));

                    case "T":
                    case "C":
                        ConnectionObject.FormatControl = FormatControl.NonPrint;
                        FtpServer.LogWrite(this, sMessage, 504, 0);
                        return(GetMessage(504, string.Format("Format {0} is not supported, use NonPrint format", args[1])));

                    default:
                        FtpServer.LogWrite(this, sMessage, 550, 0);
                        return(GetMessage(550, string.Format("Error - unknown format \"{0}\"", args[1])));
                    }
                }

            case "I":
                ConnectionObject.DataType = DataType.Image;
                FtpServer.LogWrite(this, sMessage, 200, 0);
                return(GetMessage(200, string.Format("{0} command succeeded, data type is Image (Binary)", Command)));

            case "E":
            case "L":
                ConnectionObject.DataType = DataType.Image;
                FtpServer.LogWrite(this, sMessage, 504, 0);
                return(GetMessage(504, string.Format("Data type {0} is not supported, use Image (Binary) type", args[0])));

            default:
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("Error - unknown data type \"{0}\"", args[1])));
            }
        }
예제 #5
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            ConnectionObject.User = sMessage;

            FtpServer.LogWrite(this, sMessage, 331, 0);
            return(GetMessage(331, string.Format("User {0} logged in, needs password", sMessage)));
        }
        protected override string OnProcess(string sMessage)
        {
            if (sMessage.Trim() != "")
            {
                return(GetMessage(501, "REIN needs no parameters"));
            }

            // log out current user
            ConnectionObject.LogOut();

            FtpServer.LogWrite(this, sMessage, 220, 0);
            return(GetMessage(220, "Service ready for new user!"));
        }
예제 #7
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage.Length == 0)
            {
                return(GetMessage(501, string.Format("Syntax error. {0} needs a parameter", Command)));
            }

            // append the final '/' char
            string sMessageFull = FileNameHelpers.AppendDirTag(sMessage);

            #region change to the parent dir
            if (sMessageFull == @"../")
            {
                // get the parent directory
                string parentDir = GetParentDir();
                if (parentDir == null)
                {
                    return(GetMessage(550, "Root directory, cannot change to the parent directory"));
                }

                ConnectionObject.CurrentDirectory = parentDir;
                FtpServer.LogWrite(this, sMessage, 200, 0);
                return(GetMessage(200, string.Format("{0} Successful ({1})", Command, parentDir)));
            }
            #endregion

            if (!FileNameHelpers.IsValid(sMessageFull))
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("\"{0}\" is not a valid directory string.", sMessage)));
            }

            // get the new directory path
            string newDirectory = GetPath(sMessageFull);

            // checks whether the new directory exists
            if (!ConnectionObject.FileSystemObject.DirectoryExists(newDirectory))
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("\"{0}\" no such directory.", sMessage)));
            }

            ConnectionObject.CurrentDirectory = newDirectory;
            FtpServer.LogWrite(this, sMessage, 250, 0);
            return(GetMessage(250, string.Format("{0} Successful ({1})", Command, newDirectory)));
        }
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, $"{Command} needs a parameter"));
            }

            string fileToDelete = GetPath(sMessage);

            Trace.TraceInformation($"DELE {fileToDelete} - BEGIN");
            Stopwatch sw = new Stopwatch();

            sw.Start();

            // 2015-11-24 cljung : Q&D fix. If path contains double slashes, reduce to single since
            //                     NTFS/etc treams sub1//sub2 as sub1/sub two but Azure Blob Storage doesn't
            if (ConnectionObject.FileSystemObject.FileExists(fileToDelete))
            {
                if (!StorageProviderConfiguration.FtpReplaceSlashOnDELE)
                {
                    fileToDelete = fileToDelete.Replace("//", "/");
                }
                else
                {
                    FtpServer.LogWrite(this, sMessage, 550, sw.ElapsedMilliseconds);
                    return(GetMessage(550, $"File \"{fileToDelete}\" does not exist."));
                }
            }

            if (!ConnectionObject.FileSystemObject.FileExists(fileToDelete))
            {
                FtpServer.LogWrite(this, sMessage, 550, sw.ElapsedMilliseconds);
                return(GetMessage(550, $"File \"{fileToDelete}\" does not exist."));
            }

            if (!ConnectionObject.FileSystemObject.DeleteFile(fileToDelete))
            {
                FtpServer.LogWrite(this, sMessage, 550, sw.ElapsedMilliseconds);
                return(GetMessage(550, $"Delete file \"{fileToDelete}\" failed."));
            }
            sw.Stop();
            Trace.TraceInformation($"DELE {fileToDelete} - END, Time {sw.ElapsedMilliseconds} ms");

            FtpServer.LogWrite(this, sMessage, 250, sw.ElapsedMilliseconds);
            return(GetMessage(250, $"{Command} successful. Time {sw.ElapsedMilliseconds} ms"));
        }
예제 #9
0
        protected override string OnProcess(string sMessage)
        {
            if (sMessage.Length != 0)
            {
                return(GetMessage(501, string.Format("Invalid syntax for {0} command", Command)));
            }

            // get the parent directory
            string parentDir = GetParentDir();

            if (parentDir == null)
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, "Root directory, cannot change to the parent directory"));
            }
            ConnectionObject.CurrentDirectory = parentDir;
            FtpServer.LogWrite(this, sMessage, 200, 0);
            return(GetMessage(200, string.Format("{0} Successful ({1})", Command, parentDir)));
        }
예제 #10
0
        protected override string OnProcess(string sMessage)
        {
            string[] asData = sMessage.Split(new[] { ',' });

            if (asData.Length != 6)
            {
                return(GetMessage(501, string.Format("{0}: Syntax error in parameters", Command)));
            }

            ConnectionObject.DataConnectionType = DataConnectionType.Active;

            int nSocketPort = int.Parse(asData[4]) * 256 + int.Parse(asData[5]);

            ConnectionObject.PortCommandSocketPort    = nSocketPort;
            ConnectionObject.PortCommandSocketAddress = string.Join(".", asData, 0, 4);

            FtpServer.LogWrite(this, sMessage, 200, 0);
            return(GetMessage(200, string.Format("{0} successful.", Command)));
        }
예제 #11
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            if (ConnectionObject.Login(sMessage))
            {
                FtpServer.LogWrite(this, "******", 220, 0);
                return(GetMessage(230, "Password ok, FTP server ready"));
            }
            else
            {
                FtpServer.LogWrite(this, "******", 530, 0);
                return(GetMessage(530, "Username or password incorrect"));
            }
        }
예제 #12
0
        protected override string OnProcess(string sMessage)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();
            if (ConnectionObject.FileToRename.Length == 0)
            {
                FtpServer.LogWrite(this, sMessage, 503, 0);
                return(GetMessage(503, "RNTO must be preceded by a RNFR."));
            }

            string sOldFileName = ConnectionObject.FileToRename;

            ConnectionObject.FileToRename = ""; // note:

            sMessage = sMessage.Trim();
            string sNewFileName = GetPath(sMessage);

            // check whether the new filename is valid
            if (!FileNameHelpers.IsValid(sNewFileName) || sNewFileName.EndsWith(@"/"))
            {
                FtpServer.LogWrite(this, sMessage, 553, 0);
                return(GetMessage(553, string.Format("\"{0}\" is not a valid file name", sMessage)));
            }

            // check whether the new filename exists
            // note: azure allows file&virtualdir has the same name
            if (ConnectionObject.FileSystemObject.FileExists(sNewFileName))
            {
                FtpServer.LogWrite(this, sMessage, 553, sw.ElapsedMilliseconds);
                return(GetMessage(553, string.Format("File already exists ({0}).", sMessage)));
            }

            if (!ConnectionObject.FileSystemObject.Move(sOldFileName, sNewFileName))
            {
                FtpServer.LogWrite(this, sMessage, 553, sw.ElapsedMilliseconds);
                return(GetMessage(553, "Rename failed"));
            }

            FtpServer.LogWrite(this, sMessage, 250, sw.ElapsedMilliseconds);
            return(GetMessage(250, "Renamed file successfully."));
        }
예제 #13
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            string sFile = GetPath(sMessage);

            Stopwatch sw = new Stopwatch();

            sw.Start();
            if (!FileNameHelpers.IsValid(sFile))
            {
                FtpServer.LogWrite(this, sMessage, 553, sw.ElapsedMilliseconds);
                return(GetMessage(553, string.Format("\"{0}\" is not a valid file name", sMessage)));
            }

            var socketData = new FtpDataSocket(ConnectionObject);

            if (!socketData.Loaded)
            {
                return(GetMessage(425, "Unable to establish the data connection"));
            }

            SocketHelpers.Send(ConnectionObject.Socket, GetMessage(150, "Opening connection for data transfer."), ConnectionObject.Encoding);

            if (!ConnectionObject.FileSystemObject.AppendFile(sFile, socketData.Socket.GetStream()))
            {
                FtpServer.LogWrite(this, sMessage, 553, sw.ElapsedMilliseconds);
                return(GetMessage(553, string.Format("{0} error", Command)));
            }

            // remove the orginal blob ContentMD5
            ConnectionObject.FileSystemObject.SetFileMd5(sFile, string.Empty);

            sw.Stop();
            FtpServer.LogWrite(this, sMessage, 250, sw.ElapsedMilliseconds);
            return(GetMessage(250, string.Format("{0} successful", Command)));
        }
예제 #14
0
        protected override string OnProcess(string sMessage)
        {
            ConnectionObject.DataConnectionType = DataConnectionType.Passive;

            Stopwatch sw = new Stopwatch();

            sw.Start();
            string pasvListenAddress = GetPassiveAddressInfo();

            //return GetMessage(227, string.Format("Entering Passive Mode ({0})", pasvListenAddress));

            // listen at the port by the "FTP" endpoint setting
            int port = int.Parse(ConfigurationManager.AppSettings["FTPPASV"]);

            System.Net.IPAddress  ipaddr     = SocketHelpers.GetLocalAddress();
            System.Net.IPEndPoint ipEndPoint = new System.Net.IPEndPoint(ipaddr.Address, port);

            TcpListener listener = SocketHelpers.CreateTcpListener(ipEndPoint);

            if (listener == null)
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("Couldn't start listener on port {0}", m_nPort)));
            }
            Trace.TraceInformation(string.Format("Entering Passive Mode on {0}", pasvListenAddress));
            SocketHelpers.Send(ConnectionObject.Socket, string.Format("227 Entering Passive Mode ({0})\r\n", pasvListenAddress), ConnectionObject.Encoding);

            listener.Start();

            ConnectionObject.PassiveSocket = listener.AcceptTcpClient();

            listener.Stop();

            sw.Stop();
            FtpServer.LogWrite(this, sMessage, 0, sw.ElapsedMilliseconds);

            return("");
        }
예제 #15
0
        public int Write(byte[] abData, int nDataSize)
        {
            if (BlobStream == null)
            {
                throw new Exception("BlobStream is null!");
            }

            try
            {
                BlobStream.Write(abData, 0, nDataSize);
                return(nDataSize);
            }
            catch (IOException io)
            {
                FtpServer.LogWrite($"IO failure when writing {name}: {io}");
                return(0);
            }
            catch (Exception e)
            {
                FtpServer.LogWrite($"failed to write to {name}: {e}");
                return(0);
            }
        }
예제 #16
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            string dirToRemove = GetPath(FileNameHelpers.AppendDirTag(sMessage));

            // check whether directory exists
            if (!ConnectionObject.FileSystemObject.DirectoryExists(dirToRemove))
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("Directory \"{0}\" does not exist", dirToRemove)));
            }

            // can not delete root directory
            if (dirToRemove == "/")
            {
                FtpServer.LogWrite(this, sMessage, 553, 0);
                return(GetMessage(553, "Can not remove root directory"));
            }

            // delete directory
            if (ConnectionObject.FileSystemObject.DeleteDirectory(dirToRemove))
            {
                FtpServer.LogWrite(this, sMessage, 250, 0);
                return(GetMessage(250, string.Format("{0} successful.", Command)));
            }
            else
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, string.Format("Couldn't remove directory ({0}).", dirToRemove)));
            }
        }
예제 #17
0
        public int Read(byte[] abData, int nDataSize)
        {
            if (BlobStream == null)
            {
                return(0);
            }

            try
            {
                return(BlobStream.Read(abData, 0, nDataSize));
            }
            catch (IOException io)
            {
                FtpServer.LogWrite($"IO failure when reading {name}: {io}");
                return(0);
            }
            // other exceptions
            catch (Exception e)
            {
                FtpServer.LogWrite($"error while reading file {name}: {e}");
                // need logging, fix me
                return(0);
            }
        }
예제 #18
0
 private bool FailOnReadOnlyFs([CallerMemberName] string caller = null)
 {
     FtpServer.LogWrite($"attempt to {caller} on read only file");
     return(false);
 }
예제 #19
0
 protected override string OnProcess(string sMessage)
 {
     FtpServer.LogWrite(this, sMessage, 220, 0);
     return(GetMessage(220, "Goodbye"));
 }
예제 #20
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            string sFile = GetPath(sMessage);

            if (!FileNameHelpers.IsValid(sFile) || sFile.EndsWith(@"/"))
            {
                return(GetMessage(553, string.Format("\"{0}\" is not a valid file name", sMessage)));
            }

            if (ConnectionObject.FileSystemObject.FileExists(sFile))
            {
                // 2015-11-24 cljung : RFC959 says STOR commands overwrite files, so delete if exists
                if (!StorageProviderConfiguration.FtpOverwriteFileOnSTOR)
                {
                    return(GetMessage(553, string.Format("File \"{0}\" already exists.", sMessage)));
                }
                Trace.TraceInformation(string.Format("STOR {0} - Deleting existing file", sFile));
                if (!ConnectionObject.FileSystemObject.DeleteFile(sFile))
                {
                    return(GetMessage(550, string.Format("Delete file \"{0}\" failed.", sFile)));
                }
            }

            var socketData = new FtpDataSocket(ConnectionObject);

            if (!socketData.Loaded)
            {
                return(GetMessage(425, "Unable to establish the data connection"));
            }

            Trace.TraceInformation(string.Format("STOR {0} - BEGIN", sFile));

            IFile file = ConnectionObject.FileSystemObject.OpenFile(sFile, true);

            if (file == null)
            {
                socketData.Close();// close data socket
                return(GetMessage(550, "Couldn't open file"));
            }

            SocketHelpers.Send(ConnectionObject.Socket, GetMessage(150, "Opening connection for data transfer."), ConnectionObject.Encoding);

            string md5Value = string.Empty;

            Stopwatch sw = new Stopwatch();

            sw.Start();

            // TYPE I, default
            if (ConnectionObject.DataType == DataType.Image)
            {
                // md5 hash function
                MD5 md5Hash = MD5.Create();

                var abData = new byte[m_nBufferSize];

                int nReceived = socketData.Receive(abData);

                while (nReceived > 0)
                {
                    int writeSize = file.Write(abData, nReceived);
                    // maybe error
                    if (writeSize != nReceived)
                    {
                        file.Close();
                        socketData.Close();
                        FtpServer.LogWrite(this, sMessage, 451, sw.ElapsedMilliseconds);
                        return(GetMessage(451, "Write data to Azure error!"));
                    }
                    md5Hash.TransformBlock(abData, 0, nReceived, null, 0);
                    nReceived = socketData.Receive(abData);
                }
                md5Hash.TransformFinalBlock(new byte[1], 0, 0);
                md5Value = BytesToStr(md5Hash.Hash);
            }
            // TYPE A
            // won't compute md5, because read characters from client stream
            else if (ConnectionObject.DataType == DataType.Ascii)
            {
                int readSize = SocketHelpers.CopyStreamAscii(socketData.Socket.GetStream(), file.BlobStream, m_nBufferSize);
                FtpServerMessageHandler.SendMessage(ConnectionObject.Id, string.Format("Use ascii type success, read {0} chars!", readSize));
            }
            else   // mustn't reach
            {
                file.Close();
                socketData.Close();
                FtpServer.LogWrite(this, sMessage, 451, sw.ElapsedMilliseconds);
                return(GetMessage(451, "Error in transfer data: invalid data type."));
            }

            sw.Stop();
            Trace.TraceInformation(string.Format("STOR {0} - END, Time {1} ms", sFile, sw.ElapsedMilliseconds));

            // upload notification
            ConnectionObject.FileSystemObject.Log4Upload(sFile);

            file.Close();
            socketData.Close();

            // record md5
            ConnectionObject.FileSystemObject.SetFileMd5(sFile, md5Value);

            FtpServer.LogWrite(this, sMessage, 226, sw.ElapsedMilliseconds);
            return(GetMessage(226, string.Format("{0} successful. Time {1} ms", Command, sw.ElapsedMilliseconds)));
        }
예제 #21
0
 private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
 {
     FtpServer.LogWrite($"UNHANDLED ERROR: {e.ExceptionObject}");
 }
예제 #22
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();
            if (sMessage == "")
            {
                return(GetMessage(501, string.Format("{0} needs a parameter", Command)));
            }

            string sFilePath = GetPath(sMessage);

            Trace.TraceInformation(string.Format("RETR {0} - BEGIN", sFilePath));
            Stopwatch sw = new Stopwatch();

            sw.Start();

            if (!ConnectionObject.FileSystemObject.FileExists(sFilePath))
            {
                FtpServer.LogWrite(this, sMessage, 550, sw.ElapsedMilliseconds);
                return(GetMessage(550, string.Format("File \"{0}\" doesn't exist", sMessage)));
            }

            var socketData = new FtpDataSocket(ConnectionObject);

            if (!socketData.Loaded)
            {
                FtpServer.LogWrite(this, sMessage, 425, sw.ElapsedMilliseconds);
                return(GetMessage(425, "Unable to establish the data connection"));
            }

            SocketHelpers.Send(ConnectionObject.Socket, "150 Starting data transfer, please wait...\r\n", ConnectionObject.Encoding);

            IFile file = ConnectionObject.FileSystemObject.OpenFile(sFilePath, false);

            if (file == null)
            {
                return(GetMessage(550, "Couldn't open file"));
            }

            // TYPE I, default
            if (ConnectionObject.DataType == DataType.Image)
            {
                var abBuffer = new byte[m_nBufferSize];

                int nRead = file.Read(abBuffer, m_nBufferSize);

                while (nRead > 0 && socketData.Send(abBuffer, nRead))
                {
                    nRead = file.Read(abBuffer, m_nBufferSize);
                }
            }
            // TYPE A
            else if (ConnectionObject.DataType == DataType.Ascii)
            {
                int writeSize = SocketHelpers.CopyStreamAscii(file.BlobStream, socketData.Socket.GetStream(), m_nBufferSize);
                FtpServerMessageHandler.SendMessage(ConnectionObject.Id, string.Format("Use ascii type success, write {0} chars!", writeSize));
            }
            else // mustn't reach
            {
                file.Close();
                socketData.Close();
                FtpServer.LogWrite(this, sMessage, 451, sw.ElapsedMilliseconds);
                return(GetMessage(451, "Error in transfer data: invalid data type."));
            }

            file.Close();
            socketData.Close();

            sw.Stop();
            Trace.TraceInformation(string.Format("RETR {0} - END, Time {1} ms", sFilePath, sw.ElapsedMilliseconds));

            FtpServer.LogWrite(this, sMessage, 226, sw.ElapsedMilliseconds);
            return(GetMessage(226, string.Format("File download succeeded. Time {0} ms", sw.ElapsedMilliseconds)));
        }
예제 #23
0
        protected override string OnProcess(string sMessage)
        {
            ConnectionObject.DataConnectionType = DataConnectionType.Passive;

            Stopwatch sw = new Stopwatch();

            sw.Start();

            //return GetMessage(227, string.Format("Entering Passive Mode ({0})", pasvListenAddress));

            // listen at the port by the "FTP" endpoint setting
            int port    = int.Parse(ConfigurationManager.AppSettings["FTPPASV"]);
            int maxPort = port + int.Parse(ConfigurationManager.AppSettings["MaxClients"]);

            int selectedPort = port;

            lock (ListeningPassivePorts)
            {
                while (selectedPort < maxPort && !ListeningPassivePorts.Add(selectedPort))
                {
                    selectedPort++;
                }
            }

            if (selectedPort == maxPort)
            {
                FtpServer.LogWrite("unable to select passive ports, looks like too many clients are connected at once");
                return(GetMessage(550, "Too many concurrent PASV requests"));
            }

            string pasvListenAddress = GetPassiveAddressInfo(selectedPort);

            //System.Net.IPAddress ipaddr = SocketHelpers.GetLocalAddress();
            //System.Net.IPEndPoint ipEndPoint = new System.Net.IPEndPoint(ipaddr.Address, port);
            System.Net.IPEndPoint ipEndPoint = new System.Net.IPEndPoint(IPAddress.Any, selectedPort);

            TcpListener listener = SocketHelpers.CreateTcpListener(ipEndPoint);

            if (listener == null)
            {
                FtpServer.LogWrite(this, sMessage, 550, 0);
                return(GetMessage(550, $"Couldn't start listener on port {m_nPort}"));
            }

            try
            {
                Trace.TraceInformation($"Entering Passive Mode on {pasvListenAddress}");
                SocketHelpers.Send(ConnectionObject.Socket, $"227 Entering Passive Mode ({pasvListenAddress})\r\n",
                                   ConnectionObject.Encoding);

                listener.Start();

                Task <TcpClient> acceptTask = listener.AcceptTcpClientAsync();
                int completed = Task.WaitAny(new[] { acceptTask }, TimeSpan.FromSeconds(maxAcceptWaitTimeSeconds));
                if (completed != 0)
                {
                    FtpServer.LogWrite("timeout while waiting on PASV connection");
                    return(GetMessage(550, "PASV listener timeout"));
                }

                ConnectionObject.PassiveSocket = acceptTask.Result;
            }
            finally
            {
                listener.Stop();
                sw.Stop();
                lock (ListeningPassivePorts)
                {
                    ListeningPassivePorts.Remove(selectedPort);
                }
            }
            FtpServer.LogWrite(this, sMessage, 0, sw.ElapsedMilliseconds);

            return("");
        }
예제 #24
0
        protected override string OnProcess(string sMessage)
        {
            sMessage = sMessage.Trim();

            string[] asFiles       = null;
            string[] asDirectories = null;

            // Get the file/dir to list
            string targetToList = GetPath(sMessage);

            Stopwatch sw = new Stopwatch();

            sw.Start();

            // checks the file/dir name
            if (!FileNameHelpers.IsValid(targetToList))
            {
                FtpServer.LogWrite(this, sMessage, 501, 0);
                return(GetMessage(501, string.Format("\"{0}\" is not a valid file/directory name", sMessage)));
            }

            // two vars indicating different list results
            bool targetIsFile = false;
            bool targetIsDir  = false;

            // targetToList ends with '/', must be a directory
            if (targetToList.EndsWith(@"/"))
            {
                targetIsFile = false;
                if (ConnectionObject.FileSystemObject.DirectoryExists(targetToList))
                {
                    targetIsDir = true;
                }
            }
            else
            {
                // check whether the target to list is a directory
                if (ConnectionObject.FileSystemObject.DirectoryExists(FileNameHelpers.AppendDirTag(targetToList)))
                {
                    targetIsDir = true;
                }
                // check whether the target to list is a file
                if (ConnectionObject.FileSystemObject.FileExists(targetToList))
                {
                    targetIsFile = true;
                }
            }

            if (targetIsFile)
            {
                asFiles = new string[1] {
                    targetToList
                };
                if (targetIsDir)
                {
                    asDirectories = new string[1] {
                        FileNameHelpers.AppendDirTag(targetToList)
                    }
                }
                ;
            }
            // list a directory
            else if (targetIsDir)
            {
                targetToList  = FileNameHelpers.AppendDirTag(targetToList);
                asFiles       = ConnectionObject.FileSystemObject.GetFiles(targetToList);
                asDirectories = ConnectionObject.FileSystemObject.GetDirectories(targetToList);
            }
            else
            {
                FtpServer.LogWrite(this, sMessage, 550, sw.ElapsedMilliseconds);
                return(GetMessage(550, string.Format("\"{0}\" not exists", sMessage)));
            }

            var socketData = new FtpDataSocket(ConnectionObject);

            if (!socketData.Loaded)
            {
                FtpServer.LogWrite(this, sMessage, 425, sw.ElapsedMilliseconds);
                return(GetMessage(425, "Unable to establish the data connection"));
            }

            // prepare to write response to data channel
            SocketHelpers.Send(ConnectionObject.Socket, string.Format("150 Opening data connection for {0}\r\n", Command), ConnectionObject.Encoding);

            // generate the response
            string sFileList = BuildReply(asFiles, asDirectories);

            // ToDo, send response according to ConnectionObject.DataType, i.e., Ascii or Binary
            socketData.Send(sFileList, Encoding.UTF8);
            socketData.Close();

            sw.Stop();
            FtpServer.LogWrite(this, sMessage, 226, sw.ElapsedMilliseconds);
            return(GetMessage(226, string.Format("{0} successful.", Command)));
        }