using System;
using System.Configuration;
using System.Web.UI;
using System.Web.Compilation;
using System.ComponentModel;
using System.CodeDom;
using System.IO;
using System.Security.Cryptography;

[ExpressionPrefix("CSCodee")]
public class CStringCodeeExpressionBuilder : ExpressionBuilder
{
    public CStringCodeeExpressionBuilder()
        : base()
    {
    }

    #region Décryptage
    public static string decrypte(string cs)
    {
        byte[] tab = Convert.FromBase64String(cs);
        MemoryStream m = new MemoryStream(tab);

        Rijndael algo = Rijndael.Create();
        CryptoStream cry = new CryptoStream(m, algo.CreateDecryptor(), CryptoStreamMode.Read);

        // lire le salt et l' IV
        byte[] IV = new byte[algo.IV.Length];
        byte[] salt = new byte[16];
        m.Read(salt, 0, salt.Length);
        m.Read(IV, 0, IV.Length);

        // générer la clé à partir du salt et du mot de passe
        string pwd = "abc123";
        byte[] cle;
        PasswordDeriveBytes passDerBytes = new PasswordDeriveBytes(pwd, salt);
        cle = passDerBytes.GetBytes(16);
        algo.Key = cle;
        algo.IV = IV;

        // lire les données par bloc de 256 octets
        int cb = 0;
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        byte[] buffer = new byte[256];
        do
        {
            cb = cry.Read(buffer, 0, 256);
            for (int i = 0; i < cb; i++)
                sb.Append((char)buffer[i]);
        } while (cb > 0);

        // fermer le clux
        cry.Close();

        return sb.ToString();
    }
    #endregion

    public static string GetString(string name)
    {
        //return decrypte(ConfigurationManager.ConnectionStrings[name].ConnectionString);
        return ConfigurationManager.ConnectionStrings[name].ConnectionString;
    }

    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
    {
        string name = entry.Expression; // nom de la chaîne de connexion

        Type type = entry.DeclaringType;
        PropertyDescriptor descriptor;
        descriptor = TypeDescriptor.GetProperties(type)[entry.PropertyInfo.Name];

        CodeExpression[] extab = new CodeExpression[1];
        extab[0] = new CodePrimitiveExpression(name);

        // il faudra appeler à l'évaluation de l'expression
        // la méthode statique GetString en lui passant comme paramètre
        // le nom de la chaîne de connexion
        return new CodeCastExpression(
                descriptor.PropertyType,
                new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(base.GetType()),
                "GetString", extab));
    }
}
