private ImageGalleryImage CreateImageFromMediaFile(MediaFile mediaFile, ImageGallerySettingsRecord imageGallerySettings)
        {
            if (imageGallerySettings == null)
            {
                throw new ArgumentNullException("imageGallerySettings");
            }

            var  imageSettings        = GetImageSettings(imageGallerySettings, mediaFile.Name);
            bool isValidThumbnailSize = imageGallerySettings.ThumbnailWidth > 0 &&
                                        imageGallerySettings.ThumbnailHeight > 0;
            Thumbnail thumbnail = null;

            if (isValidThumbnailSize)
            {
                thumbnail = _thumbnailService.GetThumbnail(_storageProvider.Combine(mediaFile.FolderName, mediaFile.Name),
                                                           imageGallerySettings.ThumbnailWidth,
                                                           imageGallerySettings.ThumbnailHeight,
                                                           imageGallerySettings.KeepAspectRatio);
            }

            return(new ImageGalleryImage
            {
                PublicUrl = _mediaService.GetPublicUrl(Path.Combine(mediaFile.FolderName, mediaFile.Name)),
                Name = mediaFile.Name,
                Size = mediaFile.Size,
                User = mediaFile.User,
                LastUpdated = mediaFile.LastUpdated,
                Caption = imageSettings == null ? string.Empty : imageSettings.Caption,
                Thumbnail = thumbnail,
                Title = imageSettings == null ? null : imageSettings.Title,
                Position = imageSettings == null ? 0 : imageSettings.Position
            });
        }
        protected string GetThumbnailFolder(string mediaPath)
        {
            // Creates a thumbnail folder if doesn't exists
            if (!_mediaService.GetMediaFolders(mediaPath).Select(o => o.Name).Contains(ThumbnailFolder))
            {
                _mediaService.CreateFolder(mediaPath, ThumbnailFolder);
            }

            return(_storageProvider.Combine(mediaPath, ThumbnailFolder));
        }
Example #3
0
        public override void Submitted(FormSubmittedEventContext context)
        {
            foreach (var element in context.Form.Elements.Flatten())
            {
                var fileFieldElement = element as FileField;
                if (fileFieldElement == null)
                {
                    continue;
                }

                var postedFileValue = context.ValueProvider.GetValue(fileFieldElement.Name);
                if (postedFileValue == null)
                {
                    continue;
                }

                var postedFiles = (HttpPostedFileBase[])postedFileValue.RawValue;
                if (postedFiles == null && postedFiles.Length != 1)
                {
                    continue;
                }

                var folderPath   = _tokenizer.Replace(fileFieldElement.FilePath, new { });
                var uniqFileName = _mediaLibraryService.GetUniqueFilename(folderPath, postedFiles[0].FileName);
                var path         = _storageProvider.Combine(fileFieldElement.FilePath, uniqFileName);

                context.Values[fileFieldElement.Name + ":size"] = postedFiles[0].ContentLength.ToString();
                context.Values[fileFieldElement.Name]           = path;
                fileFieldElement.PostedValue = path;
            }
        }
        public string GetUniqueFilename(string folderPath, string filename)
        {
            // compute a unique filename
            var uniqueFilename = filename;
            var index          = 1;

            while (_storageProvider.FileExists(_storageProvider.Combine(folderPath, uniqueFilename)))
            {
                uniqueFilename = Path.GetFileNameWithoutExtension(filename) + "-" + index++ + Path.GetExtension(filename);
            }

            return(uniqueFilename);
        }
Example #5
0
 protected void RemoveMedia(MediaPart part)
 {
     if (!string.IsNullOrEmpty(part.FileName))
     {
         var path = _storageProvider.Combine(part.FolderPath, part.FileName);
         _storageProvider.DeleteFile(path);
     }
 }
        /// <summary>
        /// Extract the block model file from the nominated Zip file.  A temp folder is created to store the file
        /// and the path to that file is generated for use when importing.
        /// </summary>
        /// <param name="bmFileName"></param>
        /// <param name="targetFolder"></param>
        /// <param name="attmemptModelLoad"></param>
        /// <returns></returns>
        private string ExtractBlockModelFromZip(string bmFileName, out string targetFolder, out bool attmemptModelLoad)
        {
            IStorageFile bmZipFile = _storageProvider.GetFile(bmFileName);

            targetFolder = bmFileName + "extracted";
            List <string> filesInZip = new List <string>();

            attmemptModelLoad = false;
            if (bmFileName.EndsWith(".zip"))
            {
                Stream bmZipFileStream = bmZipFile.OpenRead();
                // extract file to a temp location
                using (var fileInflater = ZipFile.Read(bmZipFileStream))
                {
                    foreach (ZipEntry entry in fileInflater)
                    {
                        if (entry == null)
                        {
                            continue;
                        }

                        if (!entry.IsDirectory && !string.IsNullOrEmpty(entry.FileName))
                        {
                            // skip disallowed files
                            //if (FileAllowed(entry.FileName, false))
                            // {
                            string fullFileName = _storageProvider.Combine(targetFolder, entry.FileName);
                            filesInZip.Add(fullFileName);
                            using (var stream = entry.OpenReader())
                            {
                                // the call will return false if the file already exists
                                if (!_storageProvider.TrySaveStream(fullFileName, stream))
                                {
                                    // try to delete the file and save again
                                    try
                                    {
                                        _storageProvider.DeleteFile(fullFileName);
                                        _storageProvider.TrySaveStream(fullFileName, stream);
                                    }
                                    catch (ArgumentException)
                                    {
                                        // ignore the exception as the file doesn't exist
                                    }
                                }
                            }
                            //}
                        }
                    }
                }
                bmZipFileStream.Close();
                if (filesInZip.Count() > 0)
                {
                    bmFileName        = filesInZip.First();
                    attmemptModelLoad = true;
                }
            }
            return(bmFileName);
        }
Example #7
0
        public string GetUniqueFilename(string folderPath, string filename)
        {
            // remove any char which is unallowed in an HTTP request
            foreach (var unallowedChar in HttpUnallowed)
            {
                filename = filename.Replace(unallowedChar.ToString(), "");
            }

            // compute a unique filename
            var uniqueFilename = filename;
            var index          = 1;

            while (_storageProvider.FileExists(_storageProvider.Combine(folderPath, uniqueFilename)))
            {
                uniqueFilename = Path.GetFileNameWithoutExtension(filename) + "-" + index++ + Path.GetExtension(filename);
            }

            return(uniqueFilename);
        }
Example #8
0
        private IStorageFile GetJournalFile(string executionId)
        {
            IStorageFile journalFile;
            var          journalPath = _storageProvider.Combine(RecipeJournalFolder, executionId);

            try {
                if (_storageProvider.TryCreateFolder(RecipeJournalFolder))
                {
                    var webConfigPath = _storageProvider.Combine(RecipeJournalFolder, "web.config");
                    var webConfigFile = _storageProvider.CreateFile(webConfigPath);
                    WriteWebConfig(webConfigFile);
                }
                journalFile = _storageProvider.GetFile(journalPath);
            }
            catch (ArgumentException) {
                journalFile = _storageProvider.CreateFile(journalPath);
                var recipeStepElement = new XElement("RecipeJournal");
                recipeStepElement.Add(new XElement("Status", "Unknown"));
                WriteJournal(journalFile, recipeStepElement);
            }

            return(journalFile);
        }
Example #9
0
        public void SaveSnapshot(Uri uri)
        {
            var urlString = uri.ToString();

            // This folder will be created before download process will copy files into it
            var folderPath = _storageProvider.Combine("_ArchivedLinks", urlString.GetHashCode().ToString());

            var contentType = GetContentType(uri);

            var allowableFileContentTypes = new string[] { "application/pdf", "image/jpeg", "image/jpg", "image/png", "image/gif" };

            if (allowableFileContentTypes.Contains(contentType))
            {
                DownloadFile(urlString, uri, folderPath, true);
            }
            else if (contentType == "text/html")
            {
                var htmlWeb  = new HtmlWeb();
                var document = htmlWeb.Load(urlString);

                DownloadHtml(ref document, uri, folderPath);
                htmlWeb.Get(urlString, "/");

                var indexPath = _storageProvider.Combine(folderPath, "index.html");
                if (_storageProvider.FileExists(indexPath))
                {
                    _storageProvider.DeleteFile(indexPath);
                }

                using (var stream = _storageProvider.CreateFile(indexPath).OpenWrite())
                {
                    document.Save(stream);
                }
            }
            else
            {
                throw new NotSupportedException("Uri type not supported");
            }
        }
        public ActionResult Download(int Id, string Reference)
        {
            if (string.IsNullOrWhiteSpace(Reference))
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Missing order parameter"));
            }
            var order = _ordersService.GetOrderByReference(Reference);

            if (order == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound, "Order not found"));
            }
            else if (order.OrderStatus < OrderStatus.Completed)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "Order is not completed"));
            }
            var detail = order.Details.Where(d => d.Id == Id).FirstOrDefault();

            if (detail == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound, "Order detail not found"));
            }
            var product = _contentManager.Get <DownloadableProductPart>(detail.ContentId);

            if (product == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound, "Product not found"));
            }
            else if (product.Media == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound, "No media available for this product"));
            }
            else
            {
                var mediaPart = product.Media.As <MediaPart>();
                try {
                    var mediaFile = _storageProvider.GetFile(_storageProvider.Combine(mediaPart.FolderPath, mediaPart.FileName));
                    return(File(mediaFile.OpenRead(), mediaPart.MimeType, mediaPart.FileName));
                }
                catch (Exception e) {
                    Logger.Error(e, "Error retrieving downloadable product : " + mediaPart.MediaUrl);
                    return(new HttpStatusCodeResult(HttpStatusCode.InternalServerError, "Error retrieving media"));
                }
            }
        }
Example #11
0
        private string MakePath(CombinedFileRecord file)
        {
            // Maybe others will come, therefore the architecture
            string extension  = "";
            string folderPath = "";

            if (file.Type == ResourceType.JavaScript)
            {
                folderPath = ScriptsPath;
                extension  = "js";
            }
            else if (file.Type == ResourceType.Style)
            {
                folderPath = StylesPath;
                extension  = "css";
            }

            return(_storageProvider.Combine(folderPath, file.GetFileName() + "." + extension));
        }
        public JsonResult Rename(string target, string name)
        {
            if (!string.IsNullOrEmpty(target))
            {
                var path = Helper.DecodePath(target).Replace("\\", "/").Replace(@"\", "/").Replace("//", "/");
                if (string.IsNullOrEmpty(Path.GetExtension(path)))
                {
                    throw new NotImplementedException("Cannot found process rename folder.");
                }
                var index    = path.LastIndexOf('/');
                var folder   = string.Empty;
                var fileName = string.Empty;
                if (index > -1)
                {
                    folder   = path.Substring(0, index);
                    fileName = path.Replace(folder, string.Empty);
                }

                var answer = new ReplaceResponse();
                mediaService.RenameFile(folder, fileName, name);

                answer.Removed.Add(target);
                var relativePath = storageProvider.Combine(folder, name);
                var file         = storageProvider.GetFile(relativePath);
                var mediaFile    = new MediaFile
                {
                    Name        = name,
                    Size        = file.GetSize(),
                    LastUpdated = file.GetLastUpdated(),
                    Type        = file.GetFileType(),
                    FolderName  = folder,
                    MediaPath   = mediaService.GetMediaPublicUrl(folder, name)
                };
                answer.Added.Add(CreateDto(mediaFile));

                return(Json(answer));
            }

            throw new NotImplementedException();
        }
Example #13
0
        protected override DriverResult Editor(ContentPart part, Fields.FileField field, IUpdateModel updater, dynamic shapeHelper)
        {
            var settings  = field.PartFieldDefinition.Settings.GetModel <FileFieldSettings>();
            var viewModel = new FileFieldViewModel
            {
                Settings = settings,
                Field    = field
            };

            if (updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null))
            {
                var postedFile = ((Controller)updater).Request.Files["FileField-" + field.Name];

                AssignDefaultMediaFolder(settings);

                var mediaFolder = FormatWithTokens(settings.MediaFolder, part.ContentItem.ContentType, field.Name, part.ContentItem.Id);

                if (postedFile != null && postedFile.ContentLength != 0)
                {
                    var extension         = ParseFileExtenstion(postedFile.FileName);
                    var allowedExtensions = ParseAllowedExtention(settings.ExtenstionsAllowed);
                    var fileName          = Path.GetFileNameWithoutExtension(postedFile.FileName);

                    if (allowedExtensions.Contains(extension))
                    {
                        if (postedFile.ContentLength <= (settings.MaxFileSize * 1024))
                        {
                            var postedFileLength = postedFile.ContentLength;
                            var postedFileData   = new byte[postedFileLength];
                            var postedFileStream = postedFile.InputStream;
                            postedFileStream.Read(postedFileData, 0, postedFileLength);


                            try
                            {
                                // try to create the folder before uploading a file into it
                                _storageProvider.CreateFolder(mediaFolder);
                            }
                            catch
                            {
                                // the folder can't be created because it already exists, continue
                            }

                            if (settings.NameTag == NameTags.Index)
                            {
                                var lastFileIndex =
                                    _storageProvider.ListFiles(mediaFolder)
                                    .Count(f => Path.GetFileNameWithoutExtension(f.GetName()).Contains(fileName));

                                fileName = String.Format("{0} ({1}).{2}", fileName, lastFileIndex + 1, extension);
                            }
                            else if (settings.NameTag == NameTags.TimeStamp)
                            {
                                fileName = String.Format("{0}-{1}.{2}", fileName,
                                                         DateTime.Now.ToString("yyyyMMddhhmmss"), extension);
                            }

                            //
                            var filePath = _storageProvider.Combine(mediaFolder, fileName);
                            var file     = _storageProvider.CreateFile(filePath);
                            using (var fileStream = file.OpenWrite())
                            {
                                fileStream.Write(postedFileData, 0, postedFileLength);
                            }

                            field.Path = _storageProvider.GetPublicUrl(file.GetPath());
                        }
                        else
                        {
                            updater.AddModelError("File", T("The file size is bigger than the maximum file size, maximum size is {0}KB.", settings.MaxFileSize));
                        }
                    }
                    else
                    {
                        updater.AddModelError("File", T("The file type is not allowed for {0}.", postedFile.FileName));
                    }
                }
                else
                {
                    if (settings.Required && string.IsNullOrWhiteSpace(field.Path))
                    {
                        updater.AddModelError("File", T("You must provide a file for {0}.", field.Name.CamelFriendly()));
                    }
                }

                if (string.IsNullOrWhiteSpace(field.Text))
                {
                    field.Text = Path.GetFileName(field.Path);
                }
            }

            return(Editor(part, field, shapeHelper));
        }
Example #14
0
        public string GetImageProfileUrl(string path, string profileName, FilterRecord customFilter, ContentItem contentItem)
        {
            // try to load the processed filename from cache
            var  filePath = _fileNameProvider.GetFileName(profileName, path);
            bool process  = false;

            // if the filename is not cached, process it
            if (string.IsNullOrEmpty(filePath))
            {
                Logger.Debug("FilePath is null, processing required, profile {0} for image {1}", profileName, path);

                process = true;
            }

            // the processd file doesn't exist anymore, process it
            else if (!_storageProvider.FileExists(filePath))
            {
                Logger.Debug("Processed file no longer exists, processing required, profile {0} for image {1}", profileName, path);

                process = true;
            }

            // if the original file is more recent, process it
            else
            {
                DateTime pathLastUpdated;
                if (TryGetImageLastUpdated(path, out pathLastUpdated))
                {
                    var filePathLastUpdated = _storageProvider.GetFile(filePath).GetLastUpdated();

                    if (pathLastUpdated > filePathLastUpdated)
                    {
                        Logger.Debug("Original file more recent, processing required, profile {0} for image {1}", profileName, path);

                        process = true;
                    }
                }
            }

            // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries.
            if (process)
            {
                Logger.Debug("Processing profile {0} for image {1}", profileName, path);

                ImageProfilePart profilePart;

                if (customFilter == null)
                {
                    profilePart = _profileService.GetImageProfileByName(profileName);
                    if (profilePart == null)
                    {
                        return(String.Empty);
                    }
                }
                else
                {
                    profilePart      = _services.ContentManager.New <ImageProfilePart>("ImageProfile");
                    profilePart.Name = profileName;
                    profilePart.Filters.Add(customFilter);
                }

                using (var image = GetImage(path)) {
                    var filterContext = new FilterContext {
                        Media = image, FilePath = _storageProvider.Combine("_Profiles", _storageProvider.Combine(profileName, CreateDefaultFileName(path)))
                    };

                    var tokens = new Dictionary <string, object>();
                    // if a content item is provided, use it while tokenizing
                    if (contentItem != null)
                    {
                        tokens.Add("Content", contentItem);
                    }

                    foreach (var filter in profilePart.Filters.OrderBy(f => f.Position))
                    {
                        var descriptor = _processingManager.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type);
                        if (descriptor == null)
                        {
                            continue;
                        }

                        var tokenized = _tokenizer.Replace(filter.State, tokens);
                        filterContext.State = FormParametersHelper.ToDynamic(tokenized);
                        descriptor.Filter(filterContext);
                    }

                    _fileNameProvider.UpdateFileName(profileName, path, filterContext.FilePath);

                    if (!filterContext.Saved)
                    {
                        _storageProvider.TryCreateFolder(_storageProvider.Combine("_Profiles", profilePart.Name));
                        var newFile = _storageProvider.OpenOrCreate(filterContext.FilePath);
                        using (var imageStream = newFile.OpenWrite()) {
                            using (var sw = new BinaryWriter(imageStream)) {
                                if (filterContext.Media.CanSeek)
                                {
                                    filterContext.Media.Seek(0, SeekOrigin.Begin);
                                }
                                using (var sr = new BinaryReader(filterContext.Media)) {
                                    int count;
                                    var buffer = new byte[8192];
                                    while ((count = sr.Read(buffer, 0, buffer.Length)) != 0)
                                    {
                                        sw.Write(buffer, 0, count);
                                    }
                                }
                            }
                        }
                    }

                    filterContext.Media.Dispose();
                    filePath = filterContext.FilePath;
                }
            }

            // generate a timestamped url to force client caches to update if the file has changed
            var publicUrl = _storageProvider.GetPublicUrl(filePath);
            var timestamp = _storageProvider.GetFile(filePath).GetLastUpdated().Ticks;

            return(publicUrl + "?v=" + timestamp.ToString(CultureInfo.InvariantCulture));
        }
Example #15
0
        /// <summary>
        /// Creates a media folder.
        /// </summary>
        /// <param name="relativePath">The path where to create the new folder. null means root.</param>
        /// <param name="folderName">The name of the folder to be created.</param>
        public void CreateFolder(string relativePath, string folderName)
        {
            Argument.ThrowIfNullOrEmpty(folderName, "folderName");

            _storageProvider.CreateFolder(relativePath == null ? folderName : _storageProvider.Combine(relativePath, folderName));
        }
        public void create_write_read_file_should_equal()
        {
            using (var stream = SUT.CreateFile(SUT.Combine(TEST_FOLDER, "test.txt")).OpenWrite())
            {
                stream.Write(new byte[] { 1 }, 0, 1);
            }

            using (var stream = SUT.GetFile(SUT.Combine(TEST_FOLDER, "test.txt")).OpenRead())
            {
                var buffer = new byte[1];
                stream.Read(buffer, 0, 1);

                Assert.AreEqual(1, buffer[0]);
            }
        }
Example #17
0
        public MediaPartHandler(
            IStorageProvider storageProvider,
            IMediaLibraryService mediaLibraryService,
            IRepository <MediaPartRecord> repository,
            IContentDefinitionManager contentDefinitionManager)
        {
            _storageProvider          = storageProvider;
            _mediaLibraryService      = mediaLibraryService;
            _contentDefinitionManager = contentDefinitionManager;

            Filters.Add(StorageFilter.For(repository));
            Filters.Add(new ActivatingFilter <TitlePart>(contentType => {
                var typeDefinition = _contentDefinitionManager.GetTypeDefinition(contentType);
                // To avoid NRE when the handler runs for ad-hoc content types, e.g. MediaLibraryExplorer.
                return(typeDefinition == null ?
                       false :
                       typeDefinition.Parts.Any(contentTypePartDefinition =>
                                                contentTypePartDefinition.PartDefinition.Name == typeof(MediaPart).Name));
            }));

            OnRemoving <MediaPart>((context, part) => RemoveMedia(part));
            OnLoaded <MediaPart>((context, part) => {
                if (!String.IsNullOrEmpty(part.FileName))
                {
                    part._publicUrl.Loader(() => _mediaLibraryService.GetMediaPublicUrl(part.FolderPath, part.FileName));
                }
            });

            OnIndexing <MediaPart>((context, part) =>
                                   context.DocumentIndex
                                   .Add("media-folderpath", Normalize(part.FolderPath)).Store()
                                   .Add("media-filename", Normalize(part.FileName)).Store()
                                   .Add("media-mimetype", Normalize(part.MimeType)).Store()
                                   .Add("media-caption", part.Caption).Analyze()
                                   .Add("media-alternatetext", part.AlternateText).Analyze()
                                   );

            OnPublished <ImagePart>((context, part) => {
                var mediaPart = part.As <MediaPart>();
                var file      = _storageProvider.GetFile(_storageProvider.Combine(mediaPart.FolderPath, mediaPart.FileName));

                using (var stream = file.OpenRead()) {
                    try {
                        using (var image = System.Drawing.Image.FromStream(stream)) {
                            part.Width  = image.Width;
                            part.Height = image.Height;
                        }
                    }
                    catch (ArgumentException) {
                        if (mediaPart.MimeType != "image/x-icon" && mediaPart.MimeType != "image/vnd.microsoft.icon")
                        {
                            throw;
                        }
                        TryFillDimensionsForIco(stream, part);
                    }
                }
            });

            OnIndexing <ImagePart>((context, part) =>
                                   context.DocumentIndex
                                   .Add("image-height", part.Height).Analyze().Store()
                                   .Add("image-width", part.Width).Analyze().Store()
                                   );

            OnPublished <DocumentPart>((context, part) => {
                var mediaPart = part.As <MediaPart>();
                var file      = _storageProvider.GetFile(_storageProvider.Combine(mediaPart.FolderPath, mediaPart.FileName));

                using (var stream = file.OpenRead()) {
                    part.Length = stream.Length;
                }
            });

            OnIndexing <DocumentPart>((context, part) =>
                                      context.DocumentIndex
                                      .Add("document-length", part.Length).Analyze().Store()
                                      );

            OnPublished <VideoPart>((context, part) => part.Length = 0);

            OnIndexing <VideoPart>((context, part) =>
                                   context.DocumentIndex
                                   .Add("video-length", part.Length).Analyze().Store()
                                   );

            OnPublished <AudioPart>((context, part) => part.Length = 0);

            OnIndexing <AudioPart>((context, part) =>
                                   context.DocumentIndex
                                   .Add("audio-length", part.Length).Analyze().Store()
                                   );

            OnIndexing <OEmbedPart>((context, part) =>
                                    context.DocumentIndex
                                    .Add("oembed-source", part.Source).Analyze().Store()
                                    );
        }
        public string GetImageProfileUrl(string path, string profileName, ContentItem contentItem, params FilterRecord[] customFilters)
        {
            // path is the publicUrl of the media, so it might contain url-encoded chars

            // try to load the processed filename from cache
            var  filePath = _fileNameProvider.GetFileName(profileName, System.Web.HttpUtility.UrlDecode(path));
            bool process  = false;

            //after reboot the app cache is empty so we reload the image in the cache if it exists in the _Profiles folder
            if (string.IsNullOrEmpty(filePath))
            {
                var profileFilePath = _storageProvider.Combine("_Profiles", FormatProfilePath(profileName, System.Web.HttpUtility.UrlDecode(path)));

                if (_storageProvider.FileExists(profileFilePath))
                {
                    _fileNameProvider.UpdateFileName(profileName, System.Web.HttpUtility.UrlDecode(path), profileFilePath);
                    filePath = profileFilePath;
                }
            }

            // if the filename is not cached, process it
            if (string.IsNullOrEmpty(filePath))
            {
                Logger.Debug("FilePath is null, processing required, profile {0} for image {1}", profileName, path);

                process = true;
            }

            // the processd file doesn't exist anymore, process it
            else if (!_storageProvider.FileExists(filePath))
            {
                Logger.Debug("Processed file no longer exists, processing required, profile {0} for image {1}", profileName, path);

                process = true;
            }

            // if the original file is more recent, process it
            else
            {
                DateTime pathLastUpdated;
                if (TryGetImageLastUpdated(path, out pathLastUpdated))
                {
                    var filePathLastUpdated = _storageProvider.GetFile(filePath).GetLastUpdated();

                    if (pathLastUpdated > filePathLastUpdated)
                    {
                        Logger.Debug("Original file more recent, processing required, profile {0} for image {1}", profileName, path);

                        process = true;
                    }
                }
            }

            // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries.
            if (process)
            {
                Logger.Debug("Processing profile {0} for image {1}", profileName, path);

                ImageProfilePart profilePart;

                if (customFilters == null || !customFilters.Any(c => c != null))
                {
                    profilePart = _profileService.GetImageProfileByName(profileName);
                    if (profilePart == null)
                    {
                        return(String.Empty);
                    }
                }
                else
                {
                    profilePart      = _services.ContentManager.New <ImageProfilePart>("ImageProfile");
                    profilePart.Name = profileName;
                    foreach (var customFilter in customFilters)
                    {
                        profilePart.Filters.Add(customFilter);
                    }
                }

                // prevent two requests from processing the same file at the same time
                // this is only thread safe at the machine level, so there is a try/catch later
                // to handle cross machines concurrency
                lock (String.Intern(path)) {
                    using (var image = GetImage(path)) {
                        if (image == null)
                        {
                            return(null);
                        }

                        var filterContext = new FilterContext {
                            Media = image, FilePath = _storageProvider.Combine("_Profiles", FormatProfilePath(profileName, System.Web.HttpUtility.UrlDecode(path)))
                        };

                        var tokens = new Dictionary <string, object>();
                        // if a content item is provided, use it while tokenizing
                        if (contentItem != null)
                        {
                            tokens.Add("Content", contentItem);
                        }

                        foreach (var filter in profilePart.Filters.OrderBy(f => f.Position))
                        {
                            var descriptor = _processingManager.DescribeFilters().SelectMany(x => x.Descriptors).FirstOrDefault(x => x.Category == filter.Category && x.Type == filter.Type);
                            if (descriptor == null)
                            {
                                continue;
                            }

                            var tokenized = _tokenizer.Replace(filter.State, tokens);
                            filterContext.State = FormParametersHelper.ToDynamic(tokenized);
                            descriptor.Filter(filterContext);
                        }

                        _fileNameProvider.UpdateFileName(profileName, System.Web.HttpUtility.UrlDecode(path), filterContext.FilePath);

                        if (!filterContext.Saved)
                        {
                            try {
                                var newFile = _storageProvider.OpenOrCreate(filterContext.FilePath);
                                using (var imageStream = newFile.OpenWrite()) {
                                    using (var sw = new BinaryWriter(imageStream)) {
                                        if (filterContext.Media.CanSeek)
                                        {
                                            filterContext.Media.Seek(0, SeekOrigin.Begin);
                                        }
                                        using (var sr = new BinaryReader(filterContext.Media)) {
                                            int count;
                                            var buffer = new byte[8192];
                                            while ((count = sr.Read(buffer, 0, buffer.Length)) != 0)
                                            {
                                                sw.Write(buffer, 0, count);
                                            }
                                        }
                                    }
                                }
                            }
                            catch (Exception e) {
                                Logger.Error(e, "A profile could not be processed: " + path);
                            }
                        }

                        filterContext.Media.Dispose();
                        filePath = filterContext.FilePath;
                    }
                }
            }

            // generate a timestamped url to force client caches to update if the file has changed
            var publicUrl = _storageProvider.GetPublicUrl(filePath);
            var timestamp = _storageProvider.GetFile(filePath).GetLastUpdated().Ticks;

            return(publicUrl + "?v=" + timestamp.ToString(CultureInfo.InvariantCulture));
        }