Skip to content

Commit 21f50d6

Browse files
authored
Merge pull request #9 from ByteGuard-HQ/feature/antimalware-abstraction
Move antimalware scanner out of configuration
2 parents 244eb83 + 13f6cac commit 21f50d6

File tree

5 files changed

+44
-43
lines changed

5 files changed

+44
-43
lines changed

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,21 @@ In order to use the antimalware scanning capabilities, ensure you have a ByteGua
4141
### Basic validation
4242

4343
```csharp
44+
// Without antimalware scanner
4445
var configuration = new FileValidatorConfiguration
4546
{
4647
SupportedFileTypes = [FileExtensions.Pdf, FileExtensions.Jpg, FileExtensions.Png],
4748
FileSizeLimit = ByteSize.MegaBytes(25),
48-
ThrowExceptionOnInvalidFile = false,
49-
AntimalwareScanner = new SpecificAntimalwareScanner(scannerOptions)
49+
ThrowExceptionOnInvalidFile = false
5050
};
5151

5252
var fileValidator = new FileValidator(configuration);
5353
var isValid = fileValidator.IsValidFile("example.pdf", fileStream);
54+
55+
// With antimalware
56+
var antimalwareScanner = AntimalwareScannerImplementation();
57+
var fileValidator = new FileValidator(configuration, antimalwareScanner);
58+
var isValid = fileValidator.IsValidFile("example.pdf", fileStream);
5459
```
5560

5661
### Using the fluent builder
@@ -60,7 +65,6 @@ var configuration = new FileValidatorConfigurationBuilder()
6065
.AllowFileTypes(FileExtensions.Pdf, FileExtensions.Jpg, FileExtensions.Png)
6166
.SetFileSizeLimit(ByteSize.MegaBytes(25))
6267
.SetThrowExceptionOnInvalidFile(false)
63-
.AddAntimalwareScanner(new SpecificAntimalwareScanner(scannerOptions))
6468
.Build();
6569

6670
var fileValidator = new FileValidator(configuration);
@@ -96,15 +100,16 @@ public async Task<IActionResult> Upload(IFormFile file)
96100
{
97101
using var stream = file.OpenReadStream();
98102

103+
var antimalwareScanner = AntimalwareScannerImplementation();
104+
99105
var configuration = new FileValidatorConfiguration
100106
{
101107
SupportedFileTypes = [FileExtensions.Pdf, FileExtensions.Docx],
102108
FileSizeLimit = ByteSize.MegaBytes(10),
103-
ThrowExceptionOnInvalidFile = false,
104-
AntimalwareScanner = new SpecificAntimalwareScanner(scannerOptions)
109+
ThrowExceptionOnInvalidFile = false
105110
};
106111

107-
var validator = new FileValidator(configuration);
112+
var validator = new FileValidator(configuration, antimalwareScanner);
108113

109114
if (!validator.IsValidFile(file.FileName, stream))
110115
{
@@ -170,7 +175,6 @@ The `FileValidatorConfiguration` supports:
170175
| `SupportedFileTypes` | Yes | N/A | A list of allowed file extensions (e.g., `.pdf`, `.jpg`).<br>Use the predefined constants in `FileExtensions` for supported types. |
171176
| `FileSizeLimit` | Yes | N/A | Maximum permitted size of files.<br>Use the static `ByteSize` class provided with this package, to simplify your limit. |
172177
| `ThrowExceptionOnInvalidFile` | No | `true` | Whether to throw an exception on invalid files or return `false`. |
173-
| `AntimalwareScanner` | No | N/A | An antimalware scanner used to scan the given file for potential malware. |
174178

175179
### Exceptions
176180

src/ByteGuard.FileValidator/Configuration/FileValidatorConfiguration.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,5 @@ public class FileValidatorConfiguration
2929
/// Whether to throw an exception if an unsupported/invalid file is encountered. Defaults to <c>true</c>.
3030
/// </summary>
3131
public bool ThrowExceptionOnInvalidFile { get; set; } = true;
32-
33-
/// <summary>
34-
/// Optional antimalware scanner to use during file validation.
35-
/// </summary>
36-
public IAntimalwareScanner? AntimalwareScanner { get; set; } = null;
3732
}
3833
}

src/ByteGuard.FileValidator/Configuration/FileValidatorConfigurationBuilder.cs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public class FileValidatorConfigurationBuilder
1010
private readonly List<string> supportedFileTypes = new List<string>();
1111
private bool throwOnInvalidFiles = true;
1212
private long fileSizeLimit = ByteSize.MegaBytes(25);
13-
private IAntimalwareScanner? antimalwareScanner = null;
1413

1514
/// <summary>
1615
/// Allow specific file types (extensions) to be validated.
@@ -44,22 +43,6 @@ public FileValidatorConfigurationBuilder SetFileSizeLimit(long inFileSizeLimit)
4443
return this;
4544
}
4645

47-
/// <summary>
48-
/// Add an antimalware scanner.
49-
/// </summary>
50-
/// <param name="scanner">Antimalware scanner to use.</param>
51-
/// <exception cref="ArgumentNullException">Thrown when the provided scanner is null.</exception>
52-
public FileValidatorConfigurationBuilder AddAntimalwareScanner(IAntimalwareScanner scanner)
53-
{
54-
if (scanner == null)
55-
{
56-
throw new ArgumentNullException(nameof(scanner));
57-
}
58-
59-
antimalwareScanner = scanner;
60-
return this;
61-
}
62-
6346
/// <summary>
6447
/// Build configuration.
6548
/// </summary>
@@ -70,8 +53,7 @@ public FileValidatorConfiguration Build()
7053
{
7154
SupportedFileTypes = supportedFileTypes,
7255
ThrowExceptionOnInvalidFile = throwOnInvalidFiles,
73-
FileSizeLimit = fileSizeLimit,
74-
AntimalwareScanner = antimalwareScanner
56+
FileSizeLimit = fileSizeLimit
7557
};
7658

7759
ConfigurationValidator.ThrowIfInvalid(configuration);

src/ByteGuard.FileValidator/FileValidator.cs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using ByteGuard.FileValidator.Exceptions;
44
using ByteGuard.FileValidator.Models;
55
using ByteGuard.FileValidator.Validators;
6+
using ByteGuard.FileValidator.Scanners;
67

78
namespace ByteGuard.FileValidator
89
{
@@ -239,17 +240,38 @@ public class FileValidator
239240
/// </summary>
240241
private readonly FileValidatorConfiguration _configuration;
241242

243+
/// <summary>
244+
/// Antimalware scanner instance.
245+
/// </summary>
246+
private readonly IAntimalwareScanner? _antimalwareScanner;
247+
242248
/// <summary>
243249
/// Instantiate a new instance of the file validator.
244250
/// </summary>
245-
/// <param name="configuration">Configuration including which files should be supported and whether an exception should be thrown when encountering an invalid file.</param>
251+
/// <param name="configuration">Validator configuration.</param>
246252
public FileValidator(FileValidatorConfiguration configuration)
247253
{
248254
ConfigurationValidator.ThrowIfInvalid(configuration);
249255

250256
_configuration = configuration;
251257
}
252258

259+
/// <summary>
260+
/// Instantiate a new instance of the file validator.
261+
/// </summary>
262+
/// <param name="configuration">Validator configuration.</param>
263+
/// <param name="antimalwareScanner">Antimalware scanner to use during file validation.</param>
264+
public FileValidator(FileValidatorConfiguration configuration, IAntimalwareScanner antimalwareScanner)
265+
: this(configuration)
266+
{
267+
if (antimalwareScanner == null)
268+
{
269+
throw new ArgumentNullException(nameof(antimalwareScanner), "Antimalware scanner cannot be null.");
270+
}
271+
272+
_antimalwareScanner = antimalwareScanner;
273+
}
274+
253275
/// <summary>
254276
/// Get all supported file types based on the current configuration.
255277
/// </summary>
@@ -326,7 +348,7 @@ public bool IsValidFile(string fileName, byte[] content)
326348
}
327349

328350
// Validate antimalware scan if configured.
329-
if (_configuration.AntimalwareScanner != null)
351+
if (_antimalwareScanner != null)
330352
{
331353
var isClean = IsMalwareClean(fileName, content);
332354
if (!isClean)
@@ -988,7 +1010,7 @@ public bool IsValidOpenDocumentFormat(string filePath)
9881010
/// <exception cref="AntimalwareScannerException">Thrown if the configured antimalware scanner encountered an error while scanning the file for malware.</exception>
9891011
public bool IsMalwareClean(string fileName, byte[] content)
9901012
{
991-
if (_configuration.AntimalwareScanner is null)
1013+
if (_antimalwareScanner is null)
9921014
{
9931015
throw new InvalidOperationException("No antimalware scanner has been configured for the FileValidator.");
9941016
}
@@ -1010,7 +1032,7 @@ public bool IsMalwareClean(string fileName, byte[] content)
10101032
/// <exception cref="AntimalwareScannerException">Thrown if the configured antimalware scanner encountered an error while scanning the file for malware.</exception>
10111033
public bool IsMalwareClean(string fileName, Stream stream)
10121034
{
1013-
if (_configuration.AntimalwareScanner is null)
1035+
if (_antimalwareScanner is null)
10141036
{
10151037
throw new InvalidOperationException("No antimalware scanner has been configured for the FileValidator.");
10161038
}
@@ -1020,7 +1042,7 @@ public bool IsMalwareClean(string fileName, Stream stream)
10201042
bool isClean;
10211043
try
10221044
{
1023-
isClean = _configuration.AntimalwareScanner.IsClean(stream, fileName);
1045+
isClean = _antimalwareScanner.IsClean(stream, fileName);
10241046
}
10251047
catch (Exception ex)
10261048
{
@@ -1051,7 +1073,7 @@ public bool IsMalwareClean(string fileName, Stream stream)
10511073
/// <exception cref="AntimalwareScannerException">Thrown if the configured antimalware scanner encountered an error while scanning the file for malware.</exception>
10521074
public bool IsMalwareClean(string filePath)
10531075
{
1054-
if (_configuration.AntimalwareScanner is null)
1076+
if (_antimalwareScanner is null)
10551077
{
10561078
throw new InvalidOperationException("No antimalware scanner has been configured for the FileValidator.");
10571079
}

tests/ByteGuard.FileValidator.Tests.Unit/FileValidatorTests.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,10 +1073,9 @@ public void IsValidFile_AntimalwareScannerDetectsMalwareAndThrowExceptionOnInval
10731073
{
10741074
SupportedFileTypes = [".pdf"],
10751075
FileSizeLimit = ByteSize.MegaBytes(25),
1076-
ThrowExceptionOnInvalidFile = true,
1077-
AntimalwareScanner = mockAntimalwareScanner
1076+
ThrowExceptionOnInvalidFile = true
10781077
};
1079-
var fileValidator = new FileValidator(config);
1078+
var fileValidator = new FileValidator(config, mockAntimalwareScanner);
10801079
var fileBytes = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x2D }; // Valid PDF signature
10811080

10821081
// Act
@@ -1097,10 +1096,9 @@ public void IsValidFile_AntimalwareScannerDetectsMalwareAndThrowExceptionOnInval
10971096
{
10981097
SupportedFileTypes = [".pdf"],
10991098
FileSizeLimit = ByteSize.MegaBytes(25),
1100-
ThrowExceptionOnInvalidFile = false,
1101-
AntimalwareScanner = mockAntimalwareScanner
1099+
ThrowExceptionOnInvalidFile = false
11021100
};
1103-
var fileValidator = new FileValidator(config);
1101+
var fileValidator = new FileValidator(config, mockAntimalwareScanner);
11041102
var fileBytes = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x2D }; // Valid PDF signature
11051103

11061104
// Act

0 commit comments

Comments
 (0)