internal FTPDirectoryListEventArgs(string dirPath, FTPFile[] files) { this.dirPath = null; this.files = null; this.dirPath = dirPath; this.files = files; }
//public FtpFileInfo(EnterpriseDT.Net.Ftp.FTPFile file) //{ // this.IsDirectory = file.isDir; // this.IsFile = !this.IsDirectory; // this.Size = file.Size; // this.Name = file.Name; // this.FullName = file.Path.TrimStart('/'); // this.LastModifiedTime = file.LastModified; //} /// <summary> /// 构造 /// </summary> /// <param name="file"></param> /// <param name="path"></param> public FtpFileInfo(EnterpriseDT.Net.Ftp.FTPFile file, string path) { this.IsDirectory = file.Dir; this.IsFile = !this.IsDirectory; this.Size = file.Size; this.Name = file.Name; this.FullName = (path.TrimEnd('/') + "/" + file.Name).TrimStart('/');//file.Path.TrimStart('/'); this.LastModifiedTime = file.LastModified; }
public virtual FTPFile[] Parse(string[] fileStrings) { this.log.Debug("Parse() called using culture: " + this.parserCulture.EnglishName); FTPFile[] sourceArray = new FTPFile[fileStrings.Length]; if (fileStrings.Length == 0) { return(sourceArray); } if (!this.userSetParser && !this.parserDetected) { this.DetectParser(fileStrings); } int length = 0; for (int i = 0; i < fileStrings.Length; i++) { if ((fileStrings[i] != null) && (fileStrings[i].Trim().Length != 0)) { try { FTPFile file = null; if (this.parser.IsMultiLine()) { StringBuilder builder = new StringBuilder(fileStrings[i]); while (((i + 1) < fileStrings.Length) && (fileStrings[i + 1].IndexOf(';') < 0)) { builder.Append(" ").Append(fileStrings[i + 1]); i++; } file = this.parser.Parse(builder.ToString()); } else { file = this.parser.Parse(fileStrings[i]); } if (file != null) { if (this.timeDiff.Ticks != 0L) { file.ApplyTimeDifference(this.timeDiff); } sourceArray[length++] = file; } } catch (RestartParsingException) { this.log.Debug("Restarting parsing from first entry in list"); i = -1; length = 0; } } } FTPFile[] destinationArray = new FTPFile[length]; Array.Copy(sourceArray, 0, destinationArray, 0, length); return(destinationArray); }
/// <summary> Parse server supplied string</summary> /// <param name="raw">raw string to parse</param> /// <returns>FTPFile object representing the raw string</returns> /// <remarks>Listing look like the below: /// CFT 45056 04/12/06 14:19:31 *FILE AFTFRE1.FILE /// CFT *MEM AFTFRE1.FILE/AFTFRE1.MBR /// CFT 36864 28/11/06 15:19:30 *FILE AFTFRE2.FILE /// CFT *MEM AFTFRE2.FILE/AFTFRE2.MBR /// CFT 45056 04/12/06 14:19:37 *FILE AFTFRE6.FILE /// CFT *MEM AFTFRE6.FILE/AFTFRE6.MBR /// QSYSOPR 28672 01/12/06 20:08:04 *FILE FPKI45POK5.FILE /// QSYSOPR *MEM FPKI45POK5.FILE/FPKI45POK5.MBR /// </remarks> public override FTPFile Parse(string raw) { string[] fields = StringSplitter.Split(raw); // skip blank lines if (fields.Length <= 0) { return(null); } // return what we can for MEM if (fields.Length >= 2 && fields[1].Equals(MEM)) { DateTime lastModifiedm = DateTime.MinValue; string ownerm = fields[0]; string namem = fields[2]; FTPFile filem = new FTPFile(FTPFile.OS400, raw, namem, 0, false, ref lastModifiedm); filem.Owner = ownerm; return(filem); } if (fields.Length < MIN_EXPECTED_FIELD_COUNT) { return(null); } // first field is owner string owner = fields[0]; // next is size long size = Int64.Parse(fields[1]); string lastModifiedStr = fields[2] + " " + fields[3]; DateTime lastModified = GetLastModified(lastModifiedStr); // test is dir bool isDir = false; if (fields[4] == DIR || fields[4] == DDIR) { isDir = true; } string name = fields[5]; if (name.EndsWith("/")) { isDir = true; name = name.Substring(0, name.Length - 1); } FTPFile file = new FTPFile(FTPFile.OS400, raw, name, size, isDir, ref lastModified); file.Owner = owner; return(file); }
/// <summary> Parse server supplied string. Should be in /// form /// <![CDATA[ /// File Code EOF Last Modification Owner RWEP /// IARPTS 101 16354 18-Mar-08 15:09:12 244, 10 "nnnn" /// JENNYCB2 101 16384 10-Jul-08 11:44:56 244, 10 "nnnn" /// ]]> /// </summary> /// <param name="raw"> /// raw string to parse /// </param> public override FTPFile Parse(string raw) { if (IsHeader(raw)) { return(null); } string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_EXPECTED_FIELD_COUNT) { return(null); } string name = fields[0]; // first two fields are date time string lastModifiedStr = fields[3] + " " + fields[4]; DateTime lastModified = DateTime.MinValue; try { lastModified = DateTime.ParseExact(lastModifiedStr, formats, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + lastModifiedStr + "'"); } // dir flag bool isDir = false; long size = 0L; try { size = Int64.Parse(fields[2]); } catch (FormatException) { log.Warn("Failed to parse size: " + fields[2]); } string owner = fields[5] + fields[6]; string permissions = fields[7].Trim(trimChars); FTPFile file = new FTPFile(FTPFile.UNKNOWN, raw, name, size, isDir, ref lastModified); file.Owner = owner; file.Permissions = permissions; return(file); }
// public RemotePath() { // } public RemotePath(string path, bool isDir) { int sep = path.LastIndexOf(DIR_SEP); // store the head of the path in an FTPFile _file = new FTPFile(FTPFile.UNKNOWN, path.Substring(sep+1), isDir); // store the tail (if any) in a string if (sep>0) { _path = path.Substring(0,sep); if (_path==".") { _path=String.Empty; } else if (_path.Length>2 && _path[1]==DIR_SEP) { _path=_path.Substring(2); } } }
/// <summary> Parse an array of raw file information returned from the /// FTP server /// /// </summary> /// <param name="files"> array of strings /// </param> /// <returns> array of FTPFile objects /// </returns> internal virtual FTPFile[] Parse(string[] files) { FTPFile[] temp = new FTPFile[files.Length]; // quick check if no files returned if (files.Length == 0) { return(temp); } int count = 0; for (int i = 0; i < files.Length; i++) { try { FTPFile file = parser.Parse(files[i]); // we skip null returns - these are duff lines we know about and don't // really want to throw an exception if (file != null) { temp[count++] = file; } } catch (FormatException ex) { log.Debug(ex.Message); if (rotateParsersOnFail && count == 0) { // first error, let's try swapping parsers RotateParsers(); FTPFile file = parser.Parse(files[i]); if (file != null) { temp[count++] = file; } } // rethrow else { throw ex; } } } FTPFile[] result = new FTPFile[count]; Array.Copy(temp, 0, result, 0, count); return(result); }
private void FixPaths(FTPFile[] result, string path, string lastPart) { // add the last part of the supplied dirname to the path if // If there is more than one result returned the last part of // the supplied dirname must be a wildcard or directory name if (result.Length > 1) { if (lastPart.Length > 0 && lastPart.IndexOf('*') < 0 && lastPart.IndexOf('?') < 0) { // must have been a directory so add to path path = PathUtil.Combine(path, lastPart); } } else if (result.Length == 1) { // if the one result returned *isn't* the same as the last part of supplied dirname, // then the last part can be added to the path if (result[0].Name != lastPart) { path = PathUtil.Combine(path, lastPart); } // if the one result returned is the same, and it happens to be a file of the same // name, that's too bad, we'll get it wrong (e.g. /abc/efg.txt/efg.txt) } for (int i = 0; i < result.Length; i++) result[i].Path = path + (path.EndsWith("/") ? "" : "/") + result[i].Name; }
public static RemotePath[] FromFTPFileArray(string basepath, FTPFile[] files) { RemotePath[] result = new RemotePath[files.GetUpperBound(0)+1]; int z = 0; foreach(FTPFile file in files) { result[z] = new RemotePath(file); result[z++].Path = basepath; // result[z++].File = file; } return result; }
/// <summary> Parse server supplied string. Should be in /// form /// <![CDATA[ /// File Code EOF Last Modification Owner RWEP /// IARPTS 101 16354 18-Mar-08 15:09:12 244, 10 "nnnn" /// JENNYCB2 101 16384 10-Jul-08 11:44:56 244, 10 "nnnn" /// ]]> /// </summary> /// <param name="raw"> /// raw string to parse /// </param> public override FTPFile Parse(string raw) { if (IsHeader(raw)) return null; string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_EXPECTED_FIELD_COUNT) return null; string name = fields[0]; // first two fields are date time string lastModifiedStr = fields[3] + " " + fields[4]; DateTime lastModified = DateTime.MinValue; try { lastModified = DateTime.ParseExact(lastModifiedStr, formats, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + lastModifiedStr + "'"); } // dir flag bool isDir = false; long size = 0L; try { size = Int64.Parse(fields[2]); } catch (FormatException) { log.Warn("Failed to parse size: " + fields[2]); } string owner = fields[5] + fields[6]; string permissions = fields[7].Trim(trimChars); FTPFile file = new FTPFile(FTPFile.UNKNOWN, raw, name, size, isDir, ref lastModified); file.Owner = owner; file.Permissions = permissions; return file; }
/// <summary> /// Parse server supplied string, e.g.: /// /// -r-------- GMETECHNOLOGY 1 TSI 8 Nov 06 11:00:25 ,GMETECHNOLOGY,file02.csv,U,20071106A00001105190.txt /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) { return(null); } string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder listing = new StringBuilder("Unexpected number of fields in listing '"); listing.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); throw new FormatException(listing.ToString()); } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) { isDir = true; } else if (ch == SYMLINK_CHAR) { isLink = true; } string group = fields[index++]; // some servers don't supply the link count int linkCount = 0; if (Char.IsDigit(fields[index][0])) // assume it is if a digit { string linkCountStr = fields[index++]; try { linkCount = System.Int32.Parse(linkCountStr); } catch (FormatException) { log.Warn("Failed to parse link count: " + linkCountStr); } } string owner = fields[index++]; // size long size = 0L; string sizeStr = fields[index++]; try { size = Int64.Parse(sizeStr); } catch (FormatException) { log.Warn("Failed to parse size: " + sizeStr); } // next 3 fields are the date time // we expect the month first on Unix. int dateTimePos = index; DateTime lastModified = DateTime.MinValue; StringBuilder stamp = new StringBuilder(fields[index++]); stamp.Append('-').Append(fields[index++]).Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0) { stamp.Append(field); // year try { lastModified = DateTime.ParseExact(stamp.ToString(), format1, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } } else { // add the year ourselves as not present int year = ParsingCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); try { lastModified = DateTime.ParseExact(stamp.ToString(), format2, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } // can't be in the future - must be the previous year // add 2 days for time zones (thanks hgfischer) if (lastModified > DateTime.Now.AddDays(2)) { lastModified = lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; for (int i = dateTimePos; i < dateTimePos + 3; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { name = raw.Substring(pos).Trim(); } else { log.Warn("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.Permissions = permissions; return(file); }
/// <summary> /// Parse an array of raw file information returned from the /// FTP server /// </summary> /// <param name="fileStrings"> array of strings /// </param> /// <returns> array of FTPFile objects /// </returns> public virtual FTPFile[] Parse(string[] fileStrings) { log.Debug("Parse() called using culture: " + parserCulture.EnglishName); FTPFile[] files = new FTPFile[fileStrings.Length]; // quick check if no files returned if (fileStrings.Length == 0) return files; if (!userSetParser && !parserDetected) DetectParser(fileStrings); int count = 0; for (int i = 0; i < fileStrings.Length; i++) { if (fileStrings[i] == null || fileStrings[i].Trim().Length == 0) continue; try { FTPFile file = null; if (parser.IsMultiLine()) { // vms uses more than 1 line for some file listings. We must keep going // thru till we've got everything StringBuilder filename = new StringBuilder(fileStrings[i]); while (i+1 < fileStrings.Length && fileStrings[i+1].IndexOf(';') < 0) { filename.Append(" ").Append(fileStrings[i+1]); i++; } file = parser.Parse(filename.ToString()); } else { file = parser.Parse(fileStrings[i]); } // we skip null returns - these are duff lines we know about and don't // really want to throw an exception if (file != null) { if (timeDiff.Ticks != 0) file.ApplyTimeDifference(timeDiff); files[count++] = file; } } catch (RestartParsingException) { log.Debug("Restarting parsing from first entry in list"); i = -1; count = 0; continue; } } FTPFile[] result = new FTPFile[count]; Array.Copy(files, 0, result, 0, count); return result; }
/// <summary> Parse an array of raw file information returned from the /// FTP server /// /// </summary> /// <param name="files"> array of strings /// </param> /// <returns> array of FTPFile objects /// </returns> internal virtual FTPFile[] Parse(string[] files) { FTPFile[] temp = new FTPFile[files.Length]; // quick check if no files returned if (files.Length == 0) return temp; int count = 0; for (int i = 0; i < files.Length; i++) { try { FTPFile file = parser.Parse(files[i]); // we skip null returns - these are duff lines we know about and don't // really want to throw an exception if (file != null) { temp[count++] = file; } } catch (FormatException ex) { log.Debug(ex.Message); if (rotateParsersOnFail && count == 0) { // first error, let's try swapping parsers RotateParsers(); FTPFile file = parser.Parse(files[i]); if (file != null) temp[count++] = file; } // rethrow else throw ex; } } FTPFile[] result = new FTPFile[count]; Array.Copy(temp, 0, result, 0, count); return result; }
public virtual FTPFile PartialParse(string fileString, ArrayList allFileStrings) { if (allFileStrings.Count == 1) { log.Debug("PartialParse() called using culture: " + parserCulture.EnglishName); } bool isLastLine = fileString == null; if (!userSetParser && !parserDetected) { DetectParser((string[])allFileStrings.ToArray(typeof(string))); } if (!userSetParser && !parserDetected) { return(null); } if (fileString == null || fileString.Trim().Length == 0) { return(null); } try { FTPFile file = null; if (parser.IsMultiLine()) { // vms uses more than 1 line for some file listings. We must keep going // thru till we've got everything if (!isLastLine) { if (allFileStrings.Count < 2) { return(null); } string secondLastFileString = (string)allFileStrings[allFileStrings.Count - 2]; string lastFileString = (string)allFileStrings[allFileStrings.Count - 1]; if (lastFileString.IndexOf(';') < 0) { secondLastFileString += lastFileString; } file = parser.Parse(secondLastFileString); } else { if (allFileStrings.Count == 0) { return(null); } else { file = parser.Parse(allFileStrings[allFileStrings.Count - 1].ToString()); } } } else { file = parser.Parse(fileString); } // we skip null returns - these are duff lines we know about and don't // really want to throw an exception if (file != null) { if (timeDiff.Ticks != 0) { file.ApplyTimeDifference(timeDiff); } return(file); } else { return(null); } } catch (RestartParsingException) { throw; } }
//public List<FileInfo> GetLocalFiles() //{ // string[] filePaths = Directory.GetFiles(localRootDir); // List<FileInfo> fileList = new List<FileInfo>(); // foreach (string filePath in filePaths) // { // LocalFile file = new LocalFile(); // FileInfo fileInfo = new FileInfo(filePath); // fileList.Add(fileInfo); // } // return fileList; //} public bool compareTimes(FTPFile ftpFile, FileInfo localFile) { DateTime localTime = localFile.LastWriteTime; DateTime ftpTime = ftpFile.LastModified; return (localTime < ftpTime); }
public RemotePath(FTPFile file) { _file = file; _path = String.Empty; }
internal FTPDirectoryListEventArgs(string dirPath, FTPFile[] files, Exception ex) { this.dirPath = dirPath; this.files = files; this.ex = ex; }
/// <summary> /// Called when a directory listing has been retrieved. /// </summary> /// <param name="files">File-details.</param> /// <param name="dir">Directory name</param> /// <param name="ex">Exception thrown (if failed)</param> protected virtual void OnDirectoryListed(string dir, FTPFile[] files, Exception ex) { if (areEventsEnabled && DirectoryListed != null) { if (!PathUtil.IsAbsolute(dir)) dir = PathUtil.Combine(ServerDirectory, dir); RaiseDirectoryListed(new FTPDirectoryListEventArgs(dir, files, ex)); } }
/// <summary> /// Returns the given directory's contents as an array of <see cref="FTPFile"/> objects. /// </summary> /// <remarks> /// This method works for Windows and most Unix FTP servers. Please inform EDT /// about unusual formats (<a href="*****@*****.**">[email protected]</a>). /// </remarks> /// <param name="directory">Name of directory AND/OR filemask.</param> /// <param name="dirListCallback">Callback to notify for each listing item</param> /// <returns>An array of <see cref="FTPFile"/> objects.</returns> public virtual FTPFile[] GetFileInfos(string directory, FTPFileCallback dirListCallback) { log.Debug("GetFileInfos('" + directory + ")"); lock (clientLock) { FTPFile[] files = null; Exception ex = null; try { OnDirectoryListing(directory); isTransferringData = true; files = ActiveClient.DirDetails(directory, dirListCallback); if (files == null) files = new FTPFile[0]; } catch (Exception e) { ex = e; throw; } finally { isTransferringData = false; OnDirectoryListed(directory, files, ex); } return files; } }
/// <summary> /// Parse server supplied string, e.g.: /// /// lrwxrwxrwx 1 wuftpd wuftpd 14 Jul 22 2002 MIRRORS -> README-MIRRORS /// -rw-r--r-- 1 b173771 users 431 Mar 31 20:04 .htaccess /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) { return(null); } string[] fields = Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder listing = new StringBuilder("Unexpected number of fields in listing '"); listing.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); throw new FormatException(listing.ToString()); } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) { isDir = true; } else if (ch == SYMLINK_CHAR) { isLink = true; } // some servers don't supply the link count int linkCount = 0; if (fields.Length > MIN_FIELD_COUNT) { try { linkCount = System.Int32.Parse(fields[index++]); } catch (FormatException) { } } // owner and group string owner = fields[index++]; string group = fields[index++]; // size long size = 0L; string sizeStr = fields[index++]; try { size = Int64.Parse(sizeStr); } catch (FormatException) { throw new FormatException("Failed to parse size: " + sizeStr); } // next 3 are the date time int dateTimePos = index; System.DateTime lastModified; System.Text.StringBuilder stamp = new System.Text.StringBuilder(fields[index++]); stamp.Append('-').Append(fields[index++]).Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0) { stamp.Append(field); // year lastModified = DateTime.ParseExact(stamp.ToString(), format1, CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None); } else { // add the year ourselves as not present int year = CultureInfo.CurrentCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); lastModified = DateTime.ParseExact(stamp.ToString(), format2, CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None); // can't be in the future - must be the previous year if (lastModified > DateTime.Now) { lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; string linkedname = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; for (int i = dateTimePos; i < dateTimePos + 3; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { string remainder = raw.Substring(pos).Trim(); if (!isLink) { name = remainder; } else { // symlink, try to extract it pos = remainder.IndexOf(SYMLINK_ARROW); if (pos <= 0) { // couldn't find symlink, give up & just assign as name name = remainder; } else { int len = SYMLINK_ARROW.Length; name = remainder.Substring(0, (pos) - (0)).Trim(); if (pos + len < remainder.Length) { linkedname = remainder.Substring(pos + len); } } } } else { throw new FormatException("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.LinkedName = linkedname; file.Permissions = permissions; return(file); }
public virtual FTPFile[] GetFileInfos(string directory) { lock (this.clientLock) { FTPFile[] files = null; try { this.OnDirectoryListing(directory); this.isTransferringData = true; files = this.ActiveClient.DirDetails(directory); if (files == null) { files = new FTPFile[0]; } } finally { this.isTransferringData = false; this.OnDirectoryListed(directory, files); } return files; } }
protected virtual void OnDirectoryListed(string dir, FTPFile[] files) { if (this.areEventsEnabled && (this.DirectoryListed != null)) { if (!PathUtil.IsAbsolute(dir)) { dir = PathUtil.Combine(this.ServerDirectory, dir); } this.RaiseDirectoryListed(new FTPDirectoryListEventArgs(dir, files)); } }
/// <summary> /// Parse server supplied string, e.g.: /// /// lrwxrwxrwx 1 wuftpd wuftpd 14 Jul 22 2002 MIRRORS -> README-MIRRORS /// -rw-r--r-- 1 b173771 users 431 Mar 31 20:04 .htaccess /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) return null; string[] fields = Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder listing = new StringBuilder("Unexpected number of fields in listing '"); listing.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); throw new FormatException(listing.ToString()); } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) isDir = true; else if (ch == SYMLINK_CHAR) isLink = true; // some servers don't supply the link count int linkCount = 0; if (fields.Length > MIN_FIELD_COUNT) { try { linkCount = System.Int32.Parse(fields[index++]); } catch (FormatException) { } } // owner and group string owner = fields[index++]; string group = fields[index++]; // size long size = 0L; string sizeStr = fields[index++]; try { size = Int64.Parse(sizeStr); } catch (FormatException) { throw new FormatException("Failed to parse size: " + sizeStr); } // next 3 are the date time int dateTimePos = index; System.DateTime lastModified; System.Text.StringBuilder stamp = new System.Text.StringBuilder(fields[index++]); stamp.Append('-').Append(fields[index++]).Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0) { stamp.Append(field); // year lastModified = DateTime.ParseExact(stamp.ToString(), format1, CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None); } else { // add the year ourselves as not present int year = CultureInfo.CurrentCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); lastModified = DateTime.ParseExact(stamp.ToString(), format2, CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None); // can't be in the future - must be the previous year if (lastModified > DateTime.Now) { lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; string linkedname = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; for (int i = dateTimePos; i < dateTimePos + 3; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { string remainder = raw.Substring(pos).Trim(); if (!isLink) name = remainder; else { // symlink, try to extract it pos = remainder.IndexOf(SYMLINK_ARROW); if (pos <= 0) { // couldn't find symlink, give up & just assign as name name = remainder; } else { int len = SYMLINK_ARROW.Length; name = remainder.Substring(0, (pos) - (0)).Trim(); if (pos + len < remainder.Length) linkedname = remainder.Substring(pos + len); } } } else { throw new FormatException("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.LinkedName = linkedname; file.Permissions = permissions; return file; }
/// <summary> Parse server supplied string</summary> /// <param name="raw">raw string to parse</param> /// <returns>FTPFile object representing the raw string</returns> /// <remarks>Listing look like the below: /// OUTPUT: /// /// Directory dirname /// /// filename /// used/allocated dd-MMM-yyyy HH:mm:ss [group,owner] (PERMS) /// filename /// used/allocated dd-MMM-yyyy HH:mm:ss [group,owner] (PERMS) /// ... /// /// Total of n files, n/m blocks /// </remarks> public override FTPFile Parse(string raw) { string[] fields = StringSplitter.Split(raw); // skip blank lines if(fields.Length <= 0) return null; // skip line which lists Directory if (fields.Length >= 2 && fields[0].Equals(HDR)) return null; // skip line which lists Total if (fields.Length > 0 && fields[0].Equals(TOTAL)) return null; if (fields.Length < MIN_EXPECTED_FIELD_COUNT) return null; // first field is name string name = fields[0]; // make sure it is the name (ends with ';<INT>') int semiPos = name.LastIndexOf(';'); // check for ; if(semiPos <= 0) { log.Warn("File version number not found in name '" + name + "'"); return null; } string nameNoVersion = name.Substring(0, semiPos); // check for version after ; string afterSemi = fields[0].Substring(semiPos+1); try { Int64.Parse(afterSemi); // didn't throw exception yet, must be number // we don't use it currently but we might in future } catch(FormatException) { // don't worry about version number } // test is dir bool isDir = false; if (nameNoVersion.EndsWith(DIR)) { isDir = true; name = nameNoVersion.Substring(0, nameNoVersion.Length-DIR.Length); } if (!versionInName && !isDir) { name = nameNoVersion; } // 2nd field is size USED/ALLOCATED format, or perhaps just USED int slashPos = fields[1].IndexOf('/'); string sizeUsed = fields[1]; if (slashPos > 0) sizeUsed = fields[1].Substring(0, slashPos); long size = Int64.Parse(sizeUsed) * blocksize; // 3 & 4 fields are date time string lastModifiedStr = TweakDateString(fields); DateTime lastModified = DateTime.MinValue; try { lastModified = DateTime.Parse(lastModifiedStr.ToString(), ParsingCulture.DateTimeFormat); } catch (FormatException) { log.Warn("Failed to parse date string '" + lastModifiedStr + "'"); } // 5th field is [group,owner] string group = null; string owner = null; if (fields.Length >= 5) { if (fields[4][0] == '[' && fields[4][fields[4].Length-1] == ']') { int commaPos = fields[4].IndexOf(','); if (commaPos < 0) { owner = fields[4].Substring(1, fields[4].Length-2); group = ""; } else { group = fields[4].Substring(1, commaPos-1); owner = fields[4].Substring(commaPos+1, fields[4].Length-commaPos-2); } } } // 6th field is permissions e.g. (RWED,RWED,RE,) string permissions = null; if (fields.Length >= 6) { if (fields[5][0] == '(' && fields[5][fields[5].Length-1] == ')') { permissions = fields[5].Substring(1, fields[5].Length-2); } } FTPFile file = new FTPFile(FTPFile.VMS, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Permissions = permissions; return file; }
/// <summary> /// Parse an array of raw file information returned from the /// FTP server /// </summary> /// <param name="fileStrings"> array of strings /// </param> /// <returns> array of FTPFile objects /// </returns> public virtual FTPFile[] Parse(string[] fileStrings) { log.Debug("Parse() called using culture: " + parserCulture.EnglishName); FTPFile[] files = new FTPFile[fileStrings.Length]; // quick check if no files returned if (fileStrings.Length == 0) { return(files); } if (!userSetParser && !parserDetected) { DetectParser(fileStrings); } int count = 0; for (int i = 0; i < fileStrings.Length; i++) { if (fileStrings[i] == null || fileStrings[i].Trim().Length == 0) { continue; } try { FTPFile file = null; if (parser.IsMultiLine()) { // vms uses more than 1 line for some file listings. We must keep going // thru till we've got everything StringBuilder filename = new StringBuilder(fileStrings[i]); while (i + 1 < fileStrings.Length && fileStrings[i + 1].IndexOf(';') < 0) { filename.Append(" ").Append(fileStrings[i + 1]); i++; } file = parser.Parse(filename.ToString()); } else { file = parser.Parse(fileStrings[i]); } // we skip null returns - these are duff lines we know about and don't // really want to throw an exception if (file != null) { if (timeDiff.Ticks != 0) { file.ApplyTimeDifference(timeDiff); } files[count++] = file; } } catch (RestartParsingException) { log.Debug("Restarting parsing from first entry in list"); i = -1; count = 0; continue; } } FTPFile[] result = new FTPFile[count]; Array.Copy(files, 0, result, 0, count); return(result); }
/// <summary> /// Parse server supplied string, e.g.: /// /// lrwxrwxrwx 1 wuftpd wuftpd 14 Jul 22 2002 MIRRORS -> README-MIRRORS /// -rw-r--r-- 1 b173771 users 431 Mar 31 20:04 .htaccess /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) return null; string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder msg = new StringBuilder("Unexpected number of fields in listing '"); msg.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); log.Warn(msg.ToString()); return null; } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) isDir = true; else if (ch == SYMLINK_CHAR) isLink = true; // some servers don't supply the link count int linkCount = 0; if (Char.IsDigit(fields[index][0])) // assume it is if a digit { string linkCountStr = fields[index++]; try { linkCount = System.Int32.Parse(linkCountStr); } catch (FormatException) { log.Warn("Failed to parse link count: " + linkCountStr); } } else if (fields[index][0] == '-') // IPXOS Treck FTP server { index++; } // owner and group string owner = ""; string group = ""; // if 2 fields ahead is numeric and there's enough fields beyond (4) for // the date, then the next two fields should be the owner & group if (IsNumeric(fields[index+2]) && fields.Length-(index+2) > 4) { owner = fields[index++]; group = fields[index++]; } // no owner else if (IsNumeric(fields[index + 1]) && fields.Length - (index + 1) > 4) { group = fields[index++]; } // size long size = 0L; string sizeStr = fields[index++].Replace(".", ""); // get rid of .'s in size try { size = Int64.Parse(sizeStr); } catch (FormatException) { log.Warn("Failed to parse size: " + sizeStr); } // next 3 fields are the date time // we expect the month first on Unix. // Connect:Enterprise UNIX has a weird extra numeric field here - we test if the // next field is numeric and if so, we skip it (except we check for a BSD variant // that means it is the day of the month) int dayOfMonth = -1; if (IsNumeric(fields[index])) { // this just might be the day of month - BSD variant // we check it is <= 31 AND that the next field starts // with a letter AND the next has a ':' within it try { char[] chars = { '0' }; string str = fields[index].TrimStart(chars); dayOfMonth = Int32.Parse(fields[index]); if (dayOfMonth > 31) // can't be day of month dayOfMonth = -1; if (!(Char.IsLetter(fields[index + 1][0]))) dayOfMonth = -1; if (fields[index + 2].IndexOf(':') <= 0) dayOfMonth = -1; } catch (FormatException) { } index++; } int dateTimePos = index; DateTime lastModified = DateTime.MinValue; StringBuilder stamp = new StringBuilder(fields[index++]); stamp.Append('-'); if (dayOfMonth > 0) stamp.Append(dayOfMonth); else stamp.Append(fields[index++]); stamp.Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0 && field.IndexOf((System.Char) '.') < 0) { stamp.Append(field); // year try { lastModified = DateTime.ParseExact(stamp.ToString(), format1, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } } else { // add the year ourselves as not present int year = ParsingCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); try { lastModified = DateTime.ParseExact(stamp.ToString(), format2, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } // can't be in the future - must be the previous year // add 2 days for time zones (thanks hgfischer) if (lastModified > DateTime.Now.AddDays(2)) { lastModified = lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; string linkedname = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; int dateFieldCount = dayOfMonth > 0 ? 2 : 3; // only 2 fields left if we had a leading day of month for (int i = dateTimePos; i < dateTimePos + dateFieldCount; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { string remainder = raw.Substring(pos).Trim(); if (!isLink) name = remainder; else { // symlink, try to extract it pos = remainder.IndexOf(SYMLINK_ARROW); if (pos <= 0) { // couldn't find symlink, give up & just assign as name name = remainder; } else { int len = SYMLINK_ARROW.Length; name = remainder.Substring(0, (pos) - (0)).Trim(); if (pos + len < remainder.Length) linkedname = remainder.Substring(pos + len); } } } else { log.Warn("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.LinkedName = linkedname; file.Permissions = permissions; return file; }
/// <summary> Parse server supplied string</summary> /// <param name="raw">raw string to parse</param> /// <returns>FTPFile object representing the raw string</returns> /// <remarks>Listing look like the below: /// CFT 45056 04/12/06 14:19:31 *FILE AFTFRE1.FILE /// CFT *MEM AFTFRE1.FILE/AFTFRE1.MBR /// CFT 36864 28/11/06 15:19:30 *FILE AFTFRE2.FILE /// CFT *MEM AFTFRE2.FILE/AFTFRE2.MBR /// CFT 45056 04/12/06 14:19:37 *FILE AFTFRE6.FILE /// CFT *MEM AFTFRE6.FILE/AFTFRE6.MBR /// QSYSOPR 28672 01/12/06 20:08:04 *FILE FPKI45POK5.FILE /// QSYSOPR *MEM FPKI45POK5.FILE/FPKI45POK5.MBR /// </remarks> public override FTPFile Parse(string raw) { string[] fields = StringSplitter.Split(raw); // skip blank lines if(fields.Length <= 0) return null; // return what we can for MEM if (fields.Length >= 2 && fields[1].Equals(MEM)) { DateTime lastModifiedm = DateTime.MinValue; string ownerm = fields[0]; string namem = fields[2]; FTPFile filem = new FTPFile(FTPFile.OS400, raw, namem, 0, false, ref lastModifiedm); filem.Owner = ownerm; return filem; } if (fields.Length < MIN_EXPECTED_FIELD_COUNT) return null; // first field is owner string owner = fields[0]; // next is size long size = Int64.Parse(fields[1]); string lastModifiedStr = fields[2] + " " + fields[3]; DateTime lastModified = GetLastModified(lastModifiedStr); // test is dir bool isDir = false; if (fields[4] == DIR || fields[4] == DDIR) isDir = true; string name = fields[5]; if (name.EndsWith("/")) { isDir = true; name = name.Substring(0, name.Length - 1); } FTPFile file = new FTPFile(FTPFile.OS400, raw, name, size, isDir, ref lastModified); file.Owner = owner; return file; }
/// <summary> Parse server supplied string</summary> /// <param name="raw">raw string to parse</param> /// <returns>FTPFile object representing the raw string</returns> /// <remarks>Listing look like the below: /// OUTPUT: /// /// Directory dirname /// /// filename /// used/allocated dd-MMM-yyyy HH:mm:ss [group,owner] (PERMS) /// filename /// used/allocated dd-MMM-yyyy HH:mm:ss [group,owner] (PERMS) /// ... /// /// Total of n files, n/m blocks /// </remarks> public override FTPFile Parse(string raw) { string[] fields = StringSplitter.Split(raw); // skip blank lines if (fields.Length <= 0) { return(null); } // skip line which lists Directory if (fields.Length >= 2 && fields[0].Equals(HDR)) { return(null); } // skip line which lists Total if (fields.Length > 0 && fields[0].Equals(TOTAL)) { return(null); } if (fields.Length < MIN_EXPECTED_FIELD_COUNT) { return(null); } // first field is name string name = fields[0]; // make sure it is the name (ends with ';<INT>') int semiPos = name.LastIndexOf(';'); // check for ; if (semiPos <= 0) { log.Warn("File version number not found in name '" + name + "'"); return(null); } string nameNoVersion = name.Substring(0, semiPos); // check for version after ; string afterSemi = fields[0].Substring(semiPos + 1); try { Int64.Parse(afterSemi); // didn't throw exception yet, must be number // we don't use it currently but we might in future } catch (FormatException) { // don't worry about version number } // test is dir bool isDir = false; if (nameNoVersion.EndsWith(DIR)) { isDir = true; name = nameNoVersion.Substring(0, nameNoVersion.Length - DIR.Length); } if (!versionInName && !isDir) { name = nameNoVersion; } // 2nd field is size USED/ALLOCATED format, or perhaps just USED int slashPos = fields[1].IndexOf('/'); string sizeUsed = fields[1]; if (slashPos > 0) { sizeUsed = fields[1].Substring(0, slashPos); } long size = Int64.Parse(sizeUsed) * blocksize; // 3 & 4 fields are date time string lastModifiedStr = TweakDateString(fields); DateTime lastModified = DateTime.MinValue; try { lastModified = DateTime.Parse(lastModifiedStr.ToString(), ParsingCulture.DateTimeFormat); } catch (FormatException) { log.Warn("Failed to parse date string '" + lastModifiedStr + "'"); } // 5th field is [group,owner] string group = null; string owner = null; if (fields.Length >= 5) { if (fields[4][0] == '[' && fields[4][fields[4].Length - 1] == ']') { int commaPos = fields[4].IndexOf(','); if (commaPos < 0) { owner = fields[4].Substring(1, fields[4].Length - 2); group = ""; } else { group = fields[4].Substring(1, commaPos - 1); owner = fields[4].Substring(commaPos + 1, fields[4].Length - commaPos - 2); } } } // 6th field is permissions e.g. (RWED,RWED,RE,) string permissions = null; if (fields.Length >= 6) { if (fields[5][0] == '(' && fields[5][fields[5].Length - 1] == ')') { permissions = fields[5].Substring(1, fields[5].Length - 2); } } FTPFile file = new FTPFile(FTPFile.VMS, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Permissions = permissions; return(file); }
/// <summary> /// Parse server supplied string, e.g.: /// /// -r-------- GMETECHNOLOGY 1 TSI 8 Nov 06 11:00:25 ,GMETECHNOLOGY,file02.csv,U,20071106A00001105190.txt /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) return null; string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder listing = new StringBuilder("Unexpected number of fields in listing '"); listing.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); throw new FormatException(listing.ToString()); } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) isDir = true; else if (ch == SYMLINK_CHAR) isLink = true; string group = fields[index++]; // some servers don't supply the link count int linkCount = 0; if (Char.IsDigit(fields[index][0])) // assume it is if a digit { string linkCountStr = fields[index++]; try { linkCount = System.Int32.Parse(linkCountStr); } catch (FormatException) { log.Warn("Failed to parse link count: " + linkCountStr); } } string owner = fields[index++]; // size long size = 0L; string sizeStr = fields[index++]; try { size = Int64.Parse(sizeStr); } catch (FormatException) { log.Warn("Failed to parse size: " + sizeStr); } // next 3 fields are the date time // we expect the month first on Unix. int dateTimePos = index; DateTime lastModified = DateTime.MinValue; StringBuilder stamp = new StringBuilder(fields[index++]); stamp.Append('-').Append(fields[index++]).Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0) { stamp.Append(field); // year try { lastModified = DateTime.ParseExact(stamp.ToString(), format1, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } } else { // add the year ourselves as not present int year = ParsingCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); try { lastModified = DateTime.ParseExact(stamp.ToString(), format2, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } // can't be in the future - must be the previous year // add 2 days for time zones (thanks hgfischer) if (lastModified > DateTime.Now.AddDays(2)) { lastModified = lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; for (int i = dateTimePos; i < dateTimePos + 3; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { name = raw.Substring(pos).Trim(); } else { log.Warn("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.Permissions = permissions; return file; }
public virtual FTPFile[] Parse(string[] fileStrings) { this.log.Debug("Parse() called using culture: " + this.parserCulture.EnglishName); FTPFile[] sourceArray = new FTPFile[fileStrings.Length]; if (fileStrings.Length == 0) { return sourceArray; } if (!this.userSetParser && !this.parserDetected) { this.DetectParser(fileStrings); } int length = 0; for (int i = 0; i < fileStrings.Length; i++) { if ((fileStrings[i] != null) && (fileStrings[i].Trim().Length != 0)) { try { FTPFile file = null; if (this.parser.IsMultiLine()) { StringBuilder builder = new StringBuilder(fileStrings[i]); while (((i + 1) < fileStrings.Length) && (fileStrings[i + 1].IndexOf(';') < 0)) { builder.Append(" ").Append(fileStrings[i + 1]); i++; } file = this.parser.Parse(builder.ToString()); } else { file = this.parser.Parse(fileStrings[i]); } if (file != null) { if (this.timeDiff.Ticks != 0L) { file.ApplyTimeDifference(this.timeDiff); } sourceArray[length++] = file; } } catch (RestartParsingException) { this.log.Debug("Restarting parsing from first entry in list"); i = -1; length = 0; } } } FTPFile[] destinationArray = new FTPFile[length]; Array.Copy(sourceArray, 0, destinationArray, 0, length); return destinationArray; }
/// <summary> /// 同步方法 /// </summary> private void List_Create_Get(FTPFile dir_or_file) { string remote_path = dir_or_file.Path; string remote_file_name = dir_or_file.Name; string tmp_local_path = string.Empty; if (this.remote_sync_dir != "/") { tmp_local_path = (this.local_base_dir + remote_path.Replace(this.remote_sync_dir, "")).Replace("//", "/"); } else { tmp_local_path = (this.local_base_dir + remote_path).Replace("//", "/"); } //文件 if (dir_or_file.Dir) { connection.LocalDirectory = tmp_local_path; if (!Directory.Exists(tmp_local_path)) { Directory.CreateDirectory(tmp_local_path); PrintEventHandler("#创建文件夹#" + tmp_local_path); } //deep in FTPFile[] files = connection.GetFileInfos(remote_path); foreach (FTPFile file in files) { if (file.fileName != "." && file.fileName != "..") { List_Create_Get(file); } } } //目录 else { bool need_download = false; //本地不存在 if (!File.Exists(tmp_local_path)) { need_download = true; PrintEventHandler("#下载文件#" + tmp_local_path); } else { //本地存在 long local_file_size = new FileInfo(tmp_local_path).Length; //大小不一致 if (local_file_size != dir_or_file.Size) { need_download = true; PrintEventHandler("#更新文件#" + tmp_local_path); } } if (need_download) { PrintEventHandler("#下载文件#" + tmp_local_path); try { connection.DownloadFile(tmp_local_path, dir_or_file.Path); if (this.deleteRemote) { connection.DeleteFile(dir_or_file.Path); PrintEventHandler("#删除远程文件#" + dir_or_file.Path); } } catch (Exception e) { if (!this.CloseByHand) { PrintEventHandler("【异常】下载文件:" + e.Message); } } } else { PrintEventHandler("本地已存在,不需下载."); if (this.deleteRemote) { connection.DeleteFile(dir_or_file.Path); PrintEventHandler("#删除远程文件#" + dir_or_file.Path); } } } }
/// <summary> /// Parse server supplied string, e.g.: /// /// lrwxrwxrwx 1 wuftpd wuftpd 14 Jul 22 2002 MIRRORS -> README-MIRRORS /// -rw-r--r-- 1 b173771 users 431 Mar 31 20:04 .htaccess /// /// </summary> /// <param name="raw"> raw string to parse /// </param> public override FTPFile Parse(string raw) { // test it is a valid line, e.g. "total 342522" is invalid char ch = raw[0]; if (ch != ORDINARY_FILE_CHAR && ch != DIRECTORY_CHAR && ch != SYMLINK_CHAR) { return(null); } string[] fields = StringSplitter.Split(raw); if (fields.Length < MIN_FIELD_COUNT) { StringBuilder msg = new StringBuilder("Unexpected number of fields in listing '"); msg.Append(raw).Append("' - expected minimum ").Append(MIN_FIELD_COUNT). Append(" fields but found ").Append(fields.Length).Append(" fields"); log.Warn(msg.ToString()); return(null); } // field pos int index = 0; // first field is perms string permissions = fields[index++]; ch = permissions[0]; bool isDir = false; bool isLink = false; if (ch == DIRECTORY_CHAR) { isDir = true; } else if (ch == SYMLINK_CHAR) { isLink = true; } // some servers don't supply the link count int linkCount = 0; if (Char.IsDigit(fields[index][0])) // assume it is if a digit { string linkCountStr = fields[index++]; try { linkCount = System.Int32.Parse(linkCountStr); } catch (FormatException) { log.Warn("Failed to parse link count: " + linkCountStr); } } else if (fields[index][0] == '-') // IPXOS Treck FTP server { index++; } // owner and group string owner = ""; string group = ""; // if 2 fields ahead is numeric and there's enough fields beyond (4) for // the date, then the next two fields should be the owner & group if (IsNumeric(fields[index + 2]) && fields.Length - (index + 2) > 4) { owner = fields[index++]; group = fields[index++]; } // no owner else if (IsNumeric(fields[index + 1]) && fields.Length - (index + 1) > 4) { group = fields[index++]; } // size long size = 0L; string sizeStr = fields[index++].Replace(".", ""); // get rid of .'s in size try { size = Int64.Parse(sizeStr); } catch (FormatException) { log.Warn("Failed to parse size: " + sizeStr); } // next 3 fields are the date time // we expect the month first on Unix. // Connect:Enterprise UNIX has a weird extra numeric field here - we test if the // next field is numeric and if so, we skip it (except we check for a BSD variant // that means it is the day of the month) int dayOfMonth = -1; if (IsNumeric(fields[index])) { // this just might be the day of month - BSD variant // we check it is <= 31 AND that the next field starts // with a letter AND the next has a ':' within it try { char[] chars = { '0' }; string str = fields[index].TrimStart(chars); dayOfMonth = Int32.Parse(fields[index]); if (dayOfMonth > 31) // can't be day of month { dayOfMonth = -1; } if (!(Char.IsLetter(fields[index + 1][0]))) { dayOfMonth = -1; } if (fields[index + 2].IndexOf(':') <= 0) { dayOfMonth = -1; } } catch (FormatException) { } index++; } int dateTimePos = index; DateTime lastModified = DateTime.MinValue; StringBuilder stamp = new StringBuilder(fields[index++]); stamp.Append('-'); if (dayOfMonth > 0) { stamp.Append(dayOfMonth); } else { stamp.Append(fields[index++]); } stamp.Append('-'); string field = fields[index++]; if (field.IndexOf((System.Char) ':') < 0 && field.IndexOf((System.Char) '.') < 0) { stamp.Append(field); // year try { lastModified = DateTime.ParseExact(stamp.ToString(), format1, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } } else { // add the year ourselves as not present int year = ParsingCulture.Calendar.GetYear(DateTime.Now); stamp.Append(year).Append('-').Append(field); try { lastModified = DateTime.ParseExact(stamp.ToString(), format2, ParsingCulture.DateTimeFormat, DateTimeStyles.None); } catch (FormatException) { log.Warn("Failed to parse date string '" + stamp.ToString() + "'"); } // can't be in the future - must be the previous year // add 2 days for time zones (thanks hgfischer) if (lastModified > DateTime.Now.AddDays(2)) { lastModified = lastModified.AddYears(-1); } } // name of file or dir. Extract symlink if possible string name = null; string linkedname = null; // we've got to find the starting point of the name. We // do this by finding the pos of all the date/time fields, then // the name - to ensure we don't get tricked up by a userid the // same as the filename,for example int pos = 0; bool ok = true; int dateFieldCount = dayOfMonth > 0 ? 2 : 3; // only 2 fields left if we had a leading day of month for (int i = dateTimePos; i < dateTimePos + dateFieldCount; i++) { pos = raw.IndexOf(fields[i], pos); if (pos < 0) { ok = false; break; } else { pos += fields[i].Length; } } if (ok) { string remainder = raw.Substring(pos).Trim(); if (!isLink) { name = remainder; } else { // symlink, try to extract it pos = remainder.IndexOf(SYMLINK_ARROW); if (pos <= 0) { // couldn't find symlink, give up & just assign as name name = remainder; } else { int len = SYMLINK_ARROW.Length; name = remainder.Substring(0, (pos) - (0)).Trim(); if (pos + len < remainder.Length) { linkedname = remainder.Substring(pos + len); } } } } else { log.Warn("Failed to retrieve name: " + raw); } FTPFile file = new FTPFile(FTPFile.UNIX, raw, name, size, isDir, ref lastModified); file.Group = group; file.Owner = owner; file.Link = isLink; file.LinkCount = linkCount; file.LinkedName = linkedname; file.Permissions = permissions; return(file); }