├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── dotnet.yml
│ └── publish.yml
├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── CHANGELOG.md
├── LICENSE
├── OOXMLValidator.sln
├── OOXMLValidatorCLI
├── Classes
│ ├── DirectoryService.cs
│ ├── DocumentUtils.cs
│ ├── FileService.cs
│ ├── FunctionUtils.cs
│ ├── Validate.cs
│ └── ValidationErrorInfoInternal.cs
├── Interfaces
│ ├── IDirectoryService.cs
│ ├── IDocumentUtils.cs
│ ├── IFileService.cs
│ ├── IFunctionUtils.cs
│ └── IValidate.cs
├── OOXMLValidatorCLI.csproj
├── Program.cs
└── stylecop.json
├── OOXMLValidatorCLITests
├── FunctionUtilsTests.cs
├── OOXMLValidatorCLITests.csproj
├── ValidateTests.cs
└── stylecop.json
├── README.md
└── dev.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{cs,vb}]
2 |
3 | # IDE0003: Remove qualification
4 | dotnet_diagnostic.IDE0003.severity = none
5 |
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: OOXMLValidator Tests
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | paths-ignore:
7 | - '**.md'
8 | pull_request:
9 | branches: [main]
10 | paths-ignore:
11 | - '**.md'
12 | env:
13 | AZURE_FUNCTIONAPP_NAME: OOXMLValidator # set this to your application's name
14 | AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root
15 |
16 | jobs:
17 | test:
18 | strategy:
19 | matrix:
20 | os:
21 | - macos-latest
22 | - ubuntu-latest
23 | - windows-latest
24 | dotnet-version:
25 | - 8.x
26 | runs-on: ${{ matrix.os }}
27 |
28 | steps:
29 | - uses: actions/checkout@v4
30 | - name: Setup DotNet ${{ matrix.dotnet-version }} Environment
31 | uses: actions/setup-dotnet@v4
32 | id: setup-dotnet
33 | with:
34 | dotnet-version: ${{ matrix.dotnet-version }}
35 | - name: Install dependencies
36 | run: dotnet restore
37 | - name: Build
38 | run: dotnet build --configuration Release --no-restore
39 | - name: Test
40 | run: dotnet test ./OOXMLValidatorCLITests/OOXMLValidatorCLITests.csproj --no-restore --verbosity normal
41 |
42 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: OOXMLValidator Publish
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v[0-9]+.[0-9]+.[0-9]+'
7 | paths-ignore:
8 | - '**.md'
9 | pull_request:
10 | branches: [main]
11 | paths-ignore:
12 | - '**.md'
13 | env:
14 | AZURE_FUNCTIONAPP_NAME: OOXMLValidator # set this to your application's name
15 | AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root
16 |
17 | jobs:
18 | publish:
19 | runs-on: ubuntu-latest
20 |
21 | strategy:
22 | matrix:
23 | build_env: ["linux-x64", "linux-arm64", "osx-x64", "osx-arm64", "win-x64"]
24 |
25 | steps:
26 | - uses: actions/checkout@v4
27 | - name: Setup DotNet 8.x Environment
28 | uses: actions/setup-dotnet@v4
29 | with:
30 | dotnet-version: 8.x
31 | - name: Install dependencies
32 | run: dotnet restore
33 |
34 | - name: Build/${{ matrix.build_env }}
35 | run: ./dev.sh build ${{ matrix.build_env }}
36 |
37 | - name: Artifacts/${{ matrix.build_env }}
38 | uses: actions/upload-artifact@v4
39 | with:
40 | name: build-${{ matrix.build_env }}
41 | path: |
42 | ./OOXMLValidatorCLI/bin/Release/net8.0/${{ matrix.build_env }}/publish/OOXMLValidatorCLI
43 | ./OOXMLValidatorCLI/bin/Release/net8.0/${{ matrix.build_env }}/publish/OOXMLValidatorCLI.exe
44 |
45 | publish-test-osx-x64:
46 | needs: publish
47 | runs-on: macos-latest
48 | steps:
49 | - uses: actions/checkout@v4
50 | - uses: actions/download-artifact@v4
51 | with:
52 | name: build-osx-x64
53 | path: ./test-ci
54 | - run: CI_SHELL_OVERRIDE=test-ci ./dev.sh test osx-x64
55 |
56 | publish-test-linux:
57 | needs: publish
58 | runs-on: ubuntu-latest
59 | steps:
60 | - uses: actions/checkout@v4
61 | - uses: actions/download-artifact@v4
62 | with:
63 | name: build-linux-x64
64 | path: ./test-ci
65 | - run: CI_SHELL_OVERRIDE=test-ci ./dev.sh test linux-x64
66 |
67 | publish-test-windows:
68 | needs: publish
69 | runs-on: windows-latest
70 | steps:
71 | - uses: actions/checkout@v4
72 | - uses: actions/download-artifact@v4
73 | with:
74 | name: build-win-x64
75 | path: ./test-ci
76 | - shell: bash
77 | run: CI_SHELL_OVERRIDE=test-ci ./dev.sh test win-x64
78 |
79 | release:
80 | name: release
81 | needs: [publish, publish-test-osx-x64, publish-test-linux, publish-test-windows]
82 | runs-on: ubuntu-latest
83 | steps:
84 | - uses: actions/download-artifact@v4
85 | with:
86 | name: build-linux-x64
87 | path: build-linux-x64
88 | - uses: actions/download-artifact@v4
89 | with:
90 | name: build-linux-arm64
91 | path: build-linux-arm64
92 | - uses: actions/download-artifact@v4
93 | with:
94 | name: build-osx-x64
95 | path: build-osx-x64
96 | - uses: actions/download-artifact@v4
97 | with:
98 | name: build-osx-arm64
99 | path: build-osx-arm64
100 | - uses: actions/download-artifact@v4
101 | with:
102 | name: build-win-x64
103 | path: build-win-x64
104 | - run: |
105 | cd build-linux-x64 && zip -r ../linux-x64.zip * && cd -
106 | cd build-linux-arm64 && zip -r ../linux-arm64.zip * && cd -
107 | cd build-osx-x64 && zip -r ../osx-x64.zip * && cd -
108 | cd build-osx-arm64 && zip -r ../osx-arm64.zip * && cd -
109 | cd build-win-x64 && zip -r ../win-x64.zip * && cd -
110 | - name: release
111 | uses: softprops/action-gh-release@v2
112 | if: startsWith(github.ref, 'refs/tags/')
113 | with:
114 | files: |
115 | linux-x64.zip
116 | linux-arm64.zip
117 | osx-x64.zip
118 | osx-arm64.zip
119 | win-x64.zip
--------------------------------------------------------------------------------
/.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 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 |
33 | .vscode/
34 | # Uncomment if you have tasks that create the project's static files in wwwroot
35 | #wwwroot/
36 |
37 | # Visual Studio 2017 auto generated files
38 | Generated\ Files/
39 |
40 | # MSTest test Results
41 | [Tt]est[Rr]esult*/
42 | [Bb]uild[Ll]og.*
43 |
44 | # NUNIT
45 | *.VisualState.xml
46 | TestResult.xml
47 |
48 | # Build Results of an ATL Project
49 | [Dd]ebugPS/
50 | [Rr]eleasePS/
51 | dlldata.c
52 |
53 | # Benchmark Results
54 | BenchmarkDotNet.Artifacts/
55 |
56 | # .NET Core
57 | project.lock.json
58 | project.fragment.lock.json
59 | artifacts/
60 |
61 | # StyleCop
62 | StyleCopReport.xml
63 |
64 | # Files built by Visual Studio
65 | *_i.c
66 | *_p.c
67 | *_h.h
68 | *.ilk
69 | *.meta
70 | *.obj
71 | *.iobj
72 | *.pch
73 | *.pdb
74 | *.ipdb
75 | *.pgc
76 | *.pgd
77 | *.rsp
78 | *.sbr
79 | *.tlb
80 | *.tli
81 | *.tlh
82 | *.tmp
83 | *.tmp_proj
84 | *_wpftmp.csproj
85 | *.log
86 | *.vspscc
87 | *.vssscc
88 | .builds
89 | *.pidb
90 | *.svclog
91 | *.scc
92 |
93 | # Chutzpah Test files
94 | _Chutzpah*
95 |
96 | # Visual C++ cache files
97 | ipch/
98 | *.aps
99 | *.ncb
100 | *.opendb
101 | *.opensdf
102 | *.sdf
103 | *.cachefile
104 | *.VC.db
105 | *.VC.VC.opendb
106 |
107 | # Visual Studio profiler
108 | *.psess
109 | *.vsp
110 | *.vspx
111 | *.sap
112 |
113 | # Visual Studio Trace Files
114 | *.e2e
115 |
116 | # TFS 2012 Local Workspace
117 | $tf/
118 |
119 | # Guidance Automation Toolkit
120 | *.gpState
121 |
122 | # ReSharper is a .NET coding add-in
123 | _ReSharper*/
124 | *.[Rr]e[Ss]harper
125 | *.DotSettings.user
126 |
127 | # JustCode is a .NET coding add-in
128 | .JustCode
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 | # The packages folder can be ignored because of Package Restore
188 | **/[Pp]ackages/*
189 | # except build/, which is used as an MSBuild target.
190 | !**/[Pp]ackages/build/
191 | # Uncomment if necessary however generally it will be regenerated when needed
192 | #!**/[Pp]ackages/repositories.config
193 | # NuGet v3's project.json files produces more ignorable files
194 | *.nuget.props
195 | *.nuget.targets
196 |
197 | # Microsoft Azure Build Output
198 | csx/
199 | *.build.csdef
200 |
201 | # Microsoft Azure Emulator
202 | ecf/
203 | rcf/
204 |
205 | # Windows Store app package directories and files
206 | AppPackages/
207 | BundleArtifacts/
208 | Package.StoreAssociation.xml
209 | _pkginfo.txt
210 | *.appx
211 |
212 | # Visual Studio cache files
213 | # files ending in .cache can be ignored
214 | *.[Cc]ache
215 | # but keep track of directories ending in .cache
216 | !?*.[Cc]ache/
217 |
218 | # Others
219 | ClientBin/
220 | ~$*
221 | *~
222 | *.dbmdl
223 | *.dbproj.schemaview
224 | *.jfm
225 | *.pfx
226 | *.publishsettings
227 | orleans.codegen.cs
228 |
229 | # Including strong name files can present a security risk
230 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
231 | #*.snk
232 |
233 | # Since there are multiple workflows, uncomment next line to ignore bower_components
234 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
235 | #bower_components/
236 |
237 | # RIA/Silverlight projects
238 | Generated_Code/
239 |
240 | # Backup & report files from converting an old project file
241 | # to a newer Visual Studio version. Backup files are not needed,
242 | # because we have git ;-)
243 | _UpgradeReport_Files/
244 | Backup*/
245 | UpgradeLog*.XML
246 | UpgradeLog*.htm
247 | ServiceFabricBackup/
248 | *.rptproj.bak
249 |
250 | # SQL Server files
251 | *.mdf
252 | *.ldf
253 | *.ndf
254 |
255 | # Business Intelligence projects
256 | *.rdl.data
257 | *.bim.layout
258 | *.bim_*.settings
259 | *.rptproj.rsuser
260 | *- Backup*.rdl
261 |
262 | # Microsoft Fakes
263 | FakesAssemblies/
264 |
265 | # GhostDoc plugin setting file
266 | *.GhostDoc.xml
267 |
268 | # Node.js Tools for Visual Studio
269 | .ntvs_analysis.dat
270 | node_modules/
271 |
272 | # Visual Studio 6 build log
273 | *.plg
274 |
275 | # Visual Studio 6 workspace options file
276 | *.opt
277 |
278 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
279 | *.vbw
280 |
281 | # Visual Studio LightSwitch build output
282 | **/*.HTMLClient/GeneratedArtifacts
283 | **/*.DesktopClient/GeneratedArtifacts
284 | **/*.DesktopClient/ModelManifest.xml
285 | **/*.Server/GeneratedArtifacts
286 | **/*.Server/ModelManifest.xml
287 | _Pvt_Extensions
288 |
289 | # Paket dependency manager
290 | .paket/paket.exe
291 | paket-files/
292 |
293 | # FAKE - F# Make
294 | .fake/
295 |
296 | # JetBrains Rider
297 | .idea/
298 | *.sln.iml
299 |
300 | # CodeRush personal settings
301 | .cr/personal
302 |
303 | # Python Tools for Visual Studio (PTVS)
304 | __pycache__/
305 | *.pyc
306 |
307 | # Cake - Uncomment if you are using it
308 | # tools/**
309 | # !tools/packages.config
310 |
311 | # Tabs Studio
312 | *.tss
313 |
314 | # Telerik's JustMock configuration file
315 | *.jmconfig
316 |
317 | # BizTalk build output
318 | *.btp.cs
319 | *.btm.cs
320 | *.odx.cs
321 | *.xsd.cs
322 |
323 | # OpenCover UI analysis results
324 | OpenCover/
325 |
326 | # Azure Stream Analytics local run output
327 | ASALocalRun/
328 |
329 | # MSBuild Binary and Structured Log
330 | *.binlog
331 |
332 | # NVidia Nsight GPU debugger configuration file
333 | *.nvuser
334 |
335 | # MFractors (Xamarin productivity tool) working folder
336 | .mfractor/
337 |
338 | # Local History for Visual Studio
339 | .localhistory/
340 |
341 | # BeatPulse healthcheck temp database
342 | healthchecksdb
343 |
344 | Properties/
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": ".NET Core Launch (console)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | "program": "${workspaceFolder}/OOXMLValidatorCLI/bin/Debug/netcoreapp3.1/OOXMLValidatorCLI.dll",
13 | "args": [
14 | "C:\\source\\deleteThis\\add-extensions-to-validator\\Presentation1.pptm"
15 | ],
16 | "cwd": "${workspaceFolder}/OOXMLValidatorCLI",
17 | "console": "integratedTerminal",
18 | "stopAtEntry": false
19 | }
20 | ]
21 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/.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}/OOXMLValidatorCLI/OOXMLValidatorCLI.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}/OOXMLValidatorCLI/OOXMLValidatorCLI.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}/OOXMLValidatorCLI/OOXMLValidatorCLI.csproj"
37 | ],
38 | "problemMatcher": "$msCompile"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 | ## [2.1.5] - 2024-06-28
9 |
10 | ### Added
11 | - Updated NuGet packages
12 | - Updated Action to use setup-dotnet@4
13 |
14 | ## [2.1.4] - 2024-06-28
15 |
16 | ### Added
17 | - Add publish GitHub Action
18 | - Add test scripts for testing and publishing output
19 | - Automatically create release & assets
20 |
21 | ### Fixed
22 | - Fixes build for Linux (#21)
23 |
24 | ## [2.1.3] - 2024-01-25
25 |
26 | ### Fixed
27 | - Sets `RollForward` to `Major`, so extension will run on macos with later versions of dotnet
28 |
29 | ### Changed
30 | - Removed net7.0 build
31 |
32 | ## [2.1.2] - 2024-01-23
33 |
34 | ### Updated
35 | - Add build for dotnet 8
36 |
37 | ## [2.1.1] - 2024-01-22
38 |
39 | ### Updated
40 |
41 | - Updated to OOXML SDK 3.0
42 | - Updated to dotnet 8
43 |
44 | ## [2.1.1] - 2022-10-27
45 |
46 | ### Fixed
47 |
48 | - Update Path property on ValidationErrorInfoInternal to have type XmlPath
49 |
50 | ## [2.1.0] - 2022-09-29
51 |
52 | ### Added
53 |
54 | - Updated Open XML SDK Version
55 |
56 | ## [2.0.0] - 2022-07-27
57 |
58 | ### Added
59 |
60 | - Returned XML data returns list of `` elements with a child `` element, instead of list of `` elements.
61 |
62 | ### Fixed
63 |
64 | - If a file cannot be opened by the Validator, a `` element is added with the error message.
65 |
66 | ## [1.2.0] - 2022-04-28
67 |
68 | ### Added
69 |
70 | - Validation can be done on all OOXML files in a single directory or recursively through all child directories
71 |
72 | ## [1.1.0] - 2022-04-11
73 |
74 | ### Added
75 |
76 | - Validation errors can be returned as XML or JSON
77 |
78 | ## [1.0.0] - 2021-09-02
79 |
80 | ### Added
81 |
82 | - Validates OOXML files and returns JSON string of validation errors.
83 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Michael Bowen
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 |
--------------------------------------------------------------------------------
/OOXMLValidator.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.9.34414.90
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OOXMLValidatorCLI", "OOXMLValidatorCLI\OOXMLValidatorCLI.csproj", "{992EF2AC-EDE5-4418-9584-E077999FD15E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OOXMLValidatorCLITests", "OOXMLValidatorCLITests\OOXMLValidatorCLITests.csproj", "{F5C0C69F-A8A2-4612-A2EE-3A15565C8FA8}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8B33E39-2324-4289-9F3B-697CBBAC64B3}"
11 | ProjectSection(SolutionItems) = preProject
12 | .editorconfig = .editorconfig
13 | .gitignore = .gitignore
14 | CHANGELOG.md = CHANGELOG.md
15 | .github\workflows\dotnet.yml = .github\workflows\dotnet.yml
16 | LICENSE = LICENSE
17 | README.md = README.md
18 | EndProjectSection
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {992EF2AC-EDE5-4418-9584-E077999FD15E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {992EF2AC-EDE5-4418-9584-E077999FD15E}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {992EF2AC-EDE5-4418-9584-E077999FD15E}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {992EF2AC-EDE5-4418-9584-E077999FD15E}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {F5C0C69F-A8A2-4612-A2EE-3A15565C8FA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {F5C0C69F-A8A2-4612-A2EE-3A15565C8FA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {F5C0C69F-A8A2-4612-A2EE-3A15565C8FA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {F5C0C69F-A8A2-4612-A2EE-3A15565C8FA8}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {A3BBF30A-BA8B-4409-B2B5-036990C1A424}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/OOXMLValidatorCLI/Classes/DirectoryService.cs:
--------------------------------------------------------------------------------
1 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | namespace OOXMLValidatorCLI.Classes
4 | {
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using OOXMLValidatorCLI.Interfaces;
8 |
9 | ///
10 | /// Provides methods for working with directories and files.
11 | ///
12 | internal class DirectoryService : IDirectoryService
13 | {
14 | ///
15 | /// Enumerates files in a directory that match the specified search pattern and search option.
16 | ///
17 | /// The path to the directory.
18 | /// The search pattern to match against the file names.
19 | /// Specifies whether to search the current directory only or all subdirectories as well.
20 | /// An enumerable collection of file names that match the search pattern and search option.
21 | public IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption)
22 | {
23 | return Directory.EnumerateFiles(path, searchPattern, searchOption);
24 | }
25 |
26 | ///
27 | /// Returns the names of files in the specified directory.
28 | ///
29 | /// The path to the directory.
30 | /// An array of file names in the specified directory.
31 | public string[] GetFiles(string path)
32 | {
33 | return Directory.GetFiles(path);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/OOXMLValidatorCLI/Classes/DocumentUtils.cs:
--------------------------------------------------------------------------------
1 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | namespace OOXMLValidatorCLI.Classes
4 | {
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using DocumentFormat.OpenXml;
9 | using DocumentFormat.OpenXml.Packaging;
10 | using DocumentFormat.OpenXml.Validation;
11 | using OOXMLValidatorCLI.Interfaces;
12 |
13 | ///
14 | /// Utility class for working with Open XML documents.
15 | ///
16 | public class DocumentUtils : IDocumentUtils
17 | {
18 | ///
19 | /// Opens a WordprocessingDocument from the specified file path.
20 | ///
21 | /// The path of the Word document.
22 | /// The opened WordprocessingDocument.
23 | public WordprocessingDocument OpenWordprocessingDocument(string filePath)
24 | {
25 | return WordprocessingDocument.Open(filePath, false);
26 | }
27 |
28 | ///
29 | /// Opens a PresentationDocument from the specified file path.
30 | ///
31 | /// The path of the PowerPoint presentation.
32 | /// The opened PresentationDocument.
33 | public PresentationDocument OpenPresentationDocument(string filePath)
34 | {
35 | return PresentationDocument.Open(filePath, false);
36 | }
37 |
38 | ///
39 | /// Opens a SpreadsheetDocument from the specified file path.
40 | ///
41 | /// The path of the Excel spreadsheet.
42 | /// The opened SpreadsheetDocument.
43 | public SpreadsheetDocument OpenSpreadsheetDocument(string filePath)
44 | {
45 | return SpreadsheetDocument.Open(filePath, false);
46 | }
47 |
48 | ///
49 | /// Validates the specified OpenXmlPackage against the specified file format version.
50 | ///
51 | /// The OpenXmlPackage to validate.
52 | /// The file format version to validate against.
53 | /// A tuple containing a boolean indicating if the validation is strict, and a collection of validation error information.
54 | public Tuple> Validate(OpenXmlPackage doc, FileFormatVersions version)
55 | {
56 | OpenXmlValidator openXmlValidator = new OpenXmlValidator(version);
57 | bool isStrict = doc.StrictRelationshipFound;
58 |
59 | IEnumerable validationErrorInfos = openXmlValidator.Validate(doc);
60 | IEnumerable errors = validationErrorInfos.Select(e => new ValidationErrorInfoInternal()
61 | {
62 | ErrorType = Enum.GetName(e.ErrorType),
63 | Description = e.Description,
64 | Path = e.Path,
65 | Id = e.Id,
66 | });
67 |
68 | return new Tuple>(isStrict, errors);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/OOXMLValidatorCLI/Classes/FileService.cs:
--------------------------------------------------------------------------------
1 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | namespace OOXMLValidatorCLI.Classes
4 | {
5 | using System.IO;
6 | using OOXMLValidatorCLI.Interfaces;
7 |
8 | ///
9 | /// Represents a service for working with files.
10 | ///
11 | public class FileService : IFileService
12 | {
13 | ///
14 | /// Gets the attributes of a file at the specified path.
15 | ///
16 | /// The path of the file.
17 | /// The attributes of the file.
18 | public FileAttributes GetAttributes(string path)
19 | {
20 | return File.GetAttributes(path);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/OOXMLValidatorCLI/Classes/FunctionUtils.cs:
--------------------------------------------------------------------------------
1 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | namespace OOXMLValidatorCLI.Classes
4 | {
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Dynamic;
8 | using System.Linq;
9 | using System.Xml.Linq;
10 | using DocumentFormat.OpenXml;
11 | using DocumentFormat.OpenXml.Packaging;
12 | using Newtonsoft.Json;
13 | using OOXMLValidatorCLI.Interfaces;
14 |
15 | ///
16 | /// Utility class for performing various functions related to Open XML documents.
17 | ///
18 | public class FunctionUtils : IFunctionUtils
19 | {
20 | private readonly IDocumentUtils documentUtils;
21 | private FileFormatVersions? fileFormatVersions;
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | /// The document utility object.
27 | public FunctionUtils(IDocumentUtils documentUtils)
28 | {
29 | this.documentUtils = documentUtils;
30 | this.fileFormatVersions = null;
31 | }
32 |
33 | ///
34 | /// Gets the maximum supported Office version based on the available FileFormatVersions.
35 | ///
36 | public FileFormatVersions OfficeVersion
37 | {
38 | get
39 | {
40 | return this.fileFormatVersions ?? Enum.GetValues(typeof(FileFormatVersions)).Cast().Max();
41 | }
42 | }
43 |
44 | ///
45 | /// Gets the OpenXmlPackage object for the specified file.
46 | ///
47 | /// The path of the file.
48 | /// The extension of the file.
49 | /// The OpenXmlPackage object.
50 | public OpenXmlPackage GetDocument(string filePath, string fileExtension)
51 | {
52 | OpenXmlPackage doc = null;
53 |
54 | switch (fileExtension)
55 | {
56 | case ".docx":
57 | case ".docm":
58 | case ".dotm":
59 | case ".dotx":
60 | doc = this.documentUtils.OpenWordprocessingDocument(filePath);
61 | break;
62 | case ".pptx":
63 | case ".pptm":
64 | case ".potm":
65 | case ".potx":
66 | case ".ppam":
67 | case ".ppsm":
68 | case ".ppsx":
69 | doc = this.documentUtils.OpenPresentationDocument(filePath);
70 | break;
71 | case ".xlsx":
72 | case ".xlsm":
73 | case ".xltm":
74 | case ".xltx":
75 | case ".xlam":
76 | doc = this.documentUtils.OpenSpreadsheetDocument(filePath);
77 | break;
78 | default:
79 | break;
80 | }
81 |
82 | return doc;
83 | }
84 |
85 | ///
86 | /// Sets the Office version based on the provided string value.
87 | ///
88 | /// The string representation of the Office version.
89 | public void SetOfficeVersion(string v)
90 | {
91 | if (v is not null && Enum.TryParse(v, out FileFormatVersions version))
92 | {
93 | this.fileFormatVersions = version;
94 | }
95 | else
96 | {
97 | FileFormatVersions currentVersion = Enum.GetValues(typeof(FileFormatVersions)).Cast().Last();
98 | this.fileFormatVersions = currentVersion;
99 | }
100 | }
101 |
102 | ///
103 | /// Validates the specified OpenXmlPackage object and returns the validation errors.
104 | ///
105 | /// The OpenXmlPackage object to validate.
106 | /// A tuple containing a boolean value indicating if the validation is strict and a collection of validation error information.
107 | public Tuple> GetValidationErrors(OpenXmlPackage doc)
108 | {
109 | return this.documentUtils.Validate(doc, this.OfficeVersion);
110 | }
111 |
112 | ///
113 | /// Gets the validation errors data in the specified format.
114 | ///
115 | /// The validation information.
116 | /// The path of the file.
117 | /// A boolean value indicating if the data should be returned in XML format.
118 | /// The validation errors data.
119 | public object GetValidationErrorsData(Tuple> validationInfo, string filePath, bool returnXml)
120 | {
121 | if (!returnXml)
122 | {
123 | List res = new List();
124 |
125 | foreach (ValidationErrorInfoInternal validationErrorInfo in validationInfo.Item2)
126 | {
127 | dynamic dyno = new ExpandoObject();
128 | dyno.Description = validationErrorInfo.Description;
129 | dyno.Path = validationErrorInfo.Path;
130 | dyno.Id = validationErrorInfo.Id;
131 | dyno.ErrorType = validationErrorInfo.ErrorType;
132 | res.Add(dyno);
133 | }
134 |
135 | string json = JsonConvert.SerializeObject(
136 | res,
137 | Formatting.None,
138 | new JsonSerializerSettings()
139 | {
140 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
141 | });
142 |
143 | return json;
144 | }
145 | else
146 | {
147 | XElement element;
148 | ValidationErrorInfoInternal first = validationInfo.Item2.FirstOrDefault();
149 |
150 | if (first?.ErrorType == "OpenXmlPackageException")
151 | {
152 | element = new XElement(
153 | "Exceptions",
154 | new XElement(
155 | "OpenXmlPackageException",
156 | new XElement("Message", first.Description)));
157 | }
158 | else
159 | {
160 | element = new XElement("ValidationErrorInfoList");
161 |
162 | foreach (ValidationErrorInfoInternal validationErrorInfo in validationInfo.Item2)
163 | {
164 | element.Add(
165 | new XElement(
166 | "ValidationErrorInfo",
167 | new XElement("Description", validationErrorInfo.Description),
168 | new XElement("Path", validationErrorInfo.Path),
169 | new XElement("Id", validationErrorInfo.Id),
170 | new XElement("ErrorType", validationErrorInfo.ErrorType)));
171 | }
172 | }
173 |
174 | XElement xml = new XElement("File", element);
175 | xml.SetAttributeValue("FilePath", filePath);
176 | xml.SetAttributeValue("IsStrict", validationInfo.Item1);
177 |
178 | return new XDocument(xml);
179 | }
180 | }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/OOXMLValidatorCLI/Classes/Validate.cs:
--------------------------------------------------------------------------------
1 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | namespace OOXMLValidatorCLI.Classes
4 | {
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Xml.Linq;
10 | using DocumentFormat.OpenXml.Packaging;
11 | using Newtonsoft.Json;
12 | using OOXMLValidatorCLI.Interfaces;
13 |
14 | ///
15 | /// Represents a class that provides validation functionality for OOXML files.
16 | ///
17 | public class Validate : IValidate
18 | {
19 | private readonly IFunctionUtils functionUtils;
20 | private readonly string[] validFileExtensions = new string[] { ".docx", ".docm", ".dotm", ".dotx", ".pptx", ".pptm", ".potm", ".potx", ".ppam", ".ppsm", ".ppsx", ".xlsx", ".xlsm", ".xltm", ".xltx", ".xlam" };
21 | private readonly IFileService fileService;
22 | private readonly IDirectoryService directoryService;
23 |
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | /// The function utilities.
28 | /// The file service.
29 | /// The directory service.
30 | public Validate(IFunctionUtils functionUtils, IFileService fileService, IDirectoryService directoryService)
31 | {
32 | this.functionUtils = functionUtils;
33 | this.fileService = fileService;
34 | this.directoryService = directoryService;
35 | }
36 |
37 | ///
38 | /// Validates the specified OOXML file.
39 | ///
40 | /// The path to the file.
41 | /// The format of the file.
42 | /// Indicates whether to return the validation errors as XML.
43 | /// Indicates whether to recursively validate files in subdirectories.
44 | /// Indicates whether to include valid files in the result.
45 | /// The validation result.
46 | public object OOXML(string filePath, string format, bool returnXml = false, bool recursive = false, bool includeValid = false)
47 | {
48 | this.functionUtils.SetOfficeVersion(format);
49 |
50 | FileAttributes fileAttributes = this.fileService.GetAttributes(filePath);
51 |
52 | if (fileAttributes.HasFlag(FileAttributes.Directory))
53 | {
54 | IEnumerable files = recursive ? this.directoryService.EnumerateFiles(filePath, "*.*", SearchOption.AllDirectories).Where(f => this.validFileExtensions.Contains(Path.GetExtension(f)))
55 | : this.directoryService.GetFiles(filePath).Where(f => this.validFileExtensions.Contains(Path.GetExtension(f)));
56 |
57 | XDocument xDocument = new XDocument(new XElement("Document"));
58 | List