From 5bf3041bb01e308fdd8299546a70f28f996be172 Mon Sep 17 00:00:00 2001 From: Myx Date: Sat, 12 Oct 2024 16:51:25 +0200 Subject: [PATCH] Add image service --- .gitignore | 46 +- .vscode/extensions.json | 4 - .vscode/launch.json | 20 - .vscode/tasks.json | 42 - services/bytefy.image/.dockerignore | 25 + services/bytefy.image/bytefy.image.sln | 21 + services/bytefy.image/bytefy.image/Dockerfile | 23 + .../bytefy.image/bytefy.image/MimeTypeMap.cs | 833 ++++++++++++++++++ services/bytefy.image/bytefy.image/Program.cs | 49 ++ .../Properties/launchSettings.json | 15 + .../bytefy.image/appsettings.Development.json | 8 + .../bytefy.image/appsettings.json | 9 + .../bytefy.image/bytefy.image.csproj | 23 + .../bytefy.image/bytefy.image.http | 11 + services/bytefy.image/docker-compose.yml | 6 + .editorconfig => tools/.editorconfig | 0 tools/.gitignore | 42 + README.md => tools/README.md | 0 angular.json => tools/angular.json | 0 package-lock.json => tools/package-lock.json | 0 package.json => tools/package.json | 0 {src => tools/src}/app/app.component.html | 0 {src => tools/src}/app/app.component.scss | 0 {src => tools/src}/app/app.component.spec.ts | 0 {src => tools/src}/app/app.component.ts | 0 {src => tools/src}/app/app.config.ts | 0 {src => tools/src}/app/app.routes.ts | 0 .../src}/app/header/header.component.html | 0 .../src}/app/header/header.component.scss | 0 .../src}/app/header/header.component.spec.ts | 0 .../src}/app/header/header.component.ts | 0 .../dual-textarea.component.html | 0 .../dual-textarea.component.scss | 0 .../dual-textarea/dual-textarea.component.ts | 0 .../upload/file-converter.component.html | 0 .../upload/file-converter.component.scss | 0 .../shared/upload/file-converter.component.ts | 0 {src => tools/src}/assets/.gitkeep | 0 {src => tools/src}/favicon.ico | Bin {src => tools/src}/index.html | 0 {src => tools/src}/main.ts | 0 {src => tools/src}/styles.scss | 0 .../ascii-to-text.component.html | 0 .../ascii-to-text.component.scss | 0 .../ascii-to-text/ascii-to-text.component.ts | 0 .../base64-converter.component.html | 0 .../base64-converter.component.scss | 0 .../base64-converter.component.spec.ts | 0 .../base64-converter.component.ts | 0 .../dds-to-png/dds-to-png.component.html | 0 .../dds-to-png/dds-to-png.component.scss | 0 .../dds-to-png/dds-to-png.component.spec.ts | 0 .../tools/dds-to-png/dds-to-png.component.ts | 0 .../tools/dds-to-png/dds-to-png.service.ts | 0 .../src}/tools/guid/guid.component.html | 0 .../src}/tools/guid/guid.component.scss | 0 .../src}/tools/guid/guid.component.ts | 0 .../jwt-to-json/jwt-to-json.component.html | 0 .../jwt-to-json/jwt-to-json.component.scss | 0 .../jwt-to-json/jwt-to-json.component.spec.ts | 0 .../jwt-to-json/jwt-to-json.component.ts | 0 .../text-to-cron/text-to-cron.component.html | 0 .../text-to-cron/text-to-cron.component.scss | 0 .../text-to-cron.component.spec.ts | 0 .../text-to-cron/text-to-cron.component.ts | 0 tsconfig.app.json => tools/tsconfig.app.json | 0 tsconfig.json => tools/tsconfig.json | 0 .../tsconfig.spec.json | 0 68 files changed, 1069 insertions(+), 108 deletions(-) delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json create mode 100644 services/bytefy.image/.dockerignore create mode 100644 services/bytefy.image/bytefy.image.sln create mode 100644 services/bytefy.image/bytefy.image/Dockerfile create mode 100644 services/bytefy.image/bytefy.image/MimeTypeMap.cs create mode 100644 services/bytefy.image/bytefy.image/Program.cs create mode 100644 services/bytefy.image/bytefy.image/Properties/launchSettings.json create mode 100644 services/bytefy.image/bytefy.image/appsettings.Development.json create mode 100644 services/bytefy.image/bytefy.image/appsettings.json create mode 100644 services/bytefy.image/bytefy.image/bytefy.image.csproj create mode 100644 services/bytefy.image/bytefy.image/bytefy.image.http create mode 100644 services/bytefy.image/docker-compose.yml rename .editorconfig => tools/.editorconfig (100%) create mode 100644 tools/.gitignore rename README.md => tools/README.md (100%) rename angular.json => tools/angular.json (100%) rename package-lock.json => tools/package-lock.json (100%) rename package.json => tools/package.json (100%) rename {src => tools/src}/app/app.component.html (100%) rename {src => tools/src}/app/app.component.scss (100%) rename {src => tools/src}/app/app.component.spec.ts (100%) rename {src => tools/src}/app/app.component.ts (100%) rename {src => tools/src}/app/app.config.ts (100%) rename {src => tools/src}/app/app.routes.ts (100%) rename {src => tools/src}/app/header/header.component.html (100%) rename {src => tools/src}/app/header/header.component.scss (100%) rename {src => tools/src}/app/header/header.component.spec.ts (100%) rename {src => tools/src}/app/header/header.component.ts (100%) rename {src => tools/src}/app/shared/dual-textarea/dual-textarea.component.html (100%) rename {src => tools/src}/app/shared/dual-textarea/dual-textarea.component.scss (100%) rename {src => tools/src}/app/shared/dual-textarea/dual-textarea.component.ts (100%) rename {src => tools/src}/app/shared/upload/file-converter.component.html (100%) rename {src => tools/src}/app/shared/upload/file-converter.component.scss (100%) rename {src => tools/src}/app/shared/upload/file-converter.component.ts (100%) rename {src => tools/src}/assets/.gitkeep (100%) rename {src => tools/src}/favicon.ico (100%) rename {src => tools/src}/index.html (100%) rename {src => tools/src}/main.ts (100%) rename {src => tools/src}/styles.scss (100%) rename {src => tools/src}/tools/ascii-to-text/ascii-to-text.component.html (100%) rename {src => tools/src}/tools/ascii-to-text/ascii-to-text.component.scss (100%) rename {src => tools/src}/tools/ascii-to-text/ascii-to-text.component.ts (100%) rename {src => tools/src}/tools/base64-converter/base64-converter.component.html (100%) rename {src => tools/src}/tools/base64-converter/base64-converter.component.scss (100%) rename {src => tools/src}/tools/base64-converter/base64-converter.component.spec.ts (100%) rename {src => tools/src}/tools/base64-converter/base64-converter.component.ts (100%) rename {src => tools/src}/tools/dds-to-png/dds-to-png.component.html (100%) rename {src => tools/src}/tools/dds-to-png/dds-to-png.component.scss (100%) rename {src => tools/src}/tools/dds-to-png/dds-to-png.component.spec.ts (100%) rename {src => tools/src}/tools/dds-to-png/dds-to-png.component.ts (100%) rename {src => tools/src}/tools/dds-to-png/dds-to-png.service.ts (100%) rename {src => tools/src}/tools/guid/guid.component.html (100%) rename {src => tools/src}/tools/guid/guid.component.scss (100%) rename {src => tools/src}/tools/guid/guid.component.ts (100%) rename {src => tools/src}/tools/jwt-to-json/jwt-to-json.component.html (100%) rename {src => tools/src}/tools/jwt-to-json/jwt-to-json.component.scss (100%) rename {src => tools/src}/tools/jwt-to-json/jwt-to-json.component.spec.ts (100%) rename {src => tools/src}/tools/jwt-to-json/jwt-to-json.component.ts (100%) rename {src => tools/src}/tools/text-to-cron/text-to-cron.component.html (100%) rename {src => tools/src}/tools/text-to-cron/text-to-cron.component.scss (100%) rename {src => tools/src}/tools/text-to-cron/text-to-cron.component.spec.ts (100%) rename {src => tools/src}/tools/text-to-cron/text-to-cron.component.ts (100%) rename tsconfig.app.json => tools/tsconfig.app.json (100%) rename tsconfig.json => tools/tsconfig.json (100%) rename tsconfig.spec.json => tools/tsconfig.spec.json (100%) diff --git a/.gitignore b/.gitignore index cc7b141..29cd45f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,42 +1,4 @@ -# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db +tools/.vscode +services/bytefy.image/bytefy.image/obj +services/bytefy.image/bytefy.image/bin +services/bytefy.image/.idea diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 77b3745..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 925af83..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a298b5b..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - } - ] -} diff --git a/services/bytefy.image/.dockerignore b/services/bytefy.image/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/services/bytefy.image/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/services/bytefy.image/bytefy.image.sln b/services/bytefy.image/bytefy.image.sln new file mode 100644 index 0000000..49bd1e8 --- /dev/null +++ b/services/bytefy.image/bytefy.image.sln @@ -0,0 +1,21 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bytefy.image", "bytefy.image\bytefy.image.csproj", "{FEB931BB-C67F-4754-A05F-ECAAC83628C4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E72677F8-7D41-48DB-AF14-D3A188D11AFA}" + ProjectSection(SolutionItems) = preProject + docker-compose.yml = docker-compose.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FEB931BB-C67F-4754-A05F-ECAAC83628C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEB931BB-C67F-4754-A05F-ECAAC83628C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEB931BB-C67F-4754-A05F-ECAAC83628C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEB931BB-C67F-4754-A05F-ECAAC83628C4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/services/bytefy.image/bytefy.image/Dockerfile b/services/bytefy.image/bytefy.image/Dockerfile new file mode 100644 index 0000000..e81d81c --- /dev/null +++ b/services/bytefy.image/bytefy.image/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["bytefy.image/bytefy.image.csproj", "bytefy.image/"] +RUN dotnet restore "bytefy.image/bytefy.image.csproj" +COPY . . +WORKDIR "/src/bytefy.image" +RUN dotnet build "bytefy.image.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "bytefy.image.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "bytefy.image.dll"] diff --git a/services/bytefy.image/bytefy.image/MimeTypeMap.cs b/services/bytefy.image/bytefy.image/MimeTypeMap.cs new file mode 100644 index 0000000..57e8717 --- /dev/null +++ b/services/bytefy.image/bytefy.image/MimeTypeMap.cs @@ -0,0 +1,833 @@ +namespace MimeTypes +{ + /// + /// Class MimeTypeMap. + /// + public static class MimeTypeMap + { + private const string Dot = "."; + private const string QuestionMark = "?"; + private const string DefaultMimeType = "application/octet-stream"; + private static readonly Lazy> Mappings = new(BuildMappings); + + private static IDictionary BuildMappings() + { + var mappings = new Dictionary(StringComparer.OrdinalIgnoreCase) { + + #region Big freaking list of mime types + + // maps both ways, + // extension -> mime type + // and + // mime type -> extension + // + // any mime types on left side not pre-loaded on right side, are added automatically + // some mime types can map to multiple extensions, so to get a deterministic mapping, + // add those to the dictionary specifically + // + // combination of values from Windows 7 Registry and + // from C:\Windows\System32\inetsrv\config\applicationHost.config + // some added, including .7z and .dat + // + // Some added based on http://www.iana.org/assignments/media-types/media-types.xhtml + // which lists mime types, but not extensions + // + {".323", "text/h323"}, + {".3g2", "video/3gpp2"}, + {".3gp", "video/3gpp"}, + {".3gp2", "video/3gpp2"}, + {".3gpp", "video/3gpp"}, + {".7z", "application/x-7z-compressed"}, + {".aa", "audio/audible"}, + {".AAC", "audio/aac"}, + {".aaf", "application/octet-stream"}, + {".aax", "audio/vnd.audible.aax"}, + {".ac3", "audio/ac3"}, + {".aca", "application/octet-stream"}, + {".accda", "application/msaccess.addin"}, + {".accdb", "application/msaccess"}, + {".accdc", "application/msaccess.cab"}, + {".accde", "application/msaccess"}, + {".accdr", "application/msaccess.runtime"}, + {".accdt", "application/msaccess"}, + {".accdw", "application/msaccess.webapplication"}, + {".accft", "application/msaccess.ftemplate"}, + {".acx", "application/internet-property-stream"}, + {".AddIn", "text/xml"}, + {".ade", "application/msaccess"}, + {".adobebridge", "application/x-bridge-url"}, + {".adp", "application/msaccess"}, + {".ADT", "audio/vnd.dlna.adts"}, + {".ADTS", "audio/aac"}, + {".afm", "application/octet-stream"}, + {".ai", "application/postscript"}, + {".aif", "audio/aiff"}, + {".aifc", "audio/aiff"}, + {".aiff", "audio/aiff"}, + {".air", "application/vnd.adobe.air-application-installer-package+zip"}, + {".amc", "application/mpeg"}, + {".anx", "application/annodex"}, + {".apk", "application/vnd.android.package-archive"}, + {".apng", "image/apng"}, + {".application", "application/x-ms-application"}, + {".art", "image/x-jg"}, + {".asa", "application/xml"}, + {".asax", "application/xml"}, + {".ascx", "application/xml"}, + {".asd", "application/octet-stream"}, + {".asf", "video/x-ms-asf"}, + {".ashx", "application/xml"}, + {".asi", "application/octet-stream"}, + {".asm", "text/plain"}, + {".asmx", "application/xml"}, + {".aspx", "application/xml"}, + {".asr", "video/x-ms-asf"}, + {".asx", "video/x-ms-asf"}, + {".atom", "application/atom+xml"}, + {".au", "audio/basic"}, + {".avci", "image/avci"}, + {".avcs", "image/avcs"}, + {".avi", "video/x-msvideo"}, + {".avif", "image/avif"}, + {".avifs", "image/avif-sequence"}, + {".axa", "audio/annodex"}, + {".axs", "application/olescript"}, + {".axv", "video/annodex"}, + {".bas", "text/plain"}, + {".bcpio", "application/x-bcpio"}, + {".bin", "application/octet-stream"}, + {".bmp", "image/bmp"}, + {".c", "text/plain"}, + {".cab", "application/octet-stream"}, + {".caf", "audio/x-caf"}, + {".calx", "application/vnd.ms-office.calx"}, + {".cat", "application/vnd.ms-pki.seccat"}, + {".cc", "text/plain"}, + {".cd", "text/plain"}, + {".cdda", "audio/aiff"}, + {".cdf", "application/x-cdf"}, + {".cer", "application/x-x509-ca-cert"}, + {".cfg", "text/plain"}, + {".chm", "application/octet-stream"}, + {".class", "application/x-java-applet"}, + {".clp", "application/x-msclip"}, + {".cmd", "text/plain"}, + {".cmx", "image/x-cmx"}, + {".cnf", "text/plain"}, + {".cod", "image/cis-cod"}, + {".config", "application/xml"}, + {".contact", "text/x-ms-contact"}, + {".coverage", "application/xml"}, + {".cpio", "application/x-cpio"}, + {".cpp", "text/plain"}, + {".crd", "application/x-mscardfile"}, + {".crl", "application/pkix-crl"}, + {".crt", "application/x-x509-ca-cert"}, + {".cs", "text/plain"}, + {".csdproj", "text/plain"}, + {".csh", "application/x-csh"}, + {".csproj", "text/plain"}, + {".css", "text/css"}, + {".csv", "text/csv"}, + {".cur", "application/octet-stream"}, + {".czx", "application/x-czx"}, + {".cxx", "text/plain"}, + {".dat", "application/octet-stream"}, + {".datasource", "application/xml"}, + {".dbproj", "text/plain"}, + {".dcr", "application/x-director"}, + {".def", "text/plain"}, + {".deploy", "application/octet-stream"}, + {".der", "application/x-x509-ca-cert"}, + {".dgml", "application/xml"}, + {".dib", "image/bmp"}, + {".dif", "video/x-dv"}, + {".dir", "application/x-director"}, + {".disco", "text/xml"}, + {".divx", "video/divx"}, + {".dll", "application/x-msdownload"}, + {".dll.config", "text/xml"}, + {".dlm", "text/dlm"}, + {".doc", "application/msword"}, + {".docm", "application/vnd.ms-word.document.macroEnabled.12"}, + {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + {".dot", "application/msword"}, + {".dotm", "application/vnd.ms-word.template.macroEnabled.12"}, + {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + {".dsp", "application/octet-stream"}, + {".dsw", "text/plain"}, + {".dtd", "text/xml"}, + {".dtsConfig", "text/xml"}, + {".dv", "video/x-dv"}, + {".dvi", "application/x-dvi"}, + {".dwf", "drawing/x-dwf"}, + {".dwg", "application/acad"}, + {".dwp", "application/octet-stream"}, + {".dxf", "application/x-dxf"}, + {".dxr", "application/x-director"}, + {".eml", "message/rfc822"}, + {".emf", "image/emf"}, + {".emz", "application/octet-stream"}, + {".eot", "application/vnd.ms-fontobject"}, + {".eps", "application/postscript"}, + {".es", "application/ecmascript"}, + {".etl", "application/etl"}, + {".etx", "text/x-setext"}, + {".evy", "application/envoy"}, + {".exe", "application/vnd.microsoft.portable-executable"}, + {".exe.config", "text/xml"}, + {".f4v", "video/mp4"}, + {".fdf", "application/vnd.fdf"}, + {".fif", "application/fractals"}, + {".filters", "application/xml"}, + {".fla", "application/octet-stream"}, + {".flac", "audio/flac"}, + {".flr", "x-world/x-vrml"}, + {".flv", "video/x-flv"}, + {".fsscript", "application/fsharp-script"}, + {".fsx", "application/fsharp-script"}, + {".generictest", "application/xml"}, + {".geojson", "application/geo+json"}, + {".gif", "image/gif"}, + {".gml", "application/gml+xml"}, + {".gpx", "application/gpx+xml"}, + {".group", "text/x-ms-group"}, + {".gsm", "audio/x-gsm"}, + {".gtar", "application/x-gtar"}, + {".gz", "application/x-gzip"}, + {".h", "text/plain"}, + {".hdf", "application/x-hdf"}, + {".hdml", "text/x-hdml"}, + {".heic", "image/heic"}, + {".heics", "image/heic-sequence"}, + {".heif", "image/heif"}, + {".heifs", "image/heif-sequence"}, + {".hhc", "application/x-oleobject"}, + {".hhk", "application/octet-stream"}, + {".hhp", "application/octet-stream"}, + {".hlp", "application/winhlp"}, + {".hpp", "text/plain"}, + {".hqx", "application/mac-binhex40"}, + {".hta", "application/hta"}, + {".htc", "text/x-component"}, + {".htm", "text/html"}, + {".html", "text/html"}, + {".htt", "text/webviewhtml"}, + {".hxa", "application/xml"}, + {".hxc", "application/xml"}, + {".hxd", "application/octet-stream"}, + {".hxe", "application/xml"}, + {".hxf", "application/xml"}, + {".hxh", "application/octet-stream"}, + {".hxi", "application/octet-stream"}, + {".hxk", "application/xml"}, + {".hxq", "application/octet-stream"}, + {".hxr", "application/octet-stream"}, + {".hxs", "application/octet-stream"}, + {".hxt", "text/html"}, + {".hxv", "application/xml"}, + {".hxw", "application/octet-stream"}, + {".hxx", "text/plain"}, + {".i", "text/plain"}, + {".ical", "text/calendar"}, + {".icalendar", "text/calendar"}, + {".ico", "image/x-icon"}, + {".ics", "text/calendar"}, + {".idl", "text/plain"}, + {".ief", "image/ief"}, + {".ifb", "text/calendar"}, + {".iii", "application/x-iphone"}, + {".inc", "text/plain"}, + {".inf", "application/octet-stream"}, + {".ini", "text/plain"}, + {".inl", "text/plain"}, + {".ins", "application/x-internet-signup"}, + {".ipa", "application/x-itunes-ipa"}, + {".ipg", "application/x-itunes-ipg"}, + {".ipproj", "text/plain"}, + {".ipsw", "application/x-itunes-ipsw"}, + {".iqy", "text/x-ms-iqy"}, + {".isp", "application/x-internet-signup"}, + {".isma", "application/octet-stream"}, + {".ismv", "application/octet-stream"}, + {".ite", "application/x-itunes-ite"}, + {".itlp", "application/x-itunes-itlp"}, + {".itms", "application/x-itunes-itms"}, + {".itpc", "application/x-itunes-itpc"}, + {".IVF", "video/x-ivf"}, + {".jar", "application/java-archive"}, + {".java", "application/octet-stream"}, + {".jck", "application/liquidmotion"}, + {".jcz", "application/liquidmotion"}, + {".jfif", "image/pjpeg"}, + {".jnlp", "application/x-java-jnlp-file"}, + {".jpb", "application/octet-stream"}, + {".jpe", "image/jpeg"}, + {".jpeg", "image/jpeg"}, + {".jpg", "image/jpeg"}, + {".js", "application/javascript"}, + {".json", "application/json"}, + {".jsx", "text/jscript"}, + {".jsxbin", "text/plain"}, + {".key", "application/vnd.apple.keynote"}, + {".latex", "application/x-latex"}, + {".library-ms", "application/windows-library+xml"}, + {".lit", "application/x-ms-reader"}, + {".loadtest", "application/xml"}, + {".lpk", "application/octet-stream"}, + {".lsf", "video/x-la-asf"}, + {".lst", "text/plain"}, + {".lsx", "video/x-la-asf"}, + {".lzh", "application/octet-stream"}, + {".m13", "application/x-msmediaview"}, + {".m14", "application/x-msmediaview"}, + {".m1v", "video/mpeg"}, + {".m2t", "video/vnd.dlna.mpeg-tts"}, + {".m2ts", "video/vnd.dlna.mpeg-tts"}, + {".m2v", "video/mpeg"}, + {".m3u", "audio/x-mpegurl"}, + {".m3u8", "audio/x-mpegurl"}, + {".m4a", "audio/m4a"}, + {".m4b", "audio/m4b"}, + {".m4p", "audio/m4p"}, + {".m4r", "audio/x-m4r"}, + {".m4v", "video/x-m4v"}, + {".mac", "image/x-macpaint"}, + {".mak", "text/plain"}, + {".man", "application/x-troff-man"}, + {".manifest", "application/x-ms-manifest"}, + {".map", "text/plain"}, + {".master", "application/xml"}, + {".mbox", "application/mbox"}, + {".mda", "application/msaccess"}, + {".mdb", "application/x-msaccess"}, + {".mde", "application/msaccess"}, + {".mdp", "application/octet-stream"}, + {".me", "application/x-troff-me"}, + {".mfp", "application/x-shockwave-flash"}, + {".mht", "message/rfc822"}, + {".mhtml", "message/rfc822"}, + {".mid", "audio/mid"}, + {".midi", "audio/mid"}, + {".mix", "application/octet-stream"}, + {".mk", "text/plain"}, + {".mk3d", "video/x-matroska-3d"}, + {".mka", "audio/x-matroska"}, + {".mkv", "video/x-matroska"}, + {".mmf", "application/x-smaf"}, + {".mno", "text/xml"}, + {".mny", "application/x-msmoney"}, + {".mod", "video/mpeg"}, + {".mov", "video/quicktime"}, + {".movie", "video/x-sgi-movie"}, + {".mp2", "video/mpeg"}, + {".mp2v", "video/mpeg"}, + {".mp3", "audio/mpeg"}, + {".mp4", "video/mp4"}, + {".mp4v", "video/mp4"}, + {".mpa", "video/mpeg"}, + {".mpe", "video/mpeg"}, + {".mpeg", "video/mpeg"}, + {".mpf", "application/vnd.ms-mediapackage"}, + {".mpg", "video/mpeg"}, + {".mpp", "application/vnd.ms-project"}, + {".mpv2", "video/mpeg"}, + {".mqv", "video/quicktime"}, + {".ms", "application/x-troff-ms"}, + {".msg", "application/vnd.ms-outlook"}, + {".msi", "application/octet-stream"}, + {".mso", "application/octet-stream"}, + {".mts", "video/vnd.dlna.mpeg-tts"}, + {".mtx", "application/xml"}, + {".mvb", "application/x-msmediaview"}, + {".mvc", "application/x-miva-compiled"}, + {".mxf", "application/mxf"}, + {".mxp", "application/x-mmxp"}, + {".nc", "application/x-netcdf"}, + {".nsc", "video/x-ms-asf"}, + {".numbers", "application/vnd.apple.numbers"}, + {".nws", "message/rfc822"}, + {".ocx", "application/octet-stream"}, + {".oda", "application/oda"}, + {".odb", "application/vnd.oasis.opendocument.database"}, + {".odc", "application/vnd.oasis.opendocument.chart"}, + {".odf", "application/vnd.oasis.opendocument.formula"}, + {".odg", "application/vnd.oasis.opendocument.graphics"}, + {".odh", "text/plain"}, + {".odi", "application/vnd.oasis.opendocument.image"}, + {".odl", "text/plain"}, + {".odm", "application/vnd.oasis.opendocument.text-master"}, + {".odp", "application/vnd.oasis.opendocument.presentation"}, + {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, + {".odt", "application/vnd.oasis.opendocument.text"}, + {".oga", "audio/ogg"}, + {".ogg", "audio/ogg"}, + {".ogv", "video/ogg"}, + {".ogx", "application/ogg"}, + {".one", "application/onenote"}, + {".onea", "application/onenote"}, + {".onepkg", "application/onenote"}, + {".onetmp", "application/onenote"}, + {".onetoc", "application/onenote"}, + {".onetoc2", "application/onenote"}, + {".opus", "audio/ogg"}, + {".orderedtest", "application/xml"}, + {".osdx", "application/opensearchdescription+xml"}, + {".otf", "application/font-sfnt"}, + {".otg", "application/vnd.oasis.opendocument.graphics-template"}, + {".oth", "application/vnd.oasis.opendocument.text-web"}, + {".otp", "application/vnd.oasis.opendocument.presentation-template"}, + {".ots", "application/vnd.oasis.opendocument.spreadsheet-template"}, + {".ott", "application/vnd.oasis.opendocument.text-template"}, + {".oxps", "application/oxps"}, + {".oxt", "application/vnd.openofficeorg.extension"}, + {".p10", "application/pkcs10"}, + {".p12", "application/x-pkcs12"}, + {".p7b", "application/x-pkcs7-certificates"}, + {".p7c", "application/pkcs7-mime"}, + {".p7m", "application/pkcs7-mime"}, + {".p7r", "application/x-pkcs7-certreqresp"}, + {".p7s", "application/pkcs7-signature"}, + {".pages", "application/vnd.apple.pages"}, + {".pbm", "image/x-portable-bitmap"}, + {".pcast", "application/x-podcast"}, + {".pct", "image/pict"}, + {".pcx", "application/octet-stream"}, + {".pcz", "application/octet-stream"}, + {".pdf", "application/pdf"}, + {".pfb", "application/octet-stream"}, + {".pfm", "application/octet-stream"}, + {".pfx", "application/x-pkcs12"}, + {".pgm", "image/x-portable-graymap"}, + {".pic", "image/pict"}, + {".pict", "image/pict"}, + {".pkgdef", "text/plain"}, + {".pkgundef", "text/plain"}, + {".pko", "application/vnd.ms-pki.pko"}, + {".pls", "audio/scpls"}, + {".pma", "application/x-perfmon"}, + {".pmc", "application/x-perfmon"}, + {".pml", "application/x-perfmon"}, + {".pmr", "application/x-perfmon"}, + {".pmw", "application/x-perfmon"}, + {".png", "image/png"}, + {".pnm", "image/x-portable-anymap"}, + {".pnt", "image/x-macpaint"}, + {".pntg", "image/x-macpaint"}, + {".pnz", "image/png"}, + {".pot", "application/vnd.ms-powerpoint"}, + {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, + {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, + {".ppa", "application/vnd.ms-powerpoint"}, + {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + {".ppm", "image/x-portable-pixmap"}, + {".pps", "application/vnd.ms-powerpoint"}, + {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + {".ppt", "application/vnd.ms-powerpoint"}, + {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + {".prf", "application/pics-rules"}, + {".prm", "application/octet-stream"}, + {".prx", "application/octet-stream"}, + {".ps", "application/postscript"}, + {".psc1", "application/PowerShell"}, + {".psd", "application/octet-stream"}, + {".psess", "application/xml"}, + {".psm", "application/octet-stream"}, + {".psp", "application/octet-stream"}, + {".pst", "application/vnd.ms-outlook"}, + {".pub", "application/x-mspublisher"}, + {".pwz", "application/vnd.ms-powerpoint"}, + {".qht", "text/x-html-insertion"}, + {".qhtm", "text/x-html-insertion"}, + {".qt", "video/quicktime"}, + {".qti", "image/x-quicktime"}, + {".qtif", "image/x-quicktime"}, + {".qtl", "application/x-quicktimeplayer"}, + {".qxd", "application/octet-stream"}, + {".ra", "audio/x-pn-realaudio"}, + {".ram", "audio/x-pn-realaudio"}, + {".rar", "application/x-rar-compressed"}, + {".ras", "image/x-cmu-raster"}, + {".rat", "application/rat-file"}, + {".rc", "text/plain"}, + {".rc2", "text/plain"}, + {".rct", "text/plain"}, + {".rdlc", "application/xml"}, + {".reg", "text/plain"}, + {".resx", "application/xml"}, + {".rf", "image/vnd.rn-realflash"}, + {".rgb", "image/x-rgb"}, + {".rgs", "text/plain"}, + {".rm", "application/vnd.rn-realmedia"}, + {".rmi", "audio/mid"}, + {".rmp", "application/vnd.rn-rn_music_package"}, + {".rmvb", "application/vnd.rn-realmedia-vbr"}, + {".roff", "application/x-troff"}, + {".rpm", "audio/x-pn-realaudio-plugin"}, + {".rqy", "text/x-ms-rqy"}, + {".rtf", "application/rtf"}, + {".rtx", "text/richtext"}, + {".rvt", "application/octet-stream"}, + {".ruleset", "application/xml"}, + {".s", "text/plain"}, + {".safariextz", "application/x-safari-safariextz"}, + {".scd", "application/x-msschedule"}, + {".scr", "text/plain"}, + {".sct", "text/scriptlet"}, + {".sd2", "audio/x-sd2"}, + {".sdp", "application/sdp"}, + {".sea", "application/octet-stream"}, + {".searchConnector-ms", "application/windows-search-connector+xml"}, + {".setpay", "application/set-payment-initiation"}, + {".setreg", "application/set-registration-initiation"}, + {".settings", "application/xml"}, + {".sgimb", "application/x-sgimb"}, + {".sgml", "text/sgml"}, + {".sh", "application/x-sh"}, + {".shar", "application/x-shar"}, + {".shtml", "text/html"}, + {".sit", "application/x-stuffit"}, + {".sitemap", "application/xml"}, + {".skin", "application/xml"}, + {".skp", "application/x-koan"}, + {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"}, + {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, + {".slk", "application/vnd.ms-excel"}, + {".sln", "text/plain"}, + {".slupkg-ms", "application/x-ms-license"}, + {".smd", "audio/x-smd"}, + {".smi", "application/octet-stream"}, + {".smx", "audio/x-smd"}, + {".smz", "audio/x-smd"}, + {".snd", "audio/basic"}, + {".snippet", "application/xml"}, + {".snp", "application/octet-stream"}, + {".sql", "application/sql"}, + {".sol", "text/plain"}, + {".sor", "text/plain"}, + {".spc", "application/x-pkcs7-certificates"}, + {".spl", "application/futuresplash"}, + {".spx", "audio/ogg"}, + {".src", "application/x-wais-source"}, + {".srf", "text/plain"}, + {".SSISDeploymentManifest", "text/xml"}, + {".ssm", "application/streamingmedia"}, + {".sst", "application/vnd.ms-pki.certstore"}, + {".stl", "application/vnd.ms-pki.stl"}, + {".sv4cpio", "application/x-sv4cpio"}, + {".sv4crc", "application/x-sv4crc"}, + {".svc", "application/xml"}, + {".svg", "image/svg+xml"}, + {".swf", "application/x-shockwave-flash"}, + {".step", "application/step"}, + {".stp", "application/step"}, + {".t", "application/x-troff"}, + {".tar", "application/x-tar"}, + {".tcl", "application/x-tcl"}, + {".testrunconfig", "application/xml"}, + {".testsettings", "application/xml"}, + {".tex", "application/x-tex"}, + {".texi", "application/x-texinfo"}, + {".texinfo", "application/x-texinfo"}, + {".tgz", "application/x-compressed"}, + {".thmx", "application/vnd.ms-officetheme"}, + {".thn", "application/octet-stream"}, + {".tif", "image/tiff"}, + {".tiff", "image/tiff"}, + {".tlh", "text/plain"}, + {".tli", "text/plain"}, + {".toc", "application/octet-stream"}, + {".tr", "application/x-troff"}, + {".trm", "application/x-msterminal"}, + {".trx", "application/xml"}, + {".ts", "video/vnd.dlna.mpeg-tts"}, + {".tsv", "text/tab-separated-values"}, + {".ttf", "application/font-sfnt"}, + {".tts", "video/vnd.dlna.mpeg-tts"}, + {".txt", "text/plain"}, + {".u32", "application/octet-stream"}, + {".uls", "text/iuls"}, + {".user", "text/plain"}, + {".ustar", "application/x-ustar"}, + {".vb", "text/plain"}, + {".vbdproj", "text/plain"}, + {".vbk", "video/mpeg"}, + {".vbproj", "text/plain"}, + {".vbs", "text/vbscript"}, + {".vcf", "text/x-vcard"}, + {".vcproj", "application/xml"}, + {".vcs", "text/plain"}, + {".vcxproj", "application/xml"}, + {".vddproj", "text/plain"}, + {".vdp", "text/plain"}, + {".vdproj", "text/plain"}, + {".vdx", "application/vnd.ms-visio.viewer"}, + {".vml", "text/xml"}, + {".vscontent", "application/xml"}, + {".vsct", "text/xml"}, + {".vsd", "application/vnd.visio"}, + {".vsdx", "application/vnd.ms-visio.viewer"}, + {".vsi", "application/ms-vsi"}, + {".vsix", "application/vsix"}, + {".vsixlangpack", "text/xml"}, + {".vsixmanifest", "text/xml"}, + {".vsmdi", "application/xml"}, + {".vspscc", "text/plain"}, + {".vss", "application/vnd.visio"}, + {".vsscc", "text/plain"}, + {".vssettings", "text/xml"}, + {".vssscc", "text/plain"}, + {".vst", "application/vnd.visio"}, + {".vstemplate", "text/xml"}, + {".vsto", "application/x-ms-vsto"}, + {".vsw", "application/vnd.visio"}, + {".vsx", "application/vnd.visio"}, + {".vtt", "text/vtt"}, + {".vtx", "application/vnd.visio"}, + {".wasm", "application/wasm"}, + {".wav", "audio/wav"}, + {".wave", "audio/wav"}, + {".wax", "audio/x-ms-wax"}, + {".wbk", "application/msword"}, + {".wbmp", "image/vnd.wap.wbmp"}, + {".wcm", "application/vnd.ms-works"}, + {".wdb", "application/vnd.ms-works"}, + {".wdp", "image/vnd.ms-photo"}, + {".webarchive", "application/x-safari-webarchive"}, + {".webm", "video/webm"}, + {".webp", "image/webp"}, /* https://en.wikipedia.org/wiki/WebP */ + {".webtest", "application/xml"}, + {".wiq", "application/xml"}, + {".wiz", "application/msword"}, + {".wks", "application/vnd.ms-works"}, + {".WLMP", "application/wlmoviemaker"}, + {".wlpginstall", "application/x-wlpg-detect"}, + {".wlpginstall3", "application/x-wlpg3-detect"}, + {".wm", "video/x-ms-wm"}, + {".wma", "audio/x-ms-wma"}, + {".wmd", "application/x-ms-wmd"}, + {".wmf", "application/x-msmetafile"}, + {".wml", "text/vnd.wap.wml"}, + {".wmlc", "application/vnd.wap.wmlc"}, + {".wmls", "text/vnd.wap.wmlscript"}, + {".wmlsc", "application/vnd.wap.wmlscriptc"}, + {".wmp", "video/x-ms-wmp"}, + {".wmv", "video/x-ms-wmv"}, + {".wmx", "video/x-ms-wmx"}, + {".wmz", "application/x-ms-wmz"}, + {".woff", "application/font-woff"}, + {".woff2", "application/font-woff2"}, + {".wpl", "application/vnd.ms-wpl"}, + {".wps", "application/vnd.ms-works"}, + {".wri", "application/x-mswrite"}, + {".wrl", "x-world/x-vrml"}, + {".wrz", "x-world/x-vrml"}, + {".wsc", "text/scriptlet"}, + {".wsdl", "text/xml"}, + {".wvx", "video/x-ms-wvx"}, + {".x", "application/directx"}, + {".xaf", "x-world/x-vrml"}, + {".xaml", "application/xaml+xml"}, + {".xap", "application/x-silverlight-app"}, + {".xbap", "application/x-ms-xbap"}, + {".xbm", "image/x-xbitmap"}, + {".xdr", "text/plain"}, + {".xht", "application/xhtml+xml"}, + {".xhtml", "application/xhtml+xml"}, + {".xla", "application/vnd.ms-excel"}, + {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, + {".xlc", "application/vnd.ms-excel"}, + {".xld", "application/vnd.ms-excel"}, + {".xlk", "application/vnd.ms-excel"}, + {".xll", "application/vnd.ms-excel"}, + {".xlm", "application/vnd.ms-excel"}, + {".xls", "application/vnd.ms-excel"}, + {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, + {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + {".xlt", "application/vnd.ms-excel"}, + {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, + {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + {".xlw", "application/vnd.ms-excel"}, + {".xml", "text/xml"}, + {".xmp", "application/octet-stream"}, + {".xmta", "application/xml"}, + {".xof", "x-world/x-vrml"}, + {".XOML", "text/plain"}, + {".xpm", "image/x-xpixmap"}, + {".xps", "application/vnd.ms-xpsdocument"}, + {".xrm-ms", "text/xml"}, + {".xsc", "application/xml"}, + {".xsd", "text/xml"}, + {".xsf", "text/xml"}, + {".xsl", "text/xml"}, + {".xslt", "text/xml"}, + {".xsn", "application/octet-stream"}, + {".xss", "application/xml"}, + {".xspf", "application/xspf+xml"}, + {".xtp", "application/octet-stream"}, + {".xwd", "image/x-xwindowdump"}, + {".z", "application/x-compress"}, + {".zip", "application/zip"}, + + {"application/fsharp-script", ".fsx"}, + {"application/msaccess", ".adp"}, + {"application/msword", ".doc"}, + {"application/octet-stream", ".bin"}, + {"application/onenote", ".one"}, + {"application/postscript", ".eps"}, + {"application/step", ".step"}, + {"application/vnd.apple.keynote", ".key"}, + {"application/vnd.apple.numbers", ".numbers"}, + {"application/vnd.apple.pages", ".pages"}, + {"application/vnd.ms-excel", ".xls"}, + {"application/vnd.ms-powerpoint", ".ppt"}, + {"application/vnd.ms-works", ".wks"}, + {"application/vnd.visio", ".vsd"}, + {"application/x-director", ".dir"}, + {"application/x-msdos-program", ".exe"}, + {"application/x-shockwave-flash", ".swf"}, + {"application/x-x509-ca-cert", ".cer"}, + {"application/x-zip-compressed", ".zip"}, + {"application/xhtml+xml", ".xhtml"}, + {"application/x-iwork-keynote-sffkey", ".key"}, + {"application/x-iwork-numbers-sffnumbers", ".numbers"}, + {"application/x-iwork-pages-sffpages", ".pages"}, + {"application/xml", ".xml"}, // anomaly, .xml -> text/xml, but application/xml -> many things, but all are xml, so safest is .xml + {"audio/aac", ".AAC"}, + {"audio/aiff", ".aiff"}, + {"audio/basic", ".snd"}, + {"audio/mid", ".midi"}, + {"audio/mp4", ".m4a"}, // one way mapping only, mime -> ext + {"audio/ogg", ".ogg"}, + {"audio/ogg; codecs=opus", ".opus"}, + {"audio/wav", ".wav"}, + {"audio/x-m4a", ".m4a"}, + {"audio/x-mpegurl", ".m3u"}, + {"audio/x-pn-realaudio", ".ra"}, + {"audio/x-smd", ".smd"}, + {"image/bmp", ".bmp"}, + {"image/heic", ".heic"}, + {"image/heif", ".heif"}, + {"image/jpeg", ".jpg"}, + {"image/pict", ".pic"}, + {"image/png", ".png"}, // Defined in [RFC-2045], [RFC-2048] + {"image/x-png", ".png"}, // See https://www.w3.org/TR/PNG/#A-Media-type :"It is recommended that implementations also recognize the media type "image/x-png"." + {"image/tiff", ".tiff"}, + {"image/x-macpaint", ".mac"}, + {"image/x-quicktime", ".qti"}, + {"message/rfc822", ".eml"}, + {"text/calendar", ".ics"}, + {"text/html", ".html"}, + {"text/plain", ".txt"}, + {"text/scriptlet", ".wsc"}, + {"text/xml", ".xml"}, + {"video/3gpp", ".3gp"}, + {"video/3gpp2", ".3gp2"}, + {"video/mp4", ".mp4"}, + {"video/mpeg", ".mpg"}, + {"video/quicktime", ".mov"}, + {"video/vnd.dlna.mpeg-tts", ".m2t"}, + {"video/x-dv", ".dv"}, + {"video/x-la-asf", ".lsf"}, + {"video/x-ms-asf", ".asf"}, + {"x-world/x-vrml", ".xof"}, + + #endregion + + }; + + var cache = mappings.ToList(); // need ToList() to avoid modifying while still enumerating + + foreach (var mapping in cache) + { + if (!mappings.ContainsKey(mapping.Value)) + { + mappings.Add(mapping.Value, mapping.Key); + } + } + + return mappings; + } + + /// + /// Tries to get the type of the MIME from the provided string. + /// + /// The filename or extension. + /// The variable to store the MIME type. + /// The MIME type. + /// + public static bool TryGetMimeType(string str, out string mimeType) + { + if (str == null) { + throw new ArgumentNullException(nameof(str)); + } + + var indexQuestionMark = str.IndexOf(QuestionMark, StringComparison.Ordinal); + if (indexQuestionMark != -1) + { + str = str.Remove(indexQuestionMark); + } + + + if (!str.StartsWith(Dot)) + { + var index = str.LastIndexOf(Dot); + if (index != -1 && str.Length > index + 1) + { + str = str.Substring(index + 1); + } + + str = Dot + str; + } + + return Mappings.Value.TryGetValue(str, out mimeType); + } + + /// + /// Gets the type of the MIME from the provided string. + /// + /// The filename or extension. + /// The MIME type. + /// + public static string GetMimeType(string str) + { + return MimeTypeMap.TryGetMimeType(str, out var result) ? result : DefaultMimeType; + } + + /// + /// Gets the extension from the provided MIME type. + /// + /// Type of the MIME. + /// if set to true, throws error if extension's not found. + /// The extension. + /// + /// + public static string GetExtension(string mimeType, bool throwErrorIfNotFound = true) + { + if (mimeType == null) + { + throw new ArgumentNullException(nameof(mimeType)); + } + + if (mimeType.StartsWith(Dot)) + { + throw new ArgumentException("Requested mime type is not valid: " + mimeType); + } + + if (Mappings.Value.TryGetValue(mimeType, out string extension)) + { + return extension; + } + + if (throwErrorIfNotFound) + { + throw new ArgumentException("Requested mime type is not registered: " + mimeType); + } + + return string.Empty; + } + } +} diff --git a/services/bytefy.image/bytefy.image/Program.cs b/services/bytefy.image/bytefy.image/Program.cs new file mode 100644 index 0000000..b23d890 --- /dev/null +++ b/services/bytefy.image/bytefy.image/Program.cs @@ -0,0 +1,49 @@ +using ImageMagick; +using Microsoft.AspNetCore.Antiforgery; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddAntiforgery(options => options.HeaderName = "2311d8d8-607d-4747-8939-1bde65643254"); +var app = builder.Build(); + +app.UseAntiforgery(); + +app.MapPost("/convert/{format}", async (IFormFile image, string format) => +{ + try + { + if (!Enum.TryParse(format, true, out MagickFormat magickFormat) || magickFormat == MagickFormat.Unknown) + return Results.BadRequest("Invalid format"); + + if (image == null || image.Length == 0) + return Results.BadRequest("No image provided"); + + if (image.Length > 20 * 1024 * 1024) + throw new Exception("Image size too large"); + + using var memoryStream = new MemoryStream(); + await image.CopyToAsync(memoryStream); + var magickImage = new MagickImage(memoryStream.ToArray()); + magickImage.Format = magickFormat; + + var resultStream = new MemoryStream(); + magickImage.Write(resultStream); + resultStream.Position = 0; + + var mimeType = MimeTypes.MimeTypeMap.GetMimeType($"image/{magickFormat.ToString().ToLower()}"); + var fileName = Path.GetFileNameWithoutExtension(image.FileName); + + return Results.File(resultStream, mimeType, fileDownloadName: $"{fileName}.{magickFormat.ToString().ToLower()}"); + } + catch (NotSupportedException) { + return Results.BadRequest(); + } +}); + +app.MapGet("/antiforgery/token", (IAntiforgery forgeryService, HttpContext context) => +{ + var tokens = forgeryService.GetAndStoreTokens(context); + var xsrfToken = tokens.RequestToken!; + return TypedResults.Content(xsrfToken, "text/plain"); +}); + +app.Run(); \ No newline at end of file diff --git a/services/bytefy.image/bytefy.image/Properties/launchSettings.json b/services/bytefy.image/bytefy.image/Properties/launchSettings.json new file mode 100644 index 0000000..a4f04f1 --- /dev/null +++ b/services/bytefy.image/bytefy.image/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "todos", + "applicationUrl": "http://localhost:1337", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/services/bytefy.image/bytefy.image/appsettings.Development.json b/services/bytefy.image/bytefy.image/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/services/bytefy.image/bytefy.image/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/services/bytefy.image/bytefy.image/appsettings.json b/services/bytefy.image/bytefy.image/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/services/bytefy.image/bytefy.image/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/services/bytefy.image/bytefy.image/bytefy.image.csproj b/services/bytefy.image/bytefy.image/bytefy.image.csproj new file mode 100644 index 0000000..62444e4 --- /dev/null +++ b/services/bytefy.image/bytefy.image/bytefy.image.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + true + true + Linux + + + + + .dockerignore + + + + + + + + + diff --git a/services/bytefy.image/bytefy.image/bytefy.image.http b/services/bytefy.image/bytefy.image/bytefy.image.http new file mode 100644 index 0000000..560ce82 --- /dev/null +++ b/services/bytefy.image/bytefy.image/bytefy.image.http @@ -0,0 +1,11 @@ +@bytefy.image_HostAddress = http://localhost:1337 + +GET {{bytefy.image_HostAddress}}/ +Accept: application/json + +### + +GET {{bytefy.image_HostAddress}}/1 +Accept: application/json + +### diff --git a/services/bytefy.image/docker-compose.yml b/services/bytefy.image/docker-compose.yml new file mode 100644 index 0000000..6430a10 --- /dev/null +++ b/services/bytefy.image/docker-compose.yml @@ -0,0 +1,6 @@ +services: + bytefy.image: + image: bytefy.image + build: + context: . + dockerfile: bytefy.image/Dockerfile diff --git a/.editorconfig b/tools/.editorconfig similarity index 100% rename from .editorconfig rename to tools/.editorconfig diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..cc7b141 --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,42 @@ +# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/README.md b/tools/README.md similarity index 100% rename from README.md rename to tools/README.md diff --git a/angular.json b/tools/angular.json similarity index 100% rename from angular.json rename to tools/angular.json diff --git a/package-lock.json b/tools/package-lock.json similarity index 100% rename from package-lock.json rename to tools/package-lock.json diff --git a/package.json b/tools/package.json similarity index 100% rename from package.json rename to tools/package.json diff --git a/src/app/app.component.html b/tools/src/app/app.component.html similarity index 100% rename from src/app/app.component.html rename to tools/src/app/app.component.html diff --git a/src/app/app.component.scss b/tools/src/app/app.component.scss similarity index 100% rename from src/app/app.component.scss rename to tools/src/app/app.component.scss diff --git a/src/app/app.component.spec.ts b/tools/src/app/app.component.spec.ts similarity index 100% rename from src/app/app.component.spec.ts rename to tools/src/app/app.component.spec.ts diff --git a/src/app/app.component.ts b/tools/src/app/app.component.ts similarity index 100% rename from src/app/app.component.ts rename to tools/src/app/app.component.ts diff --git a/src/app/app.config.ts b/tools/src/app/app.config.ts similarity index 100% rename from src/app/app.config.ts rename to tools/src/app/app.config.ts diff --git a/src/app/app.routes.ts b/tools/src/app/app.routes.ts similarity index 100% rename from src/app/app.routes.ts rename to tools/src/app/app.routes.ts diff --git a/src/app/header/header.component.html b/tools/src/app/header/header.component.html similarity index 100% rename from src/app/header/header.component.html rename to tools/src/app/header/header.component.html diff --git a/src/app/header/header.component.scss b/tools/src/app/header/header.component.scss similarity index 100% rename from src/app/header/header.component.scss rename to tools/src/app/header/header.component.scss diff --git a/src/app/header/header.component.spec.ts b/tools/src/app/header/header.component.spec.ts similarity index 100% rename from src/app/header/header.component.spec.ts rename to tools/src/app/header/header.component.spec.ts diff --git a/src/app/header/header.component.ts b/tools/src/app/header/header.component.ts similarity index 100% rename from src/app/header/header.component.ts rename to tools/src/app/header/header.component.ts diff --git a/src/app/shared/dual-textarea/dual-textarea.component.html b/tools/src/app/shared/dual-textarea/dual-textarea.component.html similarity index 100% rename from src/app/shared/dual-textarea/dual-textarea.component.html rename to tools/src/app/shared/dual-textarea/dual-textarea.component.html diff --git a/src/app/shared/dual-textarea/dual-textarea.component.scss b/tools/src/app/shared/dual-textarea/dual-textarea.component.scss similarity index 100% rename from src/app/shared/dual-textarea/dual-textarea.component.scss rename to tools/src/app/shared/dual-textarea/dual-textarea.component.scss diff --git a/src/app/shared/dual-textarea/dual-textarea.component.ts b/tools/src/app/shared/dual-textarea/dual-textarea.component.ts similarity index 100% rename from src/app/shared/dual-textarea/dual-textarea.component.ts rename to tools/src/app/shared/dual-textarea/dual-textarea.component.ts diff --git a/src/app/shared/upload/file-converter.component.html b/tools/src/app/shared/upload/file-converter.component.html similarity index 100% rename from src/app/shared/upload/file-converter.component.html rename to tools/src/app/shared/upload/file-converter.component.html diff --git a/src/app/shared/upload/file-converter.component.scss b/tools/src/app/shared/upload/file-converter.component.scss similarity index 100% rename from src/app/shared/upload/file-converter.component.scss rename to tools/src/app/shared/upload/file-converter.component.scss diff --git a/src/app/shared/upload/file-converter.component.ts b/tools/src/app/shared/upload/file-converter.component.ts similarity index 100% rename from src/app/shared/upload/file-converter.component.ts rename to tools/src/app/shared/upload/file-converter.component.ts diff --git a/src/assets/.gitkeep b/tools/src/assets/.gitkeep similarity index 100% rename from src/assets/.gitkeep rename to tools/src/assets/.gitkeep diff --git a/src/favicon.ico b/tools/src/favicon.ico similarity index 100% rename from src/favicon.ico rename to tools/src/favicon.ico diff --git a/src/index.html b/tools/src/index.html similarity index 100% rename from src/index.html rename to tools/src/index.html diff --git a/src/main.ts b/tools/src/main.ts similarity index 100% rename from src/main.ts rename to tools/src/main.ts diff --git a/src/styles.scss b/tools/src/styles.scss similarity index 100% rename from src/styles.scss rename to tools/src/styles.scss diff --git a/src/tools/ascii-to-text/ascii-to-text.component.html b/tools/src/tools/ascii-to-text/ascii-to-text.component.html similarity index 100% rename from src/tools/ascii-to-text/ascii-to-text.component.html rename to tools/src/tools/ascii-to-text/ascii-to-text.component.html diff --git a/src/tools/ascii-to-text/ascii-to-text.component.scss b/tools/src/tools/ascii-to-text/ascii-to-text.component.scss similarity index 100% rename from src/tools/ascii-to-text/ascii-to-text.component.scss rename to tools/src/tools/ascii-to-text/ascii-to-text.component.scss diff --git a/src/tools/ascii-to-text/ascii-to-text.component.ts b/tools/src/tools/ascii-to-text/ascii-to-text.component.ts similarity index 100% rename from src/tools/ascii-to-text/ascii-to-text.component.ts rename to tools/src/tools/ascii-to-text/ascii-to-text.component.ts diff --git a/src/tools/base64-converter/base64-converter.component.html b/tools/src/tools/base64-converter/base64-converter.component.html similarity index 100% rename from src/tools/base64-converter/base64-converter.component.html rename to tools/src/tools/base64-converter/base64-converter.component.html diff --git a/src/tools/base64-converter/base64-converter.component.scss b/tools/src/tools/base64-converter/base64-converter.component.scss similarity index 100% rename from src/tools/base64-converter/base64-converter.component.scss rename to tools/src/tools/base64-converter/base64-converter.component.scss diff --git a/src/tools/base64-converter/base64-converter.component.spec.ts b/tools/src/tools/base64-converter/base64-converter.component.spec.ts similarity index 100% rename from src/tools/base64-converter/base64-converter.component.spec.ts rename to tools/src/tools/base64-converter/base64-converter.component.spec.ts diff --git a/src/tools/base64-converter/base64-converter.component.ts b/tools/src/tools/base64-converter/base64-converter.component.ts similarity index 100% rename from src/tools/base64-converter/base64-converter.component.ts rename to tools/src/tools/base64-converter/base64-converter.component.ts diff --git a/src/tools/dds-to-png/dds-to-png.component.html b/tools/src/tools/dds-to-png/dds-to-png.component.html similarity index 100% rename from src/tools/dds-to-png/dds-to-png.component.html rename to tools/src/tools/dds-to-png/dds-to-png.component.html diff --git a/src/tools/dds-to-png/dds-to-png.component.scss b/tools/src/tools/dds-to-png/dds-to-png.component.scss similarity index 100% rename from src/tools/dds-to-png/dds-to-png.component.scss rename to tools/src/tools/dds-to-png/dds-to-png.component.scss diff --git a/src/tools/dds-to-png/dds-to-png.component.spec.ts b/tools/src/tools/dds-to-png/dds-to-png.component.spec.ts similarity index 100% rename from src/tools/dds-to-png/dds-to-png.component.spec.ts rename to tools/src/tools/dds-to-png/dds-to-png.component.spec.ts diff --git a/src/tools/dds-to-png/dds-to-png.component.ts b/tools/src/tools/dds-to-png/dds-to-png.component.ts similarity index 100% rename from src/tools/dds-to-png/dds-to-png.component.ts rename to tools/src/tools/dds-to-png/dds-to-png.component.ts diff --git a/src/tools/dds-to-png/dds-to-png.service.ts b/tools/src/tools/dds-to-png/dds-to-png.service.ts similarity index 100% rename from src/tools/dds-to-png/dds-to-png.service.ts rename to tools/src/tools/dds-to-png/dds-to-png.service.ts diff --git a/src/tools/guid/guid.component.html b/tools/src/tools/guid/guid.component.html similarity index 100% rename from src/tools/guid/guid.component.html rename to tools/src/tools/guid/guid.component.html diff --git a/src/tools/guid/guid.component.scss b/tools/src/tools/guid/guid.component.scss similarity index 100% rename from src/tools/guid/guid.component.scss rename to tools/src/tools/guid/guid.component.scss diff --git a/src/tools/guid/guid.component.ts b/tools/src/tools/guid/guid.component.ts similarity index 100% rename from src/tools/guid/guid.component.ts rename to tools/src/tools/guid/guid.component.ts diff --git a/src/tools/jwt-to-json/jwt-to-json.component.html b/tools/src/tools/jwt-to-json/jwt-to-json.component.html similarity index 100% rename from src/tools/jwt-to-json/jwt-to-json.component.html rename to tools/src/tools/jwt-to-json/jwt-to-json.component.html diff --git a/src/tools/jwt-to-json/jwt-to-json.component.scss b/tools/src/tools/jwt-to-json/jwt-to-json.component.scss similarity index 100% rename from src/tools/jwt-to-json/jwt-to-json.component.scss rename to tools/src/tools/jwt-to-json/jwt-to-json.component.scss diff --git a/src/tools/jwt-to-json/jwt-to-json.component.spec.ts b/tools/src/tools/jwt-to-json/jwt-to-json.component.spec.ts similarity index 100% rename from src/tools/jwt-to-json/jwt-to-json.component.spec.ts rename to tools/src/tools/jwt-to-json/jwt-to-json.component.spec.ts diff --git a/src/tools/jwt-to-json/jwt-to-json.component.ts b/tools/src/tools/jwt-to-json/jwt-to-json.component.ts similarity index 100% rename from src/tools/jwt-to-json/jwt-to-json.component.ts rename to tools/src/tools/jwt-to-json/jwt-to-json.component.ts diff --git a/src/tools/text-to-cron/text-to-cron.component.html b/tools/src/tools/text-to-cron/text-to-cron.component.html similarity index 100% rename from src/tools/text-to-cron/text-to-cron.component.html rename to tools/src/tools/text-to-cron/text-to-cron.component.html diff --git a/src/tools/text-to-cron/text-to-cron.component.scss b/tools/src/tools/text-to-cron/text-to-cron.component.scss similarity index 100% rename from src/tools/text-to-cron/text-to-cron.component.scss rename to tools/src/tools/text-to-cron/text-to-cron.component.scss diff --git a/src/tools/text-to-cron/text-to-cron.component.spec.ts b/tools/src/tools/text-to-cron/text-to-cron.component.spec.ts similarity index 100% rename from src/tools/text-to-cron/text-to-cron.component.spec.ts rename to tools/src/tools/text-to-cron/text-to-cron.component.spec.ts diff --git a/src/tools/text-to-cron/text-to-cron.component.ts b/tools/src/tools/text-to-cron/text-to-cron.component.ts similarity index 100% rename from src/tools/text-to-cron/text-to-cron.component.ts rename to tools/src/tools/text-to-cron/text-to-cron.component.ts diff --git a/tsconfig.app.json b/tools/tsconfig.app.json similarity index 100% rename from tsconfig.app.json rename to tools/tsconfig.app.json diff --git a/tsconfig.json b/tools/tsconfig.json similarity index 100% rename from tsconfig.json rename to tools/tsconfig.json diff --git a/tsconfig.spec.json b/tools/tsconfig.spec.json similarity index 100% rename from tsconfig.spec.json rename to tools/tsconfig.spec.json