private void BbcodeUser(BbcodeEventArgs e) { if (e.Tag.Tag != "user") return; e.SetHandled(); string key = string.Empty; long id = 0; switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.AbortParse(); break; case BbcodeParseMode.Flatten: key = e.Contents; e.RemoveContents(); if (key != "you") { try { id = long.Parse(key); } catch { e.AbortParse(); return; } } else { id = core.LoggedInMemberId; } if (id > 0) { core.LoadUserProfile(id); User userUser = core.PrimitiveCache[id]; if (e.Attributes.HasAttribute("ownership") && e.Attributes.GetAttribute("ownership") == "true") { e.PrefixText = userUser.DisplayNameOwnership; e.SuffixText = string.Empty; } else { e.PrefixText = userUser.DisplayName; e.SuffixText = string.Empty; } } else { e.PrefixText = core.Prose.GetString("ANONYMOUS"); e.SuffixText = string.Empty; } break; case BbcodeParseMode.Normal: if (core != null) { key = e.Contents; e.RemoveContents(); if (key != "you") { try { id = long.Parse(key); } catch { e.AbortParse(); return; } } else { id = core.LoggedInMemberId; } if (id > 0) { core.LoadUserProfile(id); User userUser = core.PrimitiveCache[id]; if (e.Attributes.HasAttribute("ownership") && e.Attributes.GetAttribute("ownership") == "true") { if ((!e.Attributes.HasAttribute("link")) || ( e.Attributes.HasAttribute("link") && e.Attributes.GetAttribute("link") == "true")) { if ((e.Options & BbcodeOptions.FullInternalUris) == BbcodeOptions.FullInternalUris) { e.PrefixText = string.Format("<a href=\"{1}\" class=\"username-card\" bs-uid=\"{2}\">{0}</a>", userUser.DisplayNameOwnership, core.Hyperlink.StripSid(core.Hyperlink.AppendAbsoluteSid(userUser.Uri)), userUser.Id); } else { e.PrefixText = string.Format("<a href=\"{1}\" class=\"username-card\" bs-uid=\"{2}\">{0}</a>", userUser.DisplayNameOwnership, userUser.Uri, userUser.Id); } e.SuffixText = string.Empty; } else { e.PrefixText = userUser.DisplayNameOwnership; e.SuffixText = string.Empty; } } else { if ((!e.Attributes.HasAttribute("link")) || (e.Attributes.HasAttribute("link") && e.Attributes.GetAttribute("link") == "true")) { if ((e.Options & BbcodeOptions.FullInternalUris) == BbcodeOptions.FullInternalUris) { e.PrefixText = string.Format("<a href=\"{1}\" class=\"username-card\" bs-uid=\"{2}\">{0}</a>", userUser.DisplayName, core.Hyperlink.StripSid(core.Hyperlink.AppendAbsoluteSid(userUser.Uri)), userUser.Id); } else { e.PrefixText = string.Format("<a href=\"{1}\" class=\"username-card\" bs-uid=\"{2}\">{0}</a>", userUser.DisplayName, userUser.Uri, userUser.Id); } e.SuffixText = string.Empty; } else { e.PrefixText = userUser.DisplayName; e.SuffixText = string.Empty; } } } else { e.PrefixText = core.Prose.GetString("ANONYMOUS"); e.SuffixText = string.Empty; } } break; } }
private static void BbcodeInstagram(BbcodeEventArgs e) { if (e.Tag.Tag != "instagram") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string instagramUrl = e.Contents; string instagramId = instagramUrl; //if (!Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase)) e.AbortParse(); e.RemoveContents(); if (TagAllowed(e.Tag.Tag, e.Options)) { ContentPreviewCache preview = ContentPreviewCache.GetPreview(e.Core, "instagram.com", instagramId, e.Core.Prose.Language); string instagram = string.Empty; if (preview != null) { instagram = preview.Body; } else { string apiUri = "http://api.instagram.com/oembed?url=" + HttpUtility.UrlEncode(instagramId); // +"&maxwidth=550"; WebClient wc = new WebClient(); string response = wc.DownloadString(apiUri); Dictionary<string, string> strings = (Dictionary<string, string>)JsonConvert.DeserializeObject(response, typeof(Dictionary<string, string>)); if (strings.ContainsKey("type") && strings.ContainsKey("title")) { string image = string.Empty; if (strings.ContainsKey("url") && strings["type"] == "photo") { image = strings["url"]; instagram = "<a href=\"" + instagramUrl + "\"><img src=\"" + strings["url"] + "\" alt=\"" + HttpUtility.HtmlEncode(strings["title"]) + "\" style=\"max-width: 100%;\" /></a>"; } else if (strings["type"] == "rich") { image = instagramUrl.TrimEnd(new char[] { '/' }) + "/media/?size=l"; instagram = "<a href=\"" + instagramUrl + "\"><img src=\"" + image + "\" alt=\"" + HttpUtility.HtmlEncode(strings["title"]) + "\" style=\"max-width: 100%;\" /></a>"; } ContentPreviewCache.Create(e.Core, "instagram.com", instagramId, string.Empty, instagram, e.Core.Prose.Language, image); } } if (!string.IsNullOrEmpty(instagram)) { e.PrefixText = instagram; e.SuffixText = string.Empty; } else { e.PrefixText = "<a href=\"" + instagramUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } } else { e.PrefixText = "<a href=\"" + instagramUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } break; } }
private void BbcodeShare(BbcodeEventArgs e) { if (e.Tag.Tag != "share") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve if (e.ShareDepth == 1) { e.AbortParse(); } else { if (e.QuoteDepth == 1) { e.AbortParse(); } else if (e.QuoteDepth > 1) { e.PrefixText = string.Empty; e.SuffixText = string.Empty; e.RemoveContents(); } else { e.PrefixText = string.Empty; e.SuffixText = string.Empty; } } break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: if (e.Attributes.HasAttributes()) { e.PrefixText = "\n--- " + Parse(e.Attributes.GetAttribute("default"), null, e.Owner, false, null, null, e.Mode) + " originally shared: ---\n"; } else { e.PrefixText = "\n--- Shared: ---\n"; } e.SuffixText = "\n---------------------\n"; break; case BbcodeParseMode.Normal: if (e.Attributes.HasAttributes()) { if (!e.InList) { e.PrefixText = "</p><p><strong>" + Parse(e.Attributes.GetAttribute("default")) + " originally shared:</strong></p><blockquote><p>"; } else { e.PrefixText = "<p><strong>" + Parse(e.Attributes.GetAttribute("default")) + " originally shared:</strong></p><blockquote>"; } } else { if (!e.InList) { e.PrefixText = "</p><blockquote><p>"; } else { e.PrefixText = "<blockquote>"; } } e.SuffixText = "</p></blockquote><p>"; break; } }
private static void BbcodeFloat(BbcodeEventArgs e) { if (e.Tag.Tag != "float") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: if (!e.InList) { if (!Regex.IsMatch(e.Attributes.GetAttribute("default"), "^(left|right)$")) e.AbortParse(); string styles = string.Empty; switch (e.Attributes.GetAttribute("default")) { case "left": styles = "float: left; margin-right: 10px; max-width: 100%;"; break; case "right": styles = "float: right; margin-left: 10px; max-width: 100%;"; break; } if (e.Attributes.HasAttribute("width")) { int width = 0; Match match = Regex.Match(e.Attributes.GetAttribute("width"), "^(\\d+)([ \t]*)(|%|px)$"); if (match.Success && int.TryParse(match.Groups[1].Value, out width)) { if (match.Groups[3].Value == "%") { styles += "; width: " + width.ToString() + "%"; } else { styles += "; width: " + width.ToString() + "px"; } } } if (e.Attributes.HasAttribute("height")) { int height = 0; Match match = Regex.Match(e.Attributes.GetAttribute("height"), "^(\\d+)([ \t]*)(|px)$"); if (match.Success && int.TryParse(match.Groups[1].Value, out height)) { styles += "; height: " + height.ToString() + "px"; } } e.PrefixText = "</p><div style=\"" + styles + "\">"; e.SuffixText = "</div><p>"; } else { e.AbortParse(); } break; } }
private static void BbcodeH3(BbcodeEventArgs e) { if (e.Tag.Tag != "h3") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: e.PrefixText = "</p><h4 id=\"" + getHeaderId(e.Contents) + "\">"; e.SuffixText = "</h4><p>"; break; } }
private static void BbcodeBold(BbcodeEventArgs e) { if (e.Tag.Tag != "b") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: e.PrefixText = "*"; e.SuffixText = "*"; break; case BbcodeParseMode.Normal: e.PrefixText = "<strong>"; e.SuffixText = "</strong>"; break; } }
private static void BbcodeColour(BbcodeEventArgs e) { if (e.Tag.Tag != "color") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: try { System.Drawing.ColorTranslator.FromHtml(e.Attributes.GetAttribute("default")); } catch { e.AbortParse(); } e.PrefixText = "<span style=\"color: " + e.Attributes.GetAttribute("default") + "\">"; e.SuffixText = "</span>"; break; } }
private static void BbcodeTableOfContents(BbcodeEventArgs e) { if (e.Tag.Tag != "toc") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Normal: break; } }
private static void BbcodeThumb(BbcodeEventArgs e) { if (e.Tag.Tag != "thumb") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.PrefixText = string.Empty; e.RemoveContents(); break; case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: if (Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase)) { e.PrefixText = "<img alt=\"Bbcode image\" class=\"bbcode-thumb\" style=\"max-width: 100px; max-height: 100px;\" src=\""; e.SuffixText = "\" />"; } else { if (e.Owner == null) { e.AbortParse(); } else { if (e.Core.Settings.UseCdn && e.Attributes.HasAttribute("cdn-object")) { e.PrefixText = "<img alt=\"Bbcode image\" class=\"bbcode-thumb\" src=\"" + e.Core.Http.DefaultProtocol + HttpUtility.HtmlEncode(e.Core.Settings.CdnTileBucketDomain) + "/" + e.Attributes.GetAttribute("cdn-object") + "\" data-at2x=\"" + e.Core.Http.DefaultProtocol + HttpUtility.HtmlEncode(e.Core.Settings.CdnSquareBucketDomain) + "/" + e.Attributes.GetAttribute("cdn-object"); e.SuffixText = "\" />"; e.RemoveContents(); } else { e.PrefixText = "<img alt=\"Bbcode image\" class=\"bbcode-thumb\" src=\"" + HttpUtility.HtmlEncode(e.Owner.UriStubAbsolute) + "images/_tile/" + e.Contents + "\" data-at2x=\"" + HttpUtility.HtmlEncode(e.Owner.UriStubAbsolute) + "images/_square/"; e.SuffixText = "\" />"; } } } break; } }
private static void BbcodeSize(BbcodeEventArgs e) { if (e.Tag.Tag != "size") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: try { int fontSize = int.Parse(e.Attributes.GetAttribute("default")); if (fontSize > 300 || fontSize < 25) e.AbortParse(); } catch { e.AbortParse(); } e.PrefixText = "<span style=\"font-size: " + e.Attributes.GetAttribute("default") + "%\">"; e.SuffixText = "</span>"; break; } }
private static void BbcodeSoundcloud(BbcodeEventArgs e) { if (e.Tag.Tag != "soundcloud") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string soundcloudUrl = e.Contents; string soundcloudId = soundcloudUrl; //if (!Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase)) e.AbortParse(); e.RemoveContents(); if (TagAllowed(e.Tag.Tag, e.Options)) { ContentPreviewCache preview = ContentPreviewCache.GetPreview(e.Core, "soundcloud.com", soundcloudId, e.Core.Prose.Language); string soundcloud = string.Empty; if (preview != null) { soundcloud = preview.Body; } else { string apiUri = "http://soundcloud.com/oembed?format=json&url=" + HttpUtility.UrlEncode(soundcloudId) + "&show_comments=false"; WebClient wc = new WebClient(); string response = wc.DownloadString(apiUri); Dictionary<string, string> strings = (Dictionary<string, string>)JsonConvert.DeserializeObject(response, typeof(Dictionary<string, string>)); if (strings.ContainsKey("html")) { soundcloud = strings["html"]; } ContentPreviewCache.Create(e.Core, "soundcloud.com", soundcloudId, string.Empty, soundcloud, e.Core.Prose.Language); } if (!string.IsNullOrEmpty(soundcloud)) { e.PrefixText = "</p>" + soundcloud + "<p>"; e.SuffixText = string.Empty; } else { e.PrefixText = "<a href=\"" + soundcloudUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } } else { e.PrefixText = "<a href=\"" + soundcloudUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } break; } }
private static void BbcodeMap(BbcodeEventArgs e) { if (e.Tag.Tag != "map") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string mapUrl = e.Contents; e.RemoveContents(); if (mapUrl.ToLower().StartsWith("http://", StringComparison.Ordinal) || mapUrl.ToLower().StartsWith("https://", StringComparison.Ordinal)) { char[] splitChars = { '=', '?', '&' }; string[] argh = mapUrl.Split(splitChars); if (argh.Length <= 2) { e.AbortParse(); } for (int y = 0; y < argh.Length - 1; y++) { if (argh[y] == "mid") { mapUrl = argh[y + 1]; } else if (y == argh.Length - 2) { e.AbortParse(); } } } mapUrl = "http://mapsengine.google.com/map/embed?mid=" + mapUrl; if (e.Core.IsMobile) { e.PrefixText = "<iframe width=\"300\" height=\"194\" src=\"" + mapUrl + "\" ></iframe>"; } else { e.PrefixText = "<iframe width=\"560\" height=\"340\" src=\"" + mapUrl + "\" ></iframe>"; } e.SuffixText = string.Empty; break; } }
private static void BbcodeList(BbcodeEventArgs e) { if (e.Tag.Tag != "list") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: if (e.Attributes.GetAttribute("default") != null) { if (Regex.IsMatch(e.Attributes.GetAttribute("default"), "^[aA1iI]{1}$")) { if (!e.InList) { e.PrefixText = "</p><ol style=\"list-style-type:" + Bbcode.OlTypeToCssName(e.Attributes.GetAttribute("default")) + "\">"; e.SuffixText = "</ol><p>"; } else { e.PrefixText = "<ol style=\"list-style-type:" + Bbcode.OlTypeToCssName(e.Attributes.GetAttribute("default")) + "\">"; e.SuffixText = "</ol>"; } } else if (Regex.IsMatch(e.Attributes.GetAttribute("default"), "^(circle|square)$")) { if (!e.InList) { e.PrefixText = "</p><ul style=\"list-style-type:" + Bbcode.UlTypeToCssName(e.Attributes.GetAttribute("default")) + "\">"; e.SuffixText = "</ul><p>"; } else { e.PrefixText = "<ul style=\"list-style-type:" + Bbcode.UlTypeToCssName(e.Attributes.GetAttribute("default")) + "\">"; e.SuffixText = "</ul>"; } } else { e.AbortParse(); } } else { if (!e.InList) { e.PrefixText = "</p><ul>"; e.SuffixText = "</ul><p>"; } else { e.PrefixText = "<ul>"; e.SuffixText = "</ul>"; } } break; } }
private static void BbcodeLaTeX(BbcodeEventArgs e) { if (e.Tag.Tag != "latex") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string latexExpression = HttpUtility.UrlEncode(e.Contents).Replace("+", "%20"); e.RemoveContents(); e.PrefixText = "<img src=\"" + e.Core.Http.DefaultProtocol + Hyperlink.Domain + "/mimetex.cgi?" + latexExpression + "\" alt=\"LaTeX Equation\"/>"; e.SuffixText = string.Empty; break; } }
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(""")) { 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> </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; }
private static void BbcodeTwitter(BbcodeEventArgs e) { if (e.Tag.Tag != "tweet") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string tweetUrl = e.Contents; string tweetId = tweetUrl; //if (!Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase)) e.AbortParse(); e.RemoveContents(); if (tweetUrl.ToLower().StartsWith("http://", StringComparison.Ordinal) || tweetUrl.ToLower().StartsWith("https://", StringComparison.Ordinal)) { char[] splitChars = { '/' }; string[] argh = tweetUrl.Split(splitChars); if (argh.Length > 0) { tweetId = argh[argh.Length - 1]; } } if (TagAllowed(e.Tag.Tag, e.Options)) { ContentPreviewCache preview = ContentPreviewCache.GetPreview(e.Core, "twitter.com", tweetId, e.Core.Prose.Language); string tweet = string.Empty; if (preview != null) { tweet = preview.Body; } else { string apiUri = "https://api.twitter.com/1/statuses/oembed.json?id=" + tweetId + "&maxwidth=550"; WebClient wc = new WebClient(); string response = wc.DownloadString(apiUri); Dictionary<string, string> strings = (Dictionary<string, string>)JsonConvert.DeserializeObject(response, typeof(Dictionary<string, string>)); if (strings.ContainsKey("html")) { tweet = strings["html"]; } ContentPreviewCache.Create(e.Core, "twitter.com", tweetId, string.Empty, tweet, e.Core.Prose.Language); } if (!string.IsNullOrEmpty(tweet)) { e.PrefixText = "</p>" + tweet + "<p>"; e.SuffixText = string.Empty; } else { e.PrefixText = "<a href=\"" + tweetUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } } else { e.PrefixText = "<a href=\"" + tweetUrl + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } break; } }
private static void BbcodeAlign(BbcodeEventArgs e) { if (e.Tag.Tag != "align") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: if (!Regex.IsMatch(e.Attributes.GetAttribute("default"), "^(left|right|center|justify)$")) e.AbortParse(); e.PrefixText = "</p><p style=\"text-align: " + e.Attributes.GetAttribute("default") + "\">"; e.SuffixText = "</p><p>"; break; } }
private static void BbcodeUnderline(BbcodeEventArgs e) { if (e.Tag.Tag != "u") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Normal: e.PrefixText = "<span style=\"text-decoration: underline;\">"; e.SuffixText = "</span>"; break; } }
private static void BbcodeCode(BbcodeEventArgs e) { if (e.Tag.Tag != "code") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Remove code blocks e.PrefixText = string.Empty; e.SuffixText = string.Empty; e.RemoveContents(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: e.PrefixText = "--- Code ---"; e.SuffixText = "------"; break; case BbcodeParseMode.Normal: bool hasColour = e.Attributes.HasAttribute("color"); string caption = (e.Attributes.HasAttribute("caption") ? e.Attributes.GetAttribute("caption") : "Code"); if (hasColour) { try { System.Drawing.ColorTranslator.FromHtml(e.Attributes.GetAttribute("color")); } catch { e.AbortParse(); } } if (!string.IsNullOrEmpty(caption)) { caption = string.Format("<strong>{0}</strong>", caption); } if (!e.InList) { e.PrefixText = string.Format("{0}</p><p><code{1}>", caption, hasColour ? " style=\"color: " + e.Attributes.GetAttribute("color") + "\"" : string.Empty) + e.Contents.Trim(new char[] { '\n' }).Replace(" ", " "); e.SuffixText = "</code></p><p>"; e.RemoveContents(); } else { if (!string.IsNullOrEmpty(caption)) { caption = string.Format("<strong>{0}</strong>", caption); } e.PrefixText = string.Format("{0}<br /><code{1}>", caption, hasColour ? " style=\"color: " + e.Attributes.GetAttribute("color") + "\"" : string.Empty) + e.Contents.Trim(new char[] { '\n' }).Replace(" ", " "); e.SuffixText = "</code>"; e.RemoveContents(); } break; } }
private static void BbcodeUrl(BbcodeEventArgs e) { if (e.Tag.Tag != "url") return; e.SetHandled(); if (urlRegex2 == null) { urlRegex2 = new Regex("^([\\w]+?://[\\w\\#$%&~/.\\-;:=,?@\\(\\)\\[\\]+]*?)$", RegexOptions.Compiled); urlRegex3 = new Regex("^((www|ftp)\\.[\\w\\#$%&~/.\\-;:=,?@\\(\\)\\[\\]+]*?)$", RegexOptions.Compiled); } switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: if (e.Attributes.HasAttributes()) { e.PrefixText = string.Empty; e.SuffixText = " : (" + e.Attributes.GetAttribute("default") + ")"; } else { e.PrefixText = string.Empty; e.SuffixText = string.Empty; } break; case BbcodeParseMode.Normal: if (e.Attributes.HasAttributes()) { if (urlRegex2.IsMatch(e.Attributes.GetAttribute("default"))) // "^([\\w]+?://[\\w\\#$%&~/.\\-;:=,?@\\(\\)\\[\\]+]*?)$", RegexOptions.Compiled { e.PrefixText = "<a href=\"" + e.Attributes.GetAttribute("default") + "\">"; } else if (urlRegex3.IsMatch(e.Attributes.GetAttribute("default"))) // "^((www|ftp)\\.[\\w\\#$%&~/.\\-;:=,?@\\(\\)\\[\\]+]*?)$", RegexOptions.Compiled { e.PrefixText = "<a href=\"http://" + e.Attributes.GetAttribute("default") + "\">"; } else { e.AbortParse(); } e.SuffixText = "</a>"; } else { Uri url = null; //"(^|\\s)((http(s)?://|ftp://|www\\.)([\\w+?\\.\\w+]+)([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?)" if (urlRegex2.IsMatch(e.Contents)) { url = new Uri(e.Contents); e.PrefixText = "<a href=\"" + e.Contents + "\">" + UriToString(e.Core, url); } else if (urlRegex3.IsMatch(e.Contents)) { url = new Uri("http://" + e.Contents); e.PrefixText = "<a href=\"http://" + e.Contents + "\">" + UriToString(e.Core, url); } else { e.AbortParse(); } e.RemoveContents(); e.SuffixText = "</a>"; } break; } }
private static void BbcodeFlash(BbcodeEventArgs e) { // TODO: flash bbcode if (e.Tag.Tag != "flash") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: if (TagAllowed(e.Tag.Tag, e.Options)) { } else { } break; } }
private static void BbcodeYouTube(BbcodeEventArgs e) { if (e.Tag.Tag != "youtube") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: string youTubeUrl = e.Contents; e.RemoveContents(); if (youTubeUrl.ToLower().StartsWith("http://youtu.be/", StringComparison.Ordinal) || youTubeUrl.ToLower().StartsWith("https://youtu.be/", StringComparison.Ordinal) || youTubeUrl.ToLower().StartsWith("youtu.be/", StringComparison.Ordinal)) { char[] splitChars = { '/' }; string[] argh = youTubeUrl.Split(splitChars); if (argh.Length < 2) { e.AbortParse(); } else { youTubeUrl = argh[argh.Length - 1]; } } else if (youTubeUrl.ToLower().StartsWith("http://", StringComparison.Ordinal) || youTubeUrl.ToLower().StartsWith("https://", StringComparison.Ordinal)) { char[] splitChars = { '=', '?', '&' }; string[] argh = youTubeUrl.Split(splitChars); if (argh.Length <= 2) { e.AbortParse(); } for (int y = 0; y < argh.Length - 1; y++) { if (argh[y] == "v") { youTubeUrl = argh[y + 1]; } else if (y == argh.Length - 2) { e.AbortParse(); } } } if (TagAllowed(e.Tag.Tag, e.Options)) { if (e.Core.Http.IsSecure) { youTubeUrl = "https://www.youtube.com/embed/" + youTubeUrl; } else { youTubeUrl = "http://www.youtube.com/embed/" + youTubeUrl; } // Old YouTube Flash Embed Code //e.PrefixText = "<object width=\"425\" height=\"350\"><param name=\"movie\" value=\"" + youTubeUrl + "\"></param><embed src=\"" + youTubeUrl + "\" type=\"application/x-shockwave-flash\" width=\"425\" height=\"350\"></embed></object>"; // New YouTube Embed Code if (e.Core.IsMobile) { e.PrefixText = "<iframe class=\"youtube-player\" type=\"text/html\" width=\"300\" height=\"194\" src=\"" + youTubeUrl + "\" frameborder=\"0\"></iframe>"; } else { e.PrefixText = "<iframe class=\"youtube-player\" type=\"text/html\" width=\"560\" height=\"340\" src=\"" + youTubeUrl + "\" frameborder=\"0\"></iframe>"; } e.SuffixText = string.Empty; } else { youTubeUrl = "http://www.youtube.com/watch?v=" + youTubeUrl; e.PrefixText = "<a href=\"" + youTubeUrl + "\"><strong>YT:</strong> " + youTubeUrl; e.SuffixText = "</a>"; } break; } }
private static void BbcodeGplus(BbcodeEventArgs e) { if (e.Tag.Tag != "gplus") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.PrefixText = string.Empty; e.RemoveContents(); break; case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: if (!Regex.IsMatch(e.Contents, "^((http|https)://)plus\\.google\\.com/(\\d+)/posts/([a-zA-Z0-9]+)$", RegexOptions.IgnoreCase)) e.AbortParse(); // Until Google resolves the rendering of the embed code on mobile devices, we will simply link to the post /*if (TagAllowed(e.Tag.Tag, e.Options)) { VariableCollection javaScriptVariableCollection = e.Core.Template.CreateChild("javascript_list"); javaScriptVariableCollection.Parse("URI", @"https://apis.google.com/js/plusone.js"); e.PrefixText = "<div class=\"g-post\" style=\"max-width: 100%;\" data-href=\""; e.SuffixText = "\"< </div>"; } else*/ { e.PrefixText = "<a href=\"" + e.Contents + "\"><strong>G+</strong>: "; e.SuffixText = "</a>"; } break; } }
private void BbcodeInternalUrl(BbcodeEventArgs e) { if (e.Tag.Tag != "iurl") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.SuffixText = string.Empty; break; case BbcodeParseMode.Flatten: if (e.Attributes.HasAttributes()) { e.PrefixText = string.Empty; e.SuffixText = string.Empty; //string.Format("(http://" + Hyperlink.Domain + "{0})", core.Hyperlink.StripSid(e.Attributes.GetAttribute("default"))); } else { e.PrefixText = "(http://" + Hyperlink.Domain; e.SuffixText = ")"; } break; case BbcodeParseMode.Normal: if (e.Attributes.HasAttributes()) { if ((e.Options & BbcodeOptions.FullInternalUris) == BbcodeOptions.FullInternalUris) { e.PrefixText = "<a href=\"" + core.Hyperlink.StripSid(core.Hyperlink.AppendAbsoluteSid(e.Attributes.GetAttribute("default"))) + "\">"; } else { if (e.Attributes.HasAttribute("sid") && e.Attributes.GetAttribute("sid").ToLower() == "true") { e.PrefixText = "<a href=\"" + core.Hyperlink.AppendSid(e.Attributes.GetAttribute("default"), true) + "\">"; } else { e.PrefixText = "<a href=\"" + core.Hyperlink.AppendSid(e.Attributes.GetAttribute("default")) + "\">"; } } e.SuffixText = "</a>"; } else { if ((e.Options & BbcodeOptions.FullInternalUris) == BbcodeOptions.FullInternalUris) { e.PrefixText = "<a href=\"" + core.Hyperlink.StripSid(core.Hyperlink.AppendAbsoluteSid(e.Contents)) + "\">"; } else { e.PrefixText = "<a href=\"" + core.Hyperlink.AppendSid(e.Contents) + "\">"; } e.SuffixText = "</a>"; } break; } }
private static void BbcodeImage(BbcodeEventArgs e) { if (e.Tag.Tag != "img") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.PrefixText = string.Empty; e.RemoveContents(); break; case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: if (!(Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase) || Regex.IsMatch(e.Contents, "^(http|https)://instagram\\.com/p/([a-z0-9]+)/media/.*$", RegexOptions.IgnoreCase))) e.AbortParse(); if (TagAllowed(e.Tag.Tag, e.Options)) { e.PrefixText = "<img alt=\"Bbcode image\" style=\"max-width: 100%;\" src=\""; e.SuffixText = "\" />"; } else { e.PrefixText = "<a href=\"" + e.Contents + "\"><strong>IMG</strong>: "; e.SuffixText = "</a>"; } break; } }
private static void BbcodeInline(BbcodeEventArgs e) { if (e.Tag.Tag != "inline") return; e.SetHandled(); switch (e.Mode) { case BbcodeParseMode.Tldr: // Preserve e.AbortParse(); break; case BbcodeParseMode.StripTags: e.PrefixText = string.Empty; e.PrefixText = string.Empty; e.RemoveContents(); break; case BbcodeParseMode.Flatten: e.PrefixText = string.Empty; e.PrefixText = string.Empty; break; case BbcodeParseMode.Normal: if (e.Owner == null) { e.AbortParse(); } else { if (Regex.IsMatch(e.Contents, "^((http|ftp|https|ftps)://)([^ \\?&=\\#\\\"\\n\\r\\t<]*?(\\.(jpg|jpeg|gif|png)))$", RegexOptions.IgnoreCase)) { e.PrefixText = "<img alt=\"Bbcode image\" src=\""; e.SuffixText = "\" />"; } else { if (e.Owner == null) { e.AbortParse(); } else { int width = 0; int height = 0; if (e.Attributes.HasAttribute("width")) { int.TryParse(e.Attributes.GetAttribute("width"), out width); } if (e.Attributes.HasAttribute("height")) { int.TryParse(e.Attributes.GetAttribute("height"), out height); } if (e.Core.Settings.UseCdn && e.Attributes.HasAttribute("cdn-object") /*&& (width > 640 || height > 640)*/) { e.PrefixText = "<img alt=\"Bbcode image\" style=\"max-width: 100%;\" src=\"" + e.Core.Http.DefaultProtocol + HttpUtility.HtmlEncode(e.Core.Settings.CdnDisplayBucketDomain) + "/" + e.Attributes.GetAttribute("cdn-object") + "\" data-at2x=\"" + e.Core.Http.DefaultProtocol + HttpUtility.HtmlEncode(e.Core.Settings.CdnFullBucketDomain) + "/" + e.Attributes.GetAttribute("cdn-object"); e.SuffixText = "\" />"; e.RemoveContents(); } else { e.PrefixText = "<img alt=\"Bbcode image\" style=\"max-width: 100%;\" src=\"" + HttpUtility.HtmlEncode(e.Owner.UriStubAbsolute) + "/images/_display/" + e.Contents + "\" data-at2x=\"" + HttpUtility.HtmlEncode(e.Owner.UriStubAbsolute) + "/images/_full/"; e.SuffixText = "\" />"; } } } } break; } }