/// <summary> /// Binds the group members grid. /// </summary> protected void BindGrid() { using (var rockContext = new RockContext()) { var pageShortLinkService = new PageShortLinkService(rockContext); var qry = pageShortLinkService.Queryable().ToList() .Select(s => new ShortLinkRow(s)) .ToList() .AsQueryable(); SortProperty sortProperty = gShortLinks.SortProperty; if (sortProperty != null) { gShortLinks.DataSource = qry.Sort(sortProperty).ToList(); } else { gShortLinks.DataSource = qry.OrderBy(l => l.Token).ToList(); } gShortLinks.DataBind(); } }
/// <summary> /// Handles the Click event of the DeleteShortLink control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="Rock.Web.UI.Controls.RowEventArgs" /> instance containing the event data.</param> protected void DeleteShortLink_Click(object sender, Rock.Web.UI.Controls.RowEventArgs e) { bool canDelete = false; var rockContext = new RockContext(); PageShortLinkService pageShortLinkService = new PageShortLinkService(rockContext); var shortLink = pageShortLinkService.Get(e.RowKeyId); if (shortLink != null) { string errorMessage; canDelete = pageShortLinkService.CanDelete(shortLink, out errorMessage); if (!canDelete) { mdGridWarning.Show(errorMessage, ModalAlertType.Alert); return; } int siteId = shortLink.SiteId; pageShortLinkService.Delete(shortLink); rockContext.SaveChanges(); } BindGrid(); }
/// <summary> /// Shows the detail. /// </summary> /// <param name="shortLinkId">The shortLink identifier.</param> /// <param name="siteId">The group id.</param> public void ShowDetail(int shortLinkId) { PageShortLink shortLink = null; if (!shortLinkId.Equals(0)) { shortLink = new PageShortLinkService(new RockContext()).Get(shortLinkId); pdAuditDetails.SetEntity(shortLink, ResolveRockUrl("~")); } if (shortLink == null) { shortLink = new PageShortLink { Id = 0 }; // hide the panel drawer that show created and last modified dates pdAuditDetails.Visible = false; } hfShortLinkId.Value = shortLink.Id.ToString(); bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!IsUserAuthorized(Authorization.EDIT)) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed(Rock.Model.PageShortLink.FriendlyTypeName); } if (readOnly) { btnEdit.Visible = false; //btnDelete.Visible = false; ShowReadonlyDetails(shortLink); } else { btnEdit.Visible = true; //btnDelete.Visible = !shortLink.IsSystem; if (shortLink.Id > 0) { ShowReadonlyDetails(shortLink); } else { ShowEditDetails(shortLink); } } }
/// <summary> /// Handles the Click event of the btnCancel control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnCancel_Click(object sender, EventArgs e) { if (hfShortLinkId.Value.Equals("0")) { // Cancelling on Add NavigateToParentPage(); } else { // Cancelling on Edit var shortLink = new PageShortLinkService(new RockContext()).Get(int.Parse(hfShortLinkId.Value)); ShowReadonlyDetails(shortLink); } }
protected void btnDelete_Click(object sender, EventArgs e) { using (var rockContext = new RockContext()) { var service = new PageShortLinkService(rockContext); var link = service.Get(hfShortLinkId.ValueAsInt()); if (link != null) { service.Delete(link); rockContext.SaveChanges(); NavigateToParentPage(); } } }
/// <summary> /// Binds the group members grid. /// </summary> protected void BindGrid() { using (var rockContext = new RockContext()) { var pageShortLinkService = new PageShortLinkService(rockContext); var shortLinkQry = pageShortLinkService.Queryable(); string token = gfShortLink.GetUserPreference(FilterAttributeKeys.Token); if (!string.IsNullOrEmpty(token)) { shortLinkQry = shortLinkQry.Where(s => s.Token.Contains(token)); } int?siteId = gfShortLink.GetUserPreference(FilterAttributeKeys.Site).AsIntegerOrNull(); if (siteId.HasValue) { shortLinkQry = shortLinkQry.Where(s => s.SiteId == siteId.Value); } var qry = shortLinkQry.ToList() .Select(s => new ShortLinkRow(s)) .ToList() .AsQueryable(); SortProperty sortProperty = gShortLinks.SortProperty; if (sortProperty != null) { gShortLinks.DataSource = qry.Sort(sortProperty).ToList(); } else { gShortLinks.DataSource = qry.OrderBy(l => l.Token).ToList(); } gShortLinks.DataBind(); } }
/// <summary> /// Executes this instance. /// </summary> /// <param name="message"></param> public override void Execute(Message message) { var rockContext = new RockContext(); var pageShortLink = new PageShortLinkService(rockContext).Get(message.PageShortLinkId); if (pageShortLink == null) { return; } var userAgent = (message.UserAgent ?? string.Empty).Trim(); if (userAgent.Length > 450) { userAgent = userAgent.Substring(0, 450); // trim super long useragents to fit in pageViewUserAgent.UserAgent } // get user agent info var clientType = InteractionDeviceType.GetClientType(userAgent); // don't log visits from crawlers if (clientType != "Crawler") { // lookup the interaction channel, and create it if it doesn't exist int channelMediumTypeValueId = DefinedValueCache.Get(SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_URLSHORTENER.AsGuid()).Id; InteractionChannelService interactionChannelService = new InteractionChannelService(rockContext); var interactionChannel = interactionChannelService.Queryable() .Where(a => a.ChannelTypeMediumValueId == channelMediumTypeValueId) .FirstOrDefault(); if (interactionChannel == null) { interactionChannel = new InteractionChannel(); interactionChannel.Name = "Short Links"; interactionChannel.ChannelTypeMediumValueId = channelMediumTypeValueId; interactionChannel.ComponentEntityTypeId = EntityTypeCache.Get <Rock.Model.PageShortLink>().Id; interactionChannel.Guid = SystemGuid.InteractionChannel.SHORT_LINKS.AsGuid(); interactionChannelService.Add(interactionChannel); rockContext.SaveChanges(); } // check that the page exists as a component var interactionComponent = new InteractionComponentService(rockContext).GetComponentByChannelIdAndEntityId(interactionChannel.Id, pageShortLink.Id, message.Token); if (message.Url.IsNotNullOrWhiteSpace()) { if (interactionComponent.ComponentSummary != message.Url) { interactionComponent.ComponentSummary = message.Url; } var urlDataJson = new { Url = message.Url }.ToJson(); if (interactionComponent.ComponentData != urlDataJson) { interactionComponent.ComponentData = urlDataJson; } } rockContext.SaveChanges(); // Add the interaction if (interactionComponent != null) { int?personAliasId = null; if (message.UserName.IsNotNullOrWhiteSpace()) { var currentUser = new UserLoginService(rockContext).GetByUserName(message.UserName); personAliasId = currentUser?.Person?.PrimaryAlias?.Id; } Parser uaParser = Parser.GetDefault(); ClientInfo client = uaParser.Parse(userAgent); var clientOs = client.OS.ToString(); var clientBrowser = client.UA.ToString(); new InteractionService(rockContext).AddInteraction(interactionComponent.Id, null, "View", message.Url, personAliasId, message.DateViewed, clientBrowser, clientOs, clientType, userAgent, message.IPAddress, message.SessionId?.AsGuidOrNull()); rockContext.SaveChanges(); } } }
/// <summary> /// Determine the logical page being requested by evaluating the routedata, or querystring and /// then loading the appropriate layout (ASPX) page /// /// Pick url on the following priority order: /// 1. PageId /// 2. Route match and site match /// 3. ShortLink match and site match /// 4. Route and no site match /// 5. ShortLink with no site match /// 6. If there is no routing info in the request then set to default page /// 7. 404 if route does not exist /// /// </summary> /// <param name="requestContext"></param> /// <returns></returns> System.Web.IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { string pageId = string.Empty; int routeId = 0; bool isSiteMatch = false; Dictionary <string, string> parms; string host; HttpRequestBase routeHttpRequest; HttpCookie siteCookie; // Context cannot be null if (requestContext == null) { throw new ArgumentNullException("requestContext"); } try { routeHttpRequest = requestContext.HttpContext.Request; siteCookie = routeHttpRequest.Cookies["last_site"]; parms = new Dictionary <string, string>(); host = WebRequestHelper.GetHostNameFromRequest(HttpContext.Current); if (requestContext.RouteData.Values["PageId"] != null) { // Pages using the default routing URL will have the page id in the RouteData.Values collection pageId = ( string )requestContext.RouteData.Values["PageId"]; isSiteMatch = true; } else if (requestContext.RouteData.DataTokens["PageRoutes"] != null) { SiteCache site = GetSite(routeHttpRequest, host, siteCookie); // Pages that use a custom URL route will have the page id in the RouteData.DataTokens collection GetPageIdFromDataTokens(requestContext, site, out pageId, out routeId, out isSiteMatch); foreach (var routeParm in requestContext.RouteData.Values) { parms.Add(routeParm.Key, ( string )routeParm.Value); } } else if (((System.Web.Routing.Route)requestContext.RouteData.Route).Url.IsNullOrWhiteSpace()) { // if we don't have routing info then set the page ID to the default page for the site. // Get the site, if not found use the default site SiteCache site = GetSite(routeHttpRequest, host, siteCookie); if (site == null) { site = SiteCache.Get(SystemGuid.Site.SITE_ROCK_INTERNAL.AsGuid()); } if (site.DefaultPageId.HasValue) { pageId = site.DefaultPageId.Value.ToString(); isSiteMatch = true; } else { throw new SystemException("Invalid Site Configuration"); } } // If the the page ID and site has not yet been matched if (string.IsNullOrEmpty(pageId) || !isSiteMatch) { SiteCache site = GetSite(routeHttpRequest, host, siteCookie); // if not found use the default site if (site == null) { site = SiteCache.Get(SystemGuid.Site.SITE_ROCK_INTERNAL.AsGuid()); } if (site != null) { // Check to see if this is a short link route string shortlink = null; if (requestContext.RouteData.Values.ContainsKey("shortlink")) { shortlink = requestContext.RouteData.Values["shortlink"].ToString(); } // If shortlink have the same name as route and route's site did not match, then check if shortlink site match. if (shortlink.IsNullOrWhiteSpace() && requestContext.RouteData.DataTokens["RouteName"] != null) { shortlink = requestContext.RouteData.DataTokens["RouteName"].ToString(); } if (shortlink.IsNotNullOrWhiteSpace()) { using (var rockContext = new Rock.Data.RockContext()) { var pageShortLink = new PageShortLinkService(rockContext).GetByToken(shortlink, site.Id); if (pageShortLink != null && (pageShortLink.SiteId == site.Id || requestContext.RouteData.DataTokens["RouteName"] == null)) { pageId = string.Empty; routeId = 0; string trimmedUrl = pageShortLink.Url.RemoveCrLf().Trim(); var transaction = new ShortLinkTransaction(); transaction.PageShortLinkId = pageShortLink.Id; transaction.Token = pageShortLink.Token; transaction.Url = trimmedUrl; if (requestContext.HttpContext.User != null) { transaction.UserName = requestContext.HttpContext.User.Identity.Name; } transaction.DateViewed = RockDateTime.Now; transaction.IPAddress = WebRequestHelper.GetClientIpAddress(routeHttpRequest); transaction.UserAgent = routeHttpRequest.UserAgent ?? string.Empty; RockQueue.TransactionQueue.Enqueue(transaction); requestContext.HttpContext.Response.Redirect(trimmedUrl); return(null); } } } // If site has has been enabled for mobile redirect, then we'll need to check what type of device is being used if (site.EnableMobileRedirect) { // get the device type string u = routeHttpRequest.UserAgent; var clientType = InteractionDeviceType.GetClientType(u); bool redirect = false; // first check if device is a mobile device if (clientType == "Mobile") { redirect = true; } // if not, mobile device and tables should be redirected also, check if device is a tablet if (!redirect && site.RedirectTablets && clientType == "Tablet") { redirect = true; } if (redirect) { if (site.MobilePageId.HasValue) { pageId = site.MobilePageId.Value.ToString(); routeId = 0; } else if (!string.IsNullOrWhiteSpace(site.ExternalUrl)) { requestContext.HttpContext.Response.Redirect(site.ExternalUrl); return(null); } } } } } PageCache page = null; if (!string.IsNullOrEmpty(pageId)) { int pageIdNumber = 0; if (int.TryParse(pageId, out pageIdNumber)) { page = PageCache.Get(pageIdNumber); } } if (page == null) { // try to get site's 404 page SiteCache site = GetSite(routeHttpRequest, host, siteCookie); if (site != null && site.PageNotFoundPageId != null) { if (Convert.ToBoolean(GlobalAttributesCache.Get().GetValue("Log404AsException"))) { Rock.Model.ExceptionLogService.LogException( new Exception($"404 Error: {routeHttpRequest.Url.AbsoluteUri}"), requestContext.HttpContext.ApplicationInstance.Context); } page = PageCache.Get(site.PageNotFoundPageId ?? 0); requestContext.HttpContext.Response.StatusCode = 404; requestContext.HttpContext.Response.TrySkipIisCustomErrors = true; } else { // no 404 page found for the site, return the default 404 error page return((System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Http404Error.aspx", typeof(System.Web.UI.Page))); } } CreateOrUpdateSiteCookie(siteCookie, requestContext, page); string theme = page.Layout.Site.Theme; string layout = page.Layout.FileName; string layoutPath = PageCache.FormatPath(theme, layout); try { return(CreateRockPage(page, layoutPath, routeId, parms, routeHttpRequest)); } catch (System.Web.HttpException) { // The Selected theme and/or layout didn't exist so try to use the layout in the default theme. theme = "Rock"; // Verify that Layout exists in the default theme directory and if not try use the default layout of the default theme string layoutPagePath = string.Format("~/Themes/Rock/Layouts/{0}.aspx", layout); if (!File.Exists(requestContext.HttpContext.Server.MapPath(layoutPagePath))) { layout = "FullWidth"; } layoutPath = PageCache.FormatPath(theme, layout); return(CreateRockPage(page, layoutPath, routeId, parms, routeHttpRequest)); } } catch (Exception ex) { if (requestContext.HttpContext != null) { requestContext.HttpContext.Cache["RockExceptionOrder"] = "66"; requestContext.HttpContext.Cache["RockLastException"] = ex; } return((System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Error.aspx", typeof(System.Web.UI.Page))); } }
/// <summary> /// Determine the logical page being requested by evaluating the routedata, or querystring and /// then loading the appropriate layout (ASPX) page /// </summary> /// <param name="requestContext"></param> /// <returns></returns> System.Web.IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } try { var httpRequest = requestContext.HttpContext.Request; var siteCookie = httpRequest.Cookies["last_site"]; string pageId = ""; int routeId = 0; var parms = new Dictionary <string, string>(); // Pages using the default routing URL will have the page id in the RouteData.Values collection if (requestContext.RouteData.Values["PageId"] != null) { pageId = (string)requestContext.RouteData.Values["PageId"]; } // Pages that use a custom URL route will have the page id in the RouteDate.DataTokens collection else if (requestContext.RouteData.DataTokens["PageRoutes"] != null) { var pageAndRouteIds = requestContext.RouteData.DataTokens["PageRoutes"] as List <PageAndRouteId>; if (pageAndRouteIds != null && pageAndRouteIds.Count > 0) { // Default to first site/page if (pageAndRouteIds.Count >= 1) { var pageAndRouteId = pageAndRouteIds.First(); pageId = pageAndRouteId.PageId.ToJson(); routeId = pageAndRouteId.RouteId; } // Then check to see if any can be matched by site if (pageAndRouteIds.Count > 1) { SiteCache site = null; // First check to see if site was specified in querystring int?siteId = httpRequest.QueryString["SiteId"].AsIntegerOrNull(); if (siteId.HasValue) { site = SiteCache.Read(siteId.Value); } // Then check to see if site can be determined by domain if (site == null) { site = SiteCache.GetSiteByDomain(httpRequest.Url.Host); } // Then check the last site if (site == null) { if (siteCookie != null && siteCookie.Value != null) { site = SiteCache.Read(siteCookie.Value.AsInteger()); } } if (site != null) { foreach (var pageAndRouteId in pageAndRouteIds) { var pageCache = PageCache.Read(pageAndRouteId.PageId); if (pageCache != null && pageCache.Layout != null && pageCache.Layout.SiteId == site.Id) { pageId = pageAndRouteId.PageId.ToJson(); routeId = pageAndRouteId.RouteId; break; } } } } } foreach (var routeParm in requestContext.RouteData.Values) { parms.Add(routeParm.Key, (string)routeParm.Value); } } // If page has not been specified get the site by the domain and use the site's default page if (string.IsNullOrEmpty(pageId)) { SiteCache site = SiteCache.GetSiteByDomain(httpRequest.Url.Host); if (site == null) { // Use last site if (siteCookie != null && siteCookie.Value != null) { site = SiteCache.Read(siteCookie.Value.AsInteger()); } } // if not found use the default site if (site == null) { site = SiteCache.Read(SystemGuid.Site.SITE_ROCK_INTERNAL.AsGuid()); } if (site != null) { // Check to see if this is a short link route if (requestContext.RouteData.Values.ContainsKey("shortlink")) { string shortlink = requestContext.RouteData.Values["shortlink"].ToString(); using (var rockContext = new Rock.Data.RockContext()) { var pageShortLink = new PageShortLinkService(rockContext).GetByToken(shortlink, site.Id); if (pageShortLink != null) { string trimmedUrl = pageShortLink.Url.RemoveCrLf().Trim(); var transaction = new ShortLinkTransaction(); transaction.PageShortLinkId = pageShortLink.Id; transaction.Token = pageShortLink.Token; transaction.Url = trimmedUrl; if (requestContext.HttpContext.User != null) { transaction.UserName = requestContext.HttpContext.User.Identity.Name; } transaction.DateViewed = RockDateTime.Now; transaction.IPAddress = UI.RockPage.GetClientIpAddress(httpRequest); transaction.UserAgent = httpRequest.UserAgent ?? ""; RockQueue.TransactionQueue.Enqueue(transaction); requestContext.HttpContext.Response.Redirect(trimmedUrl); return(null); } } } // If site has has been enabled for mobile redirect, then we'll need to check what type of device is being used if (site.EnableMobileRedirect) { // get the device type string u = httpRequest.UserAgent; var clientType = InteractionDeviceType.GetClientType(u); bool redirect = false; // first check if device is a mobile device if (clientType == "Mobile") { redirect = true; } // if not, mobile device and tables should be redirected also, check if device is a tablet if (!redirect && site.RedirectTablets) { if (clientType == "Tablet") { redirect = true; } } if (redirect) { if (site.MobilePageId.HasValue) { pageId = site.MobilePageId.Value.ToString(); } else if (!string.IsNullOrWhiteSpace(site.ExternalUrl)) { requestContext.HttpContext.Response.Redirect(site.ExternalUrl); return(null); } } } if (string.IsNullOrWhiteSpace(pageId)) { if (site.DefaultPageId.HasValue) { pageId = site.DefaultPageId.Value.ToString(); } if (site.DefaultPageRouteId.HasValue) { routeId = site.DefaultPageRouteId.Value; } } } if (string.IsNullOrEmpty(pageId)) { throw new SystemException("Invalid Site Configuration"); } } PageCache page = null; if (!string.IsNullOrEmpty(pageId)) { int pageIdNumber = 0; if (Int32.TryParse(pageId, out pageIdNumber)) { page = PageCache.Read(pageIdNumber); } } if (page == null) { // try to get site's 404 page SiteCache site = SiteCache.GetSiteByDomain(httpRequest.Url.Host); if (site == null) { // Use last site if (siteCookie != null && siteCookie.Value != null) { site = SiteCache.Read(siteCookie.Value.AsInteger()); } } if (site != null && site.PageNotFoundPageId != null) { if (Convert.ToBoolean(GlobalAttributesCache.Read().GetValue("Log404AsException"))) { Rock.Model.ExceptionLogService.LogException( new Exception(string.Format("404 Error: {0}", httpRequest.Url.AbsoluteUri)), requestContext.HttpContext.ApplicationInstance.Context); } page = PageCache.Read(site.PageNotFoundPageId ?? 0); } else { // no 404 page found for the site, return the default 404 error page return((System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Http404Error.aspx", typeof(System.Web.UI.Page))); } } string theme = page.Layout.Site.Theme; string layout = page.Layout.FileName; string layoutPath = PageCache.FormatPath(theme, layout); if (siteCookie == null) { siteCookie = new System.Web.HttpCookie("last_site", page.Layout.SiteId.ToString()); } else { siteCookie.Value = page.Layout.SiteId.ToString(); } requestContext.HttpContext.Response.SetCookie(siteCookie); try { // Return the page for the selected theme and layout Rock.Web.UI.RockPage cmsPage = (Rock.Web.UI.RockPage)BuildManager.CreateInstanceFromVirtualPath(layoutPath, typeof(Rock.Web.UI.RockPage)); cmsPage.SetPage(page); cmsPage.PageReference = new PageReference(page.Id, routeId, parms, httpRequest.QueryString); return(cmsPage); } catch (System.Web.HttpException) { // The Selected theme and/or layout didn't exist, attempt first to use the layout in the default theme. theme = "Rock"; // If not using the default layout, verify that Layout exists in the default theme directory if (layout != "FullWidth" && !File.Exists(requestContext.HttpContext.Server.MapPath(string.Format("~/Themes/Rock/Layouts/{0}.aspx", layout)))) { // If selected layout doesn't exist in the default theme, switch to the Default layout layout = "FullWidth"; } // Build the path to the aspx file to layoutPath = PageCache.FormatPath(theme, layout); // Return the default layout and/or theme Rock.Web.UI.RockPage cmsPage = (Rock.Web.UI.RockPage)BuildManager.CreateInstanceFromVirtualPath(layoutPath, typeof(Rock.Web.UI.RockPage)); cmsPage.SetPage(page); cmsPage.PageReference = new PageReference(page.Id, routeId, parms, httpRequest.QueryString); return(cmsPage); } } catch (Exception ex) { if (requestContext.HttpContext != null) { requestContext.HttpContext.Cache["RockExceptionOrder"] = "66"; requestContext.HttpContext.Cache["RockLastException"] = ex; } System.Web.UI.Page errorPage = (System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Error.aspx", typeof(System.Web.UI.Page)); return(errorPage); } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { errorMessages = new List <string>(); var service = new PageShortLinkService(rockContext); // Get the merge fields var mergeFields = GetMergeFields(action); // Get the site int siteId = GetAttributeValue(action, "Site", true).AsInteger(); SiteCache site = SiteCache.Get(siteId); if (site == null) { errorMessages.Add(string.Format("Invalid Site Value")); return(false); } // Get the token string token = GetAttributeValue(action, "Token", true).ResolveMergeFields(mergeFields); if (token.IsNullOrWhiteSpace()) { int tokenLen = GetAttributeValue(action, "RandomTokenLength").AsIntegerOrNull() ?? 7; token = service.GetUniqueToken(site.Id, tokenLen); } // Get the target url string url = GetAttributeValue(action, "Url", true).ResolveMergeFields(mergeFields).RemoveCrLf().Trim(); if (url.IsNullOrWhiteSpace()) { errorMessages.Add("A valid Target Url was not specified."); return(false); } // Save the short link var link = service.GetByToken(token, site.Id); if (link != null) { if (!GetAttributeValue(action, "Overwrite").AsBoolean()) { errorMessages.Add(string.Format("The selected token ('{0}') already exists. Please specify a unique token, or configure action to allow token re-use.", token)); return(false); } else { link.Url = url; } } else { link = new PageShortLink(); link.SiteId = site.Id; link.Token = token; link.Url = url; service.Add(link); } rockContext.SaveChanges(); // Save the resulting short link url var attribute = AttributeCache.Get(GetAttributeValue(action, "Attribute").AsGuid(), rockContext); if (attribute != null) { string shortLink = link.ShortLinkUrl; SetWorkflowAttributeValue(action, attribute.Guid, shortLink); action.AddLogEntry(string.Format("Set '{0}' attribute to '{1}'.", attribute.Name, shortLink)); } return(true); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { if (Page.IsValid) { PageShortLink link = null; using (var rockContext = new RockContext()) { var service = new PageShortLinkService(rockContext); var errors = new List <string>(); int?linkId = hfShortLinkId.Value.AsIntegerOrNull(); if (linkId.HasValue) { link = service.Get(linkId.Value); } if (link == null) { link = new PageShortLink(); service.Add(link); } int? siteId = ddlSite.SelectedValueAsInt(); string token = tbToken.Text.Trim(); string url = tbUrl.Text.RemoveCrLf().Trim(); if (!siteId.HasValue) { errors.Add("Please select a valid site."); } int minTokenLength = GetAttributeValue("MinimumTokenLength").AsIntegerOrNull() ?? 7; if (token.IsNullOrWhiteSpace() || token.Length < minTokenLength) { errors.Add(string.Format("Please enter a token that is a least {0} characters long.", minTokenLength)); } else if (siteId.HasValue && !service.VerifyUniqueToken(siteId.Value, link.Id, tbToken.Text)) { errors.Add("The selected token is already being used. Please enter a different token."); } if (url.IsNullOrWhiteSpace()) { errors.Add("Please enter a valid URL."); } if (errors.Any()) { nbError.Text = "Please correct the following:<ul><li>" + errors.AsDelimited("</li><li>") + "</li></ul>"; nbError.Visible = true; return; } link.SiteId = siteId.Value; link.Token = token; link.Url = url; if (!link.IsValid) { return; } rockContext.SaveChanges(); } Dictionary <string, string> qryParams = new Dictionary <string, string>(); qryParams["ShortLinkId"] = link.Id.ToString(); NavigateToPage(RockPage.Guid, qryParams); } }
/// <summary> /// Handles the Click event of the btnEdit control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnEdit_Click(object sender, EventArgs e) { var shortLink = new PageShortLinkService(new RockContext()).Get(int.Parse(hfShortLinkId.Value)); ShowEditDetails(shortLink); }
/// <summary> /// Determine the logical page being requested by evaluating the routedata, or querystring and /// then loading the appropriate layout (ASPX) page /// /// Pick url on the following priority order: /// 1. PageId /// 2. Route match and site match /// 3. ShortLink match and site match /// 4. Route and no site match /// 5. ShortLink with no site match /// 6. If there is no routing info in the request then set to default page /// 7. 404 if route does not exist /// /// </summary> /// <param name="requestContext"></param> /// <returns></returns> System.Web.IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { string pageId = string.Empty; int routeId = 0; bool isSiteMatch = false; Dictionary <string, string> parms; string host; HttpRequestBase routeHttpRequest; HttpCookie siteCookie; SiteCache site; // Context cannot be null if (requestContext == null) { throw new ArgumentNullException("requestContext"); } try { routeHttpRequest = requestContext.HttpContext.Request; siteCookie = routeHttpRequest.Cookies["last_site"]; parms = new Dictionary <string, string>(); host = WebRequestHelper.GetHostNameFromRequest(HttpContext.Current); site = GetSite(host, siteCookie); if (requestContext.RouteData.Values["PageId"] != null) { // Pages using the default routing URL will have the page id in the RouteData.Values collection pageId = ( string )requestContext.RouteData.Values["PageId"]; // Does the page ID exist on the requesting site isSiteMatch = IsSiteMatch(site, pageId.AsIntegerOrNull()); if (site != null && site.EnableExclusiveRoutes && !isSiteMatch) { // If the site has to match and does not then don't use the page ID. Set it to empty so the 404 can be returned. pageId = string.Empty; } else if (!isSiteMatch) { // This page belongs to another site, make sure it is allowed to be loaded. if (IsPageExclusiveToAnotherSite(site, pageId.AsIntegerOrNull(), null)) { // If the page has to match the site and does not then don't use the page ID. Set it to empty so the 404 can be returned. pageId = string.Empty; } } } else if (requestContext.RouteData.DataTokens["PageRoutes"] != null) { // Pages that use a custom URL route will have the page id in the RouteData.DataTokens collection GetPageIdFromDataTokens(requestContext, site, out pageId, out routeId, out isSiteMatch); foreach (var routeParm in requestContext.RouteData.Values) { parms.Add(routeParm.Key, ( string )routeParm.Value); } } else if (((System.Web.Routing.Route)requestContext.RouteData.Route).Url.IsNullOrWhiteSpace()) { // if we don't have routing info then set the page ID to the default page for the site. // Get the site, if not found use the default site if (site == null) { site = SiteCache.Get(SystemGuid.Site.SITE_ROCK_INTERNAL.AsGuid()); } if (site.DefaultPageId.HasValue) { pageId = site.DefaultPageId.Value.ToString(); isSiteMatch = true; } else { throw new SystemException("Invalid Site Configuration"); } } // If the the page ID and site has not yet been matched if (string.IsNullOrEmpty(pageId) || !isSiteMatch) { // if not found use the default site if (site == null) { site = SiteCache.Get(SystemGuid.Site.SITE_ROCK_INTERNAL.AsGuid()); } // Are shortlinks enabled for this site? If so, check for a matching shortlink route. if (site != null) { if (site.EnabledForShortening) { // Check to see if this is a short link route string shortlink = null; if (requestContext.RouteData.Values.ContainsKey("shortlink")) { shortlink = requestContext.RouteData.Values["shortlink"].ToString(); } else { // Because we implemented shortlinks using a {shortlink} (catchall) route, it's // possible the organization added a custom {catchall} route (at root level; no slashes) // and it is overriding our shortlink route. If they did, use it for a possible 'shortlink' // route match. if (requestContext.RouteData.DataTokens["RouteName"] != null && requestContext.RouteData.DataTokens["RouteName"].ToStringSafe().StartsWith("{")) { var routeName = requestContext.RouteData.DataTokens["RouteName"].ToStringSafe().Trim(new Char[] { '{', '}' }); shortlink = requestContext.RouteData.Values[routeName].ToStringSafe(); } } if (shortlink.IsNullOrWhiteSpace() && requestContext.RouteData.DataTokens["RouteName"] != null) { shortlink = requestContext.RouteData.DataTokens["RouteName"].ToString(); } if (shortlink.IsNotNullOrWhiteSpace()) { using (var rockContext = new Rock.Data.RockContext()) { var pageShortLink = new PageShortLinkService(rockContext).GetByToken(shortlink, site.Id); // Use the short link if the site IDs match or the current site and shortlink site are not exclusive. // Note: this is only a restriction based on the site chosen as the owner of the shortlink, the acutal URL can go anywhere. if (pageShortLink != null && (pageShortLink.SiteId == site.Id || (!site.EnableExclusiveRoutes && !pageShortLink.Site.EnableExclusiveRoutes))) { if (pageShortLink.SiteId == site.Id || requestContext.RouteData.DataTokens["RouteName"] == null) { pageId = string.Empty; routeId = 0; string trimmedUrl = pageShortLink.Url.RemoveCrLf().Trim(); var transaction = new ShortLinkTransaction { PageShortLinkId = pageShortLink.Id, Token = pageShortLink.Token, Url = trimmedUrl, DateViewed = RockDateTime.Now, IPAddress = WebRequestHelper.GetClientIpAddress(routeHttpRequest), UserAgent = routeHttpRequest.UserAgent ?? string.Empty, UserName = requestContext.HttpContext.User?.Identity.Name }; RockQueue.TransactionQueue.Enqueue(transaction); requestContext.HttpContext.Response.Redirect(trimmedUrl, false); requestContext.HttpContext.ApplicationInstance.CompleteRequest(); // Global.asax.cs will throw and log an exception if null is returned, so just return a new page. return(new System.Web.UI.Page()); } } } } } // If site has has been enabled for mobile redirect, then we'll need to check what type of device is being used if (site.EnableMobileRedirect) { // get the device type string u = routeHttpRequest.UserAgent; var clientType = InteractionDeviceType.GetClientType(u); bool redirect = false; // first check if device is a mobile device if (clientType == "Mobile") { redirect = true; } // if not, mobile device and tables should be redirected also, check if device is a tablet if (!redirect && site.RedirectTablets && clientType == "Tablet") { redirect = true; } if (redirect) { if (site.MobilePageId.HasValue) { pageId = site.MobilePageId.Value.ToString(); routeId = 0; } else if (!string.IsNullOrWhiteSpace(site.ExternalUrl)) { requestContext.HttpContext.Response.Redirect(site.ExternalUrl, false); requestContext.HttpContext.ApplicationInstance.CompleteRequest(); // Global.asax.cs will throw and log an exception if null is returned, so just return a new page. return(new System.Web.UI.Page()); } } } } } PageCache page = null; if (!string.IsNullOrEmpty(pageId)) { int pageIdNumber = 0; if (int.TryParse(pageId, out pageIdNumber)) { page = PageCache.Get(pageIdNumber); } } if (page == null) { // try to get site's 404 page if (site != null && site.PageNotFoundPageId != null) { if (Convert.ToBoolean(GlobalAttributesCache.Get().GetValue("Log404AsException"))) { Rock.Model.ExceptionLogService.LogException( new Exception($"404 Error: {routeHttpRequest.Url.AbsoluteUri}"), requestContext.HttpContext.ApplicationInstance.Context); } page = PageCache.Get(site.PageNotFoundPageId ?? 0); requestContext.HttpContext.Response.StatusCode = 404; requestContext.HttpContext.Response.TrySkipIisCustomErrors = true; } else { // no 404 page found for the site, return the default 404 error page return((System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Http404Error.aspx", typeof(System.Web.UI.Page))); } } CreateOrUpdateSiteCookie(siteCookie, requestContext, page); string theme = page.Layout.Site.Theme; string layout = page.Layout.FileName; string layoutPath = PageCache.FormatPath(theme, layout); try { return(CreateRockPage(page, layoutPath, routeId, parms, routeHttpRequest)); } catch (System.Web.HttpException) { // The Selected theme and/or layout didn't exist so try to use the layout in the default theme. theme = "Rock"; // Verify that Layout exists in the default theme directory and if not try use the default layout of the default theme string layoutPagePath = string.Format("~/Themes/Rock/Layouts/{0}.aspx", layout); if (!File.Exists(requestContext.HttpContext.Server.MapPath(layoutPagePath))) { layout = "FullWidth"; } layoutPath = PageCache.FormatPath(theme, layout); return(CreateRockPage(page, layoutPath, routeId, parms, routeHttpRequest)); } } catch (Exception ex) { if (requestContext.HttpContext != null) { requestContext.HttpContext.Cache["RockExceptionOrder"] = "66"; requestContext.HttpContext.Cache["RockLastException"] = ex; } return((System.Web.UI.Page)BuildManager.CreateInstanceFromVirtualPath("~/Error.aspx", typeof(System.Web.UI.Page))); } }
/// <summary> /// Uses the DataTokens to contstruct a list of PageAndRouteIds /// If any exist then set page and route ID to the first one found. /// Then loop through the collection looking for a site match, if one is found then set the page and route ID to that /// and the IsSiteMatch property to true. /// </summary> private void GetPageIdFromDataTokens(RequestContext routeRequestContext, SiteCache site, out string pageId, out int routeId, out bool isSiteMatch) { pageId = string.Empty; routeId = 0; isSiteMatch = false; if (site == null) { return; } // Pages that use a custom URL route will have the page id in the RouteData.DataTokens collection, if there are not any then just return. var pageAndRouteIds = (List <PageAndRouteId>)routeRequestContext.RouteData.DataTokens["PageRoutes"]; if (pageAndRouteIds == null || !pageAndRouteIds.Any()) { return; } // First try to find a match for the site // See if this is a possible shortlink if (routeRequestContext.RouteData.DataTokens["RouteName"] != null && routeRequestContext.RouteData.DataTokens["RouteName"].ToStringSafe().StartsWith("{")) { // Get the route value string routeValue = routeRequestContext.RouteData.Values.Values.FirstOrDefault().ToStringSafe(); // See if the route value string matches a shortlink for this site. var pageShortLink = new PageShortLinkService(new Rock.Data.RockContext()).GetByToken(routeValue, site.Id); if (pageShortLink != null && pageShortLink.SiteId == site.Id) { // The route entered matches a shortlink for the site, so lets NOT set the page ID for a catch-all route and let the shortlink logic take over. return; } } // Not a short link so cycle through the pages and routes to find a match for the site. foreach (var pageAndRouteId in pageAndRouteIds) { var pageCache = PageCache.Get(pageAndRouteId.PageId); if (pageCache != null && pageCache.Layout != null && pageCache.Layout.SiteId == site.Id) { pageId = pageAndRouteId.PageId.ToStringSafe(); routeId = pageAndRouteId.RouteId; isSiteMatch = true; return; } } // Default to first site/page that is not Exclusive foreach (var pageAndRouteId in pageAndRouteIds) { if (!IsPageExclusiveToAnotherSite(site, pageAndRouteId.PageId, pageAndRouteId.RouteId)) { // These are safe to assign as defaults pageId = pageAndRouteId.PageId.ToStringSafe(); routeId = pageAndRouteId.RouteId; return; } } }
/// <summary> /// Handles the OnSave event of the masterPage control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void masterPage_OnSave(object sender, EventArgs e) { Page.Validate(BlockValidationGroup); if (Page.IsValid) { PageShortLink link = null; using (var rockContext = new RockContext()) { var service = new PageShortLinkService(rockContext); var errors = new List <string>(); int? siteId = ddlSite.SelectedValueAsInt(); string token = tbToken.Text.Trim(); string url = tbUrl.Text.Trim(); if (!siteId.HasValue) { errors.Add("Please select a valid site."); } if (token.IsNullOrWhiteSpace() || token.Length < _minTokenLength) { errors.Add(string.Format("Please enter a token that is a least {0} characters long.", _minTokenLength)); } else if (siteId.HasValue && !service.VerifyUniqueToken(siteId.Value, 0, tbToken.Text)) { errors.Add("The selected token is already being used. Please enter a different token."); } if (url.IsNullOrWhiteSpace()) { errors.Add("Please enter a valid URL."); } if (errors.Any()) { nbError.Text = "Please correct the following:<ul><li>" + errors.AsDelimited("</li><li>") + "</li></ul>"; nbError.Visible = true; return; } link = new PageShortLink(); link.SiteId = siteId.Value; link.Token = token; link.Url = url; service.Add(link); rockContext.SaveChanges(); } if (link != null) { using (var rockContext = new RockContext()) { string script = "window.parent.Rock.controls.modal.close();"; ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "close-modal", script, true); } } } }
/// <summary> /// Builds the dynamic routes. /// </summary> public void BuildDynamicRoutes() { var constraintResolver = _applicationBuilder.ApplicationServices.GetRequiredService <IInlineConstraintResolver>(); var builder = new RouteBuilder(_applicationBuilder); using (var rockContext = new RockContext()) { var routes = new PageRouteService(rockContext).Queryable().ToList(); var shortlinks = new PageShortLinkService(rockContext).Queryable().ToList(); // // 3. Add Routes with a site match. // foreach (var route in routes) { var pageCache = PageCache.Get(route.PageId); builder.Routes.Add(new Route( new RouteHandler(PageRouteAsync), null, route.Route, new RouteValueDictionary(new { route.PageId, RouteId = route.Id }), new RouteValueDictionary(new { Site = new SiteMatchConstraint(pageCache.Layout.SiteId) }), new RouteValueDictionary(), constraintResolver)); } // // 4. Add Shortlink match with a site match. // foreach (var shortlink in shortlinks) { builder.Routes.Add(new Route( new RouteHandler(ShortLinkAsync), null, shortlink.Token, new RouteValueDictionary(new { ShortLinkId = shortlink.Id, shortlink.Url, shortlink.Token }), new RouteValueDictionary(new { Site = new SiteMatchConstraint(shortlink.SiteId) }), new RouteValueDictionary(), constraintResolver)); } // // 5. Add Routes with no site match. // foreach (var route in routes) { var pageCache = PageCache.Get(route.PageId); builder.Routes.Add(new Route( new RouteHandler(PageRouteAsync), null, route.Route, new RouteValueDictionary(new { route.PageId, RouteId = route.Id }), new RouteValueDictionary(), new RouteValueDictionary(), constraintResolver)); } // // 4. Add Shortlink match with no site match. // foreach (var shortlink in shortlinks) { builder.Routes.Add(new Route( new RouteHandler(ShortLinkAsync), null, shortlink.Token, new RouteValueDictionary(new { ShortLinkId = shortlink.Id, shortlink.Url, shortlink.Token }), new RouteValueDictionary(), new RouteValueDictionary(), constraintResolver)); } } _dynamicRouter = builder.Build(); }