Пример #1
0
        /// <summary>
        /// Reparses meta and link tags that weren't parsed correctly the first time.
        /// Only works inside ContentPlaceHolder controls located inside the head.
        /// 1) Parses literal controls: looks for self-closing and empty meta, link, and script controls.
        /// Supports Visible and EnableViewState attributes correctly. EnableViewState=false if not specified.
        /// The TemplateControl is re-calculated.
        /// 2) Parses HtmlGenericControls (link, meta, script tags with runat="server"). HtmlGenericControl instances for 'script' can
        /// only exist if added through code, since &lt;script runat="server"&gt; is for server side code. Supports it anyway :)
        /// Supports Visible and EnableViewState attributes correctly. EnableViewState=false if not specified.
        /// The TemplateControl is re-calculated.
        /// Note: script references don't have a built-in control, so we use a custom ScriptReference instance to provide the rebasing support.
        /// </summary>
        /// <param name="p"></param>
        public static void RepairPageHeader(Page p)
        {
            //Aquire a collection of references to each contentplaceholder in the Head section.
            //ContentPlaceHolders do not account for being located in an HtmlHead, and simply
            //perform the normal parsing logic. We will patch this by iterating through incorrectly identified tags such as
            //<link> and <meta>, and replacing them with the proper control type.
            //As a bonus, we also make script references work, but that is an extra - Head doesn't usually do anything special
            //with those anyway.

            //Note that each contentplaceholder usually contains a child ContentPlaceHolder
            if (p.Header != null)
            {
                ////////////////////// Literal parsing //////////////////////////////
                //Get a collection of all of the LiteralControls in the head
                //This will handle link, meta, and script includes
                List <LiteralControl> toParse = ControlUtils.GetControlsOfType <LiteralControl>(p.Header);

                //handle literal links
                if (toParse != null)
                {
                    foreach (LiteralControl lc in toParse)
                    {
                        //if the literal is directly inside a content tag, on a content page, the TemplateControl property will
                        //incorrectly point to the MasterPage.
                        //So if we use lc.AppRelativeTemplateSourceDirectory, it doesn't work
                        //However, if we use this.AppRelativeTemplateSourceDirectory and
                        //we have a MasterPage>MasterPage(with relative literal stylesheet reference)>Page
                        //Then the relative stylesheet reference will be broke, relative to the Page.

                        //The solution is to find the child TemplateControl of lc's nearest ContentPlaceHolder parent.
                        //We do this before ParseLiteral control, because this value will be propogated to the
                        //component controls.
                        lc.TemplateControl = ContentPlaceHolderFixes.GetAdjustedParentTemplateControl(lc);

                        //Parse literal control
                        Control c = ParseLiteralControl(lc, lc.Text);
                        //notused:  //Article.SetPathRecursive(c, getAdjustedParent(lc).AppRelativeTemplateSourceDirectory);//used to be this.
                        //Replace
                        lc.Parent.Controls.AddAt(lc.Parent.Controls.IndexOf(lc), c);
                        lc.Parent.Controls.Remove(lc);
                    }
                }

                //handle links with runat="server"
                //We just want the outermost cphs
                List <ContentPlaceHolder> cphList = ControlUtils.GetControlsOfType <ContentPlaceHolder>(p.Header, false, true);

                if (cphList != null)
                {
                    //There may be multiple CPHs in the head section
                    foreach (ContentPlaceHolder cph in cphList)
                    {
                        //Get a collection of all of the HtmlGenericControls in the current ContentPlaceHolder.
                        List <HtmlGenericControl> toFix = ControlUtils.GetControlsOfType <HtmlGenericControl>(cph);
                        if (toFix == null)
                        {
                            continue;
                        }

                        //This will handle all link tags, meta tags, or script tags with runat="server"
                        //Also affects script tags parsed in above section (URL resolution)

                        //Iterate through the collection, replacing or modifying the neccesary objects.
                        foreach (HtmlGenericControl hgc in toFix)
                        {
                            HtmlControl replacement = null;
                            switch (hgc.TagName.ToLower())
                            {
                            case "link":
                                //Create a replacement HtmlLink object with identical attributes.
                                //HtmlLink will resolve virtual URLs on the href attribute at render-time, unlike HtmlGenericControl.
                                replacement = new HtmlLink();

                                break;

                            case "meta":
                                //Create a replacement HtmlMeta object with identical attributes.
                                replacement = new HtmlMeta();
                                break;

                            case "script":
                                //Create a new script reference, which resolves the src attribute at render-time
                                replacement = new ScriptReference();
                                break;
                            }


                            if (replacement != null)
                            {
                                //Adjust the TemplateControl for the *other* ContentPlaceHolder bug.
                                replacement.TemplateControl = GetAdjustedParentTemplateControl(hgc.TemplateControl);

                                //Turn off ViewState
                                replacement.EnableViewState = false;

                                //Copy attributes
                                foreach (string s in hgc.Attributes.Keys)
                                {
                                    string val = hgc.Attributes[s];
                                    replacement.Attributes.Add(s, val);
                                }
                                //Assign known properties that aren.t collection-backed
                                replacement.EnableViewState = hgc.EnableViewState;
                                replacement.Visible         = hgc.Visible;

                                //Insert the new object next to the old, then remove the old.
                                hgc.Parent.Controls.AddAt(hgc.Parent.Controls.IndexOf(hgc), replacement);
                                hgc.Parent.Controls.Remove(hgc);
                            }
                        }
                    }
                }
            }


            /* Analyize TemplateControls. Prints TemplateControl/TemplateSourceDirectory tree for diagnostics.
             *  List<Control> allcontrols = GetControlsOfType<Control>(this);
             *  List<TemplateControl> uniqueTemplateControls =new List<TemplateControl>();
             *  Debug.WriteLine(Page.AppRelativeTemplateSourceDirectory);
             *  foreach (Control c in allcontrols)
             *  {
             *      //Debug.WriteLine(c.ID + "   (" + c.TemplateControl.ID + ") - " + c.AppRelativeTemplateSourceDirectory);
             *      if (!uniqueTemplateControls.Contains(c.TemplateControl)){
             *          uniqueTemplateControls.Add(c.TemplateControl);
             *          string s = c.TemplateSourceDirectory;
             *      }
             *
             *  }
             *  StringWriter sw = new StringWriter();
             *  PrintTree(this.Header, 0, sw);
             *  this.Header.Controls.AddAt(0, new LiteralControl(Server.HtmlEncode((sw.ToString()))));
             */
        }
Пример #2
0
        /// <summary>
        /// Parses the specified literal control and returns a replacement control (often PlaceHolder) containing
        /// the newly parsed controls. Only self-closing tags or tags that only contain whitespace. Creates
        /// HtmlMeta (for &lt;meta&gt;), HtmlLink (for &lt;link&gt;), HtmlGenericControl (for &lt;script&gt;) and uses LiteralControl instances for the rest
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private static Control ParseLiteralControl(Control c, string text)
        {
            if (c.Controls.Count > 0)
            {
                return(c);
            }
            PlaceHolder ph = new PlaceHolder();

            int strIndex = 0;

            while (strIndex < text.Length)
            {
                Match m = CommentsAndSingleTags.Match(text, strIndex);

                //We're at the end. Add the last literal and leave.
                if (!m.Success)
                {
                    if (text.Length > strIndex)
                    {
                        LiteralControl lastLiteral = new LiteralControl(text.Substring(strIndex, text.Length - strIndex));
                        ph.Controls.Add(lastLiteral);
                    }
                    break;
                }

                //We've hit another comment or tag.
                //Add the text since the last match.
                int spaceSinceLastMatch = m.Index - strIndex;
                if (spaceSinceLastMatch > 0)
                {
                    LiteralControl inbetween = new LiteralControl(text.Substring(strIndex, spaceSinceLastMatch));//"<!--In between and before matches: (-->" + text.Substring(strIndex,spaceSinceLastMatch) + "<!--)-->");
                    ph.Controls.Add(inbetween);
                }

                //build control
                string matchText = text.Substring(m.Index, m.Length);
                if (m.Groups["comment"].Success)
                {
                    LiteralControl comment = new LiteralControl(matchText);//"<!--Comment:(-->" + matchText + "<!--)-->");
                    ph.Controls.Add(comment);
                }
                else if (m.Groups["tagname"].Success)
                {
                    if (m.Groups["endtagname"].Success)
                    {
                        if (!m.Groups["tagname"].Value.Equals(m.Groups["endtagname"].Value))
                        {
                            LiteralControl error = new LiteralControl("<!-- fbs Parser Error - end tag does not match start tag : -->" + matchText);
                            ph.Controls.Add(error);
                        }
                    }

                    //Parse tag

                    string tagname = m.Groups["tagname"].Value.Trim().ToLower();

                    //Store the attribute names and values into the attrs collection
                    NameValueCollection attrs = new NameValueCollection();

                    Group anames = m.Groups["attrname"];
                    Group avals  = m.Groups["attrval"];
                    if (anames != null && avals != null)
                    {
                        for (int i = 0; i < anames.Captures.Count; i++)
                        {
                            string name = anames.Captures[i].Value;
                            if (i < avals.Captures.Count)
                            {
                                string value = avals.Captures[i].Value;
                                attrs[name] = value;
                            }
                        }
                    }
                    if (tagname.Equals("link") ||
                        tagname.Equals("meta") ||
                        tagname.Equals("script"))
                    {
                        HtmlControl hc = null;
                        switch (tagname)
                        {
                        case "link":
                            hc = new HtmlLink();
                            break;

                        case "meta":
                            hc = new HtmlMeta();
                            break;

                        case "script":
                            hc = new ScriptReference();
                            break;
                        }

                        //Inherit TemplateControl value
                        hc.TemplateControl = c.TemplateControl;
                        //Copt attrs
                        foreach (string key in attrs.AllKeys)
                        {
                            hc.Attributes[key] = attrs[key];
                        }
                        //Apply attributes to known properties that aren't Attributes backed.
                        if (hc.Attributes["visible"] != null)
                        {
                            hc.Visible = hc.Attributes["visible"].Equals("true", StringComparison.OrdinalIgnoreCase);
                            hc.Attributes.Remove("visible");
                        }
                        if (hc.Attributes["EnableViewState"] != null)
                        {
                            hc.EnableViewState = hc.Attributes["EnableViewState"].Equals("true", StringComparison.OrdinalIgnoreCase);
                            hc.Attributes.Remove("EnableViewState");
                        }
                        else
                        {
                            hc.EnableViewState = false;
                        }

                        ph.Controls.Add(hc);
                    }
                    else
                    {
                        //Just pass unrecognized text through
                        LiteralControl notRecognized = new LiteralControl(matchText);//"<!-- tag name not recognized: (-->" + matchText + "<!--)-->");
                        ph.Controls.Add(notRecognized);
                        break;
                    }
                }
                else
                {
                    LiteralControl regexError = new LiteralControl("<!-- regex error: (-->" + matchText + "<!--)-->");
                    ph.Controls.Add(regexError);
                    //Should never happen... Either group Comment or group TagName should be defined.
                }


                strIndex = m.Index + m.Length;
            }
            if (ph.Controls.Count == 1)
            {
                return(ph.Controls[0]);
            }
            else
            {
                return(ph);
            }
        }