comparison OrthancServer/OrthancFindRequestHandler.cpp @ 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 4e7c318a3f69
children d7f63122c7f3
comparison
equal deleted inserted replaced
1887:5e0a25642056 1888:512b6e76f531
32 32
33 #include "PrecompiledHeadersServer.h" 33 #include "PrecompiledHeadersServer.h"
34 #include "OrthancFindRequestHandler.h" 34 #include "OrthancFindRequestHandler.h"
35 35
36 #include "../Core/DicomFormat/DicomArray.h" 36 #include "../Core/DicomFormat/DicomArray.h"
37 #include "../Core/Lua/LuaFunctionCall.h"
37 #include "../Core/Logging.h" 38 #include "../Core/Logging.h"
38 #include "FromDcmtkBridge.h" 39 #include "FromDcmtkBridge.h"
39 #include "OrthancInitialization.h" 40 #include "OrthancInitialization.h"
40 #include "Search/LookupResource.h" 41 #include "Search/LookupResource.h"
41 #include "ServerToolbox.h" 42 #include "ServerToolbox.h"
157 158
158 return true; 159 return true;
159 } 160 }
160 161
161 162
163 bool OrthancFindRequestHandler::ApplyLuaFilter(DicomMap& target,
164 const DicomMap& source,
165 const std::string& remoteIp,
166 const std::string& remoteAet,
167 const std::string& calledAet)
168 {
169 static const char* NAME = "IncomingFindRequestFilter";
170
171 Json::Value output;
172
173 {
174 LuaScripting::Locker locker(context_.GetLua());
175
176 if (!locker.GetLua().IsExistingFunction(NAME))
177 {
178 return false;
179 }
180
181 Json::Value tmp = Json::objectValue;
182 DicomArray a(source);
183
184 for (size_t i = 0; i < a.GetSize(); i++)
185 {
186 const DicomValue& v = a.GetElement(i).GetValue();
187 std::string s = (v.IsNull() || v.IsBinary()) ? "" : v.GetContent();
188 tmp[a.GetElement(i).GetTag().Format()] = s;
189 }
190
191 Json::Value origin = Json::objectValue;
192 origin["RemoteIp"] = remoteIp;
193 origin["RemoteAet"] = remoteAet;
194 origin["CalledAet"] = calledAet;
195
196 LuaFunctionCall call(locker.GetLua(), NAME);
197 call.PushJson(tmp);
198 call.PushJson(origin);
199
200 call.ExecuteToJson(output, true);
201 }
202
203 // The Lua context is released at this point
204
205 if (output.type() != Json::objectValue)
206 {
207 LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table";
208 throw OrthancException(ErrorCode_LuaBadOutput);
209 }
210
211 Json::Value::Members members = output.getMemberNames();
212
213 for (size_t i = 0; i < members.size(); i++)
214 {
215 if (output[members[i]].type() != Json::stringValue)
216 {
217 LOG(ERROR) << "Lua: IncomingFindRequestFilter must return a table mapping names of DICOM tags to strings";
218 throw OrthancException(ErrorCode_LuaBadOutput);
219 }
220
221 DicomTag tag(FromDcmtkBridge::ParseTag(members[i]));
222 target.SetValue(tag, output[members[i]].asString());
223 }
224
225 return true;
226 }
227
228
162 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, 229 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers,
163 const DicomMap& input, 230 const DicomMap& input,
164 const std::list<DicomTag>& sequencesToReturn, 231 const std::list<DicomTag>& sequencesToReturn,
165 const std::string& remoteIp, 232 const std::string& remoteIp,
166 const std::string& remoteAet, 233 const std::string& remoteAet,
179 246
180 bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false); 247 bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false);
181 248
182 249
183 /** 250 /**
251 * Possibly apply the user-supplied Lua filter.
252 **/
253
254 DicomMap lua;
255 const DicomMap* filteredInput = &input;
256
257 if (ApplyLuaFilter(lua, input, remoteIp, remoteAet, calledAet))
258 {
259 filteredInput = &lua;
260 }
261
262
263 /**
184 * Retrieve the query level. 264 * Retrieve the query level.
185 **/ 265 **/
186 266
187 const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL); 267 assert(filteredInput != NULL);
268 const DicomValue* levelTmp = filteredInput->TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL);
188 if (levelTmp == NULL || 269 if (levelTmp == NULL ||
189 levelTmp->IsNull() || 270 levelTmp->IsNull() ||
190 levelTmp->IsBinary()) 271 levelTmp->IsBinary())
191 { 272 {
192 LOG(ERROR) << "C-FIND request without the tag 0008,0052 (QueryRetrieveLevel)"; 273 LOG(ERROR) << "C-FIND request without the tag 0008,0052 (QueryRetrieveLevel)";
202 { 283 {
203 throw OrthancException(ErrorCode_NotImplemented); 284 throw OrthancException(ErrorCode_NotImplemented);
204 } 285 }
205 286
206 287
207 DicomArray query(input); 288 DicomArray query(*filteredInput);
208 LOG(INFO) << "DICOM C-Find request at level: " << EnumerationToString(level); 289 LOG(INFO) << "DICOM C-Find request at level: " << EnumerationToString(level);
209 290
210 for (size_t i = 0; i < query.GetSize(); i++) 291 for (size_t i = 0; i < query.GetSize(); i++)
211 { 292 {
212 if (!query.GetElement(i).GetValue().IsNull()) 293 if (!query.GetElement(i).GetValue().IsNull())