Example #1
0
        public void GetSize_Name_Large_NonValidLength()
        {
            var input   = ThumbnailNameHelper.Combine("non_valid_length", ThumbnailSize.Large);
            var result2 = ThumbnailNameHelper.GetSize(input);

            Assert.AreEqual(ThumbnailSize.Unknown, result2);
        }
Example #2
0
        private async Task LoopThoughChunk(IEnumerable <string> itemsInChunk, List <string> deletedFileHashes)
        {
            var fileIndexItems = await _query.GetObjectsByFileHashAsync(itemsInChunk.ToList());

            foreach (var result in fileIndexItems.Where(result =>
                                                        result.Status == FileIndexItem.ExifStatus.NotFoundNotInIndex
                                                        ))
            {
                var fileHashesToDelete = new List <string>
                {
                    ThumbnailNameHelper.Combine(result.FileHash,
                                                ThumbnailSize.TinyMeta),
                    ThumbnailNameHelper.Combine(result.FileHash,
                                                ThumbnailSize.ExtraLarge),
                    ThumbnailNameHelper.Combine(result.FileHash,
                                                ThumbnailSize.TinyMeta),
                    ThumbnailNameHelper.Combine(result.FileHash,
                                                ThumbnailSize.Large)
                };
                foreach (var fileHash in fileHashesToDelete)
                {
                    _thumbnailStorage.FileDelete(fileHash);
                }

                _logger.LogInformation("$");
                deletedFileHashes.Add(result.FileHash);
            }
        }
Example #3
0
        public void GetSize_Name_Large()
        {
            var input   = ThumbnailNameHelper.Combine("01234567890123456789123456", ThumbnailSize.Large);
            var result2 = ThumbnailNameHelper.GetSize(input);

            Assert.AreEqual(ThumbnailSize.Large, result2);
        }
Example #4
0
        public void GetSize_Name_NonValidLength()
        {
            var input   = "01234567890123456789123456@859693845";
            var result2 = ThumbnailNameHelper.GetSize(input);

            Assert.AreEqual(ThumbnailSize.Unknown, result2);
        }
Example #5
0
        public void Combine_Compare()
        {
            var result  = ThumbnailNameHelper.Combine("test_hash", 2000);
            var result2 = ThumbnailNameHelper.Combine("test_hash", ThumbnailSize.ExtraLarge);

            Assert.AreEqual(result, result2);
        }
Example #6
0
        public async Task CreateThumbTest_FileHash_SkipExtraLarge()
        {
            var storage = new FakeIStorage(new List <string> {
                "/"
            },
                                           new List <string> {
                _fakeIStorageImageSubPath
            },
                                           new List <byte[]> {
                CreateAnImage.Bytes
            });

            var fileHash = "test_hash";

            // skip xtra large
            var isCreated = await new Thumbnail(storage,
                                                storage, new FakeIWebLogger()).CreateThumb(
                _fakeIStorageImageSubPath, fileHash, true);

            Assert.AreEqual(true, isCreated);

            Assert.AreEqual(true, storage.ExistFile(fileHash));
            Assert.AreEqual(true, storage.ExistFile(
                                ThumbnailNameHelper.Combine(fileHash, ThumbnailSize.Small)));
            Assert.AreEqual(false, storage.ExistFile(
                                ThumbnailNameHelper.Combine(fileHash, ThumbnailSize.ExtraLarge)));
        }
Example #7
0
        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"));
        }
Example #8
0
        public void GetSize_Name_UnknownSize()
        {
            var input   = "test_hash@4789358";
            var result2 = ThumbnailNameHelper.GetSize(input);

            Assert.AreEqual(ThumbnailSize.Unknown, result2);
        }
Example #9
0
        public async Task CreateThumbTest_1arg_ThumbnailAlreadyExist()
        {
            var storage = new FakeIStorage(new List <string> {
                "/"
            },
                                           new List <string> {
                _fakeIStorageImageSubPath
            },
                                           new List <byte[]> {
                CreateAnImage.Bytes
            });

            var hash = (await new FileHash(storage).GetHashCodeAsync(_fakeIStorageImageSubPath)).Key;
            await storage.WriteStreamAsync(
                new PlainTextFileHelper().StringToStream("not 0 bytes"),
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.ExtraLarge));

            await storage.WriteStreamAsync(
                new PlainTextFileHelper().StringToStream("not 0 bytes"),
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.Large));

            await storage.WriteStreamAsync(
                new PlainTextFileHelper().StringToStream("not 0 bytes"),
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.Small));

            var isCreated = await new Thumbnail(storage,
                                                storage, new FakeIWebLogger()).CreateThumb(
                _fakeIStorageImageSubPath);

            Assert.AreEqual(false, isCreated[0].Item2);
        }
Example #10
0
        [ProducesResponseType(typeof(List <ImportIndexItem>), 415)] // wrong input
        public async Task <IActionResult> Thumbnail()
        {
            var tempImportPaths = await Request.StreamFile(_appSettings, _selectorStorage);

            var thumbnailNames = new List <string>();

            // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
            foreach (var tempImportSinglePath in tempImportPaths)
            {
                var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(tempImportSinglePath);

                var thumbToUpperCase = fileNameWithoutExtension.ToUpperInvariant();

                _logger.LogInformation($"[Import/Thumbnail] - {thumbToUpperCase}");

                if (ThumbnailNameHelper.GetSize(thumbToUpperCase) == ThumbnailSize.Unknown)
                {
                    continue;
                }

                // remove existing thumbnail if exist
                if (_thumbnailStorage.ExistFile(thumbToUpperCase))
                {
                    _thumbnailStorage.FileDelete(thumbToUpperCase);
                }

                thumbnailNames.Add(thumbToUpperCase);
            }

            // Status if there is nothing uploaded
            if (tempImportPaths.Count != thumbnailNames.Count)
            {
                Response.StatusCode = 415;
                return(Json(thumbnailNames));
            }

            for (var i = 0; i < tempImportPaths.Count; i++)
            {
                if (!_hostFileSystemStorage.ExistFile(tempImportPaths[i]))
                {
                    _logger.LogInformation($"[Import/Thumbnail] ERROR {tempImportPaths[i]} does not exist");
                    continue;
                }

                await _thumbnailStorage.WriteStreamAsync(
                    _hostFileSystemStorage.ReadStream(tempImportPaths[i]), thumbnailNames[i]);

                // Remove from temp folder to avoid long list of files
                RemoveTempAndParentStreamFolder(tempImportPaths[i]);
            }

            return(Json(thumbnailNames));
        }
Example #11
0
        public async Task <bool> WriteAndCropFile(string fileHash,
                                                  OffsetModel offsetData, int sourceWidth,
                                                  int sourceHeight, FileIndexItem.Rotation rotation,
                                                  string reference = null)
        {
            try
            {
                using (var thumbnailStream = new MemoryStream(offsetData.Data, offsetData.Index, offsetData.Count))
                    using (var smallImage = await Image.LoadAsync(thumbnailStream))
                        using (var outputStream = new MemoryStream())
                        {
                            var smallImageWidth  = smallImage.Width;
                            var smallImageHeight = smallImage.Height;

                            var result = NewImageSize.NewImageSizeCalc(smallImageWidth,
                                                                       smallImageHeight, sourceWidth, sourceHeight);

                            smallImage.Mutate(
                                i => i.Resize(smallImageWidth, smallImageHeight, KnownResamplers.Lanczos3)
                                .Crop(new Rectangle(result.DestX, result.DestY, result.DestWidth, result.DestHeight)));

                            var larger = (int)Math.Round(result.DestWidth * 1.2, 0);

                            smallImage.Mutate(
                                i => i.Resize(larger, 0, KnownResamplers.Lanczos3));

                            var rotate = RotateEnumToDegrees(rotation);
                            smallImage.Mutate(
                                i => i.Rotate(rotate));

                            await smallImage.SaveAsJpegAsync(outputStream);

                            await _thumbnailStorage.WriteStreamAsync(outputStream, ThumbnailNameHelper.Combine(fileHash, ThumbnailSize.TinyMeta));

                            if (_appSettings.ApplicationType == AppSettings.StarskyAppType.WebController)
                            {
                                _logger.LogInformation($"[WriteAndCropFile] fileHash: {fileHash} is written");
                            }
                        }

                return(true);
            }
            catch (Exception ex)
            {
                var message = ex.Message;
                if (message.StartsWith("Image cannot be loaded"))
                {
                    message = "Image cannot be loaded";
                }
                _logger.LogError($"[WriteFile@meta] Exception {reference} {message}", ex);
                return(false);
            }
        }
Example #12
0
        /// <summary>
        /// This list will be included in the zip
        /// </summary>
        /// <param name="fileIndexResultsList">the items</param>
        /// <param name="thumbnail">add the thumbnail or the source image</param>
        /// <returns>list of file paths</returns>
        public async Task <List <string> > CreateListToExport(List <FileIndexItem> fileIndexResultsList, bool thumbnail)
        {
            var filePaths = new List <string>();

            foreach (var item in fileIndexResultsList.Where(p =>
                                                            p.Status == FileIndexItem.ExifStatus.Ok).ToList())
            {
                if (thumbnail)
                {
                    var sourceThumb = Path.Combine(_appSettings.ThumbnailTempFolder,
                                                   ThumbnailNameHelper.Combine(item.FileHash, ThumbnailSize.Large, true));

                    await new Thumbnail(_iStorage, _thumbnailStorage, _logger)
                    .CreateThumb(item.FilePath, item.FileHash, true);

                    filePaths.Add(sourceThumb);
                    continue;
                }

                var sourceFile = _appSettings.DatabasePathToFilePath(item.FilePath, false);

                if (!_hostFileSystemStorage.ExistFile(sourceFile))
                {
                    continue;
                }

                // the jpeg file for example
                filePaths.Add(sourceFile);

                // when there is .xmp sidecar file (but only when file is a RAW file, ignored when for example jpeg)
                if (!ExtensionRolesHelper.IsExtensionForceXmp(item.FilePath) ||
                    !_iStorage.ExistFile(
                        ExtensionRolesHelper.ReplaceExtensionWithXmp(
                            item.FilePath)))
                {
                    continue;
                }

                var xmpFileFullPath = _appSettings.DatabasePathToFilePath(
                    ExtensionRolesHelper.ReplaceExtensionWithXmp(
                        item.FilePath), false);

                if (!_hostFileSystemStorage.ExistFile(xmpFileFullPath))
                {
                    continue;
                }
                filePaths.Add(xmpFileFullPath);
            }
            return(filePaths);
        }
Example #13
0
        public async Task ThumbnailCleanerTestAsync_Cleaner_WithDifferentSizes()
        {
            var fakeStorage = new FakeIStorage(new List <string> {
                "/"
            },
                                               new List <string>
            {
                ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.Large),
                ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.ExtraLarge),
                ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.TinyMeta),
                ThumbnailNameHelper.Combine("exist", ThumbnailSize.TinyMeta),
                ThumbnailNameHelper.Combine("exist", ThumbnailSize.ExtraLarge),
                ThumbnailNameHelper.Combine("exist", ThumbnailSize.TinyMeta),
                ThumbnailNameHelper.Combine("exist", ThumbnailSize.Large),
                ThumbnailNameHelper.Combine("12234456677", ThumbnailSize.ExtraLarge),
            });

            var fakeQuery = new FakeIQuery(new List <FileIndexItem>
            {
                new FileIndexItem("/test.jpg")
                {
                    FileHash = "exist"
                }
            });

            var thumbnailCleaner = new ThumbnailCleaner(fakeStorage, fakeQuery,
                                                        new FakeIWebLogger());

            await thumbnailCleaner.CleanAllUnusedFilesAsync(1);

            Assert.IsTrue(fakeStorage.ExistFile(
                              ThumbnailNameHelper.Combine("exist", ThumbnailSize.TinyMeta)));
            Assert.IsTrue(fakeStorage.ExistFile(
                              ThumbnailNameHelper.Combine("exist", ThumbnailSize.ExtraLarge)));
            Assert.IsTrue(fakeStorage.ExistFile(
                              ThumbnailNameHelper.Combine("exist", ThumbnailSize.Large)));
            Assert.IsTrue(fakeStorage.ExistFile(
                              ThumbnailNameHelper.Combine("exist", ThumbnailSize.TinyMeta)));

            Assert.IsFalse(fakeStorage.ExistFile(
                               ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.TinyMeta)));
            Assert.IsFalse(fakeStorage.ExistFile(
                               ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.ExtraLarge)));
            Assert.IsFalse(fakeStorage.ExistFile(
                               ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.Large)));
            Assert.IsFalse(fakeStorage.ExistFile(
                               ThumbnailNameHelper.Combine("12234456677", ThumbnailSize.ExtraLarge)));
        }
Example #14
0
        public async Task WriteAndCropFile_FileIsWritten()
        {
            var storage = new FakeIStorage();
            var service = new WriteMetaThumbnailService(new FakeSelectorStorage(storage),
                                                        new FakeIWebLogger(), new AppSettings());
            var result = await service.WriteAndCropFile("test", new OffsetModel
            {
                Count = CreateAnImage.Bytes.Length,
                Data  = CreateAnImage.Bytes,
                Index = 0
            }, 6, 6,
                                                        FileIndexItem.Rotation.Horizontal);

            Assert.IsTrue(result);
            Assert.IsTrue(storage.ExistFile(ThumbnailNameHelper.Combine("test", ThumbnailSize.TinyMeta)));
        }
Example #15
0
        public void Thumbnail_GetExtraLargeSecondChoiceResult()
        {
            var storage = new FakeIStorage(new List <string> {
                "/"
            }, new List <string>
            {
                ThumbnailNameHelper.Combine("test", ThumbnailSize.ExtraLarge)
            });
            var controller = new ThumbnailController(_query, new FakeSelectorStorage(storage));

            controller.ControllerContext.HttpContext = new DefaultHttpContext();

            controller.Thumbnail("test", true, false, false);

            controller.Response.Headers.TryGetValue("x-image-size", out var value);
            Assert.AreEqual(ThumbnailSize.ExtraLarge.ToString(), value.ToString());
        }
Example #16
0
        /// <summary>
        /// Check if the image has the right first bytes, if not remove
        /// </summary>
        /// <param name="fileHash">the fileHash file</param>
        /// <param name="thumbnailToSourceSize">size of output thumbnail Large/ExtraLarge</param>
        internal bool RemoveCorruptImage(string fileHash,
                                         ThumbnailSize thumbnailToSourceSize)
        {
            if (!_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(fileHash, thumbnailToSourceSize)))
            {
                return(false);
            }
            var imageFormat = ExtensionRolesHelper.GetImageFormat(_thumbnailStorage.ReadStream(
                                                                      ThumbnailNameHelper.Combine(fileHash, thumbnailToSourceSize), 160));

            if (imageFormat != ExtensionRolesHelper.ImageFormat.unknown)
            {
                return(false);
            }
            _thumbnailStorage.FileDelete(ThumbnailNameHelper.Combine(fileHash, thumbnailToSourceSize));
            return(true);
        }
Example #17
0
        public void ThumbnailSmallOrTinyMeta_GetLargeResultWhenAllAreMissing()
        {
            var storage = new FakeIStorage(new List <string> {
                "/"
            }, new List <string>
            {
                ThumbnailNameHelper.Combine("test", ThumbnailSize.Large)
            });
            var controller = new ThumbnailController(_query, new FakeSelectorStorage(storage));

            controller.ControllerContext.HttpContext = new DefaultHttpContext();

            controller.ThumbnailSmallOrTinyMeta("test");

            controller.Response.Headers.TryGetValue("x-image-size", out var value);
            Assert.AreEqual(ThumbnailSize.Large.ToString(), value.ToString());
        }
Example #18
0
        public void RemoveCorruptImage_RemoveCorruptImage()
        {
            var storage = new FakeIStorage(
                new List <string> {
                "/"
            },
                new List <string> {
                ThumbnailNameHelper.Combine("test", ThumbnailSize.ExtraLarge)
            },
                new List <byte[]> {
                new byte[0]
            });

            var result = new Thumbnail(storage,
                                       storage, new FakeIWebLogger()).RemoveCorruptImage("test", ThumbnailSize.ExtraLarge);

            Assert.IsTrue(result);
        }
Example #19
0
        public void RemoveCorruptImage_ShouldIgnore()
        {
            var storage = new FakeIStorage(
                new List <string> {
                "/"
            },
                new List <string> {
                ThumbnailNameHelper.Combine("test", ThumbnailSize.ExtraLarge)
            },
                new List <byte[]> {
                CreateAnImage.Bytes
            });

            var result = new Thumbnail(
                storage, storage,
                new FakeIWebLogger()).RemoveCorruptImage("test", ThumbnailSize.Large);

            Assert.IsFalse(result);
        }
Example #20
0
        [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"));
            }
        }
Example #21
0
        public async Task ThumbnailCleanerTestAsync_CatchException()
        {
            var fakeStorage = new FakeIStorage(new List <string> {
                "/"
            },
                                               new List <string>
            {
                ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.Large),
            });

            var fakeQuery = new FakeIQueryException(new Microsoft.EntityFrameworkCore.Storage.RetryLimitExceededException());

            var thumbnailCleaner = new ThumbnailCleaner(fakeStorage, fakeQuery,
                                                        new FakeIWebLogger());

            await thumbnailCleaner.CleanAllUnusedFilesAsync();

            // the file is there even the connection is crashed
            Assert.IsTrue(fakeStorage.ExistFile(
                              ThumbnailNameHelper.Combine("hash1234", ThumbnailSize.Large)));
        }
Example #22
0
        public async Task Thumbnail_CorruptImage_NoContentResult_Test()
        {
            // Arrange
            var storage         = ArrangeStorage();
            var plainTextStream = new PlainTextFileHelper().StringToStream("CorruptImage");
            await storage.WriteStreamAsync(plainTextStream, ThumbnailNameHelper.Combine(
                                               "hash-corrupt-image", ThumbnailSize.ExtraLarge));

            await _query.AddItemAsync(new FileIndexItem("/test2.jpg"){ FileHash = "hash-corrupt-image" });

            // Act
            var controller = new ThumbnailController(_query, new FakeSelectorStorage(storage));

            controller.ControllerContext.HttpContext = new DefaultHttpContext();

            var actionResult = controller.Thumbnail("hash-corrupt-image",
                                                    false, true) as NoContentResult;

            Assert.AreEqual(204, actionResult.StatusCode);

            // remove files + database item
            await _query.RemoveItemAsync(await _query.GetObjectByFilePathAsync("/test2.jpg"));
        }
Example #23
0
        /// <summary>
        /// Resize image with overlay
        /// </summary>
        /// <param name="outputPath">absolute path of output on host disk</param>
        /// <param name="profile">size of output, overlay size, must contain metaData </param>
        /// <param name="item">database item with filePath</param>
        /// <returns>true when success</returns>
        /// <exception cref="DecodingException">when output is not valid</exception>
        private async Task <bool> Resizer(string outputPath, AppSettingsPublishProfiles profile,
                                          FileIndexItem item)
        {
            // for less than 1000px
            if (profile.SourceMaxWidth <= 1000 && _thumbnailStorage.ExistFile(ThumbnailNameHelper.
                                                                              Combine(item.FileHash, ThumbnailSize.Large)))
            {
                await _overlayImage.ResizeOverlayImageThumbnails(item.FileHash, outputPath, profile);
            }
            else if (profile.SourceMaxWidth <= 2000 && _thumbnailStorage.ExistFile(ThumbnailNameHelper.
                                                                                   Combine(item.FileHash, ThumbnailSize.ExtraLarge)))
            {
                await _overlayImage.ResizeOverlayImageThumbnails(
                    ThumbnailNameHelper.Combine(item.FileHash, ThumbnailSize.ExtraLarge), outputPath, profile);
            }
            else if (_subPathStorage.ExistFile(item.FilePath))
            {
                // Thumbs are 2000 px (and larger)
                await _overlayImage.ResizeOverlayImageLarge(item.FilePath, outputPath, profile);
            }

            if (profile.MetaData)
            {
                await MetaData(item, outputPath);
            }

            var imageFormat = ExtensionRolesHelper.GetImageFormat(_hostFileSystemStorage.ReadStream(outputPath, 160));

            if (imageFormat == ExtensionRolesHelper.ImageFormat.jpg)
            {
                return(true);
            }

            _hostFileSystemStorage.FileDelete(outputPath);

            throw new DecodingException("[WebHtmlPublishService] image output is not valid");
        }
Example #24
0
        public void ListSizesByHash_AllExist_exceptTinyMeta()
        {
            var hash = "01234567890123456789123456";
            var item = _query.AddItem(new FileIndexItem("/test123.jpg")
            {
                FileHash = hash
            });

            // Arrange
            var storage = new FakeIStorage(new List <string>(),
                                           new List <string> {
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.Large),
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.Small),
                ThumbnailNameHelper.Combine(hash, ThumbnailSize.ExtraLarge),
            });

            // Check if exist
            var controller = new ThumbnailController(_query, new FakeSelectorStorage(storage));

            controller.ControllerContext.HttpContext = new DefaultHttpContext();

            var actionResult = controller.ListSizesByHash(hash) as JsonResult;

            // Thumbnail exist
            Assert.AreNotEqual(actionResult, null);
            var thumbnailAnswer = actionResult.Value as ThumbnailSizesExistStatusModel;

            Assert.AreEqual(200, controller.Response.StatusCode);
            Assert.AreEqual(true, thumbnailAnswer.Large);
            Assert.AreEqual(true, thumbnailAnswer.ExtraLarge);
            Assert.AreEqual(true, thumbnailAnswer.Small);
            // > TinyMeta is optional and not needed
            Assert.AreEqual(false, thumbnailAnswer.TinyMeta);

            _query.RemoveItem(item);
        }
Example #25
0
        [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"));
        }
Example #26
0
        /// <summary>
        /// Private use => CreateThumb
        /// Create a Thumbnail file to load it faster in the UI. Use FileIndexItem or database style path, Feature used by the cli tool
        /// </summary>
        /// <param name="subPath">relative path to find the file in the storage folder</param>
        /// <param name="fileHash">the base32 hash of the subPath file</param>
        /// <param name="skipExtraLarge">skip the extra large image</param>
        /// <returns>true, if successful</returns>
        private async Task <bool> CreateThumbInternal(string subPath, string fileHash, bool skipExtraLarge = false)
        {
            // FileType=supported + subPath=exit + fileHash=NOT exist
            if (!ExtensionRolesHelper.IsExtensionThumbnailSupported(subPath) ||
                !_iStorage.ExistFile(subPath))
            {
                return(false);
            }

            // File is already tested
            if (_iStorage.ExistFile(GetErrorLogItemFullPath(subPath)))
            {
                return(false);
            }

            var thumbnailToSourceSize = ThumbnailSize.ExtraLarge;

            if (skipExtraLarge)
            {
                thumbnailToSourceSize = ThumbnailSize.Large;
            }

            var largeThumbnailHash = ThumbnailNameHelper.Combine(fileHash, thumbnailToSourceSize);

            if (!_thumbnailStorage.ExistFile(ThumbnailNameHelper.Combine(
                                                 fileHash, thumbnailToSourceSize)))
            {
                // run resize sync
                var(_, resizeSuccess, resizeMessage) = (await ResizeThumbnailFromSourceImage(subPath,
                                                                                             ThumbnailNameHelper.GetSize(thumbnailToSourceSize),
                                                                                             largeThumbnailHash));

                // check if output any good
                RemoveCorruptImage(fileHash, thumbnailToSourceSize);

                if (!resizeSuccess || !_thumbnailStorage.ExistFile(
                        ThumbnailNameHelper.Combine(fileHash, thumbnailToSourceSize)))
                {
                    _logger.LogError($"[ResizeThumbnailFromSourceImage] " +
                                     $"output is null or corrupt for subPath {subPath}");
                    await WriteErrorMessageToBlockLog(subPath, resizeMessage);

                    return(false);
                }
                Console.Write(".");
            }

            var thumbnailFromThumbnailUpdateList = new List <ThumbnailSize>();

            void Add(ThumbnailSize size)
            {
                if (!_thumbnailStorage.ExistFile(
                        ThumbnailNameHelper.Combine(
                            fileHash, size))
                    )
                {
                    thumbnailFromThumbnailUpdateList.Add(size);
                }
            }

            new List <ThumbnailSize>
            {
                ThumbnailSize.Small,
                ThumbnailSize.Large                 // <- will be false when skipExtraLarge = true
            }.ForEach(Add);

            await(thumbnailFromThumbnailUpdateList).ForEachAsync(
                async(size)
                => await ResizeThumbnailFromThumbnailImage(
                    largeThumbnailHash,
                    ThumbnailNameHelper.GetSize(size),
                    ThumbnailNameHelper.Combine(fileHash, size)),
                10);

            Console.Write(".");
            return(thumbnailFromThumbnailUpdateList.Any());
        }
Example #27
0
        public void GetSize_ExtraLarge_Int()
        {
            var result = ThumbnailNameHelper.GetSize(2000);

            Assert.AreEqual(ThumbnailSize.ExtraLarge, result);
        }
Example #28
0
        [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"));
        }
Example #29
0
        public void GetSize_Small_Int()
        {
            var result = ThumbnailNameHelper.GetSize(300);

            Assert.AreEqual(ThumbnailSize.Small, result);
        }
Example #30
0
        public void GetSize_TinyMeta_Enum()
        {
            var result = ThumbnailNameHelper.GetSize(ThumbnailSize.TinyMeta);

            Assert.AreEqual(150, result);
        }