changeset 4377:4770ac7287ec

integration varian->mainline
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Dec 2020 11:42:48 +0100
parents 79ef2b6d8e76 (current diff) b002f9abe802 (diff)
children 91e5cbacb94d
files
diffstat 8 files changed, 77 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Dec 17 10:55:32 2020 +0100
+++ b/NEWS	Thu Dec 17 11:42:48 2020 +0100
@@ -8,6 +8,9 @@
 * New config option "MallocArenaMax" to control memory usage on GNU/Linux
 * Explicit error log if trying to load a 32bit (resp. 64bit) plugin into
   a 64bit (resp. 32bit) version of Orthanc
+* New configuration options (contributions by Varian):
+  - "DeidentifyLogs" to remove patient identification from the logs (C-GET, C-MOVE, C-FIND)
+  - "DeidentifyLogsDicomVersion" to specify the deidentification rules for the logs
 
 REST API
 --------
--- a/OrthancFramework/Sources/Enumerations.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancFramework/Sources/Enumerations.cpp	Thu Dec 17 11:42:48 2020 +0100
@@ -1608,7 +1608,8 @@
     }
     else
     {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
+      throw OrthancException(ErrorCode_ParameterOutOfRange,
+                             "Unknown specific version of the DICOM standard: " + version);
     }
   }
 
--- a/OrthancServer/Resources/Configuration.json	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Resources/Configuration.json	Thu Dec 17 11:42:48 2020 +0100
@@ -629,5 +629,16 @@
   // threads share "N" memory pools (known as "arenas"). Setting this
   // option to "0" doesn't call mallopt()", which was the behavior of
   // Orthanc <= 1.8.1.
-  "MallocArenaMax" : 5 
+  "MallocArenaMax" : 5,
+
+  // Deidentify/anonymize the contents of the logs (notably C-Find,
+  // C-Get, and C-Move queries submitted to Orthanc) according to
+  // Table E.1-1 of the DICOM standard (new in Orthanc 1.8.2)
+  "DeidentifyLogs" : true,
+
+  // If "DeidentifyLogs" is true, this sets the DICOM standard
+  // to follow for the deidentification/anonymization of the query
+  // contents. Possible values are those that are specified in the
+  // definition of Orthanc::StringToDicomVersion (new in Orthanc 1.8.2)
+  "DeidentifyLogsDicomVersion" : "2017c"
 }
--- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Thu Dec 17 11:42:48 2020 +0100
@@ -639,7 +639,7 @@
       {
         CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                           << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                          << " = " << query.GetElement(i).GetValue().GetContent();
+                          << " = " << context_.GetDeidentifiedContent(query.GetElement(i));
       }
     }
 
--- a/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Thu Dec 17 11:42:48 2020 +0100
@@ -507,7 +507,7 @@
         {
           CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                             << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                            << " = " << query.GetElement(i).GetValue().GetContent();
+                            << " = " << context_.GetDeidentifiedContent(query.GetElement(i));
         }
       }
     }
@@ -517,8 +517,14 @@
      **/
 
     const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL);
+    if (levelTmp == NULL ||
+        levelTmp->IsNull() ||
+        levelTmp->IsBinary())
+    {
+      throw OrthancException(ErrorCode_BadRequest,
+                             "C-GET request without the tag 0008,0052 (QueryRetrieveLevel)");
+    }
 
-    assert(levelTmp != NULL);
     ResourceType level = StringToResourceType(levelTmp->GetContent().c_str());      
 
 
--- a/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Thu Dec 17 11:42:48 2020 +0100
@@ -344,7 +344,7 @@
         {
           CLOG(INFO, DICOM) << "  (" << query.GetElement(i).GetTag().Format()
                             << ")  " << FromDcmtkBridge::GetTagName(query.GetElement(i))
-                            << " = " << query.GetElement(i).GetValue().GetContent();
+                            << " = " << context_.GetDeidentifiedContent(query.GetElement(i));
         }
       }
     }
--- a/OrthancServer/Sources/ServerContext.cpp	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Thu Dec 17 11:42:48 2020 +0100
@@ -35,7 +35,9 @@
 #include "ServerContext.h"
 
 #include "../../OrthancFramework/Sources/Cache/SharedArchive.h"
+#include "../../OrthancFramework/Sources/DicomFormat/DicomElement.h"
 #include "../../OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h"
+#include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
 #include "../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h"
 #include "../../OrthancFramework/Sources/FileStorage/StorageAccessor.h"
@@ -267,7 +269,8 @@
     isExecuteLuaEnabled_(false),
     overwriteInstances_(false),
     dcmtkTranscoder_(new DcmtkTranscoder),
-    isIngestTranscoding_(false)
+    isIngestTranscoding_(false),
+    deidentifyLogs_(false)
   {
     try
     {
@@ -318,6 +321,24 @@
           isIngestTranscoding_ = false;
           LOG(INFO) << "Automated transcoding of incoming DICOM instances is disabled";
         }
+
+        if (lock.GetConfiguration().GetBooleanParameter("DeidentifyLogs", true))
+        {
+          deidentifyLogs_ = true;
+          CLOG(INFO, DICOM) << "Deidentification of log contents (notably for DIMSE queries) is enabled";
+
+          DicomVersion version = StringToDicomVersion(
+              lock.GetConfiguration().GetStringParameter("DeidentifyLogsDicomVersion", "2017c"));
+          CLOG(INFO, DICOM) << "Version of DICOM standard used for deidentification is "
+                            << EnumerationToString(version);
+
+          logsDeidentifierRules_.SetupAnonymization(version);
+        }
+        else
+        {
+          deidentifyLogs_ = false;
+          CLOG(INFO, DICOM) << "Deidentification of log contents (notably for DIMSE queries) is disabled";
+        }
       }
 
       jobsEngine_.SetThreadSleep(unitTesting ? 20 : 200);
@@ -1627,4 +1648,22 @@
       return false;
     }
   }
+
+  const std::string& ServerContext::GetDeidentifiedContent(const DicomElement &element) const
+  {
+    static const std::string redactedContent = "*** POTENTIAL PHI ***";
+
+    const DicomTag& tag = element.GetTag();
+    if (deidentifyLogs_ && (
+          logsDeidentifierRules_.IsCleared(tag) ||
+          logsDeidentifierRules_.IsRemoved(tag) ||
+          logsDeidentifierRules_.IsReplaced(tag)))
+    {
+      return redactedContent;
+    }
+    else
+    {
+      return element.GetValue().GetContent();
+    }
+  }
 }
--- a/OrthancServer/Sources/ServerContext.h	Thu Dec 17 10:55:32 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Thu Dec 17 11:42:48 2020 +0100
@@ -40,6 +40,8 @@
 #include "ServerJobs/IStorageCommitmentFactory.h"
 
 #include "../../OrthancFramework/Sources/Cache/MemoryCache.h"
+#include "../../OrthancFramework/Sources/DicomFormat/DicomElement.h"
+#include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
 #include "../../OrthancFramework/Sources/DicomParsing/IDicomTranscoder.h"
 
 
@@ -245,6 +247,12 @@
                        size_t since,
                        size_t limit);
 
+    // This DicomModification object is intended to be used as a
+    // "rules engine" when de-identifying logs for C-Find, C-Get, and
+    // C-Move queries (new in Orthanc 1.8.2)
+    DicomModification logsDeidentifierRules_;
+    bool              deidentifyLogs_;
+
   public:
     class DicomCacheLocker : public boost::noncopyable
     {
@@ -500,5 +508,7 @@
     {
       return transcodeDicomProtocol_;
     }
+
+    const std::string& GetDeidentifiedContent(const DicomElement& element) const;
   };
 }