context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Collections.Specialized;
  using System.Data;
  using System.IO;
  using System.Reflection;
  using System.Text;
  using System.Web;
  
  public class functions : System.Web.UI.Page {
   
     protected static String basepath = "/";
     protected static String mimetypesFile = "res/mime.types";
     protected static Hashtable mimetypes = null;
     private static IList sqlDrivers = null;
     private static IList queryVerbs = Array.AsReadOnly<String>("select,show,pragma".Split(new char[]{','}));
  
     public class FileComparer : IComparer {
        public int Compare(Object o1, Object o2)  {
           String n1 = (String)(map_value(o1)["name"]);
           String n2 = (String)(map_value(o2)["name"]);
           return(new CaseInsensitiveComparer().Compare(n1, n2));
        }
     }
  
     public Hashtable http_params(HttpRequest request) {
        NameValueCollection col = request.QueryString;
        Hashtable map = new Hashtable();
        String[] keys = col.AllKeys; 
        for (int i = 0; i < keys.Length; i++) {
           String key = keys[i];
           Object value = col[key];
           if (value != null && value.GetType().IsArray)
              value = ((Object[])value)[0];
           map[Server.HtmlEncode(key)] = value;
        }
        return map;
     }
  
     public bool empty_value(Object value) {
        if (value == null)
           return true;
        if (value.GetType().IsArray)
           return ((Object[])value).Length == 0;
        else if (value is ICollection)
           return ((ICollection)value).Count == 0;
        else
           return value.ToString().Trim().Equals("");
     }
     
     public Object file_stat(FileSystemInfo file, int level, bool foldersOnly) {
        bool isfolder = (file.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
        if (foldersOnly) {
           ArrayList folders = new ArrayList();
           if (isfolder) {
              DirectoryInfo dir = (file is DirectoryInfo) ? (DirectoryInfo)file : new DirectoryInfo(file.FullName);
              foreach (DirectoryInfo d in dir.GetDirectories())
                 folders.Add(d.Name);
           }
           folders.Sort();
           return folders;
        }
        else if (isfolder && level == 0) {
           ArrayList data = new ArrayList();
           DirectoryInfo dir = (file is DirectoryInfo) ? (DirectoryInfo)file : new DirectoryInfo(file.FullName);
           foreach (DirectoryInfo d in dir.GetDirectories())
              data.Add(file_stat(d, 1, foldersOnly));
           foreach (FileInfo f in dir.GetFiles())
              data.Add(file_stat(f, 1, foldersOnly));
           data.Sort(new FileComparer());
           return data;
        }
        else {
           String name = file.Name;
           String type = isfolder ? "inode/directory" : file_mimetype(name);
           Hashtable map = new Hashtable();
           map["name"] = name;
           map["modified"]  = file.LastWriteTime;
           map["type"] = type;
           if (file is FileInfo) {
              try { map["size"] = ((FileInfo)file).Length; } 
              catch (Exception e) {}
           }
           return map;
        }
     }
  
     public String file_read(String path) {
        FileInfo file = new FileInfo(path);
        if (!file.Exists)
           return "Cannot read "+path+" because it does not exists";
        else if ((file.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
           return "Cannot read "+path+" because it is a directory";
        else {
           try {
              int size = (int)file.Length;
              byte[] buffer = new byte[size];
              FileStream input = file.OpenRead();
              input.Read(buffer, 0, size);
              input.Close();
              return System.Text.Encoding.UTF8.GetString(buffer);
           }
           catch (Exception e) { return e.ToString(); }
        }
     }
  
     public String file_mimetype(String name) {
        if (mimetypes == null) {
           String[] lines = file_read(mimetypesFile).Replace('\t', ' ').Split("\n".ToCharArray());
           mimetypes = new Hashtable();
           foreach (String ln in lines) {
              int i = ln.IndexOf('#');
              String line = ((i >= 0) ? ln.Substring(0, i) : ln).Trim();
              if (line.Equals(""))
                 continue;
              String[] tokens = line.Split(" ".ToCharArray());
              String type = null;
              foreach (String token in tokens) {
                 if (token.Equals(""))
                    continue;
                 else if (type == null)
                    type = token;
                 else if (mimetypes[token] == null)
                    mimetypes[token] = type;
              }
           }
        }
        
        String ext = "";
        if (name != null && !name.Equals("")) {
           String[] parts = name.Split((""+Path.DirectorySeparatorChar).ToCharArray());
           parts = parts[parts.Length-1].Split(".".ToCharArray());
           if (parts.Length > 1)
              ext = parts[parts.Length-1];
        }
        String t = (String)mimetypes[ext];
        return (t == null) ? (String)mimetypes["txt"] : t;
     }
     
     private FileSystemInfo file_value(Object path) {
        if (path is FileSystemInfo)
           return (FileSystemInfo)path;
        else if (path == null)
           path = "";
        FileInfo f = new FileInfo(path.ToString());
        if (f.Exists) return f;
        DirectoryInfo d = new DirectoryInfo(path.ToString());
        if (d.Exists) return d;
        return f;
     }
  
     public FileSystemInfo file_path(String basepath, String path) {
        if (path[0] != Path.DirectorySeparatorChar)
           path = Path.DirectorySeparatorChar + path;
        return file_value(basepath + path);
     }
  
     public bool file_exists(Object path) {
        return file_value(path).Exists;
     }
     
     public void file_save(Object path, Object data) {
        byte[] bytes;
        if (data == null) {
           File.Delete(path.ToString());
           return;
        }
        else if (data is IDictionary) {
           IDictionary map = (IDictionary)data;
           Object t = map["type"];
           Object b = map["bytes"];
           if (t == null || b == null)
              throw new ApplicationException("Missing type or bytes properties for data");
           else if (t.Equals("ascii"))
              bytes = new System.Text.UTF8Encoding().GetBytes(b.ToString());
     /**
           else if (t.Equals("base64"))
              ;
           else if (t.Equals("hexa"))
              ;
           else if (t.Equals("binary"))
              ;
     **/
           else
              throw new ApplicationException("Unknown data type: "+t);
        }
        else
           bytes = new System.Text.UTF8Encoding().GetBytes(data.ToString());
           
        FileStream output = new FileStream(path.ToString(), FileMode.Create, FileAccess.Write);   
        output.Write(bytes, 0, bytes.Length);
        output.Close();
     }
      
     public IDbConnection sql_open(Hashtable param) {
        String driver = (String)param["driver"];
        if (driver == null || driver.Equals(""))
           throw new ApplicationException("Driver not specified");
        String host = (String)param["host"];
        if (host == null || host.Equals(""))
           host = "localhost";
        String password = (String)param["password"];
        if (password == null || password.Equals(""))
           password = "";
        
        IDbConnection db = null;
        if (driver.Equals("mysql")) {
           String database = (String)param["database"];
           if (database == null || database.Equals(""))
              database = "mysql";
            db = new MySql.Data.MySqlClient.MySqlConnection();
            db.ConnectionString = "server="+host+";database="+database+";uid="+param["user"]+";password="+password+";";
        }
        else if (driver.Equals("pgsql")) {
           String database = (String)param["database"];
           if (database == null || database.Equals(""))
              database = "postgres";
           String txt = "Server="+host+";Database="+database+";User ID="+param["user"]+";Password="+password+";";
           db = new Npgsql.NpgsqlConnection(txt);
        }
        else if (driver.Equals("sqlite")) {
           String database = (String)param["database"];
           if (database == null || database.Equals(""))
              database = ":memory:";
           else if (!database.StartsWith("file:"))
              database = "file:" + database;
           db = new Mono.Data.Sqlite.SqliteConnection("Data Source="+database+";version=3"); 
        }
        else
           throw new ApplicationException("Unknown driver "+driver);
           
        db.Open();
        return db;
     }
     
     public void sql_close(IDbConnection db) {
        if (db != null) {
           try { db.Close(); }
           catch (Exception e) {}
        }
     }
     
     public IList sql_query(IDbConnection db, String sql) {
        IList rows = new ArrayList();
        IDbCommand cmd = db.CreateCommand();
        cmd.CommandText = sql;
        if (!queryVerbs.Contains(sql_verb(sql))) {
           rows.Add(cmd.ExecuteNonQuery());
           return rows;
        }
        
        IDataReader rs = cmd.ExecuteReader();
        int nf = rs.FieldCount;
        while (rs.Read()) {
           IDictionary row = new Hashtable();
           rows.Add(row);
           for (int f = 0; f < nf; f++)
              row.Add(rs.GetName(f), rs.GetValue(f));
        }
        
        rs.Close();
        return rows;
     }
     
     public void sql_save(IDbConnection db, Object data, String table, String select) {
        if (data is IDictionary)
           ;
        else if (data is ICollection) {
           foreach (Object e in (ICollection)data)
              sql_save(db, e, table, select);
           return;
        }
        else if (data == null && !empty_value(select))
           data = new Hashtable();
        else
           return;
           
        IDictionary map = (IDictionary)data;
        String q1 = null;
        String q2 = null;
        String q3 = null;
        foreach (DictionaryEntry e in map) {
           String key = e.Key.ToString();
           Object val = sql_encode(e.Value);
           if (q1 == null) {
              if (!empty_value(select)) {
                 q1 = "update "+table+" set "+key+"="+val;
  
gt:                q2 = " where "+select;