/// <summary> /// Get the first checksum algorithm mutually supported by both servers. /// </summary> private FtpHashAlgorithm GetFirstMutualChecksum(FtpClient destination) { // special handling for HASH command which is a meta-command supporting all hash types if (HasFeature(FtpCapability.HASH) && destination.HasFeature(FtpCapability.HASH)) { if (HashAlgorithms.HasFlag(FtpHashAlgorithm.MD5) && destination.HashAlgorithms.HasFlag(FtpHashAlgorithm.MD5)) { return(FtpHashAlgorithm.MD5); } if (HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA1) && destination.HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA1)) { return(FtpHashAlgorithm.SHA1); } if (HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA256) && destination.HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA256)) { return(FtpHashAlgorithm.SHA256); } if (HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA512) && destination.HashAlgorithms.HasFlag(FtpHashAlgorithm.SHA512)) { return(FtpHashAlgorithm.SHA512); } if (HashAlgorithms.HasFlag(FtpHashAlgorithm.CRC) && destination.HashAlgorithms.HasFlag(FtpHashAlgorithm.CRC)) { return(FtpHashAlgorithm.CRC); } } // handling for non-standard specific hashing commands if (HasFeature(FtpCapability.MD5) && destination.HasFeature(FtpCapability.MD5)) { return(FtpHashAlgorithm.MD5); } if (HasFeature(FtpCapability.XMD5) && destination.HasFeature(FtpCapability.XMD5)) { return(FtpHashAlgorithm.MD5); } if (HasFeature(FtpCapability.MMD5) && destination.HasFeature(FtpCapability.MMD5)) { return(FtpHashAlgorithm.MD5); } if (HasFeature(FtpCapability.XSHA1) && destination.HasFeature(FtpCapability.XSHA1)) { return(FtpHashAlgorithm.SHA1); } if (HasFeature(FtpCapability.XSHA256) && destination.HasFeature(FtpCapability.XSHA256)) { return(FtpHashAlgorithm.SHA256); } if (HasFeature(FtpCapability.XSHA512) && destination.HasFeature(FtpCapability.XSHA512)) { return(FtpHashAlgorithm.SHA512); } if (HasFeature(FtpCapability.XCRC) && destination.HasFeature(FtpCapability.XCRC)) { return(FtpHashAlgorithm.CRC); } return(FtpHashAlgorithm.NONE); }
private void ValidateHashAlgorithm(FtpHashAlgorithm algorithm) { // if NO hashing algos or commands supported, throw here if (!HasFeature(FtpCapability.HASH) && !HasFeature(FtpCapability.MD5) && !HasFeature(FtpCapability.XMD5) && !HasFeature(FtpCapability.MMD5) && !HasFeature(FtpCapability.XSHA1) && !HasFeature(FtpCapability.XSHA256) && !HasFeature(FtpCapability.XSHA512) && !HasFeature(FtpCapability.XCRC)) { throw new FtpHashUnsupportedException(); } // only if the user has specified a certain hash algorithm var useFirst = (algorithm == FtpHashAlgorithm.NONE); if (!useFirst) { // first check if the HASH command supports the required algo if (HasFeature(FtpCapability.HASH) && HashAlgorithms.HasFlag(algorithm)) { // we are good } else { // second check if the special FTP command is supported based on the algo if (algorithm == FtpHashAlgorithm.MD5 && !HasFeature(FtpCapability.MD5) && !HasFeature(FtpCapability.XMD5) && !HasFeature(FtpCapability.MMD5)) { throw new FtpHashUnsupportedException(FtpHashAlgorithm.MD5, "MD5, XMD5, MMD5"); } if (algorithm == FtpHashAlgorithm.SHA1 && !HasFeature(FtpCapability.XSHA1)) { throw new FtpHashUnsupportedException(FtpHashAlgorithm.SHA1, "XSHA1"); } if (algorithm == FtpHashAlgorithm.SHA256 && !HasFeature(FtpCapability.XSHA256)) { throw new FtpHashUnsupportedException(FtpHashAlgorithm.SHA256, "XSHA256"); } if (algorithm == FtpHashAlgorithm.SHA512 && !HasFeature(FtpCapability.XSHA512)) { throw new FtpHashUnsupportedException(FtpHashAlgorithm.SHA512, "XSHA512"); } if (algorithm == FtpHashAlgorithm.CRC && !HasFeature(FtpCapability.XCRC)) { throw new FtpHashUnsupportedException(FtpHashAlgorithm.CRC, "XCRC"); } // we are good } } }
/// <summary> /// Retrieves a checksum of the given file using the specified checksum algorithm, or using the first available algorithm that the server supports. /// </summary> /// <remarks> /// The algorithm used goes in this order: /// 1. HASH command using the first supported algorithm. /// 2. MD5 / XMD5 / MMD5 commands /// 3. XSHA1 command /// 4. XSHA256 command /// 5. XSHA512 command /// 6. XCRC command /// </remarks> /// <param name="path">Full or relative path of the file to checksum</param> /// <param name="algorithm">Specify an algorithm that you prefer, or NONE to use the first available algorithm. If the preferred algorithm is not supported, a blank hash is returned.</param> /// <returns><see cref="FtpHash"/> object containing the value and algorithm. Use the <see cref="FtpHash.IsValid"/> property to /// determine if this command was successful. <see cref="FtpCommandException"/>s can be thrown from /// the underlying calls.</returns> /// <exception cref="FtpCommandException">The command fails</exception> public FtpHash GetChecksum(string path, FtpHashAlgorithm algorithm = FtpHashAlgorithm.NONE) { if (path == null) { throw new ArgumentException("Required argument is null", "path"); } ValidateHashAlgorithm(algorithm); path = path.GetFtpPath(); LogFunc(nameof(GetChecksum), new object[] { path }); var useFirst = (algorithm == FtpHashAlgorithm.NONE); // if HASH is supported and the caller prefers an algorithm and that algorithm is supported if (HasFeature(FtpCapability.HASH) && !useFirst && HashAlgorithms.HasFlag(algorithm)) { // switch to that algorithm SetHashAlgorithmInternal(algorithm); // get the hash of the file using HASH Command return(HashCommandInternal(path)); } // if HASH is supported and the caller does not prefer any specific algorithm else if (HasFeature(FtpCapability.HASH) && useFirst) { // switch to the first preferred algorithm SetHashAlgorithmInternal(HashAlgos.FirstSupported(HashAlgorithms)); // get the hash of the file using HASH Command return(HashCommandInternal(path)); } else { var result = new FtpHash(); // execute the first available algorithm, or the preferred algorithm if specified if (HasFeature(FtpCapability.MD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetHashInternal(path, "MD5"); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetHashInternal(path, "XMD5"); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.MMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetHashInternal(path, "MMD5"); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XSHA1) && (useFirst || algorithm == FtpHashAlgorithm.SHA1)) { result.Value = GetHashInternal(path, "XSHA1"); result.Algorithm = FtpHashAlgorithm.SHA1; } else if (HasFeature(FtpCapability.XSHA256) && (useFirst || algorithm == FtpHashAlgorithm.SHA256)) { result.Value = GetHashInternal(path, "XSHA256"); result.Algorithm = FtpHashAlgorithm.SHA256; } else if (HasFeature(FtpCapability.XSHA512) && (useFirst || algorithm == FtpHashAlgorithm.SHA512)) { result.Value = GetHashInternal(path, "XSHA512"); result.Algorithm = FtpHashAlgorithm.SHA512; } else if (HasFeature(FtpCapability.XCRC) && (useFirst || algorithm == FtpHashAlgorithm.CRC)) { result.Value = GetHashInternal(path, "XCRC"); result.Algorithm = FtpHashAlgorithm.CRC; } return(result); } }
/// <summary> /// Retrieves a checksum of the given file using the specified checksum algorithum, or using the first available algorithm that the server supports. /// </summary> /// <remarks> /// The algorithm used goes in this order: /// 1. HASH command; server preferred algorithm. See <see cref="FtpClient.SetHashAlgorithm"/> /// 2. MD5 / XMD5 / MMD5 commands /// 3. XSHA1 command /// 4. XSHA256 command /// 5. XSHA512 command /// 6. XCRC command /// </remarks> /// <param name="path">Full or relative path of the file to checksum</param> /// <param name="token">The token that can be used to cancel the entire process</param> /// <param name="algorithm">Specify an algorithm that you prefer, or NONE to use the first available algorithm. If the preferred algorithm is not supported, a blank hash is returned.</param> /// <returns><see cref="FtpHash"/> object containing the value and algorithm. Use the <see cref="FtpHash.IsValid"/> property to /// determine if this command was successful. <see cref="FtpCommandException"/>s can be thrown from /// the underlying calls.</returns> /// <example><code source="..\Examples\GetChecksum.cs" lang="cs" /></example> /// <exception cref="FtpCommandException">The command fails</exception> public async Task <FtpHash> GetChecksumAsync(string path, CancellationToken token = default(CancellationToken), FtpHashAlgorithm algorithm = FtpHashAlgorithm.NONE) { // if HASH is supported and the caller prefers an algorithm and that algorithm is supported var useFirst = algorithm == FtpHashAlgorithm.NONE; if (HasFeature(FtpCapability.HASH) && !useFirst && HashAlgorithms.HasFlag(algorithm)) { // switch to that algorithm await SetHashAlgorithmAsync(algorithm, token); // get the hash of the file return(await GetHashAsync(path, token)); } // if HASH is supported and the caller does not prefer any specific algorithm else if (HasFeature(FtpCapability.HASH) && useFirst) { return(await GetHashAsync(path, token)); } else { var result = new FtpHash(); // execute the first available algorithm, or the preferred algorithm if specified if (HasFeature(FtpCapability.MD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = await GetMD5Async(path, token); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = await GetXMD5Async(path, token); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.MMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = await GetMD5Async(path, token); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XSHA1) && (useFirst || algorithm == FtpHashAlgorithm.SHA1)) { result.Value = await GetXSHA1Async(path, token); result.Algorithm = FtpHashAlgorithm.SHA1; } else if (HasFeature(FtpCapability.XSHA256) && (useFirst || algorithm == FtpHashAlgorithm.SHA256)) { result.Value = await GetXSHA256Async(path, token); result.Algorithm = FtpHashAlgorithm.SHA256; } else if (HasFeature(FtpCapability.XSHA512) && (useFirst || algorithm == FtpHashAlgorithm.SHA512)) { result.Value = await GetXSHA512Async(path, token); result.Algorithm = FtpHashAlgorithm.SHA512; } else if (HasFeature(FtpCapability.XCRC) && (useFirst || algorithm == FtpHashAlgorithm.CRC)) { result.Value = await GetXCRCAsync(path, token); result.Algorithm = FtpHashAlgorithm.CRC; } return(result); } }
/// <summary> /// Retrieves a checksum of the given file using the specified checksum algorithum, or using the first available algorithm that the server supports. /// </summary> /// <remarks> /// The algorithm used goes in this order: /// 1. HASH command; server preferred algorithm. See <see cref="FtpClient.SetHashAlgorithm"/> /// 2. MD5 / XMD5 / MMD5 commands /// 3. XSHA1 command /// 4. XSHA256 command /// 5. XSHA512 command /// 6. XCRC command /// </remarks> /// <param name="path">Full or relative path of the file to checksum</param> /// <param name="algorithm">Specify an algorithm that you prefer, or NONE to use the first available algorithm. If the preferred algorithm is not supported, a blank hash is returned.</param> /// <returns><see cref="FtpHash"/> object containing the value and algorithm. Use the <see cref="FtpHash.IsValid"/> property to /// determine if this command was successful. <see cref="FtpCommandException"/>s can be thrown from /// the underlying calls.</returns> /// <example><code source="..\Examples\GetChecksum.cs" lang="cs" /></example> /// <exception cref="FtpCommandException">The command fails</exception> public FtpHash GetChecksum(string path, FtpHashAlgorithm algorithm = FtpHashAlgorithm.NONE) { // if HASH is supported and the caller prefers an algorithm and that algorithm is supported var useFirst = algorithm == FtpHashAlgorithm.NONE; if (HasFeature(FtpCapability.HASH) && !useFirst && HashAlgorithms.HasFlag(algorithm)) { // switch to that algorithm SetHashAlgorithm(algorithm); // get the hash of the file return(GetHash(path)); } // if HASH is supported and the caller does not prefer any specific algorithm else if (HasFeature(FtpCapability.HASH) && useFirst) { return(GetHash(path)); } else { var result = new FtpHash(); // execute the first available algorithm, or the preferred algorithm if specified if (HasFeature(FtpCapability.MD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetMD5(path); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetXMD5(path); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.MMD5) && (useFirst || algorithm == FtpHashAlgorithm.MD5)) { result.Value = GetMD5(path); result.Algorithm = FtpHashAlgorithm.MD5; } else if (HasFeature(FtpCapability.XSHA1) && (useFirst || algorithm == FtpHashAlgorithm.SHA1)) { result.Value = GetXSHA1(path); result.Algorithm = FtpHashAlgorithm.SHA1; } else if (HasFeature(FtpCapability.XSHA256) && (useFirst || algorithm == FtpHashAlgorithm.SHA256)) { result.Value = GetXSHA256(path); result.Algorithm = FtpHashAlgorithm.SHA256; } else if (HasFeature(FtpCapability.XSHA512) && (useFirst || algorithm == FtpHashAlgorithm.SHA512)) { result.Value = GetXSHA512(path); result.Algorithm = FtpHashAlgorithm.SHA512; } else if (HasFeature(FtpCapability.XCRC) && (useFirst || algorithm == FtpHashAlgorithm.CRC)) { result.Value = GetXCRC(path); result.Algorithm = FtpHashAlgorithm.CRC; } return(result); } }