Ejemplo n.º 1
0
        protected Element CreateFontElement(OpenNode node)
        {
            string color = node.GetAttribute("color");

            if (string.IsNullOrEmpty(color))
            {
                return(new ContainerElement());
            }
            Color c = Color.FromString(color);

            if (c == null)
            {
                return(new ContainerElement());
            }
            return(new ColorElement(c));
        }
Ejemplo n.º 2
0
        protected Element CreateImageElement(OpenNode node)
        {
            // Valid image?
            string src = node.GetAttribute("src");

            if (string.IsNullOrEmpty(src))
            {
                return(null);
            }
            if (!src.Contains("://"))
            {
                return(null);
            }
            // Parse src value
            string[] parts = src.Split(new string[] { "://" }, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 2)
            {
                return(null);
            }
            // - Determine type
            ImageType type = ImageType.RDB;

            if (parts[0].ToLower() == "rdb")
            {
                type = ImageType.RDB;
            }
            else if (parts[0].ToLower() == "tdb")
            {
                type = ImageType.TDB;
                string prefix = "id:";
                if (parts[1].StartsWith(prefix))
                {
                    parts[1] = parts[1].Substring(prefix.Length);
                }
            }
            else
            {
                return(null);
            }
            // Return image
            return(new ImageElement(type, parts[1]));
        }
Ejemplo n.º 3
0
        public Element Parse(string aoml)
        {
            ContainerElement container = new ContainerElement();
            // Parse AOML
            NodeCollection nodes = this.Parser.Parse(aoml);

            this.Parser.Sanitize(nodes);
            this.Parser.Balance(nodes);
            // Transform AOML into a DOM tree
            Stack <Element> elements = new Stack <Element>();

            elements.Push(container);
            foreach (Node node in nodes)
            {
                Element element = null;
                switch (node.Type)
                {
                case NodeType.Content:
                    // Content doesn't introduce a new level
                    // We'll simply add it as child at the current depth
                    ContentNode content = (ContentNode)node;
                    element = new TextElement(Web.UnescapeHtml(content.Value));
                    elements.Peek().Children.Add(element);
                    break;

                case NodeType.Open:
                    OpenNode open = (OpenNode)node;
                    switch (open.Name)
                    {
                    case "br":
                        // Singular linebreak element
                        element = new BreakElement();
                        elements.Peek().Children.Add(element);
                        break;

                    case "img":
                        // Singular image element
                        element = this.CreateImageElement(open);
                        if (element != null)
                        {
                            elements.Peek().Children.Add(element);
                        }
                        break;

                    case "font":
                        element = this.CreateFontElement(open);
                        elements.Peek().Children.Add(element);
                        if (!open.Closed)
                        {
                            elements.Push(element);
                        }
                        break;

                    case "a":
                        element = this.CreateLinkElement(open);
                        elements.Peek().Children.Add(element);
                        if (!open.Closed)
                        {
                            elements.Push(element);
                        }
                        break;

                    case "u":
                        element = new UnderlineElement();
                        elements.Peek().Children.Add(element);
                        if (!open.Closed)
                        {
                            elements.Push(element);
                        }
                        break;

                    case "i":
                        element = new ItalicElement();
                        elements.Peek().Children.Add(element);
                        if (!open.Closed)
                        {
                            elements.Push(element);
                        }
                        break;

                    case "center":
                    case "left":
                    case "right":
                    case "div":
                        Alignment alignment = Alignment.Inherit;
                        if (open.Name == "center" || open.GetAttribute("align") == "center")
                        {
                            alignment = Alignment.Center;
                        }
                        else if (open.Name == "left" || open.GetAttribute("align") == "left")
                        {
                            alignment = Alignment.Left;
                        }
                        else if (open.Name == "right" || open.GetAttribute("align") == "right")
                        {
                            alignment = Alignment.Right;
                        }
                        element = new AlignElement(alignment);
                        elements.Peek().Children.Add(element);
                        if (!open.Closed)
                        {
                            elements.Push(element);
                        }
                        break;

                    default:
                        throw new ArgumentException("Unexpected tag: " + open.Name);
                    }
                    break;

                case NodeType.Close:
                    // Closing a node means consuming an element from the stack
                    // But first check whether the node matches the element on the stack
                    CloseNode close = (CloseNode)node;
                    switch (close.Name)
                    {
                    case "br":
                        throw new ArgumentException("Unexpected 'br' closing tag");

                    case "img":
                        throw new ArgumentException("Unexpected 'img' closing tag");

                    case "font":
                        if (elements.Peek().Type == ElementType.Color)
                        {
                            break;
                        }
                        if (elements.Peek().Type == ElementType.Container)
                        {
                            break;
                        }
                        throw new ArgumentException("Unexpected 'font' closing tag");

                    case "a":
                        if (elements.Peek().Type == ElementType.Link)
                        {
                            break;
                        }
                        if (elements.Peek().Type == ElementType.Container)
                        {
                            break;
                        }
                        throw new ArgumentException("Unexpected 'a' closing tag");

                    case "u":
                        if (elements.Peek().Type == ElementType.Underline)
                        {
                            break;
                        }
                        throw new ArgumentException("Unexpected 'u' closing tag");

                    case "i":
                        if (elements.Peek().Type == ElementType.Italic)
                        {
                            break;
                        }
                        throw new ArgumentException("Unexpected 'i' closing tag");

                    case "div":
                    case "center":
                    case "left":
                    case "right":
                        if (elements.Peek().Type == ElementType.Align)
                        {
                            break;
                        }
                        throw new ArgumentException("Unexpected '" + close.Name + "' closing tag");

                    default:
                        throw new ArgumentException("Unexpected tag: " + close.Name);
                    }
                    if (elements.Count <= 1)
                    {
                        throw new ArgumentException("Unexpected closing tag");
                    }
                    // Go 1 step back down in the tree
                    elements.Pop();
                    break;

                default:
                    throw new InvalidOperationException("Unexpected node type");
                }
            }
            // Let's report our progress
            if (container.Children.Count == 0)
            {
                return(null);
            }
            if (container.Children.Count == 1)
            {
                return(container.Children.ToArray()[0]);
            }
            return(container);
        }
Ejemplo n.º 4
0
        protected Element CreateLinkElement(OpenNode node)
        {
            // Valid link?
            string href = node.GetAttribute("href");

            if (string.IsNullOrEmpty(href) || !href.Contains("://"))
            {
                return(new ContainerElement());
            }
            // Parse link
            int index = href.IndexOf("://");

            if (index <= 0)
            {
                return(new ContainerElement());
            }
            string  type          = href.Substring(0, index).ToLower();
            string  argument      = href.Substring(index + 3);
            Link    link          = null;
            Element windowElement = null;
            // Verify header
            Regex validCharacters = new Regex("^[a-zA-Z]+$");

            if (!validCharacters.IsMatch(type) || argument.Length == 0)
            {
                // Invalid link
                link = new InvalidLink(href);
            }
            else
            {
                // Generate link
                switch (type)
                {
                case "text":
                    windowElement = Parse(argument);
                    if (windowElement == null)
                    {
                        break;
                    }
                    link = new WindowLink(windowElement);
                    break;

                case "charref":
                    index = argument.IndexOf("/");
                    if (index < 0)
                    {
                        break;
                    }
                    index = argument.IndexOf("/", index + 1);
                    if (index <= 0)
                    {
                        break;
                    }
                    argument      = argument.Substring(index + 1);
                    windowElement = Parse(argument);
                    if (windowElement == null)
                    {
                        break;
                    }
                    link = new WindowLink(windowElement);
                    break;

                case "itemref":
                    string[] itemParts = argument.Split('/');
                    if (itemParts.Length != 3)
                    {
                        break;
                    }
                    uint lowId, highId, ql;
                    if (!uint.TryParse(itemParts[0], out lowId))
                    {
                        break;
                    }
                    if (!uint.TryParse(itemParts[1], out highId))
                    {
                        break;
                    }
                    if (!uint.TryParse(itemParts[2], out ql))
                    {
                        break;
                    }
                    link = new ItemLink(lowId, highId, ql);
                    break;

                case "itemid":
                    string[] entityParts = argument.Split('/');
                    // itemid:// can come with 4 arguments, but we have no use for the last 2
                    if (entityParts.Length != 2 && entityParts.Length != 4)
                    {
                        break;
                    }
                    uint typeId, instanceId;
                    if (!uint.TryParse(entityParts[0], out typeId))
                    {
                        break;
                    }
                    if (!uint.TryParse(entityParts[1], out instanceId))
                    {
                        break;
                    }
                    link = new EntityLink(typeId, instanceId);
                    break;

                case "chatcmd":
                    link = new CommandLink(argument);
                    break;

                case "user":
                    link = new UserLink(argument);
                    break;

                default:
                    try
                    {
                        // Attempt to create an 'OtherLink'
                        // this operation will throw an exception if the 'href' is significantly malformed
                        link = new OtherLink(href);
                    }
                    catch (UriFormatException)
                    {
                        // The 'href' is malformed, store as InvalidLink
                        link = new InvalidLink(href);
                    }
                    break;
                }
            }
            if (link == null)
            {
                return(new ContainerElement());
            }
            string style = node.GetAttribute("style");

            if (style != null)
            {
                style = style.Replace(" ", "").ToLower();
                if (!style.Contains("text-decoration:none"))
                {
                    style = null;
                }
            }
            return(new LinkElement(link, style == null));
        }