From 5f95575141e37ef772639eab1e88539281da8c50 Mon Sep 17 00:00:00 2001 From: agrath Date: Thu, 26 Jul 2012 15:36:34 -1200 Subject: [PATCH 01/26] Fixed a NRE in FileHandlerData when user has not updated umbracoSettings.config to add the new /settings/content/imaging/autoFillImageProperties node --- .../businesslogic/datatype/FileHandlerData.cs | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index 5f2262cb6e..0b856bf733 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -83,28 +83,31 @@ namespace umbraco.cms.businesslogic.datatype // check for auto fill of other properties (width, height, extension and filesize) string propertyTypeAlias = new Property(PropertyId).PropertyType.Alias; - XmlNode uploadFieldConfigNode = - UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( - string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); - if (uploadFieldConfigNode != null) + if (UmbracoSettings.ImageAutoFillImageProperties != null) { - // get the current document - Content content = Content.GetContentFromVersion(Version); - // only add dimensions to web images - if (um.SupportsResizing) + XmlNode uploadFieldConfigNode = + UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( + string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); + if (uploadFieldConfigNode != null) { - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", - um.GetDimensions().Item1); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", - um.GetDimensions().Item2); + // get the current document + Content content = Content.GetContentFromVersion(Version); + // only add dimensions to web images + if (um.SupportsResizing) + { + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", + um.GetDimensions().Item1); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", + um.GetDimensions().Item2); + } + else + { + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); + } + updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", um.Length); + updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", um.Extension); } - else - { - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); - } - updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", um.Length); - updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", um.Extension); } base.Value = um.LocalName; From fffbd960c1dee6beed9ed2c81b2220650089219f Mon Sep 17 00:00:00 2001 From: agrath Date: Thu, 26 Jul 2012 16:05:44 -1200 Subject: [PATCH 02/26] Another NRE that I missed --- .../businesslogic/datatype/FileHandlerData.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index 0b856bf733..f34677c4dc 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -132,18 +132,21 @@ namespace umbraco.cms.businesslogic.datatype private void clearRelatedValues() { string propertyTypeAlias = new Property(PropertyId).PropertyType.Alias; - XmlNode uploadFieldConfigNode = - UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( - string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); - if (uploadFieldConfigNode != null) + if (UmbracoSettings.ImageAutoFillImageProperties != null) { - // get the current document - Content content = Content.GetContentFromVersion(Version); - // only add dimensions to web images - updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", String.Empty); - updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", String.Empty); + XmlNode uploadFieldConfigNode = + UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode( + string.Format("uploadField [@alias = \"{0}\"]", propertyTypeAlias)); + if (uploadFieldConfigNode != null) + { + // get the current document + Content content = Content.GetContentFromVersion(Version); + // only add dimensions to web images + updateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", String.Empty); + updateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", String.Empty); + } } } From c104121ff1f8d75afc8092c389ecfea3bc899cbb Mon Sep 17 00:00:00 2001 From: Casey Neehouse Date: Tue, 7 Aug 2012 22:42:40 +0400 Subject: [PATCH 03/26] Inserting additional tracing to RazorMacroEngine Execute methods. --- .../RazorCore/RazorMacroEngine.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs index b8f46be9b2..7ea5cc9928 100644 --- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs +++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs @@ -77,12 +77,19 @@ namespace umbraco.MacroEngines var contextWrapper = new HttpContextWrapper(context); //inject http context - for request response + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Context (file: {0})", macro.Name)); razorWebPage.Context = contextWrapper; + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Context (file: {0})", macro.Name)); //Inject Macro Model And Parameters if (razorWebPage is IMacroContext) { + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Boxing Macro Script MacroContext (file: {0})", macro.Name)); var razorMacro = (IMacroContext)razorWebPage; + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Boxing Macro Script MacroContext (file: {0})", macro.Name)); + + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Model (file: {0})", macro.Name)); razorMacro.SetMembers(macro, currentPage); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Model (file: {0})", macro.Name)); } } @@ -106,11 +113,16 @@ namespace umbraco.MacroEngines return String.Empty; //No File Location var razorWebPage = CompileAndInstantiate(fileLocation); + + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Loading Macro Script Context (file: {0})", macro.Name)); InjectContext(razorWebPage, macro, currentPage); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Loading Macro Script Context (file: {0})", macro.Name)); //Output Razor To String var output = new StringWriter(); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Executing Macro Script (file: {0})", macro.Name)); razorWebPage.ExecutePageHierarchy(new WebPageContext(contextWrapper, razorWebPage, null), output); + HttpContext.Current.Trace.Write("umbracoMacro", string.Format("Done Executing Macro Script (file: {0})", macro.Name)); return output.ToString(); } From f97c171a972a076b740e5bb6e8d184f727210fbe Mon Sep 17 00:00:00 2001 From: Casey Neehouse Date: Wed, 8 Aug 2012 00:07:03 +0400 Subject: [PATCH 04/26] Changes to the GetDocumentsForExpiration method to only unpublish nodes set to published rather than newest. --- src/umbraco.cms/businesslogic/web/Document.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 93e7d122ca..79352d52cd 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -646,7 +646,7 @@ namespace umbraco.cms.businesslogic.web { ArrayList docs = new ArrayList(); IRecordsReader dr = - SqlHelper.ExecuteReader("select distinct nodeId from cmsDocument where newest = 1 and not expireDate is null and expireDate <= @today", + SqlHelper.ExecuteReader("select distinct nodeId from cmsDocument where published = 1 and not expireDate is null and expireDate <= @today", SqlHelper.CreateParameter("@today", DateTime.Now)); while (dr.Read()) docs.Add(dr.GetInt("nodeId")); From 493e5c7734b9cda84fbc9fe95f172c020d54a62c Mon Sep 17 00:00:00 2001 From: pgregorynz Date: Tue, 7 Aug 2012 18:20:59 -1000 Subject: [PATCH 05/26] Resolve issue #30937. Fixes problem with iFileHanderData in intranet environ in IE. --- .../businesslogic/datatype/FileHandlerData.cs | 17 +++++++++++++++-- .../uploadfield/uploadField.cs | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index 5f2262cb6e..c2ed78c2a3 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text.RegularExpressions; using System.Web; using System.Xml; using umbraco.cms.businesslogic.Files; @@ -32,13 +33,13 @@ namespace umbraco.cms.businesslogic.datatype if (value is HttpPostedFile) { var file = value as HttpPostedFile; - name = file.FileName; + name = SafeFileName(file.FileName.Substring(file.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, file.FileName.Length - file.FileName.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower()); fileStream = file.InputStream; } else if (value is HttpPostedFileBase) { var file = value as HttpPostedFileBase; - name = file.FileName; + name = SafeFileName(file.FileName.Substring(file.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, file.FileName.Length - file.FileName.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower()); fileStream = file.InputStream; } else if (value is HttpPostedFileWrapper) @@ -126,6 +127,18 @@ namespace umbraco.cms.businesslogic.datatype } } + /// + /// Check to see if filename passed has any special chars in it and strips them to create a safe filename. Used to overcome an issue when Umbraco is used in IE in an intranet environment. + /// + /// The filename passed to the file handler from the upload field. + /// A safe filename without any path specific chars. + private string SafeFileName(string filePath) + { + if (!String.IsNullOrEmpty(filePath)) + return Regex.Replace(filePath, @"[^a-zA-Z0-9\-\.\/\:]{1}", "_"); + return String.Empty; + } + private void clearRelatedValues() { string propertyTypeAlias = new Property(PropertyId).PropertyType.Alias; diff --git a/src/umbraco.editorControls/uploadfield/uploadField.cs b/src/umbraco.editorControls/uploadfield/uploadField.cs index f974bc4787..4b57d3e78c 100644 --- a/src/umbraco.editorControls/uploadfield/uploadField.cs +++ b/src/umbraco.editorControls/uploadfield/uploadField.cs @@ -161,6 +161,7 @@ namespace umbraco.editorControls #endregion + [Obsolete("This method is now obsolete due to a change in the way that files are handled. If you need to check if a URL for an uploaded file is safe you should implement your own as this method will be removed in a future version", false)] public string SafeUrl(string url) { if (!String.IsNullOrEmpty(url)) From a989ea77ff5d4e1ef22b60431fedc55bfb1d1d22 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Wed, 8 Aug 2012 08:37:07 -0100 Subject: [PATCH 06/26] Switched DMU web service to support XML and JSON so can be used by media dashboard aswell Added dmu.ashx file in old plugin folder to add backwards compatability --- .../TheOutfield/DesktopMediaUploader/dmu.ashx | 1 + .../FolderBrowser/Js/folderbrowser.js | 31 +++- src/Umbraco.Web/UI/Controls/FolderBrowser.cs | 19 ++- .../WebServices/FolderBrowserService.cs | 12 +- .../umbraco/webservices/MediaUploader.ashx.cs | 153 +++++++++++++----- 5 files changed, 160 insertions(+), 56 deletions(-) create mode 100644 src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx diff --git a/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx b/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx new file mode 100644 index 0000000000..3dab7a3f91 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/plugins/TheOutfield/DesktopMediaUploader/dmu.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" CodeBehind="MediaUploader.ashx.cs" Class="umbraco.presentation.umbraco.webservices.MediaUploader" %> diff --git a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js index cb380ba028..8d65f76e8f 100644 --- a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js +++ b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js @@ -4,7 +4,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); (function ($, Base, window, document, undefined) { var itemMappingOptions = { - 'create': function(o) { + 'create': function (o) { var item = ko.mapping.fromJS(o.data); item.selected = ko.observable(false); item.toggleSelected = function (itm, e) { @@ -115,6 +115,14 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); items: ko.observableArray([]), queued: ko.observableArray([]) }); + + self._viewModel.filtered = ko.computed(function () { + return self._viewModel.items(); + return ko.utils.arrayFilter(this.items(), function (item) { + return item.Name().toLowerCase().indexOf(self._viewModel.filterTerm()) > -1 || + item.Tags().toLowerCase().indexOf(self._viewModel.filterTerm()) > -1; + }); + }, self._viewModel); self._viewModel.selected = ko.computed(function() { return ko.utils.arrayFilter(this.items(), function(item) { @@ -301,15 +309,16 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); start: function (e, ui) { // Add dragging class to container $(".umbFolderBrowser .items").addClass("ui-sortable-dragging"); - - $(".umbFolderBrowser .items .ui-sortable-helper span").removeAttr("data-bind").text("Moving 1 item"); }, - update: function (e, ui) { + update: function (e, ui) + { + // Can't sort when filtered so just return + if (self._viewModel.filterTerm().length > 0) + return; + //var oldIndex = self._viewModel.items.indexOf(self._viewModel.tempItem()); var newIndex = ui.item.index(); - //TODO: Don't allow sorting on a filtered view - $(".umbFolderBrowser .items .selected").sort(function (a,b) { return parseInt($(a).data("order")) > parseInt($(b).data("order")) ? 1 : -1; }).each(function(idx, itm) { @@ -327,7 +336,15 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); stop: function (e, ui) { // Remove dragging class from container $(".umbFolderBrowser .items").removeClass("ui-sortable-dragging"); - //TODO: Update on server + + if (self._viewModel.filterTerm().length > 0) { + $(this).sortable("cancel"); + alert("Can't sort items which have been filtered"); + } + else + { + //TODO: Update on server + } } }); }, diff --git a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs index 272d83c8bb..cc0c4467bd 100644 --- a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs +++ b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs @@ -1,10 +1,13 @@ using System; using System.Collections.Generic; using System.Text; +using System.Web; +using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using ClientDependency.Core; using umbraco.BasePages; +using umbraco.BusinessLogic; using umbraco.IO; using umbraco.cms.businesslogic.media; @@ -113,7 +116,7 @@ namespace Umbraco.Web.UI.Controls sb.Append("
Filter:
"); // Create thumbnails container - sb.Append("
    " + + sb.Append("
      " + "
    • " + "
    "); @@ -121,11 +124,21 @@ namespace Umbraco.Web.UI.Controls Controls.Add(panel); + var user = User.GetCurrent(); + var ticket = new FormsAuthenticationTicket(1, + user != null ? user.LoginName : "", + DateTime.Now, + DateTime.Now, + false, + ""); + Page.ClientScript.RegisterStartupScript(typeof(FolderBrowser), "RegisterFolderBrowsers", - string.Format("$(function () {{ $(\".umbFolderBrowser\").folderBrowser({{ umbracoPath : '{0}', basePath : '{1}' }}); }});", + string.Format("$(function () {{ $(\".umbFolderBrowser\").folderBrowser({{ umbracoPath : '{0}', basePath : '{1}', username: '{2}', ticket: '{3}' }}); }});", IOHelper.ResolveUrl(SystemDirectories.Umbraco), - IOHelper.ResolveUrl(SystemDirectories.Base)), + IOHelper.ResolveUrl(SystemDirectories.Base), + user != null ? user.LoginName : "", + FormsAuthentication.Encrypt(ticket)), true); } diff --git a/src/Umbraco.Web/WebServices/FolderBrowserService.cs b/src/Umbraco.Web/WebServices/FolderBrowserService.cs index ed281a7894..c4d44169c5 100644 --- a/src/Umbraco.Web/WebServices/FolderBrowserService.cs +++ b/src/Umbraco.Web/WebServices/FolderBrowserService.cs @@ -45,19 +45,21 @@ namespace Umbraco.Web.WebServices var fileUrl = fileProp != null ? fileProp.Value.ToString() : ""; var thumbUrl = ThumbnailProviderManager.Current.GetThumbnailUrl(fileUrl); - - data.Add(new + var item = new { Id = child.Id, Path = child.Path, Name = child.Text, + Tags = string.Join(",", Tag.GetTags(child.Id).Select(x => x.TagCaption)), MediaTypeAlias = child.ContentType.Alias, EditUrl = string.Format("editMedia.aspx?id={0}", child.Id), FileUrl = fileUrl, - ThumbnailUrl = !string.IsNullOrEmpty(thumbUrl) - ? thumbUrl + ThumbnailUrl = !string.IsNullOrEmpty(thumbUrl) + ? thumbUrl : IOHelper.ResolveUrl(SystemDirectories.Umbraco + "/images/thumbnails/" + child.ContentType.Thumbnail) - }); + }; + + data.Add(item); } return new JavaScriptSerializer().Serialize(data); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs index 8c23e383a6..bab33aaa09 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Text; using System.Web; using System.Web.Configuration; +using System.Web.Script.Serialization; using System.Web.Security; using System.Xml; +using System.Xml.Serialization; using umbraco.BusinessLogic; using umbraco.businesslogic.Exceptions; using umbraco.cms.businesslogic.media; @@ -25,75 +27,100 @@ namespace umbraco.presentation.umbraco.webservices public void ProcessRequest(HttpContext context) { - context.Response.Clear(); - context.Response.ContentType = @"text\xml"; - context.Response.Charset = "UTF-8"; - context.Response.Cache.SetCacheability(HttpCacheability.NoCache); - context.Response.Cache.SetAllowResponseInBrowserHistory(true); + MediaResponse response = null; - var xmlTextWriter = new XmlTextWriter(context.Response.OutputStream, Encoding.UTF8); - xmlTextWriter.WriteStartDocument(); - xmlTextWriter.WriteStartElement("response"); + var action = context.Request["action"]; - string action = context.Request["action"]; - - if (IsValidRequest(context, xmlTextWriter) && !string.IsNullOrEmpty(action)) + if (IsValidRequest(context) && !string.IsNullOrEmpty(action)) { switch (action.ToLower()) { case "config": - ProcessConfigRequest(context, xmlTextWriter); + response = ProcessConfigRequest(context); break; case "folderlist": - ProcessFolderListRequest(context, xmlTextWriter); + response = ProcessFolderListRequest(context); break; case "upload": - ProcessUploadRequest(context, xmlTextWriter); + response = ProcessUploadRequest(context); break; } } - xmlTextWriter.WriteEndElement(); - xmlTextWriter.WriteEndDocument(); - xmlTextWriter.Flush(); - xmlTextWriter.Close(); + // Set success flag + if (response != null) + response.success = true; + else + response = new MediaResponse { success = false }; + + context.Response.Clear(); + context.Response.Charset = "UTF-8"; + context.Response.Cache.SetCacheability(HttpCacheability.NoCache); + context.Response.Cache.SetAllowResponseInBrowserHistory(true); + + var format = context.Request["format"]; + switch (format) + { + case "json": + // Format as JSON + context.Response.ContentType = @"application/json"; + + context.Response.Write(new JavaScriptSerializer().Serialize(response)); + + break; + default: + // Format as XML + context.Response.ContentType = @"text/xml"; + + var serializer = new XmlSerializer(response.GetType()); + serializer.Serialize(context.Response.OutputStream, response); + + break; + } + context.Response.End(); } - public void ProcessConfigRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public ConfigResponse ProcessConfigRequest(HttpContext context) { - xmlTextWriter.WriteElementString("displayName", new User(context.Request["username"]).Name); - xmlTextWriter.WriteElementString("umbracoPath", VirtualPathUtility.ToAbsolute(GlobalSettings.Path)); - xmlTextWriter.WriteElementString("maxRequestLength", GetMaxRequestLength().ToString()); + return new ConfigResponse + { + displayName = new User(context.Request["username"]).Name, + umbracoPath = VirtualPathUtility.ToAbsolute(GlobalSettings.Path), + maxRequestLength = GetMaxRequestLength() + }; } - public void ProcessFolderListRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public FolderListResponse ProcessFolderListRequest(HttpContext context) { - xmlTextWriter.WriteStartElement("folder"); + var response = new FolderListResponse + { + folder = new FolderListItem() + }; var startMediaId = AuthenticatedUser.StartMediaId; if (startMediaId < 1) { - xmlTextWriter.WriteAttributeString("id", "-1"); - xmlTextWriter.WriteAttributeString("name", "Media"); + response.folder.id = -1; + response.folder.name = "Media"; - CreateMediaTree(Media.GetRootMedias(), xmlTextWriter); + CreateMediaTree(Media.GetRootMedias(), response.folder); } else { var root = new Media(startMediaId); - xmlTextWriter.WriteAttributeString("id", root.Id.ToString()); - xmlTextWriter.WriteAttributeString("name", root.Text); + response.folder.id = root.Id; + response.folder.name = root.Text; - CreateMediaTree(root.Children, xmlTextWriter); + CreateMediaTree(root.Children, response.folder); } - xmlTextWriter.WriteEndElement(); + return response; } - public void ProcessUploadRequest(HttpContext context, XmlTextWriter xmlTextWriter) + public UploadResponse ProcessUploadRequest(HttpContext context) { int parentNodeId; if (int.TryParse(context.Request["parentNodeId"], out parentNodeId) && context.Request.Files.Count > 0) @@ -158,11 +185,13 @@ namespace umbraco.presentation.umbraco.webservices // log error Log.Add(LogTypes.Error, -1, "Parent node id is in incorrect format"); } + + return new UploadResponse(); } #region Helper Methods - private bool IsValidRequest(HttpContext context, XmlTextWriter xmlTextWriter) + private bool IsValidRequest(HttpContext context) { // check for secure connection if (GlobalSettings.UseSSL && !context.Request.IsSecureConnection) @@ -196,25 +225,25 @@ namespace umbraco.presentation.umbraco.webservices AuthenticatedUser = user; } - xmlTextWriter.WriteAttributeString("success", isValid.ToString().ToLower()); - return isValid; } - private void CreateMediaTree(IEnumerable nodes, XmlWriter xmlTextWriter) + private void CreateMediaTree(IEnumerable nodes, FolderListItem folder) { foreach (var media in nodes.Where(media => media != null && media.ContentType != null && media.ContentType.Alias == "Folder")) { - xmlTextWriter.WriteStartElement("folder"); - xmlTextWriter.WriteAttributeString("id", media.Id.ToString()); - xmlTextWriter.WriteAttributeString("name", media.Text); + var subFolder = new FolderListItem + { + id = media.Id, + name = media.Text + }; if (media.HasChildren) { - CreateMediaTree(media.Children, xmlTextWriter); + CreateMediaTree(media.Children, subFolder); } - xmlTextWriter.WriteEndElement(); + folder.folders.Add(subFolder); } } @@ -266,4 +295,46 @@ namespace umbraco.presentation.umbraco.webservices #endregion } + + public class MediaResponse + { + [XmlAttribute] + public bool success { get; set; } + } + + [XmlRoot("response")] + public class ConfigResponse : MediaResponse + { + public string displayName { get; set; } + public string umbracoPath { get; set; } + public int maxRequestLength { get; set; } + } + + [XmlRoot("response")] + public class FolderListResponse : MediaResponse + { + public FolderListItem folder { get; set; } + } + + [XmlType("folder")] + public class FolderListItem + { + [XmlAttribute] + public int id { get; set; } + + [XmlAttribute] + public string name { get; set; } + + [XmlElement("folder")] + public List folders { get; set; } + + public FolderListItem() + { + folders = new List(); + } + } + + [XmlRoot("response")] + public class UploadResponse : MediaResponse + { } } \ No newline at end of file From ccd56f5594d0eacfe24b643497110295a7b00a8d Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Wed, 8 Aug 2012 09:08:09 -0100 Subject: [PATCH 07/26] Hooked up support for overwriting Made DMU web service check for logged in user if no credentials are passed in --- .../FolderBrowser/Js/folderbrowser.js | 12 ++++++------ src/Umbraco.Web/UI/Controls/FolderBrowser.cs | 14 ++------------ .../umbraco/webservices/MediaUploader.ashx.cs | 8 +++++++- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js index 8d65f76e8f..b4d8b7bf77 100644 --- a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js +++ b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js @@ -170,10 +170,10 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); var overlay = $("
    " + "
    " + instructions + - "
    " + + "" + "" + "" + - "" + + "" + "
    " + "
    • " + "" + @@ -181,8 +181,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); "" + "
    " + "" + - "" + - "" + + "" + + "" + "Cancel" + "
    " + "
    "); @@ -243,8 +243,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); $("#fileupload").fileUploader("uploadAll"); }); - $(".upload-overlay #overwriteExisting").click(function() { - $("input[name=overwriteExisting]").val($(this).is(":checked")); + $(".upload-overlay #replaceExisting").click(function() { + $("input[name=replaceExisting]").val($(this).is(":checked")); }); $(".upload-overlay .cancel").click(function (e) { diff --git a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs index cc0c4467bd..3b6db75e7b 100644 --- a/src/Umbraco.Web/UI/Controls/FolderBrowser.cs +++ b/src/Umbraco.Web/UI/Controls/FolderBrowser.cs @@ -124,21 +124,11 @@ namespace Umbraco.Web.UI.Controls Controls.Add(panel); - var user = User.GetCurrent(); - var ticket = new FormsAuthenticationTicket(1, - user != null ? user.LoginName : "", - DateTime.Now, - DateTime.Now, - false, - ""); - Page.ClientScript.RegisterStartupScript(typeof(FolderBrowser), "RegisterFolderBrowsers", - string.Format("$(function () {{ $(\".umbFolderBrowser\").folderBrowser({{ umbracoPath : '{0}', basePath : '{1}', username: '{2}', ticket: '{3}' }}); }});", + string.Format("$(function () {{ $(\".umbFolderBrowser\").folderBrowser({{ umbracoPath : '{0}', basePath : '{1}' }}); }});", IOHelper.ResolveUrl(SystemDirectories.Umbraco), - IOHelper.ResolveUrl(SystemDirectories.Base), - user != null ? user.LoginName : "", - FormsAuthentication.Encrypt(ticket)), + IOHelper.ResolveUrl(SystemDirectories.Base)), true); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs index bab33aaa09..ae28cc4d0a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs @@ -144,7 +144,8 @@ namespace umbraco.presentation.umbraco.webservices } // Check whether to replace existing - bool replaceExisting = (context.Request["replaceExisting"] == "1"); + var parsed = false; + bool replaceExisting = (context.Request["replaceExisting"] == "1" || (bool.TryParse(context.Request["replaceExisting"], out parsed) && parsed)); // loop through uploaded files for (var j = 0; j < context.Request.Files.Count; j++) @@ -224,6 +225,11 @@ namespace umbraco.presentation.umbraco.webservices if (isValid) AuthenticatedUser = user; } + else if (User.GetCurrent() != null) + { + isValid = true; + AuthenticatedUser = User.GetCurrent(); + } return isValid; } From 44a15900c7b4f9539c57e38ef8c5a97adcccfef9 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Wed, 8 Aug 2012 09:26:25 -0100 Subject: [PATCH 08/26] Removed upload method from FolderBrowserService as re-using the DMU web service instead --- src/Umbraco.Web/WebServices/FolderBrowserService.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Umbraco.Web/WebServices/FolderBrowserService.cs b/src/Umbraco.Web/WebServices/FolderBrowserService.cs index c4d44169c5..db5333d4a7 100644 --- a/src/Umbraco.Web/WebServices/FolderBrowserService.cs +++ b/src/Umbraco.Web/WebServices/FolderBrowserService.cs @@ -86,14 +86,6 @@ namespace Umbraco.Web.WebServices }); } - [RestExtensionMethod(returnXml = false)] - public static string Upload(int parentId) - { - return new JavaScriptSerializer().Serialize(new { - success = true - }); - } - [RestExtensionMethod(returnXml = false)] public static string UpdateSortOrder(int parentId, IDictionary map) { From 37ddb9223f79a3553245cf23e4f3514f061461b4 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Wed, 8 Aug 2012 11:54:52 -0100 Subject: [PATCH 09/26] Added friendly name support to DMU webservice to allow uploaded files to set the media items friendly name --- .../umbraco/webservices/MediaUploader.ashx.cs | 6 ++++-- .../businesslogic/media/IMediaFactory.cs | 2 ++ .../businesslogic/media/MediaFactory.cs | 2 ++ .../media/UmbracoMediaFactory.cs | 19 ++++++++++++------- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs index ae28cc4d0a..e2dc9302e3 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/MediaUploader.ashx.cs @@ -159,16 +159,18 @@ namespace umbraco.presentation.umbraco.webservices var postedMediaFile = new PostedMediaFile { FileName = uploadFile.FileName, + DisplayName = context.Request["name"], ContentType = uploadFile.ContentType, ContentLength = uploadFile.ContentLength, - InputStream = uploadFile.InputStream + InputStream = uploadFile.InputStream, + ReplaceExisting = replaceExisting }; // Get concrete MediaFactory var factory = MediaFactory.GetMediaFactory(parentNodeId, postedMediaFile, AuthenticatedUser); // Handle media Item - var media = factory.HandleMedia(parentNodeId, postedMediaFile, AuthenticatedUser, replaceExisting); + var media = factory.HandleMedia(parentNodeId, postedMediaFile, AuthenticatedUser); } } diff --git a/src/umbraco.cms/businesslogic/media/IMediaFactory.cs b/src/umbraco.cms/businesslogic/media/IMediaFactory.cs index f3eb25d3e1..50c589765f 100644 --- a/src/umbraco.cms/businesslogic/media/IMediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/IMediaFactory.cs @@ -14,6 +14,8 @@ namespace umbraco.cms.businesslogic.media bool CanHandleMedia(int parentNodeId, PostedMediaFile postedFile, User user); Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user); + + [Obsolete("Use HandleMedia(int, PostedMediaFile, User) and set the ReplaceExisting property on PostedMediaFile instead")] Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting); } } diff --git a/src/umbraco.cms/businesslogic/media/MediaFactory.cs b/src/umbraco.cms/businesslogic/media/MediaFactory.cs index e44d957889..4909b5015b 100644 --- a/src/umbraco.cms/businesslogic/media/MediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/MediaFactory.cs @@ -71,9 +71,11 @@ namespace umbraco.cms.businesslogic.media public class PostedMediaFile { public string FileName { get; set; } + public string DisplayName { get; set; } public string ContentType { get; set; } public int ContentLength { get; set; } public Stream InputStream { get; set; } + public bool ReplaceExisting { get; set; } public void SaveAs(string filename) { diff --git a/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs b/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs index b7f4560a99..bf916336fc 100644 --- a/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs +++ b/src/umbraco.cms/businesslogic/media/UmbracoMediaFactory.cs @@ -31,17 +31,14 @@ namespace umbraco.cms.businesslogic.media } public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user) - { - return HandleMedia(parentNodeId, postedFile, user, false); - } - - public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting) { // Check to see if a file exists Media media; - string mediaName = extractTitleFromFileName(postedFile.FileName); + string mediaName = !string.IsNullOrEmpty(postedFile.DisplayName) + ? postedFile.DisplayName + : extractTitleFromFileName(postedFile.FileName); - if (replaceExisting && TryFindExistingMedia(parentNodeId, postedFile.FileName, out media)) + if (postedFile.ReplaceExisting && TryFindExistingMedia(parentNodeId, postedFile.FileName, out media)) { // Do nothing as existing media is returned } @@ -61,6 +58,14 @@ namespace umbraco.cms.businesslogic.media return media; } + [Obsolete("Use HandleMedia(int, PostedMediaFile, User) and set the ReplaceExisting property on PostedMediaFile instead")] + public Media HandleMedia(int parentNodeId, PostedMediaFile postedFile, User user, bool replaceExisting) + { + postedFile.ReplaceExisting = replaceExisting; + + return HandleMedia(parentNodeId, postedFile, user); + } + public abstract void DoHandleMedia(Media media, PostedMediaFile uploadedFile, User user); #region Helper Methods From cd5688284528066a589afce09e209222a7ddfa31 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Wed, 8 Aug 2012 12:09:22 -0100 Subject: [PATCH 10/26] Media grid now refreshes after uploads have completed --- .../umbraco_client/FolderBrowser/Js/folderbrowser.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js index b4d8b7bf77..cdad318d0f 100644 --- a/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js +++ b/src/Umbraco.Web.UI/umbraco_client/FolderBrowser/Js/folderbrowser.js @@ -234,6 +234,9 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); }, onProgress: function (data) { data.context.progress(data.progress); + }, + onDoneAll: function () { + self._getChildNodes(); } }); From 39d0f95c2ebac2a79ca180b04fab588bf684e4ff Mon Sep 17 00:00:00 2001 From: hartvig Date: Thu, 9 Aug 2012 06:41:30 -0200 Subject: [PATCH 11/26] Fixes null exception issue when using 'umbracoFile' as the alias of an upload property. Work items: 30980 --- src/umbraco.cms/businesslogic/Content.cs | 4 +++- .../web.Template.UMBRACOELISE.Debug.config | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/umbraco.cms/businesslogic/Content.cs b/src/umbraco.cms/businesslogic/Content.cs index a94b6e45dc..fe7d5fdb25 100644 --- a/src/umbraco.cms/businesslogic/Content.cs +++ b/src/umbraco.cms/businesslogic/Content.cs @@ -512,6 +512,9 @@ namespace umbraco.cms.businesslogic Guid newVersion = Guid.NewGuid(); bool tempHasVersion = hasVersion(); + + // we need to ensure that a version in the db exist before we add related data + SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values (" + this.Id + ",'" + newVersion + "')"); foreach (propertytype.PropertyType pt in this.ContentType.PropertyTypes) { object oldValue = ""; @@ -526,7 +529,6 @@ namespace umbraco.cms.businesslogic property.Property p = this.addProperty(pt, newVersion); if (oldValue != null && oldValue.ToString() != "") p.Value = oldValue; } - SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values (" + this.Id + ",'" + newVersion + "')"); this.Version = newVersion; return newVersion; } diff --git a/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config b/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config index 4b2e4bb8da..124bf94e8e 100644 --- a/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config +++ b/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config @@ -17,9 +17,9 @@ + value="server=.\sqlexpress;database=481;user id=DBUSER;password=DBPASSWORD"/> + value="4.8.1"/> From 28722be34c6fd97461637ade2560da089d549b36 Mon Sep 17 00:00:00 2001 From: hartvig Date: Thu, 9 Aug 2012 07:28:55 -0200 Subject: [PATCH 12/26] Fixes issue with automatic image resizing in tinyMCE. Work items: 30963 --- .../businesslogic/Files/UmbracoFile.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs index 1328eb9892..ec1d7666b4 100644 --- a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs +++ b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs @@ -174,7 +174,7 @@ namespace umbraco.cms.businesslogic.Files string fileNameThumb = DoResize(width, height, 0, String.Empty); - return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length); + return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length-1); } public string Resize(int maxWidthHeight, string fileNameAddition) @@ -197,7 +197,7 @@ namespace umbraco.cms.businesslogic.Files string fileNameThumb = String.IsNullOrEmpty(fileNameAddition) ? string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf("."))) : string.Format("{0}_{1}.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf(".")), fileNameAddition); - generateThumbnail( + fileNameThumb = generateThumbnail( image, maxWidthHeight, width, @@ -206,7 +206,7 @@ namespace umbraco.cms.businesslogic.Files _extension, fileNameThumb, maxWidthHeight == 0 - ); + ).FileName; image.Dispose(); return fileNameThumb; } @@ -220,7 +220,7 @@ namespace umbraco.cms.businesslogic.Files } - private System.Tuple generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName, bool useFixedDimensions) + private ResizedImage generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName, bool useFixedDimensions) { // Generate thumbnail float f = 1; @@ -267,14 +267,35 @@ namespace umbraco.cms.businesslogic.Files ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L); // Save the new image using the dimensions of the image - bp.Save(thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh)), codec, ep); + string newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", + string.Format("{0}x{1}", widthTh, heightTh)); + bp.Save(newFileName, codec, ep); bp.Dispose(); g.Dispose(); - return new System.Tuple(widthTh, heightTh); + return new ResizedImage(widthTh, heightTh, newFileName); } } + + internal class ResizedImage + { + public ResizedImage() + { + + } + + public ResizedImage(int width, int height, string fileName) + { + Width = width; + Height = height; + FileName = fileName; + } + + public int Width { get; set; } + public int Height { get; set; } + public string FileName { get; set; } + } } From 9531a3f37a79b751af180780ab65f1a310a7100c Mon Sep 17 00:00:00 2001 From: hartvig Date: Thu, 9 Aug 2012 10:06:10 -0200 Subject: [PATCH 13/26] Updates to login cookies --- .../BasePages/BasePage.cs | 224 +++++++++++------- 1 file changed, 141 insertions(+), 83 deletions(-) diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs index c5eb2ce75d..b0e367ebe0 100644 --- a/src/umbraco.businesslogic/BasePages/BasePage.cs +++ b/src/umbraco.businesslogic/BasePages/BasePage.cs @@ -2,22 +2,25 @@ using System; using System.Data; using System.Web; using System.Linq; +using System.Web.Security; using umbraco.BusinessLogic; using umbraco.DataLayer; using umbraco.IO; using System.Web.UI; -namespace umbraco.BasePages { +namespace umbraco.BasePages +{ /// /// umbraco.BasePages.BasePage is the default page type for the umbraco backend. /// The basepage keeps track of the current user and the page context. But does not /// Restrict access to the page itself. /// The keep the page secure, the umbracoEnsuredPage class should be used instead /// - public class BasePage : System.Web.UI.Page { + public class BasePage : System.Web.UI.Page + { private User _user; private bool _userisValidated = false; - private ClientTools m_clientTools; + private ClientTools m_clientTools; // ticks per minute 600,000,000 private static long _ticksPrMinute = 600000000; @@ -42,70 +45,78 @@ namespace umbraco.BasePages { /// Gets the SQL helper. /// /// The SQL helper. - protected static ISqlHelper SqlHelper { + protected static ISqlHelper SqlHelper + { get { return umbraco.BusinessLogic.Application.SqlHelper; } } /// /// Initializes a new instance of the class. /// - public BasePage() { + public BasePage() + { } - /// - /// Returns the current BasePage for the current request. - /// This assumes that the current page is a BasePage, otherwise, returns null; - /// - public static BasePage Current - { - get - { - return HttpContext.Current.CurrentHandler as BasePage; - } - } - - /// - /// Returns a refernce of an instance of ClientTools for access to the pages client API - /// - public ClientTools ClientTools - { - get - { - if (m_clientTools == null) - m_clientTools = new ClientTools(this); - return m_clientTools; - } - } - - [Obsolete("Use ClientTools instead")] - public void RefreshPage(int Seconds) - { - ClientTools.RefreshAdmin(Seconds); + /// + /// Returns the current BasePage for the current request. + /// This assumes that the current page is a BasePage, otherwise, returns null; + /// + public static BasePage Current + { + get + { + return HttpContext.Current.CurrentHandler as BasePage; + } } - private void validateUser() { - if ((umbracoUserContextID != "")) { + /// + /// Returns a refernce of an instance of ClientTools for access to the pages client API + /// + public ClientTools ClientTools + { + get + { + if (m_clientTools == null) + m_clientTools = new ClientTools(this); + return m_clientTools; + } + } + + [Obsolete("Use ClientTools instead")] + public void RefreshPage(int Seconds) + { + ClientTools.RefreshAdmin(Seconds); + } + + private void validateUser() + { + if ((umbracoUserContextID != "")) + { uid = GetUserId(umbracoUserContextID); timeout = GetTimeout(umbracoUserContextID); - if (timeout > DateTime.Now.Ticks) { + if (timeout > DateTime.Now.Ticks) + { _user = BusinessLogic.User.GetUser(uid); // Check for console access if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext.Current))) { throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator"); - } + } else { _userisValidated = true; updateLogin(); } - } else { + } + else + { throw new ArgumentException("User has timed out!!"); } - } else + } + else throw new ArgumentException("The user has no umbraco contextid - try logging in"); } @@ -114,9 +125,12 @@ namespace umbraco.BasePages { /// /// The umbraco user context ID. /// - public static int GetUserId(string umbracoUserContextID) { - try { - if (System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID] == null) { + public static int GetUserId(string umbracoUserContextID) + { + try + { + if (System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID] == null) + { System.Web.HttpRuntime.Cache.Insert( "UmbracoUserContext" + umbracoUserContextID, SqlHelper.ExecuteScalar("select userID from umbracoUserLogins where contextID = @contextId", @@ -131,7 +145,9 @@ namespace umbraco.BasePages { return (int)System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID]; - } catch { + } + catch + { return -1; } } @@ -143,7 +159,8 @@ namespace umbraco.BasePages { /// /// The umbraco user context ID. /// - public static bool ValidateUserContextID(string currentUmbracoUserContextID) { + public static bool ValidateUserContextID(string currentUmbracoUserContextID) + { if ((currentUmbracoUserContextID != "")) { int uid = GetUserId(currentUmbracoUserContextID); @@ -153,14 +170,16 @@ namespace umbraco.BasePages { { return true; } - + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Logout, BusinessLogic.User.GetUser(uid), -1, ""); } return false; } - private static long GetTimeout(string umbracoUserContextID) { - if (System.Web.HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID] == null) { + private static long GetTimeout(string umbracoUserContextID) + { + if (System.Web.HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID] == null) + { System.Web.HttpRuntime.Cache.Insert( "UmbracoUserContextTimeout" + umbracoUserContextID, GetTimeout(true), @@ -171,8 +190,8 @@ namespace umbraco.BasePages { } object timeout = HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID]; - if(timeout != null) - return (long) timeout; + if (timeout != null) + return (long)timeout; return 0; @@ -198,25 +217,58 @@ namespace umbraco.BasePages { /// Gets or sets the umbraco user context ID. /// /// The umbraco user context ID. - public static string umbracoUserContextID { + public static string umbracoUserContextID + { get { - // zb-00004 #29956 : refactor cookies names & handling - if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue) - return StateHelper.Cookies.UserContext.GetValue(); - else - return ""; - } - set { - // zb-00004 #29956 : refactor cookies names & handling - if (StateHelper.Cookies.HasCookies) - { - // Clearing all old cookies before setting a new one. - if (StateHelper.Cookies.UserContext.HasValue) - StateHelper.Cookies.ClearAll(); + // zb-00004 #29956 : refactor cookies names & handling + if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue) + { + try + { + string encTicket = StateHelper.Cookies.UserContext.GetValue(); + if (!String.IsNullOrEmpty(encTicket)) + return FormsAuthentication.Decrypt(encTicket).UserData; + } + catch (HttpException ex) + { + // we swallow this type of exception as it happens if a legacy (pre 4.8.1) cookie is set + } + } - // Create new cookie. - StateHelper.Cookies.UserContext.SetValue(value, 1); + return ""; + } + set + { + // zb-00004 #29956 : refactor cookies names & handling + if (StateHelper.Cookies.HasCookies) + { + // Clearing all old cookies before setting a new one. + if (StateHelper.Cookies.UserContext.HasValue) + StateHelper.Cookies.ClearAll(); + + if (!String.IsNullOrEmpty(value)) + { + FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, + value, + DateTime.Now, + DateTime.Now.AddDays(1), + false, + value, + FormsAuthentication.FormsCookiePath); + + // Encrypt the ticket. + string encTicket = FormsAuthentication.Encrypt(ticket); + + + // Create new cookie. + StateHelper.Cookies.UserContext.SetValue(encTicket, 1); + + + } else + { + StateHelper.Cookies.UserContext.Clear(); + } } } } @@ -261,7 +313,8 @@ namespace umbraco.BasePages { /// Logs a user in. /// /// The user - public static void doLogin(User u) { + public static void doLogin(User u) + { Guid retVal = Guid.NewGuid(); SqlHelper.ExecuteNonQuery( "insert into umbracoUserLogins (contextID, userID, timeout) values (@contextId,'" + u.Id + "','" + @@ -277,7 +330,8 @@ namespace umbraco.BasePages { /// Gets the user. /// /// - public User getUser() { + public User getUser() + { if (!_userisValidated) validateUser(); return _user; } @@ -285,26 +339,28 @@ namespace umbraco.BasePages { /// /// Ensures the page context. /// - public void ensureContext() { + public void ensureContext() + { validateUser(); } - - [Obsolete("Use ClientTools instead")] - public void speechBubble(speechBubbleIcon i, string header, string body) - { - ClientTools.ShowSpeechBubble(i, header, body); + + [Obsolete("Use ClientTools instead")] + public void speechBubble(speechBubbleIcon i, string header, string body) + { + ClientTools.ShowSpeechBubble(i, header, body); } - //[Obsolete("Use ClientTools instead")] - //public void reloadParentNode() - //{ - // ClientTools.ReloadParentNode(true); - //} + //[Obsolete("Use ClientTools instead")] + //public void reloadParentNode() + //{ + // ClientTools.ReloadParentNode(true); + //} /// /// a collection of available speechbubble icons /// - public enum speechBubbleIcon { + public enum speechBubbleIcon + { /// /// Save icon /// @@ -331,10 +387,12 @@ namespace umbraco.BasePages { /// Raises the event. /// /// The object that contains the event data. - protected override void OnLoad(EventArgs e) { + protected override void OnLoad(EventArgs e) + { base.OnLoad(e); - - if (!Request.IsSecureConnection && GlobalSettings.UseSSL) { + + if (!Request.IsSecureConnection && GlobalSettings.UseSSL) + { string serverName = HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]); Response.Redirect(string.Format("https://{0}{1}", serverName, Request.FilePath)); } From bb4f4822d4d34a65bc0dbdb0e3a6cfed72d8488a Mon Sep 17 00:00:00 2001 From: hartvig Date: Thu, 9 Aug 2012 10:27:34 -0200 Subject: [PATCH 14/26] Fixes issue with images with a filename that has dimensions appended (ie. myimage_300x200.jpg) inserted into tinyMCE. Work items: 30864 --- .../tinyMCE3/webcontrol/TinyMCEWebControl.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs b/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs index 770239a15e..b386ef6a51 100644 --- a/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs +++ b/src/umbraco.editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs @@ -326,10 +326,9 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol tempTag += " " + ide.Key.ToString() + "=\"" + ide.Value.ToString() + "\""; // Find the original filename, by removing the might added width and height + // NH, 4.8.1 - above replaced by loading the right media file from the db later! orgSrc = - IOHelper.ResolveUrl(orgSrc.Replace( - "_" + helper.FindAttribute(ht, "width") + "x" + helper.FindAttribute(ht, "height"), ""). - Replace("%20", " ")); + IOHelper.ResolveUrl(orgSrc.Replace("%20", " ")); // Check for either id or guid from media string mediaId = getIdFromSource(orgSrc, localMediaPath); @@ -358,15 +357,10 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol { try { - // Check extention - if (imageMedia.getProperty("umbracoExtension").Value.ToString() != orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1)) - orgSrc = orgSrc.Substring(0, orgSrc.LastIndexOf(".") + 1) + - imageMedia.getProperty("umbracoExtension").Value.ToString(); - // Format the tag tempTag = tempTag + " rel=\"" + imageMedia.getProperty("umbracoWidth").Value.ToString() + "," + - imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + orgSrc + + imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + IOHelper.ResolveUrl(imageMedia.getProperty("umbracoFile").Value.ToString()) + "\""; tempTag += "/>"; From 3acfb2a9eacf0458d854d8f7d9895b1c80098fe7 Mon Sep 17 00:00:00 2001 From: hartvig Date: Thu, 9 Aug 2012 11:15:55 -0200 Subject: [PATCH 15/26] Updates to login cookies --- src/umbraco.businesslogic/BasePages/BasePage.cs | 6 ++++++ src/umbraco.businesslogic/StateHelper.cs | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs index b0e367ebe0..7964fbad22 100644 --- a/src/umbraco.businesslogic/BasePages/BasePage.cs +++ b/src/umbraco.businesslogic/BasePages/BasePage.cs @@ -234,6 +234,12 @@ namespace umbraco.BasePages { // we swallow this type of exception as it happens if a legacy (pre 4.8.1) cookie is set } + catch (ArgumentException ex) + { + // we swallow this one because it's 99.99% certaincy is legacy based. We'll still log it, though + Log.Instance.AddException(ex); + + } } return ""; diff --git a/src/umbraco.businesslogic/StateHelper.cs b/src/umbraco.businesslogic/StateHelper.cs index 10103cffdb..4d5ab3ff17 100644 --- a/src/umbraco.businesslogic/StateHelper.cs +++ b/src/umbraco.businesslogic/StateHelper.cs @@ -354,6 +354,8 @@ namespace umbraco.BusinessLogic public void SetValue(string value) { HttpCookie cookie = new HttpCookie(_key, value); + if (GlobalSettings.UseSSL) + cookie.Secure = true; if (!TimeSpan.Zero.Equals(_expires)) cookie.Expires = DateTime.Now + _expires; ResponseCookie = cookie; @@ -378,7 +380,9 @@ namespace umbraco.BusinessLogic public void SetValue(string value, DateTime expires) { HttpCookie cookie = new HttpCookie(_key, value); - cookie.Expires = expires; + if (GlobalSettings.UseSSL) + cookie.Secure = true; + cookie.Expires = expires; ResponseCookie = cookie; // original Umbraco code also does this From c4214a7ee9ca41cc09652b65a0340ed67dc1cedd Mon Sep 17 00:00:00 2001 From: sebastiaan Date: Thu, 9 Aug 2012 14:04:49 -0200 Subject: [PATCH 16/26] The version header is no longer needed and a potential attack vector. Has now been removed - Work item: 30989 --- src/umbraco.businesslogic/UmbracoSettings.cs | 22 ------------------- .../config/umbracoSettings.Release.config | 2 -- src/umbraco.presentation/default.aspx.cs | 4 ---- 3 files changed, 28 deletions(-) diff --git a/src/umbraco.businesslogic/UmbracoSettings.cs b/src/umbraco.businesslogic/UmbracoSettings.cs index f032f89fd3..7a38b42823 100644 --- a/src/umbraco.businesslogic/UmbracoSettings.cs +++ b/src/umbraco.businesslogic/UmbracoSettings.cs @@ -311,28 +311,6 @@ namespace umbraco } } - /// - /// Gets a value indicating whether umbraco shouldn't add X-Umbraco-Version to the http header. - /// - /// true if umbraco will not add header; otherwise, false. - public static bool RemoveUmbracoVersionHeader - { - get - { - try - { - bool result; - if (bool.TryParse(GetKey("/settings/requestHandler/removeUmbracoVersionHeader"), out result)) - return result; - return false; - } - catch - { - return false; - } - } - } - /// /// This will add a trailing slash (/) to urls when in directory url mode /// NOTICE: This will always return false if Directory Urls in not active diff --git a/src/umbraco.presentation/config/umbracoSettings.Release.config b/src/umbraco.presentation/config/umbracoSettings.Release.config index 9b36698f97..dae69d2df4 100644 --- a/src/umbraco.presentation/config/umbracoSettings.Release.config +++ b/src/umbraco.presentation/config/umbracoSettings.Release.config @@ -124,8 +124,6 @@ ae oe - - false diff --git a/src/umbraco.presentation/default.aspx.cs b/src/umbraco.presentation/default.aspx.cs index 53b4b19dc1..b18e10c58a 100644 --- a/src/umbraco.presentation/default.aspx.cs +++ b/src/umbraco.presentation/default.aspx.cs @@ -206,10 +206,6 @@ namespace umbraco if (!UmbracoSettings.UseAspNetMasterPages) initUmbracoPage(); base.OnInit(e); - - // Add Umbraco header - if (!UmbracoSettings.RemoveUmbracoVersionHeader) - Response.AddHeader("X-Umbraco-Version", string.Format("{0}.{1}", GlobalSettings.VersionMajor, GlobalSettings.VersionMinor)); } private void initUmbracoPage() From a79d11aad70ea2f932fbcfe22f33fd3485327644 Mon Sep 17 00:00:00 2001 From: sebastiaan Date: Sat, 11 Aug 2012 05:55:26 -0200 Subject: [PATCH 17/26] Fix for workitem 30993 - When RTE context menu is disabled, the RTE fails to show --- .../umbracocontextmenu/editor_plugin_src.js | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js b/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js index da22f21a87..3d8ccfad4b 100644 --- a/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js +++ b/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js @@ -26,42 +26,40 @@ * @param {string} url Absolute URL to where the plugin is located. */ init: function (ed) { - var t = this; - - ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { - - var keys = UmbClientMgr.uiKeys(); - - $.each(menu.items, function (idx, el) { + if (ed.plugins.contextmenu) { - switch (el.settings.cmd) { - case "Cut": - el.settings.title = keys['defaultdialogs_cut']; - break; - case "Copy": - el.settings.title = keys['general_copy']; - break; - case "Paste": - el.settings.title = keys['defaultdialogs_paste']; - break; - case "mceAdvLink": - case "mceLink": - el.settings.title = keys['defaultdialogs_insertlink']; - break; - case "UnLink": - el.settings.title = keys['relatedlinks_removeLink']; - break; - case "mceImage": - el.settings.title = keys['defaultdialogs_insertimage']; - el.settings.cmd = "mceUmbimage"; - break; - } + ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { + var keys = UmbClientMgr.uiKeys(); + + $.each(menu.items, function (idx, el) { + + switch (el.settings.cmd) { + case "Cut": + el.settings.title = keys['defaultdialogs_cut']; + break; + case "Copy": + el.settings.title = keys['general_copy']; + break; + case "Paste": + el.settings.title = keys['defaultdialogs_paste']; + break; + case "mceAdvLink": + case "mceLink": + el.settings.title = keys['defaultdialogs_insertlink']; + break; + case "UnLink": + el.settings.title = keys['relatedlinks_removeLink']; + break; + case "mceImage": + el.settings.title = keys['defaultdialogs_insertimage']; + el.settings.cmd = "mceUmbimage"; + break; + } + }); }); - - }); + } } - }); // Register plugin From f6e59e0264e53549b2a52e3ae0f1d06b33e4e681 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Mon, 13 Aug 2012 06:38:43 -0100 Subject: [PATCH 18/26] Merge with 4.8.1 (2nd) --- .../config/umbracoSettings.Release.config | 3 - .../umbracocontextmenu/editor_plugin_src.js | 4 +- .../web.Template.UMBRACOELISE.Debug.config | 4 +- .../config/umbracoSettings.Release.config | 229 ------------------ .../umbracocontextmenu/editor_plugin_src.js | 67 ----- .../web.Template.UMBRACOELISE.Debug.config | 39 --- 6 files changed, 4 insertions(+), 342 deletions(-) delete mode 100644 src/umbraco.presentation/config/umbracoSettings.Release.config delete mode 100644 src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js delete mode 100644 src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config index 9384fc2c05..dae69d2df4 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config @@ -114,7 +114,6 @@ star - - ae oe aa @@ -125,8 +124,6 @@ ae oe - - false diff --git a/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js b/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js index da22f21a87..f3074ef21f 100644 --- a/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js +++ b/src/Umbraco.Web.UI/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js @@ -26,7 +26,7 @@ * @param {string} url Absolute URL to where the plugin is located. */ init: function (ed) { - var t = this; + if (ed.plugins.contextmenu) { ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { @@ -61,7 +61,7 @@ }); } - + } }); // Register plugin diff --git a/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config b/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config index 4b2e4bb8da..124bf94e8e 100644 --- a/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config +++ b/src/Umbraco.Web.UI/web.Template.UMBRACOELISE.Debug.config @@ -17,9 +17,9 @@ + value="server=.\sqlexpress;database=481;user id=DBUSER;password=DBPASSWORD"/> + value="4.8.1"/> diff --git a/src/umbraco.presentation/config/umbracoSettings.Release.config b/src/umbraco.presentation/config/umbracoSettings.Release.config deleted file mode 100644 index dae69d2df4..0000000000 --- a/src/umbraco.presentation/config/umbracoSettings.Release.config +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - jpeg,jpg,gif,bmp,png,tiff,tif - - alt,border,class,style,align,id,name,onclick,usemap - - - - umbracoWidth - umbracoHeight - umbracoBytes - umbracoExtension - - - - - - /scripts - - js,xml - - - false - - - - True - - - - - 1 - - - - your@email.here - - - - True - - - gif - - - True - - - UTF8 - - - false - - - - true - - - True - - - True - - - False - - - False - - - text - - - In Preview Mode - click to end]]> - - - - 1800 - - - - - false - - - - - true - - - false - - - - - false - - true - - - - - - - - - - - - plus - star - - - ae - oe - aa - ae - oe - ue - ss - ae - oe - - - - - true - - - - - - - cs - vb - - - - - - - - p - div - ul - span - - - - - - - - - - - - true - true - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - your-username - your-username - your-username - your-username - your-username - - css,xslt - - - - - - - - - - - - - UsersMembershipProvider - - - - - - - - - - diff --git a/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js b/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js deleted file mode 100644 index 3d8ccfad4b..0000000000 --- a/src/umbraco.presentation/umbraco_client/tinymce3/plugins/umbracocontextmenu/editor_plugin_src.js +++ /dev/null @@ -1,67 +0,0 @@ -/** -* editor_plugin_src.js -* -* Copyright 2012, Umbraco -* Released under MIT License. -* -* License: http://opensource.org/licenses/mit-license.html -*/ - -(function () { - var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; - - /** - * This plugin modifies the standard TinyMCE context menu, with umbraco specific changes. - * - * @class tinymce.plugins.umbContextMenu - */ - tinymce.create('tinymce.plugins.UmbracoContextMenu', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @method init - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init: function (ed) { - if (ed.plugins.contextmenu) { - - ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { - - var keys = UmbClientMgr.uiKeys(); - - $.each(menu.items, function (idx, el) { - - switch (el.settings.cmd) { - case "Cut": - el.settings.title = keys['defaultdialogs_cut']; - break; - case "Copy": - el.settings.title = keys['general_copy']; - break; - case "Paste": - el.settings.title = keys['defaultdialogs_paste']; - break; - case "mceAdvLink": - case "mceLink": - el.settings.title = keys['defaultdialogs_insertlink']; - break; - case "UnLink": - el.settings.title = keys['relatedlinks_removeLink']; - break; - case "mceImage": - el.settings.title = keys['defaultdialogs_insertimage']; - el.settings.cmd = "mceUmbimage"; - break; - } - }); - }); - } - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracocontextmenu', tinymce.plugins.UmbracoContextMenu); -})(); diff --git a/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config b/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config deleted file mode 100644 index 124bf94e8e..0000000000 --- a/src/umbraco.presentation/web.Template.UMBRACOELISE.Debug.config +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file From d2ac9158c63af82a55bec3df95737d141bf07cf5 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Mon, 13 Aug 2012 10:04:31 -0100 Subject: [PATCH 19/26] Added IFileSystem Fixed issue with last merge --- src/Umbraco.Core/IO/IFileSystem.cs | 39 ++++ src/Umbraco.Core/IO/PhysicalFileSystem.cs | 182 ++++++++++++++++++ src/Umbraco.Core/Properties/AssemblyInfo.cs | 3 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 + .../IO/AbstractFileSystemTests.cs | 156 +++++++++++++++ .../IO/PhysicalFileSystemTests.cs | 25 +++ src/Umbraco.Tests/Umbraco.Tests.csproj | 2 + .../BasePages/BasePage.cs | 4 +- .../Installer/DefaultInstallerUtility.cs | 1 - 9 files changed, 411 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Core/IO/IFileSystem.cs create mode 100644 src/Umbraco.Core/IO/PhysicalFileSystem.cs create mode 100644 src/Umbraco.Tests/IO/AbstractFileSystemTests.cs create mode 100644 src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs new file mode 100644 index 0000000000..3a2c426754 --- /dev/null +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Umbraco.Core.IO +{ + internal interface IFileSystem + { + void DeleteDirectory(string path); + + void DeleteDirectory(string path, bool recursive); + + IEnumerable GetFiles(string path); + + IEnumerable GetFiles(string path, string filter); + + IEnumerable GetDirectories(string path); + + string GetFullPath(string path); + + string GetUrl(string path); + + void DeleteFile(string path); + + bool FileExists(string path); + + bool DirectoryExists(string path); + + void AddFile(string path, Stream stream); + + void AddFile(string path, Stream stream, bool overrideIfExists); + + Stream OpenFile(string path); + + DateTimeOffset GetLastModified(string path); + + DateTimeOffset GetCreated(string path); + } +} diff --git a/src/Umbraco.Core/IO/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs new file mode 100644 index 0000000000..6f7fab4521 --- /dev/null +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.IO +{ + internal class PhysicalFileSystem : IFileSystem + { + private readonly string _rootPath; + private readonly string _rootUrl; + + public PhysicalFileSystem(string rootPath, string rootUrl) + { + if (string.IsNullOrEmpty(rootPath)) + throw new ArgumentException("The argument 'rootPath' cannot be null or empty."); + + if (string.IsNullOrEmpty(rootUrl)) + throw new ArgumentException("The argument 'rootUrl' cannot be null or empty."); + + _rootPath = rootPath; + _rootUrl = rootUrl; + } + + public IEnumerable GetDirectories(string path) + { + path = EnsureTrailingSeparator(GetFullPath(path)); + + try + { + if (Directory.Exists(path)) + return Directory.EnumerateDirectories(path).Select(MakeRelativePath); + } + catch (UnauthorizedAccessException ex) + { } + catch (DirectoryNotFoundException ex) + { } + + return Enumerable.Empty(); + } + + public virtual void DeleteDirectory(string path) + { + DeleteDirectory(path, false); + } + + public void DeleteDirectory(string path, bool recursive) + { + if (!DirectoryExists(path)) + return; + + try + { + Directory.Delete(GetFullPath(path), recursive); + } + catch (DirectoryNotFoundException ex) + { } + } + + public bool DirectoryExists(string path) + { + return Directory.Exists(GetFullPath(path)); + } + + public void AddFile(string path, Stream stream) + { + AddFile(path, stream, true); + } + + public void AddFile(string path, Stream stream, bool overrideIfExists) + { + if (FileExists(path) && !overrideIfExists) + throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", + path)); + + EnsureDirectory(Path.GetDirectoryName(path)); + + using (var destination = (Stream)File.Create(GetFullPath(path))) + stream.CopyTo(destination); + } + + public IEnumerable GetFiles(string path) + { + return GetFiles(path, "*.*"); + } + + public IEnumerable GetFiles(string path, string filter) + { + path = EnsureTrailingSeparator(GetFullPath(path)); + + try + { + if (Directory.Exists(path)) + return Directory.EnumerateFiles(path, filter).Select(MakeRelativePath); + } + catch (UnauthorizedAccessException ex) + { } + catch (DirectoryNotFoundException ex) + { } + + return Enumerable.Empty(); + } + + public Stream OpenFile(string path) + { + return File.OpenRead(GetFullPath(path)); + } + + public void DeleteFile(string path) + { + if (!FileExists(path)) + return; + + try + { + File.Delete(GetFullPath(path)); + } + catch (FileNotFoundException ex) + { } + } + + public bool FileExists(string path) + { + return File.Exists(GetFullPath(path)); + } + + public string GetFullPath(string path) + { + return !path.StartsWith(_rootPath) + ? Path.Combine(_rootPath, path) + : path; + } + + public string GetUrl(string path) + { + return _rootUrl.TrimEnd("/") + "/" + path + .TrimStart(Path.DirectorySeparatorChar) + .Replace(Path.DirectorySeparatorChar, '/'); + } + + public DateTimeOffset GetLastModified(string path) + { + return DirectoryExists(path) + ? new DirectoryInfo(GetFullPath(path)).LastWriteTimeUtc + : new FileInfo(GetFullPath(path)).LastWriteTimeUtc; + } + + public DateTimeOffset GetCreated(string path) + { + return DirectoryExists(path) + ? Directory.GetCreationTimeUtc(GetFullPath(path)) + : File.GetCreationTimeUtc(GetFullPath(path)); + } + + #region Helper Methods + + protected string MakeRelativePath(string fullPath) + { + return fullPath.Substring(_rootPath.Length).TrimStart(new char[1] + { + Path.DirectorySeparatorChar + }); + } + + protected virtual void EnsureDirectory(string path) + { + path = GetFullPath(path); + Directory.CreateDirectory(path); + } + + protected string EnsureTrailingSeparator(string path) + { + if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + path = path + Path.DirectorySeparatorChar; + + return path; + } + + #endregion + } +} diff --git a/src/Umbraco.Core/Properties/AssemblyInfo.cs b/src/Umbraco.Core/Properties/AssemblyInfo.cs index 90b7ad63b5..fd937747fc 100644 --- a/src/Umbraco.Core/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Core/Properties/AssemblyInfo.cs @@ -20,4 +20,5 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("cms")] [assembly: InternalsVisibleTo("umbraco")] -[assembly: InternalsVisibleTo("businesslogic")] \ No newline at end of file +[assembly: InternalsVisibleTo("businesslogic")] +[assembly: InternalsVisibleTo("Umbraco.Tests")] \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 265eed5a9e..bae30785d7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -47,6 +47,8 @@ + + diff --git a/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs new file mode 100644 index 0000000000..debcd8492b --- /dev/null +++ b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core.IO; +using Umbraco.Tests.BusinessLogic; + +namespace Umbraco.Tests.IO +{ + [TestFixture] + internal abstract class AbstractFileSystemTests + { + protected IFileSystem _fileSystem; + + protected AbstractFileSystemTests(IFileSystem fileSystem) + { + _fileSystem = fileSystem; + } + + [Test] + public void Can_Create_And_Delete_Files() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + Assert.IsTrue(_fileSystem.FileExists("test.txt")); + + _fileSystem.DeleteFile("test.txt"); + + Assert.IsFalse(_fileSystem.FileExists("test.txt")); + } + + [Test] + public void Can_Overwrite_File() + { + _fileSystem.AddFile("test/test.txt", CreateStream()); + _fileSystem.AddFile("test/test.txt", CreateStream()); + + var files = _fileSystem.GetFiles("test"); + + Assert.AreEqual(1, files.Count()); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void Cant_Overwrite_File() + { + _fileSystem.AddFile("test.txt", CreateStream()); + _fileSystem.AddFile("test.txt", CreateStream(), false); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Files() + { + _fileSystem.AddFile("test/test1.txt", CreateStream()); + _fileSystem.AddFile("test/test2.txt", CreateStream()); + _fileSystem.AddFile("test/test3.txt", CreateStream()); + _fileSystem.AddFile("test/test4.bak", CreateStream()); + + var files = _fileSystem.GetFiles("test"); + + Assert.AreEqual(4, files.Count()); + + files = _fileSystem.GetFiles("test", "*.txt"); + + Assert.AreEqual(3, files.Count()); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + public void Can_Read_File() + { + _fileSystem.AddFile("test.txt", CreateStream("hello world")); + + var stream = _fileSystem.OpenFile("test.txt"); + var reader = new StreamReader(stream); + var contents = reader.ReadToEnd(); + reader.Close(); + + Assert.AreEqual("hello world", contents); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Directories() + { + _fileSystem.AddFile("test/sub1/test.txt", CreateStream()); + _fileSystem.AddFile("test/sub2/test.txt", CreateStream()); + _fileSystem.AddFile("test/sub3/test.txt", CreateStream()); + + var dirs = _fileSystem.GetDirectories("test"); + + Assert.AreEqual(3, dirs.Count()); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub1")); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub2")); + Assert.IsTrue(_fileSystem.DirectoryExists("test/sub3")); + + _fileSystem.DeleteDirectory("test", true); + } + + [Test] + public void Can_Get_File_Dates() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var created = _fileSystem.GetCreated("test.txt"); + var modified = _fileSystem.GetLastModified("test.txt"); + + Assert.AreEqual(DateTime.Today.Year, created.Year); + Assert.AreEqual(DateTime.Today.Month, created.Month); + Assert.AreEqual(DateTime.Today.Date, created.Date); + + Assert.AreEqual(DateTime.Today.Year, modified.Year); + Assert.AreEqual(DateTime.Today.Month, modified.Month); + Assert.AreEqual(DateTime.Today.Date, modified.Date); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_File_Url() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var url = _fileSystem.GetUrl("test.txt"); + + Assert.AreEqual(ConstructUrl("test.txt"), url); + + _fileSystem.DeleteFile("test.txt"); + } + + #region Helper Methods + + protected Stream CreateStream(string contents = null) + { + if(string.IsNullOrEmpty(contents)) + contents = "test"; + + var bytes = Encoding.UTF8.GetBytes(contents); + var stream = new MemoryStream(bytes); + + return stream; + } + + protected abstract string ConstructUrl(string path); + + #endregion + } +} diff --git a/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs b/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs new file mode 100644 index 0000000000..dc79f82620 --- /dev/null +++ b/src/Umbraco.Tests/IO/PhysicalFileSystemTests.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core.IO; +using Umbraco.Tests.BusinessLogic; + +namespace Umbraco.Tests.IO +{ + [TestFixture] + internal class PhysicalFileSystemTests : AbstractFileSystemTests + { + public PhysicalFileSystemTests() + : base(new PhysicalFileSystem(AppDomain.CurrentDomain.BaseDirectory, + "/Media/")) + { } + + protected override string ConstructUrl(string path) + { + return "/Media/" + path; + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 68df4cd172..7b2b2cb75e 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -48,6 +48,8 @@ + + diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs index 6f239e19f3..ab555a587a 100644 --- a/src/umbraco.businesslogic/BasePages/BasePage.cs +++ b/src/umbraco.businesslogic/BasePages/BasePage.cs @@ -228,6 +228,8 @@ namespace umbraco.BasePages if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue) return StateHelper.Cookies.UserContext.GetValue(); else + { + try { string encTicket = StateHelper.Cookies.UserContext.GetValue(); if (!String.IsNullOrEmpty(encTicket)) @@ -245,7 +247,7 @@ namespace umbraco.BasePages } } - return ""; + return ""; } set { diff --git a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs index 816fc94a8d..882dbe19fa 100644 --- a/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs +++ b/src/umbraco.datalayer/Utility/Installer/DefaultInstallerUtility.cs @@ -171,7 +171,6 @@ namespace umbraco.DataLayer.Utility.Installer #endregion #region Protected Methods - protected virtual void NewInstall(string sql) { From ad291265f35ffb9bae060aa41bec90d5a9c3d6f2 Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Mon, 13 Aug 2012 10:23:45 -0100 Subject: [PATCH 20/26] Added PhysicalFileSystem constructor overload to work out the rootPath / rootUrl from a virtualRoot path (Can only work with a valid HttpContext) --- src/Umbraco.Core/IO/PhysicalFileSystem.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Umbraco.Core/IO/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs index 6f7fab4521..30398c5e04 100644 --- a/src/Umbraco.Core/IO/PhysicalFileSystem.cs +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Web; namespace Umbraco.Core.IO { @@ -11,6 +12,15 @@ namespace Umbraco.Core.IO private readonly string _rootPath; private readonly string _rootUrl; + public PhysicalFileSystem(string virtualRoot) + { + if(HttpContext.Current == null) + throw new InvalidOperationException("The single parameter constructor can only be accessed when there is a valid HttpContext"); + + _rootPath = HttpContext.Current.Server.MapPath(virtualRoot); + _rootUrl = VirtualPathUtility.ToAbsolute(virtualRoot); + } + public PhysicalFileSystem(string rootPath, string rootUrl) { if (string.IsNullOrEmpty(rootPath)) From 524244d1ec118b76c66b579633c012c3befd7a2b Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Mon, 13 Aug 2012 13:26:06 -0100 Subject: [PATCH 21/26] Added FileSystemProviders config section Added FileSystemProviderManager class for fetching a file system provider by alias (this should probably be moved into the Umbraco context in 4.10) --- .../FileSystemProviderElement.cs | 42 +++++++++++++ .../FileSystemProviderElementCollection.cs | 30 +++++++++ .../FileSystemProvidersSection.cs | 19 ++++++ src/Umbraco.Core/IO/FileSystemProvider.cs | 12 ++++ .../IO/FileSystemProviderManager.cs | 61 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 6 ++ src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++ .../config/FileSystemProviders.Release.config | 11 ++++ .../config/FileSystemProviders.config | 11 ++++ src/Umbraco.Web.UI/web.Template.config | 3 + 10 files changed, 199 insertions(+) create mode 100644 src/Umbraco.Core/Configuration/FileSystemProviderElement.cs create mode 100644 src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs create mode 100644 src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs create mode 100644 src/Umbraco.Core/IO/FileSystemProvider.cs create mode 100644 src/Umbraco.Core/IO/FileSystemProviderManager.cs create mode 100644 src/Umbraco.Web.UI/config/FileSystemProviders.Release.config create mode 100644 src/Umbraco.Web.UI/config/FileSystemProviders.config diff --git a/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs b/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs new file mode 100644 index 0000000000..c0773e64e3 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProviderElement.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + public class FileSystemProviderElement : ConfigurationElement + { + private const string ALIAS_KEY = "alias"; + private const string TYPE_KEY = "type"; + private const string PARAMETERS_KEY = "Parameters"; + + [ConfigurationProperty(ALIAS_KEY, IsKey = true, IsRequired = true)] + public string Alias + { + get + { + return ((string)(base[ALIAS_KEY])); + } + } + + [ConfigurationProperty(TYPE_KEY, IsKey = false, IsRequired = true)] + public string Type + { + get + { + return ((string)(base[TYPE_KEY])); + } + } + + [ConfigurationProperty(PARAMETERS_KEY, IsDefaultCollection = true, IsRequired = false)] + public KeyValueConfigurationCollection Parameters + { + get + { + return ((KeyValueConfigurationCollection)(base[PARAMETERS_KEY])); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs b/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs new file mode 100644 index 0000000000..0604560939 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProviderElementCollection.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + [ConfigurationCollection(typeof(FileSystemProviderElement), AddItemName = "Provider")] + public class FileSystemProviderElementCollection : ConfigurationElementCollection + { + protected override ConfigurationElement CreateNewElement() + { + return new FileSystemProviderElement(); + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((FileSystemProviderElement)(element)).Alias; + } + + new public FileSystemProviderElement this[string key] + { + get + { + return (FileSystemProviderElement)BaseGet(key); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs b/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs new file mode 100644 index 0000000000..a893d541a6 --- /dev/null +++ b/src/Umbraco.Core/Configuration/FileSystemProvidersSection.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration +{ + public class FileSystemProvidersSection : ConfigurationSection + { + private const string PROVIDERS_KEY = "providers"; + + [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)] + public FileSystemProviderElementCollection Providers + { + get { return ((FileSystemProviderElementCollection)(base[""])); } + } + } +} diff --git a/src/Umbraco.Core/IO/FileSystemProvider.cs b/src/Umbraco.Core/IO/FileSystemProvider.cs new file mode 100644 index 0000000000..31f767f28e --- /dev/null +++ b/src/Umbraco.Core/IO/FileSystemProvider.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.IO +{ + internal class FileSystemProvider + { + public const string Media = "media"; + } +} diff --git a/src/Umbraco.Core/IO/FileSystemProviderManager.cs b/src/Umbraco.Core/IO/FileSystemProviderManager.cs new file mode 100644 index 0000000000..da4a1e8dec --- /dev/null +++ b/src/Umbraco.Core/IO/FileSystemProviderManager.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.IO +{ + internal class FileSystemProviderManager + { + private readonly FileSystemProvidersSection _config; + + #region Singleton + + private static readonly FileSystemProviderManager Instance = new FileSystemProviderManager(); + + public static FileSystemProviderManager Current + { + get { return Instance; } + } + + #endregion + + #region Constructors + + public FileSystemProviderManager() + { + _config = (FileSystemProvidersSection)ConfigurationManager.GetSection("FileSystemProviders"); + } + + #endregion + + public IFileSystem GetFileSystemProvider(string alias) + { + var providerConfig = _config.Providers[alias]; + if(providerConfig == null) + throw new ArgumentException(string.Format("No provider found with the alias '{0}'", alias)); + + var providerType = Type.GetType(providerConfig.Type); + if(providerType == null) + throw new InvalidOperationException(string.Format("Could not find type '{0}'", providerConfig.Type)); + + if (providerType.IsAssignableFrom(typeof(IFileSystem))) + throw new InvalidOperationException(string.Format("The type '{0}' does not implement IFileSystem", providerConfig.Type)); + + var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0; + var constructor = providerType.GetConstructors() + .SingleOrDefault(x => x.GetParameters().Count() == paramCount + && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name))); + if(constructor == null) + throw new InvalidOperationException(string.Format("Could not find constructor for type '{0}' which accepts {1} parameters", providerConfig.Type, paramCount)); + + var parameters = new object[paramCount]; + for(var i = 0; i < paramCount; i++) + parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value; + + return (IFileSystem) constructor.Invoke(parameters); + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bae30785d7..8ae92f2038 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -32,6 +32,7 @@ + @@ -44,9 +45,14 @@ Properties\SolutionInfo.cs + + + + + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index f865dc322b..e1834295e3 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -264,6 +264,10 @@ ClientDependency.config + + + FileSystemProviders.config + xsltExtensions.config diff --git a/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config b/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config new file mode 100644 index 0000000000..cffbc4e802 --- /dev/null +++ b/src/Umbraco.Web.UI/config/FileSystemProviders.Release.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/config/FileSystemProviders.config b/src/Umbraco.Web.UI/config/FileSystemProviders.config new file mode 100644 index 0000000000..cffbc4e802 --- /dev/null +++ b/src/Umbraco.Web.UI/config/FileSystemProviders.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 773c4e0f47..9ef5698791 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -11,6 +11,7 @@
    +
    @@ -19,11 +20,13 @@ + + From aceb5b02038d7c5f93c4ba551951410653a52068 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 13 Aug 2012 22:45:01 -0100 Subject: [PATCH 22/26] U4-162 Relation Types - Resolves MySQL issues; re-enabled Tree attribute. Changed umbraco.DataLayer project to use .NET 4.0, (was previously using 3.5), reason being that we could use Guid.Parse. Also resolves workitem:30434 - Error when copying node and keeping relation between original and copy. --- .../umbraco/Trees/loadRelationTypes.cs | 2 +- src/umbraco.cms/businesslogic/relation/Relation.cs | 2 +- src/umbraco.cms/businesslogic/relation/RelationType.cs | 10 +++++----- src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs | 1 + src/umbraco.datalayer/umbraco.datalayer.csproj | 3 ++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs index c33e843b17..4e19a87947 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadRelationTypes.cs @@ -16,7 +16,7 @@ namespace umbraco /// /// RelationTypes tree for developer section /// - //[Tree("developer", "relationTypes", "Relation Types", sortOrder: 4)] + [Tree("developer", "relationTypes", "Relation Types", sortOrder: 4)] public class loadRelationTypes : BaseTree { /// diff --git a/src/umbraco.cms/businesslogic/relation/Relation.cs b/src/umbraco.cms/businesslogic/relation/Relation.cs index 66d95cab93..b0f6576f21 100644 --- a/src/umbraco.cms/businesslogic/relation/Relation.cs +++ b/src/umbraco.cms/businesslogic/relation/Relation.cs @@ -105,7 +105,7 @@ namespace umbraco.cms.businesslogic.relation public void Delete() { - SqlHelper.ExecuteNonQuery("delete from umbracoRelation where id = @id", SqlHelper.CreateParameter("@id", this.Id)); + SqlHelper.ExecuteNonQuery("DELETE FROM umbracoRelation WHERE id = @id", SqlHelper.CreateParameter("@id", this.Id)); } [MethodImpl(MethodImplOptions.Synchronized)] diff --git a/src/umbraco.cms/businesslogic/relation/RelationType.cs b/src/umbraco.cms/businesslogic/relation/RelationType.cs index c331235672..b31c6c6837 100644 --- a/src/umbraco.cms/businesslogic/relation/RelationType.cs +++ b/src/umbraco.cms/businesslogic/relation/RelationType.cs @@ -41,7 +41,7 @@ namespace umbraco.cms.businesslogic.relation public RelationType(int id) { using (IRecordsReader dr = SqlHelper.ExecuteReader( - "select id, dual, name, alias from umbracoRelationType where id = @id", SqlHelper.CreateParameter("@id", id))) + "SELECT id, [dual], name, alias FROM umbracoRelationType WHERE id = @id", SqlHelper.CreateParameter("@id", id))) { if (dr.Read()) { @@ -70,7 +70,7 @@ namespace umbraco.cms.businesslogic.relation { _name = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set name = @name where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@name", value)); + "UPDATE umbracoRelationType SET name = @name WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@name", value)); this.InvalidateCache(); } } @@ -82,7 +82,7 @@ namespace umbraco.cms.businesslogic.relation { _alias = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set alias = @alias where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@alias", value)); + "UPDATE umbracoRelationType SET alias = @alias WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@alias", value)); this.InvalidateCache(); } } @@ -94,7 +94,7 @@ namespace umbraco.cms.businesslogic.relation { _dual = value; SqlHelper.ExecuteNonQuery( - "update umbracoRelationType set [dual] = @dual where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@dual", value)); + "UPDATE umbracoRelationType SET [dual] = @dual WHERE id = " + this.Id.ToString(), SqlHelper.CreateParameter("@dual", value)); this.InvalidateCache(); } } @@ -128,7 +128,7 @@ namespace umbraco.cms.businesslogic.relation { var relationTypes = new List(); - using (IRecordsReader dr = SqlHelper.ExecuteReader("select id, dual, name, alias from umbracoRelationType")) + using (IRecordsReader dr = SqlHelper.ExecuteReader("SELECT id, [dual], name, alias FROM umbracoRelationType")) { while (dr.Read()) { diff --git a/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs b/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs index d9b7861634..4b3fab9d0f 100644 --- a/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs +++ b/src/umbraco.datalayer/SqlHelpers/MySql/MySqlHelper.cs @@ -93,6 +93,7 @@ namespace umbraco.DataLayer.SqlHelpers.MySql switch (typeof(T).FullName) { case "System.Boolean": return (T)(object)((1).Equals(scalar)); + case "System.Guid": return (T)(object)(Guid.Parse(scalar.ToString())); default: return base.ConvertScalar(scalar); } } diff --git a/src/umbraco.datalayer/umbraco.datalayer.csproj b/src/umbraco.datalayer/umbraco.datalayer.csproj index b840213a13..34eccea3a4 100644 --- a/src/umbraco.datalayer/umbraco.datalayer.csproj +++ b/src/umbraco.datalayer/umbraco.datalayer.csproj @@ -23,7 +23,7 @@ 3.5 - v3.5 + v4.0 publish\ true Disk @@ -39,6 +39,7 @@ false false true + true From d329123cdac8f3be7ee7849263a68378408d7a74 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 13 Aug 2012 23:02:17 -0100 Subject: [PATCH 23/26] U4-163 Picker Relations - reincluded data-type; previous fixes for U4-162 resolved issues. --- src/umbraco.editorControls/umbraco.editorControls.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index b4636781e3..f2f0fa7d42 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -172,6 +172,11 @@ + + + + + Code From c11bc9559cb648f201d74f25fcff90a096dfe597 Mon Sep 17 00:00:00 2001 From: hartvig Date: Tue, 14 Aug 2012 07:45:47 -0200 Subject: [PATCH 24/26] Implements U4-165 --- build/Build.proj | 179 ------------------ .../IUsercontrolDataEditor.cs | 7 + .../usercontrolDataEditor.cs | 10 +- 3 files changed, 16 insertions(+), 180 deletions(-) delete mode 100644 build/Build.proj diff --git a/build/Build.proj b/build/Build.proj deleted file mode 100644 index 498637ccd4..0000000000 --- a/build/Build.proj +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - ..\MSBuildCommunityTasks - ..\UmbracoMSBuildTasks - - - - - - - - - - .$(BUILD_NUMBER) - - - - Release - _BuildOutput\ - UmbracoCms$(DECIMAL_BUILD_NUMBER).zip - UmbracoCms.AllBinaries$(DECIMAL_BUILD_NUMBER).zip - UmbracoCms.WebPI$(DECIMAL_BUILD_NUMBER).zip - False - ..\..\build\$(BuildFolder) - $(MSBuildProjectDirectory)\$(BuildFolder) - $(BuildFolder)bin\ - $(BuildFolder)WebApp\ - $(BuildFolder)WebPi\ - $(BuildFolderRelativeToProjects)bin\ - $(BuildFolderAbsolutePath)bin\ - $(BuildFolderRelativeToProjects)WebApp\ - $(BuildFolderAbsolutePath)WebApp\ - $(BuildFolderRelativeToProjects)WebPi\ - $(BuildFolderAbsolutePath)WebPi\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/umbraco.editorControls/userControlWrapper/IUsercontrolDataEditor.cs b/src/umbraco.editorControls/userControlWrapper/IUsercontrolDataEditor.cs index 36d7344045..b480e973a7 100644 --- a/src/umbraco.editorControls/userControlWrapper/IUsercontrolDataEditor.cs +++ b/src/umbraco.editorControls/userControlWrapper/IUsercontrolDataEditor.cs @@ -1,7 +1,14 @@ +using umbraco.cms.businesslogic.property; + namespace umbraco.editorControls.userControlGrapper { public interface IUsercontrolDataEditor { object value { get; set;} } + + public interface IUsercontrolPropertyData + { + Property PropertyObject { set; } + } } diff --git a/src/umbraco.editorControls/userControlWrapper/usercontrolDataEditor.cs b/src/umbraco.editorControls/userControlWrapper/usercontrolDataEditor.cs index fe088c1cca..8e1831ea50 100644 --- a/src/umbraco.editorControls/userControlWrapper/usercontrolDataEditor.cs +++ b/src/umbraco.editorControls/userControlWrapper/usercontrolDataEditor.cs @@ -7,7 +7,7 @@ using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; - +using umbraco.cms.businesslogic.property; using umbraco.interfaces; using umbraco.editorControls; using umbraco.cms.businesslogic.datatype; @@ -83,6 +83,14 @@ namespace umbraco.editorControls.userControlGrapper } + // Add property data to the usercontrol if it supports it + // TODO: Find the best way to test for an interface! + IUsercontrolPropertyData propertyData = oControl as IUsercontrolPropertyData; + if (propertyData != null) + { + propertyData.PropertyObject = new Property(((usercontrolData)_data).PropertyId); + } + this.Controls.Add(oControl); if (!Page.IsPostBack) From e2274b78929be4af557bbbfbf8ca5c148370597f Mon Sep 17 00:00:00 2001 From: "Matt@MBP13-PC" Date: Tue, 14 Aug 2012 09:11:49 -0100 Subject: [PATCH 25/26] Hooked up IFileSystem to the file uploader / IFile --- src/Umbraco.Core/IO/AbstractFileSystem.cs | 52 ++++++ src/Umbraco.Core/IO/IFileSystem.cs | 33 ++-- src/Umbraco.Core/IO/PhysicalFileSystem.cs | 55 +++--- src/Umbraco.Core/Properties/AssemblyInfo.cs | 1 + src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../IO/AbstractFileSystemTests.cs | 29 ++++ .../umbraco.presentation/default.aspx.cs | 2 + src/umbraco.cms/businesslogic/Files/IFile.cs | 3 + .../businesslogic/Files/UmbracoFile.cs | 163 +++++++++--------- .../businesslogic/datatype/FileHandlerData.cs | 4 +- src/umbraco.cms/umbraco.cms.csproj | 4 + .../umbraco.editorControls.csproj | 4 + .../uploadfield/uploadField.cs | 59 ++++--- 13 files changed, 258 insertions(+), 152 deletions(-) create mode 100644 src/Umbraco.Core/IO/AbstractFileSystem.cs diff --git a/src/Umbraco.Core/IO/AbstractFileSystem.cs b/src/Umbraco.Core/IO/AbstractFileSystem.cs new file mode 100644 index 0000000000..3e49742c03 --- /dev/null +++ b/src/Umbraco.Core/IO/AbstractFileSystem.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.IO +{ + public abstract class AbstractFileSystem : IFileSystem + { + public abstract IEnumerable GetDirectories(string path); + + public abstract void DeleteDirectory(string path); + + public abstract void DeleteDirectory(string path, bool recursive); + + public abstract bool DirectoryExists(string path); + + public abstract void AddFile(string path, Stream stream); + + public abstract void AddFile(string path, Stream stream, bool overrideIfExists); + + public abstract IEnumerable GetFiles(string path); + + public abstract IEnumerable GetFiles(string path, string filter); + + public abstract Stream OpenFile(string path); + + public abstract void DeleteFile(string path); + + public abstract bool FileExists(string path); + + public abstract string GetRelativePath(string fullPathOrUrl); + + public abstract string GetFullPath(string path); + + public abstract string GetUrl(string path); + + public virtual long GetSize(string path) + { + var s = OpenFile(path); + var size = s.Length; + s.Close(); + + return size; + } + + public abstract DateTimeOffset GetLastModified(string path); + + public abstract DateTimeOffset GetCreated(string path); + } +} diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs index 3a2c426754..0bb11527ea 100644 --- a/src/Umbraco.Core/IO/IFileSystem.cs +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -6,32 +6,37 @@ namespace Umbraco.Core.IO { internal interface IFileSystem { + IEnumerable GetDirectories(string path); + void DeleteDirectory(string path); void DeleteDirectory(string path, bool recursive); - IEnumerable GetFiles(string path); - - IEnumerable GetFiles(string path, string filter); - - IEnumerable GetDirectories(string path); - - string GetFullPath(string path); - - string GetUrl(string path); - - void DeleteFile(string path); - - bool FileExists(string path); - bool DirectoryExists(string path); + void AddFile(string path, Stream stream); void AddFile(string path, Stream stream, bool overrideIfExists); + IEnumerable GetFiles(string path); + + IEnumerable GetFiles(string path, string filter); + Stream OpenFile(string path); + void DeleteFile(string path); + + bool FileExists(string path); + + string GetRelativePath(string fullPathOrUrl); + + string GetFullPath(string path); + + string GetUrl(string path); + + long GetSize(string path); + DateTimeOffset GetLastModified(string path); DateTimeOffset GetCreated(string path); diff --git a/src/Umbraco.Core/IO/PhysicalFileSystem.cs b/src/Umbraco.Core/IO/PhysicalFileSystem.cs index 30398c5e04..5b2cbd7db5 100644 --- a/src/Umbraco.Core/IO/PhysicalFileSystem.cs +++ b/src/Umbraco.Core/IO/PhysicalFileSystem.cs @@ -7,7 +7,7 @@ using System.Web; namespace Umbraco.Core.IO { - internal class PhysicalFileSystem : IFileSystem + internal class PhysicalFileSystem : AbstractFileSystem { private readonly string _rootPath; private readonly string _rootUrl; @@ -33,14 +33,14 @@ namespace Umbraco.Core.IO _rootUrl = rootUrl; } - public IEnumerable GetDirectories(string path) + public override IEnumerable GetDirectories(string path) { path = EnsureTrailingSeparator(GetFullPath(path)); try { if (Directory.Exists(path)) - return Directory.EnumerateDirectories(path).Select(MakeRelativePath); + return Directory.EnumerateDirectories(path).Select(GetRelativePath); } catch (UnauthorizedAccessException ex) { } @@ -50,12 +50,12 @@ namespace Umbraco.Core.IO return Enumerable.Empty(); } - public virtual void DeleteDirectory(string path) + public override void DeleteDirectory(string path) { DeleteDirectory(path, false); } - public void DeleteDirectory(string path, bool recursive) + public override void DeleteDirectory(string path, bool recursive) { if (!DirectoryExists(path)) return; @@ -68,17 +68,17 @@ namespace Umbraco.Core.IO { } } - public bool DirectoryExists(string path) + public override bool DirectoryExists(string path) { return Directory.Exists(GetFullPath(path)); } - public void AddFile(string path, Stream stream) + public override void AddFile(string path, Stream stream) { AddFile(path, stream, true); } - public void AddFile(string path, Stream stream, bool overrideIfExists) + public override void AddFile(string path, Stream stream, bool overrideIfExists) { if (FileExists(path) && !overrideIfExists) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", @@ -90,19 +90,19 @@ namespace Umbraco.Core.IO stream.CopyTo(destination); } - public IEnumerable GetFiles(string path) + public override IEnumerable GetFiles(string path) { return GetFiles(path, "*.*"); } - public IEnumerable GetFiles(string path, string filter) + public override IEnumerable GetFiles(string path, string filter) { path = EnsureTrailingSeparator(GetFullPath(path)); try { if (Directory.Exists(path)) - return Directory.EnumerateFiles(path, filter).Select(MakeRelativePath); + return Directory.EnumerateFiles(path, filter).Select(GetRelativePath); } catch (UnauthorizedAccessException ex) { } @@ -112,12 +112,12 @@ namespace Umbraco.Core.IO return Enumerable.Empty(); } - public Stream OpenFile(string path) + public override Stream OpenFile(string path) { return File.OpenRead(GetFullPath(path)); } - public void DeleteFile(string path) + public override void DeleteFile(string path) { if (!FileExists(path)) return; @@ -130,33 +130,44 @@ namespace Umbraco.Core.IO { } } - public bool FileExists(string path) + public override bool FileExists(string path) { return File.Exists(GetFullPath(path)); } - public string GetFullPath(string path) + public override string GetRelativePath(string fullPathOrUrl) + { + var relativePath = fullPathOrUrl + .TrimStart(_rootUrl) + .Replace('/', Path.DirectorySeparatorChar) + .TrimStart(_rootPath) + .TrimStart(Path.DirectorySeparatorChar); + + return relativePath; + } + + public override string GetFullPath(string path) { return !path.StartsWith(_rootPath) ? Path.Combine(_rootPath, path) : path; } - public string GetUrl(string path) + public override string GetUrl(string path) { return _rootUrl.TrimEnd("/") + "/" + path .TrimStart(Path.DirectorySeparatorChar) .Replace(Path.DirectorySeparatorChar, '/'); } - public DateTimeOffset GetLastModified(string path) + public override DateTimeOffset GetLastModified(string path) { return DirectoryExists(path) ? new DirectoryInfo(GetFullPath(path)).LastWriteTimeUtc : new FileInfo(GetFullPath(path)).LastWriteTimeUtc; } - public DateTimeOffset GetCreated(string path) + public override DateTimeOffset GetCreated(string path) { return DirectoryExists(path) ? Directory.GetCreationTimeUtc(GetFullPath(path)) @@ -165,14 +176,6 @@ namespace Umbraco.Core.IO #region Helper Methods - protected string MakeRelativePath(string fullPath) - { - return fullPath.Substring(_rootPath.Length).TrimStart(new char[1] - { - Path.DirectorySeparatorChar - }); - } - protected virtual void EnsureDirectory(string path) { path = GetFullPath(path); diff --git a/src/Umbraco.Core/Properties/AssemblyInfo.cs b/src/Umbraco.Core/Properties/AssemblyInfo.cs index fd937747fc..363d4e0f63 100644 --- a/src/Umbraco.Core/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Core/Properties/AssemblyInfo.cs @@ -21,4 +21,5 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("cms")] [assembly: InternalsVisibleTo("umbraco")] [assembly: InternalsVisibleTo("businesslogic")] +[assembly: InternalsVisibleTo("umbraco.editorControls")] [assembly: InternalsVisibleTo("Umbraco.Tests")] \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 8ae92f2038..d5621bf47f 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -51,6 +51,7 @@ + diff --git a/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs index debcd8492b..5379dcd059 100644 --- a/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/AbstractFileSystemTests.cs @@ -136,6 +136,35 @@ namespace Umbraco.Tests.IO _fileSystem.DeleteFile("test.txt"); } + [Test] + public void Can_Convert_Full_Path_And_Url_To_Relative_Path() + { + _fileSystem.AddFile("test.txt", CreateStream()); + + var url = _fileSystem.GetUrl("test.txt"); + var fullPath = _fileSystem.GetFullPath("test.txt"); + + Assert.AreNotEqual("test.txt", url); + Assert.AreNotEqual("test.txt", fullPath); + + Assert.AreEqual("test.txt", _fileSystem.GetRelativePath(url)); + Assert.AreEqual("test.txt", _fileSystem.GetRelativePath(fullPath)); + + _fileSystem.DeleteFile("test.txt"); + } + + [Test] + public void Can_Get_Size() + { + var stream = CreateStream(); + var streamLength = stream.Length; + _fileSystem.AddFile("test.txt", stream); + + Assert.AreEqual(streamLength, _fileSystem.GetSize("test.txt")); + + _fileSystem.DeleteFile("test.txt"); + } + #region Helper Methods protected Stream CreateStream(string contents = null) diff --git a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs index b18e10c58a..f320b9ec02 100644 --- a/src/Umbraco.Web/umbraco.presentation/default.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/default.aspx.cs @@ -4,6 +4,8 @@ using System.Web.UI; using System.IO; using System.Xml; using System.Text.RegularExpressions; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; using umbraco.presentation; using umbraco.cms.businesslogic.web; using umbraco.cms.businesslogic; diff --git a/src/umbraco.cms/businesslogic/Files/IFile.cs b/src/umbraco.cms/businesslogic/Files/IFile.cs index 7bfb4490f5..ccf858fb02 100644 --- a/src/umbraco.cms/businesslogic/Files/IFile.cs +++ b/src/umbraco.cms/businesslogic/Files/IFile.cs @@ -9,7 +9,10 @@ namespace umbraco.cms.businesslogic.Files { string Filename { get; } string Extension { get; } + [Obsolete("LocalName is obsolete, please use URL instead", false)] string LocalName { get; } + string Path { get; } + string Url { get; } bool SupportsResizing { get; } string GetFriendlyName(); System.Tuple GetDimensions(); diff --git a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs index ec1d7666b4..a8f65839a2 100644 --- a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs +++ b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs @@ -6,109 +6,89 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Web; +using Umbraco.Core.IO; using Encoder = System.Text.Encoder; namespace umbraco.cms.businesslogic.Files { public class UmbracoFile : IFile { - private string _fullFilePath; + private string _path; private string _fileName; - private string _directoryName; private string _extension; - private string _localName; + private string _url; private long _length; + private IFileSystem _fs; + + #region Constructors + public UmbracoFile() { - + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); } - public UmbracoFile(string fullFilePath) + public UmbracoFile(string path) { - _fullFilePath = fullFilePath; + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); + + _path = path; + initialize(); } + + #endregion - public static UmbracoFile Save(HttpPostedFile file, string fullFileName) + #region Static Methods + + //MB: Do we really need all these overloads? looking through the code, only one of them is actually used + + public static UmbracoFile Save(HttpPostedFile file, string path) { - byte[] fileData = null; - using (var binaryReader = new BinaryReader(file.InputStream)) - { - fileData = binaryReader.ReadBytes(file.ContentLength); - } - - return Save(fileData, fullFileName); + return Save(file.InputStream, path); } - public static UmbracoFile Save(HttpPostedFileBase file, string fullFileName) + public static UmbracoFile Save(HttpPostedFileBase file, string path) { - byte[] fileData = null; - using (var binaryReader = new BinaryReader(file.InputStream)) - { - fileData = binaryReader.ReadBytes(file.ContentLength); - } - - return Save(fileData, fullFileName); + return Save(file.InputStream, path); } - public static UmbracoFile Save(Stream inputStream, string fullFileName){ - - byte[] fileData = null; - using (var binaryReader = new BinaryReader(inputStream)) - { - fileData = binaryReader.ReadBytes((int)inputStream.Length); - } + public static UmbracoFile Save(Stream inputStream, string path) + { + var fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); + fs.AddFile(path, inputStream); - return Save(fileData, fullFileName); + return new UmbracoFile(path); } - public static UmbracoFile Save(byte[] file, string fullFileName) + public static UmbracoFile Save(byte[] file, string relativePath) { - string fullFilePath = IO.IOHelper.MapPath(fullFileName); - - // create directories - DirectoryInfo di = new DirectoryInfo(IO.IOHelper.MapPath(fullFilePath.Substring(0, fullFilePath.LastIndexOf(Path.DirectorySeparatorChar)))); - if (!di.Exists) - { - var currentDir = IO.IOHelper.MapPath(IO.SystemDirectories.Root); - var rootDir = IO.IOHelper.MapPath(IO.SystemDirectories.Root); - foreach (var dir in di.FullName.Substring(rootDir.Length).Split(Path.DirectorySeparatorChar)) - { - currentDir = Path.Combine(currentDir, dir); - if (!new DirectoryInfo(currentDir).Exists) - { - Directory.CreateDirectory(currentDir); - } - } - } - - File.WriteAllBytes(fullFilePath, file); - return new UmbracoFile(fullFilePath); + return Save(new MemoryStream(file), relativePath); } public static UmbracoFile Save(HttpPostedFile file) { - string tempDir = Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); - return Save(file, tempDir); - } - //filebase overload... - public static UmbracoFile Save(HttpPostedFileBase file) - { - string tempDir = Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); + string tempDir = System.IO.Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); return Save(file, tempDir); } + //filebase overload... + public static UmbracoFile Save(HttpPostedFileBase file) + { + string tempDir = System.IO.Path.Combine(IO.SystemDirectories.Media, "uploads", Guid.NewGuid().ToString()); + return Save(file, tempDir); + } + + #endregion + private void initialize() { - var fi = new FileInfo(_fullFilePath); - _fileName = fi.Name; - _length = fi.Length; - _directoryName = fi.DirectoryName; - _extension = fi.Extension.Substring(1).ToLowerInvariant(); - _localName = - "/" + fi.FullName.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length).Replace( - Path.DirectorySeparatorChar.ToString(), "/"); + _fileName = System.IO.Path.GetFileName(_path); + _length = _fs.GetSize(_path); + _extension = System.IO.Path.GetExtension(_path) != null + ? System.IO.Path.GetExtension(_path).Substring(1).ToLowerInvariant() + : ""; + _url = _fs.GetUrl(_path); } #region IFile Members @@ -124,9 +104,20 @@ namespace umbraco.cms.businesslogic.Files get { return _extension; } } + [Obsolete("LocalName is obsolete, please use Url instead", false)] public string LocalName { - get { return _localName; } + get { return Url; } + } + + public string Path + { + get { return _path; } + } + + public string Url + { + get { return _url; } } public long Length @@ -155,11 +146,8 @@ namespace umbraco.cms.businesslogic.Files { throwNotAnImageException(); - - FileStream fs = new FileStream(_fullFilePath, - FileMode.Open, FileAccess.Read, FileShare.Read); - - Image image = Image.FromStream(fs); + var fs = _fs.OpenFile(_path); + var image = Image.FromStream(fs); var fileWidth = image.Width; var fileHeight = image.Height; fs.Close(); @@ -172,42 +160,43 @@ namespace umbraco.cms.businesslogic.Files { throwNotAnImageException(); - string fileNameThumb = DoResize(width, height, 0, String.Empty); + var fileNameThumb = DoResize(width, height, 0, String.Empty); - return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length-1); + return _fs.GetUrl(fileNameThumb); } public string Resize(int maxWidthHeight, string fileNameAddition) { throwNotAnImageException(); - string fileNameThumb = DoResize(GetDimensions().Item1, GetDimensions().Item2, maxWidthHeight, fileNameAddition); + var fileNameThumb = DoResize(GetDimensions().Item1, GetDimensions().Item2, maxWidthHeight, fileNameAddition); - return fileNameThumb.Substring(IO.IOHelper.MapPath(IO.SystemDirectories.Root).Length); + return _fs.GetUrl(fileNameThumb); } private string DoResize(int width, int height, int maxWidthHeight, string fileNameAddition) { - - FileStream fs = new FileStream(_fullFilePath, - FileMode.Open, FileAccess.Read, FileShare.Read); - Image image = Image.FromStream(fs); + var fs = _fs.OpenFile(_path); + var image = Image.FromStream(fs); fs.Close(); string fileNameThumb = String.IsNullOrEmpty(fileNameAddition) ? - string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf("."))) : - string.Format("{0}_{1}.jpg", _fullFilePath.Substring(0, _fullFilePath.LastIndexOf(".")), fileNameAddition); + string.Format("{0}_UMBRACOSYSTHUMBNAIL.jpg", _path.Substring(0, _path.LastIndexOf("."))) : + string.Format("{0}_{1}.jpg", _path.Substring(0, _path.LastIndexOf(".")), fileNameAddition); + fileNameThumb = generateThumbnail( image, maxWidthHeight, width, height, - _fullFilePath, + _path, _extension, fileNameThumb, maxWidthHeight == 0 ).FileName; + image.Dispose(); + return fileNameThumb; } @@ -269,7 +258,13 @@ namespace umbraco.cms.businesslogic.Files // Save the new image using the dimensions of the image string newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh)); - bp.Save(newFileName, codec, ep); + var ms = new MemoryStream(); + bp.Save(ms, codec, ep); + ms.Seek(0, 0); + + _fs.AddFile(newFileName, ms); + + ms.Close(); bp.Dispose(); g.Dispose(); diff --git a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs index dfb21afdad..f399f9600b 100644 --- a/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs +++ b/src/umbraco.cms/businesslogic/datatype/FileHandlerData.cs @@ -58,7 +58,7 @@ namespace umbraco.cms.businesslogic.datatype ? Path.Combine(PropertyId.ToString(), name) : PropertyId + "-" + name; - fileName = Path.Combine(SystemDirectories.Media, fileName); + //fileName = Path.Combine(SystemDirectories.Media, fileName); um = UmbracoFile.Save(fileStream, fileName); if (um.SupportsResizing) @@ -111,7 +111,7 @@ namespace umbraco.cms.businesslogic.datatype } } - base.Value = um.LocalName; + base.Value = um.Url; } else { diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj index 3ff2f6eac3..068836f738 100644 --- a/src/umbraco.cms/umbraco.cms.csproj +++ b/src/umbraco.cms/umbraco.cms.csproj @@ -147,6 +147,10 @@ {E469A9CE-1BEC-423F-AC44-713CD72457EA} {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + {31785BC3-256C-4613-B2F5-A1B0BDDED8C1} + Umbraco.Core + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2} umbraco.datalayer diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index b4636781e3..8b1570ed2c 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -102,6 +102,10 @@ AllRules.ruleset + + {31785bc3-256c-4613-b2f5-a1b0bdded8c1} + Umbraco.Core + {651E1350-91B6-44B7-BD60-7207006D7003} Umbraco.Web diff --git a/src/umbraco.editorControls/uploadfield/uploadField.cs b/src/umbraco.editorControls/uploadfield/uploadField.cs index 4b57d3e78c..dbd0d6f46e 100644 --- a/src/umbraco.editorControls/uploadfield/uploadField.cs +++ b/src/umbraco.editorControls/uploadfield/uploadField.cs @@ -4,6 +4,7 @@ using System.Text.RegularExpressions; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; +using Umbraco.Core.IO; using umbraco.interfaces; using umbraco.IO; using Content = umbraco.cms.businesslogic.Content; @@ -18,8 +19,11 @@ namespace umbraco.editorControls private readonly String _thumbnails; private String _text; + private IFileSystem _fs; + public uploadField(IData Data, string ThumbnailSizes) { + _fs = FileSystemProviderManager.Current.GetFileSystemProvider(FileSystemProvider.Media); _data = (cms.businesslogic.datatype.DefaultData) Data; _thumbnails = ThumbnailSizes; } @@ -107,8 +111,6 @@ namespace umbraco.editorControls // we update additional properties post image upload if (_data.Value != DBNull.Value && !string.IsNullOrEmpty(_data.Value.ToString())) { - string fullFilePath = IOHelper.MapPath(_data.Value.ToString()); - Content content = Content.GetContentFromVersion(_data.Version); // update extension in UI @@ -177,27 +179,29 @@ namespace umbraco.editorControls Text = _data.Value.ToString(); } - private void deleteFile(string file) + private void deleteFile(string fileUrl) { - if (file.Length > 0) + if (fileUrl.Length > 0) { - // delete old file - if (File.Exists(IOHelper.MapPath(file))) - File.Delete(IOHelper.MapPath(file)); + var relativeFilePath = _fs.GetRelativePath(fileUrl); - string extension = (file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)); + // delete old file + if (_fs.FileExists(relativeFilePath)) + _fs.DeleteFile(relativeFilePath); + + string extension = (relativeFilePath.Substring(relativeFilePath.LastIndexOf(".") + 1, relativeFilePath.Length - relativeFilePath.LastIndexOf(".") - 1)); extension = extension.ToLower(); //check for thumbnails if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) { //delete thumbnails - string thumbnailfile = file.Replace("." + extension, "_thumb"); + string relativeThumbFilePath = relativeFilePath.Replace("." + extension, "_thumb"); try { - if (File.Exists(IOHelper.MapPath(thumbnailfile + _thumbnailext))) - File.Delete(IOHelper.MapPath(thumbnailfile + _thumbnailext)); + if (_fs.FileExists(relativeThumbFilePath + _thumbnailext)) + _fs.DeleteFile(relativeThumbFilePath + _thumbnailext); } catch { @@ -210,12 +214,12 @@ namespace umbraco.editorControls { if (thumb != "") { - string thumbnailextra = thumbnailfile + "_" + thumb + _thumbnailext; + string relativeExtraThumbFilePath = relativeThumbFilePath + "_" + thumb + _thumbnailext; try { - if (File.Exists(IOHelper.MapPath(thumbnailextra))) - File.Delete(IOHelper.MapPath(thumbnailextra)); + if (_fs.FileExists(relativeExtraThumbFilePath)) + _fs.DeleteFile(relativeExtraThumbFilePath); } catch { @@ -269,17 +273,18 @@ namespace umbraco.editorControls { if (!string.IsNullOrEmpty(Text)) { - string ext = _text.Substring(_text.LastIndexOf(".") + 1, _text.Length - _text.LastIndexOf(".") - 1); - string fileNameThumb = _text.Replace("." + ext, "_thumb.jpg"); - bool hasThumb = false; + var relativeFilePath = _fs.GetRelativePath(_text); + var ext = relativeFilePath.Substring(relativeFilePath.LastIndexOf(".") + 1, relativeFilePath.Length - relativeFilePath.LastIndexOf(".") - 1); + var relativeThumbFilePath = relativeFilePath.Replace("." + ext, "_thumb.jpg"); + var hasThumb = false; try { - hasThumb = File.Exists(IOHelper.MapPath(IOHelper.FindFile(fileNameThumb))); + hasThumb = _fs.FileExists(relativeThumbFilePath); // 4.8.0 added support for png thumbnails (but for legacy it might have been jpg - hence the check before) if (!hasThumb && (ext == "gif" || ext == "png")) { - fileNameThumb = _text.Replace("." + ext, "_thumb.png"); - hasThumb = File.Exists(IOHelper.MapPath(IOHelper.FindFile(fileNameThumb))); + relativeThumbFilePath = relativeFilePath.Replace("." + ext, "_thumb.png"); + hasThumb = _fs.FileExists(relativeThumbFilePath); } } catch @@ -287,17 +292,19 @@ namespace umbraco.editorControls } if (hasThumb) { - var thumb = new Image(); - thumb.ImageUrl = fileNameThumb; - thumb.BorderStyle = BorderStyle.None; + var thumb = new Image + { + ImageUrl = _fs.GetUrl(relativeThumbFilePath), + BorderStyle = BorderStyle.None + }; - output.WriteLine(""); + output.WriteLine(""); thumb.RenderControl(output); output.WriteLine("
    "); } else - output.WriteLine("" + - IOHelper.FindFile(Text) + "
    "); + output.WriteLine("" + + _fs.GetUrl(relativeFilePath) + "
    "); output.WriteLine("