예제 #1
0
        /// <summary>
        /// Uses a <see cref="IDbCommand" /> to retrieve a scalar value using the given <paramref name="commandText" />.
        /// </summary>
        /// <typeparam name="TResult">The type of the expected result.</typeparam>
        /// <param name="commandText">The command text to execute.</param>
        /// <param name="connection">The connection to use for the query.</param>
        /// <param name="commandTimeout">The command timeout in seconds.</param>
        /// <returns>The result or the default value of <typeparamref name="TResult" /> if an error occurs.</returns>
        /// <exception cref="ArgumentException">
        /// Is thrown if the <paramref name="commandText" /> or <paramref name="connection" /> are invalid.
        /// </exception>
        public static async Task <TResult> GetScalarResultAsync <TResult>(string commandText, IDbConnection connection, int commandTimeout = 30)
        {
            CheckUtil.ThrowIfNull(() => connection);
            CheckUtil.ThrowIfNullOrEmpty(() => commandText);
            try
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandTimeout = commandTimeout;
                    var commandToUse = command as DbCommand;
                    CheckUtil.ThrowIfNull(() => commandToUse);
                    // ReSharper disable once PossibleNullReferenceException
                    commandToUse.CommandText = commandText;
                    var result = await commandToUse.ExecuteScalarAsync();

                    if (result == null)
                    {
                        return(default(TResult));
                    }
                    return((TResult)result);
                }
            }
            catch (Exception ex)
            {
                ExceptionCallback?.Invoke(ex);
                return(default(TResult));
            }
        }
예제 #2
0
        /// <summary>
        /// Retrieves an opened connection to a SQL server.
        /// </summary>
        /// <param name="connectionStringOrKey">The connection string or the key to a connection-string-setting in the config.</param>
        /// <param name="providerName">
        /// The name of the provider. (Leave this null, if you set
        /// <paramref name="connectionStringIsConfigKey" /> to <c>true</c>.
        /// </param>
        /// <param name="connectionStringIsConfigKey">
        /// Indicates whether  <paramref name="connectionStringOrKey" /> should be
        /// interpreted as a config-key.
        /// </param>
        /// <returns>The opened connection of <c>null</c> if an error occured.</returns>
        /// <exception cref="ArgumentException">
        /// Is thrown if the <paramref name="connectionStringOrKey" /> is empty or if no key
        /// was found in the config.
        /// </exception>
        public static async Task <IDbConnection> GetConnectionAsync(string connectionStringOrKey, bool connectionStringIsConfigKey = false, string providerName = null)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => connectionStringOrKey);
            var connectionString = connectionStringOrKey;

            if (connectionStringIsConfigKey)
            {
                // try to get connection string from config
                connectionString = ConfigurationUtil.GetConnectionString(connectionStringOrKey);
                providerName     = ConfigurationUtil.GetProviderName(connectionStringOrKey);
            }
            CheckUtil.ThrowIfNullOrEmpty(() => connectionString);
            CheckUtil.ThrowIfNullOrEmpty(() => providerName);
            // connection-string is valid
            // ReSharper disable once AssignNullToNotNullAttribute
            var factory    = DbProviderFactories.GetFactory(providerName);
            var connection = factory.CreateConnection();

            if (connection == null)
            {
                return(null);
            }
            connection.ConnectionString = connectionString;
            try
            {
                await connection.OpenAsync();

                return(connection);
            }
            catch (Exception ex)
            {
                ExceptionCallback?.Invoke(ex);
                return(null);
            }
        }
예제 #3
0
        /// <summary>
        /// Retrieves a DateTime for the given <paramref name="columnName" />.
        /// </summary>
        /// <param name="reader">The reader to extend.</param>
        /// <param name="columnName">The name of the column in the reader result.</param>
        /// <returns>The value.</returns>
        public static DateTime?GetDateTimeValue(this IDataReader reader, string columnName)
        {
            CheckUtil.ThrowIfNull(() => reader);
            CheckUtil.ThrowIfNullOrEmpty(() => columnName);
            var offset = GetColumnOffset(reader, columnName);

            return(reader.IsDBNull(offset) ? default(DateTime?) : reader.GetDateTime(offset));
        }
예제 #4
0
        /// <summary>
        /// Retrieves a value from a reader.
        /// </summary>
        /// <typeparam name="TResult">The expected result.</typeparam>
        /// <param name="reader">The reader to extend.</param>
        /// <param name="columnName">The name of the column in the reader result.</param>
        /// <returns>The value of the column.</returns>
        public static TResult GetValue <TResult>(this IDataReader reader, string columnName)
        {
            CheckUtil.ThrowIfNull(() => reader);
            CheckUtil.ThrowIfNullOrEmpty(() => columnName);
            var offset = GetColumnOffset(reader, columnName);
            var value  = reader.GetValue(offset);

            return((TResult)value);
        }
예제 #5
0
 /// <summary>
 /// Retrieves the offset of a column with the specified <paramref name="columnName" />.
 /// </summary>
 /// <param name="reader">The reader to extend.</param>
 /// <param name="columnName">The name of the column in the reader result.</param>
 /// <returns>The index of the column.</returns>
 public static int GetColumnOffset(this IDataReader reader, string columnName)
 {
     CheckUtil.ThrowIfNull(() => reader);
     CheckUtil.ThrowIfNullOrEmpty(() => columnName);
     if (reader.IsClosed)
     {
         throw new InvalidOperationException("Reader is closed");
     }
     return(reader.GetOrdinal(columnName));
 }
예제 #6
0
        /// <summary>
        /// Loads an instance of <typeparamref name="TEntity" /> from database using a unique value defined as it's
        /// <paramref name="key" />.
        /// </summary>
        /// <remarks>
        /// In order to make this method work <see cref="KeyFindExpression" /> must be defined.
        /// </remarks>
        /// <param name="key">The key-value to search for.</param>
        /// <param name="ctx">The EF context to use.</param>
        /// <returns>The instance or <c>null</c> if no item was found.</returns>
        public async Task <TEntity> LoadAsync(string key, TContext ctx = null)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => key);
            var expr = KeyFindExpression(key);

            if (expr == null)
            {
                throw new InvalidOperationException("Can not load entities of this type because no KeyFindExpression is defined.");
            }
            return(await ExecuteContextWrappedAsync(async c => await GetValidEntities(c).SingleOrDefaultAsync(expr), ctx));
        }
예제 #7
0
        /// <summary>
        /// Compares a hash of the specified plain text value to a given hash
        /// value. Plain text is hashed with the same salt value as the original
        /// hash.
        /// </summary>
        /// <param name="plainText">Plain text to be verified against the specified hash.</param>
        /// <param name="hashAlgorithm">Case-insensitve name of the hash algorithm. Allowed values are: "SHA1", "SHA256", "SHA384", "SHA512", "HMAC256", "HMAC384", "HMAC512"</param>
        /// <param name="hashValue">Base64-encoded hash value produced by ComputeHash function. This value includes the original salt appended to it.</param>
        /// <param name="urlDecode">Indicates whether the result should be URL encoded.</param>
        /// <returns><c>true</c> if the <paramref name="plainText"/> will be hashed to <paramref name="hashValue"/>, otherwise <c>false</c>.</returns>
        public static bool VerifyHash(string plainText, string hashAlgorithm, string hashValue, bool urlDecode = true)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => plainText);
            CheckUtil.ThrowIfNullOrEmpty(() => hashValue);
            CheckUtil.ThrowIfNullOrEmpty(() => hashAlgorithm);
            if (!ValidHashAlgorithms.Contains(hashAlgorithm.ToUpper(CultureInfo.InvariantCulture)))
            {
                throw new ArgumentException("Provided algorithm is unknown.", "hashAlgorithm");
            }
            var hash = GetAlgorithm(hashAlgorithm);

            if (hash == null)
            {
                throw new InvalidOperationException("Could not obtain hasher.");
            }
            // If the caller flagged this call with urlDecode we have to UrlDecode the hashValue. If not,
            // the decoded value will be the passed one. This variable is important, because at the end
            // we have to compare the given hashValue and not the decoded one.
            var decodedHashValue = hashValue;

            if (urlDecode)
            {
                decodedHashValue = WebUtility.UrlDecode(hashValue);
            }
            // Convert base64-encoded hash value into a byte array.
            var hashWithSaltBytes = Convert.FromBase64String(decodedHashValue);
            // We must know size of hash (without salt).
            var hashSizeInBytes = hash.HashSize / 8;

            // Make sure that the specified hash value is long enough.
            if (hashWithSaltBytes.Length < hashSizeInBytes)
            {
                hash.Dispose();
                return(false);
            }
            // Allocate array to hold original salt bytes retrieved from hash.
            var saltBytes = new byte[hashWithSaltBytes.Length - hashSizeInBytes];

            // Copy salt from the end of the hash to the new array.
            for (var i = 0; i < saltBytes.Length; i++)
            {
                saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];
            }
            // Compute a new hash string.
            var expectedHashString = ComputeHash(plainText, hashAlgorithm, saltBytes, urlDecode);

            hash.Dispose();
            // If the computed hash matches the specified hash, the plain text value must be correct.
            return(hashValue.Equals(expectedHashString, StringComparison.Ordinal));
        }
예제 #8
0
        /// <summary>
        /// Uploads a single image to an Azure blob.
        /// </summary>
        /// <param name="container">The storage container to use.</param>
        /// <param name="image">The image to upload,</param>
        /// <param name="remoteFileName">The name the file should have in the storage container.</param>
        /// <param name="remoteFolder">A folder name to use or create in the storage container.</param>
        /// <returns><c>true</c> if the upload succeeds otherwise <c>false</c>.</returns>
        public static async Task <bool> UploadImageAsync(CloudBlobContainer container, Image image, string remoteFileName, string remoteFolder = null)
        {
            var name = remoteFileName;

            CheckUtil.ThrowIfNullOrEmpty(() => name);
            CheckUtil.ThrowIfNull(() => image);
            if (!remoteFolder.IsNullOrEmpty())
            {
                // ReSharper disable once AssignNullToNotNullAttribute
                remoteFileName = Path.Combine(remoteFolder, remoteFileName);
            }
            var newBlob = container.GetBlockBlobReference(remoteFileName);

            newBlob.Properties.ContentType = image.GetMimeContentType();
            var bytes = image.GetByteArrayFromImage(image.RawFormat);
            await newBlob.UploadFromByteArrayAsync(bytes, 0, bytes.Length);

            return(true);
        }
예제 #9
0
        /// <summary>
        /// Encrypts a given <paramref name="plainText"/> symetrically using <see cref="RijndaelManaged"/>.
        /// </summary>
        /// <param name="plainText">The plain text.</param>
        /// <param name="key">The secret key.</param>
        /// <param name="iv">The initialization vector of the alogrithm.</param>
        /// <returns>The encrypted text coded in Base64.</returns>
        public static string EncryptText(string plainText, byte[] key, byte[] iv)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => plainText);
            CheckUtil.ThrowIfNull(() => key);
            CheckUtil.ThrowIfNull(() => iv);
            string encrypted;

            using (var rijndael = new RijndaelManaged())
            {
                rijndael.Key = key;
                rijndael.IV  = iv;
                var encryptor   = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
                var memStream   = new MemoryStream();
                var cryptStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write);
                using (var writer = new StreamWriter(cryptStream))
                {
                    writer.Write(plainText);
                }
                encrypted = Convert.ToBase64String(memStream.ToArray());
            }
            return(encrypted);
        }
예제 #10
0
        /// <summary>
        /// Decrypts a given <paramref name="cipherText"/> symetrically using <see cref="RijndaelManaged"/>.
        /// </summary>
        /// <param name="cipherText">The encrypted Base64-encoded text.</param>
        /// <param name="key">The secret key.</param>
        /// <param name="iv">The initialization vector of the alogrithm.</param>
        /// <returns>The decrypted text.</returns>
        public static string DecryptText(string cipherText, byte[] key, byte[] iv)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => cipherText);
            CheckUtil.ThrowIfNull(() => key);
            CheckUtil.ThrowIfNull(() => iv);
            string plaintext;

            using (var rijndael = new RijndaelManaged())
            {
                rijndael.Key = key;
                rijndael.IV  = iv;
                var decryptor       = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
                var cipherTextBytes = Convert.FromBase64String(cipherText);
                var memStream       = new MemoryStream(cipherTextBytes);
                var cryptStream     = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read);
                using (var reader = new StreamReader(cryptStream))
                {
                    plaintext = reader.ReadToEnd();
                }
            }
            return(plaintext);
        }
예제 #11
0
 /// <summary>
 /// Executes a given <paramref name="commandText" /> on the <paramref name="connection" />.
 /// </summary>
 /// <param name="commandText">The command text to execute.</param>
 /// <param name="connection">The connection to use for the query.</param>
 /// <param name="commandTimeout">The command timeout in seconds.</param>
 /// <returns>The amount of affected rows or -1 if an error occured.</returns>
 /// <exception cref="ArgumentException">
 /// Is thrown if the <paramref name="commandText" /> or <paramref name="connection" /> are invalid.
 /// </exception>
 public static async Task <int> ExecuteCommandAsync(string commandText, IDbConnection connection, int commandTimeout = 30)
 {
     CheckUtil.ThrowIfNull(() => connection);
     CheckUtil.ThrowIfNullOrEmpty(() => commandText);
     try
     {
         using (var command = connection.CreateCommand())
         {
             command.CommandTimeout = commandTimeout;
             var commandToUse = command as DbCommand;
             CheckUtil.ThrowIfNull(() => commandToUse);
             // ReSharper disable once PossibleNullReferenceException
             commandToUse.CommandText = commandText;
             return(await commandToUse.ExecuteNonQueryAsync());
         }
     }
     catch (Exception ex)
     {
         ExceptionCallback?.Invoke(ex);
         return(-1);
     }
 }
예제 #12
0
 /// <summary>
 /// Retrieves a reader for a given <paramref name="commandText" /> on the <paramref name="connection" />.
 /// </summary>
 /// <param name="commandText">The command text to execute.</param>
 /// <param name="connection">The connection to use for the query.</param>
 /// <param name="behavior">The command beavior for the reader.</param>
 /// <param name="commandTimeout">The command timeout in seconds.</param>
 /// <returns>The reader or <c>null</c> if an error occurs.</returns>
 /// <exception cref="ArgumentException">
 /// Is thrown if the <paramref name="commandText" /> or <paramref name="connection" /> are invalid.
 /// </exception>
 public static async Task <IDataReader> GetReaderAsync(string commandText, IDbConnection connection, CommandBehavior behavior = CommandBehavior.CloseConnection, int commandTimeout = 30)
 {
     CheckUtil.ThrowIfNull(() => connection);
     CheckUtil.ThrowIfNullOrEmpty(() => commandText);
     try
     {
         using (var command = connection.CreateCommand())
         {
             command.CommandTimeout = commandTimeout;
             var commandToUse = command as DbCommand;
             CheckUtil.ThrowIfNull(() => commandToUse);
             // ReSharper disable once PossibleNullReferenceException
             commandToUse.CommandText = commandText;
             return(await commandToUse.ExecuteReaderAsync(behavior));
         }
     }
     catch (Exception ex)
     {
         ExceptionCallback?.Invoke(ex);
         return(null);
     }
 }
예제 #13
0
        /// <summary>
        /// Generates a hash for the given plain text value and returns a
        /// base64-encoded result. Before the hash is computed, a random salt
        /// is generated and appended to the plain text. This salt is stored at
        /// the end of the hash value, so it can be used later for hash
        /// verification.
        /// </summary>
        /// <param name="plainText">Plaintext value to be hashed. The function does not check whether this parameter is null.</param>
        /// <param name="hashAlgorithm">Case-insensitve name of the hash algorithm. Allowed values are: "SHA1", "SHA256", "SHA384", "SHA512", "HMAC256", "HMAC384", "HMAC512"</param>
        /// <param name="salt">Salt bytes. This parameter can be null, in which case a random salt value will be generated.</param>
        /// <param name="urlEncode">Indicates whether the result should be URL encoded.</param>
        /// <returns>Hash value formatted as a base64-encoded string.</returns>
        public static string ComputeHash(string plainText, string hashAlgorithm, byte[] salt, bool urlEncode = true)
        {
            CheckUtil.ThrowIfNullOrEmpty(() => plainText);
            if (string.IsNullOrEmpty(hashAlgorithm) || !ValidHashAlgorithms.Contains(hashAlgorithm.ToUpper(CultureInfo.InvariantCulture)))
            {
                throw new ArgumentException("Provided algorithm is unknown.", nameof(hashAlgorithm));
            }
            // If salt is not specified, generate it on the fly.
            if (salt == null)
            {
                // Generate a random number for the size of the salt.
                var randomizer = new Random();
                var saltSize   = randomizer.Next(MinSaltSize, MaxSaltSize);
                // Allocate a byte array, which will hold the salt.
                salt = new byte[saltSize];
                // Initialize a random number generator.
                var rng = new RNGCryptoServiceProvider();
                // Fill the salt with cryptographically strong byte values.
                rng.GetNonZeroBytes(salt);
            }
            else if (salt.Length < MinSaltSize || salt.Length > MaxSaltSize)
            {
                throw new ArgumentException("Salt length invalid. Must be between 4 and 16", nameof(salt));
            }
            var hash = GetAlgorithm(hashAlgorithm);

            if (hash == null)
            {
                throw new InvalidOperationException("Could not obtain hasher.");
            }
            // Convert plain text into a byte array.
            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            // Allocate array, which will hold plain text and salt.
            var plainTextWithSaltBytes = new byte[plainTextBytes.Length + salt.Length];

            // Copy plain text bytes into resulting array.
            for (var i = 0; i < plainTextBytes.Length; i++)
            {
                plainTextWithSaltBytes[i] = plainTextBytes[i];
            }
            // Append salt bytes to the resulting array.
            for (var i = 0; i < salt.Length; i++)
            {
                plainTextWithSaltBytes[plainTextBytes.Length + i] = salt[i];
            }
            // Compute hash value of our plain text with appended salt.
            var hashBytes = hash.ComputeHash(plainTextWithSaltBytes);
            // Create array which will hold hash and original salt bytes.
            var hashWithSaltBytes = new byte[hashBytes.Length + salt.Length];

            // Copy hash bytes into resulting array.
            for (var i = 0; i < hashBytes.Length; i++)
            {
                hashWithSaltBytes[i] = hashBytes[i];
            }
            // Append salt bytes to the result.
            for (var i = 0; i < salt.Length; i++)
            {
                hashWithSaltBytes[hashBytes.Length + i] = salt[i];
            }
            // Convert result into a base64-encoded string.
            var hashValue = Convert.ToBase64String(hashWithSaltBytes);

            if (urlEncode)
            {
                // Caller wants to url encode the result
                hashValue = WebUtility.UrlEncode(hashValue);
            }
            hash.Dispose();
            // Return the result.
            return(hashValue);
        }
예제 #14
0
        /// <summary>
        /// Retrieves the value for a given <paramref name="itemName"/> inside a <paramref name="groupName"/> from a <paramref name="fileName"/>.
        /// </summary>
        /// <param name="fileName">The full path to the INI-file.</param>
        /// <param name="groupName">The name of the group in which the setting is expected or <c>null</c> if the item is in no group.</param>
        /// <param name="itemName">The name of the item.</param>
        /// <param name="defaultValue">A default value if no value could be found.</param>
        /// <typeparam name="T">The type of the result.</typeparam>
        /// <returns>The value associated with the <paramref name="itemName"/>.</returns>
        /// <exception cref="FileNotFoundException">Is thrown if the file could not be found.</exception>
        /// <exception cref="InvalidOperationException">Is thrown in case of any other exception.</exception>
        public static T GetValue <T>(string fileName, string groupName, string itemName, T defaultValue = default(T))
        {
            CheckUtil.ThrowIfNullOrEmpty(() => fileName);
            CheckUtil.ThrowIfNullOrEmpty(() => itemName);
            if (!File.Exists(fileName))
            {
                throw new FileNotFoundException("Provided file not found.", fileName);
            }
            string[] linesInFile;
            try
            {
                linesInFile = File.ReadAllLines(fileName);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Error during read of file.", ex);
            }
            if (linesInFile == null || !linesInFile.Any())
            {
                throw new InvalidOperationException("Could not read from file.");
            }

            var groupSearch = string.Format(CultureInfo.InvariantCulture, "[{0}]", groupName);
            var groupFound  = !string.IsNullOrEmpty(groupName) && linesInFile.Any(line => line.Equals(groupSearch, StringComparison.OrdinalIgnoreCase));

            if (!groupFound)
            {
                return(defaultValue);
            }
            var inGroup = !string.IsNullOrEmpty(groupName);
            var retVal  = defaultValue;

            linesInFile.ToList().ForEach(
                line =>
            {
                if (line.StartsWith("["))
                {
                    // check if we will start the parsing or if we stop the complete process
                    if (inGroup)
                    {
                        // we where already inside the desired group
                        return;
                    }
                    inGroup = line.Equals(groupSearch, StringComparison.OrdinalIgnoreCase);
                }
                else
                {
                    if (inGroup && line.StartsWith(itemName, StringComparison.OrdinalIgnoreCase))
                    {
                        // this is the item we are looking for
                        var value = line.Split('=')[1].Trim();
                        if (string.IsNullOrEmpty(value))
                        {
                            return;
                        }
                        try
                        {
                            retVal = (T)Convert.ChangeType(value, typeof(T));
                        }
                        catch
                        {
                        }
                    }
                }
            });
            return(retVal);
        }