changeset 3679:6358923d3ced

C-FIND: forbid wildcard matching on some VRs, ignore main tags below the queried level
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 Feb 2020 20:06:19 +0100
parents 26c6d47467a9
children 453c0ece560a
files OrthancServer/Search/DatabaseLookup.cpp OrthancServer/ServerContext.cpp
diffstat 2 files changed, 63 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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));
--- 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<std::string> 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;
       }