Try our conversational search powered by Generative AI!

Al Higgs
Nov 20, 2012
  4710
(1 votes)

Restricting file types in the File Manager

I work as a developer for an EPiServer partner in the UK and also have the pleasure of running many of the CMS Developer training courses in the UK and Ireland. During these courses I am often asked questions that fall into one of two categories:

  • A question that I’ve been asked several times previously;
  • A question that has me stumped and needs a bit of research;

With that in mind I felt it would be a worthwhile exercise to try and make the answers and solutions to some of these questions available to the EPiServer community – so here goes!

This particular post relates to both a question I’ve been asked during a training course and a similar requirement on a recent EPiServer project I worked on.

The question I was asked was “is it possible to prevent certain file types from being uploaded into EPiServer’s File Manager?”. The client requirement was almost exactly the opposite – we needed to be able to specify which file types could be uploaded into a folder (i.e. Starting Point). I say the requirement was the opposite because in EPiServer it is possible to specify which types of files cannot be uploaded, not which file types can be uploaded.

Let’s deal with the question first. In short, in EPiServer it is very easy to restrict certain files from being uploaded, simply by altering the “illegalCharactersRegex” attribute on the “virtualPath” element in the EPiServer configuration file (episerver.config). The default regular expression is:

"%|&|\+|/COM[0-9]([/\.]|$)|/LPT[0-9]([/\.]|$)|/PRN([/\.]|$)|/CLOCK\$([/\.]|$)|/AUX([/\.]|$)|/NUL([/\.]|$)|/CON([/\.]|$)|/.+\.$|\.\."

To prevent additional file types from being uploaded you just need to add the extension to the regular expression. An example of preventing PDF files from being uploaded is:

"%|&|\+|/COM[0-9]([/\.]|$)|/LPT[0-9]([/\.]|$)|/PRN([/\.]|$)|/CLOCK\$([/\.]|$)|/AUX([/\.]|$)|/NUL([/\.]|$)|/CON([/\.]|$)|.pdf$ |/.+\.$|\.\."

More information can be found at http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-60/Virtual-Path-Providers/.

This approach makes it possible to restrict file types from being uploaded, but imagine you wanted to ensure that only a handful of file types could be uploaded – this approach doesn’t help us because we would literally have to list every possible file type extension except for those we wanted to allow to be uploaded. This is where my client’s requirement becomes relevant – they wanted to ensure that only images could be uploaded to a particular folder i.e. Jpeg’s, Gif’s and PNG’s.

The solution

First of all we need somewhere to specify the file types i.e. extensions that are allowed for a particular starting point. We can achieve this by adding an attribute to the relevant starting point within the episerver.config file which contains a very simple regular expression, like so:

   1: <add showInFileManager="true" virtualName="Images" virtualPath="~/Images/"
   2:         bypassAccessCheck="false" indexingServiceCatalog="Web" physicalPath="C:\EPiServer\VPP\AlloyTech-Custom\Images"
   3:         name="Images" type="EPiServer.Web.Hosting.VirtualPathVersioningProvider,EPiServer" allowedExtensions="jpg|jpeg|gif|png" />

Thankfully, EPiServer does not complain about adding attributes to the configuration that are not EPiServer specific. We now need a way of checking whether the file extension of the file being uploaded into our “Images” starting point has a file extension matching one of the options in our regular expression.

Within EPiServer there are a whole host of events that can be hooked into i.e. SavingPage, SavedPage, PublishingPage and relevant for this example UnifiedFileAdding and UnifiedFileMoving. These two events are raised when a file is added, or moved – these are the two places in which we need to check the type of file the user is attempting to add. We can register handlers for both of these events via a simple InitializationModule, like so:

   1: using System;
   2: using System.Configuration;
   3: using System.Text.RegularExpressions;
   4: using EPiServer.Configuration;
   5: using EPiServer.Core;
   6: using EPiServer.Framework;
   7: using EPiServer.Framework.Initialization;
   8: using EPiServer.Web.Hosting;
   9:  
  10: namespace EPiServerLibrary.InitializationModules
  11: {
  12:     [ModuleDependencyAttribute(typeof(EPiServer.Web.InitializationModule))]
  13:     public class RestrictFileTypes : IInitializableModule
  14:     {
  15:         Boolean _unifiedFileAddingEventAttached;
  16:         Boolean _unifiedFileMovingEventAttached;
  17:  
  18:         public void Initialize(InitializationEngine context)
  19:         {
  20:             //check whether event already attached before attempting to attach
  21:             if (!this._unifiedFileAddingEventAttached)
  22:             {
  23:                 UnifiedDirectory.UnifiedFileAdding += new UnifiedDirectoryEventHandler(ValidateFileTypes);
  24:                 this._unifiedFileAddingEventAttached = true;
  25:             }
  26:             if (!this._unifiedFileMovingEventAttached)
  27:             {
  28:                 UnifiedFile.UnifiedFileMoving += new UnifiedFileEventHandler(ValidateFileTypes);
  29:                 this._unifiedFileMovingEventAttached = true;
  30:             }
  31:         }
  32:  
  33:         private void ValidateFileTypes(UnifiedFile sender, UnifiedVirtualPathEventArgs e)
  34:         {
  35:             ValidateFileTypes(e, sender.Provider);
  36:         }
  37:  
  38:         private void ValidateFileTypes(UnifiedDirectory sender, UnifiedVirtualPathEventArgs e)
  39:         {
  40:             ValidateFileTypes(e, sender.Provider);
  41:         }
  42:  
  43:         private void ValidateFileTypes(UnifiedVirtualPathEventArgs e, VirtualPathUnifiedProvider provider)
  44:         {
  45:             //check whether the currentprovider i.e. the provider that the file is being uploaded to, has a property called allowedExtensions
  46:             PropertyInformation allowedExtensionsProperty = EPiServerSection.Instance.VirtualPathSettings.Providers[provider.ProviderName].ElementInformation.Properties["allowedExtensions"];
  47:             if (allowedExtensionsProperty != null)
  48:             {
  49:                 //get the string value of the allowedExtensions i.e. the regular expression saved in the provider cofiguration element
  50:                 string allowedExtensionsRegEx = allowedExtensionsProperty.DefaultValue.ToString();
  51:                 Regex regex = new Regex(allowedExtensionsRegEx, RegexOptions.Compiled | RegexOptions.IgnoreCase);
  52:                 //check whether the regular expression pattern matches the extension of the file being uploaded
  53:                 if (!regex.IsMatch(e.NewVirtualPath.Substring(e.NewVirtualPath.LastIndexOf('.') + 1)))
  54:                 {
  55:                     e.Cancel = true;
  56:                     e.Reason = String.Format(System.Globalization.CultureInfo.InvariantCulture, LanguageManager.Instance.TranslateFallback("/filemanager/illegalfiletype", "You cannot upload files of this type to this folder. Allowed file types are: {0}."), allowedExtensionsRegEx.Replace("|",", "));
  57:                 }
  58:             }
  59:         }
  60:  
  61:         public void Preload(string[] parameters)
  62:         {
  63:             
  64:         }
  65:  
  66:         public void Uninitialize(InitializationEngine context)
  67:         {
  68:             //tidy up, detatch event handlers
  69:             if (this._unifiedFileAddingEventAttached)
  70:             {
  71:                 UnifiedDirectory.UnifiedFileAdding -= ValidateFileTypes;
  72:                 this._unifiedFileAddingEventAttached = false;
  73:             }
  74:             if (this._unifiedFileMovingEventAttached)
  75:             {
  76:                 UnifiedFile.UnifiedFileMoving -= ValidateFileTypes;
  77:                 this._unifiedFileMovingEventAttached = false;
  78:             }
  79:         }
  80:     }
  81: }

Note, that what we are doing here within the main body is to check whether the “allowedExtensions” attribute exists for the current starting point i.e. the starting point that the user is uploading a file to, and if it does we are checking whether the extension of the file being uploaded matches an entry in the regular expression. If the regular expression is not matched it means that the type of file being uploaded is not one that we have specified as being “allowed” – in which case we can cancel the event and return a reason.

The end result is a starting point that only particular file types can be uploaded to. If the editor attempts to upload a file that does not match one of the entries in our regular expression they will be presented with the error message shown below.

image

If you would like to use this code, either copy and paste, or, download the following Zip file and deploy the assembly to the bin folder of your EPiServer project.

For now I have only tested this against CMS 6 R2.

Nov 20, 2012

Comments

Please login to comment.
Latest blogs
Optimizely and the never-ending story of the missing globe!

I've worked with Optimizely CMS for 14 years, and there are two things I'm obsessed with: Link validation and the globe that keeps disappearing on...

Tomas Hensrud Gulla | Apr 18, 2024 | Syndicated blog

Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog

Azure AI Language – Abstractive Summarisation in Optimizely CMS

In this article, I show how the abstraction summarisation feature provided by the Azure AI Language platform, can be used within Optimizely CMS to...

Anil Patel | Apr 18, 2024 | Syndicated blog

Fix your Search & Navigation (Find) indexing job, please

Once upon a time, a colleague asked me to look into a customer database with weird spikes in database log usage. (You might start to wonder why I a...

Quan Mai | Apr 17, 2024 | Syndicated blog

The A/A Test: What You Need to Know

Sure, we all know what an A/B test can do. But what is an A/A test? How is it different? With an A/B test, we know that we can take a webpage (our...

Lindsey Rogers | Apr 15, 2024

.Net Core Timezone ID's Windows vs Linux

Hey all, First post here and I would like to talk about Timezone ID's and How Windows and Linux systems use different IDs. We currently run a .NET...

sheider | Apr 15, 2024