├── docker
├── orthanc
│ ├── .gitignore
│ ├── .dockerignore
│ ├── orthanc-defaults.json
│ ├── filter-http-tools-reset.lua
│ ├── env-var-non-standards.json
│ ├── Dockerfile.builder-vcpkg
│ ├── test_legacy.py
│ ├── docker-entrypoint.sh
│ ├── helpers.py
│ ├── Dockerfile.runner-base
│ ├── generateConfiguration.py
│ ├── test-aliveness.py
│ ├── generatePluginDoc.py
│ ├── test_current.py
│ ├── env-var-legacy.json
│ ├── Dockerfile.builder-base
│ └── plugins-def.json
├── integration-tests
│ ├── .gitignore
│ ├── .dockerignore
│ ├── orthanc-tests
│ │ ├── orthanc.json
│ │ ├── wait-for-it.sh
│ │ └── Dockerfile
│ ├── sql-server
│ │ ├── entrypoint.sh
│ │ ├── Dockerfile
│ │ └── create-database.sh
│ ├── docker-compose.sqlite.yml
│ ├── docker-compose.webdav.yml
│ ├── docker-compose.ingest-transcoding.yml
│ ├── docker-compose.wsi.yml
│ ├── docker-compose.sqlite-compression.yml
│ ├── docker-compose.transfers.yml
│ ├── docker-compose.sqlite-recycling.yml
│ ├── docker-compose.scu-transcoding.yml
│ ├── docker-compose.cget.yml
│ ├── docker-compose.dicomweb.yml
│ ├── docker-compose.worklists.yml
│ ├── docker-compose.odbc-sqlite.yml
│ ├── orthanc-transcoding-tests
│ │ └── Dockerfile
│ ├── docker-compose.odbc-postgres.yml
│ ├── orthanc-under-tests
│ │ ├── odbc.ini
│ │ ├── Dockerfile.mssql
│ │ ├── Dockerfile
│ │ └── orthanc.json
│ ├── docker-compose.postgres-recycling.yml
│ ├── docker-compose.postgres-read-committed.yml
│ ├── docker-compose.postgres-serializable.yml
│ ├── docker-compose.postgres-dicomweb.yml
│ ├── docker-compose.odbc-mysql.yml
│ ├── docker-compose.mysql.yml
│ ├── docker-compose.tls-check-client.yml
│ ├── docker-compose.odbc-sql-server.yml
│ ├── docker-compose.tls-no-check-client.yml
│ └── docker-compose.s3.yml
└── SBOM.txt
├── .github
├── buildkitd.toml
└── workflows
│ ├── pre-build.yml
│ ├── build-stone-wasm.yml
│ ├── build-volview-dist.yml
│ ├── build-macos-package.yml
│ ├── build-windows-installer.yml
│ ├── build-macos-binaries.yml
│ ├── build-win-binaries.yml
│ ├── run-docker-integ-tests.yml
│ ├── build-all-dockers.yml
│ └── all-builds.yml
├── WindowsInstaller
├── .gitignore
├── Resources
│ ├── tcia.json
│ ├── pixels-masker.json
│ ├── Orthanc.ico
│ ├── Osimis.ico
│ ├── OrthancH.png
│ ├── OsimisLogo.png
│ ├── OsimisWizard.bmp
│ ├── OsimisWizard.png
│ ├── OrthancWizard.bmp
│ ├── OrthancWizard.png
│ ├── OrthancWizardLogo.bmp
│ ├── OsimisLogoShadow.png
│ ├── OsimisWizardLogo.bmp
│ ├── delayed-deletion.json
│ ├── indexer.json
│ ├── advanced-storage.json
│ ├── osimis-webviewer.json
│ ├── worklists.json
│ ├── orthanc-explorer-2.json
│ ├── odbc.json
│ ├── serve-folders.json
│ ├── transfers.json
│ ├── CMake
│ │ ├── MinGW-W64-Toolchain32.cmake
│ │ ├── DownloadPackage.cmake
│ │ └── Compiler.cmake
│ ├── mysql.json
│ ├── dicomweb.json
│ ├── webviewer.json
│ ├── azure.json
│ ├── postgresql.json
│ ├── aws-s3.json
│ ├── housekeeper.json
│ ├── README.txt
│ └── stone-webviewer.json
├── AppProcessMessages.iss
├── Dockerfile
├── Configuration
│ ├── Toolbox.h
│ ├── CMakeLists.txt
│ ├── Toolbox.cpp
│ └── PatchDefaultConfiguration.cpp
├── ciBuildWindowsInstaller.sh
├── NOTES.txt
└── ServiceControl.iss
├── orthancBuildResources
├── startOrthanc.command
├── configMacOS.json
└── readmeMacOS.txt
├── .gitignore
├── release-notes-docker-images.txt
├── UCLouvain
├── Toolbox.py
└── CreateMacOSPackage.py
├── github-mirrors
├── sync-all.sh
└── mirror-helpers.sh
├── release-procedure.txt
├── README-dockerhub.md
├── README.md
└── bash-helpers.sh
/docker/orthanc/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | tmp/
--------------------------------------------------------------------------------
/.github/buildkitd.toml:
--------------------------------------------------------------------------------
1 | [worker.oci]
2 | max-parallelism = 4
--------------------------------------------------------------------------------
/WindowsInstaller/.gitignore:
--------------------------------------------------------------------------------
1 | orthanc.json
2 | *.exe
3 |
4 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/tcia.json:
--------------------------------------------------------------------------------
1 | {
2 | "Tcia" : {
3 | "Enable" : true
4 | }
5 | }
--------------------------------------------------------------------------------
/docker/integration-tests/.gitignore:
--------------------------------------------------------------------------------
1 | orthanc-tests-repo
2 | orthanc-tests-repo-full
3 | orthanc-tests-repo-normal
--------------------------------------------------------------------------------
/orthancBuildResources/startOrthanc.command:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cd "$(dirname "$0")"
3 | ./Orthanc configMacOS.json
4 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/pixels-masker.json:
--------------------------------------------------------------------------------
1 | {
2 | "PixelsMasker" : {
3 | "Enable": false
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/docker/integration-tests/.dockerignore:
--------------------------------------------------------------------------------
1 | *.yml
2 | run-integration-tests.sh
3 | orthanc-tests-repo-normal/*
4 | orthanc-tests-repo-full/*
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-tests/orthanc.json:
--------------------------------------------------------------------------------
1 | {
2 | "RemoteAccessAllowed": true,
3 | "AuthenticationEnabled": false
4 | }
5 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/Orthanc.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/Orthanc.ico
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/Osimis.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/Osimis.ico
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OrthancH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OrthancH.png
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OsimisLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OsimisLogo.png
--------------------------------------------------------------------------------
/docker/orthanc/.dockerignore:
--------------------------------------------------------------------------------
1 | generatePluginDoc.py
2 | Dockerfile
3 | Dockerfile.runner-base
4 | Dockerfile.builder-base
5 | Dockerfile.builder-vcpkg
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OsimisWizard.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OsimisWizard.bmp
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OsimisWizard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OsimisWizard.png
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OrthancWizard.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OrthancWizard.bmp
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OrthancWizard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OrthancWizard.png
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OrthancWizardLogo.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OrthancWizardLogo.bmp
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OsimisLogoShadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OsimisLogoShadow.png
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/OsimisWizardLogo.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orthanc-server/orthanc-builder/HEAD/WindowsInstaller/Resources/OsimisWizardLogo.bmp
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | WindowsInstaller/Configuration/ThirdPartyDownloads/
3 | *~
4 | UCLouvain/__pycache__/
5 | github-mirrors/mirrors/
6 | github-mirrors/.env/
7 |
--------------------------------------------------------------------------------
/docker/integration-tests/sql-server/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #start SQL Server, start the script to create the DB
2 | /scripts/create-database.sh &
3 | /opt/mssql/bin/sqlservr
4 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/delayed-deletion.json:
--------------------------------------------------------------------------------
1 | {
2 | "DelayedDeletion" : {
3 | "Enable": false
4 | // "ThrottleDelayMs": 0,
5 | // "Path": ""
6 | }
7 | }
--------------------------------------------------------------------------------
/release-notes-docker-images.txt:
--------------------------------------------------------------------------------
1 | Note: the release notes are now in Markdown and have moved here: https://github.com/orthanc-server/orthanc-builder/blob/master/release-notes-docker-images.md
2 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.sqlite.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 |
6 | orthanc-tests:
7 | image: orthanc-tests
8 | depends_on:
9 | - orthanc-under-tests
10 |
11 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.webdav.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 |
6 | orthanc-tests-webdav:
7 | image: orthanc-tests-webdav
8 | depends_on:
9 | - orthanc-under-tests
10 |
11 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/indexer.json:
--------------------------------------------------------------------------------
1 | {
2 | "Indexer" : {
3 | "Enable" : false,
4 | "Folders" : [], // List of folders to synchronize
5 | "Interval" : 10 // Delay between two synchronizations
6 | }
7 | }
--------------------------------------------------------------------------------
/docker/integration-tests/sql-server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/mssql/server:2019-latest
2 |
3 | USER root
4 | RUN mkdir /scripts
5 |
6 | COPY create-database.sh /scripts/
7 | COPY entrypoint.sh /scripts/
8 |
9 | USER mssql
10 | ENTRYPOINT /bin/bash ./scripts/entrypoint.sh
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/advanced-storage.json:
--------------------------------------------------------------------------------
1 | {
2 | "AdvancedStorage" : {
3 | "Enable": false
4 |
5 | // more configurations options available ... check
6 | // https://github.com/orthanc-server/orthanc-advanced-storage/blob/master/Plugin/Configuration.json
7 | }
8 | }
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.ingest-transcoding.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-transcoding-tests
5 | environment:
6 | # VERBOSE_STARTUP: "true"
7 | # VERBOSE_ENABLED: "true"
8 | GDCM_PLUGIN_ENABLED: "false"
9 |
10 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/osimis-webviewer.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * WebViewer configuration. Check https://osimis.atlassian.net/wiki/spaces/OKB/pages/10321921/Osimis+Web+Viewer+-+Configuration+file
4 | for a description of all options
5 | **/
6 |
7 | "WebViewer" : {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/worklists.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * Configuration of the ModalityWorklists plugin, that can be used
4 | * to serve DICOM modality worklists.
5 | **/
6 | "Worklists" : {
7 | "Enable": false,
8 | "Database": "/var/lib/orthanc/worklists"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.wsi.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | WSI_PLUGIN_ENABLED: "true"
7 |
8 | orthanc-tests-wsi:
9 | image: orthanc-tests-wsi
10 | depends_on:
11 | - orthanc-under-tests
12 |
13 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.sqlite-compression.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | - ORTHANC__STORAGE_COMPRESSION=true
7 |
8 | orthanc-tests:
9 | image: orthanc-tests
10 | depends_on:
11 | - orthanc-under-tests
12 |
13 |
--------------------------------------------------------------------------------
/docker/orthanc/orthanc-defaults.json:
--------------------------------------------------------------------------------
1 | {
2 | "StorageDirectory" : "/var/lib/orthanc/db",
3 |
4 | "RemoteAccessAllowed": true,
5 | "AuthenticationEnabled": true,
6 |
7 | "HttpsCACertificates" : "/etc/ssl/certs/ca-certificates.crt",
8 |
9 | "Plugins" : ["/run/orthanc/plugins", "/usr/share/orthanc/plugins"]
10 | }
11 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/orthanc-explorer-2.json:
--------------------------------------------------------------------------------
1 | {
2 | "OrthancExplorer2" : {
3 | "Enable": true,
4 | "IsDefaultOrthancUI": true
5 |
6 | // more configurations options available ... check
7 | // https://github.com/orthanc-server/orthanc-explorer-2/blob/master/Plugin/DefaultConfiguration.json
8 | }
9 | }
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.transfers.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | TRANSFERS_PLUGIN_ENABLED: "true"
7 |
8 | orthanc-tests-transfers:
9 | image: orthanc-tests-transfers
10 | depends_on:
11 | - orthanc-under-tests
12 |
13 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.sqlite-recycling.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | ORTHANC__MAXIMUM_PATIENT_COUNT: "4"
7 |
8 | orthanc-tests-recycling:
9 | image: orthanc-tests-recycling
10 | depends_on:
11 | - orthanc-under-tests
12 |
13 |
--------------------------------------------------------------------------------
/docker/orthanc/filter-http-tools-reset.lua:
--------------------------------------------------------------------------------
1 | function IncomingHttpRequestFilter(method, uri, ip, username, httpHeaders)
2 |
3 | if method == 'POST' and uri == '/tools/reset' then
4 | -- regenerate the /tmp/orthanc.json before reseting orthanc
5 | os.execute("cd /startup && python3 generateConfiguration.py")
6 | end
7 |
8 | return true
9 | end
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.scu-transcoding.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-transcoding-tests
5 | environment:
6 | # VERBOSE_STARTUP: "true"
7 | # VERBOSE_ENABLED: "true"
8 | GDCM_PLUGIN_ENABLED: "false"
9 | entrypoint: "python3 /orthanc-tests/Tests/CheckScuTranscoding.py /usr/local/bin/Orthanc"
10 |
11 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.cget.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | VERBOSE_STARTUP: "true"
7 | # VERBOSE_ENABLED: "true"
8 | # GDCM_PLUGIN_ENABLED: "false"
9 |
10 | orthanc-tests-cget:
11 | image: orthanc-tests-cget
12 | depends_on:
13 | - orthanc-under-tests
14 |
15 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.dicomweb.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | # VERBOSE_STARTUP: "true"
7 | # VERBOSE_ENABLED: "true"
8 | GDCM_PLUGIN_ENABLED: "false"
9 |
10 | orthanc-tests-dicomweb:
11 | image: orthanc-tests-dicomweb
12 | depends_on:
13 | - orthanc-under-tests
14 |
15 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.worklists.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | volumes:
6 | - wl-volume:/worklists:ro
7 | environment:
8 | ORTHANC__WORKLISTS__FILTER_ISSUER_AET: "false"
9 |
10 | orthanc-tests-worklists:
11 | image: orthanc-tests-worklists
12 | depends_on:
13 | - orthanc-under-tests
14 | volumes:
15 | - wl-volume:/tests/orthanc-tests//Database/Worklists/Working
16 | volumes:
17 | wl-volume:
18 |
19 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.odbc-sqlite.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | environment:
6 | ORTHANC__ODBC__INDEX_CONNECTION_STRING: "DSN=sqlite3index"
7 | ORTHANC__ODBC__STORAGE_CONNECTION_STRING: "DSN=sqlite3storage"
8 | ORTHANC__ODBC__ENABLE_INDEX: "true"
9 | ORTHANC__ODBC__ENABLE_STORAGE: "true"
10 | # VERBOSE_ENABLED: "true"
11 | VERBOSE_STARTUP: "true"
12 |
13 | orthanc-tests:
14 | image: orthanc-tests
15 | depends_on:
16 | - orthanc-under-tests
17 |
--------------------------------------------------------------------------------
/orthancBuildResources/configMacOS.json:
--------------------------------------------------------------------------------
1 | {
2 | // The reference of the Orthanc configuration file is available at:
3 | // https://orthanc.uclouvain.be/hg/orthanc/file/default/OrthancServer/Resources/Configuration.json
4 | "Name" : "MyOrthanc",
5 |
6 | // Load all the Orthanc plugins that are available in this folder:
7 | "Plugins" : [ "." ],
8 |
9 | // Orthanc Explorer 2 configuration. Reference is available at:
10 | // https://github.com/orthanc-server/orthanc-explorer-2/blob/master/Plugin/DefaultConfiguration.json
11 | "OrthancExplorer2" : {
12 | "Enable": true,
13 | "IsDefaultOrthancUI": false
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-transcoding-tests/Dockerfile:
--------------------------------------------------------------------------------
1 | ######################################
2 | ARG IMAGE_UNDER_TEST=orthancteam/orthanc:latest
3 | FROM $IMAGE_UNDER_TEST
4 |
5 | RUN apt-get update
6 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install dcmtk mercurial
7 | RUN pip install httplib2 --break-system-package
8 | RUN pip install pillow --break-system-package
9 |
10 | WORKDIR /
11 |
12 | ARG ORTHANC_TESTS_REVISION=default
13 | RUN hg clone https://orthanc.uclouvain.be/hg/orthanc-tests/ -r $ORTHANC_TESTS_REVISION
14 |
15 | ENTRYPOINT python3 /orthanc-tests/Tests/CheckIngestTranscoding.py /usr/local/bin/Orthanc
16 |
--------------------------------------------------------------------------------
/docker/integration-tests/sql-server/create-database.sh:
--------------------------------------------------------------------------------
1 | #run the setup script to create the DB and the schema in the DB
2 | #do this in a loop because the timing for when the SQL instance is ready is indeterminate
3 | echo "----------------- creating database ---------------------------------"
4 |
5 | for i in {1..50};
6 | do
7 | /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P MyStrOngPa55word! -No -Q 'CREATE DATABASE orthanctest'
8 | if [ $? -eq 0 ]
9 | then
10 | echo "----------------- database created"
11 | break
12 | else
13 | echo "----------------- not ready yet..."
14 | sleep 1
15 | fi
16 | done
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/odbc.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * Configuration to use ODBC instead of the default SQLite
4 | * back-end of Orthanc.
5 | **/
6 | "Odbc" : {
7 | // Enable the use of ODBC to store the Orthanc index?
8 | "EnableIndex" : false,
9 |
10 | // Enable the use of ODBC to store the DICOM files?
11 | "EnableStorage" : false,
12 |
13 | // Connection string to the index database
14 | "IndexConnectionString" : "DSN=index",
15 |
16 | // Connection string to the storage area database
17 | "StorageConnectionString" : "DSN=storage"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/serve-folders.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * Configuration of the ServeFolders plugin, that can be used to
4 | * serve additional folders through the embedded Web server of
5 | * Orthanc. This is especially useful to avoid problems related to
6 | * the same-origin policy when developing Web applications in
7 | * JavaScript on the top of the REST API of Orthanc.
8 | *
9 | * The commented example would serve the documentation of the plugin
10 | * SDK at the URL http://localhost:8042/doc/index.html
11 | **/
12 | "ServeFolders" : {
13 | // "/doc" : "/usr/share/doc/orthanc/OrthancPlugin"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/transfers.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * The following options control the configuration of the
4 | * transfers accelerator plugin for Orthanc.
5 | **/
6 |
7 | "Transfers" : {
8 | "Threads" : 4, // Number of worker threads for one transfer
9 | "BucketSize" : 4096, // Optimal size for a bucket (in KB)
10 | "CacheSize" : 128, // Size of the memory cache to process DICOM files (in MB)
11 | "MaxPushTransactions" : 4, // Maximum number of simultaneous receptions in push mode
12 | "MaxHttpRetries" : 0 // Maximum number of HTTP retries for one bucket
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/docker/orthanc/env-var-non-standards.json:
--------------------------------------------------------------------------------
1 | {
2 | "ORTHANC__CASE_SENSITIVE_PN": "CaseSensitivePN",
3 | "ORTHANC__HTTPS_CA_CERTIFICATES": "HttpsCACertificates",
4 | "ORTHANC__STORE_MD5_FOR_ATTACHMENTS": "StoreMD5ForAttachments",
5 |
6 | "ORTHANC__ORTHANC_EXPLORER_2__IS_DEFAULT_ORTHANC_UI": "OrthancExplorer2.IsDefaultOrthancUI",
7 | "ORTHANC__ORTHANC_EXPLORER_2__ENABLE_LINK_TO_LEGACY_UI": "OrthancExplorer2.EnableLinkToLegacyUi",
8 | "OE2_ENABLED": "OrthancExplorer2.IsDefaultOrthancUI",
9 |
10 | "ORTHANC__POSTGRESQL": "PostgreSQL",
11 |
12 | "ORTHANC__MYSQL": "MySQL",
13 | "ORTHANC__MYSQL__SSL_CA_CERTIFICATES": "MySQL.SslCACertificates",
14 |
15 | "ORTHANC__OHIF": "OHIF"
16 | }
17 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.odbc-postgres.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - odbc-pg-server
7 | environment:
8 | ORTHANC__ODBC__INDEX_CONNECTION_STRING: "DSN=postgres"
9 | ORTHANC__ODBC__STORAGE_CONNECTION_STRING: "DSN=postgres"
10 | ORTHANC__ODBC__ENABLE_INDEX: "true"
11 | ORTHANC__ODBC__ENABLE_STORAGE: "true"
12 | VERBOSE_ENABLED: "false"
13 | VERBOSE_STARTUP: "true"
14 |
15 | orthanc-tests:
16 | image: orthanc-tests
17 | depends_on:
18 | - orthanc-under-tests
19 |
20 | odbc-pg-server:
21 | image: postgres
22 | environment:
23 | POSTGRES_PASSWORD: "postgres"
24 |
--------------------------------------------------------------------------------
/orthancBuildResources/readmeMacOS.txt:
--------------------------------------------------------------------------------
1 | This package contains Orthanc and its main plugins.
2 |
3 | QuickStart:
4 | ----------
5 |
6 | Unzip this archive (do not run Orthanc from the zip archive).
7 | Double-click startOrthanc.command to launch a pre-configured Orthanc instance.
8 | Open a browser at http://localhost:8042 to reach the Orthanc Explorer.
9 |
10 | Open the upload page, you may drop a DICOM file.
11 | Once the DICOM file is uploaded, go back to the patients page and browse the study.
12 | Click on 'Osimis WebViewer' to visualize the study in the web browser.
13 |
14 | Going further:
15 | -------------
16 | Read the Orthanc book to learn more about Orthanc configuration and advanced usage (https://book.orthanc-server.com)
17 |
18 |
19 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/CMake/MinGW-W64-Toolchain32.cmake:
--------------------------------------------------------------------------------
1 | # the name of the target operating system
2 | set(CMAKE_SYSTEM_NAME Windows)
3 |
4 | # which compilers to use for C and C++
5 | set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
6 | set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
7 | set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
8 |
9 | # here is the target environment located
10 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
11 |
12 | # adjust the default behaviour of the FIND_XXX() commands:
13 | # search headers and libraries in the target environment, search
14 | # programs in the host environment
15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
16 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
17 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
18 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-under-tests/odbc.ini:
--------------------------------------------------------------------------------
1 | [sqlite3index]
2 | Driver=SQLite3
3 | Database=/tmp/test-odbc-index.sqlite
4 |
5 | [sqlite3storage]
6 | Driver=SQLite3
7 | Database=/tmp/test-odbc-storage.sqlite
8 |
9 | [postgres]
10 | Driver = PostgreSQL Unicode
11 | Servername = odbc-pg-server
12 | Database = postgres
13 | UserName = postgres
14 | Password = postgres
15 | Port = 5432
16 |
17 | [mysql8]
18 | Driver = MySQL ODBC 8.0 Unicode Driver
19 | Servername = odbc-mysql-server
20 | Database = orthanc
21 | UID = test-user
22 | PWD = foo
23 | Port = 3306
24 |
25 | [mssql18]
26 | Driver = ODBC Driver 18 for SQL Server
27 | Server = tcp:sql-server,1433
28 | Database = orthanctest
29 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.postgres-recycling.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - pg
7 | environment:
8 | ORTHANC__MAXIMUM_PATIENT_COUNT: "4"
9 |
10 | ORTHANC__POSTGRESQL__HOST: "pg"
11 | ORTHANC__POSTGRESQL__DATABASE: "postgres"
12 | ORTHANC__POSTGRESQL__USERNAME: "postgres"
13 | ORTHANC__POSTGRESQL__PASSWORD: "postgres"
14 | ORTHANC__POSTGRESQL__ENABLE_INDEX: "true"
15 | ORTHANC__POSTGRESQL__ENABLE_STORAGE: "true"
16 |
17 | orthanc-tests-recycling:
18 | image: orthanc-tests-recycling
19 | depends_on:
20 | - orthanc-under-tests
21 |
22 | pg:
23 | image: postgres:17
24 | environment:
25 | POSTGRES_PASSWORD: "postgres"
26 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/mysql.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * Configuration to use MySQL or MariaDB instead of the default
4 | * SQLite back-end of Orthanc. You will have to install the
5 | * "orthanc-mysql" package to take advantage of this feature.
6 | **/
7 | "MySQL" : {
8 | // Enable the use of MySQL to store the Orthanc index?
9 | "EnableIndex" : false,
10 |
11 | // Enable the use of MySQL to store the DICOM files?
12 | "EnableStorage" : false,
13 |
14 | // Parameters of the MySLQ database
15 | "Host" : "localhost",
16 | "Port" : 3306,
17 | "Database" : "orthanc_db",
18 | "Username" : "orthanc_user",
19 | "Password" : "my_password",
20 |
21 | // Optional: Disable the locking of the MySQL database
22 | "Lock" : false
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/dicomweb.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * The following options control the configuration of the Orthanc
4 | * plugin adding support of WADO and DICOMweb.
5 | **/
6 |
7 | "DicomWeb" : {
8 | "Enable" : true, // Whether DICOMweb support is enabled
9 | "Root" : "/dicom-web/", // Root URI of the DICOMweb API (for QIDO-RS, STOW-RS and WADO-RS)
10 | "EnableWado" : true, // Whether WADO-URI (aka. WADO) support is enabled
11 | "WadoRoot" : "/wado", // Root URI of the WADO-URI (aka. WADO) API
12 | //"Host" : "localhost:8042", // Hard-codes the name of the host for subsequent WADO-RS requests
13 | "Ssl" : false // Whether HTTPS should be used for subsequent WADO-RS requests
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/webviewer.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * The following options control the configuration of the Orthanc
4 | * Web Viewer plugin.
5 | **/
6 |
7 | "WebViewer" : {
8 | /**
9 | * The location of the cache of the Web viewer. By default, the
10 | * cache is located inside the storage directory of Orthanc.
11 | **/
12 | // "CachePath" : "/tmp/WebViewerCache",
13 |
14 | /**
15 | * The maximum size for the cached images, in megabytes. By
16 | * default, a cache of 100 MB is used.
17 | **/
18 | // "CacheSize" : 10,
19 |
20 | /**
21 | * The number of threads that are used by the plugin to decode
22 | * the DICOM images.
23 | **/
24 | // "Threads" : 4
25 | }
26 | }
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.postgres-read-committed.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - pg
7 | environment:
8 | ORTHANC__POSTGRESQL__HOST: "pg"
9 | ORTHANC__POSTGRESQL__DATABASE: "postgres"
10 | ORTHANC__POSTGRESQL__USERNAME: "postgres"
11 | ORTHANC__POSTGRESQL__PASSWORD: "postgres"
12 | ORTHANC__POSTGRESQL__ENABLE_INDEX: "true"
13 | ORTHANC__POSTGRESQL__ENABLE_STORAGE: "true"
14 |
15 | ORTHANC__POSTGRESQL__TRANSACTION_MODE: "ReadCommitted"
16 |
17 | # VERBOSE_ENABLED: "true"
18 |
19 | orthanc-tests:
20 | image: orthanc-tests
21 | depends_on:
22 | - orthanc-under-tests
23 |
24 | pg:
25 | image: postgres:16
26 | environment:
27 | POSTGRES_PASSWORD: "postgres"
28 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.postgres-serializable.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - pg
7 | environment:
8 | ORTHANC__POSTGRESQL__HOST: "pg"
9 | ORTHANC__POSTGRESQL__DATABASE: "postgres"
10 | ORTHANC__POSTGRESQL__USERNAME: "postgres"
11 | ORTHANC__POSTGRESQL__PASSWORD: "postgres"
12 | ORTHANC__POSTGRESQL__ENABLE_INDEX: "true"
13 | ORTHANC__POSTGRESQL__ENABLE_STORAGE: "true"
14 |
15 | ORTHANC__POSTGRESQL__TRANSACTION_MODE: "Serializable"
16 |
17 | # VERBOSE_ENABLED: "true"
18 |
19 | orthanc-tests:
20 | image: orthanc-tests
21 | depends_on:
22 | - orthanc-under-tests
23 |
24 | pg:
25 | image: postgres:14
26 | environment:
27 | POSTGRES_PASSWORD: "postgres"
28 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/azure.json:
--------------------------------------------------------------------------------
1 | {
2 | // "AzureBlobStorage" : {
3 | // "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=xxxxxxxxx;AccountKey=yyyyyyyy===;EndpointSuffix=core.windows.net",
4 | // "ContainerName" : "test-orthanc-storage-plugin",
5 | // //"CreateContainerIfNotExists": true, // available from version 1.2.0
6 | // //"RootPath": "", // see below
7 | // //"MigrationFromFileSystemEnabled": false, // see below
8 | // //"StorageStructure": "flat", // see below
9 | // //"EnableLegacyUnknownFiles": true, // optional: see below
10 | // //"StorageEncryption" : {}, // optional: see the section related to encryption
11 | // //"HybridMode": "Disabled" // optional: see the section related to Hybrid storage
12 | // }
13 | }
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.postgres-dicomweb.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - pg
7 | environment:
8 | ORTHANC__POSTGRESQL__HOST: "pg"
9 | ORTHANC__POSTGRESQL__DATABASE: "postgres"
10 | ORTHANC__POSTGRESQL__USERNAME: "postgres"
11 | ORTHANC__POSTGRESQL__PASSWORD: "postgres"
12 | ORTHANC__POSTGRESQL__ENABLE_INDEX: "true"
13 | ORTHANC__POSTGRESQL__ENABLE_STORAGE: "true"
14 |
15 | ORTHANC__POSTGRESQL__TRANSACTION_MODE: "ReadCommitted"
16 |
17 | # VERBOSE_ENABLED: "true"
18 | VERBOSE_STARTUP: "true"
19 | GDCM_PLUGIN_ENABLED: "false"
20 |
21 | orthanc-tests-dicomweb:
22 | image: orthanc-tests-dicomweb
23 | depends_on:
24 | - orthanc-under-tests
25 |
26 | pg:
27 | image: postgres:16
28 | environment:
29 | POSTGRES_PASSWORD: "postgres"
30 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-under-tests/Dockerfile.mssql:
--------------------------------------------------------------------------------
1 | FROM osimis/21.12.0-buster
2 |
3 | RUN apt-get update
4 | RUN apt-get --assume-yes install curl gnupg2
5 |
6 | RUN mkdir /downloads
7 |
8 | RUN curl https://packages.microsoft.com/keys/microsoft.asc > /downloads/microsoft.asc
9 | RUN curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list
10 |
11 | RUN apt-key add /downloads/microsoft.asc
12 | RUN apt-get update && \
13 | ACCEPT_EULA=Y apt-get install -y msodbcsql17 unixodbc-dev && \
14 | apt-get clean && \
15 | rm -rf /var/lib/apt/lists/*
16 |
17 | # install gdcm and dcmtk that are used in a Lua scripts
18 | RUN apt-get --assume-yes update
19 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install dcmtk libgdcm-tools
20 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install odbc-postgresql
21 |
22 | COPY orthanc.json /etc/orthanc/orthanc.json
23 | COPY odbc.ini /etc/
24 |
--------------------------------------------------------------------------------
/WindowsInstaller/AppProcessMessages.iss:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/a/44840244/881731
2 | // https://stackoverflow.com/a/32266687/881731
3 |
4 | type
5 | TMsg = record
6 | hwnd: HWND;
7 | message: UINT;
8 | wParam: Longint;
9 | lParam: Longint;
10 | time: DWORD;
11 | pt: TPoint;
12 | end;
13 |
14 | const
15 | PM_REMOVE = 1;
16 |
17 | function PeekMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
18 | external 'PeekMessageA@user32.dll stdcall';
19 |
20 | function TranslateMessage(const lpMsg: TMsg): BOOL;
21 | external 'TranslateMessage@user32.dll stdcall';
22 |
23 | function DispatchMessage(const lpMsg: TMsg): Longint;
24 | external 'DispatchMessageA@user32.dll stdcall';
25 |
26 |
27 | procedure AppProcessMessages();
28 | var
29 | Msg: TMsg;
30 | begin
31 | while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do begin
32 | TranslateMessage(Msg);
33 | DispatchMessage(Msg);
34 | end;
35 | end;
36 |
--------------------------------------------------------------------------------
/.github/workflows/pre-build.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | outputs:
4 | is_tag:
5 | value: ${{ jobs.pre_build.outputs.is_tag }}
6 | current_branch_tag:
7 | value: ${{ jobs.pre_build.outputs.current_branch_tag }}
8 |
9 | jobs:
10 |
11 | pre_build:
12 | name: pre_build
13 | runs-on: "ubuntu-latest"
14 | outputs:
15 | current_branch_tag: ${{steps.branch_name.outputs.current_branch_tag}}
16 | is_tag: ${{steps.branch_name.outputs.is_tag}}
17 |
18 | steps:
19 | - name: Get branch/tag name
20 | id: branch_name
21 | run: |
22 | echo "current_branch_tag=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
23 | [[ "${GITHUB_REF_TYPE}" == "tag" ]] && echo "is_tag=true" >> $GITHUB_OUTPUT || echo "is_tag=false" >> $GITHUB_OUTPUT
24 |
25 | - name: Echo pre_build
26 | run: |
27 | echo ${{ steps.branch_name.outputs.is_tag }} ${{ steps.branch_name.outputs.current_branch_tag }}
28 | echo ${{ github.ref}}
29 |
30 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.odbc-mysql.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - odbc-mysql-server
7 | environment:
8 | ORTHANC__ODBC__INDEX_CONNECTION_STRING: "DSN=mysql8"
9 | ORTHANC__ODBC__STORAGE_CONNECTION_STRING: "DSN=mysql8"
10 | ORTHANC__ODBC__ENABLE_INDEX: "true"
11 | ORTHANC__ODBC__ENABLE_STORAGE: "true"
12 | VERBOSE_ENABLED: "true"
13 | VERBOSE_STARTUP: "true"
14 |
15 | orthanc-tests:
16 | image: orthanc-tests
17 | depends_on:
18 | - orthanc-under-tests
19 |
20 | odbc-mysql-server:
21 | image: mysql:8.0
22 | command:
23 | [
24 | mysqld,
25 | --default-authentication-plugin=mysql_native_password,
26 | --log-bin-trust-function-creators=1,
27 | ]
28 | environment:
29 | MYSQL_PASSWORD: foo
30 | MYSQL_USER: test-user
31 | MYSQL_DATABASE: orthanc
32 | MYSQL_ROOT_PASSWORD: foo-root
33 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.mysql.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - mysql-server
7 | environment:
8 | ORTHANC__MYSQL__HOST: mysql-server
9 | ORTHANC__MYSQL__USERNAME: test-user
10 | ORTHANC__MYSQL__DATABASE: orthanc
11 | ORTHANC__MYSQL__PASSWORD: foo
12 | ORTHANC__MYSQL__ENABLE_INDEX: "true"
13 | ORTHANC__MYSQL__ENABLE_STORAGE: "true"
14 | VERBOSE_ENABLED: "false"
15 |
16 | orthanc-tests:
17 | image: orthanc-tests
18 | depends_on:
19 | - orthanc-under-tests
20 |
21 | mysql-server:
22 | image: mysql:8.0
23 | command:
24 | [
25 | mysqld,
26 | --default-authentication-plugin=mysql_native_password,
27 | --log-bin-trust-function-creators=1,
28 | ]
29 | environment:
30 | MYSQL_PASSWORD: foo
31 | MYSQL_USER: test-user
32 | MYSQL_DATABASE: orthanc
33 | MYSQL_ROOT_PASSWORD: foo-root
34 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/postgresql.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | * Configuration to use PostgreSQL instead of the default SQLite
4 | * back-end of Orthanc. You will have to install the
5 | * "orthanc-postgresql" package to take advantage of this feature.
6 | **/
7 | "PostgreSQL" : {
8 | // Enable the use of PostgreSQL to store the Orthanc index?
9 | "EnableIndex" : false,
10 |
11 | // Enable the use of PostgreSQL to store the DICOM files?
12 | "EnableStorage" : false,
13 |
14 | // Option 1: Specify explicit authentication parameters
15 | "Host" : "localhost",
16 | "Port" : 5432,
17 | "Database" : "orthanc_db",
18 | "Username" : "orthanc_user",
19 | "Password" : "my_password",
20 |
21 | // Option 2: Authenticate using PostgreSQL connection URI
22 | // "ConnectionUri" : "postgresql://orthanc_user:my_password@localhost:5432/orthanc_db",
23 |
24 | // Optional: Disable the locking of the PostgreSQL database
25 | "Lock" : false
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.github/workflows/build-stone-wasm.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable (currently not used)'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | build-stone-wasm:
25 | name: build-stone-wasm
26 | runs-on: "ubuntu-latest"
27 |
28 | steps:
29 |
30 | - uses: actions/checkout@v3
31 |
32 | - name: Build Stone WASM
33 | run: ./build-stone-wasm.sh version=${{ inputs.stable_unstable }} workspace="${{github.workspace}}"
34 | env:
35 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
36 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
37 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.tls-check-client.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | volumes:
6 | - tls:/tls
7 | environment:
8 | VERBOSE_STARTUP: "true"
9 | VERBOSE_ENABLED: "true"
10 | ORTHANC__DICOM_TLS_CERTIFICATE: "/tls/dicom-tls-a.crt"
11 | ORTHANC__DICOM_TLS_PRIVATE_KEY: "/tls/dicom-tls-a.key"
12 | ORTHANC__DICOM_TLS_TRUSTED_CERTIFICATES: "/tls/dicom-tls-trusted.crt"
13 | ORTHANC__DICOM_TLS_REMOTE_CERTIFICATE_REQUIRED: "true"
14 | ORTHANC__EXECUTE_LUA_ENABLED: "true"
15 | ORTHANC__AUTHENTICATION_ENABLED: "false"
16 |
17 | orthanc-tests-tls-check-client:
18 | volumes:
19 | - tls:/tls
20 | image: orthanc-tests-tls-check-client
21 | depends_on:
22 | - orthanc-under-tests
23 |
24 | orthanc-tests-tls-check-client-generate-config:
25 | volumes:
26 | - tls:/tls
27 | image: orthanc-tests-tls-check-client-generate-config
28 | depends_on:
29 | - orthanc-under-tests
30 |
31 | volumes:
32 | tls:
--------------------------------------------------------------------------------
/.github/workflows/build-volview-dist.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable (currently not used)'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | build-volview-dist:
25 | name: build-volview-dist
26 | runs-on: "ubuntu-latest"
27 |
28 | steps:
29 |
30 | - uses: actions/checkout@v3
31 |
32 | - name: Build Volview dist
33 | run: ./build-volview-dist.sh version=${{ inputs.stable_unstable }} workspace="${{github.workspace}}"
34 | env:
35 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
36 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
37 |
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.odbc-sql-server.yml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | - orthanc-db
7 | environment:
8 | ORTHANC__ODBC__INDEX_CONNECTION_STRING: "Driver={ODBC Driver 18 for SQL Server};Server=tcp:orthanc-db,1433;Database=orthanctest;Uid=sa;Pwd=MyStrOngPa55word!;Encrypt=yes;TrustServerCertificate=yes;Connection Timeout=30;"
9 | ORTHANC__ODBC__STORAGE_CONNECTION_STRING: "Driver={ODBC Driver 18 for SQL Server};Server=tcp:orthanc-db,1433;Database=orthanctest;Uid=sa;Pwd=MyStrOngPa55word!;Encrypt=yes;TrustServerCertificate=yes;Connection Timeout=30;"
10 | ORTHANC__ODBC__ENABLE_INDEX: "true"
11 | ORTHANC__ODBC__ENABLE_STORAGE: "true"
12 | VERBOSE_STARTUP: "true"
13 | VERBOSE_ENABLED: "false"
14 |
15 | orthanc-tests:
16 | image: orthanc-tests
17 | depends_on:
18 | - orthanc-under-tests
19 |
20 | orthanc-db:
21 | build: sql-server
22 | environment:
23 | ACCEPT_EULA: "Y"
24 | SA_PASSWORD: "MyStrOngPa55word!"
25 |
--------------------------------------------------------------------------------
/.github/workflows/build-macos-package.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | build-macos-package:
25 | name: build-macos-package
26 | runs-on: "ubuntu-latest"
27 |
28 | steps:
29 |
30 | - uses: actions/checkout@v3
31 |
32 | - name: Build MacOS Package
33 | run: ./build-macos-package.sh is_tag=${{ inputs.is_tag }} stable_unstable=${{ inputs.stable_unstable }} current_branch_tag=${{ inputs.current_branch_tag }}
34 | env:
35 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
36 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
37 |
--------------------------------------------------------------------------------
/.github/workflows/build-windows-installer.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable (currently not used)'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | build-windows-installer:
25 | name: build-windows-installer
26 | runs-on: "ubuntu-latest"
27 |
28 | steps:
29 |
30 | - uses: actions/checkout@v3
31 |
32 | - name: Build Windows installer
33 | run: ./ciBuildWindowsInstaller.sh ${{ inputs.is_tag }} ${{ inputs.current_branch_tag }}
34 | working-directory: ./WindowsInstaller
35 | env:
36 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
37 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
38 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-under-tests/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG IMAGE_UNDER_TEST=orthancteam/orthanc:latest
2 | FROM $IMAGE_UNDER_TEST
3 |
4 | # install gdcm and dcmtk that are used in a Lua scripts
5 | RUN apt-get --assume-yes update
6 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install dcmtk libgdcm-tools wget
7 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install odbc-postgresql unixodbc-dev
8 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install libsqliteodbc
9 |
10 | #### note: this is not functional yet to validate mysql with odbc
11 | # RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install apt-utils wget dpkg-dev lsb-release
12 | # WORKDIR /tmp
13 | # RUN wget https://repo.mysql.com/mysql-apt-config_0.8.20-1_all.deb
14 | # RUN DEBIAN_FRONTEND=noninteractive dpkg -i *.deb
15 | # RUN apt-get --assume-yes update
16 | # RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install mysql-community-client-plugins
17 | # RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install mysql-connector-odbc
18 |
19 | COPY orthanc.json /etc/orthanc/orthanc.json
20 | COPY odbc.ini /etc/
21 |
22 | ENV DICOM_WEB_PLUGIN_ENABLED=true
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.tls-no-check-client.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | volumes:
6 | - tls:/tls
7 | environment:
8 | VERBOSE_STARTUP: "true"
9 | VERBOSE_ENABLED: "true"
10 | ORTHANC__DICOM_TLS_ENABLED: "true"
11 | ORTHANC__DICOM_TLS_CERTIFICATE: "/tls/dicom-tls-a.crt"
12 | ORTHANC__DICOM_TLS_PRIVATE_KEY: "/tls/dicom-tls-a.key"
13 | # although this is not used, in 1.12.4, this is still required for outgoing connections
14 | ORTHANC__DICOM_TLS_TRUSTED_CERTIFICATES: "/tls/dicom-tls-trusted.crt"
15 | ORTHANC__DICOM_TLS_REMOTE_CERTIFICATE_REQUIRED: "false"
16 | ORTHANC__EXECUTE_LUA_ENABLED: "true"
17 | ORTHANC__AUTHENTICATION_ENABLED: "false"
18 |
19 | orthanc-tests-tls-no-check-client:
20 | volumes:
21 | - tls:/tls
22 | image: orthanc-tests-tls-no-check-client
23 | depends_on:
24 | - orthanc-under-tests
25 |
26 | orthanc-tests-tls-no-check-client-generate-config:
27 | volumes:
28 | - tls:/tls
29 | image: orthanc-tests-tls-no-check-client-generate-config
30 | depends_on:
31 | - orthanc-under-tests
32 |
33 | volumes:
34 | tls:
--------------------------------------------------------------------------------
/UCLouvain/Toolbox.py:
--------------------------------------------------------------------------------
1 | # Orthanc - A Lightweight, RESTful DICOM Store
2 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
3 | # Department, University Hospital of Liege, Belgium
4 | # Copyright (C) 2017-2023 Osimis S.A., Belgium
5 | # Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
6 | # Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 | #
8 | # This program is free software: you can redistribute it and/or
9 | # modify it under the terms of the GNU Lesser General Public License
10 | # as published by the Free Software Foundation, either version 3 of
11 | # the License, or (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful, but
14 | # WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | # Lesser General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU Lesser General Public
19 | # License along with this program. If not, see
20 | # .
21 |
22 |
23 | def GetVersion(repo):
24 | if 'BuildbotVersion' in repo:
25 | return repo['BuildbotVersion']
26 | else:
27 | return repo['stable'].split('-') [-1]
28 |
--------------------------------------------------------------------------------
/github-mirrors/sync-all.sh:
--------------------------------------------------------------------------------
1 | set -ex
2 |
3 | # this scripts synchronizes the mercurial repositories from https://orthanc.uclouvain.be/hg/
4 | # and the github mirrors on https://github.com/orgs/orthanc-mirrors/
5 | # usage:
6 | # ./sync-all.sh
7 |
8 | # This script is running every day at 22 on the Github ARM 64 build slave
9 | # under user orthanc-mirrors' cron job.
10 |
11 | source mirror-helpers.sh
12 |
13 | if [ -d ".env" ]; then
14 | source .env/bin/activate
15 | else
16 | initVirtualEnv
17 | fi
18 |
19 | syncAllBranchesFromRepo orthanc
20 | syncAllBranchesFromRepo orthanc-authorization
21 | syncAllBranchesFromRepo orthanc-book
22 | syncAllBranchesFromRepo orthanc-databases
23 | syncAllBranchesFromRepo orthanc-dicomweb
24 | syncAllBranchesFromRepo orthanc-education
25 | syncAllBranchesFromRepo orthanc-gcp
26 | syncAllBranchesFromRepo orthanc-gdcm
27 | syncAllBranchesFromRepo orthanc-indexer
28 | syncAllBranchesFromRepo orthanc-imagej
29 | syncAllBranchesFromRepo orthanc-java
30 | syncAllBranchesFromRepo orthanc-neuro
31 | syncAllBranchesFromRepo orthanc-object-storage
32 | syncAllBranchesFromRepo orthanc-ohif
33 | syncAllBranchesFromRepo orthanc-python
34 | syncAllBranchesFromRepo orthanc-stone
35 | syncAllBranchesFromRepo orthanc-stl
36 | syncAllBranchesFromRepo orthanc-tcia
37 | syncAllBranchesFromRepo orthanc-tests
38 | syncAllBranchesFromRepo orthanc-transfers
39 | syncAllBranchesFromRepo orthanc-volview
40 | syncAllBranchesFromRepo orthanc-webviewer
41 | syncAllBranchesFromRepo orthanc-wsi
42 |
43 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/aws-s3.json:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | "AwsS3Storage" : {
4 | "BucketName": "test-orthanc-s3-plugin",
5 | "Region" : "eu-central-1",
6 | "AccessKey" : "AKXXX", // optional: if not specified, the plugin will use the default credentials manager (available from version 1.3.0)
7 | "SecretKey" : "RhYYYY", // optional: if not specified, the plugin will use the default credentials manager (available from version 1.3.0)
8 | "Endpoint": "", // optional: custom endpoint
9 | "ConnectionTimeout": 30, // optional: connection timeout in seconds
10 | "RequestTimeout": 1200, // optional: request timeout in seconds (max time to upload/download a file)
11 | "RootPath": "", // optional: see below
12 | "MigrationFromFileSystemEnabled": false, // optional: see below
13 | "StorageStructure": "flat", // optional: see below
14 | "EnableLegacyUnknownFiles": true, // optional: see below
15 | "VirtualAddressing": true, // optional: see the section related to MinIO
16 | "StorageEncryption" : {}, // optional: see the section related to encryption
17 | "HybridMode": "Disabled", // optional: see the section related to Hybrid storage
18 | "UseTransferManager": false, // optional: see below (available from version 2.3.0)
19 | "EnableAwsSdkLogs": false // optional: include AWS SDK logs in Orthanc logs
20 | }
21 | **/
22 | }
23 |
--------------------------------------------------------------------------------
/WindowsInstaller/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:22.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 |
5 | RUN dpkg --add-architecture i386
6 | RUN apt-get update
7 | RUN apt-get install -yq curl unrar unzip build-essential g++-mingw-w64 cmake python3 python3-pip vim mercurial wget software-properties-common apt-transport-https
8 | RUN wget -nc https://dl.winehq.org/wine-builds/winehq.key
9 | RUN apt-key add winehq.key
10 | RUN apt-add-repository https://dl.winehq.org/wine-builds/ubuntu/
11 | RUN apt-get update
12 | # RUN sed -i "s/main/main contrib non-free/" etc/apt/sources.list
13 | RUN apt-get install -yq wine
14 |
15 | # innosetup
16 | # old url: "https://downloads.sourceforge.net/project/innounp/innounp/innounp%200.45/innounp045.rar?r=&ts=1439566551&use_mirror=skylineservers"
17 |
18 | RUN mkdir innosetup && \
19 | cd innosetup && \
20 | curl -fsSL -o innounp045.rar "https://orthanc.uclouvain.be/downloads/third-party-downloads/innounp045.rar" && \
21 | unrar e innounp045.rar
22 |
23 | # old url: https://files.jrsoftware.org/is/5/isetup-5.5.8-unicode.exe
24 | RUN cd innosetup && \
25 | curl -fsSL -o is-unicode.exe "https://orthanc.uclouvain.be/downloads/third-party-downloads/isetup-5.5.8-unicode.exe" && \
26 | wine "./innounp.exe" -e "is-unicode.exe"
27 |
28 | RUN pip3 install requests
29 |
30 | COPY build-matrix.json /
31 | COPY WindowsInstaller/ /tmp/WindowsInstaller
32 | COPY UCLouvain/ /tmp/UCLouvain
33 |
34 | WORKDIR /tmp/WindowsInstaller
35 |
36 | ARG PLATFORM
37 | ARG VERSION
38 |
39 | RUN python3 --version
40 | RUN python3 -u ./CreateInstaller.py --matrix=/build-matrix.json --platform=${PLATFORM} --version=${VERSION} --from-docker
41 |
--------------------------------------------------------------------------------
/docker/orthanc/Dockerfile.builder-vcpkg:
--------------------------------------------------------------------------------
1 | ########################## Orthanc builder vcpkg
2 | # image to compile Orthanc and its plugins dynamically
3 | ARG BASE_IMAGE_TAG=current
4 | FROM orthancteam/orthanc-builder-base:${BASE_IMAGE_TAG} AS orthanc-build-vcpkg
5 |
6 | # prerequisites (for VCPKG builds)
7 | RUN export DEBIAN_FRONTEND=noninteractive && \
8 | apt-get --assume-yes update && \
9 | apt-get --assume-yes install ninja-build && \
10 | apt-get clean && \
11 | rm -rf /var/lib/apt/lists/*
12 |
13 | WORKDIR /
14 | RUN git clone https://github.com/Microsoft/vcpkg.git && \
15 | cd vcpkg/ && \
16 | git checkout 2025.03.19
17 |
18 | WORKDIR /vcpkg
19 | # RUN ls -al /vcpkg
20 | RUN ./bootstrap-vcpkg.sh
21 | ENV VCPKG_FORCE_SYSTEM_BINARIES=1
22 |
23 | RUN mkdir ~/.vcpkg/
24 |
25 | RUN ./vcpkg integrate install
26 |
27 | # patch the triplet to produce only release builds
28 | RUN bash -c '[[ $(uname -m) == "x86_64" ]] && echo "set(VCPKG_BUILD_TYPE release)" >> /vcpkg/triplets/x64-linux.cmake || echo "set(VCPKG_BUILD_TYPE release)" >> /vcpkg/triplets/community/arm64-linux.cmake'
29 |
30 | # object storage prerequisites
31 | RUN ./vcpkg install cryptopp
32 |
33 |
34 | ########################## Orthanc builder vcpkg-google
35 |
36 | FROM orthancteam/orthanc-builder-base:vcpkg-${BASE_IMAGE_TAG} AS orthanc-build-vcpkg-google
37 |
38 | WORKDIR /vcpkg
39 | RUN ./vcpkg install google-cloud-cpp[storage]
40 |
41 | ########################## Orthanc builder vcpkg-azure
42 |
43 | FROM orthancteam/orthanc-builder-base:vcpkg-${BASE_IMAGE_TAG} AS orthanc-build-vcpkg-azure
44 |
45 | WORKDIR /vcpkg
46 | RUN ./vcpkg install azure-core-cpp azure-storage-blobs-cpp
47 |
48 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/housekeeper.json:
--------------------------------------------------------------------------------
1 | {
2 | "Housekeeper": {
3 |
4 | // Enables/disables the plugin
5 | "Enable": false,
6 |
7 | // the Global Prooperty ID in which the plugin progress
8 | // is stored. Must be > 1024 and must not be used by
9 | // another plugin
10 | "GlobalPropertyId": 1025,
11 |
12 | // Forces execution even if the plugin did not detect
13 | // any changes in configuration
14 | "Force": false,
15 |
16 | // Delay (in seconds) between reconstruction of 2 studies
17 | // This avoids overloading Orthanc with the housekeeping
18 | // process and leaves room for other operations.
19 | "ThrottleDelay": 5,
20 |
21 | // Runs the plugin only at certain period of time.
22 | // If not specified, the plugin runs all the time
23 | // Examples:
24 | // to run between 0AM and 6AM everyday + every night
25 | // from 8PM to 12PM and 24h a day on the weekend:
26 | // "Schedule": {
27 | // "Monday": ["0-6", "20-24"],
28 | // "Tuesday": ["0-6", "20-24"],
29 | // "Wednesday": ["0-6", "20-24"],
30 | // "Thursday": ["0-6", "20-24"],
31 | // "Friday": ["0-6", "20-24"],
32 | // "Saturday": ["0-24"],
33 | // "Sunday": ["0-24"]
34 | // },
35 |
36 | // configure events that can trigger a housekeeping processing
37 | "Triggers" : {
38 | "StorageCompressionChange": true,
39 | "MainDicomTagsChange": true,
40 | "UnnecessaryDicomAsJsonFiles": true
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/WindowsInstaller/Configuration/Toolbox.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Orthanc - A Lightweight, RESTful DICOM Store
3 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 | * Department, University Hospital of Liege, Belgium
5 | * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 | * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
7 | * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
8 | *
9 | * This program is free software: you can redistribute it and/or
10 | * modify it under the terms of the GNU General Public License as
11 | * published by the Free Software Foundation, either version 3 of the
12 | * License, or (at your option) any later version.
13 | *
14 | * This program is distributed in the hope that it will be useful, but
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with this program. If not, see .
21 | **/
22 |
23 |
24 | #pragma once
25 |
26 | #include
27 | #include
28 |
29 | std::wstring GetStringRegKey(const std::wstring& key,
30 | const std::wstring& name,
31 | const std::wstring& defaultValue);
32 |
33 | std::string GetStringRegKeyAnsi(const std::string& key,
34 | const std::string& name,
35 | const std::string& defaultValue);
36 |
37 | DWORD GetDWordRegKey(const std::wstring& key,
38 | const std::wstring& name,
39 | DWORD defaultValue);
40 |
--------------------------------------------------------------------------------
/docker/orthanc/test_legacy.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from configurator import OrthancConfigurator
3 |
4 |
5 | class LegacyTest(unittest.TestCase):
6 |
7 | def test_default_config(self):
8 | c = OrthancConfigurator()
9 | c.mergeConfigFromDefaults()
10 |
11 | self.assertTrue(c.configuration["RemoteAccessAllowed"])
12 | self.assertTrue(c.configuration["AuthenticationEnabled"])
13 |
14 |
15 | def test_simple_env_vars_to_enable_plugin(self):
16 | c = OrthancConfigurator()
17 | c.mergeConfigFromEnvVar("WL_ENABLED", "true")
18 |
19 | self.assertIn("Worklists", c.getEnabledPlugins())
20 |
21 |
22 | def test_simple_section_to_enable_plugin(self):
23 | c = OrthancConfigurator()
24 | worklistsConfig = {
25 | "Worklists" : {
26 | "Database" : "tutu"
27 | }
28 | }
29 | c.mergeConfigFromFile(worklistsConfig, "worklist.json")
30 |
31 | self.assertIn("Worklists", c.configuration)
32 | self.assertIn("Worklists", c.getEnabledPlugins())
33 |
34 |
35 | def test_direct_secret(self):
36 | c = OrthancConfigurator()
37 | c.mergeConfigFromSecret("/run/secrets/PG_PASSWORD", "pg-password")
38 |
39 | self.assertIn("PostgreSQL", c.configuration)
40 | self.assertIn("PostgreSQL", c.getEnabledPlugins())
41 | self.assertEqual("pg-password", c.configuration["PostgreSQL"]["Password"])
42 |
43 | def test_indirect_secret(self):
44 | c = OrthancConfigurator()
45 | c.mergeConfigFromEnvVar("PG_PASSWORD_SECRET", "pg-password-file")
46 | c.mergeConfigFromSecret("/run/secrets/pg-password-file", "pg-password")
47 |
48 | self.assertIn("PostgreSQL", c.configuration)
49 | self.assertIn("PostgreSQL", c.getEnabledPlugins())
50 | self.assertEqual("pg-password", c.configuration["PostgreSQL"]["Password"])
51 |
52 | if __name__ == '__main__':
53 | unittest.main()
--------------------------------------------------------------------------------
/docker/integration-tests/docker-compose.s3.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | orthanc-under-tests:
4 | image: orthanc-under-tests
5 | depends_on:
6 | minio:
7 | condition: service_healthy
8 | createbuckets:
9 | condition: service_healthy
10 | environment:
11 | ORTHANC__AWS_S3_STORAGE__BUCKET_NAME: "my-sample-bucket"
12 | ORTHANC__AWS_S3_STORAGE__REGION: "eu-west-1"
13 | ORTHANC__AWS_S3_STORAGE__ACCESS_KEY: "minio"
14 | ORTHANC__AWS_S3_STORAGE__SECRET_KEY: "miniopwd"
15 | ORTHANC__AWS_S3_STORAGE__ENDPOINT: "http://minio:9000"
16 | ORTHANC__AWS_S3_STORAGE__VIRTUAL_ADDRESSING: "false"
17 | # VERBOSE_ENABLED: "true"
18 |
19 | orthanc-tests:
20 | image: orthanc-tests
21 | depends_on:
22 | orthanc-under-tests:
23 | condition: service_started
24 |
25 | minio:
26 | command: server /data --console-address ":9001"
27 | image: minio/minio:RELEASE.2022-03-26T06-49-28Z
28 | ports: [9000:9000, 9001:9001]
29 | environment:
30 | MINIO_REGION: "eu-west-1"
31 | MINIO_ROOT_USER: "minio"
32 | MINIO_ROOT_PASSWORD: "miniopwd"
33 | healthcheck:
34 | test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
35 | interval: 2s
36 | timeout: 1s
37 | retries: 3
38 |
39 | createbuckets:
40 | image: minio/mc:RELEASE.2022-03-17T20-25-06Z
41 | depends_on:
42 | minio:
43 | condition: service_healthy
44 | healthcheck:
45 | test: ["CMD-SHELL", "cat", "/tmp/initialized"]
46 | interval: 2s
47 | timeout: 1s
48 | retries: 10
49 | entrypoint: >
50 | /bin/sh -c "
51 | /usr/bin/mc alias set myminio http://minio:9000 minio miniopwd;
52 | /usr/bin/mc mb myminio/my-sample-bucket;
53 | /usr/bin/mc policy set public myminio/my-sample-bucket;
54 | touch /tmp/initialized;
55 | sleep 600; #otherwise the docker-compose exits once this container has completed !!!
56 | "
57 |
--------------------------------------------------------------------------------
/github-mirrors/mirror-helpers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # rewrite pushd/popd such that they do not produce any output in bash functions (https://stackoverflow.com/questions/25288194/dont-display-pushd-popd-stack-across-several-bash-scripts-quiet-pushd-popd)
4 | pushd () {
5 | command pushd "$@" > /dev/null
6 | }
7 |
8 | popd () {
9 | command popd "$@" > /dev/null
10 | }
11 |
12 | script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13 |
14 | initVirtualEnv() {
15 | python -m venv .env
16 | source .env/bin/activate
17 | pip install mercurial hg-git
18 | }
19 |
20 | firstCloneMercurialRepo() { # $1 = repo-name
21 | pushd $script_dir/mirrors/
22 | hg clone https://orthanc.uclouvain.be/hg/$1
23 |
24 | cat << EOF >> $1/.hg/hgrc
25 | [extensions]
26 | hggit=
27 | hgext.bookmarks =
28 | EOF
29 |
30 | sed -i "/^default =/a\github = git+ssh://git@github.com:orthanc-mirrors/$1.git" $1/.hg/hgrc
31 | cat $1/.hg/hgrc
32 | pushd $script_dir/mirrors/$1
33 |
34 | hg bookmark master
35 | hg push github
36 |
37 | popd
38 |
39 | popd
40 | }
41 |
42 | syncRepoBranch() { # $1 = repo-name, $2 = branch-name
43 | pushd $script_dir/mirrors/$1
44 |
45 | # hg pull -u
46 | hg update -r $2
47 | # hg pull -u
48 |
49 | if [ "$2" == "default" ]; then
50 | hg bookmark master
51 | else
52 | hg bookmark branches/$2
53 | fi
54 |
55 | hg push github || true
56 |
57 | popd
58 | }
59 |
60 | listAllBranches() { # $1 = repo-name
61 | hg branches | awk '{print $1}'
62 | }
63 |
64 | syncAllBranchesFromRepo() { # $1 = repo-name
65 |
66 | if [ ! -d "$script_dir/mirrors/$1" ]; then
67 | firstCloneMercurialRepo $1
68 | fi
69 |
70 | pushd $script_dir/mirrors/$1
71 |
72 | hg pull -u
73 |
74 | # Get all active branch names and iterate through them
75 | hg branches | awk '{print $1}' | while read branch_name; do
76 | syncRepoBranch $1 "$branch_name"
77 | done
78 |
79 | popd
80 | }
81 |
--------------------------------------------------------------------------------
/.github/workflows/build-macos-binaries.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | get-build-matrix:
25 | name: get-build-matrix
26 | runs-on: "ubuntu-latest"
27 | outputs:
28 | matrix: ${{ steps.set-matrix.outputs.matrix }}
29 | steps:
30 | # Required as the JSON input file needs to be read
31 | - uses: actions/checkout@v3
32 |
33 | - id: set-matrix
34 | uses: JoshuaTheMiller/conditional-build-matrix@main
35 | with:
36 | inputFile: 'build-matrix.json'
37 | filter: 'configs[?buildForMacOS]'
38 |
39 | - name: output
40 | run: |
41 | echo ${{steps.set-matrix.outputs.matrix}}
42 |
43 | build:
44 | name: build
45 | runs-on: "macos-15"
46 | needs: [get-build-matrix]
47 | strategy:
48 | fail-fast: false
49 | matrix: ${{fromJSON(needs.get-build-matrix.outputs.matrix)}}
50 |
51 | steps:
52 | - uses: actions/checkout@v3
53 |
54 | - name: Build if required
55 | id: build-binaries
56 | run: |
57 | pip3 install mercurial --break-system-packages
58 | ./build-macos-branch.sh version=${{ inputs.stable_unstable }} configName="${{matrix.name}}" workspace="${{github.workspace}}"
59 | env:
60 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
61 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
62 |
63 | # - name: Setup tmate session
64 | # if: ${{ failure() }}
65 | # uses: mxschmitt/action-tmate@v3
66 | # with:
67 | # limit-access-to-actor: true
68 | # timeout-minutes: 20
69 |
--------------------------------------------------------------------------------
/.github/workflows/build-win-binaries.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | stable_unstable:
13 | description: 'stable/unstable'
14 | type: string
15 | required: true
16 | secrets:
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 | jobs:
23 |
24 | get-build-matrix:
25 | name: get-build-matrix
26 | runs-on: "ubuntu-latest"
27 | outputs:
28 | matrix: ${{ steps.set-matrix.outputs.matrix }}
29 | steps:
30 | # Required as the JSON input file needs to be read
31 | - uses: actions/checkout@v3
32 |
33 | - id: set-matrix
34 | uses: JoshuaTheMiller/conditional-build-matrix@main
35 | with:
36 | inputFile: 'build-matrix.json'
37 | filter: 'configs[?buildForWin]'
38 |
39 | - name: output
40 | run: |
41 | echo ${{steps.set-matrix.outputs.matrix}}
42 |
43 | build:
44 | name: build
45 | runs-on: "windows-2022"
46 | needs: [get-build-matrix]
47 | strategy:
48 | fail-fast: false
49 | matrix: ${{fromJSON(needs.get-build-matrix.outputs.matrix)}}
50 |
51 | steps:
52 | - uses: actions/checkout@v3
53 |
54 | - name: Show python versions
55 | id: show-python-versions
56 | run: |
57 | bash -c "ls -al /c/hostedtoolcache/windows/Python/"
58 |
59 | - name: Build if required
60 | id: build-binaries
61 | run: |
62 | bash ./build-win-branch.sh version=${{ inputs.stable_unstable }} configName="${{matrix.name}}" workspace="${{github.workspace}}"
63 | env:
64 | AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
65 | AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
66 |
67 | # - name: Setup tmate session
68 | # if: ${{ failure() }}
69 | # uses: mxschmitt/action-tmate@v3
70 | # with:
71 | # limit-access-to-actor: true
72 | # timeout-minutes: 20
73 |
--------------------------------------------------------------------------------
/docker/orthanc/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -o errexit
3 |
4 | if [[ $# -ne 1 ]]; then
5 | echo "FATAL ERROR: docker-entrypoint.sh expects a single parameter: the path to the configuration files(s)"
6 | exit 2
7 | fi
8 |
9 |
10 | # DCMTK calls gethostid() when generating DICOM UIDs (used, e.g, in modifications/anonymizations).
11 | # When /etc/hostid is missing, the system tries to generate it from the IP of the system.
12 | # On some system, in particular circumstances, we have observed that the system performs a DNS query
13 | # to get the IP of the system. This DNS can timeout (after multiple with retries) and, in particular cases,
14 | # we have observed a delay of 40 seconds to generate a single DICOM UID in Orthanc.
15 | # Therefore, if /etc/hostid is missing, we generate it with a random number. This behaviour can still be deactivated by
16 | # defining GENERATE_HOST_ID_IF_MISSING=false. The host id can also be forced by defining FORCE_HOST_ID
17 | if [[ ! -z $FORCE_HOST_ID ]];then
18 | echo "Forcing hostid in /etc/hostid: $FORCE_HOST_ID"
19 | echo $FORCE_HOST_ID > /etc/hostid
20 | elif [[ ! $GENERATE_HOST_ID_IF_MISSING || $GENERATE_HOST_ID_IF_MISSING == true ]]; then
21 | if [[ ! -f /etc/hostid || $(< /etc/hostid) = 'not-generated' ]]; then
22 | host_id=$(printf '%x' $(shuf -i 268435456-4294967295 -n 1))
23 | echo "Generating random hostid in /etc/hostid: $host_id"
24 | echo $host_id > /etc/hostid
25 | fi
26 | fi
27 |
28 | # generate the configuration file
29 | cd /startup
30 | python3 generateConfiguration.py
31 |
32 | if [[ $TRACE_ENABLED == true ]]; then
33 | verbosity=--trace
34 | elif [[ $VERBOSE_ENABLED == true ]]; then
35 | verbosity=--verbose
36 | fi
37 |
38 | if [[ ! -z $LOGDIR ]];then
39 | logoption=--logdir=$LOGDIR
40 | elif [[ ! -z $LOGFILE ]];then
41 | logoption=--logfile=$LOGFILE
42 | fi
43 |
44 | jobs=""
45 | if [[ $NO_JOBS == true ]]; then
46 | jobs=--no-jobs
47 | fi
48 |
49 | if [[ ! -z $BEFORE_ORTHANC_STARTUP_SCRIPT ]]; then
50 | echo "running custom startup script"
51 | $BEFORE_ORTHANC_STARTUP_SCRIPT
52 | fi
53 |
54 | if [[ $JAVA_PLUGIN_ENABLED == true ]]; then
55 | export LD_PRELOAD=/usr/lib/jvm/default-java/lib/server/libjvm.so
56 | fi
57 |
58 | argv=(Orthanc $verbosity $logoption $jobs "$@")
59 | echo "Startup command: exec \"${argv[*]}\"" >&2
60 | exec "${argv[@]}"
61 |
--------------------------------------------------------------------------------
/release-procedure.txt:
--------------------------------------------------------------------------------
1 |
2 | The docker images and Windows installers are official releases and shall be versioned consistently (they should share the same package numbers and same content).
3 | These packages are numberd by YY.M[.r] where YY is the year, M is the month and r is the release counter for this month (starting at 1).
4 |
5 |
6 | # Upgrading packages
7 |
8 | Each time you want to release a new package (which means you'll upgrade the version of at least one component):
9 |
10 | - search for `CHANGE_VERSION` in the whole repo and look for lines containing the component(s) you're upgrading -> upgrade the versions.
11 | Note: all version numbers shall be in build-matrix.json (except for Windows Installer !)
12 | - search for `CHANGE_VERSION` in the whole repo and look for the package version numbers -> upgrade with YY.M[.r]
13 | - update the WindowsInstaller/Resources/README.txt with the new version numbers
14 | - update the docker/README-dockerhub.txt with the new version numbers (keep the previous version package list in the readme)
15 | - update the release-notes-docker-images.md
16 | - at this stage, you may commit and tag as explained before and let GitHub build the Docker images OR you may build manually with the commands below.
17 | - notify S. Jodogne that a new Windows Installer is available so he can update the download link on the Orthanc page (note, since 22.3.0, the latest
18 | windows installer is always copied under ...latest.exe and there's no need to update the Osimis website anymore)
19 |
20 | All version numbers shall be changed in build-matrix.json (and in release-notes-docker-images.md + README-dockerhub.md)
21 |
22 | List of CHANGE_VERSION_ variables:
23 | - CHANGE_VERSION_ORTHANC
24 | - CHANGE_VERSION_WVB
25 | - CHANGE_VERSION_TRANSFERS
26 | - CHANGE_VERSION_AUTH
27 | - CHANGE_VERSION_MYSQL
28 | - CHANGE_VERSION_ODBC
29 | - CHANGE_VERSION_INDEXER
30 | - CHANGE_VERSION_NEURO
31 | - CHANGE_VERSION_TCIA
32 | - CHANGE_VERSION_STONE_WEB_VIEWER
33 | - CHANGE_VERSION_GDCM
34 | - CHANGE_VERSION_ORTHANC_WEB_VIEWER
35 | - CHANGE_VERSION_DW
36 | - CHANGE_VERSION_PG
37 | - CHANGE_VERSION_WSI
38 | - CHANGE_VERSION_ORTHANC_EXPLORER_2
39 | - CHANGE_ORTHANC_TESTS_VERSION
40 | - CHANGE_VERSION_AZURE_OBJECT_STORAGE
41 | - CHANGE_VERSION_AWS_OBJECT_STORAGE
42 | - CHANGE_VERSION_GOOGLE_OBJECT_STORAGE
43 | - CHANGE_VERSION_VOLVIEW
44 | - CHANGE_VERSION_OHIF
45 | - CHANGE_VERSION_STL
46 | - CHANGE_VERSION_PYTHON
47 | - CHANGE_VERSION_EDUCATION
48 | - CHANGE_VERSION_ORTHANC_WORKLISTS
49 | - CHANGE_VERSION_PIXELS_MASKER
50 |
--------------------------------------------------------------------------------
/WindowsInstaller/Configuration/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Orthanc - A Lightweight, RESTful DICOM Store
2 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
3 | # Department, University Hospital of Liege, Belgium
4 | # Copyright (C) 2017-2023 Osimis S.A., Belgium
5 | # Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
6 | # Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 | #
8 | # This program is free software: you can redistribute it and/or
9 | # modify it under the terms of the GNU General Public License as
10 | # published by the Free Software Foundation, either version 3 of the
11 | # License, or (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful, but
14 | # WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | # General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 |
22 | cmake_minimum_required (VERSION 2.8)
23 |
24 | set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/../Resources/CMake/MinGW-W64-Toolchain32.cmake)
25 | project(WindowsService)
26 |
27 | set(ALLOW_DOWNLOADS ON)
28 | set(STATIC_BUILD ON)
29 |
30 | include(CheckLibraryExists)
31 | include(${CMAKE_SOURCE_DIR}/../Resources/CMake/Compiler.cmake)
32 | include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DownloadPackage.cmake)
33 | include(${CMAKE_SOURCE_DIR}/../Resources/CMake/BoostConfiguration.cmake)
34 |
35 | add_definitions(
36 | -DSERVICE_NAME="Orthanc"
37 | )
38 |
39 | add_library(Toolbox STATIC
40 | Toolbox.cpp
41 | ${BOOST_SOURCES}
42 | )
43 |
44 | add_executable(OrthancService
45 | WindowsService.cpp
46 | )
47 |
48 | add_executable(PatchDefaultConfiguration
49 | PatchDefaultConfiguration.cpp
50 | )
51 |
52 | target_link_libraries(OrthancService Toolbox)
53 | target_link_libraries(PatchDefaultConfiguration Toolbox)
54 |
55 | get_property(OrthancServiceLocation TARGET OrthancService PROPERTY LOCATION)
56 | get_property(PatchDefaultConfigurationLocation TARGET PatchDefaultConfiguration PROPERTY LOCATION)
57 |
58 | add_custom_command(TARGET OrthancService
59 | POST_BUILD
60 | COMMAND i686-w64-mingw32-strip ${OrthancServiceLocation}
61 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
62 | COMMENT "Stripping the symbols from the Windows service" VERBATIM
63 | )
64 |
65 | add_custom_command(TARGET PatchDefaultConfiguration
66 | POST_BUILD
67 | COMMAND i686-w64-mingw32-strip ${PatchDefaultConfigurationLocation}
68 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
69 | COMMENT "Stripping the symbols from the configuration generator" VERBATIM
70 | )
71 |
--------------------------------------------------------------------------------
/.github/workflows/run-docker-integ-tests.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | runner:
13 | description: 'Runner'
14 | type: string
15 | required: true
16 | runner_type:
17 | description: 'Runner type'
18 | type: string
19 | required: true
20 | platform:
21 | description: 'platform'
22 | type: string
23 | required: true
24 | stable_unstable:
25 | description: 'stable_unstable type'
26 | type: string
27 | required: true
28 | tests_group:
29 | description: 'tests group pg, others, full'
30 | type: string
31 | required: true
32 | image_type:
33 | description: 'image type: full, normal'
34 | type: string
35 | required: true
36 |
37 | jobs:
38 | run-integ-tests:
39 | name: run-integ-tests-${{ inputs.tests_group }}-${{ inputs.stable_unstable}}
40 | runs-on: ${{ inputs.runner }}
41 | steps:
42 |
43 | - name: Install Integration tests prerequisites
44 | # TODO: enable on ARM64 too
45 | if: inputs.runner_type == 'github-hosted'
46 | run: sudo apt-get install -y dcmtk
47 |
48 | - uses: actions/checkout@v3
49 | # TODO: enable on ARM64 too
50 | if: inputs.runner_type == 'github-hosted'
51 |
52 | - name: Pull image for integ tests
53 | # TODO: enable on ARM64 too
54 | if: inputs.runner_type == 'github-hosted'
55 | run: ./local-build.sh version=${{ inputs.stable_unstable }} platform=${{ inputs.platform }} image=full type=ci step=pull-before-test-image currentTag=${{ inputs.current_branch_tag }}-normal-${{ inputs.stable_unstable }}
56 |
57 | - name: Run normal image integration tests
58 | # TODO: enable on ARM64 too
59 | if: inputs.runner_type == 'github-hosted'
60 | run: ./run-integration-tests.sh version=${{ inputs.stable_unstable }} image=${{ inputs.image_type }} imageUnderTest=orthancteam/orthanc-pre-release:${{ inputs.current_branch_tag }}-${{ inputs.image_type }}-${{ inputs.stable_unstable }}-before-tests-amd64 testsGroup=${{ inputs.tests_group }}
61 | working-directory: ${{github.workspace}}/docker/integration-tests
62 |
63 | - name: Skipped for ARM64
64 | # TODO: enable on ARM64 too
65 | if: inputs.runner_type != 'github-hosted'
66 | run: echo "skipped on ARM 64"
67 |
68 | - name: Setup tmate session
69 | if: ${{ failure() }}
70 | uses: mxschmitt/action-tmate@v3
71 | with:
72 | limit-access-to-actor: true
73 | timeout-minutes: 20
74 |
--------------------------------------------------------------------------------
/docker/SBOM.txt:
--------------------------------------------------------------------------------
1 | This Software Bill Of Material is manually generated.
2 | It was last generated for orthancteam/orthanc:25.6.4 images and lists only the
3 | primary dependencies of Orthanc; not its plugins.
4 |
5 |
6 | Orthanc third-parties library statically linked:
7 |
8 | DCMTK ; https://github.com/DCMTK/dcmtk ; 3.6.9
9 | Civetweb ; https://github.com/civetweb/civetweb ; 1.14
10 | OpenSSL ; https://github.com/openssl/openssl ; 3.1.4
11 | curl ; https://github.com/curl/curl ; 8.9.0
12 |
13 | Orthanc third-parties library dynamically linked (depending on the base image, currently: ubuntu 24.04):
14 | info extracted from "ldd /usr/local/bin/Orthanc" and "apt list | grep jsoncpp"
15 |
16 | JsonCpp ; https://github.com/open-source-parsers/jsoncpp ; 1.9.5-6build1
17 | SQLite ; https://github.com/sqlite/sqlite ; 3.45.1-1ubuntu2.3
18 | LibJpeg ; https://github.com/winlibs/libjpeg ; 8c-2ubuntu11
19 | Zlib ; https://github.com/madler/zlib ; 1.3.1+dfsg-1
20 | LibPNG ; https://github.com/pnggroup/libpng ; 1.6.43-5build1
21 | Lua ; https://github.com/lua/lua ; 5.4.6-3build2
22 | Pugixml ; https://github.com/zeux/pugixml ; 1.14-0.1build1
23 | Protobuf ; https://github.com/protocolbuffers/protobuf ; 3.21.12-8.2ubuntu0.1
24 | LibUuid ; https://github.com/util-linux/util-linux/tree/master/libuuid ; 2.39.3-9ubuntu6.2
25 | Boost ; https://github.com/boostorg/boost ; 1.83.0-2.1ubuntu3.1
26 | Libgcc & co ; https://github.com/gcc-mirror/gcc/tree/master/libgcc ; 14.2.0-4ubuntu2~24.04cross1
27 | LibIcu ; https://github.com/unicode-org/icu ; 74.2-1ubuntu3.1
28 | bzip2 ; https://gitlab.com/bzip2/bzip2 ; 1.0.8-5.1build0.1
29 | XZ ; https://sourceforge.net/projects/lzmautils/ ; 5.6.1+really5.4.5-1ubuntu0.2
30 | zstd ; https://github.com/facebook/zstd ; 1.5.5+dfsg2-2build1.1
31 |
32 |
33 |
--------------------------------------------------------------------------------
/docker/orthanc/helpers.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import glob
4 | import json
5 | import typing
6 |
7 |
8 | class JsonPath:
9 |
10 | def __init__(self, path:str = None):
11 | if path is None or len(path) == 0:
12 | self.tokens = []
13 | else:
14 | self.tokens = path.split(".")
15 |
16 | def first(self):
17 | if self.length() == 0:
18 | raise ValueError("Empty path")
19 |
20 | return self.tokens[0]
21 |
22 | def nexts(self, fromIndex=1):
23 | if self.length() < fromIndex:
24 | raise ValueError("Path too short")
25 |
26 | return JsonPath(".".join(self.tokens[fromIndex:]))
27 |
28 | def pop(self) -> str:
29 | if self.length() == 0:
30 | raise ValueError("Empty path")
31 |
32 | first = self.tokens[0]
33 | self.tokens = self.tokens[1:]
34 | return first
35 |
36 | def append(self, token: str):
37 | self.tokens.append(token)
38 |
39 | def length(self):
40 | return len(self.tokens)
41 |
42 | def __str__(self):
43 | return ".".join(self.tokens)
44 |
45 | def clone(self):
46 | return JsonPath(".".join(self.tokens))
47 |
48 |
49 | verboseEnabled = False
50 |
51 | def enableVerboseModeForConfigGeneration():
52 | global verboseEnabled
53 | verboseEnabled = True
54 |
55 | def logInfo(text: str):
56 | global verboseEnabled
57 | if verboseEnabled:
58 | print(text)
59 |
60 | def logWarning(text: str):
61 | print("WARNING: " + text)
62 |
63 | def logError(text: str):
64 | print("ERROR: " + text)
65 |
66 |
67 | def isEnvVarDefinedEmptyOrTrue(envVar: str) -> bool:
68 | return envVar in os.environ and (os.environ.get(envVar) == "" or os.environ.get(envVar) == "true")
69 |
70 | def isEnvVarTrue(envVar: str) -> bool:
71 | return os.environ.get(envVar, "false") == "true"
72 |
73 |
74 | # transforms QUERY_RETRIEVE_SIZE into QueryRetrieveSize
75 | def envVarToCamelCase(envVarName: str) -> str:
76 | name = ""
77 | for word in envVarName.split("_"):
78 | name = name + word[0] + word.lower()[1:]
79 | return name
80 |
81 |
82 | def removeCppCommentsFromJson(text: str):
83 | def replacer(match):
84 | s = match.group(0)
85 | if s.startswith('/'):
86 | return " " # note: a space and not an empty string
87 | else:
88 | return s
89 | pattern = re.compile(
90 | r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
91 | re.DOTALL | re.MULTILINE
92 | )
93 | return re.sub(pattern, replacer, text)
94 |
95 | def insertInDict(jsonPath: JsonPath, value: any) -> dict:
96 |
97 | if jsonPath.length() == 1:
98 | output = {}
99 | output[jsonPath.first()] = value
100 | return output
101 | else:
102 | output = {}
103 | output[jsonPath.first()] = insertInDict(jsonPath.nexts(1), value)
104 | return output
105 |
106 |
107 |
--------------------------------------------------------------------------------
/WindowsInstaller/Configuration/Toolbox.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Orthanc - A Lightweight, RESTful DICOM Store
3 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 | * Department, University Hospital of Liege, Belgium
5 | * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 | * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
7 | * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
8 | *
9 | * This program is free software: you can redistribute it and/or
10 | * modify it under the terms of the GNU General Public License as
11 | * published by the Free Software Foundation, either version 3 of the
12 | * License, or (at your option) any later version.
13 | *
14 | * This program is distributed in the hope that it will be useful, but
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with this program. If not, see .
21 | **/
22 |
23 |
24 | #include "Toolbox.h"
25 |
26 | std::wstring GetStringRegKey(const std::wstring& key,
27 | const std::wstring& name,
28 | const std::wstring& defaultValue)
29 | {
30 | HKEY hKey;
31 | if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
32 | {
33 | return defaultValue;
34 | }
35 |
36 | WCHAR szBuffer[512];
37 | DWORD dwBufferSize = sizeof(szBuffer);
38 | if (RegQueryValueExW(hKey, name.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize) != ERROR_SUCCESS)
39 | {
40 | RegCloseKey(hKey);
41 | return defaultValue;
42 | }
43 |
44 | RegCloseKey(hKey);
45 | return szBuffer;
46 | }
47 |
48 |
49 | std::string GetStringRegKeyAnsi(const std::string& key,
50 | const std::string& name,
51 | const std::string& defaultValue)
52 | {
53 | HKEY hKey;
54 | if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
55 | {
56 | return defaultValue;
57 | }
58 |
59 | CHAR szBuffer[512];
60 | DWORD dwBufferSize = sizeof(szBuffer);
61 | if (RegQueryValueExA(hKey, name.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize) != ERROR_SUCCESS)
62 | {
63 | RegCloseKey(hKey);
64 | return defaultValue;
65 | }
66 |
67 | RegCloseKey(hKey);
68 | return szBuffer;
69 | }
70 |
71 |
72 | DWORD GetDWordRegKey(const std::wstring& key,
73 | const std::wstring& name,
74 | DWORD defaultValue)
75 | {
76 | HKEY hKey;
77 | if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
78 | {
79 | return defaultValue;
80 | }
81 |
82 | DWORD dwBufferSize(sizeof(DWORD));
83 | DWORD nResult(0);
84 | if (RegQueryValueExW(hKey, name.c_str(), 0, NULL,
85 | reinterpret_cast(&nResult), &dwBufferSize) != ERROR_SUCCESS)
86 | {
87 | RegCloseKey(hKey);
88 | return defaultValue;
89 | }
90 |
91 | RegCloseKey(hKey);
92 | return nResult;
93 | }
94 |
--------------------------------------------------------------------------------
/docker/orthanc/Dockerfile.runner-base:
--------------------------------------------------------------------------------
1 | ########################## orthanc-runner-base
2 |
3 | # base image to build and execute orthanc.
4 | # This image should contain only the packages that are common to both !
5 | # The purpose of this intermediate image is to benefit from Docker cache.
6 | ARG BASE_UBUNTU_IMAGE=unknown
7 | FROM ubuntu:$BASE_UBUNTU_IMAGE
8 |
9 | # we had some issues with one of the mirror -> force it to the Belgian mirror
10 | # RUN rm /etc/apt/sources.list.d/debian.sources
11 | # RUN echo "deb http://ftp.be.debian.org/debian/ bookworm main" | tee /etc/apt/sources.list.d/belgium.mirror.list
12 |
13 | RUN export DEBIAN_FRONTEND=noninteractive && \
14 | apt-get --assume-yes update && \
15 | apt-get --assume-yes install --no-install-recommends python3 && \
16 | apt-get --assume-yes install --no-install-recommends python3-dev && \
17 | apt-get --assume-yes install --no-install-recommends python3-pip && \
18 | apt-get --assume-yes install --no-install-recommends ca-certificates && \
19 | apt-get --assume-yes install --no-install-recommends tzdata && \
20 | apt-get --assume-yes install --no-install-recommends locales && \
21 | apt-get --assume-yes install --no-install-recommends libcurl4 && \
22 | apt-get --assume-yes install --no-install-recommends libboost-log1.83.0 libboost-filesystem1.83.0 libboost-locale1.83.0 libboost-regex1.83.0 libboost-system1.83.0 libboost-thread1.83.0 libboost-iostreams1.83.0 && \
23 | apt-get --assume-yes install --no-install-recommends libjpeg62 && \
24 | apt-get --assume-yes install --no-install-recommends libjsoncpp25 && \
25 | apt-get --assume-yes install --no-install-recommends liblua5.4 && \
26 | apt-get --assume-yes install --no-install-recommends libpng16-16 && \
27 | apt-get --assume-yes install --no-install-recommends libpugixml1v5 && \
28 | apt-get --assume-yes install --no-install-recommends libsqlite3-0 && \
29 | apt-get --assume-yes install --no-install-recommends libssl3 && \
30 | apt-get --assume-yes install --no-install-recommends libuuid1 && \
31 | apt-get --assume-yes install --no-install-recommends lsb-base && \
32 | apt-get --assume-yes install --no-install-recommends libpq5 && \
33 | apt-get --assume-yes install --no-install-recommends libmysqlclient21 && \
34 | apt-get --assume-yes install --no-install-recommends unixodbc && \
35 | apt-get --assume-yes install --no-install-recommends libopenslide0 && \
36 | apt-get --assume-yes install --no-install-recommends libcrypto++8 && \
37 | apt-get --assume-yes install --no-install-recommends libcpprest && \
38 | apt-get --assume-yes install --no-install-recommends libprotobuf32 && \
39 | apt-get --assume-yes install --no-install-recommends pkg-config && \
40 | apt-get --assume-yes install --no-install-recommends zlib1g && \
41 | apt-get --assume-yes clean && \
42 | rm --recursive --force /var/lib/apt/lists/*
43 |
44 | # disabled packages because of CVEs -> we use the static libraries instead
45 | # apt-get --assume-yes install --no-install-recommends libdcmtk17 && \
46 |
47 | # Make sure the en_US locale has been generated (required for
48 | # case-insensitive comparison of strings with accents)
49 | RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
50 | RUN locale-gen
51 |
--------------------------------------------------------------------------------
/WindowsInstaller/ciBuildWindowsInstaller.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # to run locally: ./ciBuildWindowsInstaller.sh false test local
4 |
5 | set -x #to debug the script
6 | set -e #to exit the script at the first failure
7 |
8 |
9 | is_tag=${1:-false}
10 | branch_tag_name=${2:-unknown}
11 | type=${3:-local}
12 |
13 |
14 | # the version must always be X.Y.Z
15 | if [[ $is_tag == "true" ]]; then
16 | version=$branch_tag_name
17 | else
18 | version=0.0.0
19 | fi
20 |
21 | if [[ $type == "local" ]]; then
22 | from_cache_arg=
23 | to_cache_arg=
24 |
25 | # when building locally, use Docker builder (easier to reuse local images)
26 | build="build"
27 | else
28 | from_cache_arg="--cache-from=orthancteam/orthanc-builder-base:win-installer"
29 | to_cache_arg="--cache-to=orthancteam/orthanc-builder-base:win-installer"
30 |
31 | # when building in CI, use buildx
32 | build="buildx build"
33 | fi
34 |
35 | add_host_cmd=--add-host=orthanc.uclouvain.be:130.104.229.21
36 |
37 | add_host_cmd=--add-host=orthanc.uclouvain.be:130.104.229.21
38 |
39 | # docker build --progress=plain -t installer-builder-32 -f Dockerfile --build-arg VERSION=$version --build-arg PLATFORM=32 ..
40 |
41 | docker $build \
42 | $add_host_cmd \
43 | --progress=plain -t installer-builder-32 \
44 | --build-arg VERSION=$version \
45 | --build-arg PLATFORM=32 \
46 | $from_cache_arg \
47 | $to_cache_arg \
48 | -f Dockerfile \
49 | ..
50 |
51 |
52 | # build Windows 32 bits
53 | dockerContainerId=$(docker create installer-builder-32)
54 |
55 |
56 | # copy the orthanc.json generated from the 32 bits version (we can't generate it with wine and Orthanc 64 bits)
57 | docker cp $dockerContainerId:/tmp/OrthancInstaller/orthanc.json .
58 | docker cp $dockerContainerId:/tmp/OrthancInstaller/OrthancInstaller-Win32.exe .
59 | docker rm $dockerContainerId
60 |
61 | # build Windows 64 bits
62 | docker $build \
63 | $add_host_cmd \
64 | --progress=plain -t installer-builder-64 \
65 | --build-arg VERSION=$version \
66 | --build-arg PLATFORM=64 \
67 | $from_cache_arg \
68 | $to_cache_arg \
69 | -f Dockerfile \
70 | ..
71 |
72 |
73 | dockerContainerId=$(docker create installer-builder-64)
74 | docker cp $dockerContainerId:/tmp/OrthancInstaller/OrthancInstaller-Win64.exe .
75 | docker rm $dockerContainerId
76 |
77 |
78 | # upload files to AWS
79 | #####################
80 |
81 | # we first need to create the container before we can copy files to it
82 | export AWS_ACCESS_KEY_ID
83 | export AWS_SECRET_ACCESS_KEY
84 | awsContainerId=$(docker create $add_host_cmd -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY anigeo/awscli s3 --region eu-west-1 cp /tmp/ s3://public-files.orthanc.team/tmp-builds/win-installer/ --recursive --exclude "*" --include "OrthancInstaller*" --cache-control=max-age=1)
85 |
86 | # CHANGE_VERSION_WIN_INSTALLER
87 | docker cp OrthancInstaller-Win32.exe $awsContainerId:/tmp/OrthancInstaller-Win32-$branch_tag_name.exe
88 | docker cp OrthancInstaller-Win64.exe $awsContainerId:/tmp/OrthancInstaller-Win64-$branch_tag_name.exe
89 |
90 | if [[ $is_tag == "true" ]]; then
91 | docker cp OrthancInstaller-Win32.exe $awsContainerId:/tmp/OrthancInstaller-Win32-latest.exe
92 | docker cp OrthancInstaller-Win64.exe $awsContainerId:/tmp/OrthancInstaller-Win64-latest.exe
93 | fi
94 |
95 | # upload
96 | docker start -a $awsContainerId
97 |
98 | # remove container
99 | docker rm $awsContainerId
100 |
--------------------------------------------------------------------------------
/docker/orthanc/generateConfiguration.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import glob
4 | import json
5 | import typing
6 | import tempfile
7 | import subprocess
8 | from envsubst import envsubst
9 |
10 | from helpers import JsonPath, logInfo, logWarning, logError, removeCppCommentsFromJson, isEnvVarDefinedEmptyOrTrue, enableVerboseModeForConfigGeneration
11 | from configurator import OrthancConfigurator
12 |
13 |
14 | configurator = OrthancConfigurator(folder = os.path.dirname(os.path.realpath(__file__)))
15 |
16 | if isEnvVarDefinedEmptyOrTrue("VERBOSE_STARTUP"):
17 | enableVerboseModeForConfigGeneration()
18 |
19 | if isEnvVarDefinedEmptyOrTrue("BUNDLE_DEBUG"):
20 | logWarning("You're using a deprecated env-var, you should use VERBOSE_STARTUP instead of BUNDLE_DEBUG")
21 | enableVerboseModeForConfigGeneration()
22 |
23 |
24 | ################# read all configuration files ################################
25 | configFiles = []
26 |
27 | logInfo("Discovering configuration files from /etc/orthanc/*.json")
28 | for filePath in glob.glob("/etc/orthanc/*.json"):
29 | configFiles.append(filePath)
30 |
31 | logInfo("Discovering configuration files from /run/secrets/*.json")
32 | for filePath in glob.glob("/run/secrets/*.json"):
33 | configFiles.append(filePath)
34 |
35 | for filePath in configFiles:
36 | logInfo("reading configuration from " + filePath)
37 | with open(filePath, "r") as f:
38 | content = f.read()
39 |
40 | # perform standard env var substitution before trying to read the json file (https://github.com/orthanc-server/orthanc-builder/issues/9)
41 | content = envsubst(content)
42 | try:
43 | cleanedContent = removeCppCommentsFromJson(content)
44 | configFromFile = json.loads(cleanedContent)
45 | except:
46 | logError("Unable to parse Json file '{f}'; check syntax".format(f = filePath))
47 |
48 | configurator.mergeConfigFromFile(configFromFile, filePath)
49 |
50 | ################# read all environment variables ################################
51 |
52 | logInfo("Analyzing environment variables")
53 | for envKey, envValue in os.environ.items():
54 |
55 | configurator.mergeConfigFromEnvVar(envKey, envValue)
56 |
57 | ################# read all secrets ################################
58 |
59 | logInfo("Analyzing secrets")
60 |
61 | for secretPath in glob.glob("/run/secrets/*"):
62 | logInfo("secret: " + secretPath)
63 |
64 | if os.path.isfile(secretPath):
65 | with open(secretPath, "r") as fp:
66 | secretValue = fp.read().rstrip("\n")
67 |
68 | configurator.mergeConfigFromSecret(secretPath, secretValue)
69 |
70 | ################# apply defaults that have not been set yet (from Orthanc and plugins) ################################
71 |
72 | configurator.mergeConfigFromDefaults(moveSoFiles=True)
73 |
74 |
75 | logInfo("generated configuration file: " + json.dumps(configurator.configuration, indent=2))
76 |
77 | if configurator.hasDeprecatedSettings:
78 | logWarning("************* you are using deprecated settings, these deprecated settings will be removed in June 2021 *************")
79 |
80 | if configurator.hasErrors:
81 | logError("There were some errors while preparing the configuration file for Orthanc.")
82 | exit(-1)
83 |
84 |
85 | configFilePath="/tmp/orthanc.json"
86 | logInfo("generating temporary configuration file in " + configFilePath)
87 | with open(configFilePath, "w+t") as fp:
88 | json.dump(configurator.configuration, fp=fp, indent=2)
89 |
--------------------------------------------------------------------------------
/README-dockerhub.md:
--------------------------------------------------------------------------------
1 | # Orthanc for Docker
2 | Docker image with [Orthanc](https://www.orthanc-server.com/) and its official plugins. Orthanc is a lightweight, RESTful Vendor Neutral Archive for medical imaging.
3 |
4 | Note: the Orthanc version included in this image is exactly the same as the Orthanc included in the `jodogne/orthanc` image. However,
5 | this image contains a few plugins that are not included in the `jodogne/orthanc-plugins` image. Furthermore,
6 | this image provides an easy configuration through environment variables which is not the case of the `jodogne/orthanc` image.
7 |
8 | Starting from the `22.6.1` release, we are providing 2 types of images:
9 | - the default image with the usual tag: e.g `22.6.1`
10 | - the full image with a e.g `22.6.1-full` tag
11 |
12 | The default image is suitable for 99.9% of users.
13 | You should use the full image only if you need to use one of these:
14 | - the Azure Blob storage plugin
15 | - the Google Cloud storage plugin
16 | - the ODBC plugin with SQL Server (msodbcsql18 is preinstalled)
17 |
18 | Full documentation is available [here](https://book.orthanc-server.com/users/docker-orthancteam.html).
19 |
20 | Sample setups using this image are available [here](https://github.com/orthanc-server/orthanc-setup-samples/).
21 |
22 | Release notes are available [here](https://github.com/orthanc-server/orthanc-builder/blob/master/release-notes-docker-images.md)
23 |
24 |
25 | # packages content
26 |
27 | #### 25.12.3 Default image
28 | ```
29 | component version
30 | ---------------------------------------------
31 | Orthanc server 1.12.10
32 | Serve folders plugin 1.12.10
33 | Connectivity check plugin 1.12.10
34 | Housekeeper plugin 1.12.10
35 | Delayed Deletion plugin 1.12.10
36 | Multitenant DICOM plugin 1.12.10
37 | Stone Web viewer plugin 2.6+266b0b912c35
38 | Osimis Web viewer plugin 1.4.3
39 | Python plugin 7.0
40 | Orthanc Web viewer plugin 2.10
41 | DICOMweb plugin 1.22
42 | PostgreSQL plugins 10.0
43 | MySQL plugins 5.2
44 | WSI Web viewer plugin 3.3
45 | Authorization plugin 0.10.3
46 | Transfers accelerator plugin 1.7
47 | GDCM plugin 1.8
48 | ODBC plugin 1.3
49 | TCIA plugin 1.2
50 | Orthanc Indexer plugin 1.1
51 | Orthanc neuroimaging plugin 1.1
52 | AWS S3 plugin 2.5.0
53 | Orthanc Explorer 2 1.10.1
54 | Kitware's VolView plugin 1.3
55 | OHIF plugin 1.7
56 | STL plugin 1.3
57 | Advanced Storage plugin 0.2.3
58 | Education plugin 1.1
59 | Worklists plugin 0.9.2
60 | Pixels masker plugin 0.1.1
61 |
62 | System components version
63 | ---------------------------------------------
64 | Base image Ubuntu version 24.04 (noble)
65 | Python 3.12
66 | Lua 5.4
67 |
68 | ```
69 |
70 | #### 25.12.3-full image
71 | ```
72 | additional component version
73 | ---------------------------------------------
74 | Azure Blob Storage plugin 2.3.1
75 | Google Cloud Storage plugin 2.5.1
76 | Java plugin 2.0
77 | ````
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | This repo contains build instructions for the following components:
4 |
5 | - the `orthancteam/orthanc` Docker image
6 | - the Windows installer
7 | - the MacOS package (zip with Orthanc executable and plugins)
8 |
9 | The Docker image is rebuilt from scratch (Orthanc and all its plugins are compiled during the build process).
10 | Windows Installer and MacOS package are collecting build artifacts from the Orthanc buildbot server.
11 |
12 | # Where to find the releases ?
13 |
14 | ## stable releases
15 |
16 | - [Docker image (linux/amd64)](https://hub.docker.com/r/orthancteam/orthanc)
17 | - [Windows 64 bits installer](https://orthanc.uclouvain.be/downloads/windows-64/installers/index.html)
18 | - [Windows 32 bits installer](https://orthanc.uclouvain.be/downloads/windows-32/installers/index.html)
19 | - [MacOS package (Universal)](https://orthanc.uclouvain.be/downloads/macos/packages/universal/index.html)
20 |
21 | ## unstable releases (nightly builds)
22 |
23 | - [Docker image (linux/amd64)](https://hub.docker.com/r/orthancteam/orthanc-unstable) (`orthancteam/orthanc-unstable:master` image)
24 |
25 |
26 | - [MacOS package (Universal)](https://public-files.orthanc.team/MacOS-packages/Orthanc-MacOS-master-unstable.zip)
27 |
28 |
29 | **Notes**:
30 |
31 | - to build stable Docker images locally, use `./local-build.sh skipCommitChecks=1`. This produces `orthancteam/orthanc:current` images.
32 | - The MacOS package does not contain the WSI plugin that can currently be built only for Intel processors.
33 |
34 | ## building ARM 64 docker images
35 |
36 | You can use this repo to build `linux/arm64` docker images but we are currently not able to build them on our build slaves because, with QEMU emulation, a build would take more than 12 hours which is the limit of github actions.
37 |
38 | Hereunder, you'll find the full instructions to build ARM64 docker images on MacOS (note: this won't build Azure & Google object-storage plugins). Note, the StoneViewer build can last very long (multiple hours) because it is using an emulated container to build the WebAssembly code:
39 | ```
40 | brew install jq
41 | brew install hg
42 |
43 | git clone https://github.com/orthanc-server/orthanc-builder.git
44 | cd orthanc-builder
45 | ./local-build.sh version=stable platform=linux/arm64 image=normal
46 | ```
47 |
48 | This produces an image `orthancteam/orthanc:current`.
49 |
50 |
51 | # Continuous Builds
52 |
53 | - MacOS stable/unstable binaries and packages are rebuilt every night (if needed) and on every commit
54 | - Windows stable installers are rebuilt at every commit, they are available at:
55 | - [https://public-files.orthanc.team/tmp-builds/win-installer/OrthancInstaller-Win64-master.exe](https://public-files.orthanc.team/tmp-builds/win-installer/OrthancInstaller-Win64-master.exe)
56 | - Docker stable and unstable images are rebuilt every night and on every commit of this repo, they are available as:
57 | - `orthancteam/orthanc:master`
58 | - `orthancteam/orthanc-unstable:master`
59 | - Integration tests are run for every Docker build
60 |
61 | # Troubleshooting (for dev)
62 |
63 | - if a MacOS build fails, you may connect to the build slave thanks to `tmate`. Access is limited to approved actors with their SSH Github key.
64 |
65 |
66 | # Creating multi-platform image
67 |
68 | image=orthancteam/orthanc-pre-release
69 | tag=24.3.5
70 | docker manifest create $image:$tag $image:$tag-amd64 $image:$tag-arm64
71 | docker manifest annotate $image:$tag $image:$tag-amd64 --os linux --arch amd64
72 | docker manifest annotate $image:$tag $image:$tag-arm64 --os linux --arch arm64
73 | docker manifest push orthancteam/orthanc-pre-release:$tag
74 |
75 |
--------------------------------------------------------------------------------
/UCLouvain/CreateMacOSPackage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Orthanc - A Lightweight, RESTful DICOM Store
4 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
5 | # Department, University Hospital of Liege, Belgium
6 | # Copyright (C) 2017-2023 Osimis S.A., Belgium
7 | # Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
8 | # Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
9 | #
10 | # This program is free software: you can redistribute it and/or
11 | # modify it under the terms of the GNU Lesser General Public License
12 | # as published by the Free Software Foundation, either version 3 of
13 | # the License, or (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful, but
16 | # WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 | # Lesser General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU Lesser General Public
21 | # License along with this program. If not, see
22 | # .
23 |
24 |
25 | import json
26 | import os
27 | import requests
28 | import sys
29 | import time
30 | import zipfile
31 |
32 | import Toolbox
33 |
34 | if len(sys.argv) != 3:
35 | print('Usage: %s [target ZIP] [version]' % sys.argv[0])
36 | print('Example: %s /tmp/MacOS.zip 23.11.0' % sys.argv[0])
37 | exit(-1)
38 |
39 | TARGET = sys.argv[1]
40 | PREFIX = 'Orthanc-MacOS-%s' % sys.argv[2]
41 |
42 |
43 | def AddContentToZip(archive, content, targetPath, isExecutable):
44 | info = zipfile.ZipInfo(os.path.join(PREFIX, targetPath))
45 | info.compress_type = zipfile.ZIP_DEFLATED # If not set, no compression takes place
46 | info.date_time = time.localtime()
47 |
48 | if isExecutable:
49 | info.external_attr = 0o100755 << 16 # -rwxr-xr-x permissions (755 in octal)
50 | else:
51 | info.external_attr = 0o100644 << 16 # -rw-r--r-- permissions (644 in octal)
52 |
53 | archive.writestr(info, content)
54 |
55 |
56 | def AddFile(archive, sourcePath, targetPath = None, isExecutable = False):
57 | if targetPath == None:
58 | targetPath = os.path.basename(sourcePath)
59 |
60 | with open(os.path.join(BASE, sourcePath), 'rb') as f:
61 | AddContentToZip(archive, f.read(), targetPath, isExecutable)
62 |
63 |
64 | def DownloadFile(archive, url, targetPath = None, isExecutable = False):
65 | if targetPath == None:
66 | targetPath = url.split('/') [-1]
67 |
68 | print(' downloading: %s' % url)
69 | r = requests.get(url)
70 | r.raise_for_status()
71 | AddContentToZip(archive, r.content, targetPath, isExecutable)
72 |
73 |
74 | BASE = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
75 |
76 |
77 | with open(os.path.join(BASE, 'build-matrix.json')) as f:
78 | matrix = json.loads(f.read())
79 |
80 |
81 | with zipfile.ZipFile(TARGET, 'w', compression = zipfile.ZIP_DEFLATED) as archive:
82 | AddFile(archive, 'orthancBuildResources/readmeMacOS.txt', 'readme.txt')
83 | AddFile(archive, 'orthancBuildResources/configMacOS.json')
84 | AddFile(archive, 'orthancBuildResources/startOrthanc.command', isExecutable = True)
85 | AddFile(archive, 'WindowsInstaller/Resources/ca-certificates.crt')
86 |
87 | for project in matrix['configs']:
88 | if project['name'].startswith('XXXX'): # This is a documentation
89 | continue
90 |
91 | if not 'downloadsMacOS' in project:
92 | print('Skipping project without MacOS binaries: %s' % project['name'])
93 | continue
94 |
95 | version = Toolbox.GetVersion(project)
96 |
97 | for f in project['downloadsMacOS']:
98 | if isinstance(f, str):
99 | url = f.replace('${VERSION}', version)
100 | DownloadFile(archive, url)
101 | else:
102 | url = f['url'].replace('${VERSION}', version)
103 | DownloadFile(archive, url, f.get('target', None), f.get('executable', False))
104 |
--------------------------------------------------------------------------------
/docker/orthanc/test-aliveness.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # this scripts performs a readiness/aliveness check of orthanc by simply calling
4 | # the /changes route from inside the container.
5 | # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
6 | # when using mTLS at Orthanc level, it is impossible to use the built-in K8 HttpGet probes hence this script.
7 | #
8 | # usage:
9 | # ./test-aliveness.py --http_port=8042 --user=toto --pwd=tutu --http_scheme=http --certfile=/my/client.cert.pem --keyfile=/my/client.key.pem --keypwd=mykeypwd
10 | # the http_port, http_scheme, user and pwd arguments are extracted from the orthanc configuration file if not provided.
11 | # check https://docs.python.org/3/library/ssl.html#ssl.SSLContext.load_cert_chain for more details about the 3 cert arguments
12 |
13 | import urllib.request # we don't use the requests module to avoid forcing installation for everyone
14 | import sys
15 | import json
16 | import base64
17 | import ssl
18 | import argparse
19 | import traceback
20 |
21 |
22 | http_port = 8042
23 | headers = {}
24 | user = None
25 | pwd = None
26 | certfile = None
27 | keyfile = None
28 | keypwd = None
29 | http_scheme = 'http'
30 |
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument('--http_port', type=int)
33 | parser.add_argument('--http_scheme', type=str)
34 | parser.add_argument('--user', type=str)
35 | parser.add_argument('--pwd', type=str)
36 | parser.add_argument('--certfile', type=str)
37 | parser.add_argument('--keyfile', type=str)
38 | parser.add_argument('--keypwd', type=str)
39 |
40 | args = parser.parse_args()
41 |
42 | # first try to read port number + user credentials from the configuration file
43 | try:
44 | with open('/tmp/orthanc.json', 'rb') as config_file:
45 | config = json.load(config_file)
46 |
47 | if 'HttpPort' in config:
48 | http_port = config['HttpPort']
49 |
50 | if 'AuthenticationEnabled' in config and config['AuthenticationEnabled']:
51 | if 'RegisteredUsers' in config and len(config['RegisteredUsers']):
52 | if args.user:
53 | pwd = config['RegisteredUsers'].get(args.user, '')
54 | else:
55 | for u, p in config['RegisteredUsers'].items():
56 | user = u
57 | pwd = p
58 | break
59 |
60 | if 'SslEnabled' in config and config['SslEnabled']:
61 | http_scheme = 'https'
62 |
63 | except:
64 | pass
65 |
66 |
67 | # override the values from the config file with the values from the command line
68 |
69 | if args.http_port:
70 | http_port = args.http_port
71 |
72 | if args.user:
73 | user = args.user
74 |
75 | if args.pwd:
76 | pwd = args.pwd
77 |
78 | if args.http_scheme:
79 | http_scheme = args.http_scheme
80 |
81 | if args.certfile:
82 | certfile = args.certfile
83 | http_scheme = 'https'
84 |
85 | if args.keyfile:
86 | keyfile = args.keyfile
87 |
88 | if args.keypwd:
89 | keypwd = args.keypwd
90 |
91 | try:
92 | ssl_context = None
93 | ssl_context = ssl.SSLContext()
94 | ssl_context.verify_mode = ssl.CERT_NONE # skip verification of server cert
95 |
96 | if certfile:
97 | ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile, password=keypwd)
98 |
99 | # In previous version, we were actually calling /system but it is actually not accessing the DB because
100 | # the DB version is cached -> call /changes instead
101 | req = urllib.request.Request(f'{http_scheme}://localhost:{http_port}/changes?last')
102 |
103 | if user and pwd:
104 | base_64_credentials = base64.b64encode(bytes(f"{user}:{pwd}", 'utf-8'))
105 | req.add_header('Authorization', 'Basic %s' % base_64_credentials.decode('utf-8'))
106 |
107 | with urllib.request.urlopen(req, context=ssl_context) as f:
108 | if f.status == 200:
109 | sys.exit(0)
110 |
111 | except Exception:
112 | print(traceback.format_exc())
113 | sys.exit(1)
114 |
--------------------------------------------------------------------------------
/docker/orthanc/generatePluginDoc.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import glob
4 | import json
5 | import typing
6 | import tempfile
7 | import subprocess
8 | import argparse
9 |
10 | from configurator import OrthancConfigurator
11 |
12 | # examples:
13 | # from docker/orthanc
14 | # python3 generatePluginDoc.py
15 | # python3 generatePluginDoc.py --folder ../orthanc-pro-builder --output html
16 |
17 | parser = argparse.ArgumentParser(description='Generates the plugins section of the documentation.')
18 | parser.add_argument('--folder', type=str, default=None,
19 | help='folder to parse (search plugins-def.json')
20 | parser.add_argument('--output', type=str, default="rst",
21 | help='output format (rst or html)')
22 |
23 | args = parser.parse_args()
24 |
25 | colWidths = [50, 50, 100]
26 |
27 | def printSeparatorLine(char):
28 | print("+" + char*colWidths[0] + "+" + char*colWidths[1] + "+" + char*colWidths[2] + "+")
29 |
30 | def fixedLengthString(length):
31 | return "{0:" + str(length) + "}"
32 |
33 | def printContentLine(cells):
34 | i = 0
35 | outputCells = []
36 | for cell in cells:
37 | if cell is None:
38 | cell = ""
39 | outputCells.append(fixedLengthString(colWidths[i]-2).format(cell)) # -2 for the 2 white spaces around '|'
40 |
41 | i = i + 1
42 |
43 | print("| " + " | ".join(outputCells) + " |")
44 |
45 |
46 | configurator = OrthancConfigurator(args.folder)
47 |
48 | if args.output == "rst":
49 |
50 | printSeparatorLine("-")
51 | printContentLine(["Plugin", "Environment variable", "Default configuration"])
52 | printSeparatorLine("=")
53 |
54 | for pluginName, pluginDef in configurator.pluginsDef.items():
55 | if "section" in pluginDef:
56 | section = pluginDef["section"]
57 | else:
58 | section = pluginName
59 |
60 | cell0 = ["**" + pluginName + "**"]
61 | cell1 = ["``" + pluginDef["enablingEnvVar"] + "``"]
62 | cell2 = [".. code-block:: json", ""]
63 |
64 | if "enabledByDefault" in pluginDef and pluginDef["enabledByDefault"]:
65 | cell1.append("Note: enabled by default")
66 |
67 | if "nonStandardDefaults" in pluginDef:
68 | defaultSettings = {
69 | section: pluginDef["nonStandardDefaults"]
70 | }
71 | jsonString = json.dumps(defaultSettings, indent=2)
72 |
73 | for jsonLine in jsonString.split("\n"):
74 | cell2.append(" " + jsonLine)
75 |
76 | else:
77 | cell2 = [""]
78 |
79 | for l in range(max(len(c) for c in [cell0, cell1, cell2])):
80 | c0 = cell0[l] if l < len(cell0) else ""
81 | c1 = cell1[l] if l < len(cell1) else ""
82 | c2 = cell2[l] if l < len(cell2) else ""
83 |
84 | printContentLine([c0, c1, c2])
85 |
86 | printSeparatorLine("-")
87 |
88 | elif args.output == "html":
89 |
90 |
91 | def printHtmlRow(el, cells):
92 | output = []
93 | output.append("")
94 | for c in cells:
95 | output.append(f"<{el}>{c}{el}>")
96 | output.append("
")
97 | print("".join(output))
98 |
99 | print("")
100 |
101 | printHtmlRow("th", ["Plugin", "Environment variable", "Default configuration"])
102 |
103 | for pluginName, pluginDef in configurator.pluginsDef.items():
104 | if "section" in pluginDef:
105 | section = pluginDef["section"]
106 | else:
107 | section = pluginName
108 |
109 | cell0 = pluginName
110 | cell1 = pluginDef["enablingEnvVar"]
111 | cell2 = ""
112 |
113 | if "enabledByDefault" in pluginDef and pluginDef["enabledByDefault"]:
114 | cell1 = cell1 + "\nNote: enabled by default"
115 |
116 | if "nonStandardDefaults" in pluginDef:
117 | defaultSettings = {
118 | section: pluginDef["nonStandardDefaults"]
119 | }
120 | cell2 = json.dumps(defaultSettings, indent=2)
121 |
122 | # cell0 = "" + cell0 + ""
123 | cell0 = "" + cell0 + ""
124 | cell1 = "" + cell1 + "
"
125 | cell2 = "" + cell2 + "
"
126 |
127 | printHtmlRow("td", [cell0, cell1, cell2])
128 |
129 | print("
")
130 |
--------------------------------------------------------------------------------
/docker/orthanc/test_current.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import json
3 | from configurator import OrthancConfigurator
4 |
5 |
6 | class CurrentTest(unittest.TestCase):
7 |
8 | def test_default_config(self):
9 | c = OrthancConfigurator()
10 | c.mergeConfigFromDefaults()
11 |
12 | self.assertTrue(c.configuration["RemoteAccessAllowed"])
13 | self.assertTrue(c.configuration["AuthenticationEnabled"])
14 |
15 | def test_multiple_files(self):
16 | c = OrthancConfigurator()
17 | worklistsConfig = {
18 | "Worklists" : {
19 | "Database" : "tutu"
20 | }
21 | }
22 | pgConfig = {
23 | "PostgreSQL" : {
24 | "Host" : "host"
25 | }
26 | }
27 |
28 | c.mergeConfigFromFile(worklistsConfig, "worklists.json")
29 | c.mergeConfigFromFile(pgConfig, "pg.json")
30 |
31 | self.assertIn("Worklists", c.getEnabledPlugins())
32 | self.assertIn("PostgreSQL", c.getEnabledPlugins())
33 |
34 |
35 | def test_file_in_env_var(self):
36 | c = OrthancConfigurator()
37 | worklistsConfig = {
38 | "Worklists" : {
39 | "Database" : "tutu"
40 | }
41 | }
42 | configFileInString = json.dumps(worklistsConfig, indent=2)
43 |
44 | c.mergeConfigFromEnvVar("ORTHANC_JSON", configFileInString)
45 |
46 | self.assertIn("Worklists", c.getEnabledPlugins())
47 | self.assertEqual("tutu", c.configuration["Worklists"]["Database"])
48 |
49 | def test_simple_env_vars_to_enable_plugin(self):
50 | c = OrthancConfigurator()
51 | c.mergeConfigFromEnvVar("WORKLISTS_PLUGIN_ENABLED", "true")
52 |
53 | self.assertIn("Worklists", c.getEnabledPlugins())
54 |
55 | def test_file_not_overwritten_by_plugin_default(self):
56 | c = OrthancConfigurator()
57 | pgConfig = {
58 | "PostgreSQL" : {
59 | "Password" : "pg-password",
60 | "Host" : "host"
61 | }
62 | }
63 | c.mergeConfigFromFile(pgConfig, "pg.json")
64 | c.mergeConfigFromDefaults()
65 |
66 | self.assertEqual("host", c.configuration["PostgreSQL"]["Host"])
67 | self.assertEqual("pg-password", c.configuration["PostgreSQL"]["Password"])
68 | self.assertEqual("postgres", c.configuration["PostgreSQL"]["Username"])
69 |
70 |
71 | def test_simple_section_to_enable_plugin(self):
72 | c = OrthancConfigurator()
73 | worklistsConfig = {
74 | "Worklists" : {
75 | "Database" : "tutu"
76 | }
77 | }
78 | c.mergeConfigFromFile(worklistsConfig, "worklist.json")
79 |
80 | self.assertIn("Worklists", c.configuration)
81 | self.assertIn("Worklists", c.getEnabledPlugins())
82 |
83 | def test_python_plugin_with_root_setting(self):
84 | c = OrthancConfigurator()
85 | config = {
86 | "PythonScript" : "tutu.py"
87 | }
88 | c.mergeConfigFromFile(config, "config.json")
89 |
90 | self.assertIn("Python", c.getEnabledPlugins())
91 |
92 |
93 | def test_direct_secret(self):
94 | c = OrthancConfigurator()
95 | c.mergeConfigFromSecret("/run/secrets/ORTHANC__POSTGRESQL__PASSWORD", "pg-password")
96 |
97 | self.assertIn("PostgreSQL", c.configuration)
98 | self.assertIn("PostgreSQL", c.getEnabledPlugins())
99 | self.assertEqual("pg-password", c.configuration["PostgreSQL"]["Password"])
100 |
101 | def test_indirect_secret(self):
102 | c = OrthancConfigurator()
103 | c.mergeConfigFromEnvVar("ORTHANC__POSTGRESQL__PASSWORD_SECRET", "pg-password-file")
104 | c.mergeConfigFromSecret("/run/secrets/pg-password-file", "pg-password")
105 |
106 | self.assertIn("PostgreSQL", c.configuration)
107 | self.assertIn("PostgreSQL", c.getEnabledPlugins())
108 | self.assertEqual("pg-password", c.configuration["PostgreSQL"]["Password"])
109 |
110 | def test_gdcm_enabled_by_default(self):
111 | c = OrthancConfigurator()
112 |
113 | self.assertIn("Gdcm", c.getEnabledPlugins())
114 |
115 | def test_disable_gdcm_by_env_var(self):
116 | c = OrthancConfigurator()
117 | c.mergeConfigFromEnvVar("GDCM_PLUGIN_ENABLED", "false")
118 |
119 | self.assertNotIn("Gdcm", c.getEnabledPlugins())
120 |
121 | if __name__ == '__main__':
122 | unittest.main()
--------------------------------------------------------------------------------
/WindowsInstaller/Configuration/PatchDefaultConfiguration.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Orthanc - A Lightweight, RESTful DICOM Store
3 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 | * Department, University Hospital of Liege, Belgium
5 | * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 | * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
7 | * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
8 | *
9 | * This program is free software: you can redistribute it and/or
10 | * modify it under the terms of the GNU General Public License as
11 | * published by the Free Software Foundation, either version 3 of the
12 | * License, or (at your option) any later version.
13 | *
14 | * This program is distributed in the hope that it will be useful, but
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with this program. If not, see .
21 | **/
22 |
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | #include "Toolbox.h"
29 |
30 |
31 | static std::streamsize GetStreamSize(std::istream& f)
32 | {
33 | // http://www.cplusplus.com/reference/iostream/istream/tellg/
34 | f.seekg(0, std::ios::end);
35 | std::streamsize size = f.tellg();
36 | f.seekg(0, std::ios::beg);
37 |
38 | return size;
39 | }
40 |
41 |
42 | static void ReadFile(std::string& content,
43 | const std::string& path)
44 | {
45 | boost::filesystem::ifstream f;
46 | f.open(path, std::ifstream::in | std::ifstream::binary);
47 | if (!f.good())
48 | {
49 | throw std::runtime_error("Cannot open file");
50 | }
51 |
52 | std::streamsize size = GetStreamSize(f);
53 | content.resize(size);
54 | if (size != 0)
55 | {
56 | f.read(reinterpret_cast(&content[0]), size);
57 | }
58 |
59 | f.close();
60 | }
61 |
62 |
63 | static void WriteFile(const void* content,
64 | size_t size,
65 | const std::string& path)
66 | {
67 | boost::filesystem::ofstream f;
68 | f.open(path, std::ofstream::out | std::ofstream::binary);
69 | if (!f.good())
70 | {
71 | throw std::runtime_error("Cannot write file");
72 | }
73 |
74 | if (size != 0)
75 | {
76 | f.write(reinterpret_cast(content), size);
77 |
78 | if (!f.good())
79 | {
80 | f.close();
81 | throw std::runtime_error("Cannot write file");
82 | }
83 | }
84 |
85 | f.close();
86 | }
87 |
88 |
89 |
90 | static std::string Escape(const std::string& s)
91 | {
92 | std::string result;
93 |
94 | for (size_t i = 0; i < s.size(); i++)
95 | {
96 | if (s[i] == '"')
97 | {
98 | result += "\\\\\"";
99 | }
100 | else if (s[i] == '\\')
101 | {
102 | result += "\\\\\\\\";
103 | }
104 | else
105 | {
106 | result += s[i];
107 | }
108 | }
109 |
110 | return result;
111 | }
112 |
113 |
114 | int main()
115 | {
116 | try
117 | {
118 | std::string storageDir = GetStringRegKeyAnsi
119 | ("SOFTWARE\\Orthanc\\Orthanc Server", "OrthancDir", "");
120 |
121 | std::string installDir = GetStringRegKeyAnsi
122 | ("SOFTWARE\\Orthanc\\Orthanc Server", "InstallDir", "");
123 |
124 | std::string configuration;
125 | ReadFile(configuration, "orthanc.json");
126 |
127 | configuration = boost::regex_replace(
128 | configuration,
129 | boost::regex("\"(Storage|Index)Directory\" : \"OrthancStorage\""),
130 | "\"\\1Directory\" : \"" + Escape(storageDir) + "\"");
131 |
132 | configuration = boost::regex_replace(
133 | configuration,
134 | boost::regex("\"Plugins\" : \\[\\s*\\]"),
135 | "\"Plugins\" : [ \"" + Escape(installDir + "\\Plugins") + "\" ]");
136 |
137 | configuration = boost::regex_replace(
138 | configuration,
139 | boost::regex("\"HttpsCACertificates\" : \"\""),
140 | "\"HttpsCACertificates\" : \"" + Escape(installDir + "\\Configuration\\ca-certificates.crt") + "\"");
141 |
142 | WriteFile(configuration.c_str(), configuration.size(), "orthanc.json");
143 | std::cerr << "Successfully patched the default Orthanc configuration" << std::endl;
144 |
145 | return 0;
146 | }
147 | catch (...)
148 | {
149 | std::cerr << "ERROR: Cannot patch the default Orthanc configuration" << std::endl;
150 | return -1;
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-tests/wait-for-it.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Use this script to test if a given TCP host/port are available
3 |
4 | cmdname=$(basename $0)
5 |
6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
7 |
8 | usage()
9 | {
10 | cat << USAGE >&2
11 | Usage:
12 | $cmdname host:port [-s] [-t timeout] [-- command args]
13 | -h HOST | --host=HOST Host or IP under test
14 | -p PORT | --port=PORT TCP port under test
15 | Alternatively, you specify the host and port as host:port
16 | -s | --strict Only execute subcommand if the test succeeds
17 | -q | --quiet Don't output any status messages
18 | -t TIMEOUT | --timeout=TIMEOUT
19 | Timeout in seconds, zero for no timeout
20 | -- COMMAND ARGS Execute command with args after the test finishes
21 | USAGE
22 | exit 1
23 | }
24 |
25 | wait_for()
26 | {
27 | if [[ $TIMEOUT -gt 0 ]]; then
28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
29 | else
30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
31 | fi
32 | start_ts=$(date +%s)
33 | while :
34 | do
35 | if [[ $ISBUSY -eq 1 ]]; then
36 | nc -z $HOST $PORT
37 | result=$?
38 | else
39 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
40 | result=$?
41 | fi
42 | if [[ $result -eq 0 ]]; then
43 | end_ts=$(date +%s)
44 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
45 | break
46 | fi
47 | sleep 1
48 | done
49 | return $result
50 | }
51 |
52 | wait_for_wrapper()
53 | {
54 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
55 | if [[ $QUIET -eq 1 ]]; then
56 | timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
57 | else
58 | timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
59 | fi
60 | PID=$!
61 | trap "kill -INT -$PID" INT
62 | wait $PID
63 | RESULT=$?
64 | if [[ $RESULT -ne 0 ]]; then
65 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
66 | fi
67 | return $RESULT
68 | }
69 |
70 | # process arguments
71 | while [[ $# -gt 0 ]]
72 | do
73 | case "$1" in
74 | *:* )
75 | hostport=(${1//:/ })
76 | HOST=${hostport[0]}
77 | PORT=${hostport[1]}
78 | shift 1
79 | ;;
80 | --child)
81 | CHILD=1
82 | shift 1
83 | ;;
84 | -q | --quiet)
85 | QUIET=1
86 | shift 1
87 | ;;
88 | -s | --strict)
89 | STRICT=1
90 | shift 1
91 | ;;
92 | -h)
93 | HOST="$2"
94 | if [[ $HOST == "" ]]; then break; fi
95 | shift 2
96 | ;;
97 | --host=*)
98 | HOST="${1#*=}"
99 | shift 1
100 | ;;
101 | -p)
102 | PORT="$2"
103 | if [[ $PORT == "" ]]; then break; fi
104 | shift 2
105 | ;;
106 | --port=*)
107 | PORT="${1#*=}"
108 | shift 1
109 | ;;
110 | -t)
111 | TIMEOUT="$2"
112 | if [[ $TIMEOUT == "" ]]; then break; fi
113 | shift 2
114 | ;;
115 | --timeout=*)
116 | TIMEOUT="${1#*=}"
117 | shift 1
118 | ;;
119 | --)
120 | shift
121 | CLI=("$@")
122 | break
123 | ;;
124 | --help)
125 | usage
126 | ;;
127 | *)
128 | echoerr "Unknown argument: $1"
129 | usage
130 | ;;
131 | esac
132 | done
133 |
134 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then
135 | echoerr "Error: you need to provide a host and port to test."
136 | usage
137 | fi
138 |
139 | TIMEOUT=${TIMEOUT:-15}
140 | STRICT=${STRICT:-0}
141 | CHILD=${CHILD:-0}
142 | QUIET=${QUIET:-0}
143 |
144 | # check to see if timeout is from busybox?
145 | # check to see if timeout is from busybox?
146 | TIMEOUT_PATH=$(realpath $(which timeout))
147 | if [[ $TIMEOUT_PATH =~ "busybox" ]]; then
148 | ISBUSY=1
149 | BUSYTIMEFLAG="-t"
150 | else
151 | ISBUSY=0
152 | BUSYTIMEFLAG=""
153 | fi
154 |
155 | if [[ $CHILD -gt 0 ]]; then
156 | wait_for
157 | RESULT=$?
158 | exit $RESULT
159 | else
160 | if [[ $TIMEOUT -gt 0 ]]; then
161 | wait_for_wrapper
162 | RESULT=$?
163 | else
164 | wait_for
165 | RESULT=$?
166 | fi
167 | fi
168 |
169 | if [[ $CLI != "" ]]; then
170 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
171 | echoerr "$cmdname: strict mode, refusing to execute subprocess"
172 | exit $RESULT
173 | fi
174 | exec "${CLI[@]}"
175 | else
176 | exit $RESULT
177 | fi
--------------------------------------------------------------------------------
/docker/orthanc/env-var-legacy.json:
--------------------------------------------------------------------------------
1 | {
2 | "AC_ALLOW_REMOTE": "RemoteAccessAllowed",
3 | "AC_AUTHENTICATION_ENABLED": "AuthenticationEnabled",
4 | "AC_REGISTERED_USERS": "RegisteredUsers",
5 | "AUTHZ_WEBSERVICE": "Authorization.WebService",
6 | "AUTHZ_TOKEN_HTTP_HEADERS": "Authorization.TokenHttpHeaders",
7 | "AUTHZ_TOKEN_GET_ARGUMENTS": "Authorization.TokenGetArguments",
8 | "AUTHZ_UNCHECKED_RESOURCES": "Authorization.UncheckedResources",
9 | "AUTHZ_UNCHECKED_FOLDERS": "Authorization.UncheckedFolders",
10 | "AUTHZ_UNCHECKED_LEVELS": "Authorization.UncheckedLevels",
11 | "AZSTOR_ACC_KEY": "BlobStorage.AccountKey",
12 | "AZSTOR_ACC_NAME": "BlobStorage.AccountName",
13 | "AZSTOR_LICENSE_STRING": "BlobStorage.LicenseString",
14 | "AZSTOR_CONTAINER": "BlobStorage.ContainerName",
15 | "DICOM_AET": "DicomAet",
16 | "DICOM_AET_CHECK_ENABLED": "DicomCheckCalledAet",
17 | "DICOM_ALWAYS_ALLOW_ECHO_ENABLED": "DicomAlwaysAllowEcho",
18 | "DICOM_ALWAYS_ALLOW_STORE_ENABLED": "DicomAlwaysAllowStore",
19 | "DICOM_CHECK_MODALITY_HOST_ENABLED": "DicomCheckModalityHost",
20 | "DICOM_DICTIONARY": "Dictionary",
21 | "DICOM_MODALITIES": "DicomModalities",
22 | "DICOM_PORT": "DicomPort",
23 | "DICOM_QUERY_RETRIEVE_SIZE": "QueryRetrieveSize",
24 | "DICOM_SCP_TIMEOUT": "DicomScpTimeout",
25 | "DICOM_SCU_TIMEOUT": "DicomScuTimeout",
26 | "DICOM_STRICT_AET_COMPARISON_ENABLED": "StrictAetComparison",
27 | "DICOM_SYNCHRONOUS_CMOVE": "SynchronousCMove",
28 | "DICOM_UNKNOWN_SOP_CLASS_ACCEPTED": "UnknownSopClassAccepted",
29 | "DW_ROOT": "DicomWeb.Root",
30 | "DW_WADO_URI_ENABLED": "DicomWeb.EnableWado",
31 | "DW_WADO_URI_ROOT": "DicomWeb.WadoRoot",
32 | "DW_HOST": "DicomWeb.Host",
33 | "DW_TLS": "DicomWeb.Ssl",
34 | "DW_SERVERS": "DicomWeb.Servers",
35 | "DW_STOW_MAX_INSTANCES": "DicomWeb.StowMaxInstances",
36 | "DW_STOW_MAX_SIZE": "DicomWeb.StowMaxSize",
37 | "EXECUTE_LUA_ENABLED": "ExecuteLuaEnabled",
38 | "HTTP_CL_TIMEOUT": "HttpTimeout",
39 | "HTTP_CL_VERIFY_PEERS": "HttpsVerifyPeers",
40 | "HTTP_CL_CA_CERTS": "HttpsCACertificates",
41 | "HTTP_CL_PROXY": "HttpProxy",
42 | "HTTP_VERBOSE": "HttpVerbose",
43 | "HTTP_PORT": "HttpPort",
44 | "HTTP_KEEP_ALIVE": "KeepAlive",
45 | "HTTP_TCP_NODELAY": "TcpNoDelay",
46 | "HTTP_REQUEST_TIMEOUT": "HttpRequestTimeout",
47 | "IMPORT_OVERWRITE_INSTANCES": "OverwriteInstances",
48 | "LISTENER_LISTEN_ALL_ADDR": "RemoteAccessAllowed",
49 | "LOCALE": "Locale",
50 | "LUA_OPTIONS": "LuaOptions",
51 | "LUA_SCRIPTS": "LuaScripts",
52 | "PEERS": "OrthancPeers",
53 | "PG_PASSWORD": "PostgreSQL.Password",
54 | "PG_INDEX_ENABLED": "PostgreSQL.EnableIndex",
55 | "PG_STORAGE_ENABLED": "PostgreSQL.EnableStorage",
56 | "PG_HOST": "PostgreSQL.Host",
57 | "PG_PORT": "PostgreSQL.Port",
58 | "PG_DB": "PostgreSQL.Database",
59 | "PG_USER": "PostgreSQL.Username",
60 | "PG_SSL": "PostgreSQL.EnableSsl",
61 | "PG_LOCK": "PostgreSQL.Lock",
62 | "PLUGINS": "Plugins",
63 | "NAME": "Name",
64 | "SCHED_JOBS_HISTORY_SIZE": "JobsHistorySize",
65 | "SCHED_MAX_CONCURRENT_JOBS": "ConcurrentJobs",
66 | "SCHED_MAX_QUEUED_JOBS": "LimitJobs",
67 | "SCHED_SAVE_JOBS": "SaveJobs",
68 | "SERVEFOLDERS_ALLOW_CACHE": "ServeFolders.AllowCache",
69 | "SERVEFOLDERS_GENERATE_ETAGS": "ServeFolders.GenerateETag",
70 | "SERVEFOLDERS_EXTENSIONS": "ServeFolders.Extensions",
71 | "SERVEFOLDERS_FOLDERS": "ServeFolders.Folders",
72 | "STABLE_AGE": "StableAge",
73 | "STORAGE_ACCESS_ON_FIND": "StorageAccessOnFind",
74 | "STORAGE_DIR": "StorageDirectory",
75 | "STORAGE_MAX_SIZE": "MaximumStorageSize",
76 | "STORAGE_MAX_PATIENTS": "MaximumPatientCount",
77 | "STORE_DICOM": "StoreDicom",
78 | "TRANSFERS_THREADS": "Transfers.Threads",
79 | "TRANSFERS_RETRIES": "Transfers.MaxHttpRetries",
80 | "TRANSFERS_BUCKET_SIZE": "Transfers.BucketSize",
81 | "TRANSFERS_CACHE_SIZE": "Transfers.CacheSize",
82 | "TRANSFERS_MAX_PUSH_TRANSACTIONS": "Transfers.MaxPushTransactions",
83 | "USERMETADATA": "UserMetadata",
84 | "WL_STORAGE_DIR": "Worklists.Database",
85 | "WVB_ANNOTATIONS_STORAGE_ENABLED": "WebViewer.AnnotationStorageEnabled",
86 | "WVB_COMBINED_TOOL_ENABLED": "WebViewer.CombinedToolEnabled",
87 | "WVB_CROSS_HAIR_ENABLED": "WebViewer.CrossHairEnabled",
88 | "WVB_LANGUAGE": "WebViewer.DefaultLanguage",
89 | "WVB_DEFAULT_SELECTED_TOOL": "WebViewer.DefaultSelectedTool",
90 | "WVB_DOWNLOAD_AS_JPEG_ENABLED": "WebViewer.DownloadAsJpegEnabled",
91 | "WVB_INSTANCE_INFO_CACHE_ENABLED": "WebViewer.InstanceInfoCacheEnabled",
92 | "WVB_KEY_IMAGE_CAPTURE_ENABLED": "WebViewer.KeyImageCaptureEnabled",
93 | "WVB_KEYBOARD_SHORTCUTS_ENABLED": "WebViewer.KeyboardShortcutsEnabled",
94 | "WVB_OPEN_ALL_PATIENT_STUDIES": "WebViewer.OpenAllPatientStudies",
95 | "WVB_PRINT_ENABLED": "WebViewer.PrintEnabled",
96 | "WVB_REFERENCE_LINES_ENABLED": "WebViewer.ReferenceLinesEnabled",
97 | "WVB_SERIES_TO_IGNORE": "WebViewer.SeriesToIgnore",
98 | "WVB_STUDY_DOWNLOAD_ENABLED": "WebViewer.StudyDownloadEnabled",
99 | "WVB_SYNCHRONIZED_BROWSING_ENABLED": "WebViewer.SynchronizedBrowsingEnabled",
100 | "WVB_TOGGLE_OVERLAY_TEXT_BUTTON_ENABLED": "WebViewer.ToggleOverlayTextButtonEnabled",
101 | "WVB_VIDEO_ENABLED": "WebViewer.VideoDisplayEnabled"
102 | }
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/README.txt:
--------------------------------------------------------------------------------
1 | Using Orthanc
2 | =============
3 |
4 | You have successfully installed the Windows installers of Orthanc!
5 | Orthanc is now running as a Windows service in the background.
6 |
7 | By default, Orthanc listens to incoming DICOM connections on TCP port
8 | 4242 and incoming HTTP connections on TCP port 8042.
9 |
10 | You can interact with Orthanc by opening its administrative Web
11 | interface, that is called "Orthanc Explorer". This can be done by
12 | clicking the link in the Start Menu or by opening your web browser at
13 | http://127.0.0.1:8042/app/explorer.html. Please remember that Orthanc
14 | Explorer does not support Microsoft Internet Explorer.
15 |
16 |
17 | Content of the package ${VERSION}
18 | -----------------------${VERSION_DASHES}
19 |
20 | Orthanc server ${ORTHANC}
21 | Serve folders plugin ${ORTHANC}
22 | Connectivity check plugin ${ORTHANC}
23 | Housekeeper plugin ${ORTHANC}
24 | Delayed Deletion plugin ${ORTHANC}
25 | Multitenant DICOM plugin ${ORTHANC}
26 | Stone Web viewer plugin ${ORTHANC_STONE}
27 | Osimis Web viewer plugin ${OSIMIS_VIEWER}
28 | Orthanc Web viewer plugin ${ORTHANC_WEBVIEWER}
29 | DICOMweb plugin ${ORTHANC_DICOMWEB}
30 | PostgreSQL plugins ${ORTHANC_POSTGRESQL}
31 | MySQL plugins ${ORTHANC_MYSQL}
32 | WSI Web viewer plugin ${ORTHANC_WSI}
33 | Transfers accelerator plugin ${ORTHANC_TRANSFERS}
34 | Authorization plugin ${ORTHANC_AUTH}
35 | GDCM decoder/transcoder plugin ${ORTHANC_GDCM}
36 | ODBC plugin ${ORTHANC_ODBC}
37 | TCIA plugin ${ORTHANC_TCIA}
38 | Orthanc Indexer plugin ${ORTHANC_INDEXER}
39 | Orthanc neuroimaging plugin ${ORTHANC_NEURO}
40 | Orthanc Explorer 2 ${ORTHANC_EXPLORER_2}
41 | Azure blob storage plugin ${ORTHANC_AZURE_STORAGE} (Win64 installers only !)
42 | Kitware's VolView plugin ${ORTHANC_VOLVIEW}
43 | OHIF plugin ${ORTHANC_OHIF}
44 | Python plugin ${ORTHANC_PYTHON}
45 | STL plugin ${ORTHANC_STL}
46 | AWS S3 plugin ${ORTHANC_AWS_STORAGE}
47 | Education plugin ${ORTHANC_EDUCATION}
48 | Worklists plugin ${ORTHANC_WORKLISTS}
49 | Pixels masker plugin ${ORTHANC_PIXELS_MASKER}
50 |
51 |
52 |
53 | Folders
54 | -------
55 |
56 | * STORAGE: During the installation, you were asked to choose a storage
57 | folder where Orthanc stores its database. By default, this folder is
58 | "C:\Orthanc". Running the uninstaller will remove the Orthanc
59 | program files from your system, but it will not delete this storage
60 | folder.
61 |
62 | If you wish to delete the data Orthanc has saved, delete this
63 | storage folder (e.g. C:\Orthanc) after uninstalling Orthanc. Keep
64 | this in mind if you use Orthanc to store protected health
65 | information (PHI).
66 |
67 | * CONFIGURATION: The Orthanc configuration files can be found inside
68 | the folder "Configuration" within the installation directory. A
69 | shortcut to the configuration folder is present in the Start Menu to
70 | access and modify it more easily.
71 |
72 | * LOGS: The Orthanc log files can be found inside the folder "Logs"
73 | within the installation directory.
74 |
75 | * PLUGINS: By default, Orthanc will look within the "Plugins" folder
76 | within the installation directory to find its plugins.
77 |
78 |
79 | Troubleshooting
80 | ---------------
81 |
82 | 1. Verify that the service called "Orthanc" is running using the
83 | Services control panel (for quick access, launch the command
84 | "services.msc").
85 |
86 | 2. Make sure you do not use Internet Explorer to open Orthanc
87 | Explorer, but rather Chrome or Firefox.
88 |
89 | 3. Verify that your firewall is configured to allow inbound
90 | connections to the TCP ports Orthanc is listening on (by default,
91 | 4242 and 8042).
92 |
93 | 4. Verify that no other applications are using the ports that Orthanc
94 | is listening on. For instance, Juniper is known to also use the
95 | port 4242 for its VPN solutions.
96 |
97 | 5. By default, remote access to Orthanc Explorer is disallowed for
98 | security reasons. Turn the option "RemoteAccessAllowed" to "true"
99 | in the Orthanc configuration file if you wish to access Orthanc
100 | from another computer.
101 |
102 | 6. Check the Orthanc logs in the "Logs" folder within the installation
103 | directory.
104 |
105 | 7. Check the Orthanc Book and associated FAQ:
106 | https://orthanc.uclouvain.be/book/
107 | https://orthanc.uclouvain.be/book/faq.html
108 |
109 | 8. Post a request for help to the Orthanc Users group:
110 | https://discourse.orthanc-server.org/
111 |
112 |
113 | Homepage
114 | --------
115 |
116 | You can find more information at the official homepage of Orthanc:
117 | http://www.orthanc-server.com/
118 |
119 |
120 | Note
121 | ----
122 |
123 | The content of this file is adapted from the unofficial Windows
124 | installer of Orthanc developed by Lury:
125 | https://github.com/luryco/OrthancService/blob/master/InstallerAssets/README.txt
126 |
--------------------------------------------------------------------------------
/WindowsInstaller/NOTES.txt:
--------------------------------------------------------------------------------
1 |
2 | Setup
3 | =====
4 |
5 | General architecture
6 | --------------------
7 |
8 | - The Windows installer is entirely built under Linux.
9 |
10 | - The installer is generated by InnoSetup
11 | (http://www.jrsoftware.org/isinfo.php) under Linux thanks to Wine.
12 |
13 | - The content of the installer is populated by a Python script, which
14 | downloads files from the Orthanc CIS (BuildBot - for core and
15 | official plugins), and from the Osimis CIS (Jenkins - for the Osimis
16 | Web viewer).
17 |
18 | - The Windows service is compiled with MinGW-W64 as a Windows 32 bit
19 | binary (including for Windows 64).
20 |
21 | - An additional tool called "PatchDefaultConfiguration" patches the
22 | default configuration file of Orthanc, in order to replace the
23 | "IndexDirectory" and "StorageDirectory" options by the choice of the
24 | user (this choice is stored as a Windows registry key).
25 |
26 |
27 |
28 | Configuration
29 | -------------
30 |
31 | Install an Ubuntu 16.04 box (or anything similar)
32 |
33 | # sudo apt-get install build-essential g++-mingw-w64 wine cmake
34 | # wget http://www.jrsoftware.org/download.php/is.exe
35 | # wine ./is.exe
36 |
37 | NB: The error messages that might appear while invoking InnoSetup
38 | are Wine-related and can be safely ignored.
39 |
40 |
41 | Build
42 | -----
43 |
44 | Windows 32 package:
45 |
46 | # rm -rf /tmp/WindowsInstaller
47 | # ./CreateInstaller.py --matrix=../build-matrix.json --platform=32 --version=22.4.0
48 |
49 | Windows 64 package:
50 |
51 | # rm -rf /tmp/WindowsInstaller
52 | # ./CreateInstaller.py --matrix=../build-matrix.json --platform=64 --version=22.4.0
53 |
54 | The resulting installers are located in "/tmp/WindowsInstaller/"
55 |
56 |
57 |
58 | Configuration files
59 | ===================
60 |
61 | The default configuration files are retrieved from the official Debian
62 | packages:
63 |
64 | # wget 'https://anonscm.debian.org/viewvc/debian-med/trunk/packages/orthanc-webviewer/trunk/debian/configuration/webviewer.json?view=co' -O Resources/webviewer.json
65 | # unix2dos Resources/webviewer.json
66 |
67 | # wget https://anonscm.debian.org/cgit/debian-med/orthanc-dicomweb.git/plain/debian/configuration/dicomweb.json -O Resources/dicomweb.json
68 | # unix2dos Resources/dicomweb.json
69 |
70 | # wget 'https://anonscm.debian.org/viewvc/debian-med/trunk/packages/orthanc-postgresql/trunk/debian/configuration/postgresql.json?view=co' -O Resources/postgresql.json
71 | # unix2dos Resources/postgresql.json
72 |
73 | # wget https://anonscm.debian.org/cgit/debian-med/orthanc.git/plain/debian/configuration/serve-folders.json -O Resources/serve-folders.json
74 | # unix2dos Resources/serve-folders.json
75 |
76 | # wget https://anonscm.debian.org/cgit/debian-med/orthanc.git/plain/debian/configuration/worklists.json -O Resources/worklists.json
77 | # unix2dos Resources/worklists.json
78 |
79 | # wget https://orthanc.uclouvain.be/hg/orthanc-stone/raw-file/StoneWebViewer-2.3/Applications/StoneWebViewer/WebApplication/configuration.json -O Resources/stone-webviewer.json
80 | # unix2dos Resources/stone-webviewer.json
81 |
82 |
83 | InnoSetup Bitmaps
84 | =================
85 |
86 | Gimp
87 | ----
88 |
89 | If you are making a BMP from within GIMP and are exporting to a BMP,
90 | use the following options:
91 |
92 | - Compatibility Options -> Do not write color space information
93 | - Advanced Options -> 24 bits (R8 G8 B8)
94 |
95 | Otherwise, InnoSetup will tag the BMP as unsupported...
96 |
97 |
98 | ImageMagick
99 | -----------
100 |
101 | http://www.imagemagick.org/Usage/formats/#bmp
102 |
103 | # convert -resize 55x58 ./Resources/OsimisLogo.png -background white -alpha remove -flatten -alpha off BMP3:./Resources/OsimisWizardLogo.bmp
104 | # convert -resize 164x314 ./Resources/OsimisWizard.png -background white -alpha remove -flatten -alpha off BMP3:./Resources/OsimisWizard.bmp
105 |
106 | # convert -resize 55x58 ./Resources/OrthancH.png -background white -alpha remove -flatten -alpha off BMP3:./Resources/OrthancWizardLogo.bmp
107 | # convert -resize 164x314 ./Resources/OrthancWizard.png -background white -alpha remove -flatten -alpha off BMP3:./Resources/OrthancWizard.bmp
108 |
109 |
110 | Icons
111 | -----
112 |
113 | http://www.imagemagick.org/Usage/thumbnails/#favicon
114 |
115 | # convert ./Resources/OsimisLogo.png -background white -alpha remove -flatten -alpha off -resize 256x256 \
116 | -define icon:auto-resize="256,128,96,64,48,32,16" \
117 | ./Resources/Osimis.ico
118 |
119 | => Bad smoothing, unfortunately... so:
120 |
121 | # convert ./Resources/OsimisLogoShadow.png -resize 256x256 /tmp/icon-256.png &&
122 | convert /tmp/icon-256.png -filter Gaussian -define filter:sigma=.5 -resize 128x128 /tmp/icon-128.png &&
123 | convert /tmp/icon-128.png -filter Gaussian -define filter:sigma=.5 -resize 64x64 /tmp/icon-64.png &&
124 | convert /tmp/icon-64.png -filter Gaussian -define filter:sigma=.5 -resize 32x32 /tmp/icon-32.png &&
125 | convert /tmp/icon-32.png -filter Gaussian -define filter:sigma=.5 -resize 16x16 /tmp/icon-16.png &&
126 | convert /tmp/icon-16.png /tmp/icon-32.png /tmp/icon-64.png /tmp/icon-128.png /tmp/icon-256.png ./Resources/Osimis.ico
127 |
128 | # convert ./Resources/OrthancH.png -resize 256x256 /tmp/icon-256.png &&
129 | convert /tmp/icon-256.png -filter Gaussian -define filter:sigma=.5 -resize 128x128 /tmp/icon-128.png &&
130 | convert /tmp/icon-128.png -filter Gaussian -define filter:sigma=.5 -resize 64x64 /tmp/icon-64.png &&
131 | convert /tmp/icon-64.png -filter Gaussian -define filter:sigma=.5 -resize 32x32 /tmp/icon-32.png &&
132 | convert /tmp/icon-32.png -filter Gaussian -define filter:sigma=.5 -resize 16x16 /tmp/icon-16.png &&
133 | convert /tmp/icon-16.png /tmp/icon-32.png /tmp/icon-64.png /tmp/icon-128.png /tmp/icon-256.png ./Resources/Orthanc.ico
134 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-under-tests/orthanc.json:
--------------------------------------------------------------------------------
1 | // how to obtain this file:
2 | // in orthanc-tests: generate the configuration file with python2 ./GenerateConfigurationForTests.py
3 | // then, paste it here and:
4 | // - remove the Plugins section
5 | // - remove the PostgreSQL/MySQL/Odbc sections
6 | // - update the IP of OrthancPeers and DicomModalities: replace localhost by orthanc-tests for the first item
7 | // - update the Worklists.Database to "/worklists"
8 | {
9 | "AcceptedTransferSyntaxes": [
10 | "1.2.840.10008.1.*"
11 | ],
12 | "AllowFindSopClassesInStudy": false,
13 | "AuthenticationEnabled": true,
14 | "BuiltinDecoderTranscoderOrder": "After",
15 | "CaseSensitivePN": false,
16 | "CheckRevisions": true,
17 | "ConcurrentJobs": 2,
18 | "DefaultEncoding": "Utf8",
19 | "DefaultPrivateCreator": "Lunit",
20 | "DeidentifyLogs": true,
21 | "DicomAet": "ORTHANC",
22 | "DicomAlwaysAllowEcho": true,
23 | "DicomAlwaysAllowFind": false,
24 | "DicomAlwaysAllowFindWorklist": false,
25 | "DicomAlwaysAllowGet": false,
26 | "DicomAlwaysAllowMove": false,
27 | "DicomAlwaysAllowStore": true,
28 | "DicomAssociationCloseDelay": 0,
29 | "DicomCheckCalledAet": false,
30 | "DicomCheckModalityHost": false,
31 | "DicomEchoChecksFind": false,
32 | "DicomLossyTranscodingQuality": 90,
33 | "DicomModalities": {
34 | "orthanctest": [
35 | "ORTHANCTEST",
36 | "orthanc-tests",
37 | 5001
38 | ],
39 | "self": [
40 | "ORTHANC",
41 | "127.0.0.1",
42 | 4242
43 | ]
44 | },
45 | "DicomModalitiesInDatabase": false,
46 | "DicomPort": 4242,
47 | "DicomScpTimeout": 30,
48 | "DicomScuPreferredTransferSyntax": "1.2.840.10008.1.2.1",
49 | "DicomScuTimeout": 10,
50 | "DicomServerEnabled": true,
51 | "DicomThreadsCount": 4,
52 | "DicomTlsEnabled": false,
53 | "DicomTlsRemoteCertificateRequired": true,
54 | "DicomWeb": {
55 | "Servers": {
56 | "sample": [
57 | "http://localhost:8042/dicom-web/",
58 | "alice",
59 | "orthanctest"
60 | ]
61 | }
62 | },
63 | "Dictionary": {
64 | "0009,0010": [
65 | "LO",
66 | "Private data element",
67 | 1,
68 | 1,
69 | "Lunit"
70 | ],
71 | "0009,1001": [
72 | "DS",
73 | "Abnormality score",
74 | 1,
75 | 1,
76 | "Lunit"
77 | ],
78 | "00e1,10c2": [
79 | "UI",
80 | "PET-CT Multi Modality Name",
81 | 1,
82 | 1,
83 | "ELSCINT1"
84 | ],
85 | "4321,1012": [
86 | "LO",
87 | "RadioButton3",
88 | 1,
89 | 1,
90 | "RadioLogic"
91 | ],
92 | "7053,1003": [
93 | "ST",
94 | "Original Image Filename",
95 | 1,
96 | 1,
97 | "Philips PET Private Group"
98 | ]
99 | },
100 | "ExecuteLuaEnabled": true,
101 | "HttpCompressionEnabled": false,
102 | "HttpDescribeErrors": true,
103 | "HttpPort": 8042,
104 | "HttpProxy": "",
105 | "HttpRequestTimeout": 30,
106 | "HttpServerEnabled": true,
107 | "HttpThreadsCount": 50,
108 | "HttpTimeout": 2,
109 | "HttpVerbose": false,
110 | "HttpsCACertificates": "/etc/ssl/certs/ca-certificates.crt",
111 | "HttpsVerifyPeers": true,
112 | "IndexDirectory": "OrthancStorage",
113 | "IngestTranscodingOfCompressed": true,
114 | "IngestTranscodingOfUncompressed": true,
115 | "JobsHistorySize": 1000,
116 | "LimitFindInstances": 20,
117 | "LimitFindResults": 10,
118 | "LoadPrivateDictionary": true,
119 | "LogExportedResources": true,
120 | "LuaScripts": [],
121 | "MallocArenaMax": 5,
122 | "MaximumPatientCount": 0,
123 | "MaximumPduLength": 16384,
124 | "MaximumStorageCacheSize": 128,
125 | "MaximumStorageSize": 0,
126 | "MediaArchiveSize": 1,
127 | "MetricsEnabled": true,
128 | "Name": "MyOrthanc",
129 | "OrthancExplorerEnabled": true,
130 | "OrthancPeers": {
131 | "peer": [
132 | "http://orthanc-tests:5000/",
133 | "alice",
134 | "orthanctest"
135 | ],
136 | "self": {
137 | "Password": "orthanctest",
138 | "Url": "http://127.0.0.1:8042/",
139 | "Username": "alice"
140 | },
141 | "transfers-bidirectional": {
142 | "Password": "orthanctest",
143 | "RemoteSelf": "transfers-bidirectional",
144 | "Url": "http://localhost:8042/",
145 | "Username": "alice"
146 | },
147 | "transfers-simple": {
148 | "Password": "orthanctest",
149 | "Url": "http://localhost:8042/",
150 | "Username": "alice"
151 | }
152 | },
153 | "OrthancPeersInDatabase": false,
154 | "OverwriteInstances": true,
155 | "QueryRetrieveSize": 100,
156 | "RegisteredUsers": {
157 | "alice": "orthanctest"
158 | },
159 | "RemoteAccessAllowed": true,
160 | "SaveJobs": false,
161 | "SslCertificate": "certificate.pem",
162 | "SslEnabled": false,
163 | "SslMinimumProtocolVersion": 4,
164 | "SslTrustedClientCertificates": "trustedClientCertificates.pem",
165 | "SslVerifyPeers": false,
166 | "StableAge": 1,
167 | "StorageAccessOnFind": "Always",
168 | "StorageCommitmentReportsSize": 100,
169 | "StorageCompression": false,
170 | "StorageDirectory": "OrthancStorage",
171 | "StoreDicom": true,
172 | "StoreMD5ForAttachments": true,
173 | "StrictAetComparison": false,
174 | "SyncStorageArea": false,
175 | "SynchronousCMove": false,
176 | "SynchronousZipStream": true,
177 | "TcpNoDelay": true,
178 | "TranscodeDicomProtocol": true,
179 | "UnknownSopClassAccepted": false,
180 | "UserContentType": {},
181 | "UserMetadata": {
182 | "my-metadata": 1098
183 | },
184 | "WebDavDeleteAllowed": true,
185 | "WebDavEnabled": true,
186 | "WebDavUploadAllowed": true,
187 | "Worklists": {
188 | "Database": "/worklists",
189 | "Enable": true
190 | },
191 | "ZipLoaderThreads": 0
192 | }
193 |
--------------------------------------------------------------------------------
/.github/workflows/build-all-dockers.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | is_tag:
5 | description: 'Is a Git Tag'
6 | type: string
7 | required: true
8 | current_branch_tag:
9 | description: 'Git branch or Tag'
10 | type: string
11 | required: true
12 | secrets:
13 | docker_hub_username:
14 | required: true
15 | docker_hub_token:
16 | required: true
17 | aws_access_key_id:
18 | required: true
19 | aws_secret_access_key:
20 | required: true
21 |
22 |
23 |
24 | jobs:
25 | build-docker-stable:
26 | # no need to build the stable image on branches
27 | if: ${{ github.ref == 'refs/heads/master' || inputs.is_tag == 'true' }}
28 | uses: ./.github/workflows/build-docker.yml
29 | with:
30 | runner: ${{ matrix.config.runner }}
31 | runner_type: ${{ matrix.config.runnerType }}
32 | platform: ${{ matrix.config.platform }}
33 | stable_unstable: ${{ matrix.config.stableUnstable }}
34 | current_branch_tag: ${{ inputs.current_branch_tag }}
35 | is_tag: ${{ inputs.is_tag }}
36 | secrets:
37 | docker_hub_username: ${{ secrets.docker_hub_username }}
38 | docker_hub_token: ${{ secrets.docker_hub_token }}
39 | aws_access_key_id: ${{ secrets.aws_access_key_id }}
40 | aws_secret_access_key: ${{ secrets.aws_secret_access_key }}
41 |
42 | strategy:
43 | fail-fast: false
44 | matrix:
45 | config:
46 | - {
47 | name: "linux/amd64",
48 | platform: "linux/amd64",
49 | stableUnstable: "stable",
50 | runner: "ubuntu-latest",
51 | runnerType: "github-hosted"
52 | }
53 | - {
54 | name: "linux/arm64",
55 | platform: "linux/arm64",
56 | stableUnstable: "stable",
57 | runner: "debian-arm64",
58 | runnerType: "self-hosted"
59 | }
60 |
61 | build-docker-unstable:
62 | if: ${{ inputs.is_tag != 'true' }}
63 | uses: ./.github/workflows/build-docker.yml
64 | with:
65 | runner: ${{ matrix.config.runner }}
66 | runner_type: ${{ matrix.config.runnerType }}
67 | platform: ${{ matrix.config.platform }}
68 | stable_unstable: ${{ matrix.config.stableUnstable }}
69 | current_branch_tag: ${{ inputs.current_branch_tag }}
70 | is_tag: ${{ inputs.is_tag }}
71 | secrets:
72 | docker_hub_username: ${{ secrets.docker_hub_username }}
73 | docker_hub_token: ${{ secrets.docker_hub_token }}
74 | aws_access_key_id: ${{ secrets.aws_access_key_id }}
75 | aws_secret_access_key: ${{ secrets.aws_secret_access_key }}
76 |
77 | strategy:
78 | fail-fast: false
79 | matrix:
80 | config:
81 | - {
82 | name: "linux/amd64",
83 | platform: "linux/amd64",
84 | stableUnstable: "unstable",
85 | runner: "ubuntu-latest",
86 | runnerType: "github-hosted"
87 | }
88 | - {
89 | name: "linux/arm64",
90 | platform: "linux/arm64",
91 | stableUnstable: "unstable",
92 | runner: "debian-arm64",
93 | runnerType: "self-hosted"
94 | }
95 |
96 | publish-manifest-stable:
97 | runs-on: "ubuntu-latest"
98 | needs: [build-docker-stable]
99 |
100 | steps:
101 |
102 | - uses: actions/checkout@v3
103 |
104 | - name: Login to DockerHub
105 | uses: docker/login-action@v2
106 | with:
107 | username: ${{ secrets.docker_hub_username }}
108 | password: ${{ secrets.docker_hub_token }}
109 |
110 | - name: Publish Dockerhub manifest normal image
111 | run: ./local-build.sh version=stable image=normal type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-normal-stable pushTag=${{ inputs.current_branch_tag }} isTag=${{ inputs.is_tag }}
112 |
113 | - name: Publish Dockerhub manifest full image
114 | run: ./local-build.sh version=stable image=full type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-full-stable pushTag=${{ inputs.current_branch_tag }}-full isTag=${{ inputs.is_tag }}
115 |
116 | - name: Publish Dockerhub manifest with latest tag for normal image
117 | if: inputs.is_tag == 'true'
118 | run: ./local-build.sh version=stable image=normal type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-normal-stable pushTag=latest isTag=${{ inputs.is_tag }}
119 |
120 | - name: Publish Dockerhub manifest with latest tag for full image
121 | if: inputs.is_tag == 'true'
122 | run: ./local-build.sh version=stable image=full type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-full-stable pushTag=latest-full isTag=${{ inputs.is_tag }}
123 |
124 |
125 | - name: Update DockerHub repo description
126 | uses: peter-evans/dockerhub-description@v3
127 | if: inputs.is_tag == 'true'
128 | with:
129 | username: ${{ secrets.docker_hub_username }}
130 | password: ${{ secrets.docker_hub_token }}
131 | repository: orthancteam/orthanc
132 | readme-filepath: README-dockerhub.md
133 |
134 |
135 | publish-manifest-unstable:
136 | runs-on: "ubuntu-latest"
137 | needs: [build-docker-unstable]
138 |
139 | steps:
140 |
141 | - uses: actions/checkout@v3
142 |
143 | - name: Login to DockerHub
144 | uses: docker/login-action@v2
145 | with:
146 | username: ${{ secrets.docker_hub_username }}
147 | password: ${{ secrets.docker_hub_token }}
148 |
149 | - name: Publish Dockerhub manifest normal image
150 | run: ./local-build.sh version=unstable image=normal type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-normal-unstable pushTag=${{ inputs.current_branch_tag }} isTag=${{ inputs.is_tag }}
151 |
152 | - name: Publish Dockerhub manifest full image
153 | run: ./local-build.sh version=unstable image=full type=ci step=publish-manifest currentTag=${{ inputs.current_branch_tag }}-full-unstable pushTag=${{ inputs.current_branch_tag }}-full isTag=${{ inputs.is_tag }}
--------------------------------------------------------------------------------
/docker/orthanc/Dockerfile.builder-base:
--------------------------------------------------------------------------------
1 | ########################## Orthanc builder base
2 | # image to compile Orthanc and its plugins dynamically
3 | ARG BASE_IMAGE_TAG=current
4 | FROM orthancteam/orthanc-runner-base:${BASE_IMAGE_TAG}
5 |
6 | ARG PLATFORM=linux/amd64
7 |
8 | RUN export DEBIAN_FRONTEND=noninteractive
9 | RUN apt-get --assume-yes update
10 | RUN apt-get --assume-yes install wget
11 | RUN apt-get --assume-yes install build-essential
12 | RUN apt-get --assume-yes install unzip
13 | RUN apt-get --assume-yes install uuid-dev
14 | RUN apt-get --assume-yes install apt-utils
15 | RUN apt-get --assume-yes install libcurl4-openssl-dev
16 | RUN apt-get --assume-yes install curl
17 | RUN apt-get --assume-yes install apt-transport-https
18 | RUN apt-get --assume-yes install liblua5.4-dev
19 | RUN apt-get --assume-yes install libgtest-dev
20 | RUN apt-get --assume-yes install libpng-dev
21 | RUN apt-get --assume-yes install libsqlite3-dev
22 | RUN apt-get --assume-yes install libjpeg-dev libboost-all-dev libwrap0-dev libcharls-dev libjsoncpp-dev libpugixml-dev
23 | RUN apt-get --assume-yes install git
24 | RUN apt-get --assume-yes install mercurial
25 | RUN apt-get --assume-yes install zip
26 | RUN apt-get --assume-yes install libpq-dev postgresql-server-dev-all
27 | RUN apt-get --assume-yes install python3-dev
28 | RUN apt-get --assume-yes install unixodbc-dev
29 | RUN apt-get --assume-yes install libgmock-dev
30 | RUN apt-get --assume-yes install protobuf-compiler
31 | RUN apt-get --assume-yes install default-libmysqlclient-dev
32 | RUN apt-get --assume-yes install zlib1g-dev
33 |
34 |
35 | RUN apt-get --assume-yes install cmake
36 | # RUN apt-get --assume-yes install awscli
37 | RUN if [ "$PLATFORM" = "linux/amd64" ]; then curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2.zip"; fi
38 | RUN if [ "$PLATFORM" = "linux/arm64" ]; then curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "/tmp/awscliv2.zip"; fi
39 | WORKDIR /tmp
40 | RUN unzip awscliv2.zip
41 | RUN ./aws/install
42 |
43 | # for orthanc-stl plugin:
44 | RUN apt-get --assume-yes install libgl1-mesa-dev libxt-dev
45 |
46 | RUN apt-get --assume-yes install default-jdk
47 |
48 | # for orthanc-wsi and orthanc-education plugins:
49 | RUN apt-get --assume-yes install libopenslide0
50 |
51 | # # install a recent cmake version (required later by recent vcpkg versions that we don't use now !)
52 | # WORKDIR /tmp
53 | # RUN wget https://github.com/Kitware/CMake/releases/download/v3.23.1/cmake-3.23.1.tar.gz
54 | # RUN tar -zxvf cmake-3.23.1.tar.gz
55 | # WORKDIR /tmp/cmake-3.23.1
56 | # RUN ./bootstrap
57 | # RUN make -j 8
58 | # RUN make install
59 | RUN cmake --version
60 |
61 | # no need to clean apt-cache, it's a build image, we don't care about its size
62 |
63 | RUN mkdir -p /sources
64 | RUN mkdir -p /build
65 | RUN mkdir -p /scripts
66 | RUN mkdir -p /third-party-downloads
67 |
68 | # download most commonly used third-party files to avoid downloading too many files from UCLouvain servers when building
69 | WORKDIR /third-party-downloads
70 | RUN wget https://public-files.orthanc.team/third-party-downloads/VolView-4.1.1.tar.gz
71 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-auth-0.7.1.tar.gz
72 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-cal-0.6.1.tar.gz
73 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-common-0.9.3.tar.gz
74 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-compression-0.2.17.tar.gz
75 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-event-stream-0.3.1.tar.gz
76 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-http-0.7.11.tar.gz
77 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-io-0.13.31.tar.gz
78 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-mqtt-0.9.5.tar.gz
79 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-s3-0.3.14.tar.gz
80 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-c-sdkutils-0.1.11.tar.gz
81 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-checksums-0.1.17.tar.gz
82 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-crt-cpp-0.24.1.tar.gz
83 | RUN wget https://public-files.orthanc.team/third-party-downloads/aws/aws-sdk-cpp-1.11.178.tar.gz
84 | RUN wget https://public-files.orthanc.team/third-party-downloads/boost_1_83_0_bcpdigest-1.12.2.tar.gz
85 | RUN wget https://public-files.orthanc.team/third-party-downloads/boost_1_84_0_bcpdigest-1.12.3.tar.gz
86 | RUN wget https://public-files.orthanc.team/third-party-downloads/boost_1_85_0_bcpdigest-1.12.4.tar.gz
87 | RUN wget https://public-files.orthanc.team/third-party-downloads/boost_1_86_0_bcpdigest-1.12.5.tar.gz
88 | RUN wget https://public-files.orthanc.team/third-party-downloads/curl-8.5.0.tar.gz
89 | RUN wget https://public-files.orthanc.team/third-party-downloads/curl-8.9.0.tar.gz
90 | RUN wget https://public-files.orthanc.team/third-party-downloads/dcmtk-3.6.8.tar.gz
91 | RUN wget https://public-files.orthanc.team/third-party-downloads/gdcm-3.0.22.tar.gz
92 | RUN wget https://public-files.orthanc.team/third-party-downloads/jpegsrc.v9f.tar.gz
93 | RUN wget https://public-files.orthanc.team/third-party-downloads/jsoncpp-1.9.5.tar.gz
94 | RUN wget https://public-files.orthanc.team/third-party-downloads/libcsv-3.0.3.tar.gz
95 | RUN wget https://public-files.orthanc.team/third-party-downloads/libpng-1.6.40.tar.gz
96 | RUN wget https://public-files.orthanc.team/third-party-downloads/nifti_clib-3.0.0.tar.gz
97 | RUN wget https://public-files.orthanc.team/third-party-downloads/openssl-3.1.4.tar.gz
98 | RUN wget https://public-files.orthanc.team/third-party-downloads/protobuf-cpp-3.5.1.tar.gz
99 | RUN wget https://public-files.orthanc.team/third-party-downloads/pugixml-1.14.tar.gz
100 | RUN wget https://public-files.orthanc.team/third-party-downloads/sqlite-amalgamation-3460100.zip
101 | RUN wget https://public-files.orthanc.team/third-party-downloads/three.js-r154-sources.tar.gz
102 | RUN wget https://public-files.orthanc.team/third-party-downloads/VTK-7.1.1.tar.gz
103 | RUN wget https://public-files.orthanc.team/third-party-downloads/zlib-1.3.1.tar.gz
104 |
105 | # for python and java plugin
106 | RUN pip install pystache --break-system-packages
107 |
108 | COPY build-or-download.sh /scripts
109 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/stone-webviewer.json:
--------------------------------------------------------------------------------
1 | {
2 | "StoneWebViewer" :
3 | {
4 | /**
5 | * Defines how dates are displayed in the UI. If this option is not
6 | * set, the DICOM tags will be displayed as such. "DD" will be
7 | * replaced by the day, "MM" by the month, and "YYYY" by the year.
8 | **/
9 | // "DateFormat" : "DD/MM/YYYY",
10 |
11 | /**
12 | * Defines how times are displayed in the UI. If this option is not
13 | * set, the DICOM tags will be displayed as such. "hh" will be
14 | * replaced by the hour, "mm" by the minutes, "ss" by the seconds
15 | * and ".f" by the fractions of seconds.
16 | **/
17 | // "TimeFormat" : "hh:mm:ss.f",
18 |
19 |
20 | /**
21 | * This option allows you to define windowing presets.
22 | * For each preset, you must provide a name, the window width
23 | * and window center.
24 | **/
25 | "WindowingPresets" : [
26 | {"Name" : "CT Lung", "WindowCenter" : -400, "WindowWidth" : 1600},
27 | {"Name" : "CT Abdomen", "WindowCenter" : 60, "WindowWidth" : 400},
28 | {"Name" : "CT Bone", "WindowCenter" : 300, "WindowWidth" : 1500},
29 | {"Name" : "CT Brain", "WindowCenter" : 40, "WindowWidth" : 80},
30 | {"Name" : "CT Chest", "WindowCenter" : 40, "WindowWidth" : 400},
31 | {"Name" : "CT Angio", "WindowCenter" : 300, "WindowWidth" : 600}
32 | ],
33 |
34 | /**
35 | * Enables/disables the combined tool. This is the default mode
36 | * for mouse interactions. The combined tool allows to access the
37 | * windowing, zoom and pan from a single mouse configuration. The
38 | * behaviour of the combined tool is defined in
39 | * CombinedToolBehaviour. The available mouse actions are
40 | * "Crosshair", "Windowing", "Pan", "Rotate", "Zoom" and
41 | * "MagnifyingGlass".
42 | **/
43 | "CombinedToolEnabled" : true,
44 | "CombinedToolBehaviour" : {
45 | "LeftMouseButton" : "Windowing",
46 | "MiddleMouseButton" : "Pan",
47 | "RightMouseButton" : "Zoom"
48 | },
49 |
50 | /**
51 | * Enables/disables the print button.
52 | **/
53 | "PrintEnabled" : true,
54 |
55 | /**
56 | * Enables/disables the button to download a screenshot of the
57 | * active viewport as a JPEG file.
58 | **/
59 | "DownloadAsJpegEnabled" : true,
60 |
61 | /**
62 | * Enables/disables the button to download the display study.
63 | * Only used if "OrthancApiRoot" is properly set.
64 | **/
65 | "DownloadStudyEnabled" : true,
66 |
67 | /**
68 | * The allowed origin for messages corresponding to dynamic actions
69 | * triggered by another Web page using "window.postMessage()". The
70 | * special value "*" will allow any origin, which is an insecure
71 | * value to be used only during development. If this option is not
72 | * set, all the requests for dynamic actions will be rejected.
73 | * https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
74 | **/
75 | "ExpectedMessageOrigin" : "http://localhost:8042",
76 |
77 | /**
78 | * Root path of the DICOMweb server. This option is automatically
79 | * set by the Orthanc plugin if missing.
80 | **/
81 | "DicomWebRoot" : "../dicom-web",
82 |
83 | /**
84 | * Set the size of the cache that stores the DICOM files. This
85 | * size is expressed in megabytes. The default value of 128MB
86 | * should work in most setups, except if very large multiframe
87 | * instances are encountered, which might for instance be the case
88 | * for mammography. Setting this parameter to zero will disable
89 | * the cache, which should only be done for testing.
90 | **/
91 | "DicomCacheSize" : 128,
92 |
93 | /**
94 | * The following parameter can be set if running the Stone Web
95 | * viewer from Orthanc, but without using the associated plugin
96 | * (e.g. using the "Serve Folders" sample plugin). Using the
97 | * plugin would overwrite this setting. This will enable features
98 | * that are only available if the Orthanc REST API is accessible
99 | * (download of studies, and playing videos). This option is
100 | * typically used by the developers of Stone.
101 | **/
102 | "OrthancApiRoot" : "..",
103 |
104 | /**
105 | * If option "DownloadDicomDir" is set to "true", the Stone Web
106 | * viewer will create DICOMDIR media archives (as generated by the
107 | * route "/studies/{id}/media" of Orthanc), instead of archives
108 | * containing a human-readable hierarchy of folders (as generated
109 | * by the route "/studies/{id}/archive").
110 | **/
111 | "DownloadDicomDir" : false,
112 |
113 | /**
114 | * By setting option "InstitutionLogo" to an URL containing an
115 | * image, this logo will be displayed at the bottom-left of the
116 | * Stone Web viewer.
117 | **/
118 | "InstitutionLogo" : "",
119 |
120 | /**
121 | * Define a list of modality type that the viewer will ignore.
122 | **/
123 | "SkipSeriesFromModalities": ["SR", "SEG", "PR"],
124 |
125 | /**
126 | * Whether to display the info panel at startup. Allowed values:
127 | * "Always", "Never", "User". With "User", the user can decide to
128 | * show or not the info panel in the user preferences panel (this
129 | * is implemented using a cookie). (New in Stone Web viewer 2.4)
130 | **/
131 | "ShowInfoPanelAtStartup": "User",
132 |
133 | /**
134 | * Whether to give access to the user preferences window. (New in
135 | * Stone Web viewer 2.4)
136 | **/
137 | "ShowUserPreferencesButton" : true,
138 |
139 | /**
140 | * Display a "not for diagnostic usage" disclaimer above the list
141 | * of studies/series. (New in Stone Web viewer 2.4)
142 | **/
143 | "ShowNotForDiagnosticUsageDisclaimer": true,
144 |
145 | /**
146 | * HTTP headers to be set in each request to the DICOMweb server.
147 | * Note that the value of the headers can be taken from the
148 | * environment variables.
149 | **/
150 | "DicomWebHttpHeaders" : {
151 | /* "Authorization" : "Bearer ${USER}" */
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/CMake/DownloadPackage.cmake:
--------------------------------------------------------------------------------
1 | macro(GetUrlFilename TargetVariable Url)
2 | string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}")
3 | endmacro()
4 |
5 |
6 | macro(GetUrlExtension TargetVariable Url)
7 | #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}")
8 | string(REGEX REPLACE "^.*\\." "" TMP "${Url}")
9 | string(TOLOWER "${TMP}" "${TargetVariable}")
10 | endmacro()
11 |
12 |
13 |
14 | ##
15 | ## Setup the patch command-line tool
16 | ##
17 |
18 | if (NOT ORTHANC_DISABLE_PATCH)
19 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
20 | set(PATCH_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/../ThirdParty/patch/patch.exe)
21 | if (NOT EXISTS ${PATCH_EXECUTABLE})
22 | message(FATAL_ERROR "Unable to find the patch.exe tool that is shipped with Orthanc")
23 | endif()
24 |
25 | else ()
26 | find_program(PATCH_EXECUTABLE patch)
27 | if (${PATCH_EXECUTABLE} MATCHES "PATCH_EXECUTABLE-NOTFOUND")
28 | message(FATAL_ERROR "Please install the 'patch' standard command-line tool")
29 | endif()
30 | endif()
31 | endif()
32 |
33 |
34 |
35 | ##
36 | ## Check the existence of the required decompression tools
37 | ##
38 |
39 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
40 | find_program(ZIP_EXECUTABLE 7z
41 | PATHS
42 | "$ENV{ProgramFiles}/7-Zip"
43 | "$ENV{ProgramW6432}/7-Zip"
44 | )
45 |
46 | if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND")
47 | message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
48 | endif()
49 |
50 | else()
51 | find_program(UNZIP_EXECUTABLE unzip)
52 | if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND")
53 | message(FATAL_ERROR "Please install the 'unzip' package")
54 | endif()
55 |
56 | find_program(TAR_EXECUTABLE tar)
57 | if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND")
58 | message(FATAL_ERROR "Please install the 'tar' package")
59 | endif()
60 | endif()
61 |
62 |
63 | macro(DownloadPackage MD5 Url TargetDirectory)
64 | if (NOT IS_DIRECTORY "${TargetDirectory}")
65 | GetUrlFilename(TMP_FILENAME "${Url}")
66 |
67 | set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}")
68 | if (NOT EXISTS "${TMP_PATH}")
69 | message("Downloading ${Url}")
70 |
71 | # This fixes issue 6: "I think cmake shouldn't download the
72 | # packages which are not in the system, it should stop and let
73 | # user know."
74 | # https://code.google.com/p/orthanc/issues/detail?id=6
75 | if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
76 | message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
77 | endif()
78 |
79 | file(DOWNLOAD "${Url}" "${TMP_PATH}"
80 | SHOW_PROGRESS EXPECTED_MD5 "${MD5}"
81 | TIMEOUT 60 INACTIVITY_TIMEOUT 60)
82 | else()
83 | message("Using local copy of ${Url}")
84 | endif()
85 |
86 | GetUrlExtension(TMP_EXTENSION "${Url}")
87 | #message(${TMP_EXTENSION})
88 | message("Uncompressing ${TMP_FILENAME}")
89 |
90 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
91 | # How to silently extract files using 7-zip
92 | # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
93 |
94 | if (("${TMP_EXTENSION}" STREQUAL "gz") OR
95 | ("${TMP_EXTENSION}" STREQUAL "tgz") OR
96 | ("${TMP_EXTENSION}" STREQUAL "xz"))
97 | execute_process(
98 | COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH}
99 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
100 | RESULT_VARIABLE Failure
101 | OUTPUT_QUIET
102 | )
103 |
104 | if (Failure)
105 | message(FATAL_ERROR "Error while running the uncompression tool")
106 | endif()
107 |
108 | if ("${TMP_EXTENSION}" STREQUAL "tgz")
109 | string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}")
110 | elseif ("${TMP_EXTENSION}" STREQUAL "gz")
111 | string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}")
112 | elseif ("${TMP_EXTENSION}" STREQUAL "xz")
113 | string(REGEX REPLACE ".xz" "" TMP_FILENAME2 "${TMP_FILENAME}")
114 | endif()
115 |
116 | execute_process(
117 | COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2}
118 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
119 | RESULT_VARIABLE Failure
120 | OUTPUT_QUIET
121 | )
122 | elseif ("${TMP_EXTENSION}" STREQUAL "zip")
123 | execute_process(
124 | COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH}
125 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
126 | RESULT_VARIABLE Failure
127 | OUTPUT_QUIET
128 | )
129 | else()
130 | message(FATAL_ERROR "Support your platform here")
131 | endif()
132 |
133 | else()
134 | if ("${TMP_EXTENSION}" STREQUAL "zip")
135 | execute_process(
136 | COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}"
137 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
138 | RESULT_VARIABLE Failure
139 | )
140 | elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz"))
141 | #message("tar xvfz ${TMP_PATH}")
142 | execute_process(
143 | COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}"
144 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
145 | RESULT_VARIABLE Failure
146 | )
147 | elseif ("${TMP_EXTENSION}" STREQUAL "bz2")
148 | execute_process(
149 | COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}"
150 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
151 | RESULT_VARIABLE Failure
152 | )
153 | elseif ("${TMP_EXTENSION}" STREQUAL "xz")
154 | execute_process(
155 | COMMAND sh -c "${TAR_EXECUTABLE} xf ${TMP_PATH}"
156 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
157 | RESULT_VARIABLE Failure
158 | )
159 | else()
160 | message(FATAL_ERROR "Unknown package format.")
161 | endif()
162 | endif()
163 |
164 | if (Failure)
165 | message(FATAL_ERROR "Error while running the uncompression tool")
166 | endif()
167 |
168 | if (NOT IS_DIRECTORY "${TargetDirectory}")
169 | message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.")
170 | endif()
171 | endif()
172 | endmacro()
173 |
--------------------------------------------------------------------------------
/docker/integration-tests/orthanc-tests/Dockerfile:
--------------------------------------------------------------------------------
1 | # mercurial does not work anymore on jodogne/orthanc-tests -> use a specific image
2 | FROM ubuntu:22.04 AS ubuntu-hg
3 |
4 | RUN apt-get update
5 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install mercurial
6 |
7 | WORKDIR /
8 |
9 | ARG ORTHANC_TESTS_REVISION=default
10 | RUN hg clone https://orthanc.uclouvain.be/hg/orthanc-tests/ -r $ORTHANC_TESTS_REVISION
11 |
12 | ##############################################################
13 | FROM jodogne/orthanc-tests AS orthanc-tests
14 | RUN mkdir /tests
15 | WORKDIR /tests
16 |
17 | COPY --from=ubuntu-hg /orthanc-tests /tests/orthanc-tests
18 | RUN ls -al /tests/
19 | RUN mkdir /tmp/orthanc-tests/
20 |
21 | RUN mkdir /scripts
22 | COPY wait-for-it.sh /scripts
23 |
24 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Tests/Run.py --server=orthanc-under-tests --force --docker -- -v
25 |
26 | ##############################################################
27 | FROM python:2.7 AS python2-7-base-image
28 |
29 | RUN apt-get update
30 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install dcmtk
31 |
32 | RUN pip install easywebdav
33 | RUN pip install httplib2
34 | RUN pip install pillow
35 | RUN pip install pydicom==1.4.1
36 | RUN pip install pynetdicom==1.5.6
37 |
38 | RUN mkdir /tests
39 | WORKDIR /tests
40 |
41 | COPY --from=ubuntu-hg /orthanc-tests /tests/orthanc-tests
42 | RUN ls -al /tests/
43 | RUN mkdir /tmp/orthanc-tests/
44 |
45 | RUN mkdir /scripts
46 | COPY wait-for-it.sh /scripts
47 |
48 |
49 | ##############################################################
50 | # at some point, the easywebdav installation broke after an update of python:3.11 -> we use a snapshot
51 | FROM orthancteam/python-snapshots:3.11-for-integ-tests AS python3-base-image
52 |
53 | RUN apt-get update
54 | RUN DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install dcmtk
55 |
56 | RUN pip install httplib2 --break-system-package
57 | RUN pip install pillow --break-system-package
58 | RUN pip install pydicom==3.0.1 --break-system-package
59 | # TODO: upgrade to pynetdicom>=3.0.1
60 | RUN pip install pynetdicom==2.1.1 --break-system-package
61 | RUN pip install 'easywebdav @ git+https://github.com/Marpache9131/easywebdav@511967ec374061161f2b3b67fb7b164fcc78143c' --break-system-package
62 |
63 | # remove echoscu... from pynetdicom to make sure we use the ones from DCMTK
64 | RUN rm /usr/local/bin/findscu /usr/local/bin/storescu /usr/local/bin/echoscu /usr/local/bin/movescu /usr/local/bin/getscu
65 |
66 | RUN mkdir /tests
67 | WORKDIR /tests
68 |
69 | COPY --from=ubuntu-hg /orthanc-tests /tests/orthanc-tests
70 | RUN ls -al /tests/
71 | RUN mkdir /tmp/orthanc-tests/
72 |
73 | RUN mkdir /scripts
74 | COPY wait-for-it.sh /scripts
75 |
76 | ##############################################################
77 | FROM python3-base-image AS orthanc-tests-dicomweb
78 |
79 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/DicomWeb/Run.py --server=orthanc-under-tests --force -- -v
80 |
81 | ##############################################################
82 | FROM orthanc-tests AS orthanc-tests-worklists
83 |
84 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/Worklists/Run.py --server=orthanc-under-tests -- -v
85 |
86 | ##############################################################
87 | FROM orthanc-tests AS orthanc-tests-recycling
88 |
89 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/Recycling/Run.py --server=orthanc-under-tests --force -- -v
90 |
91 | ##############################################################
92 | FROM orthanc-tests AS orthanc-tests-transfers
93 |
94 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/Transfers/Run.py --server=orthanc-under-tests --force -- -v
95 |
96 | ##############################################################
97 | FROM python3-base-image AS orthanc-tests-wsi
98 |
99 | RUN apt-get update
100 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libtiff-tools
101 |
102 | RUN mkdir /apps
103 |
104 | RUN wget https://orthanc.uclouvain.be/downloads/linux-standard-base/orthanc-wsi/3.3/OrthancWSIDicomToTiff --output-document /apps/OrthancWSIDicomToTiff --quiet
105 | RUN wget https://orthanc.uclouvain.be/downloads/linux-standard-base/orthanc-wsi/3.3/OrthancWSIDicomizer --output-document /apps/OrthancWSIDicomizer --quiet
106 |
107 | RUN chmod +x /apps/*
108 |
109 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/WSI/Run.py --server=orthanc-under-tests --force --dicomizer=/apps/OrthancWSIDicomizer --to-tiff=/apps/OrthancWSIDicomToTiff -- -v
110 |
111 | ##############################################################
112 | FROM python3-base-image AS orthanc-tests-webdav
113 |
114 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/WebDav/Run.py --server=orthanc-under-tests --force -- -v
115 |
116 | ##############################################################
117 | FROM python3-base-image AS orthanc-tests-cget
118 |
119 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Plugins/CGet/Run.py --server=orthanc-under-tests --force -- -v
120 |
121 | ##############################################################
122 | FROM python3-base-image AS orthanc-tests-tls-no-check-client-generate-config
123 | WORKDIR /tls
124 | ENTRYPOINT python /tests/orthanc-tests/Tests/CheckDicomTls.py --config-no-check-client
125 |
126 | ##############################################################
127 | FROM python3-base-image AS orthanc-tests-tls-no-check-client
128 | WORKDIR /tls
129 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Tests/CheckDicomTls.py --server=orthanc-under-tests --force -- -v OrthancNoCheckClient
130 |
131 | ##############################################################
132 | FROM python3-base-image AS orthanc-tests-tls-check-client-generate-config
133 | WORKDIR /tls
134 | ENTRYPOINT python /tests/orthanc-tests/Tests/CheckDicomTls.py --config-check-client
135 |
136 | ##############################################################
137 | FROM python3-base-image AS orthanc-tests-tls-check-client
138 | WORKDIR /tls
139 | ENTRYPOINT /scripts/wait-for-it.sh orthanc-under-tests:8042 -t 60 && python /tests/orthanc-tests/Tests/CheckDicomTls.py --server=orthanc-under-tests --force -- -v OrthancCheckClient
140 |
--------------------------------------------------------------------------------
/bash-helpers.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # rewrite pushd/popd such that they do not produce any output in bash functions (https://stackoverflow.com/questions/25288194/dont-display-pushd-popd-stack-across-several-bash-scripts-quiet-pushd-popd)
4 | pushd () {
5 | command pushd "$@" > /dev/null
6 | }
7 |
8 | popd () {
9 | command popd "$@" > /dev/null
10 | }
11 |
12 |
13 | getFromMatrix() { # $1 = name, $2 = field, $3 = defaultValue
14 | value=$(cat build-matrix.json | jq -r ".configs[] | select( .name == \"$1\").$2")
15 | if [[ $value == "null" ]]; then
16 | echo $3
17 | else
18 | echo $value
19 | fi
20 | }
21 |
22 | getIntegTestsRevision() { # $1 = stable/unstable
23 | value=$(cat build-matrix.json | jq -r ".integrationTests.$1")
24 | echo $value
25 | }
26 |
27 | getArtifactsMacOS() { # $1 = name, $2 = version (stable or unstable)
28 | if [[ $2 == "unstable" ]]; then
29 |
30 | artifacts=$(getFromMatrix $1 unstableArtifactsMacOS)
31 |
32 | if [[ $artifacts == "" ]]; then
33 | artifacts=$(getFromMatrix $1 artifactsMacOS)
34 | fi
35 |
36 | else
37 |
38 | artifacts=$(getFromMatrix $1 artifactsMacOS)
39 |
40 | fi
41 |
42 | echo $artifacts
43 | }
44 |
45 | getBranchTagToBuildMacOS() { # $1 = name, $2 = version (stable or unstable)
46 | if [[ $2 == "stable" ]]; then
47 |
48 | revision=$(getFromMatrix $1 stableMacOS)
49 |
50 | if [[ $revision == "" ]]; then
51 | revision=$(getFromMatrix $1 stable)
52 | fi
53 |
54 | else
55 |
56 | revision=$(getFromMatrix $1 unstableMacOS)
57 |
58 | if [[ $revision == "" ]]; then
59 | revision=$(getFromMatrix $1 unstable)
60 | fi
61 |
62 | fi
63 |
64 | echo $revision
65 | }
66 |
67 | getPrebuildStepMacOS() { # $1 = name, $2 = version (stable or unstable)
68 | if [[ $2 == "stable" ]]; then
69 | prebuild=$(getFromMatrix $1 preBuildStableMacOS "")
70 | else
71 | prebuild=$(getFromMatrix $1 preBuildUnstableMacOS "")
72 | fi
73 |
74 | echo $prebuild
75 | }
76 |
77 | getCustomBuildMacOS() { # $1 = name, $2 = version (stable or unstable)
78 | if [[ $2 == "stable" ]]; then
79 | prebuild=$(getFromMatrix $1 customBuildMacOS "")
80 | else
81 | prebuild=$(getFromMatrix $1 customBuildMacOS "")
82 | fi
83 |
84 | echo $prebuild
85 | }
86 |
87 | getArtifactsWin() { # $1 = name, $2 = version (stable or unstable)
88 | if [[ $2 == "unstable" ]]; then
89 |
90 | artifacts=$(getFromMatrix $1 unstableArtifactsWin)
91 |
92 | if [[ $artifacts == "" ]]; then
93 | artifacts=$(getFromMatrix $1 artifactsWin)
94 | fi
95 |
96 | else
97 |
98 | artifacts=$(getFromMatrix $1 artifactsWin)
99 |
100 | fi
101 |
102 | echo $artifacts
103 | }
104 |
105 | getBranchTagToBuildWin() { # $1 = name, $2 = version (stable or unstable)
106 | if [[ $2 == "stable" ]]; then
107 |
108 | revision=$(getFromMatrix $1 stableWin)
109 |
110 | if [[ $revision == "" ]]; then
111 | revision=$(getFromMatrix $1 stable)
112 | fi
113 |
114 | else
115 |
116 | revision=$(getFromMatrix $1 unstableWin)
117 |
118 | if [[ $revision == "" ]]; then
119 | revision=$(getFromMatrix $1 unstable)
120 | fi
121 |
122 | fi
123 |
124 | echo $revision
125 | }
126 |
127 | getPrebuildStepWin() { # $1 = name, $2 = version (stable or unstable)
128 | if [[ $2 == "stable" ]]; then
129 | prebuild=$(getFromMatrix $1 preBuildStableWin "")
130 |
131 | if [[ $prebuild == "" ]]; then
132 | prebuild=$(getFromMatrix $1 preBuildWin "")
133 | fi
134 | else
135 | prebuild=$(getFromMatrix $1 preBuildUnstableWin "")
136 |
137 | if [[ $prebuild == "" ]]; then
138 | prebuild=$(getFromMatrix $1 preBuildWin "")
139 | fi
140 | fi
141 |
142 | echo $prebuild
143 | }
144 |
145 | getCustomBuildWin() { # $1 = name, $2 = version (stable or unstable)
146 | if [[ $2 == "stable" ]]; then
147 | prebuild=$(getFromMatrix $1 customBuildWin "")
148 | else
149 | prebuild=$(getFromMatrix $1 customBuildWin "")
150 | fi
151 |
152 | echo $prebuild
153 | }
154 |
155 |
156 | getBranchTagToBuildDocker() { # $1 = name, $2 = version (stable or unstable)
157 | if [[ $2 == "stable" ]]; then
158 |
159 | revision=$(getFromMatrix $1 stableDocker)
160 |
161 | if [[ $revision == "" ]]; then
162 | revision=$(getFromMatrix $1 stable)
163 | fi
164 |
165 | else
166 |
167 | revision=$(getFromMatrix $1 unstableDocker)
168 |
169 | if [[ $revision == "" ]]; then
170 | revision=$(getFromMatrix $1 unstable)
171 | fi
172 |
173 | fi
174 |
175 | echo $revision
176 | }
177 |
178 | getBranchTagToBuildWin() { # $1 = name, $2 = version (stable or unstable)
179 | if [[ $2 == "stable" ]]; then
180 |
181 | revision=$(getFromMatrix $1 stableWin)
182 |
183 | if [[ $revision == "" ]]; then
184 | revision=$(getFromMatrix $1 stable)
185 | fi
186 |
187 | else
188 |
189 | revision=$(getFromMatrix $1 unstableWin)
190 |
191 | if [[ $revision == "" ]]; then
192 | revision=$(getFromMatrix $1 unstable)
193 | fi
194 |
195 | fi
196 |
197 | echo $revision
198 | }
199 |
200 | getHgCommitId() { # $1 = repo, $2 = branch/tag/revision
201 | commit_id=$(hg identify $1 -r $2)
202 | echo $commit_id
203 | }
204 |
205 | getGitCommitId() { # $1 = repo, $2 = branch/tag/revision
206 | tmp=$(mktemp -d -t git-check-last-commit-XXXXXXXXXXX)
207 | git clone --quiet --filter=blob:none --no-checkout $1 $tmp
208 | pushd $tmp
209 | git checkout $2 &> /dev/null
210 | local commit_id=$(git rev-parse $2)
211 | popd
212 | rm -rf $tmp
213 |
214 | echo $commit_id
215 | }
216 |
217 | getCommitId() { # $1 = name, $2 = version (stable or unstable), $3 = platform (macos/win/docker), $4 = skipCommitCheck (0/1), $5 = throttle (0/1)
218 |
219 | if [[ $3 == "macos" ]]; then
220 | revision=$(getBranchTagToBuildMacOS $1 $2)
221 | elif [[ $3 == "win" ]]; then
222 | revision=$(getBranchTagToBuildWin $1 $2)
223 | else
224 | revision=$(getBranchTagToBuildDocker $1 $2)
225 | fi
226 |
227 | if [[ $4 == "1" ]]; then
228 | echo $revision
229 | return
230 | fi
231 |
232 | if [[ $5 == "1" ]]; then
233 | # throttle on CI because we get a lot of bad gateway errors on UCLouvain server
234 | sleep 1
235 | fi
236 |
237 | # get the last commit id for this revision
238 | repo=$(getFromMatrix $1 repo)
239 | repoType=$(getFromMatrix $1 repoType)
240 |
241 | if [[ $repoType == "hg" ]]; then
242 |
243 | commit_id=$(getHgCommitId $repo $revision)
244 |
245 | elif [[ $repoType == "git" ]]; then
246 |
247 | commit_id=$(getGitCommitId $repo $revision)
248 |
249 | fi
250 |
251 | echo $commit_id
252 | }
253 |
--------------------------------------------------------------------------------
/.github/workflows/all-builds.yml:
--------------------------------------------------------------------------------
1 | name: all-builds
2 |
3 | on:
4 | schedule:
5 | - cron: "0 23 * * *"
6 | push:
7 | branches:
8 | - '*'
9 | tags:
10 | - '*'
11 |
12 | pull_request:
13 | branches: [ master ]
14 |
15 | concurrency:
16 | group: branch-or-tag
17 | cancel-in-progress: ${{ startsWith(github.ref, 'refs/tags/') }}
18 |
19 | jobs:
20 | pre-build:
21 | uses: ./.github/workflows/pre-build.yml
22 |
23 | build-stone-wasm-stable:
24 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
25 | needs: [pre-build]
26 | uses: ./.github/workflows/build-stone-wasm.yml
27 | with:
28 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
29 | stable_unstable: stable
30 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
31 | secrets:
32 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
33 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
34 |
35 | build-stone-wasm-unstable:
36 | if: ${{ needs.pre-build.outputs.is_tag == 'false' }}
37 | needs: [pre-build]
38 | uses: ./.github/workflows/build-stone-wasm.yml
39 | with:
40 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
41 | stable_unstable: unstable
42 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
43 | secrets:
44 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
45 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
46 |
47 | build-volview-dist-stable:
48 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
49 | needs: [pre-build]
50 | uses: ./.github/workflows/build-volview-dist.yml
51 | with:
52 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
53 | stable_unstable: stable
54 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
55 | secrets:
56 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
57 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
58 |
59 | build-volview-dist-unstable:
60 | if: ${{ needs.pre-build.outputs.is_tag == 'false' }}
61 | needs: [pre-build]
62 | uses: ./.github/workflows/build-volview-dist.yml
63 | with:
64 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
65 | stable_unstable: unstable
66 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
67 | secrets:
68 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
69 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
70 |
71 | win-stable-build:
72 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
73 | needs: [pre-build, build-stone-wasm-stable]
74 | uses: ./.github/workflows/build-win-binaries.yml
75 | with:
76 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
77 | stable_unstable: stable
78 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
79 | secrets:
80 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
81 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
82 |
83 | win-unstable-build:
84 | if: ${{ needs.pre-build.outputs.is_tag == 'false' }}
85 | needs: [pre-build, build-stone-wasm-unstable]
86 | uses: ./.github/workflows/build-win-binaries.yml
87 | with:
88 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
89 | stable_unstable: unstable
90 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
91 | secrets:
92 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
93 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
94 |
95 | macos-stable-build:
96 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
97 | needs: [pre-build, build-stone-wasm-stable, build-volview-dist-stable]
98 | uses: ./.github/workflows/build-macos-binaries.yml
99 | with:
100 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
101 | stable_unstable: stable
102 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
103 | secrets:
104 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
105 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
106 |
107 | macos-unstable-build:
108 | if: ${{ needs.pre-build.outputs.is_tag == 'false' }}
109 | needs: [pre-build, build-stone-wasm-unstable, build-volview-dist-unstable]
110 | uses: ./.github/workflows/build-macos-binaries.yml
111 | with:
112 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
113 | stable_unstable: unstable
114 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
115 | secrets:
116 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
117 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
118 |
119 |
120 | macos-stable-package:
121 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
122 | needs: [pre-build, macos-stable-build]
123 | uses: ./.github/workflows/build-macos-package.yml
124 | with:
125 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
126 | stable_unstable: stable
127 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
128 | secrets:
129 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
130 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
131 |
132 | macos-unstable-package:
133 | if: ${{ needs.pre-build.outputs.is_tag == 'false' }}
134 | needs: [pre-build, macos-unstable-build]
135 | uses: ./.github/workflows/build-macos-package.yml
136 | with:
137 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
138 | stable_unstable: unstable
139 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
140 | secrets:
141 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
142 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
143 |
144 |
145 | build-windows-installer:
146 | if: ${{ github.ref == 'refs/heads/master' || needs.pre-build.outputs.is_tag == 'true' }}
147 | needs: [pre-build, win-stable-build] #, TODO: build win binaries as well build-win-binaries-unstable]
148 | uses: ./.github/workflows/build-windows-installer.yml
149 | with:
150 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
151 | stable_unstable: unstable
152 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
153 | secrets:
154 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
155 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
156 |
157 |
158 | build-docker:
159 | needs: [pre-build]
160 | uses: ./.github/workflows/build-all-dockers.yml
161 | with:
162 | is_tag: ${{ needs.pre-build.outputs.is_tag }}
163 | current_branch_tag: ${{ needs.pre-build.outputs.current_branch_tag }}
164 | secrets:
165 | docker_hub_username: ${{ secrets.DOCKERHUB_USERNAME }}
166 | docker_hub_token: ${{ secrets.DOCKERHUB_TOKEN }}
167 | aws_access_key_id: ${{ secrets.OT_AWS_ACCESS_KEY_ID }}
168 | aws_secret_access_key: ${{ secrets.OT_AWS_SECRET_ACCESS_KEY }}
--------------------------------------------------------------------------------
/WindowsInstaller/Resources/CMake/Compiler.cmake:
--------------------------------------------------------------------------------
1 | # This file sets all the compiler-related flags
2 |
3 | if (CMAKE_CROSSCOMPILING)
4 | # Cross-compilation necessarily implies standalone and static build
5 | SET(STATIC_BUILD ON)
6 | SET(STANDALONE_BUILD ON)
7 | endif()
8 |
9 | if (CMAKE_COMPILER_IS_GNUCXX)
10 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -Wno-implicit-function-declaration")
11 | # --std=c99 makes libcurl not to compile
12 | # -pedantic gives a lot of warnings on OpenSSL
13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -Wno-variadic-macros")
14 |
15 | if (CMAKE_CROSSCOMPILING)
16 | # http://stackoverflow.com/a/3543845/881731
17 | set(CMAKE_RC_COMPILE_OBJECT " -O coff -I