# HG changeset patch # User Alain Mazy # Date 1671476421 -3600 # Node ID ede035d48b8e29e9ab52554a5da20e88f558453e # Parent 6f41d47ef9946d73d34aeb14aa4fcb401867c0f8# Parent 8638522eeda14f6a8270f216518d703019f1121c merge diff -r 6f41d47ef994 -r ede035d48b8e NEWS --- a/NEWS Mon Dec 19 16:31:12 2022 +0100 +++ b/NEWS Mon Dec 19 20:00:21 2022 +0100 @@ -14,7 +14,7 @@ REST API -------- -* Loosen the sanity checks for DICOM modifications: +* Loosen the sanity checks for DICOM modifications, if "Force" option is given: - allow modification of PatientID at study level - allow modification of PatientID, StudyInstanceUID at series level - allow modification of PatientID, StudyInstanceUID, SeriesInstanceUID at instance level @@ -29,12 +29,6 @@ * Tolerance for "image/jpg" MIME type instead of "image/jpeg" in /tools/create-dicom * /system: added MaximumStorageMode and MaximumStorageSize -OrthancFramework (C++) ----------------------- - -* DicomModification::SetAllowManualIdentifiers() has been removed since it was always true -> code cleanup. - - Common plugins code (C++) ------------------------- diff -r 6f41d47ef994 -r ede035d48b8e OrthancFramework/Resources/CMake/LibJpegConfiguration.cmake --- a/OrthancFramework/Resources/CMake/LibJpegConfiguration.cmake Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancFramework/Resources/CMake/LibJpegConfiguration.cmake Mon Dec 19 20:00:21 2022 +0100 @@ -107,7 +107,7 @@ else() include(FindJPEG) - if (NOT ${JPEG_FOUND}) + if (NOT JPEG_FOUND) message(FATAL_ERROR "Unable to find libjpeg") endif() diff -r 6f41d47ef994 -r ede035d48b8e OrthancFramework/Resources/CMake/LibPngConfiguration.cmake --- a/OrthancFramework/Resources/CMake/LibPngConfiguration.cmake Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancFramework/Resources/CMake/LibPngConfiguration.cmake Mon Dec 19 20:00:21 2022 +0100 @@ -71,7 +71,7 @@ else() include(FindPNG) - if (NOT ${PNG_FOUND}) + if (NOT PNG_FOUND) message(FATAL_ERROR "Unable to find libpng") endif() diff -r 6f41d47ef994 -r ede035d48b8e OrthancFramework/Resources/CMake/OpenSslConfiguration.cmake --- a/OrthancFramework/Resources/CMake/OpenSslConfiguration.cmake Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancFramework/Resources/CMake/OpenSslConfiguration.cmake Mon Dec 19 20:00:21 2022 +0100 @@ -59,7 +59,7 @@ else() include(FindOpenSSL) - if (NOT ${OPENSSL_FOUND}) + if (NOT OPENSSL_FOUND) message(FATAL_ERROR "Unable to find OpenSSL") endif() diff -r 6f41d47ef994 -r ede035d48b8e OrthancFramework/Sources/DicomParsing/DicomModification.cpp --- a/OrthancFramework/Sources/DicomParsing/DicomModification.cpp Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DicomModification.cpp Mon Dec 19 20:00:21 2022 +0100 @@ -522,6 +522,7 @@ DicomModification::DicomModification() : removePrivateTags_(false), level_(ResourceType_Instance), + allowManualIdentifiers_(true), keepStudyInstanceUid_(false), keepSeriesInstanceUid_(false), keepSopInstanceUid_(false), @@ -921,6 +922,56 @@ } + // Sanity checks at the patient level + if (!allowManualIdentifiers_) + { + if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a patient, the StudyInstanceUID cannot be manually modified"); + } + + if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a patient, the SeriesInstanceUID cannot be manually modified"); + } + + if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a patient, the SopInstanceUID cannot be manually modified"); + } + } + + + // Sanity checks at the study level + if (!allowManualIdentifiers_) + { + if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a study, the SeriesInstanceUID cannot be manually modified"); + } + + if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a study, the SopInstanceUID cannot be manually modified"); + } + } + + + // Sanity checks at the series level + if (!allowManualIdentifiers_) + { + if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a series, the SopInstanceUID cannot be manually modified"); + } + } + // (0) Create a summary of the source file, if a custom generator // is provided @@ -1061,6 +1112,17 @@ } } + void DicomModification::SetAllowManualIdentifiers(bool check) + { + allowManualIdentifiers_ = check; + } + + bool DicomModification::AreAllowManualIdentifiers() const + { + return allowManualIdentifiers_; + } + + static bool IsDatabaseKey(const DicomTag& tag) { return (tag == DICOM_TAG_PATIENT_ID || @@ -1213,6 +1275,62 @@ { privateCreator_ = SerializationToolbox::ReadString(request, "PrivateCreator"); } + + if (!force) + { + /** + * Sanity checks about the manual replacement of DICOM + * identifiers. Those checks were part of + * "DicomModification::Apply()" in Orthanc <= 1.11.2, and + * couldn't be disabled even if using the "Force" flag. Check + * out: + * https://groups.google.com/g/orthanc-users/c/xMUUZAnBa5g/m/WCEu-U2NBQAJ + **/ + bool isReplacedPatientId = (IsReplaced(DICOM_TAG_PATIENT_ID) || + uids_.find(DICOM_TAG_PATIENT_ID) != uids_.end()); + + if (level_ == ResourceType_Patient && !isReplacedPatientId) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a patient, her PatientID is required to be modified."); + } + + if (level_ == ResourceType_Study && isReplacedPatientId) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a study, the parent PatientID cannot be manually modified"); + } + + if (level_ == ResourceType_Series && isReplacedPatientId) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a series, the parent PatientID cannot be manually modified"); + } + + if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying a series, the parent StudyInstanceUID cannot be manually modified"); + } + + if (level_ == ResourceType_Instance && isReplacedPatientId) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying an instance, the parent PatientID cannot be manually modified"); + } + + if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying an instance, the parent StudyInstanceUID cannot be manually modified"); + } + + if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) + { + throw OrthancException(ErrorCode_BadRequest, + "When modifying an instance, the parent SeriesInstanceUID cannot be manually modified"); + } + } } @@ -1282,6 +1400,7 @@ static const char* REMOVE_PRIVATE_TAGS = "RemovePrivateTags"; static const char* LEVEL = "Level"; + static const char* ALLOW_MANUAL_IDENTIFIERS = "AllowManualIdentifiers"; static const char* KEEP_STUDY_INSTANCE_UID = "KeepStudyInstanceUID"; static const char* KEEP_SERIES_INSTANCE_UID = "KeepSeriesInstanceUID"; static const char* KEEP_SOP_INSTANCE_UID = "KeepSOPInstanceUID"; @@ -1313,6 +1432,7 @@ value = Json::objectValue; value[REMOVE_PRIVATE_TAGS] = removePrivateTags_; value[LEVEL] = EnumerationToString(level_); + value[ALLOW_MANUAL_IDENTIFIERS] = allowManualIdentifiers_; value[KEEP_STUDY_INSTANCE_UID] = keepStudyInstanceUid_; value[KEEP_SERIES_INSTANCE_UID] = keepSeriesInstanceUid_; value[KEEP_SOP_INSTANCE_UID] = keepSopInstanceUid_; @@ -1457,6 +1577,7 @@ { removePrivateTags_ = SerializationToolbox::ReadBoolean(serialized, REMOVE_PRIVATE_TAGS); level_ = StringToResourceType(SerializationToolbox::ReadString(serialized, LEVEL).c_str()); + allowManualIdentifiers_ = SerializationToolbox::ReadBoolean(serialized, ALLOW_MANUAL_IDENTIFIERS); keepStudyInstanceUid_ = SerializationToolbox::ReadBoolean(serialized, KEEP_STUDY_INSTANCE_UID); keepSeriesInstanceUid_ = SerializationToolbox::ReadBoolean(serialized, KEEP_SERIES_INSTANCE_UID); updateReferencedRelationships_ = SerializationToolbox::ReadBoolean diff -r 6f41d47ef994 -r ede035d48b8e OrthancFramework/Sources/DicomParsing/DicomModification.h --- a/OrthancFramework/Sources/DicomParsing/DicomModification.h Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DicomModification.h Mon Dec 19 20:00:21 2022 +0100 @@ -133,6 +133,7 @@ ResourceType level_; UidMap uidMap_; SetOfTags privateTagsToKeep_; + bool allowManualIdentifiers_; bool keepStudyInstanceUid_; bool keepSeriesInstanceUid_; bool keepSopInstanceUid_; @@ -223,6 +224,10 @@ void Apply(ParsedDicomFile& toModify); + void SetAllowManualIdentifiers(bool check); + + bool AreAllowManualIdentifiers() const; + void ParseModifyRequest(const Json::Value& request); // "patientNameOverridden" is set to "true" iff. the PatientName diff -r 6f41d47ef994 -r ede035d48b8e OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp Mon Dec 19 20:00:21 2022 +0100 @@ -269,6 +269,7 @@ } DicomModification modification; + modification.SetAllowManualIdentifiers(true); Json::Value request; ParseModifyRequest(request, modification, call); @@ -313,6 +314,7 @@ } DicomModification modification; + modification.SetAllowManualIdentifiers(true); Json::Value request; ParseAnonymizationRequest(request, modification, call); diff -r 6f41d47ef994 -r ede035d48b8e OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp --- a/OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp Mon Dec 19 16:31:12 2022 +0100 +++ b/OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp Mon Dec 19 20:00:21 2022 +0100 @@ -43,6 +43,8 @@ throw OrthancException(ErrorCode_NullPointer); } + modification_->SetAllowManualIdentifiers(true); + if (modification_->IsReplaced(DICOM_TAG_PATIENT_ID)) { modification_->SetLevel(ResourceType_Patient);