changeset 1888:512b6e76f531

Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-Find requests
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 11 Dec 2015 16:39:51 +0100
parents 5e0a25642056
children 444f0bdaba01
files NEWS OrthancServer/OrthancFindRequestHandler.cpp OrthancServer/OrthancFindRequestHandler.h
diffstat 3 files changed, 90 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Dec 11 15:59:05 2015 +0100
+++ b/NEWS	Fri Dec 11 16:39:51 2015 +0100
@@ -1,6 +1,7 @@
 Pending changes in the mainline
 ===============================
 
+* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-Find requests
 * Fix of DICOMDIR generation with DCMTK 3.6.1, support of encodings
 * New function in plugin SDK: "OrthancPluginSendMultipartItem2()"
 * Fix range search if the lower or upper limit is absent
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Fri Dec 11 15:59:05 2015 +0100
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Fri Dec 11 16:39:51 2015 +0100
@@ -34,6 +34,7 @@
 #include "OrthancFindRequestHandler.h"
 
 #include "../Core/DicomFormat/DicomArray.h"
+#include "../Core/Lua/LuaFunctionCall.h"
 #include "../Core/Logging.h"
 #include "FromDcmtkBridge.h"
 #include "OrthancInitialization.h"
@@ -159,6 +160,72 @@
   }
 
 
+  bool OrthancFindRequestHandler::ApplyLuaFilter(DicomMap& target,
+                                                 const DicomMap& source,
+                                                 const std::string& remoteIp,
+                                                 const std::string& remoteAet,
+                                                 const std::string& calledAet)
+  {
+    static const char* NAME = "IncomingFindRequestFilter";
+
+    Json::Value output;
+
+    {
+      LuaScripting::Locker locker(context_.GetLua());
+      
+      if (!locker.GetLua().IsExistingFunction(NAME))
+      {
+        return false;
+      }
+
+      Json::Value tmp = Json::objectValue;
+      DicomArray a(source);
+
+      for (size_t i = 0; i < a.GetSize(); i++)
+      {
+        const DicomValue& v = a.GetElement(i).GetValue();
+        std::string s = (v.IsNull() || v.IsBinary()) ? "" : v.GetContent();
+        tmp[a.GetElement(i).GetTag().Format()] = s;
+      }
+
+      Json::Value origin = Json::objectValue;
+      origin["RemoteIp"] = remoteIp;
+      origin["RemoteAet"] = remoteAet;
+      origin["CalledAet"] = calledAet;
+
+      LuaFunctionCall call(locker.GetLua(), NAME);
+      call.PushJson(tmp);
+      call.PushJson(origin);
+
+      call.ExecuteToJson(output, true);
+    }
+
+    // The Lua context is released at this point
+
+    if (output.type() != Json::objectValue)
+    {
+      LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table";
+      throw OrthancException(ErrorCode_LuaBadOutput);
+    }
+
+    Json::Value::Members members = output.getMemberNames();
+
+    for (size_t i = 0; i < members.size(); i++)
+    {
+      if (output[members[i]].type() != Json::stringValue)
+      {
+        LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table mapping names of DICOM tags to strings";
+        throw OrthancException(ErrorCode_LuaBadOutput);
+      }
+
+      DicomTag tag(FromDcmtkBridge::ParseTag(members[i]));
+      target.SetValue(tag, output[members[i]].asString());
+    }
+
+    return true;
+  }
+
+
   void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers,
                                          const DicomMap& input,
                                          const std::list<DicomTag>& sequencesToReturn,
@@ -181,10 +248,24 @@
 
 
     /**
+     * Possibly apply the user-supplied Lua filter.
+     **/
+
+    DicomMap lua;
+    const DicomMap* filteredInput = &input;
+
+    if (ApplyLuaFilter(lua, input, remoteIp, remoteAet, calledAet))
+    {
+      filteredInput = &lua;
+    }
+
+
+    /**
      * Retrieve the query level.
      **/
 
-    const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL);
+    assert(filteredInput != NULL);
+    const DicomValue* levelTmp = filteredInput->TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL);
     if (levelTmp == NULL ||
         levelTmp->IsNull() ||
         levelTmp->IsBinary())
@@ -204,7 +285,7 @@
     }
 
 
-    DicomArray query(input);
+    DicomArray query(*filteredInput);
     LOG(INFO) << "DICOM C-Find request at level: " << EnumerationToString(level);
 
     for (size_t i = 0; i < query.GetSize(); i++)
--- a/OrthancServer/OrthancFindRequestHandler.h	Fri Dec 11 15:59:05 2015 +0100
+++ b/OrthancServer/OrthancFindRequestHandler.h	Fri Dec 11 16:39:51 2015 +0100
@@ -52,6 +52,12 @@
                         const DicomTag& tag,
                         ModalityManufacturer manufacturer);
 
+    bool ApplyLuaFilter(DicomMap& target,
+                        const DicomMap& source,
+                        const std::string& remoteIp,
+                        const std::string& remoteAet,
+                        const std::string& calledAet);
+
   public:
     OrthancFindRequestHandler(ServerContext& context) :
       context_(context),