Find.cs

// Copyright � 2007 Jeffrey Bazinet, http://www.vwd-cms.com/
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Text;
using System.Collections.Specialized;

namespace VwdCms.Admin
{
    public class Find : System.Web.UI.Page
    {
        protected System.Web.UI.HtmlControls.HtmlTableRow trSearchTitle;
        protected System.Web.UI.HtmlControls.HtmlTableRow trSearch;
        protected System.Web.UI.HtmlControls.HtmlTableRow trReplaceTitle;
        protected System.Web.UI.HtmlControls.HtmlTableRow trReplace;
        protected System.Web.UI.WebControls.Button btnSearch;
        protected System.Web.UI.WebControls.Button btnReplace;
        protected System.Web.UI.WebControls.Table tblSearch;
        protected System.Web.UI.WebControls.Table tblReplace;
        protected System.Web.UI.WebControls.TextBox txtExtensions;
        protected System.Web.UI.WebControls.CheckBox chkReplaceSave;
        protected System.Web.UI.WebControls.CheckBox chkIgnoreCase;
        protected System.Web.UI.WebControls.TextBox txtReplace;
        protected System.Web.UI.WebControls.TextBox txtSearch;
        protected VwdCms.SiteMapTree smtFolders;

        protected void Page_Load(object sender, EventArgs e)
        {
            VwdCms.Configuration.Utilities.ProtectAdminPages();

            this.trSearchTitle.Style.Add("display", "none");
            this.trSearch.Style.Add("display", "none");
            this.trReplaceTitle.Style.Add("display", "none");
            this.trReplace.Style.Add("display", "none");

            this.btnSearch.Command += new CommandEventHandler(btnSearch_Command);
            this.btnReplace.Command += new CommandEventHandler(btnSearch_Command);

            if (!this.Page.IsPostBack)
            {
                // load some default extensions
                this.txtExtensions.Text = VwdCms.Constants.LivePageExtension + ";";
                this.txtExtensions.Text += VwdCms.Constants.LiveCodeExtension + ";";
                this.txtExtensions.Text += VwdCms.Constants.DraftPageExtension + ";";
                this.txtExtensions.Text += VwdCms.Constants.DraftCodeExtension + ";";
            }
        }

        void btnSearch_Command(object sender, CommandEventArgs e)
        {
            const string SearchTextToken = "{!--searchtext--!}";

            bool save = this.chkReplaceSave.Checked;
            // always reset the chkReplaceSave to unchecked
            this.chkReplaceSave.Checked = false;

            string searchText = this.txtSearch.Text;
            if (!string.IsNullOrEmpty(searchText))
            {

                bool replace = (e.CommandName == "replace");
                bool ignoreCase = this.chkIgnoreCase.Checked;


                this.tblSearch.Rows.Clear();
                this.tblSearch.Controls.Clear();
                this.AddHeader(this.tblSearch);
                this.trSearchTitle.Style.Remove("display");
                this.trSearch.Style.Remove("display");

                this.tblReplace.Rows.Clear();
                this.tblReplace.Controls.Clear();
                if (replace)
                {
                    this.AddHeader(this.tblReplace);
                    this.trReplaceTitle.Style.Remove("display");
                    this.trReplace.Style.Remove("display");
                }

                int searchTextLen = searchText.Length;

                string replaceText = this.txtReplace.Text;

                string vpSitePath = VwdCms.Configuration.Utilities.SitePath;
                string lpSitePath = VwdCms.Configuration.Utilities.GetLocalPath(vpSitePath);


                Hashtable htExtensions = new Hashtable();
                string[] extensions = this.txtExtensions.Text.Split(';', ' ');
                if (extensions != null  extensions.Length  0)
                {
                    foreach (string ext in extensions)
                    {
                        if (!string.IsNullOrEmpty(ext))
                        {
                            htExtensions.Add(ext.ToLower(), ext);
                        }
                    }
                }

                StringCollection scFolders = GetSearchFolders();

                DirectoryInfo di = null;
                int folderCount = scFolders.Count;
                FileInfo[][] files = new FileInfo[folderCount][];
                int i = 0;
                foreach (string folder in scFolders)
                {
                    di = new DirectoryInfo(folder);
                    files[i] = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
                    i++;
                }

                int startindex = 0;
                int matchindex = 0;
                int linenum = 0;
                string[] lines = null;
                string vpFile = null;
                //bool linematch = false;
                bool filematch = false;
                string searchDisplay = null;
                string replaceDisplay = null;
                string linelower = null;
                string searchTextLower = searchText.ToLower();
                string leftpart = null;
                //string rightpart = null;
                StreamWriter sw = null;
                const string HighliteTemplate = "<span style=\"background-color:#ffff99;border:solid 1px #efefef;\">{0}</span>";
                //string displayline = null;
                string matchtext = null;
                StringBuilder sbSearchDisplay = null;
                StringBuilder sbReplaceDisplay = null;
                StringBuilder sbReplaceLine = null;

                if (files != null  files.Length  0)
                {
                    for(i = 0; i  folderCount; i++)
                    {
                        foreach (FileInfo fi in files[i])
                        {
                            if (htExtensions[fi.Extension.ToLower()] != null)
                            {
                                lines = File.ReadAllLines(fi.FullName);
                                linenum = 0;
                                filematch = false;
                                vpFile = fi.FullName;
                                vpFile = vpFile.Replace(lpSitePath, vpSitePath);
                                vpFile = vpFile.Replace("\\", "/");

                                if (lines != null && lines.Length > 0)
                                {
                                    foreach (string line in lines)
                                    {
                                        //linematch = false;
                                        linenum++;
                                        if (ignoreCase)
                                        {
                                            // case insensitive search and replace
                                            //displayline = line;
                                            //newline = line;
                                            linelower = line.ToLower();
                                            startindex = 0;
                                            matchindex = linelower.IndexOf(searchTextLower, startindex);
                                            if (matchindex != -1)
                                            {
                                                sbReplaceLine = new StringBuilder();
                                                sbReplaceDisplay = new StringBuilder();
                                                sbSearchDisplay = new StringBuilder();

                                                while (matchindex != -1)
                                                {
                                                    // found a match
                                                    filematch = true;
                                                    //linematch = true;
                                                    leftpart = line.Substring(startindex, matchindex - startindex);
                                                    matchtext = line.Substring(matchindex, searchTextLen);

                                                    sbReplaceLine.Append(leftpart);
                                                    sbReplaceLine.Append(replaceText);

                                                    sbReplaceDisplay.Append(HttpUtility.HtmlEncode(leftpart));
                                                    sbReplaceDisplay.Append(string.Format(HighliteTemplate, HttpUtility.HtmlEncode(replaceText)));

                                                    sbSearchDisplay.Append(HttpUtility.HtmlEncode(leftpart));
                                                    sbSearchDisplay.Append(string.Format(HighliteTemplate, HttpUtility.HtmlEncode(matchtext)));

                                                    //rightpart = newline.Substring(index + searchTextLen);
                                                    //newline = leftpart + SearchTextToken + rightpart;

                                                    // format the line and highlite the searchText
                                                    //line = line.Replace(searchText, "{?searchtext?}");
                                                    //displayline = leftpart + string.Format(HighliteTemplate, matchtext) + rightpart;


                                                    startindex = matchindex + searchTextLen;
                                                    matchindex = linelower.IndexOf(searchTextLower, startindex);
                                                }

                                                sbReplaceLine.Append(line.Substring(startindex));

                                                sbReplaceDisplay.Append(HttpUtility.HtmlEncode(line.Substring(startindex)));

                                                sbSearchDisplay.Append(HttpUtility.HtmlEncode(line.Substring(startindex)));

                                                AddMatch(this.tblSearch, vpFile, linenum, sbSearchDisplay.ToString());

                                                if (replace)
                                                {
                                                    lines[linenum - 1] = sbReplaceLine.ToString();
                                                    AddMatch(this.tblReplace, vpFile, linenum, sbReplaceDisplay.ToString());
                                                }

                                            }
                                        }
                                        else
                                        {
                                            // case sensitive search and replace
                                            matchindex = line.IndexOf(searchText, 0);
                                            if (matchindex != -1)
                                            {
                                                // found a match
                                                filematch = true;
                                                searchDisplay = line.Replace(searchText, SearchTextToken);
                                                replaceDisplay = line.Replace(searchText, SearchTextToken);

                                                searchDisplay = HttpUtility.HtmlEncode(searchDisplay);
                                                replaceDisplay = HttpUtility.HtmlEncode(replaceDisplay);

                                                searchDisplay = searchDisplay.Replace(SearchTextToken, string.Format(HighliteTemplate, HttpUtility.HtmlEncode(searchText)));
                                                replaceDisplay = replaceDisplay.Replace(SearchTextToken, string.Format(HighliteTemplate, HttpUtility.HtmlEncode(replaceText)));

                                                AddMatch(this.tblSearch, vpFile, linenum, searchDisplay);
                                                if (replace)
                                                {
                                                    lines[linenum - 1] = line.Replace(searchText, replaceText);
                                                    AddMatch(this.tblReplace, vpFile, linenum, replaceDisplay);
                                                }
                                            }                                
                                        }
                                    }
                                }

                                if (save && filematch && replace)
                                {
                                    try
                                    {
                                        sw = new StreamWriter(fi.FullName, false);
                                        foreach (string line in lines)
                                        {
                                            sw.WriteLine(line);
                                        }
                                        sw.Flush();
                                    }
                                    finally
                                    {
                                        if (sw != null)
                                        {
                                            sw.Close();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            }
        }

        private StringCollection GetSearchFolders()
        {
            StringCollection scFolders = new StringCollection();
            this.smtFolders.LoadTree();

            if (this.smtFolders.TreeList.SelectedItems != null)
            {
                VwdCms.TreeNode node = null;
                string lpFolder = null;
                foreach (DictionaryEntry de in this.smtFolders.TreeList.SelectedItems)
                {
                    if (de.Value != null)
                    {
                        node = (VwdCms.TreeNode)de.Value;
                        lpFolder = this.Page.Server.MapPath(node.CheckBoxValue);
                        if (!scFolders.Contains(lpFolder))
                        {
                            scFolders.Add(lpFolder);
                        }
                    }
                }
            }

            return scFolders;
        }

        private void AddMatch(Table tbl, string filename, int linenum, string line)
        {
            TableRow tr = null;
            TableCell tc = null;

            string padding = "3px 2px 3px 2px";
            string borderRight = "solid 1px silver";
            string borderBottom = "solid 1px silver";

            tr = new TableRow();

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = tbl.Rows.Count.ToString();
            tc.HorizontalAlign = HorizontalAlign.Center;
            tc.Style.Add("border-bottom", borderBottom);
            tc.Style.Add("border-right", borderRight);
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = filename;
            tc.HorizontalAlign = HorizontalAlign.Left;
            tc.Style.Add("border-bottom", borderBottom);
            tc.Style.Add("border-right", borderRight);
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = linenum.ToString();
            tc.HorizontalAlign = HorizontalAlign.Center;
            tc.Style.Add("border-bottom", borderBottom);
            tc.Style.Add("border-right", borderRight);
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = line;
            tc.HorizontalAlign = HorizontalAlign.Left;
            tc.Style.Add("border-bottom", borderBottom);
            tr.Cells.Add(tc);

            tbl.Rows.Add(tr);
        }

        private void AddHeader(Table tbl)
        {
            TableRow tr = null;
            TableCell tc = null;
            string padding = "4px";

            tr = new TableRow();
            tr.Style.Add("font-weight", "bold");
            tr.Style.Add("background-color", "silver");
            tr.Style.Add("color", "black");

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = "Match";
            tc.HorizontalAlign = HorizontalAlign.Center;
            tc.Style.Add("border-bottom", "solid 2px black");
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = "File";
            tc.HorizontalAlign = HorizontalAlign.Left;
            tc.Style.Add("border-bottom", "solid 2px black");
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = "Line";
            tc.HorizontalAlign = HorizontalAlign.Center;
            tc.Style.Add("border-bottom", "solid 2px black");
            tr.Cells.Add(tc);

            tc = new TableCell();
            tc.Style.Add("padding", padding);
            tc.Text = "Line&nbsp;Text";
            tc.HorizontalAlign = HorizontalAlign.Left;
            tc.Style.Add("border-bottom", "solid 2px black);
            tr.Cells.Add(tc);

            tbl.Rows.Add(tr);

        }

    }
}