Esempio n. 1
0
        /// <summary>
        /// Parses Unix format listings
        /// </summary>
        /// <param name="client">The FTP client</param>
        /// <param name="record">A line from the listing</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        public static FtpListItem Parse(FtpClient client, string record)
        {
            // test it is a valid line, e.g. "total 342522" is invalid
            var ch = record[0];

            if (ch != FileMarker && ch != DirectoryMarker && ch != SymbolicLinkMarker)
            {
                return(null);
            }

            var values = record.SplitString();

            if (values.Length < MinFieldCount)
            {
                var msg = new StringBuilder("Unexpected number of fields in listing '");
                msg
                .Append(record)
                .Append("' - expected minimum ").Append(MinFieldCount)
                .Append(" fields but found ").Append(values.Length).Append(" fields");
                client.LogStatus(FtpTraceLevel.Verbose, msg.ToString());
                return(null);
            }

            // field pos
            var index = 0;

            // first field is perms
            string permissions;
            bool   isDir, isLink;

            ParsePermissions(values, ref index, out permissions, out isDir, out isLink);

            // some servers don't supply the link count
            var linkCount = ParseLinkCount(client, values, ref index);

            // parse owner & group permissions
            string owner, group;

            ParseOwnerGroup(values, ref index, out owner, out group);

            // parse size
            var size = ParseFileSize(client, values, ref index);

            // parse the date/time fields
            var dayOfMonth = ParseDayOfMonth(values, ref index);

            var dateTimePos  = index;
            var lastModified = DateTime.MinValue;

            ParseDateTime(client, values, ref index, dayOfMonth, ref lastModified);

            // parse name of file or dir. Extract symlink if possible
            string name       = null;
            string linkedname = null;

            ParseName(client, record, values, isLink, dayOfMonth, dateTimePos, ref name, ref linkedname);

            // create a new list item object with the parsed metadata
            var file = new FtpListItem(record, name, size, isDir, ref lastModified);

            if (isLink)
            {
                file.Type       = FtpFileSystemObjectType.Link;
                file.LinkCount  = linkCount;
                file.LinkTarget = linkedname.Trim();
            }

            file.RawGroup       = group;
            file.RawOwner       = owner;
            file.RawPermissions = permissions;
            file.CalculateUnixPermissions(permissions);
            return(file);
        }
Esempio n. 2
0
        /// <summary>
        /// Parses Unix format listings with alternate parser
        /// </summary>
        /// <param name="record">A line from the listing</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        public static FtpListItem ParseUnixAlt(FtpClient client, string record)
        {
            // test it is a valid line, e.g. "total 342522" is invalid
            var ch = record[0];

            if (ch != FileMarker && ch != DirectoryMarker && ch != SymbolicLinkMarker)
            {
                return(null);
            }

            var values = record.SplitString();

            if (values.Length < MinFieldCountAlt)
            {
                var listing = new StringBuilder("Unexpected number of fields in listing '");
                listing.Append(record)
                .Append("' - expected minimum ").Append(MinFieldCountAlt)
                .Append(" fields but found ").Append(values.Length).Append(" fields");
                throw new FormatException(listing.ToString());
            }

            // field pos
            var index = 0;

            // first field is perms
            var permissions = values[index++];

            ch = permissions[0];
            var isDir  = false;
            var isLink = false;

            if (ch == DirectoryMarker)
            {
                isDir = true;
            }
            else if (ch == SymbolicLinkMarker)
            {
                isLink = true;
            }

            var group = values[index++];

            // some servers don't supply the link count
            var linkCount = 0;

            if (char.IsDigit(values[index][0]))
            {
                // assume it is if a digit
                var linkCountStr = values[index++];
                try {
                    linkCount = int.Parse(linkCountStr);
                }
                catch (FormatException) {
                    client.LogStatus(FtpTraceLevel.Error, "Failed to parse link count: " + linkCountStr);
                }
            }

            var owner = values[index++];


            // size
            var size    = 0L;
            var sizeStr = values[index++];

            try {
                size = long.Parse(sizeStr);
            }
            catch (FormatException) {
                client.LogStatus(FtpTraceLevel.Error, "Failed to parse size: " + sizeStr);
            }

            // next 3 fields are the date time

            // we expect the month first on Unix.
            var dateTimePos  = index;
            var lastModified = DateTime.MinValue;
            var stamp        = new StringBuilder(values[index++]);

            stamp.Append('-').Append(values[index++]).Append('-');

            var field = values[index++];

            if (field.IndexOf((char)':') < 0)
            {
                stamp.Append(field);                 // year
                try {
                    lastModified = DateTime.ParseExact(stamp.ToString(), DateTimeAltFormats1, client.ListingCulture.DateTimeFormat, DateTimeStyles.None);
                }
                catch (FormatException) {
                    client.LogStatus(FtpTraceLevel.Error, "Failed to parse date string '" + stamp.ToString() + "'");
                }
            }
            else
            {
                // add the year ourselves as not present
                var year = client.ListingCulture.Calendar.GetYear(DateTime.Now);
                stamp.Append(year).Append('-').Append(field);
                try {
                    lastModified = DateTime.ParseExact(stamp.ToString(), DateTimeAltFormats2, client.ListingCulture.DateTimeFormat, DateTimeStyles.None);
                }
                catch (FormatException) {
                    client.LogStatus(FtpTraceLevel.Error, "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;

            // find the starting point of the name by finding the pos of all the date/time fields
            var pos = 0;
            var ok  = true;

            for (var i = dateTimePos; i < dateTimePos + 3; i++)
            {
                pos = record.IndexOf(values[i], pos);
                if (pos < 0)
                {
                    ok = false;
                    break;
                }
                else
                {
                    pos += values[i].Length;
                }
            }

            if (ok)
            {
                name = record.Substring(pos).Trim();
            }
            else
            {
                client.LogStatus(FtpTraceLevel.Error, "Failed to retrieve name: " + record);
            }

            // create a new list item object with the parsed metadata
            var file = new FtpListItem(record, name, size, isDir, ref lastModified);

            if (isLink)
            {
                file.Type      = FtpFileSystemObjectType.Link;
                file.LinkCount = linkCount;
            }

            file.RawGroup       = group;
            file.RawOwner       = owner;
            file.RawPermissions = permissions;
            file.CalculateUnixPermissions(permissions);
            return(file);
        }
Esempio n. 3
0
        private void lvFTPList_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(string[])))
            {
                Point        point = lvFTPList.PointToClient(new Point(e.X, e.Y));
                ListViewItem lvi   = lvFTPList.GetItemAt(point.X, point.Y);
                if (lvi != null && e.AllowedEffect == DragDropEffects.Move)
                {
                    if (tempSelected != null && tempSelected != lvi)
                    {
                        tempSelected.Selected = false;
                    }

                    FtpListItem file = lvi.Tag as FtpListItem;
                    if (file != null && file.Type == FtpFileSystemObjectType.Directory)
                    {
                        string[] filenames = e.Data.GetData(typeof(string[])) as string[];
                        if (filenames != null)
                        {
                            int renameCount = 0;
                            foreach (string filename in filenames)
                            {
                                if (file.Name != filename)
                                {
                                    string path     = Helpers.CombineURL(currentDirectory, filename);
                                    string movePath = string.Empty;
                                    if (file.Type == FtpFileSystemObjectType.Link)
                                    {
                                        if (file.Name == ".")
                                        {
                                            movePath = URLHelpers.AddSlash(filename, SlashType.Prefix, 2);
                                        }
                                        else if (file.Name == "..")
                                        {
                                            movePath = URLHelpers.AddSlash(filename, SlashType.Prefix);
                                        }
                                    }
                                    else
                                    {
                                        movePath = Helpers.CombineURL(file.FullName, filename);
                                    }

                                    if (!string.IsNullOrEmpty(movePath))
                                    {
                                        Client.Rename(path, movePath);
                                        renameCount++;
                                    }
                                }
                            }

                            if (renameCount > 0)
                            {
                                RefreshDirectory();
                            }
                        }
                    }
                }

                tempSelected = null;
            }
            else if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
                if (files != null)
                {
                    Client.UploadFiles(files, currentDirectory);
                    RefreshDirectory();
                }
            }
        }
        /// <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)
        {
            FtpListItem item  = new FtpListItem();
            Match       m     = null;
            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>.*)$";

            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(DateTimeStyles.AssumeUniversal);
            }

            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);
        }
Esempio n. 5
0
        /// <summary>
        /// Parses LIST format listings
        /// </summary>
        /// <param name="record">A line from the listing</param>
        /// <param name="capabilities">Server capabilities</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        public static FtpListItem ParseLegacy(string record, List <FtpCapability> capabilities, FtpClient client)
        {
            var 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>.*)$";
            var   item = new FtpListItem();
            Match m;

            if (!(m = Regex.Match(record, 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).Trim();
                item.Name       = item.Name.Remove(item.Name.IndexOf(" -> "));
                break;
            }


            // 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.Contains(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)
                {
                    client.LogStatus(FtpTraceLevel.Warn, "GetFtpDate() failed on " + m.Groups["modify"].Value);
                }
            }
            else
            {
                if (m.Groups["modify"].Value.Length == 0)
                {
                    client.LogStatus(FtpTraceLevel.Warn, "RegEx failed to parse modified date from " + record);
                }
                else if (item.Type == FtpFileSystemObjectType.Directory)
                {
                    client.LogStatus(FtpTraceLevel.Warn, "Modified times of directories are ignored in UNIX long listings.");
                }
                else if (capabilities.Contains(FtpCapability.MDTM))
                {
                    client.LogStatus(FtpTraceLevel.Warn, "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)
            {
                item.CalculateUnixPermissions(m.Groups["permissions"].Value);
            }

            return(item);
        }
Esempio n. 6
0
        private async Task <List <IUpdateItem> > ProcessDirectory(FtpListItem remoteDir, DirectoryInfo localDir,
                                                                  bool recursive, bool removeNotExisting, Func <FtpListItem, FileInfo, bool> versionEqualsComparer,
                                                                  CancellationToken cancellationToken)
        {
            if (remoteDir.Type != FtpFileSystemObjectType.Directory)
            {
                throw new DirectoryNotFoundException();
            }

            var results = new List <IUpdateItem>();

            var localContents = new List <FileSystemInfo>();

            if (localDir.Exists)
            {
                localContents.AddRange(localDir.GetFileSystemInfos("*", SearchOption.TopDirectoryOnly));
            }

            foreach (var remoteItem in GetSubNodes(remoteDir))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (remoteItem.Type == FtpFileSystemObjectType.Directory)
                {
                    if (recursive)
                    {
                        var localItem = localContents.OfType <DirectoryInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                        if (localItem == null)
                        {
                            localItem = new DirectoryInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                        }
                        else
                        {
                            localContents.Remove(localItem);
                        }

                        results.AddRange(await ProcessDirectory(remoteItem, localItem, recursive, removeNotExisting, versionEqualsComparer, cancellationToken));
                    }
                }
                else if (remoteItem.Type == FtpFileSystemObjectType.File)
                {
                    var itemDate = GetDate(remoteItem);
                    if (itemDate > _latestModifiedDate)
                    {
                        _latestModifiedDate = itemDate;
                    }

                    var localFile = localContents.OfType <FileInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                    if (localFile == null)
                    {
                        localFile = new FileInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                    }
                    else
                    {
                        localContents.Remove(localFile);
                    }

                    var localIsUpToDate = localFile.Exists && versionEqualsComparer(remoteItem, localFile);
                    if (!localIsUpToDate)
                    {
                        results.Add(new FtpUpdateItem(remoteItem, this, localFile));
                    }
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Remove all files that were not on the remote
            if (removeNotExisting)
            {
                results.AddRange(UpdateSourceManager.FileInfosToDeleteItems(localContents));
            }

            return(results);
        }
 /// <summary>
 /// Adds a custom file listing parser
 /// </summary>
 public static void AddCustomParser()
 {
     FtpListItem.AddParser(new FtpListItem.Parser(ParseUnixList));
 }
Esempio n. 8
0
        /// <summary>
        /// Parses Vax/VMS format listings
        /// </summary>
        /// <param name="record">A line from the listing</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        public static FtpListItem Parse(FtpClient client, string record)
        {
            var values = record.SplitString();

            // skip blank lines
            if (values.Length <= 0)
            {
                return(null);
            }

            // skip line which lists Directory
            if (values.Length >= 2 && values[0].Equals(HDirectoryMarker))
            {
                return(null);
            }

            // skip line which lists Total
            if (values.Length > 0 && values[0].Equals(TotalMarker))
            {
                return(null);
            }

            if (values.Length < MinFieldCount)
            {
                return(null);
            }

            // first field is name
            var name = values[0];

            // make sure it is the name (ends with ';<INT>')
            var semiPos = name.LastIndexOf(';');

            // check for ;
            if (semiPos <= 0)
            {
                client.LogStatus(FtpTraceLevel.Verbose, "File version number not found in name '" + name + "'");
                return(null);
            }

            var nameNoVersion = name.Substring(0, semiPos);

            // check for version after ;
            var afterSemi = values[0].Substring(semiPos + 1);

            try {
                long.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
            var isDir = false;

            if (nameNoVersion.EndsWith(DirectoryMarker))
            {
                isDir = true;
                name  = nameNoVersion.Substring(0, nameNoVersion.Length - DirectoryMarker.Length);
            }

            if (!FtpListParser.VMSNameHasVersion && !isDir)
            {
                name = nameNoVersion;
            }

            // 2nd field is size USED/ALLOCATED format, or perhaps just USED
            var size = ParseFileSize(values[1]);

            // 3 & 4 fields are date time
            var lastModified = ParseDateTime(client, values[2], values[3]);

            // 5th field is [group,owner]
            string group = null;
            string owner = null;

            ParseGroupOwner(values, out group, out owner);

            // 6th field is permissions e.g. (RWED,RWED,RE,)
            var permissions = ParsePermissions(values);

            // create a new list item object with the parsed metadata
            var file = new FtpListItem(record, name, size, isDir, ref lastModified);

            file.RawGroup       = group;
            file.RawOwner       = owner;
            file.RawPermissions = permissions;
            return(file);
        }
Esempio n. 9
0
        /// <summary>
        /// Parses IBM z/OS format listings
        /// </summary>
        /// <param name="client">The FTP client</param>
        /// <param name="record">A line from the listing</param>
        /// <returns>FtpListItem if the item is able to be parsed</returns>
        public static FtpListItem Parse(FtpClient client, string record, string path)
        {
            // Skip title line - all modes have one.
            // Also set zOSListingRealm to remember the mode we are in

            // "total nnnn"
            if (record.Contains("total"))
            {
                client.zOSListingRealm = FtpZOSListRealm.Unix;
                return(null);
            }

            // "Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname"
            if (record.Contains("Volume Unit"))
            {
                client.zOSListingRealm = FtpZOSListRealm.Dataset;
                return(null);
            }

            // " Name     VV.MM   Created       Changed      Size  Init   Mod   Id"
            if (record.Contains("Name     VV.MM"))
            {
                // This is an opportunity to issue XDSS and get the LRECL, but how?
                FtpReply reply;
                string   cwd;
                // Is caller using FtpListOption.NoPath and CWD to the right place?
                if (path.Length == 0)
                {
                    cwd = client.GetWorkingDirectory();
                }
                // Caller is not using FtpListOption.NoPath, so the path can be used
                // but needs modification depending on its ending. Remove the "(...)"
                else if (path.EndsWith(")'"))
                {
                    cwd = path.Substring(0, path.IndexOf('(')) + "\'";
                }
                else if (path.EndsWith(")"))
                {
                    cwd = path.Substring(0, path.IndexOf('('));
                }
                else
                {
                    cwd = path;
                }
                if (!(reply = client.Execute("XDSS " + cwd)).Success)
                {
                    throw new FtpCommandException(reply);
                }
                // SITE PDSTYPE=PDSE RECFM=FB BLKSIZE=16000 DIRECTORY=1 LRECL=80 PRIMARY=3 SECONDARY=110 TRACKS EATTR=SYSTEM
                string[] words = reply.Message.Split(' ');
                string[] val   = words[5].Split('=');
                client.zOSListingLRECL = UInt16.Parse(val[1]);
                client.zOSListingRealm = FtpZOSListRealm.Member;
                return(null);
            }

            // "Name      Size     TTR   Alias-of AC--------- Attributes--------- Amode Rmode"
            if (record.Contains("Name      Size     TTR"))
            {
                client.zOSListingRealm = FtpZOSListRealm.MemberU;
                return(null);
            }

            if (client.zOSListingRealm == FtpZOSListRealm.Unix)
            {
                // unix mode
                //
                //total 320
                //
                return(FtpUnixParser.Parse(client, record));
            }

            if (client.zOSListingRealm == FtpZOSListRealm.Dataset)
            {
                // PS/PO mode
                //
                //Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
                //ANSYBG 3390   2020/01/03  1   15  VB   32756 32760  PS  $.ADATA.XAA
                //ANSYBH 3390   2022/02/18  1+++++  VBS  32767 27966  PS  $.BDATA.XBB
                //

                // Ignore title line AND also ignore "VSAM", "Not Mounted" and "Error determining attributes"

                if (record.Substring(51, 4).Trim() == "PO" || record.Substring(51, 4).Trim() == "PS")
                {
                    string volume          = record.Substring(0, 6);
                    string unit            = record.Substring(7, 4);
                    string referred        = record.Substring(14, 10).Trim();
                    string ext             = record.Substring(25, 2).Trim();
                    string used            = record.Substring(27, 5).Trim();
                    string recfm           = record.Substring(34, 4).Trim();
                    string lrecl           = record.Substring(39, 5).Trim();
                    string blksz           = record.Substring(45, 5).Trim();
                    string dsorg           = record.Substring(51, 4).Trim();
                    string dsname          = record.Remove(0, 56).Trim().Split(' ')[0];
                    bool   isDir           = dsorg == "PO";
                    var    lastModifiedStr = referred;
                    if (lastModifiedStr != "**NONE**")
                    {
                        lastModifiedStr += " 00:00";
                    }
                    var lastModified = ParseDateTime(client, lastModifiedStr);
                    // If "+++++" we could assume maximum "normal" size of 65535 tracks. (3.46GB)
                    // or preferably "large format sequential" of 16777215 tracks (885.38GB)
                    // This is a huge over-estimation in all probability but it cannot be helped.
                    var size = 16777216L * 56664L;
                    if (used != "+++++")
                    {
                        size = long.Parse(used) * 56664L;                         // 3390 dev bytes per track
                    }
                    var file = new FtpListItem(record, dsname, size, isDir, ref lastModified);
                    return(file);
                }
                return(null);
            }

            if (client.zOSListingRealm == FtpZOSListRealm.Member)
            {
                // Member mode
                //
                // Name     VV.MM   Created       Changed      Size  Init   Mod   Id
                //$2CPF1    01.01 2001/10/18 2001/10/18 11:58    29    29     0 QFX3076
                //

                string name    = record.Substring(0, 8).Trim();
                string changed = string.Empty;
                string records = "0";
                // Member stats may be empty
                if (record.TrimEnd().Length > 8)
                {
                    string vvmm    = record.Substring(10, 5).Trim();
                    string created = record.Substring(17, 10).Trim();
                    changed = record.Substring(27, 16).Trim();
                    records = record.Substring(44, 5).Trim();
                    string init = record.Substring(50, 5).Trim();
                    string mod  = record.Substring(56, 5).Trim();
                    string id   = record.Substring(62, 6).Trim();
                }
                bool isDir           = false;
                var  lastModifiedStr = changed;
                var  lastModified    = ParseDateTime(client, lastModifiedStr);
                var  size            = ushort.Parse(records) * client.zOSListingLRECL;
                var  file            = new FtpListItem(record, name, size, isDir, ref lastModified);
                return(file);
            }

            if (client.zOSListingRealm == FtpZOSListRealm.MemberU)
            {
                // Member Loadlib mode
                //
                // Name      Size     TTR   Alias-of AC --------- Attributes --------- Amode Rmode
                //EAGKCPT   000058   000009          00 FO             RN RU            31    ANY
                //EAGRTPRC  005F48   000011 EAGRTALT 00 FO             RN RU            31    ANY
                //

                string name            = record.Substring(0, 8).Trim();
                string changed         = string.Empty;
                string memsize         = record.Substring(10, 6);
                string TTR             = record.Substring(19, 6);
                string Alias           = record.Substring(26, 8).Trim();
                string Attributes      = record.Substring(38, 30);
                string Amode           = record.Substring(70, 2);
                string Rmode           = record.Substring(76, 3);
                bool   isDir           = false;
                var    lastModifiedStr = changed;
                var    lastModified    = ParseDateTime(client, lastModifiedStr);
                var    size            = int.Parse(memsize, System.Globalization.NumberStyles.HexNumber);
                var    file            = new FtpListItem(record, name, size, isDir, ref lastModified);
                return(file);
            }

            return(null);
        }
        private void _ftpAddFileFromPath(FtpClient client, string rootPath, string localPath, FtpListItem item)
        {
            string newPath = localPath + '/' + item.Name;

            if (item.Type == FtpFileSystemObjectType.Movie || item.Type == FtpFileSystemObjectType.File)
            {
                IMedia newmedia = AddFile(_folder + newPath, item.Modified == default(DateTime) ? item.Created : item.Modified);
                if (item.Type == FtpFileSystemObjectType.Movie)
                {
                    newmedia.Duration     = item.Size.SMPTEFramesToTimeSpan("50"); // assuming Grass Valley K2 PAL server
                    newmedia.DurationPlay = newmedia.Duration;
                }
            }
            if (IsRecursive && item.Type == FtpFileSystemObjectType.Directory)
            {
                foreach (var file in client.GetListing(rootPath + newPath))
                {
                    _ftpAddFileFromPath(client, rootPath, newPath, file);
                }
            }
        }
Esempio n. 11
0
 public FtpFileBasicProperties(FtpListItem item)
 {
     DateModified = item.RawModified < DateTime.FromFileTimeUtc(0) ? DateTimeOffset.MinValue : item.RawModified;
     ItemDate     = item.RawCreated < DateTime.FromFileTimeUtc(0) ? DateTimeOffset.MinValue : item.RawCreated;
     Size         = (ulong)item.Size;
 }
Esempio n. 12
0
        /// <summary>
        /// Get the full path of a given FTP Listing entry
        /// </summary>
        public static void CalculateFullFtpPath(this FtpListItem item, FtpClient client, string path)
        {
            // EXIT IF NO DIR PATH PROVIDED
            if (path == null)
            {
                // check if the path is absolute
                if (IsAbsolutePath(item.Name))
                {
                    item.FullName = item.Name;
                    item.Name     = item.Name.GetFtpFileName();
                }

                return;
            }

            // ONLY IF DIR PATH PROVIDED
            if (client.ServerType == FtpServer.IBMzOSFTP &&
                client.zOSListingRealm != FtpZOSListRealm.Unix)
            {
                // The user might be using GetListing("", FtpListOption.NoPath)
                // or he might be using    GetListing("not_fully_qualified_zOS path")
                // or he might be using    GetListing("'fully_qualified_zOS path'") (note the single quotes)

                // The following examples in the comments assume a current working
                // directory of 'GEEK.'.

                // If it is not a FtpZOSListRealm.Dataset, it must be FtpZOSListRealm.Member*

                // Is caller using FtpListOption.NoPath and CWD to the right place?
                if (path.Length == 0)
                {
                    if (client.zOSListingRealm == FtpZOSListRealm.Dataset)
                    {
                        // Path: ""
                        // Fullname: 'GEEK.PROJECTS.LOADLIB'
                        item.FullName = client.GetWorkingDirectory().TrimEnd('\'') + item.Name + "\'";
                    }
                    else
                    {
                        // Path: ""
                        // Fullname: 'GEEK.PROJECTS.LOADLIB(MYPROG)'
                        item.FullName = client.GetWorkingDirectory().TrimEnd('\'') + "(" + item.Name + ")\'";
                    }
                }
                // Caller is not using FtpListOption.NoPath, so the fullname can be built
                // depending on the listing realm
                else if (path[0] == '\'')
                {
                    if (client.zOSListingRealm == FtpZOSListRealm.Dataset)
                    {
                        // Path: "'GEEK.PROJECTS.LOADLIB'"
                        // Fullname: 'GEEK.PROJECTS.LOADLIB'
                        item.FullName = item.Name;
                    }
                    else
                    {
                        // Path: "'GEEK.PROJECTS.LOADLIB(*)'"
                        // Fullname: 'GEEK.PROJECTS.LOADLIB(MYPROG)'
                        item.FullName = path.Substring(0, path.Length - 4) + "(" + item.Name + ")\'";
                    }
                }
                else
                {
                    if (client.zOSListingRealm == FtpZOSListRealm.Dataset)
                    {
                        // Path: "PROJECTS.LOADLIB"
                        // Fullname: 'GEEK.PROJECTS.LOADLIB'
                        item.FullName = client.GetWorkingDirectory().TrimEnd('\'') + item.Name + '\'';
                    }
                    else
                    {
                        // Path: "PROJECTS.LOADLIB(*)"
                        // Fullname: 'GEEK.PROJECTS.LOADLIB(MYPROG)'
                        item.FullName = client.GetWorkingDirectory().TrimEnd('\'') + path.Substring(0, path.Length - 3) + "(" + item.Name + ")\'";
                    }
                }
                return;
            }
            else if (client.ServerType == FtpServer.OpenVMS &&
                     client.ServerOS == FtpOperatingSystem.VMS)
            {
                // if this is a vax/openvms file listing
                // there are no slashes in the path name
                item.FullName = path + item.Name;
            }
            else
            {
                //this.client.LogStatus(item.Name);

                // remove globbing/wildcard from path
                if (path.GetFtpFileName().Contains("*"))
                {
                    path = path.GetFtpDirectoryName();
                }

                if (path.Length == 0)
                {
                    path = client.GetWorkingDirectory();
                }

                if (item.Name != null)
                {
                    // absolute path? then ignore the path input to this method.
                    if (IsAbsolutePath(item.Name))
                    {
                        item.FullName = item.Name;
                        item.Name     = item.Name.GetFtpFileName();
                    }
                    else if (path != null)
                    {
                        item.FullName = path.GetFtpPath(item.Name);                         //.GetFtpPathWithoutGlob();
                    }
                    else
                    {
                        client.LogStatus(FtpTraceLevel.Warn, "Couldn't determine the full path of this object: " +
                                         Environment.NewLine + item.ToString());
                    }
                }

                // if a link target is set and it doesn't include an absolute path
                // then try to resolve it.
                if (item.LinkTarget != null && !item.LinkTarget.StartsWith("/"))
                {
                    if (item.LinkTarget.StartsWith("./"))
                    {
                        item.LinkTarget = path.GetFtpPath(item.LinkTarget.Remove(0, 2)).Trim();
                    }
                    else
                    {
                        item.LinkTarget = path.GetFtpPath(item.LinkTarget).Trim();
                    }
                }
            }
        }