ContentControl.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.HtmlControls;
using System.IO;
using System.Text;
using System.Collections;
using System.Web.RegularExpressions;
using System.Text.RegularExpressions;
using System.Xml;
using VwdCms.Configuration;

namespace VwdCms
{
    public enum ShowEditLinks
    {
        Always,
        Never,
        NotInDemoMode
    }

    public class ContentControl : Panel, INamingContainer
    {
        public bool ShowControlBorder = false;
        private string _contentFile = string.Empty;
        private string _contentFolder = string.Empty;
        private string _rssUrl = string.Empty;
        private bool _loaded = false;
        private ShowEditLinks _showEditLink = ShowEditLinks.Always;
        private bool _renderPanel = true;

        protected override void OnPreRender(EventArgs e)
        {
            RenderContentEditLinks();

            base.OnPreRender(e);
        }
        
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            if (_renderPanel)
            {
                base.RenderBeginTag(writer);
            }
        }
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            if (_renderPanel)
            {
                base.RenderEndTag(writer);
            }
        }

        protected override void CreateChildControls()
        {
            if (!_loaded)
            {
                _loaded = true;

                bool contentFound = false;

                if (this.ContentFile != null  this.ContentFile != string.Empty)
                {
                    string content = GetContent(this.ContentFolder, this.ContentFile, this.Page);

                    Control parsed = this.Page.ParseControl(content);
                    Control c = null;
                    while (parsed.Controls.Count != 0)
                    {
                        c = parsed.Controls[0];
                        this.Controls.Add(c);
                    }
                    contentFound = true;
                }

                if (this.RssUrl != null  this.RssUrl != string.Empty)
                {
                    HtmlGenericControl div = new HtmlGenericControl("div");
                    div.InnerHtml = GetFeed(this.RssUrl);
                    this.Controls.Add(div);
                    contentFound = true;
                }

                if (!contentFound)
                {
                    this.Style.Add("display", "none");
                }

                if (this.ShowControlBorder)
                {
                    this.Style.Add("border", "dotted 1px gray");
                    this.Style.Add("padding", "-1px");
                }
            }
            base.CreateChildControls();
        }

        public bool RenderPanel
        {
            get { return _renderPanel; }
            set { _renderPanel = value; }
        }

        public string ContentFile
        {
            get { return _contentFile; }
            set { _contentFile = value; }
        }

        public ShowEditLinks ShowEditLink
        {
            get 
            {
                // do not put edit links  on the ads in Demo Mode
                if (this.ContentFolder.ToLower() == "ads")
                {
                    return ShowEditLinks.NotInDemoMode;
                }
                else
                {
                    return _showEditLink;
                }
            }
            set 
            { 
                _showEditLink = value; 
            }
        }

        public string ContentFolder
        {
            get 
            {
                if (_contentFolder == null || _contentFolder == string.Empty)
                {
                    _contentFolder = "Content/";
                }
                return _contentFolder; 
            }
            set 
            {
                _contentFolder = value;
            }
        }

        public string RssUrl
        {
            get { return _rssUrl; }
            set { _rssUrl = value; }
        }

        public static void GetContentControls(System.Web.UI.Page page, string pageFile, ref ArrayList controls)
        {
            StringBuilder sbPage = new StringBuilder(ReadFile(pageFile));

            Regex re = null;
            MatchCollection matches = null;

            // remove asp code
            re = new AspCodeRegex();
            matches = re.Matches(sbPage.ToString());

            foreach (Match match in matches)
            {
                sbPage.Replace(match.Value, string.Empty);
            }

            // remove Asp expressions
            re = new AspExprRegex();
            matches = re.Matches(sbPage.ToString());

            foreach (Match match in matches)
            {
                sbPage.Replace(match.Value, string.Empty);
            }

            // remove Asp directives
            re = new SimpleDirectiveRegex();
            matches = re.Matches(sbPage.ToString());

            foreach (Match match in matches)
            {
                sbPage.Replace(match.Value, string.Empty);
            }


            Control control = page.ParseControl(sbPage.ToString());

            FindContentControls(control, ref controls);

        }

        private static void FindContentControls(Control control, ref ArrayList controls)
        {
            if (control is ContentControl)
            {
                controls.Add(control);
            }
            foreach (Control child in control.Controls)
            {
                FindContentControls(child, ref controls);
            }
        }

        private static string GetContent(string contentFolder, string contentFile, System.Web.UI.Page page)
        {
            StringBuilder sbContent = new StringBuilder();
            CmsConfig cfg = CmsConfig.Current;
            contentFolder = contentFolder.ToLower();
            ManagedFolder mf = VwdCms.Configuration.Utilities.GetManagedFolder(cfg, contentFolder);

            if (mf != null)
            {
                HttpContext context = HttpContext.Current;
                string file = null;
                string[] files = contentFile.Split(';');

                if (files != null  files.Length  0)
                {
                    string lpContent = VwdCms.Configuration.Utilities.GetContentLocalPath(contentFolder);

                    int i = 0;
                    for (i = 0; i  files.Length; i++)
                    {
                        file = files[i];
                        if (file != null  file != string.Empty)
                        {
                            file = VwdCms.Configuration.Utilities.RemoveExtension(file);
                            file += mf.PrimaryExtension;

                            if (File.Exists(lpContent + file))
                            {
                                try
                                {
                                    sbContent.Append(VwdCms.IO.GetXmlNodeText(lpContent + file, "content"));
                                }
                                catch { }
                            }
                        }
                    }
                }
            }
            ReplaceVariables(ref sbContent, page);

            return sbContent.ToString();
        }
        public static string ReplaceVariables(string content, System.Web.UI.Page page)
        {
            StringBuilder sb = new StringBuilder(content);
            ReplaceVariables(ref sb, page);
            return sb.ToString();
        }

        public static void ReplaceVariables(ref StringBuilder sbContent, System.Web.UI.Page page)
        {
            if (sbContent.Length  0)
            {
                string urlScheme = page.Request.Url.Scheme;
                string siteUrl = VwdCms.Configuration.Utilities.SiteUrl;
                string secureUrl = VwdCms.Configuration.Utilities.SecureUrl;
                string imageUrl = VwdCms.Configuration.Utilities.ImageUrl;
                string prdImageUrl = VwdCms.Configuration.Utilities.ProductImageUrl;
                string domain = VwdCms.Configuration.Utilities.Domain;
                string companyname = VwdCms.Configuration.Utilities.CompanyName;
                string nickname = VwdCms.Configuration.Utilities.CompanyNickname;
                string city = VwdCms.Configuration.Utilities.City;
                string state = VwdCms.Configuration.Utilities.State;
                string country = VwdCms.Configuration.Utilities.Country;

                sbContent.Replace("{UrlScheme}", urlScheme);
                sbContent.Replace("{SiteUrl}", siteUrl);
                sbContent.Replace("{SiteSecureUrl}", secureUrl);
                sbContent.Replace("{SecureUrl}", secureUrl);
                sbContent.Replace("{ImageUrl}", imageUrl);
                sbContent.Replace("{ProductImageUrl}", prdImageUrl);
                sbContent.Replace("{Domain}", domain);
                sbContent.Replace("{CompanyName}", companyname);
                sbContent.Replace("{CompanyNickname}", nickname);
                sbContent.Replace("{City}", city);
                sbContent.Replace("{State}", state);
                sbContent.Replace("{Country}", country);
                
                // variables that depend on the page and master page
                string adkeywords = string.Empty;

                string pageUrl = string.Empty;
                string pageTitle = string.Empty;
                string pageTitleEncoded = string.Empty;

                if (page != null)
                {
                    // page url
                    pageUrl = page.Request.Url.AbsoluteUri;

                    // get data from the master page
                    if (page.Master != null)
                    {
                        VwdCms.MasterPage master = (VwdCms.MasterPage)page.Master;

                        // ad keywords
                        adkeywords = master.AdKeywords;
                        if (adkeywords == null)
                        {
                            adkeywords = string.Empty;
                        }
                        else
                        {
                            adkeywords = adkeywords.Replace("#", string.Empty);
                            adkeywords = adkeywords.Replace(" ", "+");
                            adkeywords = adkeywords.Replace(",", ";");
                            adkeywords = adkeywords.Replace(".", string.Empty);
                        }

                        // page title
                        pageTitle = master.PageTitle.Trim();
                        pageTitleEncoded = HttpUtility.UrlEncode(pageTitle);

                    }
                    else
                    {
                        pageTitle = page.Title.Trim();
                        pageTitleEncoded = HttpUtility.UrlEncode(pageTitle);
                    }
                }
                sbContent.Replace("{Query}", VwdCms.Configuration.Utilities.Query);
                sbContent.Replace("{AdKeywords}", adkeywords);

                sbContent.Replace("{PageUrl}", pageUrl);
                sbContent.Replace("{PageTitle}", pageTitle);
                sbContent.Replace("{PageTitleEncoded}", pageTitleEncoded);

            }
        }

        private static string ReadFile(string pathfile)
        {
            StreamReader sr = null;
            string text = string.Empty;

            try
            {
                sr = new StreamReader(pathfile);
                text = sr.ReadToEnd();
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                    sr = null;
                }
            }
            return text;
        }

        private string GetFeed(string feedUrl)
        {
            XmlDocument myDoc = new XmlDocument();
            myDoc.Load(feedUrl);

            XmlNode docNode = (XmlNode)myDoc.DocumentElement;
            StringBuilder result = new StringBuilder();

            string title = null;
            string channelurl = null;

            for ( int i = 0; i  docNode.ChildNodes.Count; i++)
            {
                XmlNode n = docNode.ChildNodes[i];

                if (n.Name == "channel")
                {
                    for ( int j = 0; j  n.ChildNodes.Count; j++)
                    {
                        XmlNode c = n.ChildNodes[j];

                        if (c.Name == "title")
                        {
                            title = c.InnerText;
                            if (title != null  title != string.Empty)
                            {
                                result.Append("<h1>");
                                result.Append(title);
                                result.Append("</h1>");
                            }
                        }
                        else if (c.Name == "link")
                        {
                            channelurl = c.InnerText;
                        }
                        else if (c.Name == "item")
                        {
                            GetItem(channelurl, ref c, ref result);
                        }
                    }
                }
                else if (n.Name == "item")
                {
                    GetItem(channelurl, ref n, ref result);
                }
            }

            return result.ToString();
        }

        private void GetItem(string channelurl, ref XmlNode n, ref StringBuilder result)
        {
            string title = null;
            string link = null;
            string creator = null;
            string author = null;
            string subject = null;
            string description = null;
            string content = null;

            foreach (XmlNode c in n.ChildNodes)
            {
                if (c.Name == "title")
                {
                    title = c.InnerText;
                }
                else if (c.Name == "link")
                {
                    link = c.InnerText;
                }
                else if (c.Name == "dc:creator")
                {
                    creator = c.InnerText;
                }
                else if (c.Name == "author")
                {
                    author = c.InnerText;
                }
                else if (c.Name == "dc:subject")
                {
                    subject = c.InnerText;
                }
                else if (c.Name == "description")
                {
                    description = c.InnerText;
                }
                else if (c.Name == "content:encoded")
                {
                    content = c.InnerText;
                }
            }

            result.Append("<div class=\"contentbox\">");

            if (title != null  link != null)
            {
                if (!link.StartsWith("http://")  !link.StartsWith("https://"))
                {
                    link = channelurl + link;
                }

                result.Append("<h2><a target=\"_blank\" href=\"");
                result.Append(link);
                result.Append("\">");
                result.Append(title);
                result.Append("</a></h2>");
            }
            if (subject != null)
            {
                result.Append("<h3>");
                result.Append(subject);
                result.Append("</h3>");
            }
            if (author != null)
            {
                result.Append("<div style=\"padding-left:10px;\">By ");
                result.Append(author);
                result.Append("</div>");
            }
            else if (creator != null)
            {
                result.Append("<div style=\"padding-left:10px;\">By ");
                result.Append(creator);
                result.Append("</div>");
            }

            if (content != null)
            {
                content = content.Replace("href=\"/", "href=\"" + channelurl + "/");

                result.Append("<p class=\"contenttext\">");
                result.Append(content);
                result.Append("</p>");
            }
            else if (description != null)
            {
                result.Append("<p class=\"contenttext\">");
                result.Append(description);
                result.Append("</p>");
            }

            result.Append("</div>");

        }

        private void RenderContentEditLinks()
        {
            bool showEditLink = true;

            switch (this.ShowEditLink)
            {
                case ShowEditLinks.Always:
                    showEditLink = true;
                    break;
                case ShowEditLinks.Never:
                    showEditLink = false;
                    break;
                case ShowEditLinks.NotInDemoMode:
                    CmsConfig cfg = CmsConfig.Current;
                    if (cfg != null)
                    {
                        CmsHost host = cfg.CurrentHost;
                        if (host != null)
                        {
                            if (host.DemoMode)
                            {
                                showEditLink = false;
                            }
                        }
                    }
                    break;
            }
            
            if (showEditLink)
            {
                // Note: this.ContentFile property value can contain a semicolon 
                // delimited list of content files, but for now, for the sake of 
                // simplicity, just use the first file in the list
                string file = null;
                if (!string.IsNullOrEmpty(this.ContentFile))
                {
                    string[] files = this.ContentFile.Split(';');
                    if (files != null  files.Length  0)
                    {
                        foreach (string cf in files)
                        {
                            if (!string.IsNullOrEmpty(cf))
                            {
                                file = cf;
                                break;
                            }
                        }
                    }
                }

                // if there is a file, check to see if editing is 'allowed'
                if (!string.IsNullOrEmpty(file))
                {
                    // get the virtual path to the content file to edit
                    string vpFile = VwdCms.Configuration.Utilities.SitePath + "VwdCms/" + this.ContentFolder + "/" + file;

                    bool editAllowed = IsEditLinkAllowed(vpFile);

                    // render the edit link if allowed
                    if (editAllowed)
                    {
                        AddEditLinkAttributes(vpFile, file);
                    }
                }
            }
        }

        private void AddEditLinkAttributes(string vpContentFile, string fileName)
        {
            string adminUrl = VwdCms.Configuration.Utilities.SiteUrl + "VwdCms/Admin/Admin.aspx?file=";
            string editUrl = adminUrl + vpContentFile;

            this.Style.Add("padding", "4px 0px 4px 0px");
            this.Style.Add("border", "solid 1px transparent");

            this.Attributes.Add("onclick", "VwdCms_editContent(this, '" + editUrl + "');");
            this.Attributes.Add("onmouseover", "VwdCms_showEditInfo(this, '#ffffdf', '" + fileName + "');");
            this.Attributes.Add("onmouseout", "VwdCms_hideEditInfo(this);");

        }

        public static Control CreateEditLink(string vpContentFile)
        {
            // create link to edit the page content
            string adminUrl = VwdCms.Configuration.Utilities.SiteUrl + "VwdCms/Admin/Admin.aspx?file=";
            string editUrl = adminUrl + vpContentFile;
            string fileName = VwdCms.Configuration.Utilities.GetFilename(vpContentFile, false);
            HtmlGenericControl div = null;

            div = new HtmlGenericControl("div");
            div.Style.Add("width", "100%");
            div.Style.Add("display", "inline");
            div.Style.Add("margin", "0px 0px 0px -1px");
            div.Style.Add("padding", "0px");
            div.Style.Add("float", "left");
            div.Style.Add("border", "solid 1px transparent");
            div.Attributes.Add("onclick", "VwdCms_editContent(this,'" + editUrl + "');");
            div.Attributes.Add("onmouseover", "VwdCms_showEditInfo(this, '#d9e8f0','" + fileName + "');");
            div.Attributes.Add("onmouseout", "VwdCms_hideEditInfo(this);");
            
            return div;
        }

        public static bool IsEditLinkAllowed(string vpContentFile)
        {    
            bool editAllowed = false;
            CmsConfig cfg = CmsConfig.Current;
            CmsHost host = cfg.CurrentHost;

            // Check 1:if membership has been installed, check if the user is in the 'admins' group, render the edit link
            bool membershipInstalled = !string.IsNullOrEmpty(host.ApplicationId);
            if (membershipInstalled)
            {
                MembershipUser user = Membership.GetUser();
                if (user != null)
                {
                    string[] userRoles = Roles.GetRolesForUser(); // for currently logged on user
                    if (userRoles != null  userRoles.Length  0)
                    {
                        foreach (string role in userRoles)
                        {
                            if (role != null  role.ToLower() == "admins")
                            {
                                editAllowed = true;
                                break;
                            }
                        }
                    }
                }
            }
            // Check 2: if the site is running in Demo mode, let 'Allowed' files to be edited 
            if (!editAllowed  vpContentFile != null  host.DemoMode)
            {
                HttpContext context = HttpContext.Current;
                string lpFile = context.Server.MapPath(vpContentFile);
                FileInfo finf = new FileInfo(lpFile);
                editAllowed = VwdCms.Configuration.Utilities.IsFileAllowedInDemo(finf);
            }

            return editAllowed;
        }
    }
}