Beispiel #1
0
        /// <summary>
        /// Parses the recieved hash value into the FtpHash object
        /// </summary>
        private Match ParseHashValue(FtpReply reply, FtpHash hash)
        {
            Match m;

            // Current draft says the server should return this:
            // SHA-256 0-49 169cd22282da7f147cb491e559e9dd filename.ext
            if (!(m = Regex.Match(reply.Message,
                                  @"(?<algorithm>.+)\s" +
                                  @"(?<bytestart>\d+)-(?<byteend>\d+)\s" +
                                  @"(?<hash>.+)\s" +
                                  @"(?<filename>.+)")).Success)
            {
                // Current version of FileZilla returns this:
                // SHA-1 21c2ca15cf570582949eb59fb78038b9c27ffcaf
                m = Regex.Match(reply.Message, @"(?<algorithm>.+)\s(?<hash>.+)\s");
            }

            if (m != null && m.Success)
            {
                hash.Algorithm = FtpHashAlgorithms.FromString(m.Groups["algorithm"].Value);
                hash.Value     = m.Groups["hash"].Value;
            }
            else
            {
                LogStatus(FtpTraceLevel.Warn, "Failed to parse hash from: " + reply.Message);
            }

            return(m);
        }
Beispiel #2
0
        /// <summary>
        /// Gets the hash of an object on the server using the currently selected hash algorithm.
        /// </summary>
        /// <remarks>
        /// Supported algorithms, if any, are available in the <see cref="HashAlgorithms"/>
        /// property. You should confirm that it's not equal
        /// to <see cref="FtpHashAlgorithm.NONE"/> before calling this method
        /// otherwise the server trigger a <see cref="FtpCommandException"/>
        /// due to a lack of support for the HASH command. You can
        /// set the algorithm using the <see cref="SetHashAlgorithm"/> method and
        /// you can query the server for the current hash algorithm
        /// using the <see cref="GetHashAlgorithm"/> method.
        ///
        /// This feature is experimental and based on the following draft:
        /// http://tools.ietf.org/html/draft-bryan-ftpext-hash-02
        /// </remarks>
        /// <param name="path">Full or relative path of the object to compute the hash for.</param>
        /// <returns>The hash of the file.</returns>
        /// <exception cref="FtpCommandException">
        /// Thrown if the <see cref="HashAlgorithms"/> property is <see cref="FtpHashAlgorithm.NONE"/>,
        /// the remote path does not exist, or the command cannot be executed.
        /// </exception>
        /// <exception cref="ArgumentException">Path argument is null</exception>
        /// <exception cref="NotImplementedException">Thrown when an unknown hash algorithm type is returned by the server</exception>
        /// <example><code source="..\Examples\GetHash.cs" lang="cs" /></example>
        public FtpHash GetHash(string path)
        {
            FtpReply reply;
            var      hash = new FtpHash();
            Match    m;

            if (path == null)
            {
                throw new ArgumentException("GetHash(path) argument can't be null");
            }

#if !CORE14
            lock (m_lock) {
#endif
            if (!(reply = Execute("HASH " + path.GetFtpPath())).Success)
            {
                throw new FtpCommandException(reply);
            }

#if !CORE14
        }
#endif

            // Current draft says the server should return this:
            // SHA-256 0-49 169cd22282da7f147cb491e559e9dd filename.ext
            if (!(m = Regex.Match(reply.Message,
                                  @"(?<algorithm>.+)\s" +
                                  @"(?<bytestart>\d+)-(?<byteend>\d+)\s" +
                                  @"(?<hash>.+)\s" +
                                  @"(?<filename>.+)")).Success)
            {
                // Current version of FileZilla returns this:
                // SHA-1 21c2ca15cf570582949eb59fb78038b9c27ffcaf
                m = Regex.Match(reply.Message, @"(?<algorithm>.+)\s(?<hash>.+)\s");
            }

            if (m != null && m.Success)
            {
                hash.Algorithm = FtpHashAlgorithms.FromString(m.Groups["algorithm"].Value);
                hash.Value     = m.Groups["hash"].Value;
            }
            else
            {
                LogStatus(FtpTraceLevel.Warn, "Failed to parse hash from: " + reply.Message);
            }

            return(hash);
        }
Beispiel #3
0
        /// <summary>
        /// Sets the hash algorithm on the server to be used with the HASH command asynchronously.
        /// </summary>
        /// <param name="type">Hash algorithm to use</param>
        /// <param name="token">The token that can be used to cancel the entire process</param>
        /// <exception cref="System.NotImplementedException">Thrown if the selected algorithm is not available on the server</exception>
        public async Task SetHashAlgorithmAsync(FtpHashAlgorithm type, CancellationToken token = default(CancellationToken))
        {
            FtpReply reply;
            string   algorithm;

            if ((HashAlgorithms & type) != type)
            {
                throw new NotImplementedException("The hash algorithm " + type.ToString() + " was not advertised by the server.");
            }

            algorithm = FtpHashAlgorithms.ToString(type);

            if (!(reply = await ExecuteAsync("OPTS HASH " + algorithm, token)).Success)
            {
                throw new FtpCommandException(reply);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets the currently selected hash algorithm for the HASH command asynchronously.
        /// </summary>
        /// <param name="token">The token that can be used to cancel the entire process</param>
        /// <returns>The <see cref="FtpHashAlgorithm"/> flag or <see cref="FtpHashAlgorithm.NONE"/> if there was a problem.</returns>
        public async Task <FtpHashAlgorithm> GetHashAlgorithmAsync(CancellationToken token = default(CancellationToken))
        {
            FtpReply reply;
            var      type = FtpHashAlgorithm.NONE;

            if ((reply = await ExecuteAsync("OPTS HASH", token)).Success)
            {
                try {
                    type = FtpHashAlgorithms.FromString(reply.Message);
                }
                catch (InvalidOperationException ex) {
                    // Do nothing
                }
            }

            return(type);
        }
Beispiel #5
0
        /// <summary>
        /// Gets the currently selected hash algorithm for the HASH command.
        /// </summary>
        /// <remarks>
        ///  This feature is experimental. See this link for details:
        /// http://tools.ietf.org/html/draft-bryan-ftpext-hash-02
        /// </remarks>
        /// <returns>The <see cref="FtpHashAlgorithm"/> flag or <see cref="FtpHashAlgorithm.NONE"/> if there was a problem.</returns>
        /// <example><code source="..\Examples\GetHashAlgorithm.cs" lang="cs" /></example>
        public FtpHashAlgorithm GetHashAlgorithm()
        {
            FtpReply reply;
            var      type = FtpHashAlgorithm.NONE;

#if !CORE14
            lock (m_lock) {
#endif
            if ((reply = Execute("OPTS HASH")).Success)
            {
                try {
                    type = FtpHashAlgorithms.FromString(reply.Message);
                }
                catch (InvalidOperationException ex) {
                    // Do nothing
                }
            }

#if !CORE14
        }
#endif

            return(type);
        }
Beispiel #6
0
        /// <summary>
        /// Sets the hash algorithm on the server to use for the HASH command.
        /// </summary>
        /// <remarks>
        /// If you specify an algorithm not listed in <see cref="FtpClient.HashAlgorithms"/>
        /// a <see cref="NotImplementedException"/> will be thrown
        /// so be sure to query that list of Flags before
        /// selecting a hash algorithm. Support for the
        /// HASH command is experimental. Please see
        /// the following link for more details:
        /// http://tools.ietf.org/html/draft-bryan-ftpext-hash-02
        /// </remarks>
        /// <param name="type">Hash Algorithm</param>
        /// <exception cref="System.NotImplementedException">Thrown if the selected algorithm is not available on the server</exception>
        /// <example><code source="..\Examples\SetHashAlgorithm.cs" lang="cs" /></example>
        public void SetHashAlgorithm(FtpHashAlgorithm type)
        {
            FtpReply reply;
            string   algorithm;

#if !CORE14
            lock (m_lock) {
#endif
            if ((HashAlgorithms & type) != type)
            {
                throw new NotImplementedException("The hash algorithm " + type.ToString() + " was not advertised by the server.");
            }

            algorithm = FtpHashAlgorithms.ToString(type);

            if (!(reply = Execute("OPTS HASH " + algorithm)).Success)
            {
                throw new FtpCommandException(reply);
            }

#if !CORE14
        }
#endif
        }