⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transforms.cs

📁 解压即可使用
💻 CS
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Web;
using System.IO;
using System.Web.Caching;
using System.Text.RegularExpressions;
using System.Text;


namespace CommunityServer.Components {

    /// <summary>
    /// This class is used to take the body of a post message and pre-format it to HTML. Two versions
    /// of the post body are stored in the database: raw original post and the transformed pre-formatted
    /// post. Pre-transforming the post offers better performance.
    /// </summary>
    public class Transforms {

		#region FormatPost
        // *********************************************************************
        //  FormatPost
        //
        /// <summary>
        /// Main public routine called to perform string transforms.
        /// </summary>
        /// 
        // ********************************************************************/
        public static string FormatPostText (string rawPostBody)  {
            return FormatPostText (rawPostBody, PostType.HTML, true);
        }

        public static string FormatPostText (string rawPostBody, PostType postType) {
            return FormatPostText (rawPostBody, postType, true);
        }

        public static string FormatPostText (string rawPostBody, PostType postType, bool allowCustomTransforms) {
			string formattedPost = rawPostBody;	

			// because of the way we receive the post from MSHTML, somethings can already be encoded. This breaks the regex patterns
			// so we're unencoding anything that is already encoded so regex patterns work correctly. Later we'll encode everything again.
			
			//SCOTTW: Why? Encoded markup should stay encoded...otherwise it will not render
			//formattedPost = HttpUtility.HtmlDecode( formattedPost );

			if (allowCustomTransforms ) {
				// must do emoteicons first because they are restricted from finding any inside [code][/code] blocks. We have to do
				// this before the later steps remove the [code][/code] blocks.
				if( CSContext.Current.SiteSettings.EnableEmoticons ) {
					formattedPost = EmoticonTransforms(formattedPost);
				}
			}

			// convert any html inside code/pre blocks into encoded html
			formattedPost = EncodeCodeBlocks( formattedPost );

			// strip the html posts of any offending html tags and encode any that don't meet the criteria.
			formattedPost = HtmlScrubber.Clean(formattedPost,false,true);//  ScrubHtml( formattedPost, postType );

			// convert all html tags to bbcode as the bbcode processor will only allow safe attributes to be included in the ponst.
			//			formattedPost = HtmlToBBCode( formattedPost );

			// Remove any script code
			//
			//			formattedPost = Transforms.StripScriptTags(formattedPost);

			// Peform specialized transforms first.
			//

			// Do BBCode transform, if any
			//
			formattedPost = BBcodeToHtml(formattedPost); 

			// Perform HTML Encoding of any tag elements, if not PostType.HTML
			//
			if (postType != PostType.HTML && postType != PostType.Poll) {
				formattedPost = HttpUtility.HtmlEncode(formattedPost);
				formattedPost = formattedPost.Replace("\n", Globals.HtmlNewLine);

				// Fix to reverse certain items that were HtmlEncoded above
				//
				formattedPost = UnHtmlEncode(formattedPost);
			} 

			return formattedPost;
		}
		#endregion

		#region CensorPost

		/// <summary>
		/// Validates if the supplied text would pass the censor test
		/// </summary>
		public static bool IsValidCensorText(string text)
		{
			return CensorPost(text) == text;
		}

		public static string CensorPost( string formattedPost ) {
            if(Globals.IsNullorEmpty(formattedPost))
                return formattedPost;


			RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;
			ArrayList censors = CommunityServer.Censors.GetCensors();

			foreach( Censor censor in censors ) {
				string searchPattern; 

				// if the string contains any regex patterns, then just use the pattern
				if( -1 == censor.Word.IndexOfAny( new char[]{'\\', '[', '^', '*', '{', '.', '#', '?', '+', '$', '|' } ) ) {
					searchPattern = String.Format(@"\b{0}\b", censor.Word);
				}
				else {
					searchPattern = censor.Word;
				}

				formattedPost = Regex.Replace(formattedPost, searchPattern, censor.Replacement, options);
			}
			return formattedPost;
		}
		#endregion

		#region UnHtmlEncode
		// *******************************************************************
		// UnHtmlEncode
		//
		/// <summary>
		/// If a post has been HtmlEncoded using the Web.HttpUtility, there are
		/// a few characters we don't want encoded.  This will allow for the 
		/// bbcode transforms to properly work.  So we must "UnHtmlEncode" these
		/// items, back to what they originally were.
		/// </summary>
		/// <param name="formattedPost">string of post</param>
		/// <returns>
		/// An Un-HtmlEncoded String of select items.
		/// </returns>
		// *******************************************************************
		public static string UnHtmlEncode(string formattedPost) {
			RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;

			// &quot;
			// TODO: edit the regex match to only replace within a set of brackets [].
			//
			formattedPost = Regex.Replace(formattedPost, "&quot;", "\"", options);
			
			return formattedPost;
		}
		#endregion

		#region BBDecode
        // *********************************************************************
        //  BBDecode
        //
        /// <summary>
        /// Transforms a BBCode encoded string in appropriate HTML
        /// </summary>
        /// 
        // ********************************************************************/
       public  static string BBcodeToHtml(string encodedString) {
            // TDD TODO this shouldn't be hard coded, should be in a style sheet
			//

			// Used for normal quoting with a "<pic> <username> wrote:" prefix.
			//
			string quoteStartHtml = "";	
			string quoteEndHtml = "</td></tr></table></td></tr></table></BLOCKQUOTE>";
			//quoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"txt4\"><img src=\"" + Globals.GetSkinPath() +"/images/icon-quote.gif" + "\">&nbsp;<strong>$1 wrote:</strong></td></tr><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">$3</td></tr></table></td></tr></table></BLOCKQUOTE>";

			// Used for when a username is not supplied.
			//
			string emptyquoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">";
			string emptyquoteEndHtml = "</td></tr></table></td></tr></table></BLOCKQUOTE>";
			//string emptyquoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">$2</td></tr></table></td></tr></table></BLOCKQUOTE>";

			// When using the Importer, we do not have a skin path.  We hardcode it here to
			// the default path.
			//
			if (Globals.GetSkinPath() == "")
				quoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"txt4\"><img src=\"themes/default/images/icon-quote.gif" + "\">&nbsp;<strong>$1 wrote:</strong></td></tr><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">";
			else
				quoteStartHtml = "<BLOCKQUOTE><table width=\"85%\"><tr><td class=\"txt4\"><img src=\"" + Globals.GetSkinPath() +"/images/icon-quote.gif" + "\">&nbsp;<strong>$1 wrote:</strong></td></tr><tr><td class=\"quoteTable\"><table width=\"100%\"><tr><td width=\"100%\" valign=\"top\" class=\"txt4\">";

			RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;

			// Bold, Italic, Underline
            //
            encodedString = Regex.Replace(encodedString, @"\[b(?:\s*)\]((.|\n)*?)\[/b(?:\s*)\]", "<b>$1</b>", options);
			encodedString = Regex.Replace(encodedString, @"\[i(?:\s*)\]((.|\n)*?)\[/i(?:\s*)\]", "<i>$1</i>", options);
            encodedString = Regex.Replace(encodedString, @"\[u(?:\s*)\]((.|\n)*?)\[/u(?:\s*)\]", "<u>$1</u>", options);

			// Left, Right, Center
			encodedString = Regex.Replace(encodedString, @"\[left(?:\s*)\]((.|\n)*?)\[/left(?:\s*)]", "<div style=\"text-align:left\">$1</div>", options);
			encodedString = Regex.Replace(encodedString, @"\[center(?:\s*)\]((.|\n)*?)\[/center(?:\s*)]", "<div style=\"text-align:center\">$1</div>", options);
			encodedString = Regex.Replace(encodedString, @"\[right(?:\s*)\]((.|\n)*?)\[/right(?:\s*)]", "<div style=\"text-align:right\">$1</div>", options);

            // Quote
            //
            //encodedString = Regex.Replace(encodedString, "\\[quote(?:\\s*)user=\"((.|\n)*?)\"\\]((.|\n)*?)\\[/quote(\\s*)\\]", quote, options);
			//encodedString = Regex.Replace(encodedString, "\\[quote(\\s*)\\]((.|\n)*?)\\[/quote(\\s*)\\]", emptyquote, options);
			encodedString = Regex.Replace(encodedString, "\\[quote(?:\\s*)user=\"((.|\n)*?)\"\\]", quoteStartHtml, options);
			encodedString = Regex.Replace(encodedString, "\\[/quote(\\s*)\\]", quoteEndHtml, options);
			encodedString = Regex.Replace(encodedString, "\\[quote(\\s*)\\]", emptyquoteStartHtml, options);
			encodedString = Regex.Replace(encodedString, "\\[/quote(\\s*)\\]", emptyquoteEndHtml, options);
 

            // Anchors
            //
			encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]www\.(.*?)\[/url(?:\s*)\]", "<a href=\"http://www.$1\" target=\"_blank\" title=\"$1\">$1</a>", options );
			encodedString = Regex.Replace(encodedString, @"\[url(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options );
			encodedString = Regex.Replace(encodedString, @"\[url=""((.|\n)*?)(?:\s*)""\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options );
			encodedString = Regex.Replace(encodedString, @"\[url=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/url(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options );
			encodedString = Regex.Replace(encodedString, @"\[link(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$1</a>", options );
			encodedString = Regex.Replace(encodedString, @"\[link=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/link(?:\s*)\]", "<a href=\"$1\" target=\"_blank\" title=\"$1\">$3</a>", options );

            // Image
            //
            encodedString = Regex.Replace(encodedString, @"\[img(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img src=\"$1\" border=\"0\" />", options);
			encodedString = Regex.Replace(encodedString, @"\[img=((.|\n)*?)x((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/img(?:\s*)\]", "<img width=\"$1\" height=\"$3\" src=\"$5\" border=\"0\" />", options );

            // Color
            //
            encodedString = Regex.Replace(encodedString, @"\[color=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/color(?:\s*)\]", "<span style=\"color=$1;\">$3</span>", options);

            // Horizontal Rule
            //
            encodedString = Regex.Replace(encodedString, @"\[hr(?:\s*)\]", "<hr />", options);
        
            // Email
            //
            encodedString = Regex.Replace(encodedString, @"\[email(?:\s*)\]((.|\n)*?)\[/email(?:\s*)\]", "<a href=\"mailto:$1\">$1</a>", options);

            // Font size
            //
            encodedString = Regex.Replace(encodedString, @"\[size=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/size(?:\s*)\]", "<span style=\"font-size:$1\">$3</span>", options);
			encodedString = Regex.Replace(encodedString, @"\[font=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/font(?:\s*)\]", "<span style=\"font-family:$1;\">$3</span>", options );
			encodedString = Regex.Replace(encodedString, @"\[align=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/align(?:\s*)\]", "<div style=\"text-align:$1;\">$3</span>", options );
			encodedString = Regex.Replace(encodedString, @"\[float=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/float(?:\s*)\]", "<div style=\"float:$1;\">$3</div>", options );

			string sListFormat = "<ol class=\"anf_list\" style=\"list-style:{0};\">$1</ol>";
			// Lists
			encodedString = Regex.Replace(encodedString, @"\[\*(?:\s*)]\s*([^\[]*)", "<li>$1</li>", options );
			encodedString = Regex.Replace(encodedString, @"\[list(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", "<ul class=\"anf_list\">$1</ul>", options );
			encodedString = Regex.Replace(encodedString, @"\[list=1(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format( sListFormat, "decimal" ), options );
			encodedString = Regex.Replace(encodedString, @"\[list=i(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format( sListFormat, "lower-roman" ), RegexOptions.Compiled );
			encodedString = Regex.Replace(encodedString, @"\[list=I(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format( sListFormat, "upper-roman" ), RegexOptions.Compiled );
			encodedString = Regex.Replace(encodedString, @"\[list=a(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format( sListFormat, "lower-alpha" ), RegexOptions.Compiled );
			encodedString = Regex.Replace(encodedString, @"\[list=A(?:\s*)\]((.|\n)*?)\[/list(?:\s*)\]", string.Format( sListFormat, "upper-alpha" ), RegexOptions.Compiled );

            return encodedString;
        }
		#endregion

		#region Strip Tags
        public static string StripForPreview (string content) {
            content = Regex.Replace(content, "<br>", "\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
			content = Regex.Replace(content, "<br/>", "\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
			content = Regex.Replace(content, "<br />", "\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            content = Regex.Replace(content, "<p>", "\n", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            content = content.Replace("'", "&#39;");

            return StripHtmlXmlTags(content);
        }

        public static string StripHtmlXmlTags (string content) {
            return Regex.Replace(content, "<[^>]+>", "", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }

        // *********************************************************************
        //  StripScriptTags
        //
        /// <summary>
        /// Helper function used to ensure we don't inject script into the db.
        /// </summary>
        /// <param name="dirtyText">Text to be cleaned for script tags</param>
        /// <returns>Clean text with no script tags.</returns>
        /// 
        // ********************************************************************/
        public static string StripScriptTags(string content) {
            string cleanText;

            // Perform RegEx
            content = Regex.Replace(content, "<script((.|\n)*?)</script>", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            cleanText = Regex.Replace(content, "\"javascript:", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);

            return cleanText;
        }
		#endregion

		#region Emoticon & User Transforms
        public static string EmoticonTransforms (string formattedPost) {

            // remove some overhead if this is turned off
            if (!CSContext.Current.SiteSettings.EnableEmoticons)
                return formattedPost;

            try {
                // Load the emoticon transform table
                //
				ArrayList emoticonTxTable = Smilies.GetSmilies();
				
				const string imgFormat = "<img src=\"{0}{1}\" alt=\"{2}\" />";

				// EAD 6/27/2004: Changed to loop through twice.
				// Once for brackets first, so to capture the Party emoticon
				// (special emoticons that REQUIRE brackets), so not to replace
				// with other non-bracket icons. Less efficient yes, but captures 
				// all emoticons properly.
				//
				string smileyPattern	= "";
				string replacePattern	= "";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -