DevPinoy.org
A Filipino Developers Community
   
Encoding and Decoding a string to Base64 for QueryStrings

A friend of mine asked me today about encoding a string Base64. The scenario was that he has some files that he wants to be allowed for download on their company website and that he doesn't want the people who are downloading the files from his website to see where the downloads are coming from. The files are located in a folder inside the webserver outside of the virtual directory. The decision that the came up with was just to Base64 encode all the paths, pass ito to a new page via querystring and then decode that value on the download page. I gave it a shot and this is the code i gave him to serve as a guide on how he can effectively implement this.

First, we formatted the ItemTemplates of our datagrid in our default.aspx page:

<asp:DataGrid id="fileGrid" runat="server" AutoGenerateColumns="False">
    <Columns>
        <asp:TemplateColumn>
            <ItemTemplate>
                <asp:HyperLink runat="server" Text="Get" NavigateUrl='<%# HttpEncodeFilePath(DataBinder.Eval(Container, "DataItem.FullName")) %>' Target="_self">
                </asp:HyperLink>
            </ItemTemplate>
        </asp:TemplateColumn>
        <asp:BoundColumn DataField="Name" HeaderText="Filename"></asp:BoundColumn>
        <asp:BoundColumn DataField="FullName" HeaderText="Full Path"></asp:BoundColumn>
    </Columns>
</asp:DataGrid>

The reason why we formatted the grid this way is that because we would be binding the contents of a FileInfo[] to our grid.

The next thing that we need to do is setup the events inside our default.aspx page. The listing below shows the code that we used for this page:

using System;
using System.IO;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace KeithRull.Web.EncryptPath
{
    /// <summary>
    /// Encoding a string.
    /// </summary>
    public class defaultpage : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.DataGrid fileGrid;
    
        private void Page_Load(object sender, System.EventArgs e)
        {
            //check if the request is not a postback
            if(!IsPostBack)
            {
                //assign the fileinfo[] to our grid
                fileGrid.DataSource = LoadFileSystem();
                //bind it to our grid
                fileGrid.DataBind();
            }
        }
        
        /// <summary>
        /// Gets the contents of our filesystem
        /// </summary>
        /// <returns>an array of fileinfo</returns>
        private FileInfo[] LoadFileSystem()
        {
            //create our directoryinfo and set its working folder to c:\Windows
            DirectoryInfo dInfo = new DirectoryInfo(@"c:\Windows");
            //return the files in the directory that matches our filter
            return dInfo.GetFiles("*.txt");
        }
        
        /// <summary>
        /// A function that returns the Base64 encoded path
        /// </summary>
        /// <param name="filePath">the file location</param>
        /// <returns>the base64 encoded file path</returns>
        protected string HttpEncodeFilePath(object filePath)
        {
            //variable to hold our path
            string fp = filePath as string;
            //variable to olde our byte array
            string b64 = Convert.ToBase64String(StrToByteArray(fp));
            //return the formatted base64 string
            return string.Format("download.aspx?file={0}",HttpUtility.UrlEncode(b64));
        }

        /// <summary>
        /// convert a string to a byte array.
        /// </summary>
        /// <param name="str">a string to convert to bytes</param>
        /// <returns>the byte[] containing our string</returns>
        public static byte[] StrToByteArray(string str)
        {
            //create our encoder
            System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
            //the byte[] containing our string
            return encoding.GetBytes(str);
        }
        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }
        
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.Load += new System.EventHandler(this.Page_Load);

        }
        #endregion
    }
}

The last part is setting up the download.aspx page which would accept our query string. For simplicity, we have omitted the download procedure and instead we just show the decoded string to the user.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace KeithRull.Web.EncryptPath
{
    /// <summary>
    /// Decoding a Base64 string.
    /// </summary>
    public class download : System.Web.UI.Page
    {
        private void Page_Load(object sender, System.EventArgs e)
        {
            // Check if the page Is not a PostBack
            if(!IsPostBack)
            {
                //Validate if the querystring is null
                if(Request.QueryString["file"]== null)
                {
                    //redirect to the main page
                    Response.Redirect("default.aspx");
                }
                //Get the value of our querystring
                string filePath = HttpDecodeFilePath(Request.QueryString["file"]);
                //output the decoded string to the page
                Response.Write(filePath);
            }
        }
        
        /// <summary>
        /// A function used to decode our filepath
        /// </summary>
        /// <param name="filePath">the Base64 string</param>
        /// <returns>the decoded value</returns>
        protected string HttpDecodeFilePath(object filePath)
        {
            //Get the value of our filepath and URL Decode it
            string fp = HttpUtility.UrlDecode(filePath as string);
            //Convert our string back to Base64
            byte[] b64 = Convert.FromBase64String(fp);
            //return a Base64 string
            return string.Format("{0}",ByteToStringArray(b64));
        }

        /// <summary>
        /// convert a string to a byte array.
        /// </summary>
        /// <param name="byteStr">our byte string</param>
        /// <returns>the decoded base64 string</returns>
        public static string ByteToStringArray(byte[] byteStr)
        {
            //Create our encoder
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            //return our decoded string
            return enc.GetString(byteStr);
        }

        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }
        
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.Load += new System.EventHandler(this.Page_Load);
        }
        #endregion
    }
}

And there you have it. The filepath can now be pased to the download.aspx page from our default.aspx page in the form of a base64 string and then decoded back to its original state when the download.aspx page is loaded. This application is just a simple example and can be improve by using HttpHandlers instead of using the download.aspx page. Or we can implement URL re-writing instead. The focus of this demo is plainly for showing how to base64 encode strings and decoded it on the other end.

You can download the full source code of the application here: KeithRull.Web.EncryptPath.zip (15.17 KB)


Posted 03-10-2006 12:28 AM by keithrull
Filed under:

Comments

cruizer wrote re: Encoding and Decoding a string to Base64 for QueryStrings
on 03-11-2006 4:47 AM
hmm the only problem i see here is with security. i think you should also pass a parameter that contains the hash (or some kinda hash/checksum) of the filename the user wishes to download. otherwise anybody who figures out that the filenames are base64 encoded (since they're *NOT* encrypted) will be able to download anything. also...does this check for .. (parent directory) characters? they might end up downloading private files next...
keithrull wrote re: Encoding and Decoding a string to Base64 for QueryStrings
on 03-11-2006 8:52 AM
I agree!

The demo was just designed to show him how to accomplish the task he wanted to be done. it didnt include security features such as checking if the query sting value of file is from the specified download directory.

the reason why i didnt include encytption on the strings is that he just wanted it to be a simple encoding of the paths but i agreew ith you on the validity of encryption as a proper mechanism on this types of scenarios.
MisterClay wrote re: Encoding and Decoding a string to Base64 for QueryStrings
on 03-11-2006 5:56 PM
Or use salt to tighten up the encoded querystring...
dotnetkicks.com wrote Encoding and Decoding a string to Base64 for QueryStrings
on 03-29-2006 4:41 PM
Trackback from dotnetkicks.com
Chris Baker wrote re: Encoding and Decoding a string to Base64 for QueryStrings
on 09-01-2006 7:25 AM

You could do the same thing with the LosFormatter class, specifically designed for this purpose, which is less code and the resulting string is smaller. This is how Microsoft create the _ViewState hidden variable on a WebForm.

   LosFormatter lf = new LosFormatter();

   StringWriter sw = new StringWriter();

   string myPath = @"C:\StringToMyDir";

   lf.Serialize( sw, myPath );

The above produces: /wEFEEM6XFN0cmluZ1RvTXlEaXI=

Just thought you might be interested.

Lipitor and zeita. wrote Lipitor side effects.
on 08-25-2008 11:49 AM

Lipitor. Generic lipitor side effects.

Copyright DevPinoy 2005-2008