Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Media is still accessible via it's original URL after its been sent to the recycle bin #3568

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/Umbraco.Core/Media/UmbracoFileProperty.cs
@@ -0,0 +1,53 @@
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Models;

namespace Umbraco.Core.Media
{
public class UmbracoFileProperty
{
private readonly IMedia _media;

public UmbracoFileProperty(IMedia media)
{
_media = media;
}

private Property Property()
{
return _media.Properties.FirstOrDefault(x => x.Alias.InvariantEquals("umbracoFile"));
}

public string Src
{
get
{
var value = Property()?.Value as string;
if (value != null && value.DetectIsJson())
{
// the property value is a JSON serialized image crop data set - grab the "src" property as the file source
var jObject = JsonConvert.DeserializeObject<JObject>(value);
value = jObject != null ? jObject.GetValueAsString("src") : value;
}
return value;
}
set
{
var property = Property();
if (property == null)
{
return;
}
var filename = property?.Value as string;
if (filename != null && filename.DetectIsJson())
{
var jObject = JsonConvert.DeserializeObject<JObject>(value);
jObject.Property("src").Value = value;
}

property.Value = value;
}
}
}
}
3 changes: 2 additions & 1 deletion src/Umbraco.Core/Models/Media.cs
Expand Up @@ -117,6 +117,7 @@ public override void ChangeTrashedState(bool isTrashed, int parentId = -20)
Trashed = isTrashed;
//The Media Recycle Bin Id is -21 so we correct that here
ParentId = parentId == -20 ? -21 : parentId;

}
}
}
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Services/IMediaService.cs
Expand Up @@ -112,7 +112,7 @@ public interface IMediaService : IContentServiceBase
/// <param name="mediaTypeAlias">Alias of the <see cref="IMediaType"/></param>
/// <param name="userId">Optional id of the user creating the media item</param>
/// <returns><see cref="IMedia"/></returns>
IMedia CreateMedia(string name, Guid parentId, string mediaTypeAlias, int userId = 0);
IMedia CreateMedia(string name, Guid parentId, string mediaTypeAlias, int userId = 0);

/// <summary>
/// Creates an <see cref="IMedia"/> object using the alias of the <see cref="IMediaType"/>
Expand Down
68 changes: 67 additions & 1 deletion src/Umbraco.Core/Services/MediaService.cs
Expand Up @@ -4,12 +4,14 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Media;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
Expand Down Expand Up @@ -797,6 +799,7 @@ public Attempt<OperationStatus> Move(IMedia media, int parentId, int userId = 0)
if (media.Trashed)
{
media.ChangeTrashedState(false, parentId);
UnobfuscateTrashedMedia(media);
}
Save(media, userId, false); //no events!

Expand Down Expand Up @@ -1133,6 +1136,8 @@ private Attempt<OperationStatus> MoveToRecycleBinDo(IMedia media, int userId, bo
//must be processed with shallowest levels first
var descendants = ignoreDescendants ? Enumerable.Empty<IMedia>() : GetDescendants(media).OrderBy(x => x.Level);

ObfuscateTrashedMedia(media);

//Do the updates for this item
var repository = RepositoryFactory.CreateMediaRepository(uow);
repository.DeleteContentXml(media);
Expand All @@ -1144,8 +1149,9 @@ private Attempt<OperationStatus> MoveToRecycleBinDo(IMedia media, int userId, bo
{
repository.DeleteContentXml(descendant);
descendant.ChangeTrashedState(true, descendant.ParentId);
ObfuscateTrashedMedia(descendant);
repository.AddOrUpdate(descendant);

moveInfo.Add(new MoveEventInfo<IMedia>(descendant, descendant.Path, descendant.ParentId));
}

Expand All @@ -1161,6 +1167,58 @@ private Attempt<OperationStatus> MoveToRecycleBinDo(IMedia media, int userId, bo
}
}

private void ObfuscateTrashedMedia(IMedia media)
{
var umbracoFile = new UmbracoFileProperty(media).Src;
if (umbracoFile == null)
{
return;
}
var filename = Path.GetFileName(umbracoFile);
var newUmbracoFile = MediaPath(umbracoFile) + ObfuscateFilename(filename);
MoveFile(umbracoFile, newUmbracoFile);
media.SetValue("umbracoFile", newUmbracoFile);
}

private void UnobfuscateTrashedMedia(IMedia media)
{
var umbracoFile = new UmbracoFileProperty(media);
var path = umbracoFile.Src;
var filename = Path.GetFileName(path);
if (HasBeenObfuscated(filename))
{
var newUmbracoFile = MediaPath(path) + UnobfuscateFilename(filename);
MoveFile(path, newUmbracoFile);
umbracoFile.Src = newUmbracoFile;
}
}

private string MediaPath(string umbracoFile)
{
return Path.GetDirectoryName(umbracoFile).Replace("\\", "/") + "/";
}

private void MoveFile(string from, string to)
{
_mediaFileSystem.CopyFile(from, to);
_mediaFileSystem.DeleteFile(from);
}

private string ObfuscateFilename(string filename)
{
return Guid.NewGuid().ToString("D") + "---" + filename;
}

private string UnobfuscateFilename(string filename)
{
return filename.Split(new[] {"---"}, 2, StringSplitOptions.RemoveEmptyEntries)[1];
}

private bool HasBeenObfuscated(string filename)
{
return Regex.IsMatch(filename, @"^[0-9A-Fa-f]{8}[-]?(?:[0-9A-Fa-f]{4}[-]?){3}[0-9A-Fa-f]{12}---");
}


/// <summary>
/// Permanently deletes an <see cref="IMedia"/> object as well as all of its Children.
Expand Down Expand Up @@ -1381,6 +1439,14 @@ private IEnumerable<IMedia> UpdatePropertiesOnChildren(IEnumerable<IMedia> child
if (parentTrashed != child.Trashed)
{
child.ChangeTrashedState(parentTrashed, child.ParentId);
if (parentTrashed)
{
ObfuscateTrashedMedia(child);
}
else
{
UnobfuscateTrashedMedia(child);
}
}

eventInfo.Add(new MoveEventInfo<IMedia>(child, originalPath, child.ParentId));
Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Core/Umbraco.Core.csproj
Expand Up @@ -370,6 +370,7 @@
<Compile Include="Media\TypeDetector\RasterizedTypeDetector.cs" />
<Compile Include="Media\TypeDetector\SVGDetector.cs" />
<Compile Include="Media\TypeDetector\TIFFDetector.cs" />
<Compile Include="Media\UmbracoFileProperty.cs" />
<Compile Include="Models\AuditEntry.cs" />
<Compile Include="Models\Consent.cs" />
<Compile Include="Models\ConsentExtensions.cs" />
Expand Down