changeset 2268:ce5c13b95dac

New function: OrthancPluginRegisterIncomingHttpRequestFilter2()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 22 Feb 2017 21:49:16 +0100
parents f915aff7a866
children 8e53a2acdf21
files Core/HttpServer/IIncomingHttpRequestFilter.h Core/HttpServer/MongooseServer.cpp NEWS OrthancServer/main.cpp Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h Plugins/Include/orthanc/OrthancCPlugin.h Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Plugins/Samples/Common/OrthancPluginCppWrapper.h Plugins/Samples/ModalityWorklists/Plugin.cpp Plugins/Samples/ServeFolders/Plugin.cpp
diffstat 11 files changed, 162 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/IIncomingHttpRequestFilter.h	Wed Feb 22 13:32:05 2017 +0100
+++ b/Core/HttpServer/IIncomingHttpRequestFilter.h	Wed Feb 22 21:49:16 2017 +0100
@@ -48,6 +48,7 @@
                            const char* uri,
                            const char* ip,
                            const char* username,
-                           const IHttpHandler::Arguments& httpHeaders) const = 0;
+                           const IHttpHandler::Arguments& httpHeaders,
+                           const IHttpHandler::GetArguments& getArguments) const = 0;
   };
 }
--- a/Core/HttpServer/MongooseServer.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/Core/HttpServer/MongooseServer.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -652,7 +652,8 @@
     const IIncomingHttpRequestFilter *filter = server.GetIncomingHttpRequestFilter();
     if (filter != NULL)
     {
-      if (!filter->IsAllowed(method, request->uri, remoteIp, username.c_str(), headers))
+      if (!filter->IsAllowed(method, request->uri, remoteIp,
+                             username.c_str(), headers, argumentsGET))
       {
         //output.SendUnauthorized(ORTHANC_REALM);
         output.SendStatus(HttpStatus_403_Forbidden);
--- a/NEWS	Wed Feb 22 13:32:05 2017 +0100
+++ b/NEWS	Wed Feb 22 21:49:16 2017 +0100
@@ -1,8 +1,17 @@
 Pending changes in the mainline
 ===============================
 
+Plugins
+-------
+
+* New function: "OrthancPluginRegisterIncomingHttpRequestFilter2()"
+
+Lua
+---
+
 * Added HTTP headers support for Lua HttpPost/HttpGet/HttpPut/HttpDelete
 
+
 Version 1.2.0 (2016/12/13)
 ==========================
 
--- a/OrthancServer/main.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/OrthancServer/main.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -291,10 +291,11 @@
                          const char* uri,
                          const char* ip,
                          const char* username,
-                         const IHttpHandler::Arguments& httpHeaders) const
+                         const IHttpHandler::Arguments& httpHeaders,
+                         const IHttpHandler::GetArguments& getArguments) const
   {
     if (plugins_ != NULL &&
-        !plugins_->IsAllowed(method, uri, ip, username, httpHeaders))
+        !plugins_->IsAllowed(method, uri, ip, username, httpHeaders, getArguments))
     {
       return false;
     }
--- a/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -345,6 +345,7 @@
     typedef std::list<OrthancPluginOnStoredInstanceCallback>  OnStoredCallbacks;
     typedef std::list<OrthancPluginOnChangeCallback>  OnChangeCallbacks;
     typedef std::list<OrthancPluginIncomingHttpRequestFilter>  IncomingHttpRequestFilters;
+    typedef std::list<OrthancPluginIncomingHttpRequestFilter2>  IncomingHttpRequestFilters2;
     typedef std::list<OrthancPluginDecodeImageCallback>  DecodeImageCallbacks;
     typedef std::map<Property, std::string>  Properties;
 
@@ -358,6 +359,7 @@
     DecodeImageCallbacks  decodeImageCallbacks_;
     _OrthancPluginMoveCallback moveCallbacks_;
     IncomingHttpRequestFilters  incomingHttpRequestFilters_;
+    IncomingHttpRequestFilters2 incomingHttpRequestFilters2_;
     std::auto_ptr<StorageAreaFactory>  storageArea_;
 
     boost::recursive_mutex restCallbackMutex_;
@@ -1121,6 +1123,16 @@
   }
 
 
+  void OrthancPlugins::RegisterIncomingHttpRequestFilter2(const void* parameters)
+  {
+    const _OrthancPluginIncomingHttpRequestFilter2& p = 
+      *reinterpret_cast<const _OrthancPluginIncomingHttpRequestFilter2*>(parameters);
+
+    LOG(INFO) << "Plugin has registered a callback to filter incoming HTTP requests";
+    pimpl_->incomingHttpRequestFilters2_.push_back(p.callback);
+  }
+
+
   void OrthancPlugins::AnswerBuffer(const void* parameters)
   {
     const _OrthancPluginAnswerBuffer& p = 
@@ -2688,6 +2700,10 @@
         RegisterIncomingHttpRequestFilter(parameters);
         return true;
 
+      case _OrthancPluginService_RegisterIncomingHttpRequestFilter2:
+        RegisterIncomingHttpRequestFilter2(parameters);
+        return true;
+
       case _OrthancPluginService_RegisterStorageArea:
       {
         LOG(INFO) << "Plugin has registered a custom storage area";
@@ -3098,8 +3114,11 @@
                                  const char* uri,
                                  const char* ip,
                                  const char* username,
-                                 const IHttpHandler::Arguments& httpHeaders) const
+                                 const IHttpHandler::Arguments& httpHeaders,
+                                 const IHttpHandler::GetArguments& getArguments) const
   {
+    OrthancPluginHttpMethod cMethod = Plugins::Convert(method);
+
     std::vector<const char*> httpKeys(httpHeaders.size());
     std::vector<const char*> httpValues(httpHeaders.size());
 
@@ -3111,26 +3130,56 @@
       httpValues[pos] = it->second.c_str();
     }
 
-    OrthancPluginHttpMethod cMethod = Plugins::Convert(method);
-    const char** cHttpKeys = (httpKeys.size() == 0 ? NULL : &httpKeys[0]);
-    const char** cHttpValues = (httpValues.size() == 0 ? NULL : &httpValues[0]);
+    std::vector<const char*> getKeys(getArguments.size());
+    std::vector<const char*> getValues(getArguments.size());
+
+    for (size_t i = 0; i < getArguments.size(); i++)
+    {
+      getKeys[i] = getArguments[i].first.c_str();
+      getValues[i] = getArguments[i].second.c_str();
+    }
+
+    // Improved callback with support for GET arguments, since Orthanc 1.2.1
+    for (PImpl::IncomingHttpRequestFilters2::const_iterator
+           filter = pimpl_->incomingHttpRequestFilters2_.begin();
+         filter != pimpl_->incomingHttpRequestFilters2_.end(); ++filter)
+    {
+      int32_t allowed = (*filter) (cMethod, uri, ip,
+                                   httpKeys.size(),
+                                   httpKeys.empty() ? NULL : &httpKeys[0],
+                                   httpValues.empty() ? NULL : &httpValues[0],
+                                   getKeys.size(),
+                                   getKeys.empty() ? NULL : &getKeys[0],
+                                   getValues.empty() ? NULL : &getValues[0]);
+
+      if (allowed == 0)
+      {
+        return false;
+      }
+      else if (allowed != 1)
+      {
+        // The callback is only allowed to answer 0 or 1
+        throw OrthancException(ErrorCode_Plugin);
+      }
+    }
 
     for (PImpl::IncomingHttpRequestFilters::const_iterator
            filter = pimpl_->incomingHttpRequestFilters_.begin();
          filter != pimpl_->incomingHttpRequestFilters_.end(); ++filter)
     {
-      int32_t allowed = (*filter) (cMethod, uri, ip, httpKeys.size(), cHttpKeys, cHttpValues);
-
-      if (allowed != 0 &&
-          allowed != 1)
-      {
-        throw OrthancException(ErrorCode_Plugin);
-      }
+      int32_t allowed = (*filter) (cMethod, uri, ip, httpKeys.size(),
+                                   httpKeys.empty() ? NULL : &httpKeys[0],
+                                   httpValues.empty() ? NULL : &httpValues[0]);
 
       if (allowed == 0)
       {
         return false;
       }
+      else if (allowed != 1)
+      {
+        // The callback is only allowed to answer 0 or 1
+        throw OrthancException(ErrorCode_Plugin);
+      }
     }
 
     return true;
--- a/Plugins/Engine/OrthancPlugins.h	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Engine/OrthancPlugins.h	Wed Feb 22 21:49:16 2017 +0100
@@ -106,6 +106,8 @@
 
     void RegisterIncomingHttpRequestFilter(const void* parameters);
 
+    void RegisterIncomingHttpRequestFilter2(const void* parameters);
+
     void AnswerBuffer(const void* parameters);
 
     void Redirect(const void* parameters);
@@ -281,7 +283,8 @@
                            const char* uri,
                            const char* ip,
                            const char* username,
-                           const IHttpHandler::Arguments& httpHeaders) const;
+                           const IHttpHandler::Arguments& httpHeaders,
+                           const IHttpHandler::GetArguments& getArguments) const;
 
     bool HasFindHandler();
 
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 22 21:49:16 2017 +0100
@@ -22,7 +22,7 @@
  *    - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback().
  *    - Possibly register a handler for C-Move SCP using OrthancPluginRegisterMoveCallback().
  *    - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback().
- *    - Possibly register a callback to filter incoming HTTP requests using OrthancPluginRegisterIncomingHttpRequestFilter().
+ *    - Possibly register a callback to filter incoming HTTP requests using OrthancPluginRegisterIncomingHttpRequestFilter2().
  * -# <tt>void OrthancPluginFinalize()</tt>:
  *    This function is invoked by Orthanc during its shutdown. The plugin
  *    must free all its memory.
@@ -422,6 +422,7 @@
     _OrthancPluginService_RegisterIncomingHttpRequestFilter = 1007,
     _OrthancPluginService_RegisterFindCallback = 1008,
     _OrthancPluginService_RegisterMoveCallback = 1009,
+    _OrthancPluginService_RegisterIncomingHttpRequestFilter2 = 1010,
 
     /* Sending answers to REST calls */
     _OrthancPluginService_AnswerBuffer = 2000,
@@ -1014,6 +1015,7 @@
    * @param headersValues The values of the HTTP headers.
    * @return 0 if forbidden access, 1 if allowed access, -1 if error.
    * @ingroup Callback
+   * @deprecated Please instead use OrthancPluginIncomingHttpRequestFilter2()
    **/
   typedef int32_t (*OrthancPluginIncomingHttpRequestFilter) (
     OrthancPluginHttpMethod  method,
@@ -1026,6 +1028,40 @@
 
 
   /**
+   * @brief Callback to filter incoming HTTP requests received by Orthanc.
+   *
+   * Signature of a callback function that is triggered whenever
+   * Orthanc receives an HTTP/REST request, and that answers whether
+   * this request should be allowed. If the callback returns "0"
+   * ("false"), the server answers with HTTP status code 403
+   * (Forbidden).
+   *
+   * @param method The HTTP method used by the request.
+   * @param uri The URI of interest.
+   * @param ip The IP address of the HTTP client.
+   * @param headersCount The number of HTTP headers.
+   * @param headersKeys The keys of the HTTP headers (always converted to low-case).
+   * @param headersValues The values of the HTTP headers.
+   * @param getArgumentsCount The number of GET arguments (only for the GET HTTP method).
+   * @param getArgumentsKeys The keys of the GET arguments (only for the GET HTTP method).
+   * @param getArgumentsValues The values of the GET arguments (only for the GET HTTP method).
+   * @return 0 if forbidden access, 1 if allowed access, -1 if error.
+   * @ingroup Callback
+   **/
+  typedef int32_t (*OrthancPluginIncomingHttpRequestFilter2) (
+    OrthancPluginHttpMethod  method,
+    const char*              uri,
+    const char*              ip,
+    uint32_t                 headersCount,
+    const char* const*       headersKeys,
+    const char* const*       headersValues,
+    uint32_t                 getArgumentsCount,
+    const char* const*       getArgumentsKeys,
+    const char* const*       getArgumentsValues);
+
+
+
+  /**
    * @brief Callback to handle incoming C-Find SCP requests.
    *
    * Signature of a callback function that is triggered whenever
@@ -4997,6 +5033,7 @@
    * @param callback The callback.
    * @return 0 if success, other value if error.
    * @ingroup Callbacks
+   * @deprecated Please instead use OrthancPluginRegisterIncomingHttpRequestFilter2()
    **/
   ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingHttpRequestFilter(
     OrthancPluginContext*                   context,
@@ -5546,6 +5583,32 @@
   }
 
 
+  typedef struct
+  {
+    OrthancPluginIncomingHttpRequestFilter2 callback;
+  } _OrthancPluginIncomingHttpRequestFilter2;
+
+  /**
+   * @brief Register a callback to filter incoming HTTP requests.
+   *
+   * This function registers a custom callback to filter incoming HTTP/REST
+   * requests received by the HTTP server of Orthanc.
+   *
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param callback The callback.
+   * @return 0 if success, other value if error.
+   * @ingroup Callbacks
+   **/
+  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingHttpRequestFilter2(
+    OrthancPluginContext*                   context,
+    OrthancPluginIncomingHttpRequestFilter2 callback)
+  {
+    _OrthancPluginIncomingHttpRequestFilter2 params;
+    params.callback = callback;
+
+    return context->InvokeService(context, _OrthancPluginService_RegisterIncomingHttpRequestFilter2, &params);
+  }
+
 #ifdef  __cplusplus
 }
 #endif
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -1126,14 +1126,14 @@
   }
 
 
-  static void ReportIncompatibleVersion(OrthancPluginContext* context,
-                                        unsigned int major,
-                                        unsigned int minor,
-                                        unsigned int revision)
+  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
+                                   unsigned int major,
+                                   unsigned int minor,
+                                   unsigned int revision)
   {
     std::string s = ("Your version of the Orthanc core (" +
                      std::string(context->orthancVersion) +
-                     ") is too old to run this plugin (" +
+                     ") is too old to run this plugin (version " +
                      boost::lexical_cast<std::string>(major) + "." +
                      boost::lexical_cast<std::string>(minor) + "." +
                      boost::lexical_cast<std::string>(revision) + 
@@ -1189,7 +1189,6 @@
 
     if (a < major)
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
 
@@ -1204,7 +1203,6 @@
 
     if (b < minor)
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
 
@@ -1217,7 +1215,6 @@
     }
     else
     {
-      ReportIncompatibleVersion(context, major, minor, revision);
       return false;
     }
   }
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Wed Feb 22 21:49:16 2017 +0100
@@ -461,6 +461,11 @@
     }
   }
 
+  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
+                                   unsigned int major,
+                                   unsigned int minor,
+                                   unsigned int revision);
+  
   bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
                                   unsigned int major,
                                   unsigned int minor,
--- a/Plugins/Samples/ModalityWorklists/Plugin.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Samples/ModalityWorklists/Plugin.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -192,13 +192,10 @@
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(c) == 0)
     {
-      char info[1024];
-      sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
-              context_->orthancVersion,
-              ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
-              ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
-              ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
-      OrthancPluginLogError(context_, info);
+      OrthancPlugins::ReportMinimalOrthancVersion(context_, 
+                                                  ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
+                                                  ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
+                                                  ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
       return -1;
     }
 
--- a/Plugins/Samples/ServeFolders/Plugin.cpp	Wed Feb 22 13:32:05 2017 +0100
+++ b/Plugins/Samples/ServeFolders/Plugin.cpp	Wed Feb 22 21:49:16 2017 +0100
@@ -416,13 +416,10 @@
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(context_) == 0)
     {
-      char info[1024];
-      sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
-              context_->orthancVersion,
-              ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
-              ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
-              ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
-      OrthancPluginLogError(context_, info);
+      OrthancPlugins::ReportMinimalOrthancVersion(context_, 
+                                                  ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
+                                                  ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
+                                                  ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
       return -1;
     }