diff OrthancFramework/Sources/DicomParsing/DicomModification.cpp @ 4737:979ae3ea3381

DANGEROUS commit: Anonymization is now also applied to nested sequences
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 Jul 2021 08:12:26 +0200
parents b51c08bd5c38
children 51ec061516c9
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Mon Jul 05 17:50:58 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Tue Jul 06 08:12:26 2021 +0200
@@ -44,6 +44,16 @@
 
 namespace Orthanc
 {
+  namespace
+  {
+    enum TagOperation
+    {
+      TagOperation_Keep,
+      TagOperation_Remove
+    };
+  }
+
+  
   DicomModification::DicomTagRange::DicomTagRange(uint16_t groupFrom,
                                                   uint16_t groupTo,
                                                   uint16_t elementFrom,
@@ -76,7 +86,57 @@
       return (that_.IsCleared(tag) ||
               that_.IsRemoved(tag) ||
               that_.IsReplaced(tag));
-    }                         
+    }
+
+    bool IsKeptSequence(const std::vector<DicomTag>& parentTags,
+                        const std::vector<size_t>& parentIndexes,
+                        const DicomTag& tag)
+    {
+      for (DicomModification::ListOfPaths::const_iterator
+             it = that_.keepSequences_.begin(); it != that_.keepSequences_.end(); ++it)
+      {
+        if (DicomPath::IsMatch(*it, parentTags, parentIndexes, tag))
+        {
+          return true;
+        }
+      }
+
+      return false;
+    }
+
+    Action GetDefaultAction(const std::vector<DicomTag>& parentTags,
+                            const std::vector<size_t>& parentIndexes,
+                            const DicomTag& tag)
+    {
+      if (parentTags.empty() ||
+          !that_.isAnonymization_)
+      {
+        // Don't interfere with first-level tags or with modification
+        return Action_None;
+      }
+      else if (IsKeptSequence(parentTags, parentIndexes, tag))
+      {
+        return Action_None;
+      }
+      else if (that_.ArePrivateTagsRemoved() &&
+               tag.IsPrivate())
+      {
+        // New in Orthanc 1.9.5
+        // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ
+        return Action_Remove;
+      }
+      else if (that_.IsCleared(tag) ||
+               that_.IsRemoved(tag))
+      {
+        // New in Orthanc 1.9.5
+        // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ
+        return Action_Remove;
+      }
+      else
+      {
+        return Action_None;
+      }
+    }
 
   public:
     explicit RelationshipsVisitor(DicomModification& that) :
@@ -89,14 +149,15 @@
                                      const DicomTag& tag,
                                      ValueRepresentation vr) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
-    virtual Action VisitEmptySequence(const std::vector<DicomTag>& parentTags,
-                                      const std::vector<size_t>& parentIndexes,
-                                      const DicomTag& tag) ORTHANC_OVERRIDE
+    virtual Action VisitSequence(const std::vector<DicomTag>& parentTags,
+                                 const std::vector<size_t>& parentIndexes,
+                                 const DicomTag& tag,
+                                 size_t countItems) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
     virtual Action VisitBinary(const std::vector<DicomTag>& parentTags,
@@ -106,7 +167,7 @@
                                const void* data,
                                size_t size) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
     virtual Action VisitIntegers(const std::vector<DicomTag>& parentTags,
@@ -115,7 +176,7 @@
                                  ValueRepresentation vr,
                                  const std::vector<int64_t>& values) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
     virtual Action VisitDoubles(const std::vector<DicomTag>& parentTags,
@@ -124,7 +185,7 @@
                                 ValueRepresentation vr,
                                 const std::vector<double>& value) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
     virtual Action VisitAttributes(const std::vector<DicomTag>& parentTags,
@@ -132,7 +193,7 @@
                                    const DicomTag& tag,
                                    const std::vector<DicomTag>& value) ORTHANC_OVERRIDE
     {
-      return Action_None;
+      return GetDefaultAction(parentTags, parentIndexes, tag);
     }
 
     virtual Action VisitString(std::string& newValue,
@@ -187,18 +248,30 @@
       {
         // We are within a sequence
 
-        if (!that_.keepSequences_.empty())
+        if (IsKeptSequence(parentTags, parentIndexes, tag))
         {
           // New in Orthanc 1.9.4 - Solves issue LSD-629
-          DicomPath path(parentTags, parentIndexes, tag);
-          
-          for (ListOfPaths::const_iterator it = that_.keepSequences_.begin();
-               it != that_.keepSequences_.end(); ++it)
+          return Action_None;
+        }
+
+        if (that_.isAnonymization_)
+        {
+          // New in Orthanc 1.9.5, similar to "GetDefaultAction()"
+          // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ
+          if (that_.ArePrivateTagsRemoved() &&
+              tag.IsPrivate())
           {
-            if (DicomPath::IsMatch(*it, path))
-            {
-              return Action_None;
-            }
+            return Action_Remove;
+          }
+          else if (that_.IsRemoved(tag))
+          {
+            return Action_Remove;
+          }
+          else if (that_.IsCleared(tag))
+          {
+            // This is different from "GetDefaultAction()", because we know how to clear string tags
+            newValue.clear();
+            return Action_Replace;
           }
         }
 
@@ -1106,7 +1179,7 @@
 
   static void ParseListOfTags(DicomModification& target,
                               const Json::Value& query,
-                              DicomModification::TagOperation operation,
+                              TagOperation operation,
                               bool force)
   {
     if (!query.isArray())
@@ -1131,18 +1204,18 @@
       {
         throw OrthancException(ErrorCode_BadRequest,
                                "Marking tag \"" + name + "\" as to be " +
-                               (operation == DicomModification::TagOperation_Keep ? "kept" : "removed") +
+                               (operation == TagOperation_Keep ? "kept" : "removed") +
                                " requires the \"Force\" option to be set to true");
       }
 
       switch (operation)
       {
-        case DicomModification::TagOperation_Keep:
+        case TagOperation_Keep:
           target.Keep(path);
           LOG(TRACE) << "Keep: " << name << " = " << path.Format();
           break;
 
-        case DicomModification::TagOperation_Remove:
+        case TagOperation_Remove:
           target.Remove(path);
           LOG(TRACE) << "Remove: " << name << " = " << path.Format();
           break;