SiteMapTree.cs

// Copyright � 2007 Jeffrey Bazinet, http://www.vwd-cms.com/
using System;
using System.Data;
using System.Configuration;
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.Collections;
using System.Text;
using VwdCms.Configuration;
using System.Collections.Generic;

namespace VwdCms
{
    public class SiteMapTree : System.Web.UI.WebControls.Panel
    {
        private string _imageUrl = VwdCms.Configuration.Utilities.AdminImageUrl;
        private bool _expandTreeOnLoad = true;
        private VwdCms.TreeList tlLinks;

        private bool _loaded = false;

        private int _pageCount = 0;
        private string _pageUrls = string.Empty;
        private bool _showCheckBoxes = true;
        private bool _checkBoxesChecked = true;
        private bool _renderPageLinks = false;
        private bool _renderFolderLinks = false;

        private bool _showAll = false;
        private bool _foldersOnly = false;
        private bool _expandFirstNode = true;

        public SiteMapTree()
        {
            this.tlLinks = new TreeList();
            this.tlLinks.ID = "tlLinks";
            this.Controls.Add(this.tlLinks);
        }

        protected override void OnLoad(EventArgs e)
        {
            this.LoadTree();
            
            base.OnLoad(e);
        }
        public VwdCms.TreeList TreeList
        {
            get { return this.tlLinks; }
        }

        public bool ExpandFirstNode
        {
            get { return _expandFirstNode; }
            set { _expandFirstNode = value; }
        }

        public bool FoldersOnly
        {
            get { return _foldersOnly; }
            set { _foldersOnly = value; }
        }

        public bool ShowAll
        {
            get { return _showAll; }
            set { _showAll = value; }
        }

        public int PageCount
        {
            get { return _pageCount; }
        }
        public string PageUrls
        {
            get { return _pageUrls; }
        }

        public string ImageUrl
        {
            get { return _imageUrl; }
            set { _imageUrl = value; }
        }

        public bool ShowCheckBoxes
        {
            get { return _showCheckBoxes; }
            set { _showCheckBoxes = value; }
        }

        public bool CheckBoxesChecked
        {
            get { return _checkBoxesChecked; }
            set { _checkBoxesChecked = value; }
        }

        public bool RenderPageLinks
        {
            get { return _renderPageLinks; }
            set { _renderPageLinks = value; }
        }

        public bool RenderFolderLinks
        {
            get { return _renderFolderLinks; }
            set { _renderFolderLinks = value; }
        }

        public bool ExpandTreeOnLoad
        {
            get { return _expandTreeOnLoad; }
            set { _expandTreeOnLoad = value; }
        }

        public void LoadTree()
        {
            if (!_loaded)
            {
                _loaded = true;

                string vpPath = VwdCms.Configuration.Utilities.SitePath; 
                int loc = vpPath.LastIndexOf("/");
                if (loc != -1)
                {
                    vpPath = vpPath.Substring(0, loc + 1);
                }

                if (!vpPath.EndsWith("/"))
                {
                    vpPath += "/";
                }
                string lpPath = this.Page.Server.MapPath(vpPath);

                string siteUrl = VwdCms.Configuration.Utilities.SiteUrl;
                string clientID = this.ID + "_";

                DirectoryInfo diSite = new DirectoryInfo(lpPath);
                string key = null;
                string parentKey = null;
                DirectoryInfo[] dirs = diSite.GetDirectories("*", SearchOption.AllDirectories);
                Hashtable htFolderNodes = new Hashtable(dirs.Length);

                VwdCms.TreeNode rootNode = new TreeNode();
                string rootKey = "root";
                rootNode.Key = rootKey;
                htFolderNodes.Add(rootKey, rootNode);

                // Site Node
                key = vpPath.ToLower();

                VwdCms.TreeNode siteNode = new TreeNode();
                siteNode.Key = key;
                siteNode.Parent = rootNode;
                siteNode.ImageUrl = _imageUrl + "folder.gif";
                siteNode.Text = siteUrl; 
                siteNode.ToolTip = siteUrl;
                if (this.RenderPageLinks) // this is a folder, but it is the root of the site, so use RenderPageLinks
                {
                    siteNode.NavigateUrl = siteUrl;
                }
                if (this.ShowCheckBoxes)
                {
                    siteNode.CheckBoxValue = vpPath;
                }
                rootNode.Nodes.Add(key, siteNode);
                htFolderNodes.Add(key, siteNode);

                
                VwdCms.TreeNode node = null;
                VwdCms.TreeNode parentNode = null;

                bool allowed = false;
                foreach (DirectoryInfo dInf in dirs)
                {
                    allowed = (this.ShowAll || IsFolderAllowed(dInf));

                    if (allowed)
                    {
                        key = dInf.FullName.ToLower();
                        if (!key.EndsWith("\\"))
                        {
                            key += "\\";
                        }
                        key = key.Substring(lpPath.Length);
                        key = key.Replace("\\", "/");

                        parentKey = dInf.Parent.FullName.ToLower();
                        if (!parentKey.EndsWith("\\"))
                        {
                            parentKey += "\\";
                        }
                        parentKey = parentKey.Substring(lpPath.Length);
                        parentKey = parentKey.Replace("\\", "/");

                        if (htFolderNodes.ContainsKey(parentKey))
                        {
                            parentNode = (VwdCms.TreeNode)htFolderNodes[parentKey];
                        }
                        else
                        {
                            parentNode = siteNode; 
                        }

                        if (parentNode != null)
                        {
                            node = new VwdCms.TreeNode();
                            node.Key = key;
                            node.Parent = parentNode;
                            node.ImageUrl = _imageUrl + "folder.gif";
                            node.Text = dInf.Name;
                            node.ToolTip = vpPath + key;
                            if (this.RenderFolderLinks)
                            {
                                node.NavigateUrl = siteUrl + key;
                            }

                            if (this.ShowCheckBoxes)
                            {
                                node.CheckBoxValue = vpPath + key; 
                            }

                            parentNode.Nodes.Add(key, node);
                            htFolderNodes.Add(key, node);
                        }
                    }
                }

                // get the file listing from the root directory
                if (!this.FoldersOnly)
                {
                    VwdCms.Configuration.CmsConfig cfg = VwdCms.Configuration.CmsConfig.Current;
                    VwdCms.Configuration.SiteMapSettings sitemapSettings = cfg.SiteMapSettings;
                    FileInfo[][] fileInfos = null;
                    int fileCount = 0;
                    int extensionCount = 0;
                    int i = 0;
                    if (this.ShowAll)
                    {
                        extensionCount = 1;
                        fileInfos = new FileInfo[1][];
                        fileInfos[0] = diSite.GetFiles("*.*", SearchOption.AllDirectories);
                        if (fileInfos[0] != null)
                        {
                            fileCount = fileInfos[0].Length;
                        }
                    }
                    else
                    {
                        extensionCount = sitemapSettings.PageExtensions.Count;

                        fileInfos = new FileInfo[extensionCount][];
                        foreach (KeyValuePair <string, string> kvp in sitemapSettings.PageExtensions)
                        {
                            fileInfos[i] = diSite.GetFiles("*" + kvp.Value, SearchOption.AllDirectories);
                            if (fileInfos[i] != null)
                            {
                                fileCount += fileInfos[i].Length;
                                i++;
                            }
                        }
                    }

                    // sort the files
                    SortedList slFiles = new SortedList(fileCount);
                    string extension = null;
                    int extNum = 0;
                    foreach(KeyValuePair<string, string> kvp in sitemapSettings.PageExtensions)
                    {
                        extension = kvp.Value;
                        foreach (FileInfo fi in fileInfos[extNum])
                        {
                            // 3 letter extensions return any files with extensions that begin with the 3 letters
                            // so *.htm will also return *.html files. Make sure to only add the files that precisely 
                            // match the extension that was used to search
                            if (this.ShowAll || fi.Extension.ToLower() == extension)
                            {
                                key = fi.FullName;
                                key = key.Substring(lpPath.Length);

                                if (!slFiles.ContainsKey(key))
                                {
                                    slFiles.Add(key, fi);
                                }
                            }
                        }
                        extNum++;
                    }

                    string title = null;
                    FileInfo fInf = null;
                    string currFolder = string.Empty;
                    StringBuilder sbPageUrls = new StringBuilder();

                    foreach (DictionaryEntry de in slFiles)
                    {
                        if (de.Value != null)
                        {
                            fInf = (FileInfo)de.Value;

                            allowed = IsFileAllowed(fInf);

                            if (allowed)
                            {
                                key = fInf.FullName.ToLower();
                                key = key.Substring(lpPath.Length);
                                key = key.Replace("\\", "/");

                                parentKey = fInf.Directory.FullName.ToLower();
                                if (!parentKey.EndsWith("\\"))
                                {
                                    parentKey += "\\";
                                }
                                parentKey = parentKey.Substring(lpPath.Length);
                                parentKey = parentKey.Replace("\\", "/");
                                if (parentKey == string.Empty)
                                {
                                    parentNode = siteNode;
                                }
                                else if (htFolderNodes.ContainsKey(parentKey))
                                {
                                    parentNode = (VwdCms.TreeNode)htFolderNodes[parentKey];
                                }
                                else
                                {
                                    parentNode = null;
                                }

                                if (parentNode != null)
                                {
                                    _pageCount++;
                                    node = new VwdCms.TreeNode();
                                    node.Key = key;
                                    node.Parent = parentNode;
                                    node.ImageUrl = _imageUrl + fInf.Extension.Substring(1) + ".gif";

                                    node.ToolTip = vpPath + key;
                                    title = fInf.Name.Replace(".exclude", string.Empty);
                                    node.Text = title;
                                    if (this.RenderPageLinks)
                                    {
                                        node.NavigateUrl = siteUrl + key;
                                    }
                                    if (this.ShowCheckBoxes)
                                    {
                                        node.CheckBoxValue = siteUrl + key;
                                    }

                                    sbPageUrls.Append(siteUrl + key + "\r\n");

                                    parentNode.Nodes.Add(key, node);
                                }
                            }
                        }
                    }

                    _pageUrls = sbPageUrls.ToString();
                }

                // now setup the TreeList control and set the RootNode
                this.tlLinks.ImageUrl = this.ImageUrl;
                this.tlLinks.RegisterJavaScriptFile = true;
                this.tlLinks.RegisterStyleSheetFile = false;
                this.tlLinks.ExpandTreeOnLoad = this.ExpandTreeOnLoad;
                this.tlLinks.ExpandFirstNode = this.ExpandFirstNode;
                this.tlLinks.ShowCheckBoxes = this.ShowCheckBoxes;
                this.tlLinks.CheckBoxesChecked = this.CheckBoxesChecked;
                this.tlLinks.RootNode = rootNode;
                this.tlLinks.RenderNodes();
            }
        }

        private static bool IsFolderAllowed(DirectoryInfo dInf)
        {
            CmsConfig cfg = CmsConfig.Current;
            VwdCms.Configuration.SiteMapSettings sitemapSettings = cfg.SiteMapSettings;
            Hashtable htHiddenFolders = sitemapSettings.HiddenFoldersHashtable;

            bool allowed = !htHiddenFolders.ContainsKey(dInf.FullName.ToLower());
            
            return allowed;
        }

        public static bool IsFileAllowed(FileInfo fInf)
        {
            CmsConfig cfg = CmsConfig.Current;
            VwdCms.Configuration.SiteMapSettings sitemapSettings = cfg.SiteMapSettings;
            Hashtable htHiddenPages = sitemapSettings.HiddenPagesHashtable;

            string filename = fInf.FullName.ToLower();

            bool allowed = !htHiddenPages.ContainsKey(filename);

            // look at the filename to determine if it is a draft page content file
            if (allowed)
            {
                if (filename.IndexOf(".draft.) != -1)
                {
                    allowed = false;
                }
            }

            // is the parent folder allowed?
            if (allowed)
            {
                allowed = IsFolderAllowed(fInf.Directory);
            }


            int extensionCount = sitemapSettings.PageExtensions.Count;

            if (allowed)
            {
                Hashtable htExtensions = sitemapSettings.PageExtensionsHashtable;

                string lpFile = fInf.FullName;

                // look at the extension
                string extension = VwdCms.Configuration.Utilities.GetExtension(lpFile);
                string completeExtension = VwdCms.Configuration.Utilities.GetExtensionComplete(lpFile);

                if (!string.IsNullOrEmpty(extension))
                {
                    allowed = htExtensions.ContainsKey(extension);
                }

                // look at the complete exension
                if (allowed)
                {
                    switch (completeExtension)
                    {
                        case VwdCms.Constants.DraftCodeExtension:
                        case VwdCms.Constants.DraftPageExtension:
                            allowed = false;
                            break;
                    }
                }

            }
            return allowed;
        }


    }
}