From 81b1a375efb7744382871d34c2c5b9ed64fe78cf Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 14 Oct 2010 16:33:12 -0700 Subject: [PATCH 1/5] Fixing dots on routes - http://orchard.codeplex.com/workitem/16533 --HG-- branch : dev --- .../Core/Routable/Drivers/RoutePartDriver.cs | 9 +++++++-- .../Core/Routable/Services/RoutableService.cs | 11 +++++++++-- .../Orchard.Blogs/Controllers/BlogAdminController.cs | 5 ----- .../Orchard.Blogs/Handlers/BlogPartArchiveHandler.cs | 8 ++++---- .../Modules/Orchard.Blogs/Models/BlogPart.cs | 1 - src/Orchard/Mvc/Html/HtmlHelperExtensions.cs | 1 - 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs index 5a0b308cc..4356be02a 100644 --- a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs +++ b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs @@ -82,8 +82,13 @@ namespace Orchard.Core.Routable.Drivers { part.Title = model.Title; part.Slug = model.Slug; - if (!_routableService.IsSlugValid(part.Slug)) { - updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).")); + if ( !_routableService.IsSlugValid(part.Slug) ) { + if ( ( part.Slug ?? String.Empty ).Trim().EndsWith(".") ) { + updater.AddModelError("Routable.Slug", T("The \".\" can't be used around routes.")); + } + else { + updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).")); + } } string originalSlug = part.Slug; diff --git a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs index 7d29d7397..0c013e1c1 100644 --- a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs +++ b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs @@ -26,6 +26,9 @@ namespace Orchard.Core.Routable.Services { if (slug.Length > 1000) slug = slug.Substring(0, 1000); + // dots are not allowed at the begin and the end of routes + slug = slug.Trim('.'); + model.Slug = slug.ToLowerInvariant(); } @@ -63,8 +66,13 @@ namespace Orchard.Core.Routable.Services { } public bool IsSlugValid(string slug) { + slug = (slug ?? String.Empty).Trim(); + return !( SlugHasProhibitedChard(slug) || slug.StartsWith(".") || slug.EndsWith(".") ); + } + + public bool SlugHasProhibitedChard(string slug) { // see http://tools.ietf.org/html/rfc3987 for prohibited chars - return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s]+$"); + return Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s]+$"); } public bool ProcessSlug(RoutePart part) { @@ -80,7 +88,6 @@ namespace Orchard.Core.Routable.Services { // of slugs to consider for conflict detection pathsLikeThis = pathsLikeThis.Where(p => p.ContentItem.Id != part.ContentItem.Id); - //todo: (heskew) need better messages if (pathsLikeThis.Count() > 0) { var originalSlug = part.Slug; //todo: (heskew) make auto-uniqueness optional diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs index 069495e45..bd5bc5990 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs @@ -43,7 +43,6 @@ namespace Orchard.Blogs.Controllers { public IOrchardServices Services { get; set; } public ActionResult Create() { - //TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to create blogs"))) return new HttpUnauthorizedResult(); @@ -57,7 +56,6 @@ namespace Orchard.Blogs.Controllers { [HttpPost, ActionName("Create")] public ActionResult CreatePOST() { - //TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't create blog"))) return new HttpUnauthorizedResult(); @@ -79,7 +77,6 @@ namespace Orchard.Blogs.Controllers { } public ActionResult Edit(string blogSlug) { - //TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to edit blog"))) return new HttpUnauthorizedResult(); @@ -93,7 +90,6 @@ namespace Orchard.Blogs.Controllers { [HttpPost, ActionName("Edit")] public ActionResult EditPOST(string blogSlug) { - //TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't edit blog"))) return new HttpUnauthorizedResult(); @@ -112,7 +108,6 @@ namespace Orchard.Blogs.Controllers { [HttpPost] public ActionResult Remove(string blogSlug) { - //TODO: (erikpo) Might think about moving this to an ActionFilter/Attribute if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't delete blog"))) return new HttpUnauthorizedResult(); diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPartArchiveHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPartArchiveHandler.cs index 1574775b3..bad560846 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPartArchiveHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Handlers/BlogPartArchiveHandler.cs @@ -18,21 +18,21 @@ namespace Orchard.Blogs.Handlers { private static void RecalculateBlogArchive(IRepository blogArchiveRepository, IRepository commonRepository, BlogPostPart blogPostPart) { blogArchiveRepository.Flush(); - //INFO: (erikpo) Remove all current blog archive records + // remove all current blog archive records var blogArchiveRecords = from bar in blogArchiveRepository.Table where bar.BlogPart == blogPostPart.BlogPart.Record select bar; blogArchiveRecords.ToList().ForEach(blogArchiveRepository.Delete); - //INFO: (erikpo) Get all blog posts for the current blog + // get all blog posts for the current blog var postsQuery = from bpr in commonRepository.Table where bpr.ContentItemRecord.ContentType.Name == "BlogPost" && bpr.Container.Id == blogPostPart.BlogPart.Record.Id orderby bpr.PublishedUtc select bpr; - //INFO: (erikpo) Create a dictionary of all the year/month combinations and their count of posts that are published in this blog + // create a dictionary of all the year/month combinations and their count of posts that are published in this blog var inMemoryBlogArchives = new Dictionary(postsQuery.Count()); foreach (var post in postsQuery) { if (!post.PublishedUtc.HasValue) @@ -46,7 +46,7 @@ namespace Orchard.Blogs.Handlers { inMemoryBlogArchives[key] = 1; } - //INFO: (erikpo) Create the new blog archive records based on the in memory values + // create the new blog archive records based on the in memory values foreach (KeyValuePair item in inMemoryBlogArchives) { blogArchiveRepository.Create(new BlogPartArchiveRecord {BlogPart = blogPostPart.BlogPart.Record, Year = item.Key.Year, Month = item.Key.Month, PostCount = item.Value}); } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPart.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPart.cs index 09bffdedc..7aec67522 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Models/BlogPart.cs @@ -9,7 +9,6 @@ namespace Orchard.Blogs.Models { set { this.As().Title = value; } } - //TODO: (erikpo) Need a data type for slug public string Slug { get { return this.As().Slug; } set { this.As().Slug = value; } diff --git a/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs b/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs index 8af130861..d4bf700da 100644 --- a/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs +++ b/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs @@ -195,7 +195,6 @@ namespace Orchard.Mvc.Html { return value.HasValue ? htmlHelper.DateTimeRelative(value.Value, T) : defaultIfNull; } - //TODO: (erikpo) This method needs localized public static LocalizedString DateTimeRelative(this HtmlHelper htmlHelper, DateTime value, Localizer T) { var time = htmlHelper.Resolve().UtcNow - value; From a49112c177912995686c774175c07d8bc5e049ec Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 14 Oct 2010 16:40:33 -0700 Subject: [PATCH 2/5] Fixing fix --HG-- branch : dev --- src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs index 4356be02a..4827bb8c9 100644 --- a/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs +++ b/src/Orchard.Web/Core/Routable/Drivers/RoutePartDriver.cs @@ -83,7 +83,8 @@ namespace Orchard.Core.Routable.Drivers { part.Slug = model.Slug; if ( !_routableService.IsSlugValid(part.Slug) ) { - if ( ( part.Slug ?? String.Empty ).Trim().EndsWith(".") ) { + var slug = (part.Slug ?? String.Empty); + if ( slug.StartsWith(".") || slug.EndsWith(".") ) { updater.AddModelError("Routable.Slug", T("The \".\" can't be used around routes.")); } else { From ff91690cfb73babcd54a8d341f145a94f505ec1f Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 14 Oct 2010 16:55:09 -0700 Subject: [PATCH 3/5] Adding a test for slugs --HG-- branch : dev --- .../Routable/Services/RoutableServiceTests.cs | 7 +++++++ src/Orchard.Web/Core/Routable/Services/RoutableService.cs | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs index c83dbceb7..3d02cc9af 100644 --- a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs +++ b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs @@ -84,6 +84,13 @@ namespace Orchard.Core.Tests.Routable.Services { Assert.That(_routableService.IsSlugValid("some/page"), Is.True); } + [Test] + public void DotsAroundSlugAreAllowed() { + Assert.That(_routableService.IsSlugValid(".slug"), Is.False); + Assert.That(_routableService.IsSlugValid("slug."), Is.False); + Assert.That(_routableService.IsSlugValid("slug.slug"), Is.True); + } + [Test] public void EmptySlugsShouldBeConsideredValid() { // so that automatic generation on Publish occurs diff --git a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs index 0c013e1c1..b5403aa88 100644 --- a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs +++ b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs @@ -66,13 +66,7 @@ namespace Orchard.Core.Routable.Services { } public bool IsSlugValid(string slug) { - slug = (slug ?? String.Empty).Trim(); - return !( SlugHasProhibitedChard(slug) || slug.StartsWith(".") || slug.EndsWith(".") ); - } - - public bool SlugHasProhibitedChard(string slug) { - // see http://tools.ietf.org/html/rfc3987 for prohibited chars - return Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s]+$"); + return String.IsNullOrWhiteSpace(slug) || Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s]+$") && !(slug.StartsWith(".") || slug.EndsWith(".")); } public bool ProcessSlug(RoutePart part) { From 0483275d3615abf40bfe678fd549ab1fcccd6454 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 14 Oct 2010 17:14:58 -0700 Subject: [PATCH 4/5] Corrected ContentType List action --HG-- branch : dev --- .../Modules/Orchard.ContentTypes/Controllers/AdminController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs index 916f4160c..0e8f9ab48 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs @@ -27,7 +27,7 @@ namespace Orchard.ContentTypes.Controllers { #region Types public ActionResult List() { - return View(new ListContentTypesViewModel { + return View("List", new ListContentTypesViewModel { Types = _contentDefinitionService.GetTypes() }); } From defe72cf52f821faa46f91e3bbb6bce35a3603ee Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Thu, 14 Oct 2010 17:16:41 -0700 Subject: [PATCH 5/5] No Cassini for new theme container proj --HG-- branch : dev --- src/Orchard.Web/Themes/Orchard.Themes.csproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Themes/Orchard.Themes.csproj b/src/Orchard.Web/Themes/Orchard.Themes.csproj index c9a43d947..8f8b9f150 100644 --- a/src/Orchard.Web/Themes/Orchard.Themes.csproj +++ b/src/Orchard.Web/Themes/Orchard.Themes.csproj @@ -243,9 +243,8 @@ False - False - - + True + http://orchard.codeplex.com False