using System; using System.Collections.Generic; using System.Net; using System.Text; using System.Web; using System.Data; using System.Web.UI.WebControls; using CMS.CMSHelper; using CMS.GlobalHelper; using CMS.IO; using CMS.SettingsProvider; using CMS.UIControls; using CMS.ExtendedControls.ActionsConfig; using CMS.IO.Compression; using CMS.ExtendedControls; public partial class CMSAdminControls_Validation_HTMLValidator : DocumentValidator { #region "Constants" private const string DEFAULT_VALIDATOR_URL = "http://validator.w3.org/check"; #endregion #region "Variables" private string mValidatorURL = null; private DataSet mDataSource = null; private bool mUseServerRequest = false; private string mAppValidatorPath = null; private string mErrorText = null; #endregion #region "Properties" /// /// URL to which validator requests will be sent /// public string ValidatorURL { get { return mValidatorURL ?? (mValidatorURL = DataHelper.GetNotEmpty(SettingsHelper.AppSettings["CMSValidationHTMLValidatorURL"], DEFAULT_VALIDATOR_URL)); } set { mValidatorURL = value; } } /// /// Indicates if control is used on live site /// public override bool IsLiveSite { get { return base.IsLiveSite; } set { base.IsLiveSite = value; gridValidationResult.IsLiveSite = value; } } /// /// Validator application path use to resolve links referencing on validator pages /// private string AppValidatorPath { get { if (mAppValidatorPath == null) { mAppValidatorPath = URLHelper.RemoveProtocolAndDomain(ValidatorURL); int lastId = mAppValidatorPath.LastIndexOfCSafe('/'); if (lastId >= 0) { mAppValidatorPath = mAppValidatorPath.Substring(0, lastId).TrimEnd('/'); } else { mAppValidatorPath = ""; } } return mAppValidatorPath; } } /// /// Indicates if server request will be used rather than javascript request to obtain HTML /// public bool UseServerRequestType { get { return mUseServerRequest; } set { mUseServerRequest = value; } } /// /// Key to store validation result /// protected override string ResultKey { get { return "validation|html|" + CultureCode + "|" + Url; } } /// /// Gets or sets source of the data for unigrid control /// public override DataSet DataSource { get { if (mDataSource == null) { mDataSource = base.DataSource; } base.DataSource = mDataSource; return mDataSource; } set { base.DataSource = value; mDataSource = value; } } /// /// Messages placeholder /// public override MessagesPlaceHolder MessagesPlaceHolder { get { return plcMess; } } #endregion #region "Control methods" /// /// Page load /// protected void Page_Load(object sender, EventArgs e) { if (!RequestHelper.IsPostBack()) { DataSource = null; } // Configure controls SetupControls(); if (RequestHelper.IsPostBack()) { ReloadData(); } } /// /// Page PreRender /// protected void Page_PreRender(object sender, EventArgs e) { if (!string.IsNullOrEmpty(mErrorText)) { ShowError(mErrorText); } } /// /// Initializes all nested controls. /// private void SetupControls() { IsLiveSite = false; InitializeScripts(); HeaderActions.ActionsList.Clear(); // Validate action HeaderAction validate = new HeaderAction(); validate.ControlType = HeaderActionTypeEnum.Hyperlink; validate.OnClientClick = "LoadHTMLToElement('" + hdnHTML.ClientID + "'," + ScriptHelper.GetString(Url) + ");"; validate.Text = GetString("general.validate"); validate.Tooltip = validate.Text; validate.ImageUrl = GetImageUrl("Design/Controls/Validation/checks.png"); validate.CommandName = "validate"; // View HTML code string click = GetViewSourceActionClick(); HeaderAction viewCode = new HeaderAction(); viewCode.ControlType = HeaderActionTypeEnum.Hyperlink; viewCode.OnClientClick = click; viewCode.Text = GetString("validation.viewcode"); viewCode.Tooltip = viewCode.Text; viewCode.ImageUrl = GetImageUrl("Design/Controls/Validation/codeview.png"); // Show results in new window HeaderAction newWindow = new HeaderAction(); newWindow.ControlType = HeaderActionTypeEnum.Hyperlink; newWindow.OnClientClick = click; newWindow.Text = GetString("validation.showresultsnewwindow"); newWindow.Tooltip = newWindow.Text; if (DataHelper.DataSourceIsEmpty(DataSource)) { newWindow.Enabled = false; newWindow.OnClientClick = null; newWindow.ImageUrl = GetImageUrl("Design/Controls/Validation/windownewdisabled.png"); } else { newWindow.Enabled = true; string encodedKey = ScriptHelper.GetString(HttpUtility.UrlEncode(ResultKey), false); newWindow.OnClientClick = String.Format("modalDialog('" + ResolveUrl("~/CMSModules/Content/CMSDesk/Validation/ValidationResults.aspx") + "?datakey={0}&docid={1}&hash={2}', 'ViewValidationResult', 800, 600);return false;", encodedKey, Node.DocumentID, QueryHelper.GetHash(String.Format("?datakey={0}&docid={1}", encodedKey, Node.DocumentID))); newWindow.ImageUrl = GetImageUrl("Design/Controls/Validation/windownew.png"); } HeaderActions.AddAction(validate); HeaderActions.AddAction(viewCode); HeaderActions.AddAction(newWindow); HeaderActions.HelpName = "helpTopic"; HeaderActions.HelpTopicName = "htmlvalidator"; HeaderActions.ActionPerformed += HeaderActions_ActionPerformed; // Set sorting and add events gridValidationResult.OrderBy = "line ASC"; gridValidationResult.IsLiveSite = IsLiveSite; gridValidationResult.OnExternalDataBound += gridValidationResult_OnExternalDataBound; gridValidationResult.OnDataReload += gridValidationResult_OnDataReload; gridValidationResult.ZeroRowsText = GetString("validation.html.notvalidated"); gridValidationResult.ShowActionsMenu = true; gridValidationResult.AllColumns = "line, column, message, explanation, source"; // Set custom validating text up.ProgressHTML = String.Concat("
", String.Concat("\"",", GetString("validation.validating"), ""), "
"); } /// /// Actions handler. /// protected void HeaderActions_ActionPerformed(object sender, CommandEventArgs e) { switch (e.CommandName) { case "validate": Validate(); break; } } /// /// Actions handler. /// private void Validate() { DataSource = null; DataSource = ValidateHtml(); ReloadData(); } /// /// Loads data from the data source property. /// public void ReloadData() { SetupControls(); gridValidationResult.ReloadData(); ProcessResult(DataSource); } protected DataSet gridValidationResult_OnDataReload(string completeWhere, string currentOrder, int currentTopN, string columns, int currentOffset, int currentPageSize, ref int totalRecords) { return DataSource; } /// /// On external databound event /// /// Sender /// Action what is called /// Parameter /// Result object protected object gridValidationResult_OnExternalDataBound(object sender, string sourceName, object parameter) { return GridExternalDataBound(sender, sourceName, parameter); } #endregion #region "Validation request methods" /// /// Get validation request parameters /// /// Content of HTML document /// Validator request parameters private string GetRequestParameters(string htmlDocument) { string requestData = "fragment=" + HttpUtility.UrlEncode(htmlDocument); requestData += "&output=soap12"; return requestData; } /// /// Send validation request to validator and obtain result /// /// Validator parameters /// DataSet containing validator response private DataSet GetValidationResult(string validatorParameters) { try { DataSet dsValResult = null; // Create web request HttpWebRequest req = (HttpWebRequest)WebRequest.Create(ValidatorURL); req.Method = "POST"; req.UserAgent = HttpContext.Current.Request.UserAgent; req.ContentType = "application/x-www-form-urlencoded"; byte[] data = Encoding.GetEncoding("UTF-8").GetBytes(validatorParameters); req.ContentLength = data.Length; using (StreamWrapper writer = StreamWrapper.New(req.GetRequestStream())) { writer.Write(data, 0, data.Length); } // Process server answer StreamWrapper answer = StreamWrapper.New(req.GetResponse().GetResponseStream()); if (answer != null) { dsValResult = new DataSet(); dsValResult.ReadXml(answer.SystemStream); answer.Close(); } return dsValResult; } catch { mErrorText = GetString("validation.servererror"); return null; } } /// /// General method to process validation and return validation results /// private DataSet ValidateHtml() { if (!String.IsNullOrEmpty(Url)) { string docHtml = GetHtml(Url); if (!String.IsNullOrEmpty(docHtml)) { DataSet dsValidationResult = GetValidationResult(GetRequestParameters(docHtml)); if (!DataHelper.DataSourceIsEmpty(dsValidationResult)) { // Check if result contains error table if (!DataHelper.DataSourceIsEmpty(dsValidationResult.Tables["error"])) { Dictionary parameters = new Dictionary(); parameters["validatorurl"] = ValidatorURL; parameters["validatorapppath"] = AppValidatorPath; DataTable tbError = DocumentValidationHelper.ProcessValidationResult(dsValidationResult, DocumentValidationEnum.HTML, parameters); DataSet result = new DataSet(); result.Tables.Add(tbError); return result; } else { return new DataSet(); } } } else { mErrorText = GetString("validation.diffdomainorprotocol"); } } return null; } /// /// Process validation results /// /// Validation result public void ProcessResult(DataSet validationResult) { if (validationResult != null) { pnlStatus.Visible = true; mErrorText = null; // Check if result is not empty if (!DataHelper.DataSourceIsEmpty(validationResult) && !DataHelper.DataSourceIsEmpty(validationResult.Tables["error"])) { // Show validation errors lblResults.Text = GetString("validation.validationresults"); lblResults.Visible = true; gridValidationResult.Visible = true; lblStatus.Text = GetString("validation.html.resultinvalid"); imgStatus.ImageUrl = GetImageUrl("Design/Controls/Validation/warning.png"); } else { // Show validation is valid lblStatus.Text = GetString("validation.html.resultvalid"); lblResults.Visible = false; gridValidationResult.Visible = false; imgStatus.ImageUrl = GetImageUrl("Design/Controls/Validation/check.png"); } } else { // No results obtained from validator, show error pnlStatus.Visible = false; lblResults.Visible = false; gridValidationResult.Visible = false; if (string.IsNullOrEmpty(mErrorText)) { mErrorText = GetString("validation.errorinitialization"); } } } private string GetHtml(string url) { if (UseServerRequestType) { // Create web client and try to obtaining HTML using it WebClient client = new WebClient(); try { StreamReader reader = StreamReader.New(client.OpenRead(url)); return reader.ReadToEnd(); } catch { return null; } } else { // Get HTML stored using javascript return ValidationHelper.Base64Decode(hdnHTML.Value); } } #endregion }