Represents a file system object on the server
상속: IFtpListItem
		public bool TryDequeue(out FtpListItem item)
		{
			var result = !_priorityQueue.IsEmpty
				? _priorityQueue.TryDequeue(out item)
				: _normalQueue.TryDequeue(out item);

			OnRemove?.Invoke(this, new ObservedListEventArgs(item));

			return result;
		}
		public bool Contains(FtpListItem checkItem, IEqualityComparer<FtpListItem> comparer = null)
		{
			if (comparer == null)
			{
				comparer = _ftpListItemComparer;
			}

			return 
				_priorityQueue.Contains(checkItem, comparer) || 
				_normalQueue.Contains(checkItem, comparer);
		}
예제 #3
0
        public static void Download(this FtpClient conn, FtpListItem file, string localFile)
        {
            if (file.Type != FtpFileSystemObjectType.File) throw new FtpException("invaild file");

            using (var responseStream = conn.OpenRead(file.FullName))
            {
                // Cache data in memory.
                using (var downloadCache = new MemoryStream(MaxCacheSize))
                {
                    int bytesSize = 0;
                    int cachedSize = 0;
                    byte[] downloadBuffer = new byte[BufferSize];

                    // Download the file until the download is completed.
                    while (true)
                    {
                        // Read a buffer of data from the stream.
                        bytesSize = responseStream.Read(downloadBuffer, 0,
                            downloadBuffer.Length);

                        // If the cache is full, or the download is completed, write
                        // the data in cache to local file.
                        if (bytesSize == 0
                            || MaxCacheSize < cachedSize + bytesSize)
                        {
                            // Write the data in cache to local file.
                            WriteCacheToFile(downloadCache, localFile, cachedSize);

                            // Stop downloading the file if the download is paused,
                            // canceled or completed.
                            if (bytesSize == 0)
                            {
                                break;
                            }

                            // Reset cache.
                            downloadCache.Seek(0, SeekOrigin.Begin);
                            cachedSize = 0;

                        }

                        // Write the data from the buffer to the cache in memory.
                        downloadCache.Write(downloadBuffer, 0, bytesSize);
                        cachedSize += bytesSize;
                    }
                }
            }
        }
		public void DeleteFileCallsClientDelete()
		{
			//Arrange
			var file = new FtpListItem
					   {
						   FullName = ""
					   };

			_ftpClient.Expect(x => x.DeleteFile(file.FullName));

			//Act
			_ftpWrapper.DeleteFile(file);

			//Assert
			_ftpClient.VerifyAllExpectations();
		}
		public void Enqueue(FtpListItem item, bool priority = false)
		{
			OnAdd?.Invoke(this, new ObservedListEventArgs(item, priority));

			if (priority)
			{
				if (!_priorityQueue.Any(x => _ftpListItemComparer.Equals(x, item)))
				{
					_priorityQueue.Enqueue(item);
				}
			}
			else
			{
				if (!_normalQueue.Any(x => _ftpListItemComparer.Equals(x, item)))
				{
					_normalQueue.Enqueue(item);
				}
			}
		}
예제 #6
0
        public static void BeginDereferenceLinkExample(FtpListItem item) {
            // The using statement here is OK _only_ because m_reset.WaitOne()
            // causes the code to block until the async process finishes, otherwise
            // the connection object would be disposed early. In practice, you
            // typically would not wrap the following code with a using statement.
            using (FtpClient conn = new FtpClient()) {
                m_reset.Reset();

                conn.Host = "localhost";
                conn.Credentials = new NetworkCredential("ftptest", "ftptest");
                conn.Connect();

                if (item.Type == FtpFileSystemObjectType.Link && item.LinkTarget != null) {
                    conn.BeginDereferenceLink(item, new AsyncCallback(DereferenceLinkCallback), conn);
                    m_reset.WaitOne();
                }

                conn.Disconnect();
            }
        }
예제 #7
0
        /// <summary>
        /// Parses LIST format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseUnixList(string buf, FtpCapability capabilities)
        {
            string regex =
                @"(?<permissions>[\w-]{10})\s+" +
                @"(?<objectcount>\d+)\s+" +
                @"(?<user>[\w\d]+)\s+" +
                @"(?<group>[\w\d]+)\s+" +
                @"(?<size>\d+)\s+" +
                @"(?<modify>\w+\s+\d+\s+\d+:\d+|\w+\s+\d+\s+\d+)\s+" +
                @"(?<name>.*)$";
            FtpListItem item = new FtpListItem();
            Match m;

            if (!(m = Regex.Match(buf, regex, RegexOptions.IgnoreCase)).Success)
                return null;

            if (m.Groups["permissions"].Value.StartsWith("d"))
                item.Type = FtpFileSystemObjectType.Directory;
            else if (m.Groups["permissions"].Value.StartsWith("-"))
                item.Type = FtpFileSystemObjectType.File;
            else
                return null;

            // if we can't determine a file name then
            // we are not considering this a successful parsing operation.
            if (m.Groups["name"].Value.Length < 1)
                return null;
            item.Name = m.Groups["name"].Value;

            if (item.Type == FtpFileSystemObjectType.Directory && (item.Name == "." || item.Name == ".."))
                return null;

            ////
            // Ignore the Modify times sent in LIST format for files
            // when the server has support for the MDTM command
            // because they will never be as accurate as what can be had
            // by using the MDTM command. MDTM does not work on directories
            // so if a modify time was parsed from the listing we will try
            // to convert it to a DateTime object and use it for directories.
            ////
            if ((!capabilities.HasFlag(FtpCapability.MDTM) || item.Type == FtpFileSystemObjectType.Directory) && m.Groups["modify"].Value.Length > 0)
                item.Modified = m.Groups["modify"].Value.GetFtpDate();

            if (m.Groups["size"].Value.Length > 0) {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                    item.Size = size;
            }

            if (m.Groups["permissions"].Value.Length > 0) {
                Match perms = Regex.Match(m.Groups["permissions"].Value,
                    @"[\w-]{1}(?<owner>[\w-]{3})(?<group>[\w-]{3})(?<others>[\w-]{3})",
                    RegexOptions.IgnoreCase);

                if (perms.Success) {
                    if (perms.Groups["owner"].Value.Length == 3) {
                        if (perms.Groups["owner"].Value[0] == 'r')
                            item.OwnerPermissions |= FtpPermission.Read;
                        if (perms.Groups["owner"].Value[1] == 'w')
                            item.OwnerPermissions |= FtpPermission.Write;
                        if (perms.Groups["owner"].Value[2] == 'x' || perms.Groups["owner"].Value[2] == 's')
                            item.OwnerPermissions |= FtpPermission.Execute;
                        if (perms.Groups["owner"].Value[2] == 's' || perms.Groups["owner"].Value[2] == 'S')
                            item.SpecialPermissions |= FtpSpecialPermissions.SetUserID;
                    }

                    if (perms.Groups["group"].Value.Length == 3) {
                        if (perms.Groups["group"].Value[0] == 'r')
                            item.GroupPermissions |= FtpPermission.Read;
                        if (perms.Groups["group"].Value[1] == 'w')
                            item.GroupPermissions |= FtpPermission.Write;
                        if (perms.Groups["group"].Value[2] == 'x' || perms.Groups["group"].Value[2] == 's')
                            item.GroupPermissions |= FtpPermission.Execute;
                        if (perms.Groups["group"].Value[2] == 's' || perms.Groups["group"].Value[2] == 'S')
                            item.SpecialPermissions |= FtpSpecialPermissions.SetGroupID;
                    }

                    if (perms.Groups["others"].Value.Length == 3) {
                        if (perms.Groups["others"].Value[0] == 'r')
                            item.OthersPermissions |= FtpPermission.Read;
                        if (perms.Groups["others"].Value[1] == 'w')
                            item.OthersPermissions |= FtpPermission.Write;
                        if (perms.Groups["others"].Value[2] == 'x' || perms.Groups["others"].Value[2] == 't')
                            item.OthersPermissions |= FtpPermission.Execute;
                        if (perms.Groups["others"].Value[2] == 't' || perms.Groups["others"].Value[2] == 'T')
                            item.SpecialPermissions |= FtpSpecialPermissions.Sticky;
                    }
                }
            }

            return item;
        }
예제 #8
0
        private string GetURL(FtpListItem file)
        {
            if (file != null && file.Type == FtpFileSystemObjectType.File)
            {
                FTPAccount accountClone = Account.Clone();
                accountClone.SubFolderPath = currentDirectory;
                accountClone.HttpHomePathAutoAddSubFolderPath = true;
                return accountClone.GetUriPath(file.Name);
            }

            return null;
        }
예제 #9
0
        /// <summary>
        /// Parses IIS DOS format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseDosList(string buf, FtpCapability capabilities)
        {
            FtpListItem item = new FtpListItem();
            Match m;

            // directory
            if ((m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+<DIR>\s+(?<name>.*)$", RegexOptions.IgnoreCase)).Success) {
                DateTime modify;

                item.Type = FtpFileSystemObjectType.Directory;
                item.Name = m.Groups["name"].Value;

                if (DateTime.TryParse(m.Groups["modify"].Value, out modify))
                    item.Modified = modify;
            }
            // file
            else if ((m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+(?<size>\d+)\s+(?<name>.*)$", RegexOptions.IgnoreCase)).Success) {
                DateTime modify;
                long size;

                item.Type = FtpFileSystemObjectType.File;
                item.Name = m.Groups["name"].Value;

                if (long.TryParse(m.Groups["size"].Value, out size))
                    item.Size = size;

                if (DateTime.TryParse(m.Groups["modify"].Value, out modify))
                    item.Modified = modify;
            }
            else
                return null;

            return item;
        }
예제 #10
0
        /// <summary>
        /// Parses MLS* format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseMachineList(string buf, FtpCapability capabilities)
        {
            FtpListItem item = new FtpListItem();
            Match m;

            if (!(m = Regex.Match(buf, "^type=(?<type>.+?);", RegexOptions.IgnoreCase)).Success)
                return null;

            switch (m.Groups["type"].Value.ToLower()) {
                case "dir":
                    item.Type = FtpFileSystemObjectType.Directory;
                    break;
                case "file":
                    item.Type = FtpFileSystemObjectType.File;
                    break;
                // These are not supported for now.
                case "link":
                case "device":
                default:
                    return null;
            }

            if ((m = Regex.Match(buf, "; (?<name>.*)$", RegexOptions.IgnoreCase)).Success)
                item.Name = m.Groups["name"].Value;
            else // if we can't parse the file name there is a problem.
                return null;

            if ((m = Regex.Match(buf, "modify=(?<modify>.+?);", RegexOptions.IgnoreCase)).Success)
                item.Modified = m.Groups["modify"].Value.GetFtpDate();

            if ((m = Regex.Match(buf, "created?=(?<create>.+?);", RegexOptions.IgnoreCase)).Success)
                item.Created = m.Groups["create"].Value.GetFtpDate();

            if ((m = Regex.Match(buf, @"size=(?<size>\d+);", RegexOptions.IgnoreCase)).Success) {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                    item.Size = size;
            }

            if((m = Regex.Match(buf, @"unix.mode=(?<mode>\d+);", RegexOptions.IgnoreCase)).Success) {
                if (m.Groups["mode"].Value.Length == 4) {
                    item.SpecialPermissions = (FtpSpecialPermissions)int.Parse(m.Groups["mode"].Value[0].ToString());
                    item.OwnerPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[1].ToString());
                    item.GroupPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[2].ToString());
                    item.OthersPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[3].ToString());
                }
                else if(m.Groups["mode"].Value.Length == 3) {
                    item.OwnerPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[0].ToString());
                    item.GroupPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[1].ToString());
                    item.OthersPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[2].ToString());
                }
            }

            return item;
        }
예제 #11
0
		public void DownloadFiles(int maxPerSession = 0)
		{
			if (_downloadStatus)
			{
				return;
			}

			_downloadStatus = true;

			var downloadCount = 0;
			
			if (maxPerSession != 0)
			{
				Log.Info($"Beginning session of {maxPerSession} downloads.");
			}

			FtpListItem item;

			while ((maxPerSession == 0 || downloadCount < maxPerSession) && DownloadList.TryDequeue(out item))
			{
				CurrentItem = item;

				try
				{
					if (DownloadFile(item))
					{
						downloadCount++;
						DeleteFile(item);
					}
				}
				catch (Exception e)
				{
					Log.Error($"{e.Message}");
					TrackErrorCount(item);
				}
			}

			_downloadStatus = false;
		}
예제 #12
0
        static FtpListItem ParseVaxList(string buf, FtpCapability capabilities) {
            string regex =
                @"(?<name>.+)\.(?<extension>.+);(?<version>\d+)\s+" +
                @"(?<size>\d+)\s+" +
                @"(?<modify>\d+-\w+-\d+\s+\d+:\d+)";
            Match m;

            if ((m = Regex.Match(buf, regex)).Success) {
                FtpListItem item = new FtpListItem();

                item.m_name = string.Format("{0}.{1};{2}",
                    m.Groups["name"].Value,
                    m.Groups["extension"].Value,
                    m.Groups["version"].Value);

                if (m.Groups["extension"].Value.ToUpper() == "DIR")
                    item.m_type = FtpFileSystemObjectType.Directory;
                else
                    item.m_type = FtpFileSystemObjectType.File;

                if (!long.TryParse(m.Groups["size"].Value, out item.m_size))
                    item.m_size = -1;

                if (!DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out item.m_modified))
                    item.m_modified = DateTime.MinValue;

                return item;
            }

            return null;
        }
        private static void downloadFile(FtpClient client, FtpListItem file, bool deleteFtpFile)
        {
            string destinationPath = String.Format(@"{0}\{1}", Directory.GetCurrentDirectory(), file.Name);

            using (var ftpStream = client.OpenRead(file.FullName)) {
                using (var fileStream = File.Create(destinationPath, (int)ftpStream.Length)) {
                    var buffer = new byte[8 * 1024];
                    int count;
                    while ((count = ftpStream.Read(buffer, 0, buffer.Length)) > 0) {
                        fileStream.Write(buffer, 0, count);
                    }
                }
            }
            DownloadedFile temp = new DownloadedFile();
            temp.originalPath = file.FullName;
            temp.fullOriginalPath = client.Host + file.FullName;
            temp.finalPath = destinationPath;
            temp.name = file.Name;
            temp.extension = ".txt";
            minervaFiles.Add(temp);
            if (deleteFtpFile) {
                client.DeleteFile(file.FullName);
            }
        }
        private static void ftpStepIntoFolder(FtpListItem folder)
        {
            logFile.WriteLine(String.Format("stepping into ftp folder {0}", folder));
            client.SetWorkingDirectory(folder.FullName);

            FtpListItem[] files;
            files = client.GetListing();
            body = body + "\nfolder: " + folder.Name + "\n";
            body = body + "filesFound: " + files.Length + "\n";
            if (files.Length > 0)
            {
                for (var i = 0; i < files.Length; i++)
                {
                    setCurrentDirectory(rootDirectory);
                    logFile.WriteLine(String.Format("resetting current directory {0}", rootDirectory));

                    System.IO.Stream output;

                    bool downloadThisFile = true;
                    bool fileAlreadyExisted = false;
                    bool fileDownloadSuccess = true;

                    //if the file already exists, no reason to redownload it if it's valid
                    if (System.IO.File.Exists(files[i].Name))
                    {
                        //Make sure we don't have a partial file...
                        FileInfo info = new FileInfo(files[i].Name);
                        if (info.Length == files[i].Size)
                        {
                            logFile.WriteLine(String.Format("{0} already exists in directy, must not have been processed correctly", files[i].Name));
                            downloadThisFile = false;
                            fileAlreadyExisted = true;
                        }
                        else {
                            logFile.WriteLine(String.Format("{0} already exists in directy, incorrect file size...partial download", files[i].Name));
                        }
                    }
                    //If the file has an invalid naming convention, no point trying to download it
                    if(!validateFileName(files[i].Name) && downloadThisFile)
                    {
                        //We can flag this file as an error
                        filesInvalidName++;
                        Console.WriteLine("{0} name is invalid...not downloading", files[i].Name);
                        logFile.WriteLine(String.Format("{0} is improperly named...skipping it", files[i].Name));
                        report.WriteLine(String.Format("{0},-,{1},-,- ,Couldn't parse name! did not download file",files[i].Name,folder.Name));
                        downloadThisFile = false;
                        fileAlreadyExisted = false;
                        fileDownloadSuccess = false;
                    }

                    //If the file has an invalid account number, no reason to download it
                    int accountNumber = extractAccountNumber(files[i].Name);
                    if (!validateAccountNumber(accountNumber) && downloadThisFile)
                    {
                        downloadThisFile = false;
                        fileAlreadyExisted = false;
                        logFile.WriteLine("{0} is an invalid account number", accountNumber);
                    }

                    if (downloadThisFile)
                    {
                        output = new System.IO.FileStream(files[i].Name, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite);
                        Stream input = client.OpenRead(files[i].FullName);
                        //represents miliseconds of delay between each chunk of data read
                        int downloadThrottle = 0;
                        int attempts = 0;
                        int attemptsAllowed = 10;
                        //start reading the chunks and copying them
                        logFile.WriteLine(String.Format("Begin download of {0}", files[i].Name));
                        Console.WriteLine("Download begin! {0}", files[i].Name);
                        downloadFile(input, output, downloadThrottle);
                        attempts++;
                        while (output.Length != input.Length)
                        {
                            if (attempts < attemptsAllowed)
                            {
                                Console.WriteLine("file did not download correctly...");
                                logFile.WriteLine(String.Format("{0} downloaded incorrectly...{1} of {2}", files[i].Name,output.Length,input.Length));
                                //Close the output file, so we can create a new one...
                                output.Close();
                                //reopen the file we want to download
                                input = client.OpenRead(files[i].FullName);
                                //recreate the file in the download location
                                output = new System.IO.FileStream(files[i].Name, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite);
                                //slightly reduce download speed
                                downloadThrottle = attempts * 10;
                                //attempt to download
                                Console.WriteLine("Attempt redownload of {0}", files[i].Name);
                                logFile.WriteLine(String.Format("attempt redownload of {0}", files[i].Name));
                                downloadFile(input, output, downloadThrottle);
                                //Increase the number of attemps we have had
                                attempts++;
                            }
                            else
                            {
                                Console.WriteLine("reached max download attempts...");
                                logFile.WriteLine(String.Format("Max download attemps reached for {0}. Canceling download Attempt...", files[i].Name));
                                report.WriteLine(String.Format("{0},{1},{2},-,- ,File download failed 10 times - needs to manual download", files[i].Name,extractAccountNumber(files[i].Name), folder.Name));
                                fileDownloadSuccess = false;
                                fileAlreadyExisted = false;
                                break;
                            }
                        }
                        //close the file we just created
                        output.Close();

                    }
                    if (fileAlreadyExisted || fileDownloadSuccess)
                    {
                        Console.WriteLine("File successfully exists in our directory!");
                        logFile.WriteLine(String.Format("{0} exists successfully!",files[0].Name));
                        //copy file to its home
                        List<string> directories = new List<string>() { "COMMV_PDFS", extractAccountNumber(files[i].Name).ToString(), folder.Name };
                        logFile.WriteLine(String.Format("move file to final destination!"));
                        KeyValuePair<string, int> kvp1,kvp2 = new KeyValuePair<string, int>();
                        kvp1 = buildDestinationAndMoveFile(files[i].Name, folder.Name, directories);
                        //go back to the applications directory
                        logFile.WriteLine(String.Format("reset currentDirectory {0}", rootDirectory));
                        Directory.SetCurrentDirectory(rootDirectory);
                        //Copy file to archive
                        directories = new List<string>() { "PeruvianAutomatedArchive", "Done", folder.Name };
                        logFile.WriteLine(String.Format("move file to archive destination!"));
                        kvp2 = buildDestinationAndMoveFile(files[i].Name, folder.Name, directories);
                        //insert record into database
                        insertToDatabase(extractAccountNumber(files[i].Name).ToString(), files[i].Name, kvp1.Key, "0", folder.Name);

                        //record some success/fail data about the files we are pulling down
                        switch (kvp1.Value)
                        {
                            case 0:
                                filesFail++;
                                break;
                            case 1:
                                filesDuplicate++;
                                break;
                            case 2:
                                filesMoved++;
                                break;
                        }
                        //delete file from ftp
                        try
                        {
                            client.DeleteFile(files[i].FullName);
                            logFile.WriteLine(String.Format("Deleted {0} from the ftp server",files[i].Name));
                        }
                        catch (Exception e) {
                            logFile.WriteLine(String.Format("failed to delete {0} from the ftp server", files[i].Name));
                            logFile.WriteLine(String.Format("{0}", e));
                        }
                        //delete file from directory
                        try {
                            File.Delete(rootDirectory + "\\" + files[i].Name);
                            logFile.WriteLine(String.Format("deleted {0} from {1}", files[i].Name,rootDirectory));
                        }
                        catch (Exception e) {
                            logFile.WriteLine(String.Format("delete failed...{e}", e));
                        }
                        //open record .csv and append
                        report.WriteLine(String.Format("{0},{1},{2},{3},{4}, ",files[i].Name,extractAccountNumber(files[i].Name),folder.Name,kvp1.Key,kvp2.Key));
                    }
                }
            }
            body = body + "Successful moves: " + filesMoved + "\n";
            body = body + "File Already Existed: " + filesDuplicate + "\n";
            body = body + "Failure to move: " + filesFail + "\n";
            body = body + "File invalid name: " + filesInvalidName+ "\n";
        }
예제 #15
0
        /// <summary>
        /// Parses MLS* format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseMachineList(string buf, FtpCapability capabilities)
        {
            FtpListItem item = new FtpListItem();
            Match       m;

            if (!(m = Regex.Match(buf, "^type=(?<type>.+?);", RegexOptions.IgnoreCase)).Success)
            {
                return(null);
            }

            switch (m.Groups["type"].Value.ToLower())
            {
            case "dir":
                item.Type = FtpFileSystemObjectType.Directory;
                break;

            case "file":
                item.Type = FtpFileSystemObjectType.File;
                break;

            // These are not supported for now.
            case "link":
            case "device":
            default:
                return(null);
            }

            if ((m = Regex.Match(buf, "; (?<name>.*)$", RegexOptions.IgnoreCase)).Success)
            {
                item.Name = m.Groups["name"].Value;
            }
            else // if we can't parse the file name there is a problem.
            {
                return(null);
            }

            if ((m = Regex.Match(buf, "modify=(?<modify>.+?);", RegexOptions.IgnoreCase)).Success)
            {
                item.Modified = m.Groups["modify"].Value.GetFtpDate();
            }

            if ((m = Regex.Match(buf, "created?=(?<create>.+?);", RegexOptions.IgnoreCase)).Success)
            {
                item.Created = m.Groups["create"].Value.GetFtpDate();
            }

            if ((m = Regex.Match(buf, @"size=(?<size>\d+);", RegexOptions.IgnoreCase)).Success)
            {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                {
                    item.Size = size;
                }
            }

            if ((m = Regex.Match(buf, @"unix.mode=(?<mode>\d+);", RegexOptions.IgnoreCase)).Success)
            {
                if (m.Groups["mode"].Value.Length == 4)
                {
                    item.SpecialPermissions = (FtpSpecialPermissions)int.Parse(m.Groups["mode"].Value[0].ToString());
                    item.OwnerPermissions   = (FtpPermission)int.Parse(m.Groups["mode"].Value[1].ToString());
                    item.GroupPermissions   = (FtpPermission)int.Parse(m.Groups["mode"].Value[2].ToString());
                    item.OthersPermissions  = (FtpPermission)int.Parse(m.Groups["mode"].Value[3].ToString());
                }
                else if (m.Groups["mode"].Value.Length == 3)
                {
                    item.OwnerPermissions  = (FtpPermission)int.Parse(m.Groups["mode"].Value[0].ToString());
                    item.GroupPermissions  = (FtpPermission)int.Parse(m.Groups["mode"].Value[1].ToString());
                    item.OthersPermissions = (FtpPermission)int.Parse(m.Groups["mode"].Value[2].ToString());
                }
            }

            return(item);
        }
 void DownloadFile(FtpListItem item,string localFolderPath)
 {
     DownloadFile(item.Name, localFolderPath);
 }
예제 #17
0
        /// <summary>
        /// Parses LIST format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseUnixList(string buf, FtpCapability capabilities)
        {
            string regex =
                @"(?<permissions>[\w-]{10})\s+" +
                @"(?<objectcount>\d+)\s+" +
                @"(?<user>[\w\d]+)\s+" +
                @"(?<group>[\w\d]+)\s+" +
                @"(?<size>\d+)\s+" +
                @"(?<modify>\w+\s+\d+\s+\d+:\d+|\w+\s+\d+\s+\d+)\s+" +
                @"(?<name>.*)$";
            FtpListItem item = new FtpListItem();
            Match       m;

            if (!(m = Regex.Match(buf, regex, RegexOptions.IgnoreCase)).Success)
            {
                return(null);
            }

            if (m.Groups["permissions"].Value.StartsWith("d"))
            {
                item.Type = FtpFileSystemObjectType.Directory;
            }
            else if (m.Groups["permissions"].Value.StartsWith("-"))
            {
                item.Type = FtpFileSystemObjectType.File;
            }
            else
            {
                return(null);
            }

            // if we can't determine a file name then
            // we are not considering this a successful parsing operation.
            if (m.Groups["name"].Value.Length < 1)
            {
                return(null);
            }
            item.Name = m.Groups["name"].Value;

            if (item.Type == FtpFileSystemObjectType.Directory && (item.Name == "." || item.Name == ".."))
            {
                return(null);
            }

            ////
            // Ignore the Modify times sent in LIST format for files
            // when the server has support for the MDTM command
            // because they will never be as accurate as what can be had
            // by using the MDTM command. MDTM does not work on directories
            // so if a modify time was parsed from the listing we will try
            // to convert it to a DateTime object and use it for directories.
            ////
            if ((!capabilities.HasFlag(FtpCapability.MDTM) || item.Type == FtpFileSystemObjectType.Directory) && m.Groups["modify"].Value.Length > 0)
            {
                item.Modified = m.Groups["modify"].Value.GetFtpDate();
            }

            if (m.Groups["size"].Value.Length > 0)
            {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                {
                    item.Size = size;
                }
            }

            if (m.Groups["permissions"].Value.Length > 0)
            {
                Match perms = Regex.Match(m.Groups["permissions"].Value,
                                          @"[\w-]{1}(?<owner>[\w-]{3})(?<group>[\w-]{3})(?<others>[\w-]{3})",
                                          RegexOptions.IgnoreCase);

                if (perms.Success)
                {
                    if (perms.Groups["owner"].Value.Length == 3)
                    {
                        if (perms.Groups["owner"].Value[0] == 'r')
                        {
                            item.OwnerPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["owner"].Value[1] == 'w')
                        {
                            item.OwnerPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["owner"].Value[2] == 'x' || perms.Groups["owner"].Value[2] == 's')
                        {
                            item.OwnerPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["owner"].Value[2] == 's' || perms.Groups["owner"].Value[2] == 'S')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.SetUserID;
                        }
                    }

                    if (perms.Groups["group"].Value.Length == 3)
                    {
                        if (perms.Groups["group"].Value[0] == 'r')
                        {
                            item.GroupPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["group"].Value[1] == 'w')
                        {
                            item.GroupPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["group"].Value[2] == 'x' || perms.Groups["group"].Value[2] == 's')
                        {
                            item.GroupPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["group"].Value[2] == 's' || perms.Groups["group"].Value[2] == 'S')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.SetGroupID;
                        }
                    }

                    if (perms.Groups["others"].Value.Length == 3)
                    {
                        if (perms.Groups["others"].Value[0] == 'r')
                        {
                            item.OthersPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["others"].Value[1] == 'w')
                        {
                            item.OthersPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["others"].Value[2] == 'x' || perms.Groups["others"].Value[2] == 't')
                        {
                            item.OthersPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["others"].Value[2] == 't' || perms.Groups["others"].Value[2] == 'T')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.Sticky;
                        }
                    }
                }
            }

            return(item);
        }
예제 #18
0
		public void DeleteFile(FtpListItem file)
		{
			_client.DeleteFile(file.FullName);

			if (file.FullName == "") return;

			var path = Path.GetDirectoryName(file.FullName);
			while (path != "\\" + _settings.FtpRootCheckDir && DeleteFolder(path))
			{
				path = Path.GetDirectoryName(path);
			}
		}
예제 #19
0
		private void TrackErrorCount(FtpListItem file)
		{
			if (_currentErrors.ContainsKey(file.Name))
			{
				_currentErrors[file.Name]++;
			}
			else
			{
				_currentErrors.Add(file.Name, 1);
			}

			if (_currentErrors[file.Name] < _settings.MaxRetryCount)
			{
				DownloadList.Enqueue(file);
				return;
			}

			_currentErrors.Remove(file.Name);
			Log.Warn($"Removed {file.Name} from download list");
		}
예제 #20
0
파일: Client.cs 프로젝트: CKoewing/FTPbox
        /// <summary>
        /// Convert an FtpItem to a ClientItem
        /// </summary>
        private ClientItem ConvertItem(FtpListItem f)
        {
            var fullPath = f.FullName;
            if (fullPath.StartsWith("./"))
            {
                var cwd = WorkingDirectory;
                var wd = (controller.Paths.Remote != null && cwd.StartsWithButNotEqual(controller.Paths.Remote) && cwd != "/") ? cwd : controller.GetCommonPath(cwd, false);
                fullPath = fullPath.Substring(2);
                if (wd != "/")
                    fullPath = string.Format("/{0}/{1}", wd, fullPath);
                fullPath = fullPath.Replace("//", "/");
            }

            return new ClientItem
                {
                    Name = f.Name,
                    FullPath = fullPath,
                    Type = _ItemTypeOf(f.Type),
                    Size = f.Size,
                    LastWriteTime = f.Modified
                };
        }
예제 #21
0
        /// <summary>
        /// Parses LIST format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseUnixList(string buf, FtpCapability capabilities) {
            string regex =
                @"(?<permissions>.+)\s+" +
                @"(?<objectcount>\d+)\s+" +
                @"(?<user>.+)\s+" +
                @"(?<group>.+)\s+" +
                @"(?<size>\d+)\s+" +
                @"(?<modify>\w+\s+\d+\s+\d+:\d+|\w+\s+\d+\s+\d+)\s" +
                @"(?<name>.*)$";
            FtpListItem item = new FtpListItem();
            Match m;

            if (!(m = Regex.Match(buf, regex, RegexOptions.IgnoreCase)).Success)
                return null;

            // if this field is missing we can't determine
            // what the object is.
            if (m.Groups["permissions"].Value.Length == 0)
                return null;

            switch (m.Groups["permissions"].Value[0]) {
                case 'd':
                    item.Type = FtpFileSystemObjectType.Directory;
                    break;
                case '-':
                case 's':
                    item.Type = FtpFileSystemObjectType.File;
                    break;
                case 'l':
                    item.Type = FtpFileSystemObjectType.Link;
                    break;
                default:
                    return null;
            }

            // if we can't determine a file name then
            // we are not considering this a successful parsing operation.
            if (m.Groups["name"].Value.Length < 1)
                return null;
            item.Name = m.Groups["name"].Value;

            switch (item.Type) {
                case FtpFileSystemObjectType.Directory:
                    // ignore these...
                    if (item.Name == "." || item.Name == "..")
                        return null;
                    break;
                case FtpFileSystemObjectType.Link:
                    if (!item.Name.Contains(" -> "))
                        return null;
                    item.LinkTarget = item.Name.Remove(0, item.Name.IndexOf("-> ") + 3);
                    item.Name = item.Name.Remove(item.Name.IndexOf(" -> "));
                    break;
            }

            // for date parser testing only
            //capabilities = ~(capabilities & FtpCapability.MDTM);

            ////
            // Ignore the Modify times sent in LIST format for files
            // when the server has support for the MDTM command
            // because they will never be as accurate as what can be had 
            // by using the MDTM command. MDTM does not work on directories
            // so if a modify time was parsed from the listing we will try
            // to convert it to a DateTime object and use it for directories.
            ////
            if (((capabilities & FtpCapability.MDTM) != FtpCapability.MDTM || item.Type == FtpFileSystemObjectType.Directory) && m.Groups["modify"].Value.Length > 0) {
                item.Modified = m.Groups["modify"].Value.GetFtpDate(DateTimeStyles.AssumeLocal);
                if (item.Modified == DateTime.MinValue) {
                    FtpTrace.WriteLine("GetFtpDate() failed on {0}", m.Groups["modify"].Value);
                }
            }
            else {
                if (m.Groups["modify"].Value.Length == 0)
                    FtpTrace.WriteLine("RegEx failed to parse modified date from {0}.", buf);
                else if (item.Type == FtpFileSystemObjectType.Directory)
                    FtpTrace.WriteLine("Modified times of directories are ignored in UNIX long listings.");
                else if ((capabilities & FtpCapability.MDTM) == FtpCapability.MDTM)
                    FtpTrace.WriteLine("Ignoring modified date because MDTM feature is present. If you aren't already, pass FtpListOption.Modify or FtpListOption.SizeModify to GetListing() to retrieve the modification time.");
            }

            if (m.Groups["size"].Value.Length > 0) {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                    item.Size = size;
            }

            if (m.Groups["permissions"].Value.Length > 0) {
                Match perms = Regex.Match(m.Groups["permissions"].Value,
                    @"[\w-]{1}(?<owner>[\w-]{3})(?<group>[\w-]{3})(?<others>[\w-]{3})",
                    RegexOptions.IgnoreCase);

                if (perms.Success) {
                    if (perms.Groups["owner"].Value.Length == 3) {
                        if (perms.Groups["owner"].Value[0] == 'r')
                            item.OwnerPermissions |= FtpPermission.Read;
                        if (perms.Groups["owner"].Value[1] == 'w')
                            item.OwnerPermissions |= FtpPermission.Write;
                        if (perms.Groups["owner"].Value[2] == 'x' || perms.Groups["owner"].Value[2] == 's')
                            item.OwnerPermissions |= FtpPermission.Execute;
                        if (perms.Groups["owner"].Value[2] == 's' || perms.Groups["owner"].Value[2] == 'S')
                            item.SpecialPermissions |= FtpSpecialPermissions.SetUserID;
                    }

                    if (perms.Groups["group"].Value.Length == 3) {
                        if (perms.Groups["group"].Value[0] == 'r')
                            item.GroupPermissions |= FtpPermission.Read;
                        if (perms.Groups["group"].Value[1] == 'w')
                            item.GroupPermissions |= FtpPermission.Write;
                        if (perms.Groups["group"].Value[2] == 'x' || perms.Groups["group"].Value[2] == 's')
                            item.GroupPermissions |= FtpPermission.Execute;
                        if (perms.Groups["group"].Value[2] == 's' || perms.Groups["group"].Value[2] == 'S')
                            item.SpecialPermissions |= FtpSpecialPermissions.SetGroupID;
                    }

                    if (perms.Groups["others"].Value.Length == 3) {
                        if (perms.Groups["others"].Value[0] == 'r')
                            item.OthersPermissions |= FtpPermission.Read;
                        if (perms.Groups["others"].Value[1] == 'w')
                            item.OthersPermissions |= FtpPermission.Write;
                        if (perms.Groups["others"].Value[2] == 'x' || perms.Groups["others"].Value[2] == 't')
                            item.OthersPermissions |= FtpPermission.Execute;
                        if (perms.Groups["others"].Value[2] == 't' || perms.Groups["others"].Value[2] == 'T')
                            item.SpecialPermissions |= FtpSpecialPermissions.Sticky;
                    }
                }
            }

            return item;
        }
예제 #22
0
        /// <summary>
        /// Parses LIST format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseUnixList(string buf, FtpCapability capabilities)
        {
            string regex =
                @"(?<permissions>.+)\s+" +
                @"(?<objectcount>\d+)\s+" +
                @"(?<user>.+)\s+" +
                @"(?<group>.+)\s+" +
                @"(?<size>\d+)\s+" +
                @"(?<modify>\w+\s+\d+\s+\d+:\d+|\w+\s+\d+\s+\d+)\s" +
                @"(?<name>.*)$";
            FtpListItem item = new FtpListItem();
            Match       m;

            if (!(m = Regex.Match(buf, regex, RegexOptions.IgnoreCase)).Success)
            {
                return(null);
            }

            // if this field is missing we can't determine
            // what the object is.
            if (m.Groups["permissions"].Value.Length == 0)
            {
                return(null);
            }

            switch (m.Groups["permissions"].Value[0])
            {
            case 'd':
                item.Type = FtpFileSystemObjectType.Directory;
                break;

            case '-':
            case 's':
                item.Type = FtpFileSystemObjectType.File;
                break;

            case 'l':
                item.Type = FtpFileSystemObjectType.Link;
                break;

            default:
                return(null);
            }

            // if we can't determine a file name then
            // we are not considering this a successful parsing operation.
            if (m.Groups["name"].Value.Length < 1)
            {
                return(null);
            }
            item.Name = m.Groups["name"].Value;

            switch (item.Type)
            {
            case FtpFileSystemObjectType.Directory:
                // ignore these...
                if (item.Name == "." || item.Name == "..")
                {
                    return(null);
                }
                break;

            case FtpFileSystemObjectType.Link:
                if (!item.Name.Contains(" -> "))
                {
                    return(null);
                }
                item.LinkTarget = item.Name.Remove(0, item.Name.IndexOf("-> ") + 3);
                item.Name       = item.Name.Remove(item.Name.IndexOf(" -> "));
                break;
            }

            // for date parser testing only
            //capabilities = ~(capabilities & FtpCapability.MDTM);

            ////
            // Ignore the Modify times sent in LIST format for files
            // when the server has support for the MDTM command
            // because they will never be as accurate as what can be had
            // by using the MDTM command. MDTM does not work on directories
            // so if a modify time was parsed from the listing we will try
            // to convert it to a DateTime object and use it for directories.
            ////
            if (((capabilities & FtpCapability.MDTM) != FtpCapability.MDTM || item.Type == FtpFileSystemObjectType.Directory) && m.Groups["modify"].Value.Length > 0)
            {
                item.Modified = m.Groups["modify"].Value.GetFtpDate(DateTimeStyles.AssumeLocal);
                if (item.Modified == DateTime.MinValue)
                {
                    FtpTrace.WriteLine("GetFtpDate() failed on {0}", m.Groups["modify"].Value);
                }
            }
            else
            {
                if (m.Groups["modify"].Value.Length == 0)
                {
                    FtpTrace.WriteLine("RegEx failed to parse modified date from {0}.", buf);
                }
                else if (item.Type == FtpFileSystemObjectType.Directory)
                {
                    FtpTrace.WriteLine("Modified times of directories are ignored in UNIX long listings.");
                }
                else if ((capabilities & FtpCapability.MDTM) == FtpCapability.MDTM)
                {
                    FtpTrace.WriteLine("Ignoring modified date because MDTM feature is present. If you aren't already, pass FtpListOption.Modify or FtpListOption.SizeModify to GetListing() to retrieve the modification time.");
                }
            }

            if (m.Groups["size"].Value.Length > 0)
            {
                long size;

                if (long.TryParse(m.Groups["size"].Value, out size))
                {
                    item.Size = size;
                }
            }

            if (m.Groups["permissions"].Value.Length > 0)
            {
                Match perms = Regex.Match(m.Groups["permissions"].Value,
                                          @"[\w-]{1}(?<owner>[\w-]{3})(?<group>[\w-]{3})(?<others>[\w-]{3})",
                                          RegexOptions.IgnoreCase);

                if (perms.Success)
                {
                    if (perms.Groups["owner"].Value.Length == 3)
                    {
                        if (perms.Groups["owner"].Value[0] == 'r')
                        {
                            item.OwnerPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["owner"].Value[1] == 'w')
                        {
                            item.OwnerPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["owner"].Value[2] == 'x' || perms.Groups["owner"].Value[2] == 's')
                        {
                            item.OwnerPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["owner"].Value[2] == 's' || perms.Groups["owner"].Value[2] == 'S')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.SetUserID;
                        }
                    }

                    if (perms.Groups["group"].Value.Length == 3)
                    {
                        if (perms.Groups["group"].Value[0] == 'r')
                        {
                            item.GroupPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["group"].Value[1] == 'w')
                        {
                            item.GroupPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["group"].Value[2] == 'x' || perms.Groups["group"].Value[2] == 's')
                        {
                            item.GroupPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["group"].Value[2] == 's' || perms.Groups["group"].Value[2] == 'S')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.SetGroupID;
                        }
                    }

                    if (perms.Groups["others"].Value.Length == 3)
                    {
                        if (perms.Groups["others"].Value[0] == 'r')
                        {
                            item.OthersPermissions |= FtpPermission.Read;
                        }
                        if (perms.Groups["others"].Value[1] == 'w')
                        {
                            item.OthersPermissions |= FtpPermission.Write;
                        }
                        if (perms.Groups["others"].Value[2] == 'x' || perms.Groups["others"].Value[2] == 't')
                        {
                            item.OthersPermissions |= FtpPermission.Execute;
                        }
                        if (perms.Groups["others"].Value[2] == 't' || perms.Groups["others"].Value[2] == 'T')
                        {
                            item.SpecialPermissions |= FtpSpecialPermissions.Sticky;
                        }
                    }
                }
            }

            return(item);
        }
예제 #23
0
        /// <summary>
        /// Parses IIS DOS format listings
        /// </summary>
        /// <param name="buf">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        static FtpListItem ParseDosList(string buf, FtpCapability capabilities) {
            FtpListItem item = new FtpListItem();
            string[] datefmt = new string[] {
                "MM-dd-yy  hh:mmtt",
                "MM-dd-yyyy  hh:mmtt"
            };
            Match m;

            // directory
            if ((m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+<DIR>\s+(?<name>.*)$", RegexOptions.IgnoreCase)).Success) {
                DateTime modify;

                item.Type = FtpFileSystemObjectType.Directory;
                item.Name = m.Groups["name"].Value;

                //if (DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify))
                if (DateTime.TryParseExact(m.Groups["modify"].Value, datefmt, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify))
                    item.Modified = modify;
            }
            // file
            else if ((m = Regex.Match(buf, @"(?<modify>\d+-\d+-\d+\s+\d+:\d+\w+)\s+(?<size>\d+)\s+(?<name>.*)$", RegexOptions.IgnoreCase)).Success) {
                DateTime modify;
                long size;

                item.Type = FtpFileSystemObjectType.File;
                item.Name = m.Groups["name"].Value;

                if (long.TryParse(m.Groups["size"].Value, out size))
                    item.Size = size;

                //if (DateTime.TryParse(m.Groups["modify"].Value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify))
                if (DateTime.TryParseExact(m.Groups["modify"].Value, datefmt, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out modify))
                    item.Modified = modify;
            }
            else
                return null;

            return item;
        }
 private static void printFiles(FtpListItem[] files)
 {
     foreach (var dir in files)
     {
         Console.WriteLine(dir.Name);
     }
 }
예제 #25
0
		public bool DownloadFile(FtpListItem file)
		{
			var filePath = _settings.TempDownloadPath + file.Name;

			try
			{
				var fileExists = File.Exists(filePath);
				
				var stats = new ProgressStatistic
				{
					CurrentBytesSampleCount = 50
				};

				stats.ProgressChanged += OnProgressUpdated;
				stats.Finished += OnProgressUpdated;

				if (!_client.FileExists(file.FullName))
				{
					Log.Warn($"Attempted to download {file.Name}, but it no longer exists on the server.");
					DownloadError(new DownloadedEventArgs(new DownloadedFile {DownloadLocation = filePath, FtpListItem = file}));
					return false;
				}

				DownloadStarted(new DownloadedEventArgs(new DownloadedFile { DownloadLocation = filePath, FtpListItem = file }, stats));

				using (var local = new FileStream(filePath, fileExists ? FileMode.Append : FileMode.Create))
				{					
					using (var stream = _client.OpenRead(file.FullName, local.Position))
					{
						var args = new CopyFromArguments(stats.ProgressChange, new TimeSpan(0, 0, 1), stream.Length);
						Log.Info($"{(fileExists ? "Resuming" : "Downloading")} {file.Name}");
						local.CopyFrom(stream, args);
					}

					if (local.Length != file.Size)
					{
						throw new Exception("File reported as download, but is not complete.");
					}
				}

				Log.Info("Completed " + file.Name);

				DownloadComplete(new DownloadedEventArgs(new DownloadedFile {DownloadLocation = filePath, FtpListItem = file}, stats));

				return true;
			}

			catch (FtpException e)
			{
				DownloadError(new DownloadedEventArgs(new DownloadedFile { DownloadLocation = filePath, FtpListItem = file }));
				Log.Error("FTP error with " + file.Name);
				Log.Error(e.Message);
				TrackErrorCount(file);
				return false;
			}
			
			catch (NotSupportedException)
			{
				//The file exists, but doesn't support seeking to the end for resume.
				//Delete the existing file and try again from scratch.
				File.Delete(filePath);
				return DownloadFile(file);
			}

			catch (Exception e)
			{
				DownloadError(new DownloadedEventArgs(new DownloadedFile { DownloadLocation = filePath, FtpListItem = file }));
				Log.Error("Error with " + file.Name);
				Log.Error(e.Message);
				TrackErrorCount(file);
				return false;
			}
		}