Exemplo n.º 1
0
        public static SanitizedMarkup SanitizeMarkup(string inputMarkup)
        {
            var writer = new MarkupWriter(GetAllowedTags());

            var tokens = TokenizeMarkup(inputMarkup);

            foreach (var token in tokens)
            {
                token.ProcessOutput(writer);
            }

            while (writer.OpenTags.Count > 0)
            {
                writer.CloseTag();
            }

            var markupText = writer.ToString();

            for (var i = 0; i < EmptyTagPassCount; i++)
            {
                markupText = EmptyTagRegex.Replace(
                    markupText,
                    match =>
                {
                    var tagName       = match.Groups[EmptyTagNameGroup].Value;
                    var tagDefinition = writer.GetTagDefinition(tagName);
                    return(tagDefinition.AllowEmpty ? match.Value : string.Empty);
                });
            }

            return(new SanitizedMarkup(markupText, writer.TransitionalDoctypeRequired));
        }
Exemplo n.º 2
0
        public void ProcessOutput(MarkupWriter writer)
        {
            var tagDefinition = writer.GetTagDefinition(TagName);

            // If the tag is not defined, silently ignore it
            if (tagDefinition == null)
            {
                return;
            }

            if (IsOpeningTag)
            {
                // If we force a nesting, record the injection set so that we can collapse it later
                var injection = EnsureCorrectNesting(writer, tagDefinition);
                if (injection.Length > 0)
                {
                    writer.Injections.Push(injection);
                }

                var allowedAttributes = (from a in Attributes
                                         where tagDefinition.AllowedAttributes.Contains(a.Key, StringComparer.InvariantCultureIgnoreCase)
                                         select a).ToDictionary(k => k.Key, v => v.Value);

                // We use the tag name from the definition here so that any upscaling can occur
                if (tagDefinition.IsShortcut)
                {
                    writer.ShortcutTag(tagDefinition, allowedAttributes);
                }
                else
                {
                    writer.OpenTag(tagDefinition, allowedAttributes);
                }
            }
            else
            {
                // Only continue if the tag is actually in the stack, else ignore it silently
                if (writer.OpenTags.Contains(tagDefinition.TagName, StringComparer.InvariantCultureIgnoreCase))
                {
                    // Close any tags above this one in the stack
                    while (writer.OpenTags.Count > 0 && !writer.OpenTags.Peek().Equals(tagDefinition.TagName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        writer.CloseTag();
                    }

                    // If there are still open tags, we must be next in line
                    if (writer.OpenTags.Count > 0)
                    {
                        writer.CloseTag();
                    }
                }
            }
        }
Exemplo n.º 3
0
        static string[] EnsureCorrectNesting(MarkupWriter writer, TagDefinition tagDefinition)
        {
            if (tagDefinition == null)
            {
                return new string[] { }
            }
            ;

            var injection = new List <string>();

            // If we're not allowed to have any parents at all, close them all down
            if (tagDefinition.BlockedParents.Union(tagDefinition.BlockedDirectParents).Intersect(TagDefinition.AllTags).Any())
            {
                while (writer.OpenTags.Count > 0)
                {
                    writer.CloseTag();
                }
            }

            // Keep closing tags until we get out from under any disallowed direct parents
            while (
                tagDefinition.BlockedDirectParents.Any() &&
                writer.OpenTags.Any() &&
                tagDefinition.BlockedDirectParents.Contains(writer.OpenTags.Peek()))
            {
                writer.CloseTag();
            }

            // If we have to be withing a particular direct parent, keep closing tags until we find one
            while (
                tagDefinition.RequiredDirectParents.Any() &&
                writer.OpenTags.Any() &&
                !tagDefinition.RequiredDirectParents.Contains(writer.OpenTags.Peek()))
            {
                writer.CloseTag();
            }

            // Keep closing tags until we get out from under any disallowed parents
            while (
                tagDefinition.BlockedParents.Any() &&
                writer.OpenTags.Intersect(tagDefinition.BlockedParents).Any())
            {
                writer.CloseTag();
            }

            // If we have to be within a specific parent, inject it
            if (tagDefinition.RequiredDirectParents.Any())
            {
                var directParentInjectionCandidates = (
                    from dpt in tagDefinition.RequiredDirectParents
                    where !dpt.Equals(TagDefinition.TagRoot)
                    select dpt).ToArray();
                var haveRequiredDirectParent =
                    (writer.OpenTags.Count == 0 && tagDefinition.RequiredDirectParents.Contains(TagDefinition.TagRoot)) ||
                    (writer.OpenTags.Any() && directParentInjectionCandidates.Contains(writer.OpenTags.First()));
                if (!haveRequiredDirectParent)
                {
                    var injectionTag = writer.GetTagDefinition(directParentInjectionCandidates.First());
                    InjectParent(writer, injection, injectionTag);
                }
            }

            if (tagDefinition.RequiredParents.Any())
            {
                var haveRequiredParent = writer.OpenTags.Intersect(tagDefinition.RequiredParents).Any();
                if (!haveRequiredParent)
                {
                    var injectionTag = writer.GetTagDefinition(tagDefinition.RequiredParents.First());
                    InjectParent(writer, injection, injectionTag);
                }
            }

            // If any injection has occurred, record the tag that caused it so we can collapse it later
            if (injection.Any())
            {
                injection.Insert(0, tagDefinition.TagName);
            }

            return(injection.Distinct().ToArray());
        }