├── test
└── Altinn.FileAnalyzers.Tests
│ ├── Usings.cs
│ ├── MimeType
│ ├── example.pdf
│ ├── example.jpg.pdf
│ ├── MimeTypeAnalyserTests.cs
│ └── MimeTypeValidatorTests.cs
│ ├── ModuleInitializer.cs
│ ├── PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt
│ ├── PublicApiTests.cs
│ ├── EmbeddedResource.cs
│ └── Altinn.FileAnalyzers.Tests.csproj
├── .csharpierignore
├── global.json
├── renovate.json
├── .config
└── dotnet-tools.json
├── src
├── Directory.Build.targets
├── Directory.Build.props
└── Altinn.FileAnalyzers
│ ├── Altinn.FileAnalyzers.csproj
│ └── MimeType
│ ├── MimeTypeAnalyser.cs
│ ├── MimeTypeValidator.cs
│ └── ServiceCollectionExtensions.cs
├── .github
├── workflows
│ ├── add-to-project.yml
│ ├── dotnet-test.yml
│ ├── publish-release.yml
│ ├── codeql.yml
│ ├── test-and-analyze-fork.yml
│ └── test-and-analyze.yml
└── release.yml
├── .vscode
├── launch.json
└── tasks.json
├── LICENSE
├── Directory.Build.props
├── Directory.Packages.props
├── Altinn.FileAnalyzers.sln
├── .gitattributes
├── README.md
├── .gitignore
└── .editorconfig
/test/Altinn.FileAnalyzers.Tests/Usings.cs:
--------------------------------------------------------------------------------
1 | global using Xunit;
2 |
--------------------------------------------------------------------------------
/.csharpierignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | .git/
4 | *.xml
5 | *.csproj
6 | *.props
7 | *.targets
8 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.413",
4 | "rollForward": "latestFeature",
5 | "allowPrerelease": false
6 | }
7 | }
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/MimeType/example.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/altinn/fileanalyzers-lib-dotnet/main/test/Altinn.FileAnalyzers.Tests/MimeType/example.pdf
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/MimeType/example.jpg.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/altinn/fileanalyzers-lib-dotnet/main/test/Altinn.FileAnalyzers.Tests/MimeType/example.jpg.pdf
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "local>Altinn/renovate-config"
5 | ],
6 | "ignoreDeps": ["Altinn.App.Core"]
7 | }
8 |
--------------------------------------------------------------------------------
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "csharpier": {
6 | "version": "1.1.2",
7 | "commands": [
8 | "csharpier"
9 | ],
10 | "rollForward": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | namespace Altinn.Codelists.Tests;
4 |
5 | internal static class ModuleInitializer
6 | {
7 | [ModuleInitializer]
8 | public static void Initialize()
9 | {
10 | VerifierSettings.AutoVerify(includeBuildServer: false);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 | $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/add-to-project.yml:
--------------------------------------------------------------------------------
1 | name: Add new issues to Team Apps project
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 |
8 | jobs:
9 | add-to-project:
10 | name: Add issue to Team Apps project
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/add-to-project@main
14 | with:
15 | project-url: https://github.com/orgs/Altinn/projects/39
16 | github-token: ${{ secrets.ASSIGN_PROJECT_TOKEN }}
17 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - ignore-for-release
5 | categories:
6 | - title: Breaking Changes 🛠
7 | labels:
8 | - semver-major
9 | - breaking-change
10 | - title: New Features 🎉
11 | labels:
12 | - semver-minor
13 | - feature
14 | - title: Bugfixes 🐛
15 | labels:
16 | - semver-patch
17 | - bugfix
18 | - title: Dependency Upgrades 📦
19 | labels:
20 | - dependency
21 | - title: Other Changes
22 | labels:
23 | - "*"
24 |
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/PublicApiTests.PublicApi_ShouldNotChange_Unintentionally.verified.txt:
--------------------------------------------------------------------------------
1 | [assembly: System.Reflection.AssemblyMetadata("PackageReference.Altinn.App.Core", "8.0.0")]
2 | [assembly: System.Reflection.AssemblyMetadata("PackageReference.Mime-Detective", "")]
3 | [assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName=".NET 8.0")]
4 | namespace Altinn.FileAnalyzers.MimeType
5 | {
6 | public static class ServiceCollectionExtensions
7 | {
8 | public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddMimeTypeValidation(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { }
9 | public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddMimeTypeValidation(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, MimeDetective.IContentInspector inspector) { }
10 | }
11 | }
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/PublicApiTests.cs:
--------------------------------------------------------------------------------
1 | using PublicApiGenerator;
2 |
3 | namespace Altinn.FileAnalyzers.Tests;
4 |
5 | public class PublicApiTests
6 | {
7 | private static readonly string[] _excludedAttributes =
8 | [
9 | "System.Runtime.CompilerServices.RefSafetyRulesAttribute",
10 | "System.Diagnostics.DebuggerNonUserCodeAttribute",
11 | "System.ComponentModel.EditorBrowsableAttribute",
12 | "System.Runtime.CompilerServices.InternalsVisibleToAttribute",
13 | ];
14 |
15 | [Fact]
16 | public async Task PublicApi_ShouldNotChange_Unintentionally()
17 | {
18 | // Arrange
19 | var assembly = typeof(Altinn.FileAnalyzers.MimeType.ServiceCollectionExtensions).Assembly;
20 |
21 | // Act
22 | var publicApi = assembly.GeneratePublicApi(
23 | new ApiGeneratorOptions { ExcludeAttributes = _excludedAttributes }
24 | );
25 |
26 | // Assert
27 | await Verify(publicApi);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | // Use IntelliSense to find out which attributes exist for C# debugging
6 | // Use hover for the description of the existing attributes
7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
8 | "name": ".NET Core Launch (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/test/Altinn.FileAnalyzers.Tests/bin/Debug/net6.0/Altinn.FileAnalyzers.Tests.dll",
14 | "args": [],
15 | "cwd": "${workspaceFolder}/test/Altinn.FileAnalyzers.Tests",
16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17 | "console": "internalConsole",
18 | "stopAtEntry": false
19 | },
20 | {
21 | "name": ".NET Core Attach",
22 | "type": "coreclr",
23 | "request": "attach"
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/EmbeddedResource.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace Altinn.FileAnalyzers.Tests;
4 |
5 | public static class EmbeddedResource
6 | {
7 | public static async Task LoadDataAsString(string resourceName)
8 | {
9 | var resourceStream = LoadDataAsStream(resourceName);
10 |
11 | using var reader = new StreamReader(resourceStream);
12 | string text = await reader.ReadToEndAsync();
13 |
14 | return text;
15 | }
16 |
17 | public static Stream LoadDataAsStream(string resourceName)
18 | {
19 | var assembly = Assembly.GetExecutingAssembly();
20 | Stream? resourceStream = assembly.GetManifestResourceStream(resourceName);
21 |
22 | if (resourceStream is null)
23 | {
24 | throw new InvalidOperationException(
25 | $"Unable to find resource {resourceName} embedded in assembly {assembly.FullName}."
26 | );
27 | }
28 |
29 | resourceStream.Seek(0, SeekOrigin.Begin);
30 |
31 | return resourceStream;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Altinn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet-test.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test on windows, macos and ubuntu
2 | on:
3 | push:
4 | branches: [ main ]
5 | pull_request:
6 | branches: [ main ]
7 | types: [opened, synchronize, reopened]
8 | workflow_dispatch:
9 | jobs:
10 | analyze:
11 | strategy:
12 | matrix:
13 | os: [macos-latest,windows-latest,ubuntu-latest] # TODO: Fix test to run on ubuntu-latest also
14 | name: Run dotnet build and test
15 | runs-on: ${{ matrix.os}}
16 | env:
17 | DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE: false
18 | steps:
19 | - name: Setup .NET
20 | uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5
21 | with:
22 | dotnet-version: |
23 | 8.0.x
24 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
25 | with:
26 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
27 | - name: Build
28 | run: |
29 | dotnet build Altinn.FileAnalyzers.sln -v m
30 | - name: Test
31 | run: |
32 | dotnet test Altinn.FileAnalyzers.sln -v m
33 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}/test/Altinn.FileAnalyzers.Tests/Altinn.FileAnalyzers.Tests.csproj",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | },
16 | {
17 | "label": "publish",
18 | "command": "dotnet",
19 | "type": "process",
20 | "args": [
21 | "publish",
22 | "${workspaceFolder}/test/Altinn.FileAnalyzers.Tests/Altinn.FileAnalyzers.Tests.csproj",
23 | "/property:GenerateFullPaths=true",
24 | "/consoleloggerparameters:NoSummary"
25 | ],
26 | "problemMatcher": "$msCompile"
27 | },
28 | {
29 | "label": "watch",
30 | "command": "dotnet",
31 | "type": "process",
32 | "args": [
33 | "watch",
34 | "run",
35 | "--project",
36 | "${workspaceFolder}/test/Altinn.FileAnalyzers.Tests/Altinn.FileAnalyzers.Tests.csproj"
37 | ],
38 | "problemMatcher": "$msCompile"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/.github/workflows/publish-release.yml:
--------------------------------------------------------------------------------
1 | name: Pack and publish nugets
2 |
3 | on:
4 | release:
5 | types:
6 | - published
7 |
8 | jobs:
9 | build-pack:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
13 | with:
14 | fetch-depth: 0
15 |
16 | - name: Install dotnet
17 | uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5
18 | with:
19 | dotnet-version: |
20 | 8.0.x
21 | - name: Install deps
22 | run: |
23 | dotnet restore
24 | - name: Build
25 | run: |
26 | dotnet build --configuration Release --no-restore -p:Deterministic=true -p:BuildNumber=${{ github.run_number }}
27 | - name: Pack
28 | run: |
29 | dotnet pack Altinn.FileAnalyzers.sln --configuration Release --no-restore --no-build -p:BuildNumber=${{ github.run_number }} -p:Deterministic=true
30 | - name: Versions
31 | run: |
32 | dotnet --version
33 | - name: Publish
34 | run: |
35 | dotnet nuget push src/**/bin/Release/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | NU1901;NU1902;NU1903;NU1904
5 |
6 |
7 |
8 | latest
9 | true
10 | Recommended
11 | strict
12 | true
13 | all
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers
20 |
21 |
22 | all
23 | runtime; build; native; contentfiles; analyzers
24 |
25 |
26 | all
27 | runtime; build; native; contentfiles; analyzers
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | true
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | $([System.IO.Directory]::GetParent($(MSBuildThisFileDirectory)).Parent.FullName)
13 | preview.0
14 | v
15 | true
16 |
17 |
18 |
19 |
20 | $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(BuildNumber)
21 | $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(BuildNumber)
22 | $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(BuildNumber)
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | true
32 |
33 |
34 |
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/Altinn.FileAnalyzers.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 | false
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | runtime; build; native; contentfiles; analyzers; buildtransitive
28 | all
29 |
30 |
31 | runtime; build; native; contentfiles; analyzers; buildtransitive
32 | all
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/Altinn.FileAnalyzers/Altinn.FileAnalyzers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 | Altinn;Studio;App;Core
8 |
9 | This class library holds extra file analyzers for Altinn Studio apps.
10 |
11 |
12 | direct
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | <_Parameter1>PackageReference.%(PackageReference.Identity)
30 | <_Parameter2 Condition="'%(PackageReference.VersionOverride)' != ''">%(PackageReference.VersionOverride)
31 | <_Parameter2 Condition="'%(PackageReference.VersionOverride)' == ''">%(PackageReference.Version)
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Altinn.FileAnalyzers.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.33516.290
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.FileAnalyzers", "src\Altinn.FileAnalyzers\Altinn.FileAnalyzers.csproj", "{FB7A3052-06C8-4A84-A198-F3AEECE1472D}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Altinn.FileAnalyzers.Tests", "test\Altinn.FileAnalyzers.Tests\Altinn.FileAnalyzers.Tests.csproj", "{94532621-70D1-405D-8BBC-8330C0FCCF2D}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {FB7A3052-06C8-4A84-A198-F3AEECE1472D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {FB7A3052-06C8-4A84-A198-F3AEECE1472D}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {FB7A3052-06C8-4A84-A198-F3AEECE1472D}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {FB7A3052-06C8-4A84-A198-F3AEECE1472D}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {94532621-70D1-405D-8BBC-8330C0FCCF2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {94532621-70D1-405D-8BBC-8330C0FCCF2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {94532621-70D1-405D-8BBC-8330C0FCCF2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {94532621-70D1-405D-8BBC-8330C0FCCF2D}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {C00954BE-7360-45D6-B49F-A2925CC278FB}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/src/Altinn.FileAnalyzers/MimeType/MimeTypeAnalyser.cs:
--------------------------------------------------------------------------------
1 | using Altinn.App.Core.Features.FileAnalysis;
2 | using Microsoft.AspNetCore.Http;
3 | using Microsoft.AspNetCore.Http.Features;
4 | using MimeDetective;
5 |
6 | namespace Altinn.FileAnalyzers.MimeType;
7 |
8 | internal sealed class MimeTypeAnalyser(
9 | IHttpContextAccessor _httpContextAccessor,
10 | IContentInspector _inspector
11 | ) : IFileAnalyser
12 | {
13 | ///
14 | public string Id { get; private set; } = "mimeTypeAnalyser";
15 |
16 | ///
17 | public Task Analyse(Stream stream, string? filename = null)
18 | {
19 | // Allow synchronous IO access for the usage of MimeDetective
20 | // which does not have async methods. This on a per request basis.
21 | var syncIOFeature =
22 | _httpContextAccessor.HttpContext?.Features.Get();
23 | if (syncIOFeature is not null)
24 | syncIOFeature.AllowSynchronousIO = true;
25 |
26 | var results = _inspector.Inspect(stream);
27 |
28 | // We only care for the 100% match anything else is considered unsafe.
29 | var match = results
30 | .OrderByDescending(match => match.Points)
31 | .FirstOrDefault(match => match.Percentage == 1);
32 |
33 | var fileAnalysisResult = new FileAnalysisResult(Id);
34 | if (match is not null)
35 | {
36 | fileAnalysisResult.Extensions = match.Definition.File.Extensions.ToList();
37 | fileAnalysisResult.MimeType = match.Definition.File.MimeType;
38 | fileAnalysisResult.Filename = filename;
39 | }
40 |
41 | return Task.FromResult(fileAnalysisResult);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/MimeType/MimeTypeAnalyserTests.cs:
--------------------------------------------------------------------------------
1 | using Altinn.App.Core.Features.FileAnalysis;
2 | using Altinn.FileAnalyzers.MimeType;
3 | using Microsoft.AspNetCore.Http;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using MimeDetective;
6 | using Moq;
7 |
8 | namespace Altinn.FileAnalyzers.Tests.MimeType;
9 |
10 | public class MimeTypeAnalyserTests
11 | {
12 | private readonly IContentInspector _contentInspector;
13 |
14 | public MimeTypeAnalyserTests()
15 | {
16 | IServiceCollection services = new ServiceCollection();
17 | services.AddMimeTypeValidation();
18 | var serviceProvider = services.BuildServiceProvider();
19 | _contentInspector = serviceProvider.GetRequiredService();
20 | }
21 |
22 | [Fact]
23 | public async Task Analyse_ValidPdf_ShouldReturnCorrectMimeType()
24 | {
25 | var httpContextAccessorMock = new Mock();
26 | var mimeTypeAnalyser = new MimeTypeAnalyser(
27 | httpContextAccessorMock.Object,
28 | _contentInspector
29 | );
30 | var stream = EmbeddedResource.LoadDataAsStream(
31 | "Altinn.FileAnalyzers.Tests.MimeType.example.pdf"
32 | );
33 |
34 | FileAnalysisResult analysisResult = await mimeTypeAnalyser.Analyse(stream);
35 |
36 | Assert.Equal("application/pdf", analysisResult.MimeType);
37 | }
38 |
39 | [Fact]
40 | public async Task Analyse_InvalidPdf_ShouldReturnCorrectMimeType()
41 | {
42 | var httpContextAccessorMock = new Mock();
43 | var mimeTypeAnalyser = new MimeTypeAnalyser(
44 | httpContextAccessorMock.Object,
45 | _contentInspector
46 | );
47 | var stream = EmbeddedResource.LoadDataAsStream(
48 | "Altinn.FileAnalyzers.Tests.MimeType.example.jpg.pdf"
49 | );
50 |
51 | FileAnalysisResult analysisResult = await mimeTypeAnalyser.Analyse(stream);
52 |
53 | Assert.Equal("image/jpeg", analysisResult.MimeType);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Altinn.FileAnalyzers/MimeType/MimeTypeValidator.cs:
--------------------------------------------------------------------------------
1 | using Altinn.App.Core.Features.FileAnalysis;
2 | using Altinn.App.Core.Features.Validation;
3 | using Altinn.App.Core.Models.Validation;
4 | using Altinn.Platform.Storage.Interface.Models;
5 |
6 | namespace Altinn.FileAnalyzers.MimeType;
7 |
8 | internal sealed class MimeTypeValidator : IFileValidator
9 | {
10 | ///
11 | public string Id { get; private set; } = "mimeTypeValidator";
12 |
13 | ///
14 | public Task<(bool Success, IEnumerable Errors)> Validate(
15 | DataType dataType,
16 | IEnumerable fileAnalysisResults
17 | )
18 | {
19 | List errors = new();
20 |
21 | var fileMimeTypeResult = fileAnalysisResults.FirstOrDefault(x => x.MimeType is not null);
22 |
23 | // Verify that file mime type is an allowed content-type
24 | if (
25 | !dataType.AllowedContentTypes.Contains(
26 | fileMimeTypeResult?.MimeType,
27 | StringComparer.InvariantCultureIgnoreCase
28 | ) && !dataType.AllowedContentTypes.Contains("application/octet-stream")
29 | )
30 | {
31 | ValidationIssue error = new()
32 | {
33 | Source = "File",
34 | Code = ValidationIssueCodes.DataElementCodes.ContentTypeNotAllowed,
35 | Severity = ValidationIssueSeverity.Error,
36 | Description =
37 | $"The {fileMimeTypeResult?.Filename + " "}file does not appear to be of the allowed content type according to the configuration for data type {dataType.Id}. Allowed content types are {string.Join(", ", dataType.AllowedContentTypes)}",
38 | };
39 |
40 | errors.Add(error);
41 |
42 | return Task.FromResult<(bool Success, IEnumerable Errors)>(
43 | (false, errors)
44 | );
45 | }
46 |
47 | return Task.FromResult<(bool Success, IEnumerable Errors)>((true, errors));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Altinn.FileAnalyzers/MimeType/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Altinn.App.Core.Features.FileAnalysis;
2 | using Altinn.App.Core.Features.Validation;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using MimeDetective;
5 |
6 | namespace Altinn.FileAnalyzers.MimeType;
7 |
8 | ///
9 | /// Extension methods for adding MimeType analysis and validation to the service collection
10 | ///
11 | public static class ServiceCollectionExtensions
12 | {
13 | ///
14 | /// Adds support for MimeType analysis and validation by registering
15 | /// * IFileAnalyser implementation
16 | /// * IFileValidator implementation
17 | /// based on the MimeDetective library.
18 | ///
19 | public static IServiceCollection AddMimeTypeValidation(this IServiceCollection services)
20 | {
21 | var inspector = new ContentInspectorBuilder()
22 | {
23 | Definitions = MimeDetective.Definitions.DefaultDefinitions.All(),
24 | MatchEvaluatorOptions = new MimeDetective.Engine.DefinitionMatchEvaluatorOptions()
25 | {
26 | IncludeMatchesComplete = true,
27 | IncludeMatchesFailed = false,
28 | IncludeMatchesPartial = true,
29 | IncludeSegmentsPrefix = true,
30 | IncludeSegmentsStrings = true,
31 | },
32 | }.Build();
33 | services.AddMimeTypeValidation(inspector);
34 | return services;
35 | }
36 |
37 | ///
38 | /// Adds support for MimeType analysis and validation by registering
39 | /// * IFileAnalyser implementation
40 | /// * IFileValidator implementation
41 | /// based on the MimeDetective library.
42 | ///
43 | public static IServiceCollection AddMimeTypeValidation(
44 | this IServiceCollection services,
45 | IContentInspector inspector
46 | )
47 | {
48 | services.AddSingleton();
49 | services.AddSingleton();
50 |
51 | services.AddSingleton(inspector);
52 | return services;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | # The branches below must be a subset of the branches above
8 | branches: [ "main" ]
9 | schedule:
10 | - cron: '37 20 * * 3'
11 |
12 | jobs:
13 | analyze:
14 | name: Analyze
15 | runs-on: ubuntu-latest
16 | permissions:
17 | actions: read
18 | contents: read
19 | security-events: write
20 |
21 | strategy:
22 | fail-fast: false
23 | matrix:
24 | language: [ 'csharp' ]
25 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
26 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
27 |
28 | steps:
29 | - name: Checkout repository
30 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
31 |
32 | # Initializes the CodeQL tools for scanning.
33 | - name: Initialize CodeQL
34 | uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # v4
35 | with:
36 | languages: ${{ matrix.language }}
37 | queries: security-extended,security-and-quality
38 | # If you wish to specify custom queries, you can do so here or in a config file.
39 | # By default, queries listed here will override any specified in a config file.
40 | # Prefix the list here with "+" to use these queries and those in the config file.
41 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
42 |
43 |
44 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
45 | # If this step fails, then you should remove it and run the build manually (see below)
46 | - name: Autobuild
47 | uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db # v4
48 |
49 | # ℹ️ Command-line programs to run using the OS shell.
50 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
51 |
52 | # If the Autobuild fails above, remove it and uncomment the following three lines.
53 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
54 |
55 | # - run: |
56 | # echo "Run, Build Application using script"
57 | # ./location_of_script_within_repo/buildscript.sh
58 |
59 | - name: Perform CodeQL Analysis
60 | uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # v4
61 | with:
62 | category: "/language:${{matrix.language}}"
63 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/test-and-analyze-fork.yml:
--------------------------------------------------------------------------------
1 | name: Code test and analysis (fork)
2 | on:
3 | pull_request:
4 | branches: [ main ]
5 | types: [opened, synchronize, reopened, ready_for_review]
6 | jobs:
7 | test:
8 | if: github.repository_owner == 'Altinn' && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true)
9 | name: Build and Test
10 | runs-on: windows-latest
11 | steps:
12 | - name: Setup .NET
13 | uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5
14 | with:
15 | dotnet-version: |
16 | 8.0.x
17 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
18 | with:
19 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
20 |
21 | - name: dotnet build
22 | run: dotnet build Altinn.FileAnalyzers.sln -v m
23 |
24 | - name: dotnet test
25 | run: dotnet test Altinn.FileAnalyzers.sln --results-directory TestResults/ --collect:"XPlat Code Coverage" -v m
26 |
27 | - name: Generate coverage results
28 | run: |
29 | dotnet tool install --global dotnet-reportgenerator-globaltool
30 | reportgenerator -reports:TestResults/**/coverage.cobertura.xml -targetdir:TestResults/Output/CoverageReport -reporttypes:Cobertura
31 |
32 | - name: Archive code coverage results
33 | uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
34 | with:
35 | name: code-coverage-report
36 | path: TestResults/Output/CoverageReport/
37 |
38 | code-coverage:
39 | if: github.repository_owner == 'Altinn' && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false)
40 | name: Report code coverage
41 | runs-on: ubuntu-latest
42 | needs: test
43 | steps:
44 | - name: Download Coverage Results
45 | uses: actions/download-artifact@master
46 | with:
47 | name: code-coverage-report
48 | path: dist/
49 | - name: Create Coverage Summary Report
50 | uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0
51 | with:
52 | filename: dist/Cobertura.xml
53 | badge: true
54 | fail_below_min: true
55 | format: markdown
56 | hide_branch_rate: false
57 | hide_complexity: true
58 | indicators: true
59 | output: both
60 | thresholds: '60 80'
61 |
62 | - name: Add Coverage PR Comment
63 | uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2
64 | with:
65 | recreate: true
66 | path: code-coverage-results.md
--------------------------------------------------------------------------------
/test/Altinn.FileAnalyzers.Tests/MimeType/MimeTypeValidatorTests.cs:
--------------------------------------------------------------------------------
1 | using Altinn.App.Core.Features.FileAnalysis;
2 | using Altinn.App.Core.Models.Validation;
3 | using Altinn.FileAnalyzers.MimeType;
4 | using Altinn.Platform.Storage.Interface.Models;
5 |
6 | namespace Altinn.FileAnalyzers.Tests.MimeType;
7 |
8 | public class MimeTypeValidatorTests
9 | {
10 | [Fact]
11 | public async Task Validate_MimeTypeCorrect_ShouldValidateOk()
12 | { // Simulate config in applicationMetadata.json
13 | var dataType = new DataType()
14 | {
15 | EnabledFileValidators = new List() { "mimeTypeValidator" },
16 | AllowedContentTypes = new List() { "application/pdf" },
17 | };
18 |
19 | // Simulate file analysis result
20 | IEnumerable fileAnalysisResults = new List()
21 | {
22 | new FileAnalysisResult("mimeTypeValidator")
23 | {
24 | MimeType = "application/pdf",
25 | Filename = "test.pdf",
26 | Extensions = new List() { "pdf" },
27 | },
28 | };
29 |
30 | var validator = new MimeTypeValidator();
31 | (bool success, IEnumerable errors) = await validator.Validate(
32 | dataType,
33 | fileAnalysisResults
34 | );
35 |
36 | Assert.True(success);
37 | Assert.Empty(errors);
38 | }
39 |
40 | [Fact]
41 | public async Task Validate_MimeTypeCorrect_ShouldReturnWithError()
42 | { // Simulate config in applicationMetadata.json
43 | var dataType = new DataType()
44 | {
45 | EnabledFileValidators = new List() { "mimeTypeValidator" },
46 | AllowedContentTypes = new List() { "application/pdf" },
47 | };
48 |
49 | // Simulate file analysis result
50 | IEnumerable fileAnalysisResults = new List()
51 | {
52 | new FileAnalysisResult("mimeTypeValidator")
53 | {
54 | MimeType = "application/pdfx",
55 | Filename = "test.png",
56 | Extensions = new List() { "png" },
57 | },
58 | };
59 |
60 | var validator = new MimeTypeValidator();
61 | (bool success, IEnumerable errors) = await validator.Validate(
62 | dataType,
63 | fileAnalysisResults
64 | );
65 |
66 | Assert.False(success);
67 | Assert.Equal(
68 | ValidationIssueCodes.DataElementCodes.ContentTypeNotAllowed,
69 | errors.FirstOrDefault()?.Code
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/.github/workflows/test-and-analyze.yml:
--------------------------------------------------------------------------------
1 | name: Code test and analysis
2 | on:
3 | push:
4 | branches: [ main ]
5 | pull_request:
6 | branches: [ main ]
7 | types: [opened, synchronize, reopened]
8 | workflow_dispatch:
9 | jobs:
10 | analyze:
11 | if: |
12 | github.repository_owner == 'Altinn' &&
13 | (github.event_name != 'pull_request' && github.event.repository.fork == false) ||
14 | (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false)
15 | name: Static code analysis
16 | runs-on: windows-latest
17 | steps:
18 | - name: Setup .NET
19 | uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5
20 | with:
21 | dotnet-version: |
22 | 8.0.x
23 | - name: Set up JDK 11
24 | uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
25 | with:
26 | distribution: 'zulu'
27 | java-version: 17
28 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
29 | with:
30 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
31 | - name: Cache SonarCloud packages
32 | uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
33 | with:
34 | path: ~\sonar\cache
35 | key: ${{ runner.os }}-sonar
36 | restore-keys: ${{ runner.os }}-sonar
37 | - name: Cache SonarCloud scanner
38 | id: cache-sonar-scanner
39 | uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
40 | with:
41 | path: .\.sonar\scanner
42 | key: ${{ runner.os }}-sonar-scanner
43 | restore-keys: ${{ runner.os }}-sonar-scanner
44 | - name: Install SonarCloud scanner
45 | if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
46 | shell: powershell
47 | run: |
48 | New-Item -Path .\.sonar\scanner -ItemType Directory
49 | dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
50 | - name: Build & Test
51 | run: |
52 | dotnet test Altinn.FileAnalyzers.sln -v m
53 | - name: Analyze
54 | env:
55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
56 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
57 | shell: powershell
58 | run: |
59 | .\.sonar\scanner\dotnet-sonarscanner begin /k:"Altinn_fileanalyzers-lib-dotnet" /o:"altinn" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vstest.reportsPaths="**/*.trx" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml"
60 |
61 | dotnet build Altinn.FileAnalyzers.sln
62 | dotnet test Altinn.FileAnalyzers.sln `
63 | --no-build `
64 | --results-directory TestResults/ `
65 | --collect:"XPlat Code Coverage" `
66 | -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
67 |
68 | .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Altinn File Analyzers
2 | 
3 | 
4 | 
5 |
6 | This library contains code for doing deep file analysis based the actual binary data of files uploaded to an instance in Altinn 3. The implementation is two folded, one part that analyses and another part that validates against the analysis results. The reasoning for this split is to be able to use only the analyzer and extract metadata without validating. In addition it will be simpler to configure validators against a standardized result set rather than embed that into the analysis code.
7 |
8 | The [Getting started](#getting-started) section describes the basic steps required in order to use this package within an Altinn 3 application. For a more comprehensive description of file analysers in Altinn 3 please see https://docs.altinn.studio/app/development/logic/validation/files/.
9 |
10 |
11 |
12 | ## Getting started using the package
13 |
14 | This guide assumes you have an existing Altinn 3 application. If not please see https://docs.altinn.studio/app/getting-started/create-app/ to get started.
15 |
16 | 1. Add reference to [Altinn.FileAnalyzers nuget package](https://www.nuget.org/packages/Altinn.FileAnalyzers)
17 | Open command line to the repo of your application and navigate to the App folder where the App.csproj file is located and run the following command:
18 |
19 | ```shell
20 | nuget install Altinn.FileAnalyzers
21 | ```
22 | 2. Register the analyzers you would like to use
23 | Each analyzer/validator has it's own method for registering required services. Se table below for available analyser.
24 | ```csharp
25 | services.AddMimeTypeValidation();
26 | ```
27 |
28 | 3. Configure the the analyzer for the datatype it should be used for
29 | The analyzer is configured on a per datatype basis and will only run against the configured datatype. The example below configures the mime type analyzer and it's corresponding validator.
30 |
31 | ```json
32 | {
33 | "id": "08112113-cc3a-4d35-a8d2-bfba53a1ddfd",
34 | "allowedContentTypes": ["image/jpeg", "application/pdf"],
35 | "taskId": "Task_1",
36 | "maxSize": 25,
37 | "maxCount": 1,
38 | "minCount": 1,
39 | "enablePdfCreation": false,
40 | "enabledFileAnalysers": [ "mimeTypeAnalyser" ],
41 | "enabledFileValidators": [ "mimeTypeValidator" ]
42 | }
43 | ```
44 |
45 | ## Available analyzers and their corresponding validators
46 | | Analyser Id | Validator Id | Description |
47 | | --------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
48 | | mimeTypeAnalyser | mimeTypeValidator | Checks if a file is actually the MIME type it claims to be. This uses the [Mime Detective](https://github.com/MediatedCommunications/Mime-Detective) library to determine the mime type. |
49 |
50 |
51 | ## Automated tests
52 |
53 | ## Contributing
54 |
55 | ## Licence
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
352 | *.received.txt
353 | *.received.json
354 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # NOTE: Requires **VS2019 16.3** or later
2 |
3 | # New Rule Set
4 | # Description:
5 |
6 | # Code files
7 | [*.{cs,vb}]
8 |
9 |
10 | dotnet_diagnostic.SA0001.severity = error
11 |
12 | dotnet_diagnostic.SA0002.severity = none
13 |
14 | dotnet_diagnostic.SA1000.severity = warning
15 |
16 | dotnet_diagnostic.SA1001.severity = warning
17 |
18 | dotnet_diagnostic.SA1002.severity = warning
19 |
20 | dotnet_diagnostic.SA1003.severity = warning
21 |
22 | dotnet_diagnostic.SA1004.severity = warning
23 |
24 | dotnet_diagnostic.SA1005.severity = warning
25 |
26 | dotnet_diagnostic.SA1006.severity = warning
27 |
28 | dotnet_diagnostic.SA1007.severity = warning
29 |
30 | dotnet_diagnostic.SA1008.severity = warning
31 |
32 | dotnet_diagnostic.SA1009.severity = warning
33 |
34 | dotnet_diagnostic.SA1010.severity = warning
35 |
36 | dotnet_diagnostic.SA1011.severity = warning
37 |
38 | dotnet_diagnostic.SA1012.severity = warning
39 |
40 | dotnet_diagnostic.SA1013.severity = warning
41 |
42 | dotnet_diagnostic.SA1014.severity = warning
43 |
44 | dotnet_diagnostic.SA1015.severity = warning
45 |
46 | dotnet_diagnostic.SA1016.severity = warning
47 |
48 | dotnet_diagnostic.SA1017.severity = warning
49 |
50 | dotnet_diagnostic.SA1018.severity = warning
51 |
52 | dotnet_diagnostic.SA1019.severity = warning
53 |
54 | dotnet_diagnostic.SA1020.severity = warning
55 |
56 | dotnet_diagnostic.SA1021.severity = warning
57 |
58 | dotnet_diagnostic.SA1022.severity = warning
59 |
60 | dotnet_diagnostic.SA1023.severity = warning
61 |
62 | dotnet_diagnostic.SA1024.severity = none
63 |
64 | dotnet_diagnostic.SA1025.severity = warning
65 |
66 | dotnet_diagnostic.SA1026.severity = warning
67 |
68 | dotnet_diagnostic.SA1027.severity = warning
69 |
70 | dotnet_diagnostic.SA1028.severity = none
71 |
72 | dotnet_diagnostic.SA1100.severity = error
73 |
74 | dotnet_diagnostic.SA1101.severity = none
75 |
76 | dotnet_diagnostic.SA1102.severity = error
77 |
78 | dotnet_diagnostic.SA1103.severity = error
79 |
80 | dotnet_diagnostic.SA1104.severity = error
81 |
82 | dotnet_diagnostic.SA1105.severity = error
83 |
84 | dotnet_diagnostic.SA1106.severity = error
85 |
86 | dotnet_diagnostic.SA1107.severity = error
87 |
88 | dotnet_diagnostic.SA1108.severity = error
89 |
90 | dotnet_diagnostic.SA1110.severity = error
91 |
92 | dotnet_diagnostic.SA1111.severity = error
93 |
94 | dotnet_diagnostic.SA1112.severity = error
95 |
96 | dotnet_diagnostic.SA1113.severity = error
97 |
98 | dotnet_diagnostic.SA1114.severity = error
99 |
100 | dotnet_diagnostic.SA1115.severity = error
101 |
102 | dotnet_diagnostic.SA1116.severity = error
103 |
104 | dotnet_diagnostic.SA1117.severity = error
105 |
106 | dotnet_diagnostic.SA1118.severity = error
107 |
108 | dotnet_diagnostic.SA1119.severity = error
109 |
110 | dotnet_diagnostic.SA1120.severity = error
111 |
112 | dotnet_diagnostic.SA1121.severity = error
113 |
114 | dotnet_diagnostic.SA1122.severity = error
115 |
116 | dotnet_diagnostic.SA1123.severity = none
117 |
118 | dotnet_diagnostic.SA1124.severity = none
119 |
120 | dotnet_diagnostic.SA1125.severity = error
121 |
122 | dotnet_diagnostic.SA1127.severity = error
123 |
124 | dotnet_diagnostic.SA1128.severity = none
125 |
126 | dotnet_diagnostic.SA1129.severity = error
127 |
128 | dotnet_diagnostic.SA1130.severity = error
129 |
130 | dotnet_diagnostic.SA1131.severity = error
131 |
132 | dotnet_diagnostic.SA1132.severity = error
133 |
134 | dotnet_diagnostic.SA1133.severity = error
135 |
136 | dotnet_diagnostic.SA1134.severity = error
137 |
138 | dotnet_diagnostic.SA1135.severity = error
139 |
140 | dotnet_diagnostic.SA1136.severity = error
141 |
142 | dotnet_diagnostic.SA1137.severity = warning
143 |
144 | dotnet_diagnostic.SA1139.severity = none
145 |
146 | dotnet_diagnostic.SA1200.severity = none
147 |
148 | dotnet_diagnostic.SA1201.severity = none
149 |
150 | dotnet_diagnostic.SA1202.severity = none
151 |
152 | dotnet_diagnostic.SA1203.severity = none
153 |
154 | dotnet_diagnostic.SA1204.severity = none
155 |
156 | dotnet_diagnostic.SA1205.severity = none
157 |
158 | dotnet_diagnostic.SA1206.severity = none
159 |
160 | dotnet_diagnostic.SA1207.severity = none
161 |
162 | dotnet_diagnostic.SA1208.severity = error
163 |
164 | dotnet_diagnostic.SA1209.severity = error
165 |
166 | dotnet_diagnostic.SA1210.severity = error
167 |
168 | dotnet_diagnostic.SA1211.severity = error
169 |
170 | dotnet_diagnostic.SA1212.severity = none
171 |
172 | dotnet_diagnostic.SA1213.severity = none
173 |
174 | dotnet_diagnostic.SA1214.severity = none
175 |
176 | dotnet_diagnostic.SA1216.severity = error
177 |
178 | dotnet_diagnostic.SA1217.severity = error
179 |
180 | dotnet_diagnostic.SA1300.severity = error
181 |
182 | dotnet_diagnostic.SA1302.severity = error
183 |
184 | dotnet_diagnostic.SA1303.severity = error
185 |
186 | dotnet_diagnostic.SA1304.severity = error
187 |
188 | dotnet_diagnostic.SA1305.severity = error
189 |
190 | dotnet_diagnostic.SA1306.severity = error
191 |
192 | dotnet_diagnostic.SA1307.severity = error
193 |
194 | dotnet_diagnostic.SA1308.severity = error
195 |
196 | dotnet_diagnostic.SA1309.severity = none
197 |
198 | dotnet_diagnostic.SA1310.severity = none
199 |
200 | dotnet_diagnostic.SA1311.severity = error
201 |
202 | dotnet_diagnostic.SA1312.severity = error
203 |
204 | dotnet_diagnostic.SA1313.severity = none
205 |
206 | dotnet_diagnostic.SA1314.severity = error
207 |
208 | dotnet_diagnostic.SA1400.severity = warning
209 |
210 | dotnet_diagnostic.SA1401.severity = error
211 |
212 | dotnet_diagnostic.SA1402.severity = none
213 |
214 | dotnet_diagnostic.SA1403.severity = error
215 |
216 | dotnet_diagnostic.SA1404.severity = error
217 |
218 | dotnet_diagnostic.SA1405.severity = none
219 |
220 | dotnet_diagnostic.SA1406.severity = none
221 |
222 | dotnet_diagnostic.SA1407.severity = error
223 |
224 | dotnet_diagnostic.SA1408.severity = error
225 |
226 | dotnet_diagnostic.SA1410.severity = none
227 |
228 | dotnet_diagnostic.SA1411.severity = none
229 |
230 | dotnet_diagnostic.SA1413.severity = none
231 |
232 | dotnet_diagnostic.SA1500.severity = error
233 |
234 | dotnet_diagnostic.SA1501.severity = error
235 |
236 | dotnet_diagnostic.SA1502.severity = error
237 |
238 | dotnet_diagnostic.SA1503.severity = error
239 |
240 | dotnet_diagnostic.SA1504.severity = error
241 |
242 | dotnet_diagnostic.SA1505.severity = error
243 |
244 | dotnet_diagnostic.SA1506.severity = error
245 |
246 | dotnet_diagnostic.SA1507.severity = error
247 |
248 | dotnet_diagnostic.SA1508.severity = warning
249 |
250 | dotnet_diagnostic.SA1509.severity = warning
251 |
252 | dotnet_diagnostic.SA1510.severity = error
253 |
254 | dotnet_diagnostic.SA1511.severity = error
255 |
256 | dotnet_diagnostic.SA1512.severity = warning
257 |
258 | dotnet_diagnostic.SA1513.severity = error
259 |
260 | dotnet_diagnostic.SA1514.severity = error
261 |
262 | dotnet_diagnostic.SA1515.severity = error
263 |
264 | dotnet_diagnostic.SA1516.severity = error
265 |
266 | dotnet_diagnostic.SA1517.severity = error
267 |
268 | dotnet_diagnostic.SA1518.severity = error
269 |
270 | dotnet_diagnostic.SA1519.severity = error
271 |
272 | dotnet_diagnostic.SA1520.severity = error
273 |
274 | dotnet_diagnostic.SA1600.severity = error
275 |
276 | dotnet_diagnostic.SA1601.severity = error
277 |
278 | dotnet_diagnostic.SA1602.severity = none
279 |
280 | dotnet_diagnostic.SA1604.severity = error
281 |
282 | dotnet_diagnostic.SA1605.severity = error
283 |
284 | dotnet_diagnostic.SA1606.severity = error
285 |
286 | dotnet_diagnostic.SA1607.severity = error
287 |
288 | dotnet_diagnostic.SA1608.severity = error
289 |
290 | dotnet_diagnostic.SA1610.severity = error
291 |
292 | dotnet_diagnostic.SA1611.severity = none
293 |
294 | dotnet_diagnostic.SA1612.severity = error
295 |
296 | dotnet_diagnostic.SA1613.severity = error
297 |
298 | dotnet_diagnostic.SA1614.severity = error
299 |
300 | dotnet_diagnostic.SA1615.severity = none
301 |
302 | dotnet_diagnostic.SA1616.severity = none
303 |
304 | dotnet_diagnostic.SA1617.severity = error
305 |
306 | dotnet_diagnostic.SA1618.severity = none
307 |
308 | dotnet_diagnostic.SA1619.severity = none
309 |
310 | dotnet_diagnostic.SA1620.severity = none
311 |
312 | dotnet_diagnostic.SA1621.severity = error
313 |
314 | dotnet_diagnostic.SA1622.severity = none
315 |
316 | dotnet_diagnostic.SA1623.severity = none
317 |
318 | dotnet_diagnostic.SA1624.severity = error
319 |
320 | dotnet_diagnostic.SA1625.severity = error
321 |
322 | dotnet_diagnostic.SA1626.severity = warning
323 |
324 | dotnet_diagnostic.SA1627.severity = error
325 |
326 | dotnet_diagnostic.SA1629.severity = none
327 |
328 | dotnet_diagnostic.SA1633.severity = none
329 |
330 | dotnet_diagnostic.SA1634.severity = none
331 |
332 | dotnet_diagnostic.SA1635.severity = none
333 |
334 | dotnet_diagnostic.SA1636.severity = none
335 |
336 | dotnet_diagnostic.SA1637.severity = none
337 |
338 | dotnet_diagnostic.SA1638.severity = none
339 |
340 | dotnet_diagnostic.SA1640.severity = none
341 |
342 | dotnet_diagnostic.SA1641.severity = none
343 |
344 | dotnet_diagnostic.SA1642.severity = none
345 |
346 | dotnet_diagnostic.SA1643.severity = none
347 |
348 | dotnet_diagnostic.SA1648.severity = error
349 |
350 | dotnet_diagnostic.SA1649.severity = error
351 |
352 | dotnet_diagnostic.SA1651.severity = error
353 |
354 | # CA1707: Identifiers should not contain underscores
355 | dotnet_diagnostic.CA1707.severity = none
356 |
357 | [*.{cs,vb}]
358 | #### Naming styles ####
359 |
360 | # Naming rules
361 |
362 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
363 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
364 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
365 |
366 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
367 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
368 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
369 |
370 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
371 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
372 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
373 |
374 | # Symbol specifications
375 |
376 | dotnet_naming_symbols.interface.applicable_kinds = interface
377 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
378 | dotnet_naming_symbols.interface.required_modifiers =
379 |
380 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
381 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
382 | dotnet_naming_symbols.types.required_modifiers =
383 |
384 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
385 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
386 | dotnet_naming_symbols.non_field_members.required_modifiers =
387 |
388 | # Naming styles
389 |
390 | dotnet_naming_style.begins_with_i.required_prefix = I
391 | dotnet_naming_style.begins_with_i.required_suffix =
392 | dotnet_naming_style.begins_with_i.word_separator =
393 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
394 |
395 | dotnet_naming_style.pascal_case.required_prefix =
396 | dotnet_naming_style.pascal_case.required_suffix =
397 | dotnet_naming_style.pascal_case.word_separator =
398 | dotnet_naming_style.pascal_case.capitalization = pascal_case
399 |
400 | dotnet_naming_style.pascal_case.required_prefix =
401 | dotnet_naming_style.pascal_case.required_suffix =
402 | dotnet_naming_style.pascal_case.word_separator =
403 | dotnet_naming_style.pascal_case.capitalization = pascal_case
404 | dotnet_style_coalesce_expression = true:suggestion
405 | dotnet_style_null_propagation = true:suggestion
406 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
407 | dotnet_style_prefer_auto_properties = true:silent
408 | dotnet_style_object_initializer = true:suggestion
409 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
410 | tab_width = 4
411 | indent_size = 4
412 | end_of_line = crlf
413 | dotnet_style_namespace_match_folder = true:suggestion
414 |
415 | [*.cs]
416 | csharp_using_directive_placement = outside_namespace:silent
417 | csharp_prefer_simple_using_statement = true:suggestion
418 | csharp_prefer_braces = true:silent
419 | csharp_style_namespace_declarations = block_scoped:silent
420 | csharp_style_prefer_method_group_conversion = true:silent
421 | csharp_style_prefer_top_level_statements = true:silent
422 | csharp_style_expression_bodied_methods = false:silent
423 | csharp_style_expression_bodied_constructors = false:silent
424 | csharp_style_expression_bodied_operators = false:silent
425 | csharp_style_expression_bodied_properties = true:silent
426 | csharp_style_expression_bodied_indexers = true:silent
427 | csharp_style_expression_bodied_accessors = true:silent
428 | csharp_style_expression_bodied_lambdas = true:silent
429 | csharp_style_expression_bodied_local_functions = false:silent
430 | csharp_indent_labels = one_less_than_current
431 |
432 | # Verify settings
433 | # https://github.com/VerifyTests/Verify?tab=readme-ov-file#editorconfig-settings
434 |
435 | [*.{received,verified}.{json,txt,xml}]
436 | charset = "utf-8-bom"
437 | end_of_line = lf
438 | indent_size = unset
439 | indent_style = unset
440 | insert_final_newline = false
441 | tab_width = unset
442 | trim_trailing_whitespace = false
443 |
--------------------------------------------------------------------------------