changeset 3349:ef18ea68a362

merge
author Alain Mazy <alain@mazy.be>
date Thu, 18 Apr 2019 15:52:56 +0200
parents a1cd981a0f9a (current diff) ab17e8e94776 (diff)
children ba051f674f4b 5069af20932a
files
diffstat 20 files changed, 103 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomNetworking/DicomUserConnection.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/Core/DicomNetworking/DicomUserConnection.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -590,11 +590,11 @@
           }
         }
 
-        return new ParsedDicomFile(*fix);
+        return new ParsedDicomFile(*fix, GetDefaultDicomEncoding(), false /* be strict */);
       }
 
       default:
-        return new ParsedDicomFile(fields);
+        return new ParsedDicomFile(fields, GetDefaultDicomEncoding(), false /* be strict */);
     }
   }
 
--- a/Core/DicomNetworking/Internals/CommandDispatcher.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/Core/DicomNetworking/Internals/CommandDispatcher.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -94,6 +94,8 @@
 #include "../../Logging.h"
 
 #include <dcmtk/dcmnet/dcasccfg.h>      /* for class DcmAssociationConfiguration */
+#include <dcmtk/dcmdata/dcuid.h>        /* for variable dcmAllStorageSOPClassUIDs */
+
 #include <boost/lexical_cast.hpp>
 
 static OFBool    opt_rejectWithoutImplementationUID = OFFalse;
@@ -169,7 +171,7 @@
         }
       }
     }
-
+    
     if (accepted)
     {
       cond = ASC_acceptPresentationContext(
@@ -217,7 +219,7 @@
 static OFCondition acceptUnknownContextsWithPreferredTransferSyntaxes(
   T_ASC_Parameters * params,
   const char* transferSyntaxes[], int transferSyntaxCount,
-  T_ASC_SC_ROLE acceptedRole = ASC_SC_ROLE_DEFAULT)
+  T_ASC_SC_ROLE acceptedRole)
 {
   OFCondition cond = EC_Normal;
   /*
@@ -239,159 +241,6 @@
 {
   namespace Internals
   {
-    /**
-     * EXTRACT OF FILE "dcmdata/libsrc/dcuid.cc" FROM DCMTK 3.6.0
-     * (dcmAllStorageSOPClassUIDs).
-     *
-     * an array of const strings containing all known Storage SOP
-     * Classes that fit into the conventional
-     * PATIENT-STUDY-SERIES-INSTANCE information model,
-     * i.e. everything a Storage SCP might want to store in a PACS.
-     * Special cases such as hanging protocol storage or the Storage
-     * SOP Class are not included in this list.
-     *
-     * THIS LIST CONTAINS ALL STORAGE SOP CLASSES INCLUDING RETIRED
-     * ONES AND IS LARGER THAN 64 ENTRIES.
-     */
-
-    const char* orthancStorageSOPClassUIDs[] =
-    {
-      UID_AmbulatoryECGWaveformStorage,
-      UID_ArterialPulseWaveformStorage,
-      UID_AutorefractionMeasurementsStorage,
-      UID_BasicStructuredDisplayStorage,
-      UID_BasicTextSRStorage,
-      UID_BasicVoiceAudioWaveformStorage,
-      UID_BlendingSoftcopyPresentationStateStorage,
-#if DCMTK_VERSION_NUMBER >= 361
-      UID_BreastProjectionXRayImageStorageForProcessing,
-      UID_BreastProjectionXRayImageStorageForPresentation,
-#endif
-      UID_BreastTomosynthesisImageStorage,
-      UID_CardiacElectrophysiologyWaveformStorage,
-      UID_ChestCADSRStorage,
-      UID_ColonCADSRStorage,
-      UID_ColorSoftcopyPresentationStateStorage,
-      UID_ComprehensiveSRStorage,
-      UID_ComputedRadiographyImageStorage,
-      UID_CTImageStorage,
-      UID_DeformableSpatialRegistrationStorage,
-      UID_DigitalIntraOralXRayImageStorageForPresentation,
-      UID_DigitalIntraOralXRayImageStorageForProcessing,
-      UID_DigitalMammographyXRayImageStorageForPresentation,
-      UID_DigitalMammographyXRayImageStorageForProcessing,
-      UID_DigitalXRayImageStorageForPresentation,
-      UID_DigitalXRayImageStorageForProcessing,
-      UID_EncapsulatedCDAStorage,
-      UID_EncapsulatedPDFStorage,
-      UID_EnhancedCTImageStorage,
-      UID_EnhancedMRColorImageStorage,
-      UID_EnhancedMRImageStorage,
-      UID_EnhancedPETImageStorage,
-      UID_EnhancedSRStorage,
-      UID_EnhancedUSVolumeStorage,
-      UID_EnhancedXAImageStorage,
-      UID_EnhancedXRFImageStorage,
-      UID_GeneralAudioWaveformStorage,
-      UID_GeneralECGWaveformStorage,
-      UID_GenericImplantTemplateStorage,
-      UID_GrayscaleSoftcopyPresentationStateStorage,
-      UID_HemodynamicWaveformStorage,
-      UID_ImplantAssemblyTemplateStorage,
-      UID_ImplantationPlanSRDocumentStorage,
-      UID_ImplantTemplateGroupStorage,
-      UID_IntraocularLensCalculationsStorage,
-      UID_KeratometryMeasurementsStorage,
-      UID_KeyObjectSelectionDocumentStorage,
-      UID_LensometryMeasurementsStorage,
-      UID_MacularGridThicknessAndVolumeReportStorage,
-      UID_MammographyCADSRStorage,
-      UID_MRImageStorage,
-      UID_MRSpectroscopyStorage,
-      UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage,
-      UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage,
-      UID_MultiframeSingleBitSecondaryCaptureImageStorage,
-      UID_MultiframeTrueColorSecondaryCaptureImageStorage,
-      UID_NuclearMedicineImageStorage,
-      UID_OphthalmicAxialMeasurementsStorage,
-      UID_OphthalmicPhotography16BitImageStorage,
-      UID_OphthalmicPhotography8BitImageStorage,
-      UID_OphthalmicTomographyImageStorage,
-      UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage,
-      UID_PositronEmissionTomographyImageStorage,
-      UID_ProcedureLogStorage,
-      UID_PseudoColorSoftcopyPresentationStateStorage,
-      UID_RawDataStorage,
-      UID_RealWorldValueMappingStorage,
-      UID_RespiratoryWaveformStorage,
-      UID_RTBeamsTreatmentRecordStorage,
-      UID_RTBrachyTreatmentRecordStorage,
-      UID_RTDoseStorage,
-      UID_RTImageStorage,
-      UID_RTIonBeamsTreatmentRecordStorage,
-      UID_RTIonPlanStorage,
-      UID_RTPlanStorage,
-      UID_RTStructureSetStorage,
-      UID_RTTreatmentSummaryRecordStorage,
-      UID_SecondaryCaptureImageStorage,
-      UID_SegmentationStorage,
-      UID_SpatialFiducialsStorage,
-      UID_SpatialRegistrationStorage,
-      UID_SpectaclePrescriptionReportStorage,
-      UID_StereometricRelationshipStorage,
-      UID_SubjectiveRefractionMeasurementsStorage,
-      UID_SurfaceSegmentationStorage,
-      UID_TwelveLeadECGWaveformStorage,
-      UID_UltrasoundImageStorage,
-      UID_UltrasoundMultiframeImageStorage,
-      UID_VideoEndoscopicImageStorage,
-      UID_VideoMicroscopicImageStorage,
-      UID_VideoPhotographicImageStorage,
-      UID_VisualAcuityMeasurementsStorage,
-      UID_VLEndoscopicImageStorage,
-      UID_VLMicroscopicImageStorage,
-      UID_VLPhotographicImageStorage,
-      UID_VLSlideCoordinatesMicroscopicImageStorage,
-      UID_VLWholeSlideMicroscopyImageStorage,
-      UID_XAXRFGrayscaleSoftcopyPresentationStateStorage,
-      UID_XRay3DAngiographicImageStorage,
-      UID_XRay3DCraniofacialImageStorage,
-      UID_XRayAngiographicImageStorage,
-      UID_XRayRadiationDoseSRStorage,
-      UID_XRayRadiofluoroscopicImageStorage,
-      // retired
-      UID_RETIRED_HardcopyColorImageStorage,
-      UID_RETIRED_HardcopyGrayscaleImageStorage,
-      UID_RETIRED_NuclearMedicineImageStorage,
-      UID_RETIRED_StandaloneCurveStorage,
-      UID_RETIRED_StandaloneModalityLUTStorage,
-      UID_RETIRED_StandaloneOverlayStorage,
-      UID_RETIRED_StandalonePETCurveStorage,
-      UID_RETIRED_StandaloneVOILUTStorage,
-      UID_RETIRED_StoredPrintStorage,
-      UID_RETIRED_UltrasoundImageStorage,
-      UID_RETIRED_UltrasoundMultiframeImageStorage,
-      UID_RETIRED_VLImageStorage,
-#if DCMTK_VERSION_NUMBER >= 364
-      UID_RETIRED_VLMultiframeImageStorage,
-#else
-      UID_RETIRED_VLMultiFrameImageStorage,
-#endif
-      UID_RETIRED_XRayAngiographicBiPlaneImageStorage,
-      // draft
-      UID_DRAFT_SRAudioStorage,
-      UID_DRAFT_SRComprehensiveStorage,
-      UID_DRAFT_SRDetailStorage,
-      UID_DRAFT_SRTextStorage,
-      UID_DRAFT_WaveformStorage,
-      UID_DRAFT_RTBeamsDeliveryInstructionStorage,
-      NULL
-    };
-
-    const int orthancStorageSOPClassUIDsCount = (sizeof(orthancStorageSOPClassUIDs) / sizeof(const char*)) - 1;
-
-
-
     OFCondition AssociationCleanup(T_ASC_Association *assoc)
     {
       OFCondition cond = ASC_dropSCPAssociation(assoc);
@@ -588,7 +437,10 @@
       }
 
       /* accept the Verification SOP Class if presented */
-      cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), &transferSyntaxes[0], transferSyntaxes.size());
+      cond = ASC_acceptContextsWithPreferredTransferSyntaxes(
+        assoc->params,
+        &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(),
+        &transferSyntaxes[0], transferSyntaxes.size());
       if (cond.bad())
       {
         LOG(INFO) << cond.text();
@@ -596,8 +448,24 @@
         return NULL;
       }
 
-      /* the array of Storage SOP Class UIDs comes from dcuid.h */
-      cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, orthancStorageSOPClassUIDs, orthancStorageSOPClassUIDsCount, &transferSyntaxes[0], transferSyntaxes.size());
+      /* 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(count == numberOfDcmAllStorageSOPClassUIDs);
+#endif
+      
+      cond = ASC_acceptContextsWithPreferredTransferSyntaxes(
+        assoc->params,
+        dcmAllStorageSOPClassUIDs, count,
+        &transferSyntaxes[0], transferSyntaxes.size());
       if (cond.bad())
       {
         LOG(INFO) << cond.text();
@@ -613,7 +481,7 @@
          * to be a storage SOP class.
          **/
         cond = acceptUnknownContextsWithPreferredTransferSyntaxes(
-          assoc->params, &transferSyntaxes[0], transferSyntaxes.size());
+          assoc->params, &transferSyntaxes[0], transferSyntaxes.size(), ASC_SC_ROLE_DEFAULT);
         if (cond.bad())
         {
           LOG(INFO) << cond.text();
--- a/Core/DicomParsing/DicomModification.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/Core/DicomParsing/DicomModification.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -158,6 +158,13 @@
         newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Series);
         return Action_Replace;
       }
+      else if (parentTags.size() == 1 &&
+               parentTags[0] == DICOM_TAG_REFERENCED_SERIES_SEQUENCE &&
+               tag == DICOM_TAG_SERIES_INSTANCE_UID)
+      {
+        newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Series);
+        return Action_Replace;
+      }
       else
       {
         return Action_None;
--- a/Core/DicomParsing/ParsedDicomFile.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/Core/DicomParsing/ParsedDicomFile.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -1024,13 +1024,6 @@
   }
 
 
-  ParsedDicomFile::ParsedDicomFile(const DicomMap& map) : 
-    pimpl_(new PImpl)
-  {
-    CreateFromDicomMap(map, GetDefaultDicomEncoding(), false /* be strict by default */);
-  }
-
-
   ParsedDicomFile::ParsedDicomFile(const void* content, 
                                    size_t size) : pimpl_(new PImpl)
   {
--- a/Core/DicomParsing/ParsedDicomFile.h	Thu Apr 18 15:52:25 2019 +0200
+++ b/Core/DicomParsing/ParsedDicomFile.h	Thu Apr 18 15:52:56 2019 +0200
@@ -101,8 +101,6 @@
                     Encoding defaultEncoding,
                     bool permissive);
 
-    ParsedDicomFile(const DicomMap& map);
-
     ParsedDicomFile(const void* content,
                     size_t size);
 
--- a/NEWS	Thu Apr 18 15:52:25 2019 +0200
+++ b/NEWS	Thu Apr 18 15:52:56 2019 +0200
@@ -1,7 +1,15 @@
 Pending changes in the mainline
 ===============================
 
+
+Maintenance
+-----------
+
 * Size of the Orthanc static binaries are reduced by compressing ICU data
+* Anonymization: Preserve hierarchical relationships in (0008,1115) [] (0020,000e)
+* Fix issue #136 (C-FIND request fails when found DICOM file does not have certain tags)
+* Fix issue #137 (C-STORE fails for unknown SOP Class although server is configured to accept any)
+* Fix issue #138 (POST to modalities/{name} accepts invalid characters)
 
 
 Version 1.5.6 (2019-03-01)
--- a/OrthancServer/DicomInstanceToStore.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/OrthancServer/DicomInstanceToStore.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -179,7 +179,9 @@
           }
           else
           {
-            parsed_.TakeOwnership(new ParsedDicomFile(summary_.GetConstContent()));
+            parsed_.TakeOwnership(new ParsedDicomFile(summary_.GetConstContent(),
+                                                      GetDefaultDicomEncoding(),
+                                                      false /* be strict */));
           }                                
         }
 
--- a/OrthancServer/OrthancConfiguration.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/OrthancServer/OrthancConfiguration.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -759,6 +759,8 @@
   void OrthancConfiguration::UpdateModality(const std::string& symbolicName,
                                             const RemoteModalityParameters& modality)
   {
+    CheckAlphanumeric(symbolicName);
+    
     modalities_[symbolicName] = modality;
     SaveModalities();
   }
@@ -774,6 +776,8 @@
   void OrthancConfiguration::UpdatePeer(const std::string& symbolicName,
                                         const WebServiceParameters& peer)
   {
+    CheckAlphanumeric(symbolicName);
+    
     peer.CheckClientCertificate();
 
     peers_[symbolicName] = peer;
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -371,7 +371,7 @@
     }
     else
     {
-      ParsedDicomFile dicom(result);
+      ParsedDicomFile dicom(result, GetDefaultDicomEncoding(), true /* be permissive, cf. issue #136 */);
 
       for (std::list<DicomTag>::const_iterator tag = sequencesToReturn.begin();
            tag != sequencesToReturn.end(); ++tag)
--- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -442,10 +442,24 @@
     ServerContext& context = OrthancRestApi::GetContext(call);
     Json::Value request;
 
-    if (call.ParseJsonRequest(request) &&
-        request.type() == Json::objectValue &&
-        request.isMember(KEY_LEVEL) && request[KEY_LEVEL].type() == Json::stringValue &&
-        (!request.isMember(KEY_QUERY) || request[KEY_QUERY].type() == Json::objectValue))
+    if (!call.ParseJsonRequest(request) ||
+        request.type() != Json::objectValue)
+    {
+      throw OrthancException(ErrorCode_BadFileFormat, "Must provide a JSON object");
+    }
+    else if (!request.isMember(KEY_LEVEL) ||
+             request[KEY_LEVEL].type() != Json::stringValue)
+    {
+      throw OrthancException(ErrorCode_BadFileFormat,
+                             "The JSON body must contain field " + std::string(KEY_LEVEL));
+    }
+    else if (request.isMember(KEY_QUERY) &&
+             request[KEY_QUERY].type() != Json::objectValue)
+    {
+      throw OrthancException(ErrorCode_BadFileFormat,
+                             "The field " + std::string(KEY_QUERY) + " must contain a JSON object");
+    }
+    else
     {
       std::auto_ptr<QueryRetrieveHandler>  handler(new QueryRetrieveHandler(context));
 
@@ -958,7 +972,8 @@
         request[KEY_RESOURCES].type() != Json::arrayValue ||
         request[KEY_LEVEL].type() != Json::stringValue)
     {
-      throw OrthancException(ErrorCode_BadFileFormat);
+      throw OrthancException(ErrorCode_BadFileFormat, "Must provide a JSON body containing fields " +
+                             std::string(KEY_RESOURCES) + " and " + std::string(KEY_LEVEL));
     }
 
     ResourceType level = StringToResourceType(request[KEY_LEVEL].asCString());
@@ -1236,6 +1251,10 @@
       answers.ToJson(result, true);
       call.GetOutput().AnswerJson(result);
     }
+    else
+    {
+      throw OrthancException(ErrorCode_BadFileFormat, "Must provide a JSON object");
+    }
   }
 
 
--- a/OrthancServer/ServerContext.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/OrthancServer/ServerContext.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -245,7 +245,7 @@
       OrthancConfiguration::ReaderLock lock;
 
       queryRetrieveArchive_.reset(
-        new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("QueryRetrieveSize", 10)));
+        new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("QueryRetrieveSize", 100)));
       mediaArchive_.reset(
         new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("MediaArchiveSize", 1)));
       defaultLocalAet_ = lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC");
--- a/Resources/CMake/BoostConfiguration.cmake	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/CMake/BoostConfiguration.cmake	Thu Apr 18 15:52:56 2019 +0200
@@ -147,6 +147,13 @@
       add_definitions(-DBOOST_HAS_SCHED_YIELD=1)
     endif()
 
+    # Fix for error: "boost_1_69_0/boost/chrono/detail/inlined/mac/thread_clock.hpp:54:28: 
+    # error: use of undeclared identifier 'pthread_mach_thread_np'"
+    # https://github.com/envoyproxy/envoy/pull/1785
+    if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+      add_definitions(-D_DARWIN_C_SOURCE=1)
+    endif()
+
   elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
     list(APPEND BOOST_SOURCES
       ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_dll.cpp
--- a/Resources/CMake/LuaConfiguration.cmake	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/CMake/LuaConfiguration.cmake	Thu Apr 18 15:52:56 2019 +0200
@@ -101,9 +101,9 @@
   source_group(ThirdParty\\Lua REGULAR_EXPRESSION ${LUA_SOURCES_DIR}/.*)
 
 else()
-  include(FindLua51)
+  include(FindLua)
 
-  if (NOT LUA51_FOUND)
+  if (NOT LUA_FOUND)
     message(FATAL_ERROR "Please install the liblua-dev package")
   endif()
 
--- a/Resources/CMake/UuidConfiguration.cmake	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/CMake/UuidConfiguration.cmake	Thu Apr 18 15:52:56 2019 +0200
@@ -114,12 +114,18 @@
       message(FATAL_ERROR "Please install uuid-dev, e2fsprogs (OpenBSD) or e2fsprogs-libuuid (FreeBSD)")
     endif()
 
-    check_library_exists(uuid uuid_generate_random "" HAVE_UUID_LIB)
-    if (NOT HAVE_UUID_LIB)
+    find_library(LIBUUID uuid
+      PATHS
+      /usr/lib
+      /usr/local/lib
+      )
+
+    check_library_exists(${LIBUUID} uuid_generate_random "" HAVE_LIBUUID)
+    if (NOT HAVE_LIBUUID)
       message(FATAL_ERROR "Unable to find the uuid library")
     endif()
     
-    link_libraries(uuid)
+    link_libraries(${LIBUUID})
   endif()
 
 endif()
--- a/Resources/Configuration.json	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/Configuration.json	Thu Apr 18 15:52:56 2019 +0200
@@ -397,7 +397,7 @@
   // Maximum number of query/retrieve DICOM requests that are
   // maintained by Orthanc. The least recently used requests get
   // deleted as new requests are issued.
-  "QueryRetrieveSize" : 10,
+  "QueryRetrieveSize" : 100,
 
   // When handling a C-Find SCP request, setting this flag to "true"
   // will enable case-sensitive match for PN value representation
--- a/Resources/Samples/Python/AutoClassify.py	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/Samples/Python/AutoClassify.py	Thu Apr 18 15:52:56 2019 +0200
@@ -107,7 +107,7 @@
             })
 
     for change in r['Changes']:
-        # We are only interested interested in the arrival of new instances
+        # We are only interested in the arrival of new instances
         if change['ChangeType'] == 'NewInstance':
             try:
                 ClassifyInstance(change['ID'])
--- a/Resources/Samples/Python/ChangesLoop.py	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/Samples/Python/ChangesLoop.py	Thu Apr 18 15:52:56 2019 +0200
@@ -71,7 +71,7 @@
             })
 
     for change in r['Changes']:
-        # We are only interested interested in the arrival of new instances
+        # We are only interested in the arrival of new instances
         if change['ChangeType'] == 'NewInstance':
             # Call the callback function
             path = change['Path']
--- a/Resources/Samples/Python/HighPerformanceAutoRouting.py	Thu Apr 18 15:52:25 2019 +0200
+++ b/Resources/Samples/Python/HighPerformanceAutoRouting.py	Thu Apr 18 15:52:56 2019 +0200
@@ -70,7 +70,7 @@
             })
 
         for change in r['Changes']:
-            # We are only interested interested in the arrival of new instances
+            # We are only interested in the arrival of new instances
             if change['ChangeType'] == 'NewInstance':
                 queue.put(change['ID'])
 
--- a/TODO	Thu Apr 18 15:52:25 2019 +0200
+++ b/TODO	Thu Apr 18 15:52:56 2019 +0200
@@ -64,6 +64,8 @@
 Short-term
 ----------
 
+* Support "Retrieve AE Title" (0008,0054) in C-FIND:
+  https://groups.google.com/d/msg/orthanc-users/wPl0g5mqZco/5X1Z8tEzBgAJ
 * Support C-GET: 
   http://dclunie.blogspot.be/2016/05/to-c-move-is-human-to-c-get-divine.html
 * Check Big Endian transfer syntax in ParsedDicomFile::EmbedImage and
--- a/UnitTestsSources/FromDcmtkTests.cpp	Thu Apr 18 15:52:25 2019 +0200
+++ b/UnitTestsSources/FromDcmtkTests.cpp	Thu Apr 18 15:52:56 2019 +0200
@@ -1119,7 +1119,7 @@
 
   {
     DicomMap m;
-    ParsedDicomFile dicom(m);
+    ParsedDicomFile dicom(m, GetDefaultDicomEncoding(), false);
     ASSERT_EQ(1u, dicom.GetDcmtkObject().getDataset()->card());
     CheckEncoding(dicom, Encoding_Ascii);
   }
@@ -1134,7 +1134,7 @@
   {
     DicomMap m;
     m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 148", false);
-    ParsedDicomFile dicom(m);
+    ParsedDicomFile dicom(m, GetDefaultDicomEncoding(), false);
     ASSERT_EQ(1u, dicom.GetDcmtkObject().getDataset()->card());
     CheckEncoding(dicom, Encoding_Latin5);
   }