Fixes various issues relating to File Repositories and Services: U4-4014 FileRepositories offer no way to create folders, U4-4013 The models that the FileService produces causes security exceptions, U4-3993 Replace system.io calls in umbraco.scriptTasks legacy task

updates to latest CDF
This commit is contained in:
Shannon
2014-01-09 18:08:13 +11:00
parent 7c720460f5
commit 4db6ce4b22
24 changed files with 199 additions and 83 deletions

View File

@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
@@ -30,5 +31,17 @@ namespace Umbraco.Core.IO
{
return Path.GetFileName(fs.GetFullPath(path));
}
//TODO: Currently this is the only way to do this
internal static void CreateFolder(this IFileSystem fs, string folderPath)
{
var path = fs.GetRelativePath(folderPath);
var tempFile = Path.Combine(path, Guid.NewGuid().ToString("N") + ".tmp");
using (var s = new MemoryStream())
{
fs.AddFile(tempFile, s);
}
fs.DeleteFile(tempFile);
}
}
}

View File

@@ -5,6 +5,8 @@ using Umbraco.Core.CodeAnnotations;
namespace Umbraco.Core.IO
{
//TODO: There is no way to create a directory here without creating a file in a directory and then deleting it
public interface IFileSystem
{
IEnumerable<string> GetDirectories(string path);

View File

@@ -6,6 +6,16 @@ using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
internal sealed class Folder : Entity
{
public Folder(string folderPath)
{
Path = folderPath;
}
public string Path { get; set; }
}
/// <summary>
/// Represents an abstract file which provides basic functionality for a File with an Alias and Name
/// </summary>
@@ -23,6 +33,8 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Path);
private string _alias;
private string _name;
/// <summary>
/// Gets or sets the Name of the File including extension
@@ -32,7 +44,11 @@ namespace Umbraco.Core.Models
{
get
{
return new FileInfo(Path).Name;
if (_name == null)
{
_name = System.IO.Path.GetFileName(Path);
}
return _name;
}
}
@@ -44,10 +60,14 @@ namespace Umbraco.Core.Models
{
get
{
var fileInfo = new FileInfo(Path);
var name = fileInfo.Name;
int lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
return name.Substring(0, lastIndexOf);
if (_alias == null)
{
var name = System.IO.Path.GetFileName(Path);
if (name == null) return string.Empty;
var lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
_alias = name.Substring(0, lastIndexOf);
}
return _alias;
}
}
@@ -60,6 +80,10 @@ namespace Umbraco.Core.Models
get { return _path; }
set
{
//reset
_alias = null;
_name = null;
SetPropertyValueAndDetectChanges(o =>
{
_path = value;

View File

@@ -33,6 +33,16 @@ namespace Umbraco.Core.Persistence.Repositories
get { return _fileSystem; }
}
internal virtual void AddFolder(string folderPath)
{
_work.RegisterAdded(new Folder(folderPath), this);
}
internal virtual void DeleteFolder(string folderPath)
{
_work.RegisterRemoved(new Folder(folderPath), this);
}
#region Implementation of IRepository<TId,TEntity>
public virtual void AddOrUpdate(TEntity entity)
@@ -68,7 +78,16 @@ namespace Umbraco.Core.Persistence.Repositories
public void PersistNewItem(IEntity entity)
{
PersistNewItem((TEntity)entity);
//special case for folder
var folder = entity as Folder;
if (folder != null)
{
PersistNewFolder(folder);
}
else
{
PersistNewItem((TEntity)entity);
}
}
public void PersistUpdatedItem(IEntity entity)
@@ -78,23 +97,46 @@ namespace Umbraco.Core.Persistence.Repositories
public void PersistDeletedItem(IEntity entity)
{
PersistDeletedItem((TEntity)entity);
//special case for folder
var folder = entity as Folder;
if (folder != null)
{
PersistDeletedFolder(folder);
}
else
{
PersistDeletedItem((TEntity)entity);
}
}
#endregion
#region Abstract IUnitOfWorkRepository Methods
internal virtual void PersistNewFolder(Folder entity)
{
_fileSystem.CreateFolder(entity.Path);
}
internal virtual void PersistDeletedFolder(Folder entity)
{
_fileSystem.DeleteDirectory(entity.Path);
}
#region Abstract IUnitOfWorkRepository Methods
protected virtual void PersistNewItem(TEntity entity)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content));
FileSystem.AddFile(entity.Name, stream, true);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)))
{
FileSystem.AddFile(entity.Path, stream, true);
}
}
protected virtual void PersistUpdatedItem(TEntity entity)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content));
FileSystem.AddFile(entity.Name, stream, true);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)))
{
FileSystem.AddFile(entity.Path, stream, true);
}
}
protected virtual void PersistDeletedItem(TEntity entity)

View File

@@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories
{
public interface IScriptRepository : IRepository<string, Script>
{
}
}

View File

@@ -28,9 +28,10 @@ namespace Umbraco.Core.Persistence.Repositories
public override Script Get(string id)
{
if(!FileSystem.FileExists(id))
if(FileSystem.FileExists(id) == false)
{
throw new Exception(string.Format("The file {0} was not found", id));
return null;
//throw new Exception(string.Format("The file {0} was not found", id));
}
string content = string.Empty;

View File

@@ -23,24 +23,4 @@ namespace Umbraco.Core.Persistence.SqlSyntax
set { _sqlSyntaxProvider = value; }
}
}
internal static class SqlSyntaxProviderExtensions
{
/// <summary>
/// This is used to generate a delete query that uses a sub-query to select the data, it is required because there's a very particular syntax that
/// needs to be used to work for all servers: MySql, SQLCE and MSSQL
/// </summary>
/// <returns></returns>
/// <remarks>
/// See: http://issues.umbraco.org/issue/U4-3876
/// </remarks>
public static string GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery)
{
return string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)",
sqlProvider.GetQuotedTableName(tableName),
sqlProvider.GetQuotedColumnName(columnName),
subQuery.SQL);
}
}
}

View File

@@ -0,0 +1,22 @@
namespace Umbraco.Core.Persistence.SqlSyntax
{
internal static class SqlSyntaxProviderExtensions
{
/// <summary>
/// This is used to generate a delete query that uses a sub-query to select the data, it is required because there's a very particular syntax that
/// needs to be used to work for all servers: MySql, SQLCE and MSSQL
/// </summary>
/// <returns></returns>
/// <remarks>
/// See: http://issues.umbraco.org/issue/U4-3876
/// </remarks>
public static string GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery)
{
return string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)",
sqlProvider.GetQuotedTableName(tableName),
sqlProvider.GetQuotedColumnName(columnName),
subQuery.SQL);
}
}
}

View File

@@ -4,6 +4,7 @@ using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
@@ -195,6 +196,26 @@ namespace Umbraco.Core.Services
return script.IsValid();
}
public void CreateScriptFolder(string folderPath)
{
var uow = _fileUowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateScriptRepository(uow))
{
((ScriptRepository)repository).AddFolder(folderPath);
uow.Commit();
}
}
public void DeleteScriptFolder(string folderPath)
{
var uow = _fileUowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateScriptRepository(uow))
{
((ScriptRepository)repository).DeleteFolder(folderPath);
uow.Commit();
}
}
/// <summary>
/// Gets a list of all <see cref="ITemplate"/> objects
/// </summary>

View File

@@ -76,6 +76,19 @@ namespace Umbraco.Core.Services
/// <returns>True if Script is valid, otherwise false</returns>
bool ValidateScript(Script script);
/// <summary>
/// Creates a folder for scripts
/// </summary>
/// <param name="folderPath"></param>
/// <returns></returns>
void CreateScriptFolder(string folderPath);
/// <summary>
/// Deletes a folder for scripts
/// </summary>
/// <param name="folderPath"></param>
void DeleteScriptFolder(string folderPath);
/// <summary>
/// Gets a list of all <see cref="ITemplate"/> objects
/// </summary>

View File

@@ -209,6 +209,7 @@
<Compile Include="Persistence\SqlSyntax\SqlCeSyntax.cs" />
<Compile Include="Persistence\SqlSyntax\SqlServerSyntax.cs" />
<Compile Include="Persistence\SqlSyntax\SqlServerVersionName.cs" />
<Compile Include="Persistence\SqlSyntax\SqlSyntaxProviderExtensions.cs" />
<Compile Include="PropertyEditors\PropertyCacheValue.cs" />
<Compile Include="PropertyEditors\PropertyValueCacheAttribute.cs" />
<Compile Include="PropertyEditors\PropertyValueTypeAttribute.cs" />

View File

@@ -101,9 +101,9 @@
<Project>{07fbc26b-2927-4a22-8d96-d644c667fecc}</Project>
<Name>UmbracoExamine</Name>
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net40" />
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />

View File

@@ -93,9 +93,9 @@
<Project>{07fbc26b-2927-4a22-8d96-d644c667fecc}</Project>
<Name>UmbracoExamine</Name>
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="CookComputing.XmlRpcV2, Version=2.5.0.0, Culture=neutral, PublicKeyToken=a7d6e17aa302004d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
<package id="CodeSharp.Package.AspNetWebPage" version="1.0" targetFramework="net40" />
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />

View File

@@ -1,7 +1,9 @@
using System;
using System.Data;
using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using umbraco.BusinessLogic;
using umbraco.DataLayer;
using umbraco.BasePages;
@@ -42,48 +44,43 @@ namespace umbraco
public bool Save()
{
string[] scriptFileAr = _alias.Split('\u00A4');
var scriptFileAr = _alias.Split('\u00A4');
var relPath = scriptFileAr[0];
var fileName = scriptFileAr[1];
var fileType = scriptFileAr[2];
var createFolder = ParentID;
string relPath = scriptFileAr[0];
string fileName = scriptFileAr[1];
string fileType = scriptFileAr[2];
if (createFolder == 1)
{
ApplicationContext.Current.Services.FileService.CreateScriptFolder(relPath + fileName);
return true;
}
int createFolder = ParentID;
string basePath = IOHelper.MapPath(SystemDirectories.Scripts + "/" + relPath + fileName);
if (System.IO.File.Exists(basePath))
var found = ApplicationContext.Current.Services.FileService.GetScriptByName(relPath + fileName + "." + fileType);
if (found != null)
{
m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName, fileType);
return true;
}
else
{
if (createFolder == 1)
{
System.IO.Directory.CreateDirectory(basePath);
}
else
{
System.IO.File.Create(basePath + "." + fileType).Close();
m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName,
fileType);
}
}
ApplicationContext.Current.Services.FileService.SaveScript(new Script(relPath + fileName + "." + fileType));
m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName, fileType);
return true;
}
public bool Delete()
{
string path = IOHelper.MapPath(SystemDirectories.Scripts + "/" + _alias.TrimStart('/'));
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
else if (System.IO.Directory.Exists(path))
System.IO.Directory.Delete(path, true);
LogHelper.Info<ScriptTasks>(string.Format("{0} Deleted by user {1}", _alias, UmbracoEnsuredPage.CurrentUser.Id));
if (_alias.Contains(".") == false)
{
//there is no extension so we'll assume it's a folder
ApplicationContext.Current.Services.FileService.DeleteScriptFolder(_alias.TrimStart('/'));
}
else
{
ApplicationContext.Current.Services.FileService.DeleteScript(_alias.TrimStart('/'));
}
return true;
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
<package id="Tidy.Net" version="1.0.0" targetFramework="net40" />

View File

@@ -104,9 +104,9 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.6.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
</packages>

View File

@@ -66,9 +66,9 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
</packages>

View File

@@ -112,9 +112,9 @@
<Project>{651E1350-91B6-44B7-BD60-7207006D7003}</Project>
<Name>Umbraco.Web</Name>
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="System">
<Name>System</Name>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
<package id="ClientDependency" version="1.7.1.1" targetFramework="net40" />
<package id="Microsoft.ApplicationBlocks.Data" version="1.0.1559.20655" targetFramework="net40" />
</packages>

View File

@@ -104,9 +104,9 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.7.0.4, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ClientDependency.Core, Version=1.7.1.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll</HintPath>
<HintPath>..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.ApplicationBlocks.Data, Version=1.0.1559.20655, Culture=neutral">
<SpecificVersion>False</SpecificVersion>