// used by the html generator public List <FileIndexItem> ReadExifAndXmpFromFileAddFilePathHash(List <string> subPathList, List <string> fileHashes = null) { var fileIndexList = new List <FileIndexItem>(); for (int i = 0; i < subPathList.Count; i++) { var subPath = subPathList[i]; var returnItem = ReadExifAndXmpFromFile(subPath); var imageFormat = ExtensionRolesHelper.GetImageFormat(_iStorage.ReadStream(subPath, 50)); returnItem.ImageFormat = imageFormat; returnItem.FileName = Path.GetFileName(subPath); returnItem.IsDirectory = false; returnItem.Status = FileIndexItem.ExifStatus.Ok; returnItem.ParentDirectory = FilenamesHelper.GetParentPath(subPath); if (fileHashes == null || fileHashes.Count <= i) { returnItem.FileHash = new FileHash(_iStorage).GetHashCode(subPath).Key; } else { returnItem.FileHash = fileHashes[i]; } fileIndexList.Add(returnItem); } return(fileIndexList); }
/// <summary> /// Show previous en next items in the folder view. /// There is equivalent class for prev next in the display view /// </summary> /// <param name="currentFolder">subPath style</param> /// <returns>relative object</returns> public RelativeObjects GetNextPrevInFolder(string currentFolder) { if (currentFolder != "/") { PathHelper.RemoveLatestSlash(currentFolder); } // We use breadcrumbs to get the parent folder var parentFolderPath = FilenamesHelper.GetParentPath(currentFolder); var itemsInSubFolder = QueryGetNextPrevInFolder(parentFolderPath); var photoIndexOfSubFolder = itemsInSubFolder.FindIndex(p => p.FilePath == currentFolder); var relativeObject = new RelativeObjects(); if (photoIndexOfSubFolder != itemsInSubFolder.Count - 1 && currentFolder != "/") { // currentFolder != "/" >= on the home folder you will automatically go to a subfolder relativeObject.NextFilePath = itemsInSubFolder[photoIndexOfSubFolder + 1]?.FilePath; relativeObject.NextHash = itemsInSubFolder[photoIndexOfSubFolder + 1]?.FileHash; } if (photoIndexOfSubFolder >= 1) { relativeObject.PrevFilePath = itemsInSubFolder[photoIndexOfSubFolder - 1]?.FilePath; relativeObject.PrevHash = itemsInSubFolder[photoIndexOfSubFolder - 1]?.FileHash; } return(relativeObject); }
/// <summary> /// Check if a currentChildFolderBuilder exist in the parentFolderBuilder /// </summary> /// <param name="parentFolderBuilder">parent folder (subPath style)</param> /// <param name="currentChildFolderBuilder">child folder with asterisk</param> /// <returns>SubPath without asterisk</returns> private StringBuilder MatchChildDirectories(StringBuilder parentFolderBuilder, StringBuilder currentChildFolderBuilder) { // should return a list of: </2019/10/2019_10_08> var childDirectories = _storage.GetDirectories(parentFolderBuilder.ToString()).ToList(); var matchingFoldersPath = childDirectories.FirstOrDefault(p => MatchChildFolderSearch(parentFolderBuilder, currentChildFolderBuilder, p) ); // When a new folder with asterisk is created if (matchingFoldersPath == null) { var defaultValue = RemoveAsteriskFromString(currentChildFolderBuilder); // When only using Asterisk in structure if (defaultValue == "/") { defaultValue = "/default"; } parentFolderBuilder.Append(defaultValue); return(parentFolderBuilder); } // When a regex folder is matched var childFolderName = PathHelper.PrefixDbSlash(FilenamesHelper.GetFileName(matchingFoldersPath)); parentFolderBuilder.Append(childFolderName); return(parentFolderBuilder); }
/// <summary> /// Get the collections items when preflighting /// Returns as Tuple /// item1: inputFileSubPaths, toFileSubPaths /// item2: list of fileIndex Results (which contains only error cases) /// </summary> /// <param name="inputFileSubPaths">from where to copy (file or folder)</param> /// <param name="toFileSubPaths">copy to (file or folder)</param> /// <param name="fileIndexResultsList">results list</param> /// <param name="collections">enable file collections</param> /// <returns>inputFileSubPaths list, toFileSubPaths list and fileIndexResultsList</returns> private Tuple <Tuple <string[], string[]>, List <FileIndexItem> > CollectionAddPreflight( IReadOnlyList <string> inputFileSubPaths, IReadOnlyList <string> toFileSubPaths, List <FileIndexItem> fileIndexResultsList, bool collections) { if (!collections) { return(new Tuple <Tuple <string[], string[]>, List <FileIndexItem> >( new Tuple <string[], string[]>(inputFileSubPaths.ToArray(), toFileSubPaths.ToArray()), fileIndexResultsList )); } var inputCollectionFileSubPaths = new List <string>(); var toCollectionFileSubPaths = new List <string>(); for (var i = 0; i < inputFileSubPaths.Count; i++) { // When the input is a folder, just copy the array if (_iStorage.ExistFolder(inputFileSubPaths[i])) { inputCollectionFileSubPaths.Add(inputFileSubPaths[i]); toCollectionFileSubPaths.Add(toFileSubPaths[i]); continue; } // when it is a file update the 'to paths' var collectionPaths = _query.SingleItem(inputFileSubPaths[i], null, true, false).FileIndexItem.CollectionPaths; inputCollectionFileSubPaths.AddRange(collectionPaths); for (var j = 0; j < collectionPaths.Count; j++) { var collectionItem = collectionPaths[j]; // When moving to a folder if (_iStorage.ExistFolder(toFileSubPaths[i])) { toCollectionFileSubPaths.Add(toFileSubPaths[i]); continue; } var extensionWithoutDot = FilenamesHelper.GetFileExtensionWithoutDot(collectionItem); // when rename-ing the current file, but the other ones are implicit copied if (j == 0) { extensionWithoutDot = FilenamesHelper.GetFileExtensionWithoutDot(toFileSubPaths[i]); } // Rename other sidecar files // From file to Deleted var parentFolder = FilenamesHelper.GetParentPath(toFileSubPaths[i]); var baseName = FilenamesHelper.GetFileNameWithoutExtension(toFileSubPaths[i]); toCollectionFileSubPaths.Add($"{parentFolder}/{baseName}.{extensionWithoutDot}"); } } return(new Tuple <Tuple <string[], string[]>, List <FileIndexItem> >( new Tuple <string[], string[]>(inputCollectionFileSubPaths.ToArray(), toCollectionFileSubPaths.ToArray()), fileIndexResultsList )); }
private IActionResult ReturnThumbnailResult(string f, bool json, ThumbnailSize size) { Response.Headers.Add("x-image-size", new StringValues(size.ToString())); var stream = _thumbnailStorage.ReadStream(ThumbnailNameHelper.Combine(f, size), 50); var imageFormat = ExtensionRolesHelper.GetImageFormat(stream); if (imageFormat == ExtensionRolesHelper.ImageFormat.unknown) { SetExpiresResponseHeadersToZero(); return(NoContent()); // 204 } // When using the api to check using javascript // use the cached version of imageFormat, otherwise you have to check if it deleted if (json) { return(Json("OK")); } stream = _thumbnailStorage.ReadStream( ThumbnailNameHelper.Combine(f, size)); // thumbs are always in jpeg Response.Headers.Add("x-filename", new StringValues(FilenamesHelper.GetFileName(f + ".jpg"))); return(File(stream, "image/jpeg")); }
private static string GetFileName(string toFileSubPath, string inputFileSubPath) { // Needed to create SetFilePath() for item that is copied, not the folder // no double slash when moving to root folder return(toFileSubPath == "/" ? $"/{FilenamesHelper.GetFileName(inputFileSubPath)}" : $"{toFileSubPath}/{FilenamesHelper.GetFileName(inputFileSubPath)}"); }
internal async Task <List <string> > AddParentCacheIfNotExistAsync(IEnumerable <string> updatedPaths) { var parentDirectoryList = new HashSet <string>(); foreach (var path in updatedPaths) { parentDirectoryList.Add(FilenamesHelper.GetParentPath(path)); } var shouldAddParentDirectoriesToCache = parentDirectoryList.Where(parentDirectory => !_query.CacheGetParentFolder(parentDirectory).Item1).ToList(); if (!shouldAddParentDirectoriesToCache.Any()) { return(new List <string>()); } var databaseQueryResult = await _query.GetAllObjectsAsync(shouldAddParentDirectoriesToCache); _logger.LogInformation("[AddParentCacheIfNotExist] files added to cache " + string.Join(",", shouldAddParentDirectoriesToCache)); foreach (var directory in shouldAddParentDirectoriesToCache) { var byDirectory = databaseQueryResult.Where(p => p.ParentDirectory == directory).ToList(); _query.AddCacheParentItem(directory, byDirectory); } return(shouldAddParentDirectoriesToCache); }
private async Task LoopOverSidecarFiles(List <string> subPaths) { var parentDirectories = new HashSet <string>(); var xmpSubPaths = subPaths .Where(ExtensionRolesHelper.IsExtensionSidecar).ToList(); foreach (var xmpPath in xmpSubPaths) { parentDirectories.Add(FilenamesHelper.GetParentPath(xmpPath)); } var itemsInDirectories = new HashSet <FileIndexItem>( await _query.GetAllFilesAsync(parentDirectories.ToList())); // that is an filepath without extension var collectionPath = xmpSubPaths.Select(singlePath => $"{FilenamesHelper.GetParentPath(singlePath)}/" + FilenamesHelper.GetFileNameWithoutExtension(singlePath)).ToList(); foreach (var item in itemsInDirectories) { foreach (var singleCollectionPath in collectionPath) { if (item.FilePath.StartsWith(singleCollectionPath) && !ExtensionRolesHelper.IsExtensionSidecar(item.FilePath)) { item.RemoveSidecarExtension("xmp"); await _query.UpdateItemAsync(item); } } } Console.WriteLine(); }
/// <summary> /// Get the output of structure applied on the storage /// With the DateTime and fileNameBase applied /// </summary> /// <param name="parsedStructuredList">parsed object, only needed to apply on the storage</param> /// <returns>string with subPath</returns> private string ApplyStructureRangeToStorage(List <List <StructureRange> > parsedStructuredList) { var parentFolderBuilder = new StringBuilder(); foreach (var subStructureItem in parsedStructuredList) { var currentChildFolderBuilder = new StringBuilder(); currentChildFolderBuilder.Append("/"); foreach (var structureItem in subStructureItem) { currentChildFolderBuilder.Append(structureItem.Output); } var parentFolderSubPath = FilenamesHelper.GetParentPath(parentFolderBuilder.ToString()); var existParentFolder = _storage.ExistFolder(parentFolderSubPath); // default situation without asterisk or child directory is NOT found if (!currentChildFolderBuilder.ToString().Contains("*") || !existParentFolder) { var currentChildFolderRemovedAsterisk = RemoveAsteriskFromString(currentChildFolderBuilder); parentFolderBuilder.Append(currentChildFolderRemovedAsterisk); continue; } parentFolderBuilder = MatchChildDirectories(parentFolderBuilder, currentChildFolderBuilder); } return(parentFolderBuilder.ToString()); }
private async Task FromFileToDeleted(string inputFileSubPath, string toFileSubPath, List <FileIndexItem> fileIndexResultsList, List <FileIndexItem> fileIndexItems, DetailView detailView) { // when trying to rename something wrongs var fileName = FilenamesHelper.GetFileName(toFileSubPath); if (!FilenamesHelper.IsValidFileName(fileName)) { fileIndexResultsList.Add(new FileIndexItem { Status = FileIndexItem.ExifStatus.OperationNotSupported }); return; //next } // from/input cache should be cleared var inputParentSubFolder = FilenamesHelper.GetParentPath(inputFileSubPath); _query.RemoveCacheParentItem(inputParentSubFolder); var toParentSubFolder = FilenamesHelper.GetParentPath(toFileSubPath); if (string.IsNullOrEmpty(toParentSubFolder)) { toParentSubFolder = "/"; } // clear cache (to FileSubPath parents) _query.RemoveCacheParentItem(toParentSubFolder); // Check if the parent folder exist in the database await _query.AddParentItemsAsync(toParentSubFolder); // Save in database before change on disk await SaveToDatabaseAsync(fileIndexItems, fileIndexResultsList, detailView, toFileSubPath); // add folder to file system if (!_iStorage.ExistFolder(toParentSubFolder)) { _iStorage.CreateDirectory(toParentSubFolder); fileIndexResultsList.Add(new FileIndexItem(toParentSubFolder) { Status = FileIndexItem.ExifStatus.Ok }); } _iStorage.FileMove(inputFileSubPath, toFileSubPath); MoveSidecarFile(inputFileSubPath, toFileSubPath); // when renaming a folder it should warn the UI that it should remove the source item fileIndexResultsList.Add(new FileIndexItem(inputFileSubPath) { Status = FileIndexItem.ExifStatus.NotFoundSourceMissing }); }
public StorageThumbnailFilesystemTest() { var createNewImage = new CreateAnImage(); var appSettings = new AppSettings { ThumbnailTempFolder = createNewImage.BasePath }; _thumbnailStorage = new StorageThumbnailFilesystem(appSettings, new FakeIWebLogger()); _fileNameWithoutExtension = FilenamesHelper.GetFileNameWithoutExtension(createNewImage.FileName); }
/// <summary> /// Get the fileName from the structure and ignore the parent folders /// Does NOT check if the file already exist /// </summary> /// <param name="dateTime">DateTime to parse</param> /// <param name="fileNameBase">include fileName if requested in structure</param> /// <param name="extensionWithoutDot">fileExtension without dot</param> /// <returns>filename without starting slash</returns> public string ParseFileName(DateTime dateTime, string fileNameBase = "", string extensionWithoutDot = "") { CheckStructureFormat(); var fileNameStructure = PathHelper.PrefixDbSlash(FilenamesHelper.GetFileName(_structure)); var parsedStructuredList = ParseStructure(fileNameStructure, dateTime, fileNameBase, extensionWithoutDot); return(PathHelper.RemovePrefixDbSlash(ApplyStructureRangeToStorage(parsedStructuredList))); }
public Task <List <FileIndexItem> > GetObjectsByFilePathCollectionAsync(List <string> filePathList) { var result = new List <FileIndexItem>(); foreach (var path in filePathList) { var fileNameWithoutExtension = FilenamesHelper.GetFileNameWithoutExtension(path); result.AddRange(_fakeContext.Where(p => p.ParentDirectory == FilenamesHelper.GetParentPath(path) && p.FileName.StartsWith(fileNameWithoutExtension))); } return(Task.FromResult(result)); }
internal static string AppendIndexerToFilePath(string parentDirectory, string fileName, int index) { if (index >= 1) { fileName = string.Concat( FilenamesHelper.GetFileNameWithoutExtension(fileName), $"_{index}.", FilenamesHelper.GetFileExtensionWithoutDot(fileName) ); } return(PathHelper.AddSlash(parentDirectory) + PathHelper.RemovePrefixDbSlash(fileName)); }
public Task <List <ImportIndexItem> > Preflight(List <string> inputFileFullPaths, ImportSettingsModel importSettings) { var results = new List <ImportIndexItem>(); foreach (var inputFileFullPath in inputFileFullPaths) { // if the item fails var importIndexFileError = new ImportIndexItem { FilePath = "/" + FilenamesHelper.GetFileName(inputFileFullPath), SourceFullFilePath = "~/temp/test", FileHash = "FAKE", MakeModel = "added if the item fails", Status = ImportStatus.FileError }; // Check if extension is correct if (!ExtensionRolesHelper.IsExtensionSyncSupported(inputFileFullPath)) { results.Add(importIndexFileError); } // Check if the file is correct var imageFormat = ExtensionRolesHelper.GetImageFormat( _selectorStorage.Get(SelectorStorage.StorageServices.HostFilesystem) .ReadStream(inputFileFullPath, 160)); if (!ExtensionRolesHelper.ExtensionSyncSupportedList.Contains($"{imageFormat}")) { results.Add(importIndexFileError); } results.Add(new ImportIndexItem { Id = 4, SourceFullFilePath = inputFileFullPath, FilePath = inputFileFullPath, Status = ImportStatus.Ok, FileHash = "FAKE", MakeModel = "added okay", FileIndexItem = new FileIndexItem() { FileHash = "FAKE_OK", FilePath = inputFileFullPath } }); } PreflightList.AddRange(results); return(Task.FromResult(results)); }
/// <summary> /// this updates the main database item for a sidecar file /// </summary> /// <param name="xmpSubPath">sidecar file</param> /// <param name="directoryWithFileIndexItems">directory where the sidecar is located</param> /// <returns>completed task</returns> private async Task UpdateSidecarFile(string xmpSubPath, List <FileIndexItem> directoryWithFileIndexItems) { if (!ExtensionRolesHelper.IsExtensionSidecar(xmpSubPath)) { return; } var sidecarExt = FilenamesHelper.GetFileExtensionWithoutDot(xmpSubPath); foreach (var item in directoryWithFileIndexItems.Where(item => !item.SidecarExtensionsList.Contains(sidecarExt))) { item.AddSidecarExtension(sidecarExt); await _query.UpdateItemAsync(item); } }
/// <summary> /// Uses Cache /// </summary> /// <param name="inputFilePaths">list of paths</param> /// <param name="collections">uses collections </param> /// <returns>list with items</returns> public async Task <List <FileIndexItem> > GetObjectsByFilePathAsync(List <string> inputFilePaths, bool collections) { var resultFileIndexItemsList = new List <FileIndexItem>(); var toQueryPaths = new List <string>(); foreach (var path in inputFilePaths) { var parentPath = FilenamesHelper.GetParentPath(path); var(success, cachedResult) = CacheGetParentFolder(parentPath); List <FileIndexItem> item = null; switch (collections) { case false: if (!success) { break; } item = cachedResult.Where(p => p.ParentDirectory == parentPath && p.FileName == FilenamesHelper.GetFileName(path)).ToList(); break; case true: if (!success) { break; } item = cachedResult.Where(p => p.ParentDirectory == parentPath && p.FileCollectionName == FilenamesHelper.GetFileNameWithoutExtension(path)).ToList(); break; } if (!success || !item.Any()) { toQueryPaths.Add(path); continue; } resultFileIndexItemsList.AddRange(item); } var fileIndexItemsList = await GetObjectsByFilePathQuery(toQueryPaths.ToArray(), collections); resultFileIndexItemsList.AddRange(fileIndexItemsList); return(resultFileIndexItemsList); }
/// <summary> /// Sidecar files don't have an own item, but there referenced by file items /// in the method xmp files are added to the AddSidecarExtension list. /// </summary> /// <param name="xmpSubPath">sidecar item</param> /// <returns>completed task</returns> public async Task UpdateSidecarFile(string xmpSubPath) { if (!ExtensionRolesHelper.IsExtensionSidecar(xmpSubPath)) { return; } var parentPath = FilenamesHelper.GetParentPath(xmpSubPath); var fileNameWithoutExtension = FilenamesHelper.GetFileNameWithoutExtension(xmpSubPath); var directoryWithFileIndexItems = (await _query.GetAllFilesAsync(parentPath)).Where( p => p.ParentDirectory == parentPath && p.FileCollectionName == fileNameWithoutExtension).ToList(); await UpdateSidecarFile(xmpSubPath, directoryWithFileIndexItems); }
[ProducesResponseType(404)] // not found public IActionResult ListSizesByHash(string f) { // For serving jpeg files f = FilenamesHelper.GetFileNameWithoutExtension(f); // Restrict the fileHash to letters and digits only // I/O function calls should not be vulnerable to path injection attacks if (!Regex.IsMatch(f, "^[a-zA-Z0-9_-]+$")) { return(BadRequest()); } var data = new ThumbnailSizesExistStatusModel { TinyMeta = _thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.TinyMeta)), Small = _thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.Small)), Large = _thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.Large)), ExtraLarge = _thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.ExtraLarge)) }; // Success has all items (except tinyMeta) if (data.Small && data.Large && data.ExtraLarge) { return(Json(data)); } var sourcePath = _query.GetSubPathByHash(f); var isThumbnailSupported = ExtensionRolesHelper.IsExtensionThumbnailSupported(sourcePath); switch (isThumbnailSupported) { case true when !string.IsNullOrEmpty(sourcePath): Response.StatusCode = 202; return(Json(data)); case false when !string.IsNullOrEmpty(sourcePath): Response.StatusCode = 210; // A conflict, that the thumb is not generated yet return(Json("Thumbnail is not supported; for example you try to view a raw or video file")); default: return(NotFound("not in index")); } }
/// <summary> /// Extractes a <c>tar</c> archive to the specified directory. /// </summary> /// <param name="stream">The <i>.tar</i> to extract.</param> /// <param name="outputDir">Output directory to write the files.</param> public void ExtractTar(Stream stream, string outputDir) { var buffer = new byte[100]; while (true) { stream.Read(buffer, 0, 100); var name = Encoding.ASCII.GetString(buffer).Trim('\0'); if (string.IsNullOrEmpty(name) || stream.Position > stream.Length) { break; } stream.Seek(24, SeekOrigin.Current); stream.Read(buffer, 0, 12); var size = Convert.ToInt64(Encoding.UTF8.GetString(buffer, 0, 12).Trim('\0').Trim(), 8); stream.Seek(376L, SeekOrigin.Current); var output = $"{outputDir}/{name}"; if (!_storage.ExistFolder(FilenamesHelper.GetParentPath(output))) { _storage.CreateDirectory(FilenamesHelper.GetParentPath(output)); } if (!name.EndsWith("/", StringComparison.InvariantCulture)) { var str = new MemoryStream(); var buf = new byte[size]; stream.Read(buf, 0, buf.Length); str.Write(buf, 0, buf.Length); _storage.WriteStreamOpenOrCreate(str, output); } var pos = stream.Position; var offset = 512 - (pos % 512); if (offset == 512) { offset = 0; } stream.Seek(offset, SeekOrigin.Current); } }
[ProducesResponseType(210)] // raw public async Task <IActionResult> ByZoomFactor( string f, int z = 0, string filePath = "") { // For serving jpeg files f = FilenamesHelper.GetFileNameWithoutExtension(f); // Restrict the fileHash to letters and digits only // I/O function calls should not be vulnerable to path injection attacks if (!Regex.IsMatch(f, "^[a-zA-Z0-9_-]+$")) { return(BadRequest()); } // Cached view of item var sourcePath = await _query.GetSubPathByHashAsync(f); if (sourcePath == null) { if (await _query.GetObjectByFilePathAsync(filePath) == null) { return(NotFound("not in index")); } sourcePath = filePath; } if (ExtensionRolesHelper.IsExtensionThumbnailSupported(sourcePath)) { var fs1 = _iStorage.ReadStream(sourcePath); var fileExt = FilenamesHelper.GetFileExtensionWithoutDot(sourcePath); Response.Headers.Add("x-filename", FilenamesHelper.GetFileName(sourcePath)); return(File(fs1, MimeHelper.GetMimeType(fileExt))); } Response.StatusCode = 210; // A conflict, that the thumb is not generated yet return(Json("Thumbnail is not supported; for example you try to view a raw file")); }
// For displaying single photo's // Display feature only?! // input: Name of item by db style path // With Caching feature :) /// <summary> /// SingleItemPath do the query for singleitem + return detailview object /// </summary> /// <param name="singleItemDbPath"></param> /// <param name="colorClassActiveList">list of colorclasses to show, default show all</param> /// <param name="enableCollections">enable collections feature > default true</param> /// <param name="hideDeleted">do not show deleted files > default true</param> /// <returns>view object to show on the page</returns> public DetailView SingleItem( string singleItemDbPath, List <ColorClassParser.Color> colorClassActiveList = null, bool enableCollections = true, bool hideDeleted = true, SortType sort = SortType.FileName) { if (string.IsNullOrWhiteSpace(singleItemDbPath)) { return(null); } var parentFolder = FilenamesHelper.GetParentPath(singleItemDbPath); var fileIndexItemsList = DisplayFileFolders( parentFolder, null, false, false).ToList(); return(SingleItem( fileIndexItemsList, singleItemDbPath, colorClassActiveList, enableCollections, hideDeleted, sort)); }
internal string GetParentDirectoryFromRequestHeader() { var to = Request.Headers["to"].ToString(); if (to == "/") { return("/"); } // only used for direct import if (_iStorage.ExistFolder(FilenamesHelper.GetParentPath(to)) && FilenamesHelper.IsValidFileName(FilenamesHelper.GetFileName(to))) { Request.Headers["filename"] = FilenamesHelper.GetFileName(to); return(FilenamesHelper.GetParentPath(PathHelper.RemoveLatestSlash(to))); } // ReSharper disable once ConvertIfStatementToReturnStatement if (!_iStorage.ExistFolder(PathHelper.RemoveLatestSlash(to))) { return(null); } return(PathHelper.RemoveLatestSlash(to)); }
private static IOrderedQueryable <FileIndexItem> GetObjectsByFilePathCollectionQuery(ApplicationDbContext context, IEnumerable <string> filePathList) { var predicates = new List <Expression <Func <FileIndexItem, bool> > >(); // ReSharper disable once LoopCanBeConvertedToQuery foreach (var path in filePathList) { var fileNameWithoutExtension = FilenamesHelper.GetFileNameWithoutExtension(path); if (string.IsNullOrEmpty(FilenamesHelper.GetFileExtensionWithoutDot(path))) { predicates.Add(p => p.ParentDirectory == FilenamesHelper.GetParentPath(path) && p.FileName == fileNameWithoutExtension); continue; } predicates.Add(p => p.ParentDirectory == FilenamesHelper.GetParentPath(path) && p.FileName.StartsWith(fileNameWithoutExtension + ".")); } var predicate = PredicateBuilder.OrLoop(predicates); return(context.FileIndex.Where(predicate).OrderBy(r => r.FileName)); }
public async Task <IActionResult> FromUrl(string fileUrl, string filename, string structure) { if (filename == null) { filename = Base32.Encode(FileHash.GenerateRandomBytes(8)) + ".unknown"; } // I/O function calls should not be vulnerable to path injection attacks if (!Regex.IsMatch(filename, "^[a-zA-Z0-9_\\s\\.]+$") || !FilenamesHelper.IsValidFileName(filename)) { return(BadRequest()); } var tempImportFullPath = Path.Combine(_appSettings.TempFolder, filename); var importSettings = new ImportSettingsModel(Request) { Structure = structure }; var isDownloaded = await _httpClientHelper.Download(fileUrl, tempImportFullPath); if (!isDownloaded) { return(NotFound("'file url' not found or domain not allowed " + fileUrl)); } var importedFiles = await _import.Importer(new List <string> { tempImportFullPath }, importSettings); RemoveTempAndParentStreamFolder(tempImportFullPath); if (importedFiles.Count == 0) { Response.StatusCode = 206; } return(Json(importedFiles)); }
private ImportIndexItem ApplyStructure(ImportIndexItem importIndexItem, string overwriteStructure) { importIndexItem.Structure = _appSettings.Structure; // Feature to overwrite structures when importing using a header // Overwrite the structure in the ImportIndexItem if (!string.IsNullOrWhiteSpace(overwriteStructure)) { importIndexItem.Structure = overwriteStructure; } var structureService = new StructureService(_subPathStorage, importIndexItem.Structure); importIndexItem.FileIndexItem.ParentDirectory = structureService.ParseSubfolders( importIndexItem.FileIndexItem.DateTime, importIndexItem.FileIndexItem.FileCollectionName, FilenamesHelper.GetFileExtensionWithoutDot(importIndexItem.FileIndexItem.FileName)); importIndexItem.FileIndexItem.FileName = structureService.ParseFileName( importIndexItem.FileIndexItem.DateTime, importIndexItem.FileIndexItem.FileCollectionName, FilenamesHelper.GetFileExtensionWithoutDot(importIndexItem.FileIndexItem.FileName)); importIndexItem.FilePath = importIndexItem.FileIndexItem.FilePath; return(importIndexItem); }
[ResponseCache(Duration = 29030400)] // 4 weeks public IActionResult ThumbnailSmallOrTinyMeta(string f) { f = FilenamesHelper.GetFileNameWithoutExtension(f); // Restrict the fileHash to letters and digits only // I/O function calls should not be vulnerable to path injection attacks if (!Regex.IsMatch(f, "^[a-zA-Z0-9_-]+$")) { return(BadRequest()); } if (_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.Small))) { var stream = _thumbnailStorage.ReadStream(ThumbnailNameHelper.Combine(f, ThumbnailSize.Small)); Response.Headers.TryAdd("x-image-size", new StringValues(ThumbnailSize.Small.ToString())); return(File(stream, "image/jpeg")); } if (_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.TinyMeta))) { var stream = _thumbnailStorage.ReadStream(ThumbnailNameHelper.Combine(f, ThumbnailSize.TinyMeta)); Response.Headers.TryAdd("x-image-size", new StringValues(ThumbnailSize.TinyMeta.ToString())); return(File(stream, "image/jpeg")); } if (!_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, ThumbnailSize.Large))) { SetExpiresResponseHeadersToZero(); return(NotFound("hash not found")); } var streamDefaultThumbnail = _thumbnailStorage.ReadStream(ThumbnailNameHelper.Combine(f, ThumbnailSize.Large)); Response.Headers.TryAdd("x-image-size", new StringValues(ThumbnailSize.Large.ToString())); return(File(streamDefaultThumbnail, "image/jpeg")); }
/// <summary> /// fileIndexItemsList, Create an detailView object /// </summary> /// <param name="fileIndexItemsList">list of fileIndexItems</param> /// <param name="singleItemDbPath">database style path</param> /// <param name="colorClassActiveList">list of colorClasses to show, default show all</param> /// <param name="enableCollections">enable collections feature > default true</param> /// <param name="hideDeleted">do not show deleted files > default true</param> /// <returns>view object to show on the page</returns> public DetailView SingleItem( List <FileIndexItem> fileIndexItemsList, string singleItemDbPath, List <ColorClassParser.Color> colorClassActiveList = null, bool enableCollections = true, bool hideDeleted = true, SortType sort = SortType.FileName) { // reject empty requests if (string.IsNullOrWhiteSpace(singleItemDbPath)) { return(null); } var parentFolder = FilenamesHelper.GetParentPath(singleItemDbPath); // RemoveLatestSlash is for '/' folder var fileName = singleItemDbPath.Replace( PathHelper.RemoveLatestSlash(parentFolder) + "/", string.Empty); // Home has no parent, so return a value if (fileName == string.Empty && parentFolder == "/" && GetObjectByFilePath("/") != null) { return(new DetailView { FileIndexItem = GetObjectByFilePath("/"), RelativeObjects = new RelativeObjects(), Breadcrumb = new List <string> { "/" }, ColorClassActiveList = colorClassActiveList, IsDirectory = true, SubPath = "/", Collections = enableCollections }); } var currentFileIndexItem = fileIndexItemsList.FirstOrDefault(p => p.FileName == fileName); // Could be not found or not in directory cache if (currentFileIndexItem == null) { // retry currentFileIndexItem = GetObjectByFilePath(singleItemDbPath); if (currentFileIndexItem == null) { return(null); } AddCacheItem(currentFileIndexItem); } // To know when a file is deleted if (currentFileIndexItem.Tags.Contains("!delete!")) { currentFileIndexItem.Status = FileIndexItem.ExifStatus.Deleted; } if (currentFileIndexItem.IsDirectory == true) { currentFileIndexItem.CollectionPaths = new List <string> { singleItemDbPath }; return(new DetailView { IsDirectory = true, SubPath = singleItemDbPath, FileIndexItem = currentFileIndexItem, Collections = enableCollections, }); } if (currentFileIndexItem.Tags.Contains("!delete!")) { hideDeleted = false; } var fileIndexItemsForPrevNextList = DisplayFileFolders( parentFolder, colorClassActiveList, enableCollections, hideDeleted).ToList(); var itemResult = new DetailView { FileIndexItem = currentFileIndexItem, RelativeObjects = GetNextPrevInSubFolder(currentFileIndexItem, fileIndexItemsForPrevNextList, sort), Breadcrumb = Breadcrumbs.BreadcrumbHelper(singleItemDbPath), ColorClassActiveList = colorClassActiveList, IsDirectory = false, SubPath = singleItemDbPath, Collections = enableCollections }; // First item is current item var collectionPaths = new List <string> { singleItemDbPath }; collectionPaths.AddRange(fileIndexItemsList .Where(p => p.FileCollectionName == currentFileIndexItem.FileCollectionName) .Select(p => p.FilePath)); var collectionPathsHashSet = new HashSet <string>(collectionPaths); itemResult.FileIndexItem.CollectionPaths = collectionPathsHashSet.ToList(); return(itemResult); }
public void FilenamesHelper_GetFileExtensionWithoutDot_NoExtension() { var result = FilenamesHelper.GetFileExtensionWithoutDot("/test_image"); Assert.AreEqual(string.Empty, result); }
[ResponseCache(Duration = 29030400)] // 4 weeks public IActionResult Thumbnail( string f, bool isSingleItem = false, bool json = false, bool extraLarge = true) { // f is Hash // isSingleItem => detailView // Retry thumbnail => is when you press reset thumbnail // json, => to don't waste the users bandwidth. // For serving jpeg files f = FilenamesHelper.GetFileNameWithoutExtension(f); // Get the text before at (@) so replace @2000 with nothing to match fileHash var beforeAt = Regex.Match(f, ".*(?=@)", RegexOptions.None, TimeSpan.FromSeconds(1)).Value; if (!string.IsNullOrEmpty(beforeAt)) { f = beforeAt; } // Restrict the fileHash to letters and digits only // I/O function calls should not be vulnerable to path injection attacks if (!Regex.IsMatch(f, "^[a-zA-Z0-9_-]+$")) { return(BadRequest()); } var preferredSize = ThumbnailSize.ExtraLarge; var altSize = ThumbnailSize.Large; if (!extraLarge) { preferredSize = ThumbnailSize.Large; altSize = ThumbnailSize.ExtraLarge; } if (_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, preferredSize))) { return(ReturnThumbnailResult(f, json, preferredSize)); } if (_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(f, altSize))) { return(ReturnThumbnailResult(f, json, altSize)); } // Cached view of item var sourcePath = _query.GetSubPathByHash(f); if (sourcePath == null) { SetExpiresResponseHeadersToZero(); return(NotFound("not in index")); } // Need to check again for recently moved files if (!_iStorage.ExistFile(sourcePath)) { // remove from cache _query.ResetItemByHash(f); // query database again sourcePath = _query.GetSubPathByHash(f); SetExpiresResponseHeadersToZero(); if (sourcePath == null) { return(NotFound("not in index")); } } if (!_iStorage.ExistFile(sourcePath)) { return(NotFound("There is no thumbnail image " + f + " and no source image " + sourcePath)); } if (!isSingleItem) { // "Photo exist in database but " + "isSingleItem flag is Missing" SetExpiresResponseHeadersToZero(); Response.StatusCode = 202; // A conflict, that the thumb is not generated yet return(Json("Thumbnail is not ready yet")); } if (ExtensionRolesHelper.IsExtensionThumbnailSupported(sourcePath)) { var fs1 = _iStorage.ReadStream(sourcePath); var fileExt = FilenamesHelper.GetFileExtensionWithoutDot(sourcePath); var fileName = HttpUtility.UrlEncode(FilenamesHelper.GetFileName(sourcePath)); Response.Headers.TryAdd("x-filename", new StringValues(fileName)); return(File(fs1, MimeHelper.GetMimeType(fileExt))); } Response.StatusCode = 210; // A conflict, that the thumb is not generated yet return(Json("Thumbnail is not supported; for example you try to view a raw file")); }