# HG changeset patch # User Sebastien Jodogne # Date 1582225579 -3600 # Node ID 6358923d3ced5a646fe0f3225d612d2747f65f14 # Parent 26c6d47467a9cec20da86ea1b480c894465a7b5e C-FIND: forbid wildcard matching on some VRs, ignore main tags below the queried level diff -r 26c6d47467a9 -r 6358923d3ced OrthancServer/Search/DatabaseLookup.cpp --- a/OrthancServer/Search/DatabaseLookup.cpp Thu Feb 20 20:00:02 2020 +0100 +++ b/OrthancServer/Search/DatabaseLookup.cpp Thu Feb 20 20:06:19 2020 +0100 @@ -198,8 +198,26 @@ AddConstraint(constraint.release()); } - else if (dicomQuery.find('*') != std::string::npos || - dicomQuery.find('?') != std::string::npos) + else if ( + /** + * New test in Orthanc 1.6.0: Wild card matching is only allowed + * for a subset of value representations: AE, CS, LO, LT, PN, + * SH, ST, UC, UR, UT. + * http://dicom.nema.org/medical/dicom/2019e/output/chtml/part04/sect_C.2.2.2.4.html + **/ + (vr == ValueRepresentation_ApplicationEntity || // AE + vr == ValueRepresentation_CodeString || // CS + vr == ValueRepresentation_LongString || // LO + vr == ValueRepresentation_LongText || // LT + vr == ValueRepresentation_PersonName || // PN + vr == ValueRepresentation_ShortString || // SH + vr == ValueRepresentation_ShortText || // ST + vr == ValueRepresentation_UnlimitedCharacters || // UC + vr == ValueRepresentation_UniversalResource || // UR + vr == ValueRepresentation_UnlimitedText // UT + ) && + (dicomQuery.find('*') != std::string::npos || + dicomQuery.find('?') != std::string::npos)) { AddConstraint(new DicomTagConstraint (tag, ConstraintType_Wildcard, dicomQuery, caseSensitive, mandatoryTag)); diff -r 26c6d47467a9 -r 6358923d3ced OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Thu Feb 20 20:00:02 2020 +0100 +++ b/OrthancServer/ServerContext.cpp Thu Feb 20 20:06:19 2020 +0100 @@ -801,7 +801,8 @@ size_t since, size_t limit) { - unsigned int databaseLimit = (queryLevel == ResourceType_Instance ? limitFindInstances_ : limitFindResults_); + unsigned int databaseLimit = (queryLevel == ResourceType_Instance ? + limitFindInstances_ : limitFindResults_); std::vector resources, instances; @@ -815,6 +816,11 @@ LOG(INFO) << "Number of candidate resources after fast DB filtering on main DICOM tags: " << resources.size(); + /** + * "resources" contains the Orthanc ID of the resource at level + * "queryLevel", "instances" contains one the Orthanc ID of one + * sample instance from this resource. + **/ assert(resources.size() == instances.size()); size_t countResults = 0; @@ -839,12 +845,47 @@ // Case (1): The main DICOM tags, as stored in the database, // are sufficient to look for match - if (!GetIndex().GetAllMainDicomTags(dicom, instances[i])) + DicomMap tmp; + if (!GetIndex().GetAllMainDicomTags(tmp, instances[i])) { // The instance has been removed during the execution of the // lookup, ignore it continue; } + +#if 1 + // New in Orthanc 1.6.0: Only keep the main DICOM tags at the + // level of interest for the query + switch (queryLevel) + { + // WARNING: Don't reorder cases below, and don't add "break" + case ResourceType_Instance: + dicom.MergeMainDicomTags(tmp, ResourceType_Instance); + + case ResourceType_Series: + dicom.MergeMainDicomTags(tmp, ResourceType_Series); + + case ResourceType_Study: + dicom.MergeMainDicomTags(tmp, ResourceType_Study); + + case ResourceType_Patient: + dicom.MergeMainDicomTags(tmp, ResourceType_Patient); + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + // Special case of the "Modality" at the study level, in order + // to deal with C-FIND on "ModalitiesInStudy" (0008,0061). + // Check out integration test "test_rest_modalities_in_study". + if (queryLevel == ResourceType_Study) + { + dicom.CopyTagIfExists(tmp, DICOM_TAG_MODALITY); + } +#else + dicom.Assign(tmp); // This emulates Orthanc <= 1.5.8 +#endif hasOnlyMainDicomTags = true; }