using System; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Collections; using System.Data; using CMS.CMSHelper; using CMS.Controls; using CMS.DataEngine; using CMS.EventLog; using CMS.ExtendedControls; using CMS.FormEngine; using CMS.GlobalHelper; using CMS.SettingsProvider; using CMS.SiteProvider; using CMS.DocumentEngine; using CMS.WorkflowEngine; using CMS.UIControls; using TimeZoneInfo = CMS.SiteProvider.TimeZoneInfo; using TreeNode = CMS.DocumentEngine.TreeNode; public partial class CMSModules_Content_Controls_ViewVersion : VersionHistoryControl, IPostBackEventHandler { #region "Variables" private TreeNode mCompareNode = null; private FormInfo fi = null; private int versionHistoryId = 0; private int versionCompare = 0; private AttachmentsDataSource dsAttachments = null; private AttachmentsDataSource dsAttachmentsCompare = null; private Hashtable attachments = null; private Hashtable attachmentsCompare = null; private bool noCompare = false; private bool even = true; private bool error = false; private TimeZoneInfo usedTimeZone = null; private TimeZoneInfo serverTimeZone = null; /// /// Column marked as unsorted - default string. /// private const string UNSORTED = "##UNSORTED##"; /// /// Predefined DateTime format. /// private const string DATE_FORMAT = " GMT{0: + 00.00; - 00.00}"; #endregion #region "Properties" /// /// Messages placeholder /// public override MessagesPlaceHolder MessagesPlaceHolder { get { return plcMess; } } /// /// Indicates if control is used on live site. /// public override bool IsLiveSite { get { return base.IsLiveSite; } set { plcMess.IsLiveSite = value; base.IsLiveSite = value; } } /// /// Current edited node. /// public override TreeNode Node { get; set; } /// /// Compare node. /// public TreeNode CompareNode { get { return mCompareNode; } set { mCompareNode = value; } } #endregion #region "Methods" /// /// Shows the specified error message. /// /// Error message text public override void ShowError(string text) { error = true; base.ShowError(text); } protected override void OnInit(EventArgs e) { base.OnInit(e); ControlsHelper.EnsureScriptManager(Page); } protected void Page_Load(object sender, EventArgs e) { // Register WOpener script ScriptHelper.RegisterWOpenerScript(Page); if (QueryHelper.GetBoolean("rollbackok", false)) { ShowConfirmation(GetString("VersionProperties.RollbackOK")); } noCompare = QueryHelper.GetBoolean("noCompare", false); versionHistoryId = QueryHelper.GetInteger("versionhistoryid", 0); versionCompare = QueryHelper.GetInteger("compareHistoryId", 0); // Converting modified time to correct time zone TimeZoneHelper.GetCurrentTimeZoneDateTimeString(DateTime.Now, CurrentUser, CMSContext.CurrentSite, out usedTimeZone); serverTimeZone = TimeZoneHelper.ServerTimeZone; // No comparing available in Recycle bin pnlControl.Visible = !noCompare; if (versionHistoryId > 0) { try { // Get original version of document Node = VersionManager.GetVersion(versionHistoryId, null); CompareNode = VersionManager.GetVersion(versionCompare, null); if (Node != null) { // Check read permissions if (CMSContext.CurrentUser.IsAuthorizedPerDocument(Node, NodePermissionsEnum.Read) != AuthorizationResultEnum.Allowed) { RedirectToAccessDenied(String.Format(GetString("cmsdesk.notauthorizedtoreaddocument"), Node.NodeAliasPath)); } if (!RequestHelper.IsPostBack()) { LoadDropDown(Node.DocumentID, versionHistoryId); ReloadData(); } drpCompareTo.SelectedIndexChanged += drpCompareTo_SelectedIndexChanged; } else { ShowInformation(GetString("editeddocument.notexists")); pnlAdditionalControls.Visible = false; } } catch (Exception ex) { if (Node == null) { RedirectToInformation(GetString("editeddocument.notexists")); } else { ShowError(GetString("document.viewversionerror") + " " + ex.Message); } EventLogProvider.LogException("Content", "VIEWVERSION", ex); } } } /// /// Reloads control with new data. /// private void ReloadData() { tblDocument.Rows.Clear(); DataClassInfo ci = DataClassInfoProvider.GetDataClass(Node.NodeClassName); if (ci != null) { fi = FormHelper.GetFormInfo(ci.ClassName, false); TableHeaderCell labelCell = new TableHeaderCell(); TableHeaderCell valueCell = null; // Add header column with version number if (CompareNode == null) { labelCell.Text = GetString("General.FieldName"); labelCell.EnableViewState = false; valueCell = new TableHeaderCell(); valueCell.EnableViewState = false; valueCell.Text = GetString("General.Value"); // Add table header AddRow(labelCell, valueCell, "UniGridHead", false); } else { labelCell.Text = GetString("lock.versionnumber"); valueCell = GetRollbackTableHeaderCell("source", Node.DocumentID, versionHistoryId); TableHeaderCell valueCompare = GetRollbackTableHeaderCell("compare", CompareNode.DocumentID, versionCompare); // Add table header AddRow(labelCell, valueCell, valueCompare, true, "UniGridHead", false); } if (ci.ClassIsProduct) { // Add coupled class fields ClassStructureInfo skuCsi = ClassStructureInfo.GetClassInfo("ecommerce.sku"); if (skuCsi != null) { foreach (string col in skuCsi.ColumnNames) { AddField(Node, CompareNode, col); } } } if (ci.ClassIsCoupledClass) { // Add coupled class fields ClassStructureInfo coupledCsi = ClassStructureInfo.GetClassInfo(Node.NodeClassName); if (coupledCsi != null) { foreach (string col in coupledCsi.ColumnNames) { // If comparing with other version and current coupled column is not versioned do not display it if (!((CompareNode != null) && !(VersionManager.IsVersionedCoupledColumn(Node.NodeClassName, col)))) { AddField(Node, CompareNode, col); } } } } // Add versioned document class fields ClassStructureInfo docCsi = ClassStructureInfo.GetClassInfo("cms.document"); if (docCsi != null) { foreach (string col in docCsi.ColumnNames) { // If comparing with other version and current document column is not versioned do not display it // One exception is DocumentNamePath column which will be displayed even if it is not marked as a versioned column if (!((CompareNode != null) && (!(VersionManager.IsVersionedDocumentColumn(col) || (col.ToLowerCSafe() == "documentnamepath"))))) { AddField(Node, CompareNode, col); } } } // Add versioned document class fields ClassStructureInfo treeCsi = ClassStructureInfo.GetClassInfo("cms.tree"); if (treeCsi != null) { foreach (string col in treeCsi.ColumnNames) { // Do not display cms_tree columns when comparing with other version // cms_tree columns are not versioned if (CompareNode == null) { AddField(Node, CompareNode, col); } } } // Add unsorted attachments to the table AddField(Node, CompareNode, UNSORTED); } } /// /// Gets new table header cell which contains label and rollback image. /// /// ID suffix /// Document ID /// Version history ID private TableHeaderCell GetRollbackTableHeaderCell(string suffixID, int documentID, int versionID) { TableHeaderCell tblHeaderCell = new TableHeaderCell(); tblHeaderCell.EnableViewState = false; string tooltip = GetString("history.versionrollbacktooltip"); // Label Label lblValue = new Label(); lblValue.ID = "lbl" + suffixID; lblValue.Text = HTMLHelper.HTMLEncode(GetVersionNumber(documentID, versionID)); lblValue.EnableViewState = false; // Panel Panel pnlLabel = new Panel(); pnlLabel.ID = "pnlLabel" + suffixID; pnlLabel.CssClass = "LeftAlign"; pnlLabel.Controls.Add(lblValue); pnlLabel.EnableViewState = false; // Rollback image Image imgRollback = new Image(); imgRollback.ID = "imgRollback" + suffixID; imgRollback.AlternateText = tooltip; imgRollback.ToolTip = tooltip; imgRollback.EnableViewState = false; // Disable buttons according to permissions bool canApprove = WorkflowManager.CheckStepPermissions(Node, WorkflowActionEnum.Approve); if (!canApprove || !CanModify || (CheckedOutByAnotherUser && !CanCheckIn)) { imgRollback.ImageUrl = GetImageUrl("Design/Controls/UniGrid/Actions/undodisabled.png"); imgRollback.Enabled = false; } else { imgRollback.ImageUrl = GetImageUrl("Design/Controls/UniGrid/Actions/undo.png"); imgRollback.Style.Add("cursor", "pointer"); // Prepare onclick script string confirmScript = "if (confirm(" + ScriptHelper.GetString(GetString("Unigrid.VersionHistory.Actions.Rollback.Confirmation")) + ")) { "; confirmScript += Page.ClientScript.GetPostBackEventReference(this, versionID.ToString()) + "; return false; }"; imgRollback.Attributes.Add("onclick", confirmScript); } // Rollback panel Panel pnlImage = new Panel(); pnlImage.EnableViewState = false; pnlImage.ID = "pnlRollback" + suffixID; pnlImage.CssClass = "RightAlign"; pnlImage.Controls.Add(imgRollback); tblHeaderCell.Controls.Add(pnlLabel); tblHeaderCell.Controls.Add(pnlImage); return tblHeaderCell; } /// /// Loads dropdown list with versions. /// /// ID of current document /// ID of current version history private void LoadDropDown(int documentId, int versionHistoryId) { DataSet ds = VersionManager.GetDocumentHistory(documentId, "VersionHistoryID !=" + versionHistoryId, "ModifiedWhen DESC, VersionNumber DESC", -1, "VersionHistoryID, VersionNumber, ModifiedWhen"); // Converting modified time to correct time zone if (!DataHelper.DataSourceIsEmpty(ds)) { foreach (DataRow dr in ds.Tables[0].Rows) { string version = ValidationHelper.GetString(dr["VersionNumber"], null); version += " (" + GetUserDate(dr["ModifiedWhen"]) + ")"; drpCompareTo.Items.Add(new ListItem(version, ValidationHelper.GetString(dr["VersionHistoryID"], "0"))); } } // If history to be compared is available if (drpCompareTo.Items.Count > 0) { drpCompareTo.Items.Insert(0, GetString("history.select")); } // Otherwise hide dropdown list else { pnlControl.Visible = false; } // Pre-select dropdown list if (drpCompareTo.Items.FindByValue(versionCompare.ToString()) != null) { drpCompareTo.SelectedValue = versionCompare.ToString(); } } /// /// Returns string with converted DateTime parameters according to specific user timezone settings. /// private string GetUserDate(object dateTimeVal) { DateTime date = ValidationHelper.GetDateTime(dateTimeVal, DataHelper.DATETIME_NOT_SELECTED); return TimeZoneHelper.ConvertTimeZoneDateTime(date, serverTimeZone, usedTimeZone) + TimeZoneHelper.GetGMTStringOffset(DATE_FORMAT, usedTimeZone); } /// /// Returns version number with date for given document. /// private string GetVersionNumber(int documentId, int version) { DataSet ds = VersionManager.GetDocumentHistory(documentId, "VersionHistoryID =" + version, null, 1, "VersionNumber, ModifiedWhen"); if (DataHelper.DataSourceIsEmpty(ds)) { return null; } else { string versionNumber = ValidationHelper.GetString(ds.Tables[0].Rows[0]["VersionNumber"], null); versionNumber += " (" + GetUserDate(ds.Tables[0].Rows[0]["ModifiedWhen"]) + ")"; return versionNumber; } } /// /// Adds the field to the form. /// /// Document node /// Document compare node /// Column name private void AddField(TreeNode node, TreeNode compareNode, string columnName) { FormFieldInfo ffi = null; if (fi != null) { ffi = fi.GetFormField(columnName); } TableCell valueCell = new TableCell(); valueCell.EnableViewState = false; TableCell valueCompare = new TableCell(); valueCompare.EnableViewState = false; TableCell labelCell = new TableCell(); labelCell.EnableViewState = false; TextComparison comparefirst = null; TextComparison comparesecond = null; bool switchSides = true; bool loadValue = true; bool empty = true; bool allowLabel = true; // Get the caption if ((columnName == UNSORTED) || (ffi != null)) { AttachmentInfo aiCompare = null; // Compare attachments if ((columnName == UNSORTED) || (ffi.DataType == FormFieldDataTypeEnum.DocumentAttachments)) { allowLabel = false; string title = null; if (columnName == UNSORTED) { title = GetString("attach.unsorted") + ":"; } else { title = (String.IsNullOrEmpty(ffi.Caption) ? ffi.Name : ffi.Caption) + ":"; } // Prepare DataSource for original node loadValue = false; dsAttachments = new AttachmentsDataSource(); dsAttachments.DocumentVersionHistoryID = versionHistoryId; if (columnName != UNSORTED) { dsAttachments.AttachmentGroupGUID = ffi.Guid; } dsAttachments.Path = node.NodeAliasPath; dsAttachments.CultureCode = CMSContext.PreferredCultureCode; SiteInfo si = SiteInfoProvider.GetSiteInfo(node.NodeSiteID); dsAttachments.SiteName = si.SiteName; dsAttachments.OrderBy = "AttachmentOrder, AttachmentName, AttachmentHistoryID"; dsAttachments.SelectedColumns = "AttachmentHistoryID, AttachmentGUID, AttachmentImageWidth, AttachmentImageHeight, AttachmentExtension, AttachmentName, AttachmentSize, AttachmentOrder, AttachmentTitle, AttachmentDescription"; dsAttachments.IsLiveSite = false; dsAttachments.DataSource = null; dsAttachments.DataBind(); // Get the attachments table attachments = GetAttachmentsTable((DataSet)dsAttachments.DataSource, versionHistoryId, node.DocumentID); // Prepare datasource for compared node if (compareNode != null) { dsAttachmentsCompare = new AttachmentsDataSource(); dsAttachmentsCompare.DocumentVersionHistoryID = versionCompare; if (columnName != UNSORTED) { dsAttachmentsCompare.AttachmentGroupGUID = ffi.Guid; } dsAttachmentsCompare.Path = compareNode.NodeAliasPath; dsAttachmentsCompare.CultureCode = CMSContext.PreferredCultureCode; dsAttachmentsCompare.SiteName = si.SiteName; dsAttachmentsCompare.OrderBy = "AttachmentOrder, AttachmentName, AttachmentHistoryID"; dsAttachmentsCompare.SelectedColumns = "AttachmentHistoryID, AttachmentGUID, AttachmentImageWidth, AttachmentImageHeight, AttachmentExtension, AttachmentName, AttachmentSize, AttachmentOrder, AttachmentTitle, AttachmentDescription"; dsAttachmentsCompare.IsLiveSite = false; dsAttachmentsCompare.DataSource = null; dsAttachmentsCompare.DataBind(); // Get the table to compare attachmentsCompare = GetAttachmentsTable((DataSet)dsAttachmentsCompare.DataSource, versionCompare, node.DocumentID); // Switch the sides if older version is on the right if (versionHistoryId > versionCompare) { Hashtable dummy = attachmentsCompare; attachmentsCompare = attachments; attachments = dummy; } // Add comparison AddTableComparison(attachments, attachmentsCompare, "" + title + "", true, true); } else { // Normal display if (attachments.Count != 0) { bool first = true; foreach (DictionaryEntry item in attachments) { string itemValue = ValidationHelper.GetString(item.Value, null); if (!String.IsNullOrEmpty(itemValue)) { valueCell = new TableCell(); labelCell = new TableCell(); if (first) { labelCell.Text = "" + String.Format(title, item.Key) + ""; first = false; } valueCell.Text = itemValue; AddRow(labelCell, valueCell, null, even); even = !even; } } } } } // Compare single file attachment else if (ffi.DataType == FormFieldDataTypeEnum.File) { // Get the attachment AttachmentInfo ai = DocumentHelper.GetAttachment(ValidationHelper.GetGuid(node.GetValue(columnName), Guid.Empty), versionHistoryId, TreeProvider, false); if (compareNode != null) { aiCompare = DocumentHelper.GetAttachment(ValidationHelper.GetGuid(compareNode.GetValue(columnName), Guid.Empty), versionCompare, TreeProvider, false); } loadValue = false; empty = true; // Prepare text comparison controls if ((ai != null) || (aiCompare != null)) { string textorig = null; if (ai != null) { textorig = CreateAttachment(ai.Generalized.DataClass, versionHistoryId); } string textcompare = null; if (aiCompare != null) { textcompare = CreateAttachment(aiCompare.Generalized.DataClass, versionCompare); } comparefirst = new TextComparison(); comparefirst.SynchronizedScrolling = false; comparefirst.IgnoreHTMLTags = true; comparefirst.ConsiderHTMLTagsEqual = true; comparefirst.BalanceContent = false; comparesecond = new TextComparison(); comparesecond.SynchronizedScrolling = false; comparesecond.IgnoreHTMLTags = true; // Source text must be older version if (versionHistoryId < versionCompare) { comparefirst.SourceText = textorig; comparefirst.DestinationText = textcompare; } else { comparefirst.SourceText = textcompare; comparefirst.DestinationText = textorig; } comparefirst.PairedControl = comparesecond; comparesecond.RenderingMode = TextComparisonTypeEnum.DestinationText; valueCell.Controls.Add(comparefirst); valueCompare.Controls.Add(comparesecond); switchSides = false; // Add both cells if (compareNode != null) { AddRow(labelCell, valueCell, valueCompare, switchSides, null, even); } // Add one cell only else { valueCell.Controls.Clear(); Literal ltl = new Literal(); ltl.Text = textorig; valueCell.Controls.Add(ltl); AddRow(labelCell, valueCell, null, even); } even = !even; } } } if (allowLabel && (labelCell.Text == "")) { labelCell.Text = "" + columnName + ":"; } if (loadValue) { string textcompare = null; switch (columnName.ToLowerCSafe()) { // Document content - display content of editable regions and editable web parts case "documentcontent": EditableItems ei = new EditableItems(); ei.LoadContentXml(ValidationHelper.GetString(node.GetValue(columnName), "")); // Add text comparison control if (compareNode != null) { EditableItems eiCompare = new EditableItems(); eiCompare.LoadContentXml(ValidationHelper.GetString(compareNode.GetValue(columnName), "")); // Create editable regions comparison Hashtable hashtable; Hashtable hashtableCompare; // Source text must be older version if (versionHistoryId < versionCompare) { hashtable = ei.EditableRegions; hashtableCompare = eiCompare.EditableRegions; } else { hashtable = eiCompare.EditableRegions; hashtableCompare = ei.EditableRegions; } // Add comparison AddTableComparison(hashtable, hashtableCompare, "" + columnName + " ({0}):", false, false); // Create editable webparts comparison // Source text must be older version if (versionHistoryId < versionCompare) { hashtable = ei.EditableWebParts; hashtableCompare = eiCompare.EditableWebParts; } else { hashtable = eiCompare.EditableWebParts; hashtableCompare = ei.EditableWebParts; } // Add comparison AddTableComparison(hashtable, hashtableCompare, "" + columnName + " ({0}):", false, false); } // No compare node else { // Editable regions Hashtable hashtable = ei.EditableRegions; if (hashtable.Count != 0) { foreach (DictionaryEntry region in hashtable) { string regionValue = ValidationHelper.GetString(region.Value, null); if (!String.IsNullOrEmpty(regionValue)) { string regionKey = ValidationHelper.GetString(region.Key, null); valueCell = new TableCell(); labelCell = new TableCell(); labelCell.Text = "" + columnName + " (" + DictionaryHelper.GetFirstKey(regionKey) + "):"; valueCell.Text = HttpUtility.HtmlDecode(HTMLHelper.StripTags(regionValue, false)); AddRow(labelCell, valueCell, null, even); even = !even; } } } // Editable web parts hashtable = ei.EditableWebParts; if (hashtable.Count != 0) { foreach (DictionaryEntry part in hashtable) { string partValue = ValidationHelper.GetString(part.Value, null); if (!String.IsNullOrEmpty(partValue)) { string partKey = ValidationHelper.GetString(part.Key, null); valueCell = new TableCell(); labelCell = new TableCell(); labelCell.Text = "" + columnName + " (" + DictionaryHelper.GetFirstKey(partKey) + "):"; valueCell.Text = HttpUtility.HtmlDecode(HTMLHelper.StripTags(partValue, false)); AddRow(labelCell, valueCell, null, even); even = !even; } } } } break; // Others, display the string value default: // Shift date time values to user time zone object origobject = node.GetValue(columnName); string textorig = null; if (origobject is DateTime) { TimeZoneInfo usedTimeZone = null; textorig = TimeZoneHelper.GetCurrentTimeZoneDateTimeString(ValidationHelper.GetDateTime(origobject, DateTimeHelper.ZERO_TIME), CurrentUser, CMSContext.CurrentSite, out usedTimeZone); } else { textorig = ValidationHelper.GetString(origobject, ""); } // Add text comparison control if (compareNode != null) { // Shift date time values to user time zone object compareobject = compareNode.GetValue(columnName); if (compareobject is DateTime) { TimeZoneInfo usedTimeZone = null; textcompare = TimeZoneHelper.GetCurrentTimeZoneDateTimeString(ValidationHelper.GetDateTime(compareobject, DateTimeHelper.ZERO_TIME), CurrentUser, CMSContext.CurrentSite, out usedTimeZone); } else { textcompare = ValidationHelper.GetString(compareobject, ""); } comparefirst = new TextComparison(); comparefirst.SynchronizedScrolling = false; comparesecond = new TextComparison(); comparesecond.SynchronizedScrolling = false; comparesecond.RenderingMode = TextComparisonTypeEnum.DestinationText; // Source text must be older version if (versionHistoryId < versionCompare) { comparefirst.SourceText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(textorig, false)); comparefirst.DestinationText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(textcompare, false)); } else { comparefirst.SourceText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(textcompare, false)); comparefirst.DestinationText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(textorig, false)); } comparefirst.PairedControl = comparesecond; if (Math.Max(comparefirst.SourceText.Length, comparefirst.DestinationText.Length) < 100) { comparefirst.BalanceContent = false; } valueCell.Controls.Add(comparefirst); valueCompare.Controls.Add(comparesecond); switchSides = false; } else { valueCell.Text = HttpUtility.HtmlDecode(HTMLHelper.StripTags(textorig, false)); } empty = (String.IsNullOrEmpty(textorig)) && (String.IsNullOrEmpty(textcompare)); break; } } if (!empty) { if (compareNode != null) { AddRow(labelCell, valueCell, valueCompare, switchSides, null, even); even = !even; } else { AddRow(labelCell, valueCell, null, even); even = !even; } } } /// /// Gets the hashtable of attachments from the DataSet. /// /// Source DataSet /// Version history ID /// Document ID protected Hashtable GetAttachmentsTable(DataSet ds, int versionId, int documentId) { Hashtable result = new Hashtable(); if (!DataHelper.DataSourceIsEmpty(ds)) { foreach (DataRow dr in ds.Tables[0].Rows) { // Get attachment GUID Guid attachmentGuid = ValidationHelper.GetGuid(dr["AttachmentGUID"], Guid.Empty); result[attachmentGuid.ToString()] = CreateAttachment(new DataRowContainer(dr), versionId); } } return result; } /// /// Adds the table comparison for matching objects. /// /// Left side table /// Right side table /// Title format string /// If true, the HTML code is kept (attachment comparison) /// If true, only first title is rendered protected void AddTableComparison(Hashtable hashtable, Hashtable hashtableCompare, string titleFormat, bool attachments, bool renderOnlyFirstTitle) { TableCell valueCell = new TableCell(); TableCell valueCompare = new TableCell(); TableCell labelCell = new TableCell(); TextComparison comparefirst = null; TextComparison comparesecond = null; bool firstTitle = true; // Go through left column regions if (hashtable != null) { foreach (DictionaryEntry entry in hashtable) { object value = entry.Value; if (value != null) { // Initialize comparators comparefirst = new TextComparison(); comparefirst.SynchronizedScrolling = false; comparesecond = new TextComparison(); comparesecond.SynchronizedScrolling = false; comparesecond.RenderingMode = TextComparisonTypeEnum.DestinationText; if (attachments) { comparefirst.IgnoreHTMLTags = true; comparefirst.ConsiderHTMLTagsEqual = true; comparesecond.IgnoreHTMLTags = true; } comparefirst.PairedControl = comparesecond; // Initialize cells valueCell = new TableCell(); valueCompare = new TableCell(); labelCell = new TableCell(); string key = ValidationHelper.GetString(entry.Key, null); string strValue = ValidationHelper.GetString(value, null); if (firstTitle || !renderOnlyFirstTitle) { labelCell.Text = String.Format(titleFormat, DictionaryHelper.GetFirstKey(key)); firstTitle = false; } if (attachments) { comparefirst.SourceText = strValue; } else { comparefirst.SourceText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(strValue, false)); } if ((hashtableCompare != null) && hashtableCompare.Contains(key)) { // Compare to the existing other version string compareKey = ValidationHelper.GetString(hashtableCompare[key], null); if (attachments) { comparefirst.DestinationText = compareKey; } else { comparefirst.DestinationText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(compareKey, false)); } hashtableCompare.Remove(key); } else { // Compare to an empty string comparefirst.DestinationText = ""; } // Do not balance content if too short if (attachments) { comparefirst.BalanceContent = false; } else if (Math.Max(comparefirst.SourceText.Length, comparefirst.DestinationText.Length) < 100) { comparefirst.BalanceContent = false; } // Create cell comparison valueCell.Controls.Add(comparefirst); valueCompare.Controls.Add(comparesecond); AddRow(labelCell, valueCell, valueCompare, false, null, even); even = !even; } } } // Go through right column regions which left if (hashtableCompare != null) { foreach (DictionaryEntry entry in hashtableCompare) { object value = entry.Value; if (value != null) { // Initialize comparators comparefirst = new TextComparison(); comparefirst.SynchronizedScrolling = false; comparesecond = new TextComparison(); comparesecond.SynchronizedScrolling = false; comparesecond.RenderingMode = TextComparisonTypeEnum.DestinationText; comparefirst.PairedControl = comparesecond; if (attachments) { comparefirst.IgnoreHTMLTags = true; comparefirst.ConsiderHTMLTagsEqual = true; comparesecond.IgnoreHTMLTags = true; } // Initialize cells valueCell = new TableCell(); valueCompare = new TableCell(); labelCell = new TableCell(); if (firstTitle || !renderOnlyFirstTitle) { labelCell.Text = String.Format(titleFormat, DictionaryHelper.GetFirstKey(ValidationHelper.GetString(entry.Key, null))); firstTitle = false; } comparefirst.SourceText = ""; string strValue = ValidationHelper.GetString(value, null); if (attachments) { comparefirst.DestinationText = strValue; } else { comparefirst.DestinationText = HttpUtility.HtmlDecode(HTMLHelper.StripTags(strValue, false)); } if (attachments) { comparefirst.BalanceContent = false; } else if (Math.Max(comparefirst.SourceText.Length, comparefirst.DestinationText.Length) < 100) { comparefirst.BalanceContent = false; } // Create cell comparison valueCell.Controls.Add(comparefirst); valueCompare.Controls.Add(comparesecond); AddRow(labelCell, valueCell, valueCompare, false, null, even); even = !even; } } } } /// /// Returns new TableRow with CSS class set according to even/odd position in table. /// private TableRow CreateRow(string cssClass, bool even, TableCell labelCell) { TableRow newRow = new TableRow(); // Set CSS if (!String.IsNullOrEmpty(cssClass)) { newRow.CssClass = cssClass; } else if (even) { newRow.CssClass = "EvenRow"; } else { newRow.CssClass = "OddRow"; } labelCell.Wrap = false; newRow.Cells.Add(labelCell); return newRow; } /// /// Creates 2 column table. /// /// Cell with label /// Cell with content /// Returns TableRow object private TableRow AddRow(TableCell labelCell, TableCell valueCell, string cssClass, bool even) { TableRow newRow = CreateRow(cssClass, even, labelCell); valueCell.Width = new Unit(100, UnitType.Percentage); newRow.Cells.Add(valueCell); tblDocument.Rows.Add(newRow); return newRow; } /// /// Creates 3 column table. Older version must be always in the left column. /// /// Cell with label /// Cell with content /// Cell with compare content /// Indicates if cells should be switched to match corresponding version /// CSS class /// Determines whether row is odd or even /// Returns TableRow object private TableRow AddRow(TableCell labelCell, TableCell valueCell, TableCell compareCell, bool switchSides, string cssClass, bool even) { TableRow newRow = CreateRow(cssClass, even, labelCell); const int cellWidth = 40; // Switch sides to match version if (switchSides) { // Older version must be in the left column if (versionHistoryId < versionCompare) { valueCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(valueCell); compareCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(compareCell); } else { compareCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(compareCell); valueCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(valueCell); } } // Do not switch sides else { valueCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(valueCell); compareCell.Width = new Unit(cellWidth, UnitType.Percentage); newRow.Cells.Add(compareCell); } tblDocument.Rows.Add(newRow); return newRow; } /// /// Creates attachment string. /// private string CreateAttachment(IDataContainer dc, int versionId) { string result = null; if (dc != null) { // Get attachment GUID Guid attachmentGuid = ValidationHelper.GetGuid(dc.GetValue("AttachmentGUID"), Guid.Empty); // Get attachment extension string attachmentExt = ValidationHelper.GetString(dc.GetValue("AttachmentExtension"), null); string iconUrl = GetFileIconUrl(attachmentExt, "List"); // Get link for attachment string attachmentUrl = null; string attName = ValidationHelper.GetString(dc.GetValue("AttachmentName"), null); attachmentUrl = CMSContext.ResolveUIUrl(TreePathUtils.GetAttachmentUrl(attachmentGuid, URLHelper.GetSafeFileName(attName, CMSContext.CurrentSiteName), versionId, null)); // Ensure correct URL attachmentUrl = URLHelper.AddParameterToUrl(attachmentUrl, "sitename", CMSContext.CurrentSiteName); // Optionally trim attachment name string attachmentName = TextHelper.LimitLength(attName, 90); bool isImage = ImageHelper.IsImage(attachmentExt); // Tooltip string tooltip = null; if (isImage) { int attachmentWidth = ValidationHelper.GetInteger(dc.GetValue("AttachmentImageWidth"), 0); if (attachmentWidth > 300) { attachmentWidth = 300; } tooltip = "onmouseout=\"UnTip()\" onmouseover=\"TipImage(" + attachmentWidth + ", '" + URLHelper.AddParameterToUrl(attachmentUrl, "width", "300") + "', " + ScriptHelper.GetString(HTMLHelper.HTMLEncode(attachmentName)) + ")\""; } string attachmentSize = DataHelper.GetSizeString(ValidationHelper.GetLong(dc.GetValue("AttachmentSize"), 0)); string title = ValidationHelper.GetString(dc.GetValue("AttachmentTitle"), string.Empty); string description = ValidationHelper.GetString(dc.GetValue("AttachmentDescription"), string.Empty); // Icon StringBuilder sb = new StringBuilder(); sb.Append("\"","); sb.Append(" ", HTMLHelper.HTMLEncode(attachmentName), " (", HTMLHelper.HTMLEncode(attachmentSize), ")
"); sb.Append(""); sb.Append("
", GetString("general.title"), ":", HTMLHelper.HTMLEncode(title), "
", GetString("general.description"), ":", HTMLHelper.HTMLEncode(description), "

"); result = sb.ToString(); } return result; } #endregion #region "Events" /// /// Dropdown list selection changed. /// private void drpCompareTo_SelectedIndexChanged(object sender, EventArgs e) { string url = URLHelper.CurrentURL; url = URLHelper.RemoveParameterFromUrl(url, "rollbackok"); if (drpCompareTo.SelectedIndex == 0) { url = URLHelper.RemoveParameterFromUrl(url, "compareHistoryId"); } else { url = URLHelper.AddParameterToUrl(url, "compareHistoryId", drpCompareTo.SelectedValue); } URLHelper.Redirect(url); } #endregion #region "IPostBackEventHandler Members" /// /// Raises event postback event. /// /// Argument public void RaisePostBackEvent(string eventArgument) { int rollbackVersionId = ValidationHelper.GetInteger(eventArgument, 0); if (rollbackVersionId > 0) { if (Node == null) { return; } if (CheckedOutByUserID > 0) { // Document is checked out ShowError(GetString("VersionProperties.CannotRollbackCheckedOut")); } else { // Check permissions bool canApprove = WorkflowManager.CheckStepPermissions(Node, WorkflowActionEnum.Approve); if (!canApprove || !CanModify) { ShowError(String.Format(GetString("cmsdesk.notauthorizedtoeditdocument"), Node.NodeAliasPath)); } else { try { // Rollback version int newVersionHistoryId = VersionManager.RollbackVersion(rollbackVersionId); ShowConfirmation(GetString("VersionProperties.RollbackOK")); string url = URLHelper.CurrentURL; // Add URL parameters url = URLHelper.AddParameterToUrl(url, "versionHistoryId", newVersionHistoryId.ToString()); url = URLHelper.AddParameterToUrl(url, "compareHistoryId", versionCompare.ToString()); url = URLHelper.AddParameterToUrl(url, "rollbackok", "1"); // Prepare URL url = ScriptHelper.GetString(URLHelper.ResolveUrl(url), true); // Prepare script for refresh parent window and this dialog StringBuilder builder = new StringBuilder(); builder.Append("if (wopener != null) {\n"); builder.Append("if (wopener.RefreshTree != null) {wopener.RefreshTree(", Node.NodeParentID, ", ", Node.NodeID, "); }"); builder.Append("wopener.document.location.replace(wopener.document.location);}\n"); builder.Append("window.document.location.replace(" + url + ");"); string script = ScriptHelper.GetScript(builder.ToString()); ScriptHelper.RegisterStartupScript(this, typeof(string), "RefreshAndReload", script); } catch (Exception ex) { ShowError(GetString("versionproperties.rollbackerror")); EventLogProvider.LogException("Content", "ROLLBACKVERSION", ex); } } } // Display form if error occurs if (error) { ReloadData(); } } } #endregion }