# HG changeset patch # User Sebastien Jodogne # Date 1611584314 -3600 # Node ID 9c070a34de1848f18e95d7ed1cc95eeffd1981de # Parent c92ec129698ad4e83cca00baf57013d9f2d70d7a IApplicationEntityFilter::GetAcceptedTransferSyntaxes() diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Resources/CodeGeneration/CheckDcmtkTransferSyntaxes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Resources/CodeGeneration/CheckDcmtkTransferSyntaxes.py Mon Jan 25 15:18:34 2021 +0100 @@ -0,0 +1,49 @@ +#!/usr/bin/python + +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# Copyright (C) 2017-2021 Osimis S.A., Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program. If not, see +# . + + +import json +import os +import re +import sys + +if len(sys.argv) != 2: + print('Usage: %s [Path to DCMTK source code]' % sys.argv[0]) + exit(-1) + + +orthancSyntaxes = [] + + +with open(os.path.join(os.path.dirname(__file__), 'DicomTransferSyntaxes.json'), 'r') as f: + for syntax in json.loads(f.read()): + orthancSyntaxes.append(syntax['UID']) + + +with open(os.path.join(sys.argv[1], 'dcmdata/include/dcmtk/dcmdata/dcuid.h'), 'r') as f: + r = re.compile(r'^#define UID_([A-Za-z0-9_]+)TransferSyntax\s+"([0-9.]+)"$') + + for line in f.readlines(): + m = r.match(line) + if m != None: + syntax = m.group(2) + if not syntax in orthancSyntaxes: + print('Missing syntax: %s => %s' % (syntax, m.group(1))) diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxes.py --- a/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxes.py Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxes.py Mon Jan 25 15:18:34 2021 +0100 @@ -26,7 +26,7 @@ import sys import pystache -BASE = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +BASE = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) @@ -34,7 +34,7 @@ ## https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EDICOM_transfer_syntax -with open(os.path.join(BASE, 'Resources', 'DicomTransferSyntaxes.json'), 'r') as f: +with open(os.path.join(BASE, 'Resources', 'CodeGeneration', 'DicomTransferSyntaxes.json'), 'r') as f: SYNTAXES = json.loads(f.read()) @@ -43,7 +43,7 @@ ## Generate the "DicomTransferSyntax" enumeration in "Enumerations.h" ## -path = os.path.join(BASE, 'Core', 'Enumerations.h') +path = os.path.join(BASE, 'Sources', 'Enumerations.h') with open(path, 'r') as f: a = f.read() @@ -60,14 +60,14 @@ ## Generate the implementations ## -with open(os.path.join(BASE, 'Core', 'Enumerations_TransferSyntaxes.impl.h'), 'w') as b: - with open(os.path.join(BASE, 'Resources', 'GenerateTransferSyntaxesEnumerations.mustache'), 'r') as a: +with open(os.path.join(BASE, 'Sources', 'Enumerations_TransferSyntaxes.impl.h'), 'w') as b: + with open(os.path.join(BASE, 'Resources', 'CodeGeneration', 'GenerateTransferSyntaxesEnumerations.mustache'), 'r') as a: b.write(pystache.render(a.read(), { 'Syntaxes' : SYNTAXES })) -with open(os.path.join(BASE, 'Core', 'DicomParsing', 'FromDcmtkBridge_TransferSyntaxes.impl.h'), 'w') as b: - with open(os.path.join(BASE, 'Resources', 'GenerateTransferSyntaxesDcmtk.mustache'), 'r') as a: +with open(os.path.join(BASE, 'Sources', 'DicomParsing', 'FromDcmtkBridge_TransferSyntaxes.impl.h'), 'w') as b: + with open(os.path.join(BASE, 'Resources', 'CodeGeneration', 'GenerateTransferSyntaxesDcmtk.mustache'), 'r') as a: b.write(pystache.render(a.read(), { 'Syntaxes' : SYNTAXES })) diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache --- a/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache Mon Jan 25 15:18:34 2021 +0100 @@ -71,4 +71,13 @@ {{/Syntaxes}} return false; } + + + void GetAllTransferSyntaxes(std::set& target) + { + target.clear(); + {{#Syntaxes}} + target.insert(DicomTransferSyntax_{{Value}}); + {{/Syntaxes}} + } } diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Sources/DicomNetworking/IApplicationEntityFilter.h --- a/OrthancFramework/Sources/DicomNetworking/IApplicationEntityFilter.h Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Sources/DicomNetworking/IApplicationEntityFilter.h Mon Jan 25 15:18:34 2021 +0100 @@ -22,6 +22,7 @@ #pragma once +#include "../Compatibility.h" #include "../Enumerations.h" #include @@ -44,10 +45,15 @@ const std::string& calledAet, DicomRequestType type) = 0; - virtual bool IsAllowedTransferSyntax(const std::string& remoteIp, - const std::string& remoteAet, - const std::string& calledAet, - TransferSyntax syntax) = 0; + virtual void GetAcceptedTransferSyntaxes(std::set& target, + const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet) = 0; + + ORTHANC_DEPRECATED(virtual bool IsAllowedTransferSyntax(const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet, + TransferSyntax syntax)) = 0; virtual bool IsUnknownSopClassAccepted(const std::string& remoteIp, const std::string& remoteAet, diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp --- a/OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp Mon Jan 25 15:18:34 2021 +0100 @@ -409,185 +409,152 @@ { /* accept the abstract syntaxes for C-STORE, if presented */ - - std::vector storageTransferSyntaxes; - - // This is the list of the transfer syntaxes that were supported up to Orthanc 0.7.1 - storageTransferSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); - storageTransferSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax); - storageTransferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + + std::set storageTransferSyntaxes; - // New transfer syntaxes supported since Orthanc 0.7.2 - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Deflated)) - { - storageTransferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); - } - - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpeg)) + if (server.HasApplicationEntityFilter()) { - storageTransferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax); + server.GetApplicationEntityFilter().GetAcceptedTransferSyntaxes( + storageTransferSyntaxes, remoteIp, remoteAet, calledAet); } - - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpeg2000)) + else { - storageTransferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEG2000TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEG2000TransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax); - } - - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_JpegLossless)) - { - storageTransferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax); - storageTransferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax); - } - - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpip)) - { - storageTransferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax); - storageTransferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax); - } - - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Mpeg2)) - { - storageTransferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax); - storageTransferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax); + /** + * In the absence of filter, accept all the known transfer + * syntaxes. Note that this is different from Orthanc + * framework <= 1.8.2, where only the uncompressed transfer + * syntaxes are accepted by default. + **/ + GetAllTransferSyntaxes(storageTransferSyntaxes); } -#if DCMTK_VERSION_NUMBER >= 361 - // New in Orthanc 1.6.0 - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Mpeg4)) + if (storageTransferSyntaxes.empty()) + { + LOG(WARNING) << "The DICOM server accepts no transfer syntax, thus C-STORE SCP is disabled"; + } + else { - storageTransferSyntaxes.push_back(UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax); - storageTransferSyntaxes.push_back(UID_MPEG4HighProfileLevel4_1TransferSyntax); - storageTransferSyntaxes.push_back(UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax); - storageTransferSyntaxes.push_back(UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax); - storageTransferSyntaxes.push_back(UID_MPEG4StereoHighProfileLevel4_2TransferSyntax); - } -#endif + /** + * If accepted, put "Little Endian Explicit" at the first + * place in the accepted transfer syntaxes. This first place + * has an impact on the result of "getscu" (cf. integration + * test "test_getscu"). We choose "Little Endian Explicit", + * as this preserves the VR of the private tags, even if the + * remote modality doesn't have the dictionary of private tags. + * + * TODO - Should "PREFERRED_TRANSFER_SYNTAX" be an option of + * class "DicomServer"? + **/ + const DicomTransferSyntax PREFERRED_TRANSFER_SYNTAX = DicomTransferSyntax_LittleEndianExplicit; + + std::vector storageTransferSyntaxesC; + storageTransferSyntaxesC.reserve(storageTransferSyntaxes.size()); - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Rle)) - { - storageTransferSyntaxes.push_back(UID_RLELosslessTransferSyntax); - } + if (storageTransferSyntaxes.find(PREFERRED_TRANSFER_SYNTAX) != storageTransferSyntaxes.end()) + { + storageTransferSyntaxesC.push_back(GetTransferSyntaxUid(PREFERRED_TRANSFER_SYNTAX)); + } + + for (std::set::const_iterator + it = storageTransferSyntaxes.begin(); it != storageTransferSyntaxes.end(); ++it) + { + if (*it != PREFERRED_TRANSFER_SYNTAX) // Don't add the preferred transfer syntax twice + { + storageTransferSyntaxesC.push_back(GetTransferSyntaxUid(*it)); + } + } - /* the array of Storage SOP Class UIDs that is defined within "dcmdata/libsrc/dcuid.cc" */ - size_t count = 0; - while (dcmAllStorageSOPClassUIDs[count] != NULL) - { - count++; - } + /* the array of Storage SOP Class UIDs that is defined within "dcmdata/libsrc/dcuid.cc" */ + size_t count = 0; + while (dcmAllStorageSOPClassUIDs[count] != NULL) + { + count++; + } #if DCMTK_VERSION_NUMBER >= 362 - // The global variable "numberOfDcmAllStorageSOPClassUIDs" is - // only published if DCMTK >= 3.6.2: - // https://bitbucket.org/sjodogne/orthanc/issues/137 - assert(static_cast(count) == numberOfDcmAllStorageSOPClassUIDs); + // The global variable "numberOfDcmAllStorageSOPClassUIDs" is + // only published if DCMTK >= 3.6.2: + // https://bitbucket.org/sjodogne/orthanc/issues/137 + assert(static_cast(count) == numberOfDcmAllStorageSOPClassUIDs); #endif - if (!server.HasGetRequestHandlerFactory()) // dcmqrsrv.cc line 828 - { - // This branch exactly corresponds to Orthanc <= 1.6.1 (in - // which C-GET SCP was not supported) - cond = ASC_acceptContextsWithPreferredTransferSyntaxes( - assoc->params, dcmAllStorageSOPClassUIDs, count, - &storageTransferSyntaxes[0], storageTransferSyntaxes.size()); - if (cond.bad()) + if (!server.HasGetRequestHandlerFactory()) // dcmqrsrv.cc line 828 { - CLOG(INFO, DICOM) << cond.text(); - AssociationCleanup(assoc); - return NULL; + // This branch exactly corresponds to Orthanc <= 1.6.1 (in + // which C-GET SCP was not supported) + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( + assoc->params, dcmAllStorageSOPClassUIDs, count, + &storageTransferSyntaxesC[0], storageTransferSyntaxesC.size()); + if (cond.bad()) + { + CLOG(INFO, DICOM) << cond.text(); + AssociationCleanup(assoc); + return NULL; + } } - } - else // see dcmqrsrv.cc lines 839 - 876 - { - /* accept storage syntaxes with proposed role */ - int npc = ASC_countPresentationContexts(assoc->params); - for (int i = 0; i < npc; i++) + else // see dcmqrsrv.cc lines 839 - 876 { - T_ASC_PresentationContext pc; - ASC_getPresentationContext(assoc->params, i, &pc); - if (dcmIsaStorageSOPClassUID(pc.abstractSyntax)) + /* accept storage syntaxes with proposed role */ + int npc = ASC_countPresentationContexts(assoc->params); + for (int i = 0; i < npc; i++) { - /** - * We are prepared to accept whatever role the caller - * proposes. Normally we can be the SCP of the Storage - * Service Class. When processing the C-GET operation - * we can be the SCU of the Storage Service Class. - **/ - const T_ASC_SC_ROLE role = pc.proposedRole; - - /** - * Accept in the order "least wanted" to "most wanted" - * transfer syntax. Accepting a transfer syntax will - * override previously accepted transfer syntaxes. - **/ - for (int k = static_cast(storageTransferSyntaxes.size()) - 1; k >= 0; k--) + T_ASC_PresentationContext pc; + ASC_getPresentationContext(assoc->params, i, &pc); + if (dcmIsaStorageSOPClassUID(pc.abstractSyntax)) { - for (int j = 0; j < static_cast(pc.transferSyntaxCount); j++) + /** + * We are prepared to accept whatever role the caller + * proposes. Normally we can be the SCP of the Storage + * Service Class. When processing the C-GET operation + * we can be the SCU of the Storage Service Class. + **/ + const T_ASC_SC_ROLE role = pc.proposedRole; + + /** + * Accept in the order "least wanted" to "most wanted" + * transfer syntax. Accepting a transfer syntax will + * override previously accepted transfer syntaxes. + **/ + for (int k = static_cast(storageTransferSyntaxesC.size()) - 1; k >= 0; k--) { - /** - * If the transfer syntax was proposed then we can accept it - * appears in our supported list of transfer syntaxes - **/ - if (strcmp(pc.proposedTransferSyntaxes[j], storageTransferSyntaxes[k]) == 0) + for (int j = 0; j < static_cast(pc.transferSyntaxCount); j++) { - cond = ASC_acceptPresentationContext( - assoc->params, pc.presentationContextID, storageTransferSyntaxes[k], role); - if (cond.bad()) + /** + * If the transfer syntax was proposed then we can accept it + * appears in our supported list of transfer syntaxes + **/ + if (strcmp(pc.proposedTransferSyntaxes[j], storageTransferSyntaxesC[k]) == 0) { - CLOG(INFO, DICOM) << cond.text(); - AssociationCleanup(assoc); - return NULL; + cond = ASC_acceptPresentationContext( + assoc->params, pc.presentationContextID, storageTransferSyntaxesC[k], role); + if (cond.bad()) + { + CLOG(INFO, DICOM) << cond.text(); + AssociationCleanup(assoc); + return NULL; + } } } } } - } - } /* for */ - } + } /* for */ + } - if (!server.HasApplicationEntityFilter() || - server.GetApplicationEntityFilter().IsUnknownSopClassAccepted(remoteIp, remoteAet, calledAet)) - { - /* - * Promiscous mode is enabled: Accept everything not known not - * to be a storage SOP class. - **/ - cond = acceptUnknownContextsWithPreferredTransferSyntaxes( - assoc->params, &storageTransferSyntaxes[0], storageTransferSyntaxes.size(), ASC_SC_ROLE_DEFAULT); - if (cond.bad()) + if (!server.HasApplicationEntityFilter() || + server.GetApplicationEntityFilter().IsUnknownSopClassAccepted(remoteIp, remoteAet, calledAet)) { - CLOG(INFO, DICOM) << cond.text(); - AssociationCleanup(assoc); - return NULL; + /* + * Promiscous mode is enabled: Accept everything not known not + * to be a storage SOP class. + **/ + cond = acceptUnknownContextsWithPreferredTransferSyntaxes( + assoc->params, &storageTransferSyntaxesC[0], storageTransferSyntaxesC.size(), ASC_SC_ROLE_DEFAULT); + if (cond.bad()) + { + CLOG(INFO, DICOM) << cond.text(); + AssociationCleanup(assoc); + return NULL; + } } } } diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Sources/Enumerations.h --- a/OrthancFramework/Sources/Enumerations.h Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Sources/Enumerations.h Mon Jan 25 15:18:34 2021 +0100 @@ -24,6 +24,7 @@ #include "OrthancFramework.h" +#include #include @@ -894,4 +895,7 @@ const char* GetResourceTypeText(ResourceType type, bool isPlural, bool isLowerCase); + + ORTHANC_PUBLIC + void GetAllTransferSyntaxes(std::set& target); } diff -r c92ec129698a -r 9c070a34de18 OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h --- a/OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h Mon Jan 25 15:18:34 2021 +0100 @@ -552,4 +552,52 @@ return false; } + + + void GetAllTransferSyntaxes(std::set& target) + { + target.clear(); + target.insert(DicomTransferSyntax_LittleEndianImplicit); + target.insert(DicomTransferSyntax_LittleEndianExplicit); + target.insert(DicomTransferSyntax_DeflatedLittleEndianExplicit); + target.insert(DicomTransferSyntax_BigEndianExplicit); + target.insert(DicomTransferSyntax_JPEGProcess1); + target.insert(DicomTransferSyntax_JPEGProcess2_4); + target.insert(DicomTransferSyntax_JPEGProcess3_5); + target.insert(DicomTransferSyntax_JPEGProcess6_8); + target.insert(DicomTransferSyntax_JPEGProcess7_9); + target.insert(DicomTransferSyntax_JPEGProcess10_12); + target.insert(DicomTransferSyntax_JPEGProcess11_13); + target.insert(DicomTransferSyntax_JPEGProcess14); + target.insert(DicomTransferSyntax_JPEGProcess15); + target.insert(DicomTransferSyntax_JPEGProcess16_18); + target.insert(DicomTransferSyntax_JPEGProcess17_19); + target.insert(DicomTransferSyntax_JPEGProcess20_22); + target.insert(DicomTransferSyntax_JPEGProcess21_23); + target.insert(DicomTransferSyntax_JPEGProcess24_26); + target.insert(DicomTransferSyntax_JPEGProcess25_27); + target.insert(DicomTransferSyntax_JPEGProcess28); + target.insert(DicomTransferSyntax_JPEGProcess29); + target.insert(DicomTransferSyntax_JPEGProcess14SV1); + target.insert(DicomTransferSyntax_JPEGLSLossless); + target.insert(DicomTransferSyntax_JPEGLSLossy); + target.insert(DicomTransferSyntax_JPEG2000LosslessOnly); + target.insert(DicomTransferSyntax_JPEG2000); + target.insert(DicomTransferSyntax_JPEG2000MulticomponentLosslessOnly); + target.insert(DicomTransferSyntax_JPEG2000Multicomponent); + target.insert(DicomTransferSyntax_JPIPReferenced); + target.insert(DicomTransferSyntax_JPIPReferencedDeflate); + target.insert(DicomTransferSyntax_MPEG2MainProfileAtMainLevel); + target.insert(DicomTransferSyntax_MPEG2MainProfileAtHighLevel); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_1); + target.insert(DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo); + target.insert(DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2); + target.insert(DicomTransferSyntax_HEVCMainProfileLevel5_1); + target.insert(DicomTransferSyntax_HEVCMain10ProfileLevel5_1); + target.insert(DicomTransferSyntax_RLELossless); + target.insert(DicomTransferSyntax_RFC2557MimeEncapsulation); + target.insert(DicomTransferSyntax_XML); + } } diff -r c92ec129698a -r 9c070a34de18 OrthancServer/Sources/main.cpp --- a/OrthancServer/Sources/main.cpp Thu Jan 21 19:06:00 2021 +0100 +++ b/OrthancServer/Sources/main.cpp Mon Jan 25 15:18:34 2021 +0100 @@ -364,6 +364,92 @@ } } + + virtual void GetAcceptedTransferSyntaxes(std::set& target, + const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet) ORTHANC_OVERRIDE + { + target.clear(); + + // This is the list of the transfer syntaxes that were supported up to Orthanc 0.7.1 + target.insert(DicomTransferSyntax_LittleEndianExplicit); + target.insert(DicomTransferSyntax_BigEndianExplicit); + target.insert(DicomTransferSyntax_LittleEndianImplicit); + + // New transfer syntaxes supported since Orthanc 0.7.2 + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Deflated)) + { + target.insert(DicomTransferSyntax_DeflatedLittleEndianExplicit); + } + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpeg)) + { + target.insert(DicomTransferSyntax_JPEGProcess1); + target.insert(DicomTransferSyntax_JPEGProcess2_4); + target.insert(DicomTransferSyntax_JPEGProcess3_5); + target.insert(DicomTransferSyntax_JPEGProcess6_8); + target.insert(DicomTransferSyntax_JPEGProcess7_9); + target.insert(DicomTransferSyntax_JPEGProcess10_12); + target.insert(DicomTransferSyntax_JPEGProcess11_13); + target.insert(DicomTransferSyntax_JPEGProcess14); + target.insert(DicomTransferSyntax_JPEGProcess15); + target.insert(DicomTransferSyntax_JPEGProcess16_18); + target.insert(DicomTransferSyntax_JPEGProcess17_19); + target.insert(DicomTransferSyntax_JPEGProcess20_22); + target.insert(DicomTransferSyntax_JPEGProcess21_23); + target.insert(DicomTransferSyntax_JPEGProcess24_26); + target.insert(DicomTransferSyntax_JPEGProcess25_27); + target.insert(DicomTransferSyntax_JPEGProcess28); + target.insert(DicomTransferSyntax_JPEGProcess29); + target.insert(DicomTransferSyntax_JPEGProcess14SV1); + } + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpeg2000)) + { + target.insert(DicomTransferSyntax_JPEG2000); + target.insert(DicomTransferSyntax_JPEG2000LosslessOnly); + target.insert(DicomTransferSyntax_JPEG2000Multicomponent); + target.insert(DicomTransferSyntax_JPEG2000MulticomponentLosslessOnly); + } + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_JpegLossless)) + { + target.insert(DicomTransferSyntax_JPEGLSLossless); + target.insert(DicomTransferSyntax_JPEGLSLossy); + } + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Jpip)) + { + target.insert(DicomTransferSyntax_JPIPReferenced); + target.insert(DicomTransferSyntax_JPIPReferencedDeflate); + } + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Mpeg2)) + { + target.insert(DicomTransferSyntax_MPEG2MainProfileAtMainLevel); + target.insert(DicomTransferSyntax_MPEG2MainProfileAtHighLevel); + } + +#if DCMTK_VERSION_NUMBER >= 361 + // New in Orthanc 1.6.0 + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Mpeg4)) + { + target.insert(DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_1); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo); + target.insert(DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo); + target.insert(DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2); + } +#endif + + if (IsAllowedTransferSyntax(remoteIp, remoteAet, calledAet, TransferSyntax_Rle)) + { + target.insert(DicomTransferSyntax_RLELossless); + } + } + + virtual bool IsAllowedTransferSyntax(const std::string& remoteIp, const std::string& remoteAet, const std::string& calledAet,