public void IsValidTests() {
            // Arrange
            var attribute = new FileExtensionsAttribute();

            // Act & Assert
            Assert.IsTrue(attribute.IsValid(null));  // Optional values are always valid
            Assert.IsTrue(attribute.IsValid("foo.png"));
            Assert.IsTrue(attribute.IsValid("foo.jpeg"));
            Assert.IsTrue(attribute.IsValid("foo.jpg"));
            Assert.IsTrue(attribute.IsValid("foo.gif"));
            Assert.IsTrue(attribute.IsValid(@"C:\Foo\bar.jpg"));
            Assert.IsFalse(attribute.IsValid("foo"));
            Assert.IsFalse(attribute.IsValid("foo.png.pif"));
            Assert.IsFalse(attribute.IsValid(@"C:\foo.png\bar"));
            Assert.IsFalse(attribute.IsValid("\0foo.png"));  // Illegal character
        }
        /// <summary>
        ///     Checks that the specified file name extension or extensions is valid.
        /// </summary>
        /// <returns>
        ///     true if the file name extension is valid; otherwise, false.
        /// </returns>
        /// <param name="value">A comma delimited list of valid file extensions.</param>
        public override bool IsValid(object value)
        {
            var file = value as HttpPostedFileBase;

            return(_innerAttribute.IsValid(file != null ? file.FileName : value));
        }
        public void IsValidWithCustomArgumentsTests()
        {
            var attribute = new FileExtensionsAttribute("pdf|doc|docx|rtf");

            Assert.IsTrue(attribute.IsValid(null));  // Optional values are always valid
            Assert.IsTrue(attribute.IsValid("foo.pdf"));
            Assert.IsTrue(attribute.IsValid("foo.doc"));
            Assert.IsTrue(attribute.IsValid("foo.docx"));
            Assert.IsTrue(attribute.IsValid("foo.rtf"));
            Assert.IsTrue(attribute.IsValid(new HttpPostedFileBaseStub("foo.rtf")));
            Assert.IsTrue(attribute.IsValid(@"C:\Foo\bar.pdf"));
            Assert.IsFalse(attribute.IsValid("foo"));
            Assert.IsFalse(attribute.IsValid("foo.png"));
            Assert.IsFalse(attribute.IsValid("foo.jpeg"));
            Assert.IsFalse(attribute.IsValid(new HttpPostedFileBaseStub("foo.jpeg")));
            Assert.IsFalse(attribute.IsValid("foo.doc.txt"));
        }
        public void IsValidWithNoArgumentTests()
        {
            var attribute = new FileExtensionsAttribute();

            Assert.IsTrue(attribute.IsValid(null));  // Optional values are always valid
            Assert.IsTrue(attribute.IsValid("foo.png"));
            Assert.IsTrue(attribute.IsValid("foo.jpeg"));
            Assert.IsTrue(attribute.IsValid("foo.jpg"));
            Assert.IsTrue(attribute.IsValid("foo.gif"));
            Assert.IsTrue(attribute.IsValid(new HttpPostedFileBaseStub("foo.gif")));
            Assert.IsTrue(attribute.IsValid(@"C:\Foo\bar.png"));
            Assert.IsFalse(attribute.IsValid("foo"));
            Assert.IsFalse(attribute.IsValid("foo.doc"));
            Assert.IsFalse(attribute.IsValid("foo.txt"));
            Assert.IsFalse(attribute.IsValid("foo.png.txt"));
            Assert.IsFalse(attribute.IsValid(new HttpPostedFileBaseStub("foo.png.txt")));
        }
        /// <summary>
        /// Checks if the file is allowed based on specific conditions.
        /// </summary>
        /// <param name="file"></param>
        /// <param name="allowedExtensions">Comma separated, e.g: "txt,pdf,doc,docx". You need to pass FileCheckLayers.CheckExtensions as one of the layers.</param>
        /// <param name="allowedContentTypes">Comma separated, e.g: "text/plain,application/pdf,application/msword". You need to pass FileCheckLayers.CheckContentType as one of the layers.</param>
        /// <param name="maxSingleFileSize">Accepted file size in bytes. You need to pass FileCheckLayers.CheckFileSize as one of the layers.</param>
        /// <param name="layers">The check-points that you want the file to go through.</param>
        /// <returns>true if the file is passed; otherwise false.</returns>
        public static bool IsFileAllowed(this IFormFile file, string allowedExtensions, string allowedContentTypes, long?maxSingleFileSize, params FileCheckLayers[] layers)
        {
            try
            {
                //Build the layers dictionay (since we will check the layers more than once).
                Dictionary <FileCheckLayers, bool> foundLayers = SetupLayersDictionary(layers);

                //Check null values.
                CheckNulls(file, allowedExtensions, allowedContentTypes, maxSingleFileSize, foundLayers);

                var allowedContentTypesArray = new string[] { };

                if (!string.IsNullOrWhiteSpace(allowedContentTypes))
                {
                    allowedContentTypesArray = allowedContentTypes.Trim().Split(",");
                }

                bool foundAllLayers = foundLayers.TryGetValue(FileCheckLayers.AllLayers, out foundAllLayers);


                //FileCheckLayers.CheckExtensions
                bool foundCheckExtensions = foundLayers.TryGetValue(FileCheckLayers.CheckExtensions, out foundCheckExtensions);
                if (foundCheckExtensions || foundAllLayers)
                {
                    var fileExtensionsAttribute = new FileExtensionsAttribute()
                    {
                        Extensions = allowedExtensions
                    };
                    if (!fileExtensionsAttribute.IsValid(file?.FileName))
                    {
                        throw new BusinessException(string.Format($"File extension {file?.FileName} could not be found in the {nameof(allowedExtensions)}."));
                    }
                    ;
                }


                //Layer2 checker, check if the recieved content-type matches the given file name.
                bool foundCheckFileContentTypeToFileExtension = foundLayers.TryGetValue(FileCheckLayers.CheckFileContentTypeToFileExtension, out foundCheckFileContentTypeToFileExtension);
                if (foundCheckFileContentTypeToFileExtension || foundAllLayers)
                {
                    MatchContentTypeToFileName(file?.FileName, file?.ContentType, allowedContentTypesArray, foundLayers, foundAllLayers);
                }


                //Layer3 checker, check if given content-type is allowed
                bool foundCheckContentType = foundLayers.TryGetValue(FileCheckLayers.CheckContentType, out foundCheckContentType);
                if (foundCheckContentType || foundAllLayers)
                {
                    IsContentTypeAllowed(file?.ContentType, allowedContentTypesArray);
                }

                //Check file size.
                bool foundCheckFileSize = foundLayers.TryGetValue(FileCheckLayers.CheckFileSize, out foundCheckFileSize);
                if (foundCheckFileSize || foundAllLayers)
                {
                    if (file?.Length > maxSingleFileSize)
                    {
                        throw new BusinessException(string.Format($"File size {file?.Length} exceeded the {nameof(maxSingleFileSize)}."));
                    }
                }
            }
            catch (BusinessException ex)
            {
                //TODO: add throw exception option.
                return(false);
            }

            return(true);
        }