using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ScrewTurn.Wiki.PluginFramework;
using System.Text;
namespace ScrewTurn.Wiki {
public partial class DefaultPage : BasePage {
private PageInfo currentPage = null;
private PageContent currentContent = null;
private bool discussMode = false;
private bool viewCodeMode = false;
protected void Page_Load(object sender, EventArgs e) {
discussMode = Request["Discuss"] != null;
viewCodeMode = Request["Code"] != null && !discussMode;
if(!Settings.EnableViewPageCodeFeature) viewCodeMode = false;
currentPage = DetectPageInfo(true);
VerifyAndPerformRedirects();
// The following actions are verified:
// - View content (redirect to AccessDenied)
// - Edit or Edit with Approval (for button display)
// - Any Administrative activity (Rollback/Admin/Perms) (for button display)
// - Download attachments (for button display - download permissions are also checked in GetFile)
// - View discussion (for button display in content mode)
// - Post discussion (for button display in discuss mode)
string currentUsername = SessionFacade.GetCurrentUsername();
string[] currentGroups = SessionFacade.GetCurrentGroupNames();
bool canView = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.ReadPage, currentUsername, currentGroups);
bool canEdit = false;
bool canEditWithApproval = false;
Pages.CanEditPage(currentPage, currentUsername, currentGroups, out canEdit, out canEditWithApproval);
if(canEditWithApproval && canEdit) canEditWithApproval = false;
bool canDownloadAttachments = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.DownloadAttachments, currentUsername, currentGroups);
bool canSetPerms = AuthChecker.CheckActionForGlobals(Actions.ForGlobals.ManagePermissions, currentUsername, currentGroups);
bool canAdmin = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.ManagePage, currentUsername, currentGroups);
bool canViewDiscussion = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.ReadDiscussion, currentUsername, currentGroups);
bool canPostDiscussion = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.PostDiscussion, currentUsername, currentGroups);
bool canManageDiscussion = AuthChecker.CheckActionForPage(currentPage, Actions.ForPages.ManageDiscussion, currentUsername, currentGroups);
if(!canView) {
if(SessionFacade.LoginKey == null) UrlTools.Redirect("Login.aspx?Redirect=" + Tools.UrlEncode(Request.Url.ToString()));
else UrlTools.Redirect(UrlTools.BuildUrl("AccessDenied.aspx"));
}
attachmentViewer.Visible = canDownloadAttachments;
attachmentViewer.PageInfo = currentPage;
currentContent = Content.GetPageContent(currentPage, true);
pnlPageInfo.Visible = Settings.EnablePageInfoDiv;
SetupTitles();
SetupToolbarLinks(canEdit || canEditWithApproval, canViewDiscussion, canPostDiscussion, canDownloadAttachments, canAdmin, canAdmin, canSetPerms);
SetupLabels();
SetupPrintAndRssLinks();
SetupMetaInformation();
VerifyAndPerformPageRedirection();
SetupRedirectionSource();
SetupNavigationPaths();
SetupAdjacentPages();
SessionFacade.Breadcrumbs.AddPage(currentPage);
SetupBreadcrumbsTrail();
SetupDoubleClickHandler();
SetupEmailNotification();
SetupPageContent(canPostDiscussion, canManageDiscussion);
}
///
/// Verifies the need for a redirect and performs it.
///
private void VerifyAndPerformRedirects() {
if(currentPage == null) {
UrlTools.Redirect(UrlTools.BuildUrl("PageNotFound.aspx?Page=", Tools.UrlEncode(DetectFullName())));
}
if(Request["Edit"] == "1") {
UrlTools.Redirect(UrlTools.BuildUrl("Edit.aspx?Page=", Tools.UrlEncode(currentPage.FullName)));
}
if(Request["History"] == "1") {
UrlTools.Redirect(UrlTools.BuildUrl("History.aspx?Page=", Tools.UrlEncode(currentPage.FullName)));
}
}
///
/// Sets the titles used in the page.
///
private void SetupTitles() {
string title = FormattingPipeline.PrepareTitle(currentContent.Title, false, FormattingContext.PageContent, currentPage);
Page.Title = title + " - " + Settings.WikiTitle;
lblPageTitle.Text = title;
}
///
/// Sets the content and visibility of all toolbar links.
///
/// A value indicating whether the current user can edit the page.
/// A value indicating whether the current user can view the page discussion.
/// A value indicating whether the current user can post messages in the page discussion.
/// A value indicating whether the current user can download attachments.
/// A value indicating whether the current user can rollback the page.
/// A value indicating whether the current user can perform at least one administration task.
/// A value indicating whether the current user can set page permissions.
private void SetupToolbarLinks(bool canEdit, bool canViewDiscussion, bool canPostMessages,
bool canDownloadAttachments, bool canRollback, bool canAdmin, bool canSetPerms) {
lblDiscussLink.Visible = !discussMode && !viewCodeMode && canViewDiscussion;
if(lblDiscussLink.Visible) {
lblDiscussLink.Text = string.Format(@"{1} ({2})",
Properties.Messages.Discuss, Properties.Messages.Discuss, Pages.GetMessageCount(currentPage));
}
lblEditLink.Visible = Settings.EnablePageToolbar && !discussMode && !viewCodeMode && canEdit;
if(lblEditLink.Visible) {
lblEditLink.Text = string.Format(@"{2}",
Properties.Messages.EditThisPage,
UrlTools.BuildUrl("Edit.aspx?Page=", Tools.UrlEncode(currentPage.FullName)),
Properties.Messages.Edit);
}
if(Settings.EnablePageToolbar && Settings.EnableViewPageCodeFeature) {
lblViewCodeLink.Visible = !discussMode && !viewCodeMode && !canEdit;
if(lblViewCodeLink.Visible) {
lblViewCodeLink.Text = string.Format(@"{1}",
Properties.Messages.ViewPageCode, Properties.Messages.ViewPageCode);
}
}
else lblViewCodeLink.Visible = false;
lblHistoryLink.Visible = Settings.EnablePageToolbar && !discussMode && !viewCodeMode && canViewDiscussion;
if(lblHistoryLink.Visible) {
lblHistoryLink.Text = string.Format(@"{2}",
Properties.Messages.ViewPageHistory,
UrlTools.BuildUrl("History.aspx?Page=", Tools.UrlEncode(currentPage.FullName)),
Properties.Messages.History);
}
int attachmentCount = GetAttachmentCount();
lblAttachmentsLink.Visible = canDownloadAttachments && !discussMode && !viewCodeMode && attachmentCount > 0;
if(lblAttachmentsLink.Visible) {
lblAttachmentsLink.Text = string.Format(@"{1}",
Properties.Messages.Attachments, Properties.Messages.Attachments);
}
attachmentViewer.Visible = lblAttachmentsLink.Visible;
int bakCount = GetBackupCount();
lblAdminToolsLink.Visible = Settings.EnablePageToolbar && !discussMode && !viewCodeMode &&
((canRollback && bakCount > 0)|| canAdmin || canSetPerms);
if(lblAdminToolsLink.Visible) {
lblAdminToolsLink.Text = string.Format(@"{1}",
Properties.Messages.AdminTools, Properties.Messages.Admin);
if(canRollback && bakCount > 0) {
lblRollbackPage.Text = string.Format(@"{2}",
Tools.UrlEncode(currentPage.FullName),
Properties.Messages.RollbackThisPage, Properties.Messages.Rollback);
}
else lblRollbackPage.Visible = false;
if(canAdmin) {
lblAdministratePage.Text = string.Format(@"{2}",
Tools.UrlEncode(currentPage.FullName),
Properties.Messages.AdministrateThisPage, Properties.Messages.Administrate);
}
else lblAdministratePage.Visible = false;
if(canSetPerms) {
lblSetPagePermissions.Text = string.Format(@"{2}",
Tools.UrlEncode(currentPage.FullName),
Properties.Messages.SetPermissionsForThisPage, Properties.Messages.Permissions);
}
else lblSetPagePermissions.Visible = false;
}
lblPostMessageLink.Visible = discussMode && !viewCodeMode && canPostMessages;
if(lblPostMessageLink.Visible) {
lblPostMessageLink.Text = string.Format(@"{2}",
Properties.Messages.PostMessage,
UrlTools.BuildUrl("Post.aspx?Page=", Tools.UrlEncode(currentPage.FullName)),
Properties.Messages.PostMessage);
}
lblBackLink.Visible = discussMode || viewCodeMode;
if(lblBackLink.Visible) {
lblBackLink.Text = string.Format(@"{2}",
Properties.Messages.Back,
UrlTools.BuildUrl(Tools.UrlEncode(currentPage.FullName), Settings.PageExtension, "?NoRedirect=1"),
Properties.Messages.Back);
}
}
///
/// Gets the number of backups for the current page.
///
/// The number of backups.
private int GetBackupCount() {
return Pages.GetBackups(currentPage).Count;
}
///
/// Gets the number of attachments for the current page.
///
/// The number of attachments.
private int GetAttachmentCount() {
int count = 0;
foreach(IFilesStorageProviderV30 prov in Collectors.FilesProviderCollector.AllProviders) {
count += prov.ListPageAttachments(currentPage).Length;
}
return count;
}
///
/// Sets the content and visibility of all labels used in the page.
///
private void SetupLabels() {
if(discussMode) {
lblModified.Visible = false;
lblModifiedDateTime.Visible = false;
lblBy.Visible = false;
lblAuthor.Visible = false;
lblCategorizedAs.Visible = false;
lblPageCategories.Visible = false;
lblNavigationPaths.Visible = false;
lblDiscussedPage.Text = "" + FormattingPipeline.PrepareTitle(currentContent.Title, false, FormattingContext.PageContent, currentPage) + "";
}
else {
lblPageDiscussionFor.Visible = false;
lblDiscussedPage.Visible = false;
lblModifiedDateTime.Text =
Preferences.AlignWithTimezone(currentContent.LastModified).ToString(Settings.DateTimeFormat);
lblAuthor.Text = Users.UserLink(currentContent.User);
lblPageCategories.Text = GetFormattedPageCategories();
}
}
///
/// Sets the Print and RSS links.
///
private void SetupPrintAndRssLinks() {
if(!viewCodeMode) {
lblPrintLink.Text = string.Format(@"{2}",
UrlTools.BuildUrl("Print.aspx?Page=", Tools.UrlEncode(currentPage.FullName), discussMode ? "&Discuss=1" : ""),
Properties.Messages.PrinterFriendlyVersion, Properties.Messages.Print);
if(Settings.RssFeedsMode != RssFeedsMode.Disabled) {
lblRssLink.Text = string.Format(@"RSS",
UrlTools.BuildUrl("RSS.aspx?Page=", Tools.UrlEncode(currentPage.FullName), discussMode ? "&Discuss=1" : ""),
discussMode ? Properties.Messages.RssForThisDiscussion : Properties.Messages.RssForThisPage,
discussMode ? " class=\"discuss\"" : "");
}
else lblRssLink.Visible = false;
}
else {
lblPrintLink.Visible = false;
lblRssLink.Visible = false;
}
}
///
/// Gets the categories for the current page, already formatted for display.
///
/// The categories, formatted for display.
private string GetFormattedPageCategories() {
CategoryInfo[] categories = Pages.GetCategoriesForPage(currentPage);
if(categories.Length == 0) {
return string.Format(@"{2}",
GetCategoryLink("-"),
Properties.Messages.Uncategorized, Properties.Messages.Uncategorized);
}
else {
StringBuilder sb = new StringBuilder(categories.Length * 10);
for(int i = 0; i < categories.Length; i++) {
sb.AppendFormat(@"{2}",
GetCategoryLink(categories[i].FullName),
NameTools.GetLocalName(categories[i].FullName),
NameTools.GetLocalName(categories[i].FullName));
if(i != categories.Length - 1) sb.Append(", ");
}
return sb.ToString();
}
}
///
/// Gets the link to a category.
///
/// The full name of the category.
/// The link URL.
private string GetCategoryLink(string category) {
return UrlTools.BuildUrl("AllPages.aspx?Cat=", Tools.UrlEncode(category));
}
///
/// Sets the content of the META description and keywords for the current page.
///
private void SetupMetaInformation() {
// Set keywords and description
if(currentContent.Keywords != null && currentContent.Keywords.Length > 0) {
Literal lit = new Literal();
lit.Text = string.Format("", PrintKeywords(currentContent.Keywords));
Page.Header.Controls.Add(lit);
}
if(!string.IsNullOrEmpty(currentContent.Description)) {
Literal lit = new Literal();
lit.Text = string.Format("", currentContent.Description);
Page.Header.Controls.Add(lit);
}
}
///
/// Prints the keywords in a CSV list.
///
///
///
private string PrintKeywords(string[] keywords) {
StringBuilder sb = new StringBuilder(50);
for(int i = 0; i < keywords.Length; i++) {
sb.Append(keywords[i]);
if(i != keywords.Length - 1) sb.Append(", ");
}
return sb.ToString();
}
///
/// Verifies the need for a page redirection, and performs it when appropriate.
///
private void VerifyAndPerformPageRedirection() {
if(currentPage == null) return;
// Force formatting so that the destination can be detected
Content.GetFormattedPageContent(currentPage, true);
PageInfo dest = Redirections.GetDestination(currentPage);
if(dest == null) return;
if(dest != null) {
if(Request["NoRedirect"] != "1") {
UrlTools.Redirect(dest.FullName + Settings.PageExtension + "?From=" + currentPage.FullName, false);
}
else {
// Write redirection hint
StringBuilder sb = new StringBuilder();
sb.Append(@"
");
Literal literal = new Literal();
literal.Text = sb.ToString();
plhContent.Controls.Add(literal);
}
}
}
///
/// Sets the breadcrumbs trail, if appropriate.
///
private void SetupBreadcrumbsTrail() {
if(Settings.DisableBreadcrumbsTrail || discussMode || viewCodeMode) {
lblBreadcrumbsTrail.Visible = false;
return;
}
StringBuilder sb = new StringBuilder(1000);
sb.Append(@"");
PageInfo[] pageTrail = SessionFacade.Breadcrumbs.AllPages;
int min = 3;
if(pageTrail.Length < 3) min = pageTrail.Length;
sb.Append(@"
");
sb.Append(@"
");
// Write hyperLink
sb.Append(@"
[X] ");
for(int i = 0; i < pageTrail.Length; i++) {
AppendBreadcrumb(sb, pageTrail[i], "f");
}
sb.Append("
");
sb.Append("
");
lblBreadcrumbsTrail.Text = sb.ToString();
}
///
/// Appends a breadbrumb trail element.
///
/// The destination .
/// The page to append.
/// The drop-down menu ID prefix.
private void AppendBreadcrumb(StringBuilder sb, PageInfo page, string dpPrefix) {
PageNameComparer comp = new PageNameComparer();
PageContent pc = Content.GetPageContent(page, true);
string id = AppendBreadcrumbDropDown(sb, page, dpPrefix);
string nspace = NameTools.GetNamespace(page.FullName);
sb.Append("» ");
if(comp.Compare(page, currentPage) == 0) sb.Append("");
sb.AppendFormat(@"{1}",
Tools.UrlEncode(page.FullName) + Settings.PageExtension,
FormattingPipeline.PrepareTitle(pc.Title, false, FormattingContext.PageContent, currentPage) + (string.IsNullOrEmpty(nspace) ? "" : (" (" + NameTools.GetNamespace(page.FullName) + ")")),
(id != null ? @" onmouseover=""javascript:return __ShowDropDown(event, '" + id + @"', this);""" : ""),
(id != null ? @" id=""lnk" + id + @"""" : ""),
(id != null ? @" onmouseout=""javascript:return __HideDropDown('" + id + @"');""" : ""));
if(comp.Compare(page, currentPage) == 0) sb.Append("");
sb.Append(" ");
}
///
/// Appends the drop-down menu DIV with outgoing links for a page.
///
/// The destination .
/// The page.
/// The drop-down menu DIV ID prefix.
/// The DIV ID, or null if no target pages were found.
private string AppendBreadcrumbDropDown(StringBuilder sb, PageInfo page, string dbPrefix) {
// Build outgoing links list
// Generate list DIV
// Return DIV's ID
string[] outgoingLinks = Pages.GetPageOutgoingLinks(page);
if(outgoingLinks == null || outgoingLinks.Length == 0) return null;
string id = dbPrefix + Guid.NewGuid().ToString();
StringBuilder buffer = new StringBuilder(300);
buffer.AppendFormat(@"", id);
bool pageAdded = false;
foreach(string link in outgoingLinks) {
PageInfo target = Pages.FindPage(link);
if(target != null) {
pageAdded = true;
PageContent cont = Content.GetPageContent(target, true);
string title = FormattingPipeline.PrepareTitle(cont.Title, false, FormattingContext.PageContent, currentPage);
buffer.AppendFormat(@"
{2}", link, Settings.PageExtension, title, title);
}
}
buffer.Append("
");
sb.Insert(0, buffer.ToString());
if(pageAdded) return id;
else return null;
}
///
/// Sets the redirection source page link, if appropriate.
///
private void SetupRedirectionSource() {
if(Request["From"] != null) {
PageInfo source = Pages.FindPage(Request["From"]);
if(source != null) {
StringBuilder sb = new StringBuilder(300);
sb.Append(@"");
lblRedirectionSource.Text = sb.ToString();
}
else lblRedirectionSource.Visible = false;
}
else lblRedirectionSource.Visible = false;
}
///
/// Sets the navigation paths label.
///
private void SetupNavigationPaths() {
string[] paths = NavigationPaths.PathsPerPage(currentPage);
string currentPath = Request["NavPath"];
if(!string.IsNullOrEmpty(currentPath)) currentPath = currentPath.ToLowerInvariant();
if(!discussMode && !viewCodeMode && paths.Length > 0) {
StringBuilder sb = new StringBuilder(500);
sb.Append(Properties.Messages.Paths);
sb.Append(": ");
for(int i = 0; i < paths.Length; i++) {
NavigationPath path = NavigationPaths.Find(paths[i]);
if(path != null) {
if(currentPath != null && paths[i].ToLowerInvariant().Equals(currentPath)) sb.Append("");
sb.Append(@"");
sb.Append(NameTools.GetLocalName(path.FullName));
sb.Append("");
if(currentPath != null && paths[i].ToLowerInvariant().Equals(currentPath)) sb.Append("");
if(i != paths.Length - 1) sb.Append(", ");
}
}
lblNavigationPaths.Text = sb.ToString();
}
else lblNavigationPaths.Visible = false;
}
///
/// Prepares the previous and next pages link for navigation paths.
///
/// The previous page link.
/// The next page link.
private void SetupAdjacentPages() {
StringBuilder prev = new StringBuilder(50), next = new StringBuilder(50);
if(Request["NavPath"] != null) {
NavigationPath path = NavigationPaths.Find(Request["NavPath"]);
if(path != null) {
int idx = Array.IndexOf(path.Pages, currentPage.FullName);
if(idx != -1) {
if(idx > 0) {
PageInfo prevPage = Pages.FindPage(path.Pages[idx - 1]);
prev.Append(@"« ");
}
if(idx < path.Pages.Length - 1) {
PageInfo nextPage = Pages.FindPage(path.Pages[idx + 1]);
next.Append(@" »");
}
}
}
}
if(prev.Length > 0) {
lblPreviousPage.Text = prev.ToString();
}
else lblPreviousPage.Visible = false;
if(next.Length > 0) {
lblNextPage.Text = next.ToString();
}
else lblNextPage.Visible = false;
}
///
/// Sets the JavaScript double-click editing handler.
///
private void SetupDoubleClickHandler() {
if(Settings.EnableDoubleClickEditing && !discussMode && !viewCodeMode) {
StringBuilder sb = new StringBuilder(200);
sb.Append(@"");
lblDoubleClickHandler.Text = sb.ToString();
}
else lblDoubleClickHandler.Visible = false;
}
///
/// Sets the email notification button.
///
private void SetupEmailNotification() {
if(SessionFacade.LoginKey != null && SessionFacade.CurrentUsername != "admin") {
bool pageChanges;
bool discussionMessages;
UserInfo user = Users.FindUser(SessionFacade.CurrentUsername);
if(user.Provider.UsersDataReadOnly) {
btnEmailNotification.Visible = false;
return;
}
Users.GetEmailNotification(user, currentPage, out pageChanges, out discussionMessages);
bool active = false;
if(discussMode) {
active = discussionMessages;
}
else {
active = pageChanges;
}
if(active) {
btnEmailNotification.CssClass = "activenotification" + (discussMode ? " discuss" : "");
btnEmailNotification.ToolTip = Properties.Messages.EmailNotificationsAreActive;
}
else {
btnEmailNotification.CssClass = "inactivenotification" + (discussMode ? " discuss" : "");
btnEmailNotification.ToolTip = Properties.Messages.ClickToEnableEmailNotifications;
}
}
else btnEmailNotification.Visible = false;
}
protected void btnEmailNotification_Click(object sender, EventArgs e) {
bool pageChanges;
bool discussionMessages;
UserInfo user = Users.FindUser(SessionFacade.CurrentUsername);
Users.GetEmailNotification(user, currentPage, out pageChanges, out discussionMessages);
if(discussMode) {
Users.SetEmailNotification(user, currentPage, pageChanges, !discussionMessages);
}
else {
Users.SetEmailNotification(user, currentPage, !pageChanges, discussionMessages);
}
SetupEmailNotification();
}
///
/// Sets the actual page content, based on the current view mode (normal, discussion, view code).
///
/// A value indicating whether the current user can post messages.
/// A value indicating whether the current user can manage the discussion.
private void SetupPageContent(bool canPostMessages, bool canManageDiscussion) {
if(!discussMode && !viewCodeMode) {
Literal literal = new Literal();
literal.Text = Content.GetFormattedPageContent(currentPage, true);
plhContent.Controls.Add(literal);
}
else if(!discussMode && viewCodeMode) {
if(Settings.EnableViewPageCodeFeature) {
Literal literal = new Literal();
StringBuilder sb = new StringBuilder(currentContent.Content.Length + 100);
sb.Append(@"");
literal.Text = sb.ToString();
plhContent.Controls.Add(literal);
}
}
else if(discussMode && !viewCodeMode) {
PageDiscussion discussion = LoadControl("~/PageDiscussion.ascx") as PageDiscussion;
discussion.CurrentPage = currentPage;
discussion.CanPostMessages = canPostMessages;
discussion.CanManageDiscussion = canManageDiscussion;
plhContent.Controls.Add(discussion);
}
}
}
}