Exemplo n.º 1
0
        private string Parse(string input, User viewer, Primitive postOwner, bool appendP, string id, string styleClass, BbcodeParseMode mode, bool fullInternalUrls)
        {
            #if DEBUG
            timer.Start();
            parseCount++;
            #endif
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }

            if (mode == BbcodeParseMode.Normal)
            {
                // Convert all URLs that aren't BB Coded into BB Code
                input = ParseUrls(input);
            }

            StringBuilder debugLog = new StringBuilder();

            BbcodeOptions options = BbcodeOptions.ShowImages | BbcodeOptions.ShowFlash | BbcodeOptions.ShowVideo | BbcodeOptions.ShowAudio;

            if (viewer != null)
            {
                options = viewer.UserInfo.GetUserBbcodeOptions;
            }

            if (fullInternalUrls)
            {
                options = options | BbcodeOptions.FullInternalUris;
            }

            long start = DateTime.Now.Ticks;
            Stack tags = new Stack();
            bool inTag = false;
            bool startAttr = false;
            bool endTag = false;
            bool inQuote = false;
            int inList = 0;
            bool parseList = false;
            bool inCode = false;
            string Tag = string.Empty;
            string attr = string.Empty;
            int startIndex = 0;
            int strLength = input.Length;
            int end = strLength;
            int quoteDepth = 0;
            int shareStart = 0;
            int shareDepth = 0;

            StringBuilder newOutput = new StringBuilder();
            int lastEndIndex = 0;

            if (mode == BbcodeParseMode.Normal && appendP)
            {
                newOutput.Append("<p");
                if (!string.IsNullOrEmpty(id))
                {
                    newOutput.Append(" id=\"");
                    newOutput.Append(id);
                    newOutput.Append("\"");
                }

                if (!string.IsNullOrEmpty(styleClass))
                {
                    newOutput.Append(" class=\"");
                    newOutput.Append(styleClass);
                    newOutput.Append("\"");
                }
                newOutput.Append(">");
            }

            List<BbcodeTaglet> taglets = new List<BbcodeTaglet>();

            int indexOffset = 0;
            int i = 0;
            while (i < strLength)
            {
                char current = input[i];
                if (!inQuote && inList > 0)
                {
                    if (current.Equals('[') && tags.Count > 0 && (i + 7) <= input.Length)
                    {
                        if (input.Substring(i, 3) == "[*]" || input.Substring(i, 7) == "[/list]")
                        {
                            if (((BbcodeTag)tags.Peek()).Tag.Equals("*"))
                            {
                                endTag = true;
                                Tag = "*";
                                parseList = true;
                            }
                        }
                    }
                }
                if (current.Equals(']') && !inQuote || (inList > 0 && parseList))
                {
                    parseList = false;
                    startAttr = false;
                    if (!endTag && !inCode)
                    {
                        if (Tag.Length > 0)
                        {
                            tags.Push(new BbcodeTag(Tag, attr, startIndex, indexOffset));
                            if (Tag.Equals("list"))
                            {
                                if (ValidList((BbcodeTag)tags.Peek()))
                                {
                                    if (EndTag(input, i, "list")) inList++;
                                }
                                else
                                {
                                    tags.Pop();
                                }
                            }

                            if (Tag.Equals("code"))
                            {
                                inCode = true;
                            }

                            if (Tag.Equals("quote"))
                            {
                                quoteDepth++;
                            }

                            if (Tag.Equals("share"))
                            {
                                quoteDepth++;
                                shareDepth++;
                            }
                        }
                    }
                    if (endTag)
                    {
                        if (Tag.Length > 0)
                        {
                            if (tags.Count > 0)
                            {
                                bool startTagExists = false;
                                foreach (BbcodeTag bt in tags)
                                {
                                    if (bt.Tag.Equals(Tag)) startTagExists = true;
                                }
                                if (startTagExists)
                                {
                                    while (!((BbcodeTag)tags.Peek()).Tag.Equals(Tag))
                                    {
                                        // TODO: style
                                        tags.Pop();
                                    }
                                }
                                if (((BbcodeTag)tags.Peek()).Tag.Equals(Tag))
                                {
                                    BbcodeTag tempTag = (BbcodeTag)tags.Pop();
                                    int tagLength = Tag.Length;
                                    int startTagLength = 2 + tagLength + tempTag.Attributes.Length;
                                    int endTagLength = 3 + tagLength;
                                    int startReplaceLength = 2 + tagLength;
                                    int endReplaceLength = 3 + tagLength;
                                    int endOffset = 0;
                                    bool abortParse = false;
                                    string insertStart = string.Empty;
                                    string insertEnd = string.Empty;
                                    bool listItem = false;
                                    bool trimStart = false;

                                    /*
                                     * A couple of special cases
                                     */
                                    if (Tag.Equals("code"))
                                    {
                                        inCode = false;
                                    }

                                    if (Tag.Equals("list"))
                                    {
                                        inList--;
                                    }

                                    if (Tag.Equals("*"))
                                    {
                                        listItem = true;
                                        endOffset = 0;
                                        endTagLength = 0;
                                    }

                                    if (Tag.Equals("quote"))
                                    {
                                        quoteDepth--;
                                    }

                                    if (Tag.Equals("share"))
                                    {
                                        quoteDepth--;
                                    }

                                    bool handled = false;

                                    int tempIndex = tempTag.indexStart + tempTag.StartLength;
                                    string contents = string.Empty;
                                    int tempLength = i - tempIndex - tempTag.EndLength + 1;
                                    if (tempLength > 0)
                                    {
                                        contents = input.Substring(tempIndex, tempLength);
                                    }

                                    BbcodeEventArgs eventArgs = new BbcodeEventArgs(core, contents, tempTag, options, postOwner, (inList > 0), quoteDepth, shareDepth, mode, ref insertStart, ref insertEnd, ref handled, ref abortParse);
                                    BbcodeHooks(eventArgs);

                                    insertStart = eventArgs.PrefixText;
                                    insertEnd = eventArgs.SuffixText;
                                    handled = eventArgs.Handled;
                                    abortParse = eventArgs.ParseAborted;

                                    if (eventArgs.NoContents)
                                    {
                                        startTagLength += eventArgs.Contents.Length;
                                    }

                                    if (!handled)
                                    {
                                        abortParse = true;
                                    }

                                    startReplaceLength = insertStart.Length;
                                    endReplaceLength = insertEnd.Length;

                                    /* We force trimming the share to the first shared to behave properly */
                                    if (mode == BbcodeParseMode.Tldr && Tag.Equals("share") && quoteDepth == 1)
                                    {
                                        trimStart = true;
                                        /* Do not delete the tag as we are in Tldr mode, but do remove everything before it */
                                        taglets.Add(new BbcodeTaglet(trimStart, tempTag.indexStart, 0, insertStart));
                                    }

                                    if (!abortParse)
                                    {
                                        /* two pass method */
                                        taglets.Add(new BbcodeTaglet(trimStart, tempTag.indexStart, startTagLength, insertStart));
                                        taglets.Add(new BbcodeTaglet(startIndex - endOffset, endTagLength, insertEnd, listItem));
                                    }
                                }
                            }
                        }
                    }
                    inTag = false;
                    endTag = false;
                    inQuote = false;
                    Tag = string.Empty;
                    attr = string.Empty;
                }
                else
                {
                    if (inTag)
                    {
                        if (current.Equals('&') && (i + 6) <= strLength && input.Substring(i, 6).Equals("&quot;"))
                        {
                            inQuote = !inQuote;
                        }
                        if (i == startIndex + 1 && current.Equals('/'))
                        {
                            endTag = true;
                        }
                        else
                        {
                            if (current.Equals(' ') || current.Equals('='))
                            {
                                if (Tag.Length == 0)
                                {
                                    inTag = false;
                                    endTag = false;
                                    inQuote = false;
                                    Tag = string.Empty;
                                    attr = string.Empty;
                                }
                                else
                                {
                                    startAttr = true;
                                }
                            }
                            if (startAttr)
                            {
                                attr += current.ToString();
                            }
                            else
                            {
                                if ((current >= 'a' && current <= 'z') || (current >= 'A' && current <= 'Z') || (current >= '0' && current <= '9') || current == '*')
                                {
                                    Tag += current.ToString().ToLower();
                                }
                                else
                                {
                                    inTag = false;
                                    endTag = false;
                                    inQuote = false;
                                    Tag = string.Empty;
                                    attr = string.Empty;
                                }
                            }
                        }
                    }
                }
                if (current.Equals('[') && !inQuote)
                {
                    startIndex = i;
                    inTag = true;
                    endTag = false;
                    inQuote = false;
                    startAttr = false; // fixed parsing error
                    Tag = string.Empty;
                    attr = string.Empty;
                }
                i++;
                if (!inTag)
                {
                    int nextIndex = input.IndexOf('[', i);
                    if (nextIndex > 0)
                    {
                        i = startIndex = nextIndex;
                    }
                }
            }

            /* second pass */
            /* unpack the list into the input stream */
            taglets.Sort();

            for (int t = 0; t < taglets.Count; t++)
            {
                BbcodeTaglet taglet = taglets[t];
                if ((!taglet.TrimStart) && taglet.StartIndex - lastEndIndex > 0)
                {
                    newOutput.Append(input.Substring(lastEndIndex, taglet.StartIndex - lastEndIndex));
                }
                newOutput.Append(taglet.RenderText);
                lastEndIndex = taglet.StartIndex + taglet.Length;
            }

            if (input.Length > lastEndIndex)
            {
                newOutput.Append(input.Substring(lastEndIndex, input.Length - lastEndIndex));
            }

            if (mode == BbcodeParseMode.Tldr)
            {
                if (shareStart > 0)
                {
                    newOutput.Remove(0, shareStart);
                }
            }

            if (mode == BbcodeParseMode.Normal && appendP)
            {
                newOutput.Append("</p>");
            }

            input = newOutput.ToString();
            double time = ((double)(DateTime.Now.Ticks - start)) / 10000000;

            if (mode == BbcodeParseMode.Normal)
            {
                input = input.Replace("\r\n", "\n");
                input = input.Replace("\n", "<br />");
                //input = input.Replace("<br /><br />", "</p><p>"); // Maybe? Need parser to break span tags at new lines
                input = input.Replace("<br /><br /><a ", "</p><p><a "); // But if the next tag is an anchor then it's a pretty decent chance that there is no formatting
                input = input.Replace("<p></p>", string.Empty);
                input = input.Replace("<p><br /><br />", "<p>");
                input = input.Replace("<p><br />", "<p>");
                input = input.Replace("<br /></p>", "</p>");
                input = input.Replace("<br /><li>", "<li>");
                input = input.Replace("<br /></ul>", "</ul>");
                input = input.Replace("<br /></ol>", "</ol>");
                input = input.Replace("<blockquote></blockquote>", "<blockquote>&nbsp;</blockquote>");
                //input = Regex.Replace(input, @"\<p\>(\s+)\<\/p\>", string.Empty, RegexOptions.Compiled);
                input = input.Replace("<p></p>", string.Empty);
                input = input.Replace("<p> </p>", string.Empty);
                input = input.Replace("<p>\n</p>", string.Empty);
                input = input.Replace("<p>\r\n</p>", string.Empty);

                input = ParseEmoticons(core, input);
            }

            #if DEBUG
            timer.Stop();
            #endif

            return input;
        }
Exemplo n.º 2
0
 public BbcodeEventArgs(Core core, string contents, BbcodeTag tag, BbcodeOptions options, User postOwner, bool inList, int quoteDepth, int shareDepth, BbcodeParseMode mode, ref string prefixText, ref string suffixText, ref bool handled, ref bool abortParse)
 {
     this.core = core;
     this.tag = tag;
     this.options = options;
     this.attributes = tag.GetAttributes();
     this.contents = contents;
     this.prefixText = prefixText;
     this.suffixText = suffixText;
     this.inList = inList;
     this.quoteDepth = quoteDepth;
     this.shareDepth = shareDepth;
     this.mode = mode;
     this.handled = handled;
     this.abortParse = abortParse;
     this.owner = postOwner;
 }
Exemplo n.º 3
0
 private string Parse(string input, User viewer, Primitive postOwner, bool appendP, string id, string styleClass, BbcodeParseMode mode)
 {
     return Parse(input, viewer, postOwner, appendP, id, styleClass, mode, false);
 }