changeset 1539:7b7aaeee3773

remove duplicated files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 11 Aug 2020 13:26:33 +0200
parents d1806b4e4839
children e20a2381200d
files Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginException.h Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/VersionScriptPlugins.map Applications/Samples/RtViewerPlugin/Resources/OrthancSdk-1.0.0/orthanc/OrthancCPlugin.h Applications/StoneWebViewer/Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginException.h Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Applications/StoneWebViewer/Resources/Orthanc/Plugins/VersionScriptPlugins.map Applications/StoneWebViewer/Resources/OrthancSdk-1.0.0/orthanc/OrthancCPlugin.h
diffstat 14 files changed, 0 insertions(+), 18980 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# This is the list of the symbols that must be exported by Orthanc
-# plugins, if targeting OS X
-
-_OrthancPluginInitialize
-_OrthancPluginFinalize
-_OrthancPluginGetName
-_OrthancPluginGetVersion
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3383 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "OrthancPluginCppWrapper.h"
-
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/move/unique_ptr.hpp>
-#include <boost/thread.hpp>
-#include <json/reader.h>
-#include <json/writer.h>
-
-
-#if !ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
-static const OrthancPluginErrorCode OrthancPluginErrorCode_NullPointer = OrthancPluginErrorCode_Plugin;
-#endif
-
-
-namespace OrthancPlugins
-{
-  static OrthancPluginContext* globalContext_ = NULL;
-
-
-  void SetGlobalContext(OrthancPluginContext* context)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
-    }
-    else if (globalContext_ == NULL)
-    {
-      globalContext_ = context;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
-    }
-  }
-
-
-  bool HasGlobalContext()
-  {
-    return globalContext_ != NULL;
-  }
-
-
-  OrthancPluginContext* GetGlobalContext()
-  {
-    if (globalContext_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
-    }
-    else
-    {
-      return globalContext_;
-    }
-  }
-
-
-  void MemoryBuffer::Check(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (code == OrthancPluginErrorCode_UnknownResource ||
-             code == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  MemoryBuffer::MemoryBuffer()
-  {
-    buffer_.data = NULL;
-    buffer_.size = 0;
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  MemoryBuffer::MemoryBuffer(const void* buffer,
-                             size_t size)
-  {
-    uint32_t s = static_cast<uint32_t>(size);
-    if (static_cast<size_t>(s) != size)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) !=
-             OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else
-    {
-      memcpy(buffer_.data, buffer, size);
-    }
-  }
-#endif
-
-
-  void MemoryBuffer::Clear()
-  {
-    if (buffer_.data != NULL)
-    {
-      OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &buffer_);
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-  }
-
-
-  void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
-  {
-    Clear();
-
-    buffer_.data = other.data;
-    buffer_.size = other.size;
-
-    other.data = NULL;
-    other.size = 0;
-  }
-
-
-  void MemoryBuffer::Swap(MemoryBuffer& other)
-  {
-    std::swap(buffer_.data, other.buffer_.data);
-    std::swap(buffer_.size, other.buffer_.size);
-  }
-
-
-  OrthancPluginMemoryBuffer MemoryBuffer::Release()
-  {
-    OrthancPluginMemoryBuffer result = buffer_;
-
-    buffer_.data = NULL;
-    buffer_.size = 0;
-
-    return result;
-  }
-
-
-  void MemoryBuffer::ToString(std::string& target) const
-  {
-    if (buffer_.size == 0)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size);
-    }
-  }
-
-
-  void MemoryBuffer::ToJson(Json::Value& target) const
-  {
-    if (buffer_.data == NULL ||
-        buffer_.size == 0)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    const char* tmp = reinterpret_cast<const char*>(buffer_.data);
-
-    Json::Reader reader;
-    if (!reader.parse(tmp, tmp + buffer_.size, target))
-    {
-      LogError("Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiGet(const std::string& uri,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str()));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
-    }
-  }
-
-  bool MemoryBuffer::RestApiGet(const std::string& uri,
-                                const std::map<std::string, std::string>& httpHeaders,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    std::vector<const char*> headersKeys;
-    std::vector<const char*> headersValues;
-    
-    for (std::map<std::string, std::string>::const_iterator
-           it = httpHeaders.begin(); it != httpHeaders.end(); it++)
-    {
-      headersKeys.push_back(it->first.c_str());
-      headersValues.push_back(it->second.c_str());
-    }
-
-    return CheckHttp(OrthancPluginRestApiGet2(
-                       GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(),
-                       (headersKeys.empty() ? NULL : &headersKeys[0]),
-                       (headersValues.empty() ? NULL : &headersValues[0]), applyPlugins));
-  }
-
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const void* body,
-                                 size_t bodySize,
-                                 bool applyPlugins)
-  {
-    Clear();
-    
-    // Cast for compatibility with Orthanc SDK <= 1.5.6
-    const char* b = reinterpret_cast<const char*>(body);
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const void* body,
-                                size_t bodySize,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    // Cast for compatibility with Orthanc SDK <= 1.5.6
-    const char* b = reinterpret_cast<const char*>(body);
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPut(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const Json::Value& body,
-                                 bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const Json::Value& body,
-                                bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(uri, writer.write(body), applyPlugins);
-  }
-
-
-  void MemoryBuffer::CreateDicom(const Json::Value& tags,
-                                 OrthancPluginCreateDicomFlags flags)
-  {
-    Clear();
-
-    Json::FastWriter writer;
-    std::string s = writer.write(tags);
-
-    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), NULL, flags));
-  }
-
-  void MemoryBuffer::CreateDicom(const Json::Value& tags,
-                                 const OrthancImage& pixelData,
-                                 OrthancPluginCreateDicomFlags flags)
-  {
-    Clear();
-
-    Json::FastWriter writer;
-    std::string s = writer.write(tags);
-
-    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), pixelData.GetObject(), flags));
-  }
-
-
-  void MemoryBuffer::ReadFile(const std::string& path)
-  {
-    Clear();
-    Check(OrthancPluginReadFile(GetGlobalContext(), &buffer_, path.c_str()));
-  }
-
-
-  void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query)
-  {
-    Clear();
-    Check(OrthancPluginWorklistGetDicomQuery(GetGlobalContext(), &buffer_, query));
-  }
-
-
-  void OrthancString::Assign(char* str)
-  {
-    Clear();
-
-    if (str != NULL)
-    {
-      str_ = str;
-    }
-  }
-
-
-  void OrthancString::Clear()
-  {
-    if (str_ != NULL)
-    {
-      OrthancPluginFreeString(GetGlobalContext(), str_);
-      str_ = NULL;
-    }
-  }
-
-
-  void OrthancString::ToString(std::string& target) const
-  {
-    if (str_ == NULL)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(str_);
-    }
-  }
-
-
-  void OrthancString::ToJson(Json::Value& target) const
-  {
-    if (str_ == NULL)
-    {
-      LogError("Cannot convert an empty memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Reader reader;
-    if (!reader.parse(str_, target))
-    {
-      LogError("Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void MemoryBuffer::DicomToJson(Json::Value& target,
-                                 OrthancPluginDicomToJsonFormat format,
-                                 OrthancPluginDicomToJsonFlags flags,
-                                 uint32_t maxStringLength)
-  {
-    OrthancString str;
-    str.Assign(OrthancPluginDicomBufferToJson
-               (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
-    str.ToJson(target);
-  }
-
-
-  bool MemoryBuffer::HttpGet(const std::string& url,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpGet(GetGlobalContext(), &buffer_, url.c_str(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-
-
-  bool MemoryBuffer::HttpPost(const std::string& url,
-                              const std::string& body,
-                              const std::string& username,
-                              const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
-                                           body.c_str(), body.size(),
-                                           username.empty() ? NULL : username.c_str(),
-                                           password.empty() ? NULL : password.c_str()));
-  }
-
-
-  bool MemoryBuffer::HttpPut(const std::string& url,
-                             const std::string& body,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
-                                          body.empty() ? NULL : body.c_str(),
-                                          body.size(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-
-
-  void MemoryBuffer::GetDicomInstance(const std::string& instanceId)
-  {
-    Clear();
-    Check(OrthancPluginGetDicomForInstance(GetGlobalContext(), &buffer_, instanceId.c_str()));
-  }
-
-
-  bool HttpDelete(const std::string& url,
-                  const std::string& username,
-                  const std::string& password)
-  {
-    OrthancPluginErrorCode error = OrthancPluginHttpDelete
-      (GetGlobalContext(), url.c_str(),
-       username.empty() ? NULL : username.c_str(),
-       password.empty() ? NULL : password.c_str());
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-
-
-  void LogError(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogError(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void LogWarning(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void LogInfo(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void OrthancConfiguration::LoadConfiguration()
-  {
-    OrthancString str;
-    str.Assign(OrthancPluginGetConfiguration(GetGlobalContext()));
-
-    if (str.GetContent() == NULL)
-    {
-      LogError("Cannot access the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    str.ToJson(configuration_);
-
-    if (configuration_.type() != Json::objectValue)
-    {
-      LogError("Unable to read the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-    
-
-  OrthancConfiguration::OrthancConfiguration()
-  {
-    LoadConfiguration();
-  }
-
-
-  OrthancConfiguration::OrthancConfiguration(bool loadConfiguration)
-  {
-    if (loadConfiguration)
-    {
-      LoadConfiguration();
-    }
-    else
-    {
-      configuration_ = Json::objectValue;
-    }
-  }
-
-
-  std::string OrthancConfiguration::GetPath(const std::string& key) const
-  {
-    if (path_.empty())
-    {
-      return key;
-    }
-    else
-    {
-      return path_ + "." + key;
-    }
-  }
-
-
-  bool OrthancConfiguration::IsSection(const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    return (configuration_.isMember(key) &&
-            configuration_[key].type() == Json::objectValue);
-  }
-
-
-  void OrthancConfiguration::GetSection(OrthancConfiguration& target,
-                                        const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.path_ = GetPath(key);
-
-    if (!configuration_.isMember(key))
-    {
-      target.configuration_ = Json::objectValue;
-    }
-    else
-    {
-      if (configuration_[key].type() != Json::objectValue)
-      {
-        LogError("The configuration section \"" + target.path_ +
-                 "\" is not an associative array as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-
-      target.configuration_ = configuration_[key];
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupStringValue(std::string& target,
-                                               const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::stringValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a string as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asString();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupIntegerValue(int& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::intValue:
-        target = configuration_[key].asInt();
-        return true;
-
-      case Json::uintValue:
-        target = configuration_[key].asUInt();
-        return true;
-
-      default:
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not an integer as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target,
-                                                        const std::string& key) const
-  {
-    int tmp;
-    if (!LookupIntegerValue(tmp, key))
-    {
-      return false;
-    }
-
-    if (tmp < 0)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a positive integer as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      target = static_cast<unsigned int>(tmp);
-      return true;
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupBooleanValue(bool& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::booleanValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a Boolean as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asBool();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupFloatValue(float& target,
-                                              const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::realValue:
-        target = configuration_[key].asFloat();
-        return true;
-
-      case Json::intValue:
-        target = static_cast<float>(configuration_[key].asInt());
-        return true;
-
-      case Json::uintValue:
-        target = static_cast<float>(configuration_[key].asUInt());
-        return true;
-
-      default:
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not an integer as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target,
-                                                 const std::string& key,
-                                                 bool allowSingleString) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.clear();
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::arrayValue:
-      {
-        bool ok = true;
-
-        for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++)
-        {
-          if (configuration_[key][i].type() == Json::stringValue)
-          {
-            target.push_back(configuration_[key][i].asString());
-          }
-          else
-          {
-            ok = false;
-          }
-        }
-
-        if (ok)
-        {
-          return true;
-        }
-
-        break;
-      }
-
-      case Json::stringValue:
-        if (allowSingleString)
-        {
-          target.push_back(configuration_[key].asString());
-          return true;
-        }
-
-        break;
-
-      default:
-        break;
-    }
-
-    LogError("The configuration option \"" + GetPath(key) +
-             "\" is not a list of strings as expected");
-
-    ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-  }
-
-
-  bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target,
-                                                const std::string& key,
-                                                bool allowSingleString) const
-  {
-    std::list<std::string> lst;
-
-    if (LookupListOfStrings(lst, key, allowSingleString))
-    {
-      target.clear();
-
-      for (std::list<std::string>::const_iterator
-             it = lst.begin(); it != lst.end(); ++it)
-      {
-        target.insert(*it);
-      }
-
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  std::string OrthancConfiguration::GetStringValue(const std::string& key,
-                                                   const std::string& defaultValue) const
-  {
-    std::string tmp;
-    if (LookupStringValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  int OrthancConfiguration::GetIntegerValue(const std::string& key,
-                                            int defaultValue) const
-  {
-    int tmp;
-    if (LookupIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key,
-                                                             unsigned int defaultValue) const
-  {
-    unsigned int tmp;
-    if (LookupUnsignedIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  bool OrthancConfiguration::GetBooleanValue(const std::string& key,
-                                             bool defaultValue) const
-  {
-    bool tmp;
-    if (LookupBooleanValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  float OrthancConfiguration::GetFloatValue(const std::string& key,
-                                            float defaultValue) const
-  {
-    float tmp;
-    if (LookupFloatValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  void OrthancConfiguration::GetDictionary(std::map<std::string, std::string>& target,
-                                           const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.clear();
-
-    if (!configuration_.isMember(key))
-    {
-      return;
-    }
-
-    if (configuration_[key].type() != Json::objectValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a string as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    Json::Value::Members members = configuration_[key].getMemberNames();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& value = configuration_[key][members[i]];
-
-      if (value.type() == Json::stringValue)
-      {
-        target[members[i]] = value.asString();
-      }
-      else
-      {
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not a dictionary mapping strings to strings");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-    }
-  }
-
-
-  void OrthancImage::Clear()
-  {
-    if (image_ != NULL)
-    {
-      OrthancPluginFreeImage(GetGlobalContext(), image_);
-      image_ = NULL;
-    }
-  }
-
-
-  void OrthancImage::CheckImageAvailable() const
-  {
-    if (image_ == NULL)
-    {
-      LogError("Trying to access a NULL image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancImage::OrthancImage() :
-    image_(NULL)
-  {
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginImage*  image) :
-    image_(image)
-  {
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height)
-  {
-    image_ = OrthancPluginCreateImage(GetGlobalContext(), format, width, height);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot create an image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height,
-                             uint32_t                  pitch,
-                             void*                     buffer)
-  {
-    image_ = OrthancPluginCreateImageAccessor
-      (GetGlobalContext(), format, width, height, pitch, buffer);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot create an image accessor");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-  void OrthancImage::UncompressPngImage(const void* data,
-                                        size_t size)
-  {
-    Clear();
-
-    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Png);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a PNG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::UncompressJpegImage(const void* data,
-                                         size_t size)
-  {
-    Clear();
-    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a JPEG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::DecodeDicomImage(const void* data,
-                                      size_t size,
-                                      unsigned int frame)
-  {
-    Clear();
-    image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a DICOM image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancPluginPixelFormat OrthancImage::GetPixelFormat() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePixelFormat(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetWidth() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageWidth(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetHeight() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageHeight(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetPitch() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePitch(GetGlobalContext(), image_);
-  }
-
-
-  void* OrthancImage::GetBuffer() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageBuffer(GetGlobalContext(), image_);
-  }
-
-
-  void OrthancImage::CompressPngImage(MemoryBuffer& target) const
-  {
-    CheckImageAvailable();
-
-    OrthancPlugins::MemoryBuffer answer;
-    OrthancPluginCompressPngImage(GetGlobalContext(), *answer, GetPixelFormat(),
-                                  GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-
-    target.Swap(answer);
-  }
-
-
-  void OrthancImage::CompressJpegImage(MemoryBuffer& target,
-                                       uint8_t quality) const
-  {
-    CheckImageAvailable();
-
-    OrthancPlugins::MemoryBuffer answer;
-    OrthancPluginCompressJpegImage(GetGlobalContext(), *answer, GetPixelFormat(),
-                                   GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-
-    target.Swap(answer);
-  }
-
-
-  void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output) const
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerPngImage(GetGlobalContext(), output, GetPixelFormat(),
-                                           GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-  }
-
-
-  void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output,
-                                     uint8_t quality) const
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerJpegImage(GetGlobalContext(), output, GetPixelFormat(),
-                                            GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-  }
-
-
-  OrthancPluginImage* OrthancImage::Release()
-  {
-    CheckImageAvailable();
-    OrthancPluginImage* tmp = image_;
-    image_ = NULL;
-    return tmp;
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
-    matcher_(NULL),
-    worklist_(worklist)
-  {
-    if (worklist_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void FindMatcher::SetupDicom(const void*  query,
-                               uint32_t     size)
-  {
-    worklist_ = NULL;
-
-    matcher_ = OrthancPluginCreateFindMatcher(GetGlobalContext(), query, size);
-    if (matcher_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  FindMatcher::~FindMatcher()
-  {
-    // The "worklist_" field
-
-    if (matcher_ != NULL)
-    {
-      OrthancPluginFreeFindMatcher(GetGlobalContext(), matcher_);
-    }
-  }
-
-
-
-  bool FindMatcher::IsMatch(const void*  dicom,
-                            uint32_t     size) const
-  {
-    int32_t result;
-
-    if (matcher_ != NULL)
-    {
-      result = OrthancPluginFindMatcherIsMatch(GetGlobalContext(), matcher_, dicom, size);
-    }
-    else if (worklist_ != NULL)
-    {
-      result = OrthancPluginWorklistIsMatch(GetGlobalContext(), worklist_, dicom, size);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    if (result == 0)
-    {
-      return false;
-    }
-    else if (result == 1)
-    {
-      return true;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-#endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
-
-  void AnswerJson(const Json::Value& value,
-                  OrthancPluginRestOutput* output
-    )
-  {
-    Json::StyledWriter writer;
-    std::string bodyString = writer.write(value);
-
-    OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json");
-  }
-
-  void AnswerString(const std::string& answer,
-                    const char* mimeType,
-                    OrthancPluginRestOutput* output
-    )
-  {
-    OrthancPluginAnswerBuffer(GetGlobalContext(), output, answer.c_str(), answer.size(), mimeType);
-  }
-
-  void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output)
-  {
-    OrthancPluginSendHttpStatusCode(GetGlobalContext(), output, httpError);
-  }
-
-  void AnswerMethodNotAllowed(OrthancPluginRestOutput *output, const char* allowedMethods)
-  {
-    OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowedMethods);
-  }
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        bool applyPlugins)
-  {
-    MemoryBuffer answer;
-    if (!answer.RestApiGet(uri, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToString(result);
-      return true;
-    }
-  }
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        const std::map<std::string, std::string>& httpHeaders,
-                        bool applyPlugins)
-  {
-    MemoryBuffer answer;
-    if (!answer.RestApiGet(uri, httpHeaders, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToString(result);
-      return true;
-    }
-  }
-
-
-
-  bool RestApiGet(Json::Value& result,
-                  const std::string& uri,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiGet(uri, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(std::string& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        result.assign(answer.GetData(), answer.GetSize());
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(result, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const void* body,
-                  size_t bodySize,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty()) // i.e, on a PUT to metadata/..., orthanc returns an empty response
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const Json::Value& body,
-                  bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(result, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiDelete(const std::string& uri,
-                     bool applyPlugins)
-  {
-    OrthancPluginErrorCode error;
-
-    if (applyPlugins)
-    {
-      error = OrthancPluginRestApiDeleteAfterPlugins(GetGlobalContext(), uri.c_str());
-    }
-    else
-    {
-      error = OrthancPluginRestApiDelete(GetGlobalContext(), uri.c_str());
-    }
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-
-
-  void ReportMinimalOrthancVersion(unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision)
-  {
-    LogError("Your version of the Orthanc core (" +
-             std::string(GetGlobalContext()->orthancVersion) +
-             ") 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) +
-             " is required)");
-  }
-
-
-  bool CheckMinimalOrthancVersion(unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision)
-  {
-    if (!HasGlobalContext())
-    {
-      LogError("Bad Orthanc context in the plugin");
-      return false;
-    }
-
-    if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
-    {
-      // Assume compatibility with the mainline
-      return true;
-    }
-
-    // Parse the version of the Orthanc core
-    int aa, bb, cc;
-    if (
-#ifdef _MSC_VER
-      sscanf_s
-#else
-      sscanf
-#endif
-      (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
-      aa < 0 ||
-      bb < 0 ||
-      cc < 0)
-    {
-      return false;
-    }
-
-    unsigned int a = static_cast<unsigned int>(aa);
-    unsigned int b = static_cast<unsigned int>(bb);
-    unsigned int c = static_cast<unsigned int>(cc);
-
-    // Check the major version number
-
-    if (a > major)
-    {
-      return true;
-    }
-
-    if (a < major)
-    {
-      return false;
-    }
-
-
-    // Check the minor version number
-    assert(a == major);
-
-    if (b > minor)
-    {
-      return true;
-    }
-
-    if (b < minor)
-    {
-      return false;
-    }
-
-    // Check the patch level version number
-    assert(a == major && b == minor);
-
-    if (c >= revision)
-    {
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-  const char* AutodetectMimeType(const std::string& path)
-  {
-    const char* mime = OrthancPluginAutodetectMimeType(GetGlobalContext(), path.c_str());
-
-    if (mime == NULL)
-    {
-      // Should never happen, just for safety
-      return "application/octet-stream";
-    }
-    else
-    {
-      return mime;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
-  size_t OrthancPeers::GetPeerIndex(const std::string& name) const
-  {
-    size_t index;
-    if (LookupName(index, name))
-    {
-      return index;
-    }
-    else
-    {
-      LogError("Inexistent peer: " + name);
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-
-
-  OrthancPeers::OrthancPeers() :
-    peers_(NULL),
-    timeout_(0)
-  {
-    peers_ = OrthancPluginGetPeers(GetGlobalContext());
-
-    if (peers_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-
-    uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
-
-    for (uint32_t i = 0; i < count; i++)
-    {
-      const char* name = OrthancPluginGetPeerName(GetGlobalContext(), peers_, i);
-      if (name == NULL)
-      {
-        OrthancPluginFreePeers(GetGlobalContext(), peers_);
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-
-      index_[name] = i;
-    }
-  }
-
-
-  OrthancPeers::~OrthancPeers()
-  {
-    if (peers_ != NULL)
-    {
-      OrthancPluginFreePeers(GetGlobalContext(), peers_);
-    }
-  }
-
-
-  bool OrthancPeers::LookupName(size_t& target,
-                                const std::string& name) const
-  {
-    Index::const_iterator found = index_.find(name);
-
-    if (found == index_.end())
-    {
-      return false;
-    }
-    else
-    {
-      target = found->second;
-      return true;
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerName(size_t index) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
-      if (s == NULL)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-      else
-      {
-        return s;
-      }
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerUrl(size_t index) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
-      if (s == NULL)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-      else
-      {
-        return s;
-      }
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerUrl(const std::string& name) const
-  {
-    return GetPeerUrl(GetPeerIndex(name));
-  }
-
-
-  bool OrthancPeers::LookupUserProperty(std::string& value,
-                                        size_t index,
-                                        const std::string& key) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerUserProperty(GetGlobalContext(), peers_, static_cast<uint32_t>(index), key.c_str());
-      if (s == NULL)
-      {
-        return false;
-      }
-      else
-      {
-        value.assign(s);
-        return true;
-      }
-    }
-  }
-
-
-  bool OrthancPeers::LookupUserProperty(std::string& value,
-                                        const std::string& peer,
-                                        const std::string& key) const
-  {
-    return LookupUserProperty(value, GetPeerIndex(peer), key);
-  }
-
-
-  bool OrthancPeers::DoGet(MemoryBuffer& target,
-                           size_t index,
-                           const std::string& uri) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      target.Swap(answer);
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoGet(MemoryBuffer& target,
-                           const std::string& name,
-                           const std::string& uri) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoGet(target, index, uri));
-  }
-
-
-  bool OrthancPeers::DoGet(Json::Value& target,
-                           size_t index,
-                           const std::string& uri) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoGet(buffer, index, uri))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoGet(Json::Value& target,
-                           const std::string& name,
-                           const std::string& uri) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoGet(buffer, name, uri))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(MemoryBuffer& target,
-                            const std::string& name,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoPost(target, index, uri, body));
-  }
-
-
-  bool OrthancPeers::DoPost(Json::Value& target,
-                            size_t index,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoPost(buffer, index, uri, body))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(Json::Value& target,
-                            const std::string& name,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoPost(buffer, name, uri, body))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(MemoryBuffer& target,
-                            size_t index,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      target.Swap(answer);
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPut(size_t index,
-                           const std::string& uri,
-                           const std::string& body) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPut(const std::string& name,
-                           const std::string& uri,
-                           const std::string& body) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoPut(index, uri, body));
-  }
-
-
-  bool OrthancPeers::DoDelete(size_t index,
-                              const std::string& uri) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoDelete(const std::string& name,
-                              const std::string& uri) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoDelete(index, uri));
-  }
-#endif
-
-
-
-
-
-  /******************************************************************
-   ** JOBS
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_JOB == 1
-  void OrthancJob::CallbackFinalize(void* job)
-  {
-    if (job != NULL)
-    {
-      delete reinterpret_cast<OrthancJob*>(job);
-    }
-  }
-
-
-  float OrthancJob::CallbackGetProgress(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->progress_;
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  const char* OrthancJob::CallbackGetContent(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->content_.c_str();
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  const char* OrthancJob::CallbackGetSerialized(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      const OrthancJob& tmp = *reinterpret_cast<OrthancJob*>(job);
-
-      if (tmp.hasSerialized_)
-      {
-        return tmp.serialized_.c_str();
-      }
-      else
-      {
-        return NULL;
-      }
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->Step();
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
-    {
-      return OrthancPluginJobStepStatus_Failure;
-    }
-    catch (...)
-    {
-      return OrthancPluginJobStepStatus_Failure;
-    }
-  }
-
-
-  OrthancPluginErrorCode OrthancJob::CallbackStop(void* job,
-                                                  OrthancPluginJobStopReason reason)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      reinterpret_cast<OrthancJob*>(job)->Stop(reason);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-  OrthancPluginErrorCode OrthancJob::CallbackReset(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      reinterpret_cast<OrthancJob*>(job)->Reset();
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-  void OrthancJob::ClearContent()
-  {
-    Json::Value empty = Json::objectValue;
-    UpdateContent(empty);
-  }
-
-
-  void OrthancJob::UpdateContent(const Json::Value& content)
-  {
-    if (content.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
-    }
-    else
-    {
-      Json::FastWriter writer;
-      content_ = writer.write(content);
-    }
-  }
-
-
-  void OrthancJob::ClearSerialized()
-  {
-    hasSerialized_ = false;
-    serialized_.clear();
-  }
-
-
-  void OrthancJob::UpdateSerialized(const Json::Value& serialized)
-  {
-    if (serialized.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
-    }
-    else
-    {
-      Json::FastWriter writer;
-      serialized_ = writer.write(serialized);
-      hasSerialized_ = true;
-    }
-  }
-
-
-  void OrthancJob::UpdateProgress(float progress)
-  {
-    if (progress < 0 ||
-        progress > 1)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    progress_ = progress;
-  }
-
-
-  OrthancJob::OrthancJob(const std::string& jobType) :
-    jobType_(jobType),
-    progress_(0)
-  {
-    ClearContent();
-    ClearSerialized();
-  }
-
-
-  OrthancPluginJob* OrthancJob::Create(OrthancJob* job)
-  {
-    if (job == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
-    }
-
-    OrthancPluginJob* orthanc = OrthancPluginCreateJob(
-      GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
-      CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
-      CallbackStep, CallbackStop, CallbackReset);
-
-    if (orthanc == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-    else
-    {
-      return orthanc;
-    }
-  }
-
-
-  std::string OrthancJob::Submit(OrthancJob* job,
-                                 int priority)
-  {
-    if (job == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
-    }
-
-    OrthancPluginJob* orthanc = Create(job);
-
-    char* id = OrthancPluginSubmitJob(GetGlobalContext(), orthanc, priority);
-
-    if (id == NULL)
-    {
-      LogError("Plugin cannot submit job");
-      OrthancPluginFreeJob(GetGlobalContext(), orthanc);
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-    else
-    {
-      std::string tmp(id);
-      tmp.assign(id);
-      OrthancPluginFreeString(GetGlobalContext(), id);
-
-      return tmp;
-    }
-  }
-
-
-  void OrthancJob::SubmitAndWait(Json::Value& result,
-                                 OrthancJob* job /* takes ownership */,
-                                 int priority)
-  {
-    std::string id = Submit(job, priority);
-
-    for (;;)
-    {
-      boost::this_thread::sleep(boost::posix_time::milliseconds(100));
-
-      Json::Value status;
-      if (!RestApiGet(status, "/jobs/" + id, false) ||
-          !status.isMember("State") ||
-          status["State"].type() != Json::stringValue)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InexistentItem);        
-      }
-
-      const std::string state = status["State"].asString();
-      if (state == "Success")
-      {
-        if (status.isMember("Content"))
-        {
-          result = status["Content"];
-        }
-        else
-        {
-          result = Json::objectValue;
-        }
-
-        return;
-      }
-      else if (state == "Running")
-      {
-        continue;
-      }
-      else if (!status.isMember("ErrorCode") ||
-               status["ErrorCode"].type() != Json::intValue)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
-      }
-      else
-      {
-        if (!status.isMember("ErrorDescription") ||
-            status["ErrorDescription"].type() != Json::stringValue)
-        {
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());
-        }
-        else
-        {
-#if HAS_ORTHANC_EXCEPTION == 1
-          throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
-                                          status["ErrorDescription"].asString());
-#else
-          LogError("Exception while executing the job: " + status["ErrorDescription"].asString());
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
-#endif
-        }
-      }
-    }
-  }
-
-
-  void OrthancJob::SubmitFromRestApiPost(OrthancPluginRestOutput* output,
-                                         const Json::Value& body,
-                                         OrthancJob* job)
-  {
-    static const char* KEY_SYNCHRONOUS = "Synchronous";
-    static const char* KEY_ASYNCHRONOUS = "Asynchronous";
-    static const char* KEY_PRIORITY = "Priority";
-
-    boost::movelib::unique_ptr<OrthancJob> protection(job);
-  
-    if (body.type() != Json::objectValue)
-    {
-#if HAS_ORTHANC_EXCEPTION == 1
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                      "Expected a JSON object in the body");
-#else
-      LogError("Expected a JSON object in the body");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-    }
-
-    bool synchronous = true;
-  
-    if (body.isMember(KEY_SYNCHRONOUS))
-    {
-      if (body[KEY_SYNCHRONOUS].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_SYNCHRONOUS) +
-                                        "\" must be Boolean");
-#else
-        LogError("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        synchronous = body[KEY_SYNCHRONOUS].asBool();
-      }
-    }
-
-    if (body.isMember(KEY_ASYNCHRONOUS))
-    {
-      if (body[KEY_ASYNCHRONOUS].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_ASYNCHRONOUS) +
-                                        "\" must be Boolean");
-#else
-        LogError("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        synchronous = !body[KEY_ASYNCHRONOUS].asBool();
-      }
-    }
-
-    int priority = 0;
-
-    if (body.isMember(KEY_PRIORITY))
-    {
-      if (body[KEY_PRIORITY].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_PRIORITY) +
-                                        "\" must be an integer");
-#else
-        LogError("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        priority = !body[KEY_PRIORITY].asInt();
-      }
-    }
-  
-    Json::Value result;
-
-    if (synchronous)
-    {
-      OrthancPlugins::OrthancJob::SubmitAndWait(result, protection.release(), priority);
-    }
-    else
-    {
-      std::string id = OrthancPlugins::OrthancJob::Submit(protection.release(), priority);
-
-      result = Json::objectValue;
-      result["ID"] = id;
-      result["Path"] = "/jobs/" + id;
-    }
-
-    std::string s = result.toStyledString();
-    OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(),
-                              s.size(), "application/json");
-  }
-
-#endif
-
-
-
-
-  /******************************************************************
-   ** METRICS
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
-  MetricsTimer::MetricsTimer(const char* name) :
-    name_(name)
-  {
-    start_ = boost::posix_time::microsec_clock::universal_time();
-  }
-  
-  MetricsTimer::~MetricsTimer()
-  {
-    const boost::posix_time::ptime stop = boost::posix_time::microsec_clock::universal_time();
-    const boost::posix_time::time_duration diff = stop - start_;
-    OrthancPluginSetMetricsValue(GetGlobalContext(), name_.c_str(), static_cast<float>(diff.total_milliseconds()),
-                                 OrthancPluginMetricsType_Timer);
-  }
-#endif
-
-
-
-
-  /******************************************************************
-   ** HTTP CLIENT
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
-  class HttpClient::RequestBodyWrapper : public boost::noncopyable
-  {
-  private:
-    static RequestBodyWrapper& GetObject(void* body)
-    {
-      assert(body != NULL);
-      return *reinterpret_cast<RequestBodyWrapper*>(body);
-    }
-
-    IRequestBody&  body_;
-    bool           done_;
-    std::string    chunk_;
-
-  public:
-    RequestBodyWrapper(IRequestBody& body) :
-      body_(body),
-      done_(false)
-    {
-    }      
-
-    static uint8_t IsDone(void* body)
-    {
-      return GetObject(body).done_;
-    }
-    
-    static const void* GetChunkData(void* body)
-    {
-      return GetObject(body).chunk_.c_str();
-    }
-    
-    static uint32_t GetChunkSize(void* body)
-    {
-      return static_cast<uint32_t>(GetObject(body).chunk_.size());
-    }
-
-    static OrthancPluginErrorCode Next(void* body)
-    {
-      RequestBodyWrapper& that = GetObject(body);
-        
-      if (that.done_)
-      {
-        return OrthancPluginErrorCode_BadSequenceOfCalls;
-      }
-      else
-      {
-        try
-        {
-          that.done_ = !that.body_.ReadNextChunk(that.chunk_);
-          return OrthancPluginErrorCode_Success;
-        }
-        catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-        {
-          return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-        }
-        catch (...)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-      }
-    }    
-  };
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  static OrthancPluginErrorCode AnswerAddHeaderCallback(void* answer,
-                                                        const char* key,
-                                                        const char* value)
-  {
-    assert(answer != NULL && key != NULL && value != NULL);
-
-    try
-    {
-      reinterpret_cast<HttpClient::IAnswer*>(answer)->AddHeader(key, value);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  static OrthancPluginErrorCode AnswerAddChunkCallback(void* answer,
-                                                       const void* data,
-                                                       uint32_t size)
-  {
-    assert(answer != NULL);
-
-    try
-    {
-      reinterpret_cast<HttpClient::IAnswer*>(answer)->AddChunk(data, size);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-  HttpClient::HttpClient() :
-    httpStatus_(0),
-    method_(OrthancPluginHttpMethod_Get),
-    timeout_(0),
-    pkcs11_(false),
-    chunkedBody_(NULL),
-    allowChunkedTransfers_(true)
-  {
-  }
-
-
-  void HttpClient::AddHeaders(const HttpHeaders& headers)
-  {
-    for (HttpHeaders::const_iterator it = headers.begin();
-         it != headers.end(); ++it)
-    {
-      headers_[it->first] = it->second;
-    }
-  }
-
-  
-  void HttpClient::SetCredentials(const std::string& username,
-                                  const std::string& password)
-  {
-    username_ = username;
-    password_ = password;
-  }
-
-  
-  void HttpClient::ClearCredentials()
-  {
-    username_.empty();
-    password_.empty();
-  }
-
-
-  void HttpClient::SetCertificate(const std::string& certificateFile,
-                                  const std::string& keyFile,
-                                  const std::string& keyPassword)
-  {
-    certificateFile_ = certificateFile;
-    certificateKeyFile_ = keyFile;
-    certificateKeyPassword_ = keyPassword;
-  }
-
-  
-  void HttpClient::ClearCertificate()
-  {
-    certificateFile_.clear();
-    certificateKeyFile_.clear();
-    certificateKeyPassword_.clear();
-  }
-
-
-  void HttpClient::ClearBody()
-  {
-    fullBody_.clear();
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SwapBody(std::string& body)
-  {
-    fullBody_.swap(body);
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SetBody(const std::string& body)
-  {
-    fullBody_ = body;
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SetBody(IRequestBody& body)
-  {
-    fullBody_.clear();
-    chunkedBody_ = &body;
-  }
-
-
-  namespace
-  {
-    class HeadersWrapper : public boost::noncopyable
-    {
-    private:
-      std::vector<const char*>  headersKeys_;
-      std::vector<const char*>  headersValues_;
-
-    public:
-      HeadersWrapper(const HttpClient::HttpHeaders& headers)
-      {
-        headersKeys_.reserve(headers.size());
-        headersValues_.reserve(headers.size());
-
-        for (HttpClient::HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); ++it)
-        {
-          headersKeys_.push_back(it->first.c_str());
-          headersValues_.push_back(it->second.c_str());
-        }
-      }
-
-      void AddStaticString(const char* key,
-                           const char* value)
-      {
-        headersKeys_.push_back(key);
-        headersValues_.push_back(value);
-      }
-
-      uint32_t GetCount() const
-      {
-        return headersKeys_.size();
-      }
-
-      const char* const* GetKeys() const
-      {
-        return headersKeys_.empty() ? NULL : &headersKeys_[0];
-      }
-
-      const char* const* GetValues() const
-      {
-        return headersValues_.empty() ? NULL : &headersValues_[0];
-      }
-    };
-
-
-    class MemoryRequestBody : public HttpClient::IRequestBody
-    {
-    private:
-      std::string  body_;
-      bool         done_;
-
-    public:
-      MemoryRequestBody(const std::string& body) :
-        body_(body),
-        done_(false)
-      {
-        if (body_.empty())
-        {
-          done_ = true;
-        }
-      }
-
-      virtual bool ReadNextChunk(std::string& chunk)
-      {
-        if (done_)
-        {
-          return false;
-        }
-        else
-        {
-          chunk.swap(body_);
-          done_ = true;
-          return true;
-        }
-      }
-    };
-
-
-    // This class mimics Orthanc::ChunkedBuffer
-    class ChunkedBuffer : public boost::noncopyable
-    {
-    private:
-      typedef std::list<std::string*>  Content;
-
-      Content  content_;
-      size_t   size_;
-
-    public:
-      ChunkedBuffer() :
-        size_(0)
-      {
-      }
-
-      ~ChunkedBuffer()
-      {
-        Clear();
-      }
-
-      void Clear()
-      {
-        for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
-        {
-          assert(*it != NULL);
-          delete *it;
-        }
-
-        content_.clear();
-      }
-
-      void Flatten(std::string& target) const
-      {
-        target.resize(size_);
-
-        size_t pos = 0;
-
-        for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
-        {
-          assert(*it != NULL);
-          size_t s = (*it)->size();
-
-          if (s != 0)
-          {
-            memcpy(&target[pos], (*it)->c_str(), s);
-            pos += s;
-          }
-        }
-
-        assert(size_ == 0 ||
-               pos == target.size());
-      }
-
-      void AddChunk(const void* data,
-                    size_t size)
-      {
-        content_.push_back(new std::string(reinterpret_cast<const char*>(data), size));
-        size_ += size;
-      }
-
-      void AddChunk(const std::string& chunk)
-      {
-        content_.push_back(new std::string(chunk));
-        size_ += chunk.size();
-      }
-    };
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    class MemoryAnswer : public HttpClient::IAnswer
-    {
-    private:
-      HttpClient::HttpHeaders  headers_;
-      ChunkedBuffer            body_;
-
-    public:
-      const HttpClient::HttpHeaders& GetHeaders() const
-      {
-        return headers_;
-      }
-
-      const ChunkedBuffer& GetBody() const
-      {
-        return body_;
-      }
-
-      virtual void AddHeader(const std::string& key,
-                             const std::string& value)
-      {
-        headers_[key] = value;
-      }
-
-      virtual void AddChunk(const void* data,
-                            size_t size)
-      {
-        body_.AddChunk(data, size);
-      }
-    };
-#endif
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  void HttpClient::ExecuteWithStream(uint16_t& httpStatus,
-                                     IAnswer& answer,
-                                     IRequestBody& body) const
-  {
-    HeadersWrapper h(headers_);
-
-    if (method_ == OrthancPluginHttpMethod_Post ||
-        method_ == OrthancPluginHttpMethod_Put)
-    {
-      // Automatically set the "Transfer-Encoding" header if absent
-      bool found = false;
-
-      for (HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); ++it)
-      {
-        if (boost::iequals(it->first, "Transfer-Encoding"))
-        {
-          found = true;
-          break;
-        }
-      }
-
-      if (!found)
-      {
-        h.AddStaticString("Transfer-Encoding", "chunked");
-      }
-    }
-
-    RequestBodyWrapper request(body);
-        
-    OrthancPluginErrorCode error = OrthancPluginChunkedHttpClient(
-      GetGlobalContext(),
-      &answer,
-      AnswerAddChunkCallback,
-      AnswerAddHeaderCallback,
-      &httpStatus,
-      method_,
-      url_.c_str(),
-      h.GetCount(),
-      h.GetKeys(),
-      h.GetValues(),
-      &request,
-      RequestBodyWrapper::IsDone,
-      RequestBodyWrapper::GetChunkData,
-      RequestBodyWrapper::GetChunkSize,
-      RequestBodyWrapper::Next,
-      username_.empty() ? NULL : username_.c_str(),
-      password_.empty() ? NULL : password_.c_str(),
-      timeout_,
-      certificateFile_.empty() ? NULL : certificateFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(),
-      pkcs11_ ? 1 : 0);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-#endif    
-
-
-  void HttpClient::ExecuteWithoutStream(uint16_t& httpStatus,
-                                        HttpHeaders& answerHeaders,
-                                        std::string& answerBody,
-                                        const std::string& body) const
-  {
-    HeadersWrapper headers(headers_);
-
-    MemoryBuffer answerBodyBuffer, answerHeadersBuffer;
-
-    OrthancPluginErrorCode error = OrthancPluginHttpClient(
-      GetGlobalContext(),
-      *answerBodyBuffer,
-      *answerHeadersBuffer,
-      &httpStatus,
-      method_,
-      url_.c_str(),
-      headers.GetCount(),
-      headers.GetKeys(),
-      headers.GetValues(),
-      body.empty() ? NULL : body.c_str(),
-      body.size(),
-      username_.empty() ? NULL : username_.c_str(),
-      password_.empty() ? NULL : password_.c_str(),
-      timeout_,
-      certificateFile_.empty() ? NULL : certificateFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(),
-      pkcs11_ ? 1 : 0);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-
-    Json::Value v;
-    answerHeadersBuffer.ToJson(v);
-
-    if (v.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Value::Members members = v.getMemberNames();
-    answerHeaders.clear();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& h = v[members[i]];
-      if (h.type() != Json::stringValue)
-      {
-        ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-      }
-      else
-      {
-        answerHeaders[members[i]] = h.asString();
-      }
-    }
-
-    answerBodyBuffer.ToString(answerBody);
-  }
-
-
-  void HttpClient::Execute(IAnswer& answer)
-  {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    if (allowChunkedTransfers_)
-    {
-      if (chunkedBody_ != NULL)
-      {
-        ExecuteWithStream(httpStatus_, answer, *chunkedBody_);
-      }
-      else
-      {
-        MemoryRequestBody wrapper(fullBody_);
-        ExecuteWithStream(httpStatus_, answer, wrapper);
-      }
-
-      return;
-    }
-#endif
-    
-    // Compatibility mode for Orthanc SDK <= 1.5.6 or if chunked
-    // transfers are disabled. This results in higher memory usage
-    // (all chunks from the answer body are sent at once)
-
-    HttpHeaders answerHeaders;
-    std::string answerBody;
-    Execute(answerHeaders, answerBody);
-
-    for (HttpHeaders::const_iterator it = answerHeaders.begin(); 
-         it != answerHeaders.end(); ++it)
-    {
-      answer.AddHeader(it->first, it->second);      
-    }
-
-    if (!answerBody.empty())
-    {
-      answer.AddChunk(answerBody.c_str(), answerBody.size());
-    }
-  }
-
-
-  void HttpClient::Execute(HttpHeaders& answerHeaders /* out */,
-                           std::string& answerBody /* out */)
-  {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    if (allowChunkedTransfers_)
-    {
-      MemoryAnswer answer;
-      Execute(answer);
-      answerHeaders = answer.GetHeaders();
-      answer.GetBody().Flatten(answerBody);
-      return;
-    }
-#endif
-    
-    // Compatibility mode for Orthanc SDK <= 1.5.6 or if chunked
-    // transfers are disabled. This results in higher memory usage
-    // (all chunks from the request body are sent at once)
-
-    if (chunkedBody_ != NULL)
-    {
-      ChunkedBuffer buffer;
-      
-      std::string chunk;
-      while (chunkedBody_->ReadNextChunk(chunk))
-      {
-        buffer.AddChunk(chunk);
-      }
-
-      std::string body;
-      buffer.Flatten(body);
-
-      ExecuteWithoutStream(httpStatus_, answerHeaders, answerBody, body);
-    }
-    else
-    {
-      ExecuteWithoutStream(httpStatus_, answerHeaders, answerBody, fullBody_);
-    }
-  }
-
-
-  void HttpClient::Execute(HttpHeaders& answerHeaders /* out */,
-                           Json::Value& answerBody /* out */)
-  {
-    std::string body;
-    Execute(answerHeaders, body);
-    
-    Json::Reader reader;
-    if (!reader.parse(body, answerBody))
-    {
-      LogError("Cannot convert HTTP answer body to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void HttpClient::Execute()
-  {
-    HttpHeaders answerHeaders;
-    std::string body;
-    Execute(answerHeaders, body);
-  }
-
-#endif  /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */
-
-
-
-
-
-  /******************************************************************
-   ** CHUNKED HTTP SERVER
-   ******************************************************************/
-
-  namespace Internals
-  {
-    void NullRestCallback(OrthancPluginRestOutput* output,
-                          const char* url,
-                          const OrthancPluginHttpRequest* request)
-    {
-    }
-  
-    IChunkedRequestReader *NullChunkedRestCallback(const char* url,
-                                                   const OrthancPluginHttpRequest* request)
-    {
-      return NULL;
-    }
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-
-    OrthancPluginErrorCode ChunkedRequestReaderAddChunk(
-      OrthancPluginServerChunkedRequestReader* reader,
-      const void*                              data,
-      uint32_t                                 size)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-
-        reinterpret_cast<IChunkedRequestReader*>(reader)->AddChunk(data, size);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    
-    OrthancPluginErrorCode ChunkedRequestReaderExecute(
-      OrthancPluginServerChunkedRequestReader* reader,
-      OrthancPluginRestOutput*                 output)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-
-        reinterpret_cast<IChunkedRequestReader*>(reader)->Execute(output);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    
-    void ChunkedRequestReaderFinalize(
-      OrthancPluginServerChunkedRequestReader* reader)
-    {
-      if (reader != NULL)
-      {
-        delete reinterpret_cast<IChunkedRequestReader*>(reader);
-      }
-    }
-
-#else
-    
-    OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                    const char* url,
-                                                    const OrthancPluginHttpRequest* request,
-                                                    RestCallback         GetHandler,
-                                                    ChunkedRestCallback  PostHandler,
-                                                    RestCallback         DeleteHandler,
-                                                    ChunkedRestCallback  PutHandler)
-    {
-      try
-      {
-        std::string allowed;
-
-        if (GetHandler != Internals::NullRestCallback)
-        {
-          allowed += "GET";
-        }
-
-        if (PostHandler != Internals::NullChunkedRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "POST";
-        }
-
-        if (DeleteHandler != Internals::NullRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "DELETE";
-        }
-
-        if (PutHandler != Internals::NullChunkedRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "PUT";
-        }
-      
-        switch (request->method)
-        {
-          case OrthancPluginHttpMethod_Get:
-            if (GetHandler == Internals::NullRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              GetHandler(output, url, request);
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Post:
-            if (PostHandler == Internals::NullChunkedRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              boost::movelib::unique_ptr<IChunkedRequestReader> reader(PostHandler(url, request));
-              if (reader.get() == NULL)
-              {
-                ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-              }
-              else
-              {
-                reader->AddChunk(request->body, request->bodySize);
-                reader->Execute(output);
-              }
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Delete:
-            if (DeleteHandler == Internals::NullRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              DeleteHandler(output, url, request);
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Put:
-            if (PutHandler == Internals::NullChunkedRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              boost::movelib::unique_ptr<IChunkedRequestReader> reader(PutHandler(url, request));
-              if (reader.get() == NULL)
-              {
-                ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-              }
-              else
-              {
-                reader->AddChunk(request->body, request->bodySize);
-                reader->Execute(output);
-              }
-            }
-
-            break;
-
-          default:
-            ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-        }
-
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
-        if (HasGlobalContext() &&
-            e.HasDetails())
-        {
-          // The "false" instructs Orthanc not to log the detailed
-          // error message. This is to avoid duplicating the details,
-          // because "OrthancException" already does it on construction.
-          OrthancPluginSetHttpErrorDetails
-            (GetGlobalContext(), output, e.GetDetails(), false);
-        }
-#endif
-
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-#endif
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  OrthancPluginErrorCode IStorageCommitmentScpHandler::Lookup(
-    OrthancPluginStorageCommitmentFailureReason* target,
-    void* rawHandler,
-    const char* sopClassUid,
-    const char* sopInstanceUid)
-  {
-    assert(target != NULL &&
-           rawHandler != NULL);
-      
-    try
-    {
-      IStorageCommitmentScpHandler& handler = *reinterpret_cast<IStorageCommitmentScpHandler*>(rawHandler);
-      *target = handler.Lookup(sopClassUid, sopInstanceUid);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  void IStorageCommitmentScpHandler::Destructor(void* rawHandler)
-  {
-    assert(rawHandler != NULL);
-    delete reinterpret_cast<IStorageCommitmentScpHandler*>(rawHandler);
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-  DicomInstance::DicomInstance(const OrthancPluginDicomInstance* instance) :
-    toFree_(false),
-    instance_(instance)
-  {
-  }
-#else
-  DicomInstance::DicomInstance(OrthancPluginDicomInstance* instance) :
-    toFree_(false),
-    instance_(instance)
-  {
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  DicomInstance::DicomInstance(const void* buffer,
-                               size_t size) :
-    toFree_(true),
-    instance_(OrthancPluginCreateDicomInstance(GetGlobalContext(), buffer, size))
-  {
-    if (instance_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
-    }
-  }
-#endif
-
-
-  DicomInstance::~DicomInstance()
-  {
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    if (toFree_ &&
-        instance_ != NULL)
-    {
-      OrthancPluginFreeDicomInstance(
-        GetGlobalContext(), const_cast<OrthancPluginDicomInstance*>(instance_));
-    }
-#endif
-  }
-
-  
-  std::string DicomInstance::GetRemoteAet() const
-  {
-    const char* s = OrthancPluginGetInstanceRemoteAet(GetGlobalContext(), instance_);
-    if (s == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return std::string(s);
-    }
-  }
-
-
-  void DicomInstance::GetJson(Json::Value& target) const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceJson(GetGlobalContext(), instance_));
-    s.ToJson(target);
-  }
-  
-
-  void DicomInstance::GetSimplifiedJson(Json::Value& target) const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceSimplifiedJson(GetGlobalContext(), instance_));
-    s.ToJson(target);
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-  std::string DicomInstance::GetTransferSyntaxUid() const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceTransferSyntaxUid(GetGlobalContext(), instance_));
-
-    std::string result;
-    s.ToString(result);
-    return result;
-  }
-#endif
-
-  
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-  bool DicomInstance::HasPixelData() const
-  {
-    int32_t result = OrthancPluginHasInstancePixelData(GetGlobalContext(), instance_);
-    if (result < 0)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return (result != 0);
-    }
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)  
-  void DicomInstance::GetRawFrame(std::string& target,
-                                  unsigned int frameIndex) const
-  {
-    MemoryBuffer buffer;
-    OrthancPluginErrorCode code = OrthancPluginGetInstanceRawFrame(
-      GetGlobalContext(), *buffer, instance_, frameIndex);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      buffer.ToString(target);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)  
-  OrthancImage* DicomInstance::GetDecodedFrame(unsigned int frameIndex) const
-  {
-    OrthancPluginImage* image = OrthancPluginGetInstanceDecodedFrame(
-      GetGlobalContext(), instance_, frameIndex);
-
-    if (image == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return new OrthancImage(image);
-    }
-  }
-#endif  
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  void DicomInstance::Serialize(std::string& target) const
-  {
-    MemoryBuffer buffer;
-    OrthancPluginErrorCode code = OrthancPluginSerializeDicomInstance(
-      GetGlobalContext(), *buffer, instance_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      buffer.ToString(target);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-#endif
-  
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  DicomInstance* DicomInstance::Transcode(const void* buffer,
-                                          size_t size,
-                                          const std::string& transferSyntax)
-  {
-    OrthancPluginDicomInstance* instance = OrthancPluginTranscodeDicomInstance(
-      GetGlobalContext(), buffer, size, transferSyntax.c_str());
-
-    if (instance == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      boost::movelib::unique_ptr<DicomInstance> result(new DicomInstance(instance));
-      result->toFree_ = true;
-      return result.release();
-    }
-  }
-#endif
-}
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1228 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "OrthancPluginException.h"
-
-#include <orthanc/OrthancCPlugin.h>
-#include <boost/noncopyable.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <json/value.h>
-#include <vector>
-#include <list>
-#include <set>
-#include <map>
-
-
-
-/**
- * The definition of ORTHANC_PLUGINS_VERSION_IS_ABOVE below is for
- * backward compatibility with Orthanc SDK <= 1.3.0.
- * 
- *   $ hg diff -r Orthanc-1.3.0:Orthanc-1.3.1 ../../../Plugins/Include/orthanc/OrthancCPlugin.h
- *
- **/
-#if !defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)
-#define ORTHANC_PLUGINS_VERSION_IS_ABOVE(major, minor, revision)        \
-  (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER > major ||                      \
-   (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER == major &&                    \
-    (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER > minor ||                    \
-     (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER == minor &&                  \
-      ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER >= revision))))
-#endif
-
-
-#if !defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE)
-#define ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(major, minor, revision)      \
-  (ORTHANC_VERSION_MAJOR > major ||                                     \
-   (ORTHANC_VERSION_MAJOR == major &&                                   \
-    (ORTHANC_VERSION_MINOR > minor ||                                   \
-     (ORTHANC_VERSION_MINOR == minor &&                                 \
-      ORTHANC_VERSION_REVISION >= revision))))
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
-// The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  1
-#else
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  0
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 4, 2)
-#  define HAS_ORTHANC_PLUGIN_PEERS  1
-#  define HAS_ORTHANC_PLUGIN_JOB    1
-#else
-#  define HAS_ORTHANC_PLUGIN_PEERS  0
-#  define HAS_ORTHANC_PLUGIN_JOB    0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  1
-#else
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
-#  define HAS_ORTHANC_PLUGIN_METRICS  1
-#else
-#  define HAS_ORTHANC_PLUGIN_METRICS  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 1, 0)
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  1
-#else
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  1
-#else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  1
-#else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 0)
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  1
-#else
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  0
-#endif
-
-
-
-namespace OrthancPlugins
-{
-  typedef void (*RestCallback) (OrthancPluginRestOutput* output,
-                                const char* url,
-                                const OrthancPluginHttpRequest* request);
-
-  void SetGlobalContext(OrthancPluginContext* context);
-
-  bool HasGlobalContext();
-
-  OrthancPluginContext* GetGlobalContext();
-
-  
-  class OrthancImage;
-
-
-  class MemoryBuffer : public boost::noncopyable
-  {
-  private:
-    OrthancPluginMemoryBuffer  buffer_;
-
-    void Check(OrthancPluginErrorCode code);
-
-    bool CheckHttp(OrthancPluginErrorCode code);
-
-  public:
-    MemoryBuffer();
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    // This constructor makes a copy of the given buffer in the memory
-    // handled by the Orthanc core
-    MemoryBuffer(const void* buffer,
-                 size_t size);
-#endif
-
-    ~MemoryBuffer()
-    {
-      Clear();
-    }
-
-    OrthancPluginMemoryBuffer* operator*()
-    {
-      return &buffer_;
-    }
-
-    // This transfers ownership from "other" to "this"
-    void Assign(OrthancPluginMemoryBuffer& other);
-
-    void Swap(MemoryBuffer& other);
-
-    OrthancPluginMemoryBuffer Release();
-
-    const char* GetData() const
-    {
-      if (buffer_.size > 0)
-      {
-        return reinterpret_cast<const char*>(buffer_.data);
-      }
-      else
-      {
-        return NULL;
-      }
-    }
-
-    size_t GetSize() const
-    {
-      return buffer_.size;
-    }
-
-    bool IsEmpty() const
-    {
-      return GetSize() == 0 || GetData() == NULL;
-    }
-
-    void Clear();
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-
-    bool RestApiGet(const std::string& uri,
-                    bool applyPlugins);
-
-    bool RestApiGet(const std::string& uri,
-                    const std::map<std::string, std::string>& httpHeaders,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const void* body,
-                     size_t bodySize,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const void* body,
-                    size_t bodySize,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const Json::Value& body,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const Json::Value& body,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const std::string& body,
-                     bool applyPlugins)
-    {
-      return RestApiPost(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    bool RestApiPut(const std::string& uri,
-                    const std::string& body,
-                    bool applyPlugins)
-    {
-      return RestApiPut(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    void CreateDicom(const Json::Value& tags,
-                     OrthancPluginCreateDicomFlags flags);
-
-    void CreateDicom(const Json::Value& tags,
-                     const OrthancImage& pixelData,
-                     OrthancPluginCreateDicomFlags flags);
-
-    void ReadFile(const std::string& path);
-
-    void GetDicomQuery(const OrthancPluginWorklistQuery* query);
-
-    void DicomToJson(Json::Value& target,
-                     OrthancPluginDicomToJsonFormat format,
-                     OrthancPluginDicomToJsonFlags flags,
-                     uint32_t maxStringLength);
-
-    bool HttpGet(const std::string& url,
-                 const std::string& username,
-                 const std::string& password);
-
-    bool HttpPost(const std::string& url,
-                  const std::string& body,
-                  const std::string& username,
-                  const std::string& password);
-
-    bool HttpPut(const std::string& url,
-                 const std::string& body,
-                 const std::string& username,
-                 const std::string& password);
-
-    void GetDicomInstance(const std::string& instanceId);
-  };
-
-
-  class OrthancString : public boost::noncopyable
-  {
-  private:
-    char*   str_;
-
-    void Clear();
-
-  public:
-    OrthancString() :
-      str_(NULL)
-    {
-    }
-
-    ~OrthancString()
-    {
-      Clear();
-    }
-
-    // This transfers ownership, warning: The string must have been
-    // allocated by the Orthanc core
-    void Assign(char* str);
-
-    const char* GetContent() const
-    {
-      return str_;
-    }
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-  };
-
-
-  class OrthancConfiguration : public boost::noncopyable
-  {
-  private:
-    Json::Value  configuration_;  // Necessarily a Json::objectValue
-    std::string  path_;
-
-    std::string GetPath(const std::string& key) const;
-
-    void LoadConfiguration();
-    
-  public:
-    OrthancConfiguration();
-
-    explicit OrthancConfiguration(bool load);
-
-    const Json::Value& GetJson() const
-    {
-      return configuration_;
-    }
-
-    bool IsSection(const std::string& key) const;
-
-    void GetSection(OrthancConfiguration& target,
-                    const std::string& key) const;
-
-    bool LookupStringValue(std::string& target,
-                           const std::string& key) const;
-    
-    bool LookupIntegerValue(int& target,
-                            const std::string& key) const;
-
-    bool LookupUnsignedIntegerValue(unsigned int& target,
-                                    const std::string& key) const;
-
-    bool LookupBooleanValue(bool& target,
-                            const std::string& key) const;
-
-    bool LookupFloatValue(float& target,
-                          const std::string& key) const;
-
-    bool LookupListOfStrings(std::list<std::string>& target,
-                             const std::string& key,
-                             bool allowSingleString) const;
-
-    bool LookupSetOfStrings(std::set<std::string>& target,
-                            const std::string& key,
-                            bool allowSingleString) const;
-
-    std::string GetStringValue(const std::string& key,
-                               const std::string& defaultValue) const;
-
-    int GetIntegerValue(const std::string& key,
-                        int defaultValue) const;
-
-    unsigned int GetUnsignedIntegerValue(const std::string& key,
-                                         unsigned int defaultValue) const;
-
-    bool GetBooleanValue(const std::string& key,
-                         bool defaultValue) const;
-
-    float GetFloatValue(const std::string& key,
-                        float defaultValue) const;
-
-    void GetDictionary(std::map<std::string, std::string>& target,
-                       const std::string& key) const;
-  };
-
-  class OrthancImage : public boost::noncopyable
-  {
-  private:
-    OrthancPluginImage*    image_;
-
-    void Clear();
-
-    void CheckImageAvailable() const;
-
-  public:
-    OrthancImage();
-
-    explicit OrthancImage(OrthancPluginImage* image);
-
-    OrthancImage(OrthancPluginPixelFormat  format,
-                 uint32_t                  width,
-                 uint32_t                  height);
-
-    OrthancImage(OrthancPluginPixelFormat  format,
-                 uint32_t                  width,
-                 uint32_t                  height,
-                 uint32_t                  pitch,
-                 void*                     buffer);
-
-    ~OrthancImage()
-    {
-      Clear();
-    }
-
-    void UncompressPngImage(const void* data,
-                            size_t size);
-
-    void UncompressJpegImage(const void* data,
-                             size_t size);
-
-    void DecodeDicomImage(const void* data,
-                          size_t size,
-                          unsigned int frame);
-
-    OrthancPluginPixelFormat GetPixelFormat() const;
-
-    unsigned int GetWidth() const;
-
-    unsigned int GetHeight() const;
-
-    unsigned int GetPitch() const;
-    
-    void* GetBuffer() const;
-
-    const OrthancPluginImage* GetObject() const
-    {
-      return image_;
-    }
-
-    void CompressPngImage(MemoryBuffer& target) const;
-
-    void CompressJpegImage(MemoryBuffer& target,
-                           uint8_t quality) const;
-
-    void AnswerPngImage(OrthancPluginRestOutput* output) const;
-
-    void AnswerJpegImage(OrthancPluginRestOutput* output,
-                         uint8_t quality) const;
-    
-    void* GetWriteableBuffer();
-
-    OrthancPluginImage* Release();
-  };
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  class FindMatcher : public boost::noncopyable
-  {
-  private:
-    OrthancPluginFindMatcher*          matcher_;
-    const OrthancPluginWorklistQuery*  worklist_;
-
-    void SetupDicom(const void*            query,
-                    uint32_t               size);
-
-  public:
-    explicit FindMatcher(const OrthancPluginWorklistQuery*  worklist);
-
-    FindMatcher(const void*  query,
-                uint32_t     size)
-    {
-      SetupDicom(query, size);
-    }
-
-    explicit FindMatcher(const MemoryBuffer&  dicom)
-    {
-      SetupDicom(dicom.GetData(), dicom.GetSize());
-    }
-
-    ~FindMatcher();
-
-    bool IsMatch(const void*  dicom,
-                 uint32_t     size) const;
-
-    bool IsMatch(const MemoryBuffer& dicom) const
-    {
-      return IsMatch(dicom.GetData(), dicom.GetSize());
-    }
-  };
-#endif
-
-
-  bool RestApiGet(Json::Value& result,
-                  const std::string& uri,
-                  bool applyPlugins);
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        bool applyPlugins);
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        const std::map<std::string, std::string>& httpHeaders,
-                        bool applyPlugins);
-
-  bool RestApiPost(std::string& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins);
-
-  inline bool RestApiPost(Json::Value& result,
-                          const std::string& uri,
-                          const std::string& body,
-                          bool applyPlugins)
-  {
-    return RestApiPost(result, uri, body.empty() ? NULL : body.c_str(),
-                       body.size(), applyPlugins);
-  }
-
-  inline bool RestApiPost(Json::Value& result,
-                          const std::string& uri,
-                          const MemoryBuffer& body,
-                          bool applyPlugins)
-  {
-    return RestApiPost(result, uri, body.GetData(),
-                       body.GetSize(), applyPlugins);
-  }
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const void* body,
-                  size_t bodySize,
-                  bool applyPlugins);
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const Json::Value& body,
-                  bool applyPlugins);
-
-  inline bool RestApiPut(Json::Value& result,
-                         const std::string& uri,
-                         const std::string& body,
-                         bool applyPlugins)
-  {
-    return RestApiPut(result, uri, body.empty() ? NULL : body.c_str(),
-                      body.size(), applyPlugins);
-  }
-
-  bool RestApiDelete(const std::string& uri,
-                     bool applyPlugins);
-
-  bool HttpDelete(const std::string& url,
-                  const std::string& username,
-                  const std::string& password);
-
-  void AnswerJson(const Json::Value& value,
-                  OrthancPluginRestOutput* output);
-
-  void AnswerString(const std::string& answer,
-                    const char* mimeType,
-                    OrthancPluginRestOutput* output);
-
-  void AnswerHttpError(uint16_t httpError,
-                       OrthancPluginRestOutput* output);
-
-  void AnswerMethodNotAllowed(OrthancPluginRestOutput* output, const char* allowedMethods);
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-  const char* AutodetectMimeType(const std::string& path);
-#endif
-
-  void LogError(const std::string& message);
-
-  void LogWarning(const std::string& message);
-
-  void LogInfo(const std::string& message);
-
-  void ReportMinimalOrthancVersion(unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision);
-  
-  bool CheckMinimalOrthancVersion(unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision);
-
-
-  namespace Internals
-  {
-    template <RestCallback Callback>
-    static OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output,
-                                          const char* url,
-                                          const OrthancPluginHttpRequest* request)
-    {
-      try
-      {
-        Callback(output, url, request);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
-        if (HasGlobalContext() &&
-            e.HasDetails())
-        {
-          // The "false" instructs Orthanc not to log the detailed
-          // error message. This is to avoid duplicating the details,
-          // because "OrthancException" already does it on construction.
-          OrthancPluginSetHttpErrorDetails
-            (GetGlobalContext(), output, e.GetDetails(), false);
-        }
-#endif
-
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-  }
-
-  
-  template <RestCallback Callback>
-  void RegisterRestCallback(const std::string& uri,
-                            bool isThreadSafe)
-  {
-    if (isThreadSafe)
-    {
-      OrthancPluginRegisterRestCallbackNoLock
-        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
-    }
-    else
-    {
-      OrthancPluginRegisterRestCallback
-        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
-    }
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
-  class OrthancPeers : public boost::noncopyable
-  {
-  private:
-    typedef std::map<std::string, uint32_t>   Index;
-
-    OrthancPluginPeers   *peers_;
-    Index                 index_;
-    uint32_t              timeout_;
-
-    size_t GetPeerIndex(const std::string& name) const;
-
-  public:
-    OrthancPeers();
-
-    ~OrthancPeers();
-
-    uint32_t GetTimeout() const
-    {
-      return timeout_;
-    }
-
-    void SetTimeout(uint32_t timeout)
-    {
-      timeout_ = timeout;
-    }
-
-    bool LookupName(size_t& target,
-                    const std::string& name) const;
-
-    std::string GetPeerName(size_t index) const;
-
-    std::string GetPeerUrl(size_t index) const;
-
-    std::string GetPeerUrl(const std::string& name) const;
-
-    size_t GetPeersCount() const
-    {
-      return index_.size();
-    }
-
-    bool LookupUserProperty(std::string& value,
-                            size_t index,
-                            const std::string& key) const;
-
-    bool LookupUserProperty(std::string& value,
-                            const std::string& peer,
-                            const std::string& key) const;
-
-    bool DoGet(MemoryBuffer& target,
-               size_t index,
-               const std::string& uri) const;
-
-    bool DoGet(MemoryBuffer& target,
-               const std::string& name,
-               const std::string& uri) const;
-
-    bool DoGet(Json::Value& target,
-               size_t index,
-               const std::string& uri) const;
-
-    bool DoGet(Json::Value& target,
-               const std::string& name,
-               const std::string& uri) const;
-
-    bool DoPost(MemoryBuffer& target,
-                size_t index,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(MemoryBuffer& target,
-                const std::string& name,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(Json::Value& target,
-                size_t index,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(Json::Value& target,
-                const std::string& name,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPut(size_t index,
-               const std::string& uri,
-               const std::string& body) const;
-
-    bool DoPut(const std::string& name,
-               const std::string& uri,
-               const std::string& body) const;
-
-    bool DoDelete(size_t index,
-                  const std::string& uri) const;
-
-    bool DoDelete(const std::string& name,
-                  const std::string& uri) const;
-  };
-#endif
-
-
-
-#if HAS_ORTHANC_PLUGIN_JOB == 1
-  class OrthancJob : public boost::noncopyable
-  {
-  private:
-    std::string   jobType_;
-    std::string   content_;
-    bool          hasSerialized_;
-    std::string   serialized_;
-    float         progress_;
-
-    static void CallbackFinalize(void* job);
-
-    static float CallbackGetProgress(void* job);
-
-    static const char* CallbackGetContent(void* job);
-
-    static const char* CallbackGetSerialized(void* job);
-
-    static OrthancPluginJobStepStatus CallbackStep(void* job);
-
-    static OrthancPluginErrorCode CallbackStop(void* job,
-                                               OrthancPluginJobStopReason reason);
-
-    static OrthancPluginErrorCode CallbackReset(void* job);
-
-  protected:
-    void ClearContent();
-
-    void UpdateContent(const Json::Value& content);
-
-    void ClearSerialized();
-
-    void UpdateSerialized(const Json::Value& serialized);
-
-    void UpdateProgress(float progress);
-    
-  public:
-    OrthancJob(const std::string& jobType);
-    
-    virtual ~OrthancJob()
-    {
-    }
-
-    virtual OrthancPluginJobStepStatus Step() = 0;
-
-    virtual void Stop(OrthancPluginJobStopReason reason) = 0;
-    
-    virtual void Reset() = 0;
-
-    static OrthancPluginJob* Create(OrthancJob* job /* takes ownership */);
-
-    static std::string Submit(OrthancJob* job /* takes ownership */,
-                              int priority);
-
-    static void SubmitAndWait(Json::Value& result,
-                              OrthancJob* job /* takes ownership */,
-                              int priority);
-
-    // Submit a job from a POST on the REST API with the same
-    // conventions as in the Orthanc core (according to the
-    // "Synchronous" and "Priority" options)
-    static void SubmitFromRestApiPost(OrthancPluginRestOutput* output,
-                                      const Json::Value& body,
-                                      OrthancJob* job);
-  };
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
-  inline void SetMetricsValue(char* name,
-                              float value)
-  {
-    OrthancPluginSetMetricsValue(GetGlobalContext(), name,
-                                 value, OrthancPluginMetricsType_Default);
-  }
-
-  class MetricsTimer : public boost::noncopyable
-  {
-  private:
-    std::string               name_;
-    boost::posix_time::ptime  start_;
-
-  public:
-    explicit MetricsTimer(const char* name);
-
-    ~MetricsTimer();
-  };
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
-  class HttpClient : public boost::noncopyable
-  {
-  public:
-    typedef std::map<std::string, std::string>  HttpHeaders;
-
-    class IRequestBody : public boost::noncopyable
-    {
-    public:
-      virtual ~IRequestBody()
-      {
-      }
-
-      virtual bool ReadNextChunk(std::string& chunk) = 0;
-    };
-
-
-    class IAnswer : public boost::noncopyable
-    {
-    public:
-      virtual ~IAnswer()
-      {
-      }
-
-      virtual void AddHeader(const std::string& key,
-                             const std::string& value) = 0;
-
-      virtual void AddChunk(const void* data,
-                            size_t size) = 0;
-    };
-
-
-  private:
-    class RequestBodyWrapper;
-
-    uint16_t                 httpStatus_;
-    OrthancPluginHttpMethod  method_;
-    std::string              url_;
-    HttpHeaders              headers_;
-    std::string              username_;
-    std::string              password_;
-    uint32_t                 timeout_;
-    std::string              certificateFile_;
-    std::string              certificateKeyFile_;
-    std::string              certificateKeyPassword_;
-    bool                     pkcs11_;
-    std::string              fullBody_;
-    IRequestBody*            chunkedBody_;
-    bool                     allowChunkedTransfers_;
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    void ExecuteWithStream(uint16_t& httpStatus,  // out
-                           IAnswer& answer,       // out
-                           IRequestBody& body) const;
-#endif
-
-    void ExecuteWithoutStream(uint16_t& httpStatus,        // out
-                              HttpHeaders& answerHeaders,  // out
-                              std::string& answerBody,     // out
-                              const std::string& body) const;
-    
-  public:
-    HttpClient();
-
-    uint16_t GetHttpStatus() const
-    {
-      return httpStatus_;
-    }
-
-    void SetMethod(OrthancPluginHttpMethod method)
-    {
-      method_ = method;
-    }
-
-    const std::string& GetUrl() const
-    {
-      return url_;
-    }
-
-    void SetUrl(const std::string& url)
-    {
-      url_ = url;
-    }
-
-    void SetHeaders(const HttpHeaders& headers)
-    {
-      headers_ = headers;
-    }
-
-    void AddHeader(const std::string& key,
-                   const std::string& value)
-    {
-      headers_[key] = value;
-    }
-
-    void AddHeaders(const HttpHeaders& headers);
-
-    void SetCredentials(const std::string& username,
-                        const std::string& password);
-
-    void ClearCredentials();
-
-    void SetTimeout(unsigned int timeout)  // 0 for default timeout
-    {
-      timeout_ = timeout;
-    }
-
-    void SetCertificate(const std::string& certificateFile,
-                        const std::string& keyFile,
-                        const std::string& keyPassword);
-
-    void ClearCertificate();
-
-    void SetPkcs11(bool pkcs11)
-    {
-      pkcs11_ = pkcs11;
-    }
-
-    void ClearBody();
-
-    void SwapBody(std::string& body);
-
-    void SetBody(const std::string& body);
-
-    void SetBody(IRequestBody& body);
-
-    // This function can be used to disable chunked transfers if the
-    // remote server is Orthanc with a version <= 1.5.6.
-    void SetChunkedTransfersAllowed(bool allow)
-    {
-      allowChunkedTransfers_ = allow;
-    }
-
-    bool IsChunkedTransfersAllowed() const
-    {
-      return allowChunkedTransfers_;
-    }
-
-    void Execute(IAnswer& answer);
-
-    void Execute(HttpHeaders& answerHeaders /* out */,
-                 std::string& answerBody /* out */);
-
-    void Execute(HttpHeaders& answerHeaders /* out */,
-                 Json::Value& answerBody /* out */);
-
-    void Execute();
-  };
-#endif
-
-
-
-  class IChunkedRequestReader : public boost::noncopyable
-  {
-  public:
-    virtual ~IChunkedRequestReader()
-    {
-    }
-
-    virtual void AddChunk(const void* data,
-                          size_t size) = 0;
-
-    virtual void Execute(OrthancPluginRestOutput* output) = 0;
-  };
-
-
-  typedef IChunkedRequestReader* (*ChunkedRestCallback) (const char* url,
-                                                         const OrthancPluginHttpRequest* request);
-
-
-  namespace Internals
-  {
-    void NullRestCallback(OrthancPluginRestOutput* output,
-                          const char* url,
-                          const OrthancPluginHttpRequest* request);
-  
-    IChunkedRequestReader *NullChunkedRestCallback(const char* url,
-                                                   const OrthancPluginHttpRequest* request);
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-    template <ChunkedRestCallback Callback>
-    static OrthancPluginErrorCode ChunkedProtect(OrthancPluginServerChunkedRequestReader** reader,
-                                                const char* url,
-                                                const OrthancPluginHttpRequest* request)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-        else
-        {
-          *reader = reinterpret_cast<OrthancPluginServerChunkedRequestReader*>(Callback(url, request));
-          if (*reader == NULL)
-          {
-            return OrthancPluginErrorCode_Plugin;
-          }
-          else
-          {
-            return OrthancPluginErrorCode_Success;
-          }
-        }
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    OrthancPluginErrorCode ChunkedRequestReaderAddChunk(
-      OrthancPluginServerChunkedRequestReader* reader,
-      const void*                              data,
-      uint32_t                                 size);
-
-    OrthancPluginErrorCode ChunkedRequestReaderExecute(
-      OrthancPluginServerChunkedRequestReader* reader,
-      OrthancPluginRestOutput*                 output);
-
-    void ChunkedRequestReaderFinalize(
-      OrthancPluginServerChunkedRequestReader* reader);
-
-#else  
-
-    OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                    const char* url,
-                                                    const OrthancPluginHttpRequest* request,
-                                                    RestCallback GetHandler,
-                                                    ChunkedRestCallback PostHandler,
-                                                    RestCallback DeleteHandler,
-                                                    ChunkedRestCallback PutHandler);
-
-    template<
-      RestCallback         GetHandler,
-      ChunkedRestCallback  PostHandler,
-      RestCallback         DeleteHandler,
-      ChunkedRestCallback  PutHandler
-      >
-    inline OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                           const char* url,
-                                                           const OrthancPluginHttpRequest* request)
-    {
-      return ChunkedRestCompatibility(output, url, request, GetHandler,
-                                      PostHandler, DeleteHandler, PutHandler);
-    }
-#endif
-  }
-
-
-
-  // NB: We use a templated class instead of a templated function, because
-  // default values are only available in functions since C++11
-  template<
-    RestCallback         GetHandler    = Internals::NullRestCallback,
-    ChunkedRestCallback  PostHandler   = Internals::NullChunkedRestCallback,
-    RestCallback         DeleteHandler = Internals::NullRestCallback,
-    ChunkedRestCallback  PutHandler    = Internals::NullChunkedRestCallback
-    >
-  class ChunkedRestRegistration : public boost::noncopyable
-  {
-  public:
-    static void Apply(const std::string& uri)
-    {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-      OrthancPluginRegisterChunkedRestCallback(
-        GetGlobalContext(), uri.c_str(),
-        GetHandler == Internals::NullRestCallback         ? NULL : Internals::Protect<GetHandler>,
-        PostHandler == Internals::NullChunkedRestCallback ? NULL : Internals::ChunkedProtect<PostHandler>,
-        DeleteHandler == Internals::NullRestCallback      ? NULL : Internals::Protect<DeleteHandler>,
-        PutHandler == Internals::NullChunkedRestCallback  ? NULL : Internals::ChunkedProtect<PutHandler>,
-        Internals::ChunkedRequestReaderAddChunk,
-        Internals::ChunkedRequestReaderExecute,
-        Internals::ChunkedRequestReaderFinalize);
-#else
-      OrthancPluginRegisterRestCallbackNoLock(
-        GetGlobalContext(), uri.c_str(), 
-        Internals::ChunkedRestCompatibility<GetHandler, PostHandler, DeleteHandler, PutHandler>);
-#endif
-    }
-  };
-
-  
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  class IStorageCommitmentScpHandler : public boost::noncopyable
-  {
-  public:
-    virtual ~IStorageCommitmentScpHandler()
-    {
-    }
-    
-    virtual OrthancPluginStorageCommitmentFailureReason Lookup(const std::string& sopClassUid,
-                                                               const std::string& sopInstanceUid) = 0;
-    
-    static OrthancPluginErrorCode Lookup(OrthancPluginStorageCommitmentFailureReason* target,
-                                         void* rawHandler,
-                                         const char* sopClassUid,
-                                         const char* sopInstanceUid);
-
-    static void Destructor(void* rawHandler);
-  };
-#endif
-
-
-  class DicomInstance : public boost::noncopyable
-  {
-  private:
-    bool toFree_;
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-    const OrthancPluginDicomInstance*  instance_;
-#else
-    OrthancPluginDicomInstance*  instance_;
-#endif
-    
-  public:
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-    DicomInstance(const OrthancPluginDicomInstance* instance);
-#else
-    DicomInstance(OrthancPluginDicomInstance* instance);
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    DicomInstance(const void* buffer,
-                  size_t size);
-#endif
-
-    ~DicomInstance();
-
-    std::string GetRemoteAet() const;
-
-    const void* GetBuffer() const
-    {
-      return OrthancPluginGetInstanceData(GetGlobalContext(), instance_);
-    }
-
-    size_t GetSize() const
-    {
-      return static_cast<size_t>(OrthancPluginGetInstanceSize(GetGlobalContext(), instance_));
-    }
-
-    void GetJson(Json::Value& target) const;
-
-    void GetSimplifiedJson(Json::Value& target) const;
-
-    OrthancPluginInstanceOrigin GetOrigin() const
-    {
-      return OrthancPluginGetInstanceOrigin(GetGlobalContext(), instance_);
-    }
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-    std::string GetTransferSyntaxUid() const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-    bool HasPixelData() const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    unsigned int GetFramesCount() const
-    {
-      return OrthancPluginGetInstanceFramesCount(GetGlobalContext(), instance_);
-    }
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    void GetRawFrame(std::string& target,
-                     unsigned int frameIndex) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    OrthancImage* GetDecodedFrame(unsigned int frameIndex) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    void Serialize(std::string& target) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    static DicomInstance* Transcode(const void* buffer,
-                                    size_t size,
-                                    const std::string& transferSyntax);
-#endif
-  };
-}
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginException.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#if !defined(HAS_ORTHANC_EXCEPTION)
-#  error The macro HAS_ORTHANC_EXCEPTION must be defined
-#endif
-
-
-#if HAS_ORTHANC_EXCEPTION == 1
-#  include <OrthancException.h>
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::Orthanc::ErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::Orthanc::OrthancException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::Orthanc::ErrorCode_ ## code
-#else
-#  include <orthanc/OrthancCPlugin.h>
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::OrthancPluginErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::OrthancPlugins::PluginException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::OrthancPluginErrorCode_ ## code
-#endif
-
-
-#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
-
-
-#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
-                                                  
-
-#define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
-  if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \
-  {                                                                 \
-    ORTHANC_PLUGINS_THROW_EXCEPTION(code);                          \
-  }
-
-
-namespace OrthancPlugins
-{
-#if HAS_ORTHANC_EXCEPTION == 0
-  class PluginException
-  {
-  private:
-    OrthancPluginErrorCode  code_;
-
-  public:
-    explicit PluginException(OrthancPluginErrorCode code) : code_(code)
-    {
-    }
-
-    OrthancPluginErrorCode GetErrorCode() const
-    {
-      return code_;
-    }
-
-    const char* What(OrthancPluginContext* context) const
-    {
-      const char* description = OrthancPluginGetErrorDescription(context, code_);
-      if (description)
-      {
-        return description;
-      }
-      else
-      {
-        return "No description available";
-      }
-    }
-  };
-#endif
-}
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, Belgium
-# Copyright (C) 2017-2020 Osimis S.A., Belgium
-#
-# This program is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-# In Orthanc <= 1.7.1, the instructions below were part of
-# "Compiler.cmake", and were protected by the (now unused) option
-# "ENABLE_PLUGINS_VERSION_SCRIPT" in CMake
-
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/VersionScriptPlugins.map")
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${CMAKE_CURRENT_LIST_DIR}/ExportedSymbolsPlugins.list")
-endif()
--- a/Applications/Samples/RtViewerPlugin/Resources/Orthanc/Plugins/VersionScriptPlugins.map	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-# This is a version-script for Orthanc plugins
-
-{
-global:
-  OrthancPluginInitialize;
-  OrthancPluginFinalize;
-  OrthancPluginGetName;
-  OrthancPluginGetVersion;
-
-local:
-  *;
-};
--- a/Applications/Samples/RtViewerPlugin/Resources/OrthancSdk-1.0.0/orthanc/OrthancCPlugin.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4740 +0,0 @@
-/**
- * \mainpage
- *
- * This C/C++ SDK allows external developers to create plugins that
- * can be loaded into Orthanc to extend its functionality. Each
- * Orthanc plugin must expose 4 public functions with the following
- * signatures:
- * 
- * -# <tt>int32_t OrthancPluginInitialize(const OrthancPluginContext* context)</tt>:
- *    This function is invoked by Orthanc when it loads the plugin on startup.
- *    The plugin must:
- *    - Check its compatibility with the Orthanc version using
- *      ::OrthancPluginCheckVersion().
- *    - Store the context pointer so that it can use the plugin 
- *      services of Orthanc.
- *    - Register all its REST callbacks using ::OrthancPluginRegisterRestCallback().
- *    - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback().
- *    - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback().
- *    - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea().
- *    - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2().
- *    - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback().
- *    - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback().
- * -# <tt>void OrthancPluginFinalize()</tt>:
- *    This function is invoked by Orthanc during its shutdown. The plugin
- *    must free all its memory.
- * -# <tt>const char* OrthancPluginGetName()</tt>:
- *    The plugin must return a short string to identify itself.
- * -# <tt>const char* OrthancPluginGetVersion()</tt>:
- *    The plugin must return a string containing its version number.
- *
- * The name and the version of a plugin is only used to prevent it
- * from being loaded twice. Note that, in C++, it is mandatory to
- * declare these functions within an <tt>extern "C"</tt> section.
- * 
- * To ensure multi-threading safety, the various REST callbacks are
- * guaranteed to be executed in mutual exclusion since Orthanc
- * 0.8.5. If this feature is undesired (notably when developing
- * high-performance plugins handling simultaneous requests), use
- * ::OrthancPluginRegisterRestCallbackNoLock().
- **/
-
-
-
-/**
- * @defgroup Images Images and compression
- * @brief Functions to deal with images and compressed buffers.
- *
- * @defgroup REST REST
- * @brief Functions to answer REST requests in a callback.
- *
- * @defgroup Callbacks Callbacks
- * @brief Functions to register and manage callbacks by the plugins.
- *
- * @defgroup Worklists Worklists
- * @brief Functions to register and manage worklists.
- *
- * @defgroup Orthanc Orthanc
- * @brief Functions to access the content of the Orthanc server.
- **/
-
-
-
-/**
- * @defgroup Toolbox Toolbox
- * @brief Generic functions to help with the creation of plugins.
- **/
-
-
-
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders of this
- * program give permission to link the code of its release with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify file(s) with this exception, you may extend this exception to
- * your version of the file(s), but you are not obligated to do so. If
- * you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files
- * in the program, then also delete it here.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-
-#pragma once
-
-
-#include <stdio.h>
-#include <string.h>
-
-#ifdef WIN32
-#define ORTHANC_PLUGINS_API __declspec(dllexport)
-#else
-#define ORTHANC_PLUGINS_API
-#endif
-
-#define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER     1
-#define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER     0
-#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER  0
-
-
-
-/********************************************************************
- ** Check that function inlining is properly supported. The use of
- ** inlining is required, to avoid the duplication of object code
- ** between two compilation modules that would use the Orthanc Plugin
- ** API.
- ********************************************************************/
-
-/* If the auto-detection of the "inline" keyword below does not work
-   automatically and that your compiler is known to properly support
-   inlining, uncomment the following #define and adapt the definition
-   of "static inline". */
-
-/* #define ORTHANC_PLUGIN_INLINE static inline */
-
-#ifndef ORTHANC_PLUGIN_INLINE
-#  if __STDC_VERSION__ >= 199901L
-/*   This is C99 or above: http://predef.sourceforge.net/prestd.html */
-#    define ORTHANC_PLUGIN_INLINE static inline
-#  elif defined(__cplusplus)
-/*   This is C++ */
-#    define ORTHANC_PLUGIN_INLINE static inline
-#  elif defined(__GNUC__)
-/*   This is GCC running in C89 mode */
-#    define ORTHANC_PLUGIN_INLINE static __inline
-#  elif defined(_MSC_VER)
-/*   This is Visual Studio running in C89 mode */
-#    define ORTHANC_PLUGIN_INLINE static __inline
-#  else
-#    error Your compiler is not known to support the "inline" keyword
-#  endif
-#endif
-
-
-
-/********************************************************************
- ** Inclusion of standard libraries.
- ********************************************************************/
-
-/**
- * For Microsoft Visual Studio, a compatibility "stdint.h" can be
- * downloaded at the following URL:
- * https://orthanc.googlecode.com/hg/Resources/ThirdParty/VisualStudio/stdint.h
- **/
-#include <stdint.h>
-
-#include <stdlib.h>
-
-
-
-/********************************************************************
- ** Definition of the Orthanc Plugin API.
- ********************************************************************/
-
-/** @{ */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-  /**
-   * The various error codes that can be returned by the Orthanc core.
-   **/
-  typedef enum
-  {
-    OrthancPluginErrorCode_InternalError = -1    /*!< Internal error */,
-    OrthancPluginErrorCode_Success = 0    /*!< Success */,
-    OrthancPluginErrorCode_Plugin = 1    /*!< Error encountered within the plugin engine */,
-    OrthancPluginErrorCode_NotImplemented = 2    /*!< Not implemented yet */,
-    OrthancPluginErrorCode_ParameterOutOfRange = 3    /*!< Parameter out of range */,
-    OrthancPluginErrorCode_NotEnoughMemory = 4    /*!< Not enough memory */,
-    OrthancPluginErrorCode_BadParameterType = 5    /*!< Bad type for a parameter */,
-    OrthancPluginErrorCode_BadSequenceOfCalls = 6    /*!< Bad sequence of calls */,
-    OrthancPluginErrorCode_InexistentItem = 7    /*!< Accessing an inexistent item */,
-    OrthancPluginErrorCode_BadRequest = 8    /*!< Bad request */,
-    OrthancPluginErrorCode_NetworkProtocol = 9    /*!< Error in the network protocol */,
-    OrthancPluginErrorCode_SystemCommand = 10    /*!< Error while calling a system command */,
-    OrthancPluginErrorCode_Database = 11    /*!< Error with the database engine */,
-    OrthancPluginErrorCode_UriSyntax = 12    /*!< Badly formatted URI */,
-    OrthancPluginErrorCode_InexistentFile = 13    /*!< Inexistent file */,
-    OrthancPluginErrorCode_CannotWriteFile = 14    /*!< Cannot write to file */,
-    OrthancPluginErrorCode_BadFileFormat = 15    /*!< Bad file format */,
-    OrthancPluginErrorCode_Timeout = 16    /*!< Timeout */,
-    OrthancPluginErrorCode_UnknownResource = 17    /*!< Unknown resource */,
-    OrthancPluginErrorCode_IncompatibleDatabaseVersion = 18    /*!< Incompatible version of the database */,
-    OrthancPluginErrorCode_FullStorage = 19    /*!< The file storage is full */,
-    OrthancPluginErrorCode_CorruptedFile = 20    /*!< Corrupted file (e.g. inconsistent MD5 hash) */,
-    OrthancPluginErrorCode_InexistentTag = 21    /*!< Inexistent tag */,
-    OrthancPluginErrorCode_ReadOnly = 22    /*!< Cannot modify a read-only data structure */,
-    OrthancPluginErrorCode_IncompatibleImageFormat = 23    /*!< Incompatible format of the images */,
-    OrthancPluginErrorCode_IncompatibleImageSize = 24    /*!< Incompatible size of the images */,
-    OrthancPluginErrorCode_SharedLibrary = 25    /*!< Error while using a shared library (plugin) */,
-    OrthancPluginErrorCode_UnknownPluginService = 26    /*!< Plugin invoking an unknown service */,
-    OrthancPluginErrorCode_UnknownDicomTag = 27    /*!< Unknown DICOM tag */,
-    OrthancPluginErrorCode_BadJson = 28    /*!< Cannot parse a JSON document */,
-    OrthancPluginErrorCode_Unauthorized = 29    /*!< Bad credentials were provided to an HTTP request */,
-    OrthancPluginErrorCode_BadFont = 30    /*!< Badly formatted font file */,
-    OrthancPluginErrorCode_DatabasePlugin = 31    /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */,
-    OrthancPluginErrorCode_StorageAreaPlugin = 32    /*!< Error in the plugin implementing a custom storage area */,
-    OrthancPluginErrorCode_EmptyRequest = 33    /*!< The request is empty */,
-    OrthancPluginErrorCode_NotAcceptable = 34    /*!< Cannot send a response which is acceptable according to the Accept HTTP header */,
-    OrthancPluginErrorCode_SQLiteNotOpened = 1000    /*!< SQLite: The database is not opened */,
-    OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001    /*!< SQLite: Connection is already open */,
-    OrthancPluginErrorCode_SQLiteCannotOpen = 1002    /*!< SQLite: Unable to open the database */,
-    OrthancPluginErrorCode_SQLiteStatementAlreadyUsed = 1003    /*!< SQLite: This cached statement is already being referred to */,
-    OrthancPluginErrorCode_SQLiteExecute = 1004    /*!< SQLite: Cannot execute a command */,
-    OrthancPluginErrorCode_SQLiteRollbackWithoutTransaction = 1005    /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */,
-    OrthancPluginErrorCode_SQLiteCommitWithoutTransaction = 1006    /*!< SQLite: Committing a nonexistent transaction */,
-    OrthancPluginErrorCode_SQLiteRegisterFunction = 1007    /*!< SQLite: Unable to register a function */,
-    OrthancPluginErrorCode_SQLiteFlush = 1008    /*!< SQLite: Unable to flush the database */,
-    OrthancPluginErrorCode_SQLiteCannotRun = 1009    /*!< SQLite: Cannot run a cached statement */,
-    OrthancPluginErrorCode_SQLiteCannotStep = 1010    /*!< SQLite: Cannot step over a cached statement */,
-    OrthancPluginErrorCode_SQLiteBindOutOfRange = 1011    /*!< SQLite: Bing a value while out of range (serious error) */,
-    OrthancPluginErrorCode_SQLitePrepareStatement = 1012    /*!< SQLite: Cannot prepare a cached statement */,
-    OrthancPluginErrorCode_SQLiteTransactionAlreadyStarted = 1013    /*!< SQLite: Beginning the same transaction twice */,
-    OrthancPluginErrorCode_SQLiteTransactionCommit = 1014    /*!< SQLite: Failure when committing the transaction */,
-    OrthancPluginErrorCode_SQLiteTransactionBegin = 1015    /*!< SQLite: Cannot start a transaction */,
-    OrthancPluginErrorCode_DirectoryOverFile = 2000    /*!< The directory to be created is already occupied by a regular file */,
-    OrthancPluginErrorCode_FileStorageCannotWrite = 2001    /*!< Unable to create a subdirectory or a file in the file storage */,
-    OrthancPluginErrorCode_DirectoryExpected = 2002    /*!< The specified path does not point to a directory */,
-    OrthancPluginErrorCode_HttpPortInUse = 2003    /*!< The TCP port of the HTTP server is already in use */,
-    OrthancPluginErrorCode_DicomPortInUse = 2004    /*!< The TCP port of the DICOM server is already in use */,
-    OrthancPluginErrorCode_BadHttpStatusInRest = 2005    /*!< This HTTP status is not allowed in a REST API */,
-    OrthancPluginErrorCode_RegularFileExpected = 2006    /*!< The specified path does not point to a regular file */,
-    OrthancPluginErrorCode_PathToExecutable = 2007    /*!< Unable to get the path to the executable */,
-    OrthancPluginErrorCode_MakeDirectory = 2008    /*!< Cannot create a directory */,
-    OrthancPluginErrorCode_BadApplicationEntityTitle = 2009    /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */,
-    OrthancPluginErrorCode_NoCFindHandler = 2010    /*!< No request handler factory for DICOM C-FIND SCP */,
-    OrthancPluginErrorCode_NoCMoveHandler = 2011    /*!< No request handler factory for DICOM C-MOVE SCP */,
-    OrthancPluginErrorCode_NoCStoreHandler = 2012    /*!< No request handler factory for DICOM C-STORE SCP */,
-    OrthancPluginErrorCode_NoApplicationEntityFilter = 2013    /*!< No application entity filter */,
-    OrthancPluginErrorCode_NoSopClassOrInstance = 2014    /*!< DicomUserConnection: Unable to find the SOP class and instance */,
-    OrthancPluginErrorCode_NoPresentationContext = 2015    /*!< DicomUserConnection: No acceptable presentation context for modality */,
-    OrthancPluginErrorCode_DicomFindUnavailable = 2016    /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */,
-    OrthancPluginErrorCode_DicomMoveUnavailable = 2017    /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */,
-    OrthancPluginErrorCode_CannotStoreInstance = 2018    /*!< Cannot store an instance */,
-    OrthancPluginErrorCode_CreateDicomNotString = 2019    /*!< Only string values are supported when creating DICOM instances */,
-    OrthancPluginErrorCode_CreateDicomOverrideTag = 2020    /*!< Trying to override a value inherited from a parent module */,
-    OrthancPluginErrorCode_CreateDicomUseContent = 2021    /*!< Use \"Content\" to inject an image into a new DICOM instance */,
-    OrthancPluginErrorCode_CreateDicomNoPayload = 2022    /*!< No payload is present for one instance in the series */,
-    OrthancPluginErrorCode_CreateDicomUseDataUriScheme = 2023    /*!< The payload of the DICOM instance must be specified according to Data URI scheme */,
-    OrthancPluginErrorCode_CreateDicomBadParent = 2024    /*!< Trying to attach a new DICOM instance to an inexistent resource */,
-    OrthancPluginErrorCode_CreateDicomParentIsInstance = 2025    /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */,
-    OrthancPluginErrorCode_CreateDicomParentEncoding = 2026    /*!< Unable to get the encoding of the parent resource */,
-    OrthancPluginErrorCode_UnknownModality = 2027    /*!< Unknown modality */,
-    OrthancPluginErrorCode_BadJobOrdering = 2028    /*!< Bad ordering of filters in a job */,
-    OrthancPluginErrorCode_JsonToLuaTable = 2029    /*!< Cannot convert the given JSON object to a Lua table */,
-    OrthancPluginErrorCode_CannotCreateLua = 2030    /*!< Cannot create the Lua context */,
-    OrthancPluginErrorCode_CannotExecuteLua = 2031    /*!< Cannot execute a Lua command */,
-    OrthancPluginErrorCode_LuaAlreadyExecuted = 2032    /*!< Arguments cannot be pushed after the Lua function is executed */,
-    OrthancPluginErrorCode_LuaBadOutput = 2033    /*!< The Lua function does not give the expected number of outputs */,
-    OrthancPluginErrorCode_NotLuaPredicate = 2034    /*!< The Lua function is not a predicate (only true/false outputs allowed) */,
-    OrthancPluginErrorCode_LuaReturnsNoString = 2035    /*!< The Lua function does not return a string */,
-    OrthancPluginErrorCode_StorageAreaAlreadyRegistered = 2036    /*!< Another plugin has already registered a custom storage area */,
-    OrthancPluginErrorCode_DatabaseBackendAlreadyRegistered = 2037    /*!< Another plugin has already registered a custom database back-end */,
-    OrthancPluginErrorCode_DatabaseNotInitialized = 2038    /*!< Plugin trying to call the database during its initialization */,
-    OrthancPluginErrorCode_SslDisabled = 2039    /*!< Orthanc has been built without SSL support */,
-    OrthancPluginErrorCode_CannotOrderSlices = 2040    /*!< Unable to order the slices of the series */,
-    OrthancPluginErrorCode_NoWorklistHandler = 2041    /*!< No request handler factory for DICOM C-Find Modality SCP */,
-
-    _OrthancPluginErrorCode_INTERNAL = 0x7fffffff
-  } OrthancPluginErrorCode;
-
-
-  /**
-   * Forward declaration of one of the mandatory functions for Orthanc
-   * plugins.
-   **/
-  ORTHANC_PLUGINS_API const char* OrthancPluginGetName();
-
-
-  /**
-   * The various HTTP methods for a REST call.
-   **/
-  typedef enum
-  {
-    OrthancPluginHttpMethod_Get = 1,    /*!< GET request */
-    OrthancPluginHttpMethod_Post = 2,   /*!< POST request */
-    OrthancPluginHttpMethod_Put = 3,    /*!< PUT request */
-    OrthancPluginHttpMethod_Delete = 4, /*!< DELETE request */
-
-    _OrthancPluginHttpMethod_INTERNAL = 0x7fffffff
-  } OrthancPluginHttpMethod;
-
-
-  /**
-   * @brief The parameters of a REST request.
-   * @ingroup Callbacks
-   **/
-  typedef struct
-  {
-    /**
-     * @brief The HTTP method.
-     **/
-    OrthancPluginHttpMethod method;    
-
-    /**
-     * @brief The number of groups of the regular expression.
-     **/
-    uint32_t                groupsCount;
-
-    /**
-     * @brief The matched values for the groups of the regular expression.
-     **/
-    const char* const*      groups;
-
-    /**
-     * @brief For a GET request, the number of GET parameters.
-     **/
-    uint32_t                getCount;
-
-    /**
-     * @brief For a GET request, the keys of the GET parameters.
-     **/
-    const char* const*      getKeys;
-
-    /**
-     * @brief For a GET request, the values of the GET parameters.
-     **/
-    const char* const*      getValues;
-
-    /**
-     * @brief For a PUT or POST request, the content of the body.
-     **/
-    const char*             body;
-
-    /**
-     * @brief For a PUT or POST request, the number of bytes of the body.
-     **/
-    uint32_t                bodySize;
-
-
-    /* --------------------------------------------------
-       New in version 0.8.1
-       -------------------------------------------------- */
-
-    /**
-     * @brief The number of HTTP headers.
-     **/
-    uint32_t                headersCount;
-
-    /**
-     * @brief The keys of the HTTP headers (always converted to low-case).
-     **/
-    const char* const*      headersKeys;
-
-    /**
-     * @brief The values of the HTTP headers.
-     **/
-    const char* const*      headersValues;
-
-  } OrthancPluginHttpRequest;
-
-
-  typedef enum 
-  {
-    /* Generic services */
-    _OrthancPluginService_LogInfo = 1,
-    _OrthancPluginService_LogWarning = 2,
-    _OrthancPluginService_LogError = 3,
-    _OrthancPluginService_GetOrthancPath = 4,
-    _OrthancPluginService_GetOrthancDirectory = 5,
-    _OrthancPluginService_GetConfigurationPath = 6,
-    _OrthancPluginService_SetPluginProperty = 7,
-    _OrthancPluginService_GetGlobalProperty = 8,
-    _OrthancPluginService_SetGlobalProperty = 9,
-    _OrthancPluginService_GetCommandLineArgumentsCount = 10,
-    _OrthancPluginService_GetCommandLineArgument = 11,
-    _OrthancPluginService_GetExpectedDatabaseVersion = 12,
-    _OrthancPluginService_GetConfiguration = 13,
-    _OrthancPluginService_BufferCompression = 14,
-    _OrthancPluginService_ReadFile = 15,
-    _OrthancPluginService_WriteFile = 16,
-    _OrthancPluginService_GetErrorDescription = 17,
-    _OrthancPluginService_CallHttpClient = 18,
-    _OrthancPluginService_RegisterErrorCode = 19,
-    _OrthancPluginService_RegisterDictionaryTag = 20,
-    _OrthancPluginService_DicomBufferToJson = 21,
-    _OrthancPluginService_DicomInstanceToJson = 22,
-    _OrthancPluginService_CreateDicom = 23,
-    _OrthancPluginService_ComputeMd5 = 24,
-    _OrthancPluginService_ComputeSha1 = 25,
-    _OrthancPluginService_LookupDictionary = 26,
-
-    /* Registration of callbacks */
-    _OrthancPluginService_RegisterRestCallback = 1000,
-    _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001,
-    _OrthancPluginService_RegisterStorageArea = 1002,
-    _OrthancPluginService_RegisterOnChangeCallback = 1003,
-    _OrthancPluginService_RegisterRestCallbackNoLock = 1004,
-    _OrthancPluginService_RegisterWorklistCallback = 1005,
-    _OrthancPluginService_RegisterDecodeImageCallback = 1006,
-
-    /* Sending answers to REST calls */
-    _OrthancPluginService_AnswerBuffer = 2000,
-    _OrthancPluginService_CompressAndAnswerPngImage = 2001,  /* Unused as of Orthanc 0.9.4 */
-    _OrthancPluginService_Redirect = 2002,
-    _OrthancPluginService_SendHttpStatusCode = 2003,
-    _OrthancPluginService_SendUnauthorized = 2004,
-    _OrthancPluginService_SendMethodNotAllowed = 2005,
-    _OrthancPluginService_SetCookie = 2006,
-    _OrthancPluginService_SetHttpHeader = 2007,
-    _OrthancPluginService_StartMultipartAnswer = 2008,
-    _OrthancPluginService_SendMultipartItem = 2009,
-    _OrthancPluginService_SendHttpStatus = 2010,
-    _OrthancPluginService_CompressAndAnswerImage = 2011,
-    _OrthancPluginService_SendMultipartItem2 = 2012,
-
-    /* Access to the Orthanc database and API */
-    _OrthancPluginService_GetDicomForInstance = 3000,
-    _OrthancPluginService_RestApiGet = 3001,
-    _OrthancPluginService_RestApiPost = 3002,
-    _OrthancPluginService_RestApiDelete = 3003,
-    _OrthancPluginService_RestApiPut = 3004,
-    _OrthancPluginService_LookupPatient = 3005,
-    _OrthancPluginService_LookupStudy = 3006,
-    _OrthancPluginService_LookupSeries = 3007,
-    _OrthancPluginService_LookupInstance = 3008,
-    _OrthancPluginService_LookupStudyWithAccessionNumber = 3009,
-    _OrthancPluginService_RestApiGetAfterPlugins = 3010,
-    _OrthancPluginService_RestApiPostAfterPlugins = 3011,
-    _OrthancPluginService_RestApiDeleteAfterPlugins = 3012,
-    _OrthancPluginService_RestApiPutAfterPlugins = 3013,
-    _OrthancPluginService_ReconstructMainDicomTags = 3014,
-    _OrthancPluginService_RestApiGet2 = 3015,
-
-    /* Access to DICOM instances */
-    _OrthancPluginService_GetInstanceRemoteAet = 4000,
-    _OrthancPluginService_GetInstanceSize = 4001,
-    _OrthancPluginService_GetInstanceData = 4002,
-    _OrthancPluginService_GetInstanceJson = 4003,
-    _OrthancPluginService_GetInstanceSimplifiedJson = 4004,
-    _OrthancPluginService_HasInstanceMetadata = 4005,
-    _OrthancPluginService_GetInstanceMetadata = 4006,
-    _OrthancPluginService_GetInstanceOrigin = 4007,
-
-    /* Services for plugins implementing a database back-end */
-    _OrthancPluginService_RegisterDatabaseBackend = 5000,
-    _OrthancPluginService_DatabaseAnswer = 5001,
-    _OrthancPluginService_RegisterDatabaseBackendV2 = 5002,
-    _OrthancPluginService_StorageAreaCreate = 5003,
-    _OrthancPluginService_StorageAreaRead = 5004,
-    _OrthancPluginService_StorageAreaRemove = 5005,
-
-    /* Primitives for handling images */
-    _OrthancPluginService_GetImagePixelFormat = 6000,
-    _OrthancPluginService_GetImageWidth = 6001,
-    _OrthancPluginService_GetImageHeight = 6002,
-    _OrthancPluginService_GetImagePitch = 6003,
-    _OrthancPluginService_GetImageBuffer = 6004,
-    _OrthancPluginService_UncompressImage = 6005,
-    _OrthancPluginService_FreeImage = 6006,
-    _OrthancPluginService_CompressImage = 6007,
-    _OrthancPluginService_ConvertPixelFormat = 6008,
-    _OrthancPluginService_GetFontsCount = 6009,
-    _OrthancPluginService_GetFontInfo = 6010,
-    _OrthancPluginService_DrawText = 6011,
-    _OrthancPluginService_CreateImage = 6012,
-    _OrthancPluginService_CreateImageAccessor = 6013,
-    _OrthancPluginService_DecodeDicomImage = 6014,
-
-    /* Primitives for handling worklists */
-    _OrthancPluginService_WorklistAddAnswer = 7000,
-    _OrthancPluginService_WorklistMarkIncomplete = 7001,
-    _OrthancPluginService_WorklistIsMatch = 7002,
-    _OrthancPluginService_WorklistGetDicomQuery = 7003,
-
-    _OrthancPluginService_INTERNAL = 0x7fffffff
-  } _OrthancPluginService;
-
-
-  typedef enum
-  {
-    _OrthancPluginProperty_Description = 1,
-    _OrthancPluginProperty_RootUri = 2,
-    _OrthancPluginProperty_OrthancExplorer = 3,
-
-    _OrthancPluginProperty_INTERNAL = 0x7fffffff
-  } _OrthancPluginProperty;
-
-
-
-  /**
-   * The memory layout of the pixels of an image.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    /**
-     * @brief Graylevel 8bpp image.
-     *
-     * The image is graylevel. Each pixel is unsigned and stored in
-     * one byte.
-     **/
-    OrthancPluginPixelFormat_Grayscale8 = 1,
-
-    /**
-     * @brief Graylevel, unsigned 16bpp image.
-     *
-     * The image is graylevel. Each pixel is unsigned and stored in
-     * two bytes.
-     **/
-    OrthancPluginPixelFormat_Grayscale16 = 2,
-
-    /**
-     * @brief Graylevel, signed 16bpp image.
-     *
-     * The image is graylevel. Each pixel is signed and stored in two
-     * bytes.
-     **/
-    OrthancPluginPixelFormat_SignedGrayscale16 = 3,
-
-    /**
-     * @brief Color image in RGB24 format.
-     *
-     * This format describes a color image. The pixels are stored in 3
-     * consecutive bytes. The memory layout is RGB.
-     **/
-    OrthancPluginPixelFormat_RGB24 = 4,
-
-    /**
-     * @brief Color image in RGBA32 format.
-     *
-     * This format describes a color image. The pixels are stored in 4
-     * consecutive bytes. The memory layout is RGBA.
-     **/
-    OrthancPluginPixelFormat_RGBA32 = 5,
-
-    OrthancPluginPixelFormat_Unknown = 6,   /*!< Unknown pixel format */
-
-    _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginPixelFormat;
-
-
-
-  /**
-   * The content types that are supported by Orthanc plugins.
-   **/
-  typedef enum
-  {
-    OrthancPluginContentType_Unknown = 0,      /*!< Unknown content type */
-    OrthancPluginContentType_Dicom = 1,        /*!< DICOM */
-    OrthancPluginContentType_DicomAsJson = 2,  /*!< JSON summary of a DICOM file */
-
-    _OrthancPluginContentType_INTERNAL = 0x7fffffff
-  } OrthancPluginContentType;
-
-
-
-  /**
-   * The supported types of DICOM resources.
-   **/
-  typedef enum
-  {
-    OrthancPluginResourceType_Patient = 0,     /*!< Patient */
-    OrthancPluginResourceType_Study = 1,       /*!< Study */
-    OrthancPluginResourceType_Series = 2,      /*!< Series */
-    OrthancPluginResourceType_Instance = 3,    /*!< Instance */
-    OrthancPluginResourceType_None = 4,        /*!< Unavailable resource type */
-
-    _OrthancPluginResourceType_INTERNAL = 0x7fffffff
-  } OrthancPluginResourceType;
-
-
-
-  /**
-   * The supported types of changes that can happen to DICOM resources.
-   * @ingroup Callbacks
-   **/
-  typedef enum
-  {
-    OrthancPluginChangeType_CompletedSeries = 0,    /*!< Series is now complete */
-    OrthancPluginChangeType_Deleted = 1,            /*!< Deleted resource */
-    OrthancPluginChangeType_NewChildInstance = 2,   /*!< A new instance was added to this resource */
-    OrthancPluginChangeType_NewInstance = 3,        /*!< New instance received */
-    OrthancPluginChangeType_NewPatient = 4,         /*!< New patient created */
-    OrthancPluginChangeType_NewSeries = 5,          /*!< New series created */
-    OrthancPluginChangeType_NewStudy = 6,           /*!< New study created */
-    OrthancPluginChangeType_StablePatient = 7,      /*!< Timeout: No new instance in this patient */
-    OrthancPluginChangeType_StableSeries = 8,       /*!< Timeout: No new instance in this series */
-    OrthancPluginChangeType_StableStudy = 9,        /*!< Timeout: No new instance in this study */
-    OrthancPluginChangeType_OrthancStarted = 10,    /*!< Orthanc has started */
-    OrthancPluginChangeType_OrthancStopped = 11,    /*!< Orthanc is stopping */
-    OrthancPluginChangeType_UpdatedAttachment = 12, /*!< Some user-defined attachment has changed for this resource */
-    OrthancPluginChangeType_UpdatedMetadata = 13,   /*!< Some user-defined metadata has changed for this resource */
-
-    _OrthancPluginChangeType_INTERNAL = 0x7fffffff
-  } OrthancPluginChangeType;
-
-
-  /**
-   * The compression algorithms that are supported by the Orthanc core.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    OrthancPluginCompressionType_Zlib = 0,          /*!< Standard zlib compression */
-    OrthancPluginCompressionType_ZlibWithSize = 1,  /*!< zlib, prefixed with uncompressed size (uint64_t) */
-    OrthancPluginCompressionType_Gzip = 2,          /*!< Standard gzip compression */
-    OrthancPluginCompressionType_GzipWithSize = 3,  /*!< gzip, prefixed with uncompressed size (uint64_t) */
-
-    _OrthancPluginCompressionType_INTERNAL = 0x7fffffff
-  } OrthancPluginCompressionType;
-
-
-  /**
-   * The image formats that are supported by the Orthanc core.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    OrthancPluginImageFormat_Png = 0,    /*!< Image compressed using PNG */
-    OrthancPluginImageFormat_Jpeg = 1,   /*!< Image compressed using JPEG */
-    OrthancPluginImageFormat_Dicom = 2,  /*!< Image compressed using DICOM */
-
-    _OrthancPluginImageFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginImageFormat;
-
-
-  /**
-   * The value representations present in the DICOM standard (version 2013).
-   * @ingroup Toolbox
-   **/
-  typedef enum
-  {
-    OrthancPluginValueRepresentation_AE = 1,   /*!< Application Entity */
-    OrthancPluginValueRepresentation_AS = 2,   /*!< Age String */
-    OrthancPluginValueRepresentation_AT = 3,   /*!< Attribute Tag */
-    OrthancPluginValueRepresentation_CS = 4,   /*!< Code String */
-    OrthancPluginValueRepresentation_DA = 5,   /*!< Date */
-    OrthancPluginValueRepresentation_DS = 6,   /*!< Decimal String */
-    OrthancPluginValueRepresentation_DT = 7,   /*!< Date Time */
-    OrthancPluginValueRepresentation_FD = 8,   /*!< Floating Point Double */
-    OrthancPluginValueRepresentation_FL = 9,   /*!< Floating Point Single */
-    OrthancPluginValueRepresentation_IS = 10,  /*!< Integer String */
-    OrthancPluginValueRepresentation_LO = 11,  /*!< Long String */
-    OrthancPluginValueRepresentation_LT = 12,  /*!< Long Text */
-    OrthancPluginValueRepresentation_OB = 13,  /*!< Other Byte String */
-    OrthancPluginValueRepresentation_OF = 14,  /*!< Other Float String */
-    OrthancPluginValueRepresentation_OW = 15,  /*!< Other Word String */
-    OrthancPluginValueRepresentation_PN = 16,  /*!< Person Name */
-    OrthancPluginValueRepresentation_SH = 17,  /*!< Short String */
-    OrthancPluginValueRepresentation_SL = 18,  /*!< Signed Long */
-    OrthancPluginValueRepresentation_SQ = 19,  /*!< Sequence of Items */
-    OrthancPluginValueRepresentation_SS = 20,  /*!< Signed Short */
-    OrthancPluginValueRepresentation_ST = 21,  /*!< Short Text */
-    OrthancPluginValueRepresentation_TM = 22,  /*!< Time */
-    OrthancPluginValueRepresentation_UI = 23,  /*!< Unique Identifier (UID) */
-    OrthancPluginValueRepresentation_UL = 24,  /*!< Unsigned Long */
-    OrthancPluginValueRepresentation_UN = 25,  /*!< Unknown */
-    OrthancPluginValueRepresentation_US = 26,  /*!< Unsigned Short */
-    OrthancPluginValueRepresentation_UT = 27,  /*!< Unlimited Text */
-
-    _OrthancPluginValueRepresentation_INTERNAL = 0x7fffffff
-  } OrthancPluginValueRepresentation;
-
-
-  /**
-   * The possible output formats for a DICOM-to-JSON conversion.
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomToJson()
-   **/
-  typedef enum
-  {
-    OrthancPluginDicomToJsonFormat_Full = 1,    /*!< Full output, with most details */
-    OrthancPluginDicomToJsonFormat_Short = 2,   /*!< Tags output as hexadecimal numbers */
-    OrthancPluginDicomToJsonFormat_Human = 3,   /*!< Human-readable JSON */
-
-    _OrthancPluginDicomToJsonFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginDicomToJsonFormat;
-
-
-  /**
-   * Flags to customize a DICOM-to-JSON conversion. By default, binary
-   * tags are formatted using Data URI scheme.
-   * @ingroup Toolbox
-   **/
-  typedef enum
-  {
-    OrthancPluginDicomToJsonFlags_IncludeBinary         = (1 << 0),  /*!< Include the binary tags */
-    OrthancPluginDicomToJsonFlags_IncludePrivateTags    = (1 << 1),  /*!< Include the private tags */
-    OrthancPluginDicomToJsonFlags_IncludeUnknownTags    = (1 << 2),  /*!< Include the tags unknown by the dictionary */
-    OrthancPluginDicomToJsonFlags_IncludePixelData      = (1 << 3),  /*!< Include the pixel data */
-    OrthancPluginDicomToJsonFlags_ConvertBinaryToAscii  = (1 << 4),  /*!< Output binary tags as-is, dropping non-ASCII */
-    OrthancPluginDicomToJsonFlags_ConvertBinaryToNull   = (1 << 5),  /*!< Signal binary tags as null values */
-
-    _OrthancPluginDicomToJsonFlags_INTERNAL = 0x7fffffff
-  } OrthancPluginDicomToJsonFlags;
-
-
-  /**
-   * Flags to the creation of a DICOM file.
-   * @ingroup Toolbox
-   * @see OrthancPluginCreateDicom()
-   **/
-  typedef enum
-  {
-    OrthancPluginCreateDicomFlags_DecodeDataUriScheme   = (1 << 0),  /*!< Decode fields encoded using data URI scheme */
-    OrthancPluginCreateDicomFlags_GenerateIdentifiers   = (1 << 1),  /*!< Automatically generate DICOM identifiers */
-
-    _OrthancPluginCreateDicomFlags_INTERNAL = 0x7fffffff
-  } OrthancPluginCreateDicomFlags;
-
-
-  /**
-   * The constraints on the DICOM identifiers that must be supported
-   * by the database plugins.
-   **/
-  typedef enum
-  {
-    OrthancPluginIdentifierConstraint_Equal = 1,           /*!< Equal */
-    OrthancPluginIdentifierConstraint_SmallerOrEqual = 2,  /*!< Less or equal */
-    OrthancPluginIdentifierConstraint_GreaterOrEqual = 3,  /*!< More or equal */
-    OrthancPluginIdentifierConstraint_Wildcard = 4,        /*!< Case-sensitive wildcard matching (with * and ?) */
-
-    _OrthancPluginIdentifierConstraint_INTERNAL = 0x7fffffff
-  } OrthancPluginIdentifierConstraint;
-
-
-  /**
-   * The origin of a DICOM instance that has been received by Orthanc.
-   **/
-  typedef enum
-  {
-    OrthancPluginInstanceOrigin_Unknown = 1,        /*!< Unknown origin */
-    OrthancPluginInstanceOrigin_DicomProtocol = 2,  /*!< Instance received through DICOM protocol */
-    OrthancPluginInstanceOrigin_RestApi = 3,        /*!< Instance received through REST API of Orthanc */
-    OrthancPluginInstanceOrigin_Plugin = 4,         /*!< Instance added to Orthanc by a plugin */
-    OrthancPluginInstanceOrigin_Lua = 5,            /*!< Instance added to Orthanc by a Lua script */
-
-    _OrthancPluginInstanceOrigin_INTERNAL = 0x7fffffff
-  } OrthancPluginInstanceOrigin;
-
-
-  /**
-   * @brief A memory buffer allocated by the core system of Orthanc.
-   *
-   * A memory buffer allocated by the core system of Orthanc. When the
-   * content of the buffer is not useful anymore, it must be free by a
-   * call to ::OrthancPluginFreeMemoryBuffer().
-   **/
-  typedef struct
-  {
-    /**
-     * @brief The content of the buffer.
-     **/
-    void*      data;
-
-    /**
-     * @brief The number of bytes in the buffer.
-     **/
-    uint32_t   size;
-  } OrthancPluginMemoryBuffer;
-
-
-
-
-  /**
-   * @brief Opaque structure that represents the HTTP connection to the client application.
-   * @ingroup Callback
-   **/
-  typedef struct _OrthancPluginRestOutput_t OrthancPluginRestOutput;
-
-
-
-  /**
-   * @brief Opaque structure that represents a DICOM instance received by Orthanc.
-   **/
-  typedef struct _OrthancPluginDicomInstance_t OrthancPluginDicomInstance;
-
-
-
-  /**
-   * @brief Opaque structure that represents an image that is uncompressed in memory.
-   * @ingroup Images
-   **/
-  typedef struct _OrthancPluginImage_t OrthancPluginImage;
-
-
-
-  /**
-   * @brief Opaque structure that represents the storage area that is actually used by Orthanc.
-   * @ingroup Images
-   **/
-  typedef struct _OrthancPluginStorageArea_t OrthancPluginStorageArea;
-
-
-
-  /**
-   * @brief Opaque structure to an object that represents a C-Find query.
-   * @ingroup Worklists
-   **/
-  typedef struct _OrthancPluginWorklistQuery_t OrthancPluginWorklistQuery;
-
-
-
-  /**
-   * @brief Opaque structure to an object that represents the answers to a C-Find query.
-   * @ingroup Worklists
-   **/
-  typedef struct _OrthancPluginWorklistAnswers_t OrthancPluginWorklistAnswers;
-
-
-
-  /**
-   * @brief Signature of a callback function that answers to a REST request.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginRestCallback) (
-    OrthancPluginRestOutput* output,
-    const char* url,
-    const OrthancPluginHttpRequest* request);
-
-
-
-  /**
-   * @brief Signature of a callback function that is triggered when Orthanc receives a DICOM instance.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginOnStoredInstanceCallback) (
-    OrthancPluginDicomInstance* instance,
-    const char* instanceId);
-
-
-
-  /**
-   * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginOnChangeCallback) (
-    OrthancPluginChangeType changeType,
-    OrthancPluginResourceType resourceType,
-    const char* resourceId);
-
-
-
-  /**
-   * @brief Signature of a callback function to decode a DICOM instance as an image.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginDecodeImageCallback) (
-    OrthancPluginImage** target,
-    const void* dicom,
-    const uint32_t size,
-    uint32_t frameIndex);
-
-
-
-  /**
-   * @brief Signature of a function to free dynamic memory.
-   **/
-  typedef void (*OrthancPluginFree) (void* buffer);
-
-
-
-  /**
-   * @brief Callback for writing to the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc writes a file to the storage area.
-   *
-   * @param uuid The UUID of the file.
-   * @param content The content of the file.
-   * @param size The size of the file.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageCreate) (
-    const char* uuid,
-    const void* content,
-    int64_t size,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback for reading from the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc reads a file from the storage area.
-   *
-   * @param content The content of the file (output).
-   * @param size The size of the file (output).
-   * @param uuid The UUID of the file of interest.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageRead) (
-    void** content,
-    int64_t* size,
-    const char* uuid,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback for removing a file from the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc deletes a file from the storage area.
-   *
-   * @param uuid The UUID of the file to be removed.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageRemove) (
-    const char* uuid,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback to handle the C-Find SCP requests received by Orthanc.
-   *
-   * Signature of a callback function that is triggered when Orthanc
-   * receives a C-Find SCP request against modality worklists.
-   *
-   * @param answers The target structure where answers must be stored.
-   * @param query The worklist query.
-   * @param remoteAet The Application Entity Title (AET) of the modality from which the request originates.
-   * @param calledAet The Application Entity Title (AET) of the modality that is called by the request.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginWorklistCallback) (
-    OrthancPluginWorklistAnswers*     answers,
-    const OrthancPluginWorklistQuery* query,
-    const char*                       remoteAet,
-    const char*                       calledAet);
-
-
-
-  /**
-   * @brief Data structure that contains information about the Orthanc core.
-   **/
-  typedef struct _OrthancPluginContext_t
-  {
-    void*                     pluginsManager;
-    const char*               orthancVersion;
-    OrthancPluginFree         Free;
-    OrthancPluginErrorCode  (*InvokeService) (struct _OrthancPluginContext_t* context,
-                                              _OrthancPluginService service,
-                                              const void* params);
-  } OrthancPluginContext;
-
-
-  
-  /**
-   * @brief An entry in the dictionary of DICOM tags.
-   **/
-  typedef struct
-  {
-    uint16_t                          group;            /*!< The group of the tag */
-    uint16_t                          element;          /*!< The element of the tag */
-    OrthancPluginValueRepresentation  vr;               /*!< The value representation of the tag */
-    uint32_t                          minMultiplicity;  /*!< The minimum multiplicity of the tag */
-    uint32_t                          maxMultiplicity;  /*!< The maximum multiplicity of the tag (0 means arbitrary) */
-  } OrthancPluginDictionaryEntry;
-
-
-
-  /**
-   * @brief Free a string.
-   * 
-   * Free a string that was allocated by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param str The string to be freed.
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeString(
-    OrthancPluginContext* context, 
-    char* str)
-  {
-    if (str != NULL)
-    {
-      context->Free(str);
-    }
-  }
-
-
-  /**
-   * @brief Check the compatibility of the plugin wrt. the version of its hosting Orthanc.
-   * 
-   * This function checks whether the version of this C header is
-   * compatible with the current version of Orthanc. The result of
-   * this function should always be checked in the
-   * OrthancPluginInitialize() entry point of the plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return 1 if and only if the versions are compatible. If the
-   * result is 0, the initialization of the plugin should fail.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int  OrthancPluginCheckVersion(
-    OrthancPluginContext* context)
-  {
-    int major, minor, revision;
-
-    if (sizeof(int32_t) != sizeof(OrthancPluginErrorCode) ||
-        sizeof(int32_t) != sizeof(OrthancPluginHttpMethod) ||
-        sizeof(int32_t) != sizeof(_OrthancPluginService) ||
-        sizeof(int32_t) != sizeof(_OrthancPluginProperty) ||
-        sizeof(int32_t) != sizeof(OrthancPluginPixelFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginContentType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginResourceType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginChangeType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginCompressionType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginImageFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginValueRepresentation) ||
-        sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) ||
-        sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) ||
-        sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) ||
-        sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin))
-    {
-      /* Mismatch in the size of the enumerations */
-      return 0;
-    }
-
-    /* Assume compatibility with the mainline */
-    if (!strcmp(context->orthancVersion, "mainline"))
-    {
-      return 1;
-    }
-
-    /* Parse the version of the Orthanc core */
-    if ( 
-#ifdef _MSC_VER
-      sscanf_s
-#else
-      sscanf
-#endif
-      (context->orthancVersion, "%4d.%4d.%4d", &major, &minor, &revision) != 3)
-    {
-      return 0;
-    }
-
-    /* Check the major number of the version */
-
-    if (major > ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER)
-    {
-      return 1;
-    }
-
-    if (major < ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER)
-    {
-      return 0;
-    }
-
-    /* Check the minor number of the version */
-
-    if (minor > ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER)
-    {
-      return 1;
-    }
-
-    if (minor < ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER)
-    {
-      return 0;
-    }
-
-    /* Check the revision number of the version */
-
-    if (revision >= ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER)
-    {
-      return 1;
-    }
-    else
-    {
-      return 0;
-    }
-  }
-
-
-  /**
-   * @brief Free a memory buffer.
-   * 
-   * Free a memory buffer that was allocated by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The memory buffer to release.
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeMemoryBuffer(
-    OrthancPluginContext* context, 
-    OrthancPluginMemoryBuffer* buffer)
-  {
-    context->Free(buffer->data);
-  }
-
-
-  /**
-   * @brief Log an error.
-   *
-   * Log an error message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogError(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogError, message);
-  }
-
-
-  /**
-   * @brief Log a warning.
-   *
-   * Log a warning message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogWarning, message);
-  }
-
-
-  /**
-   * @brief Log an information.
-   *
-   * Log an information message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogInfo, message);
-  }
-
-
-
-  typedef struct
-  {
-    const char* pathRegularExpression;
-    OrthancPluginRestCallback callback;
-  } _OrthancPluginRestCallback;
-
-  /**
-   * @brief Register a REST callback.
-   *
-   * This function registers a REST callback against a regular
-   * expression for a URI. This function must be called during the
-   * initialization of the plugin, i.e. inside the
-   * OrthancPluginInitialize() public function.
-   *
-   * Each REST callback is guaranteed to run in mutual exclusion.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param pathRegularExpression Regular expression for the URI. May contain groups.
-   * @param callback The callback function to handle the REST call.
-   * @see OrthancPluginRegisterRestCallbackNoLock()
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback(
-    OrthancPluginContext*     context,
-    const char*               pathRegularExpression,
-    OrthancPluginRestCallback callback)
-  {
-    _OrthancPluginRestCallback params;
-    params.pathRegularExpression = pathRegularExpression;
-    params.callback = callback;
-    context->InvokeService(context, _OrthancPluginService_RegisterRestCallback, &params);
-  }
-
-
-
-  /**
-   * @brief Register a REST callback, without locking.
-   *
-   * This function registers a REST callback against a regular
-   * expression for a URI. This function must be called during the
-   * initialization of the plugin, i.e. inside the
-   * OrthancPluginInitialize() public function.
-   *
-   * Contrarily to OrthancPluginRegisterRestCallback(), the callback
-   * will NOT be invoked in mutual exclusion. This can be useful for
-   * high-performance plugins that must handle concurrent requests
-   * (Orthanc uses a pool of threads, one thread being assigned to
-   * each incoming HTTP request). Of course, it is up to the plugin to
-   * implement the required locking mechanisms.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param pathRegularExpression Regular expression for the URI. May contain groups.
-   * @param callback The callback function to handle the REST call.
-   * @see OrthancPluginRegisterRestCallback()
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallbackNoLock(
-    OrthancPluginContext*     context,
-    const char*               pathRegularExpression,
-    OrthancPluginRestCallback callback)
-  {
-    _OrthancPluginRestCallback params;
-    params.pathRegularExpression = pathRegularExpression;
-    params.callback = callback;
-    context->InvokeService(context, _OrthancPluginService_RegisterRestCallbackNoLock, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginOnStoredInstanceCallback callback;
-  } _OrthancPluginOnStoredInstanceCallback;
-
-  /**
-   * @brief Register a callback for received instances.
-   *
-   * This function registers a callback function that is called
-   * whenever a new DICOM instance is stored into the Orthanc core.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback function.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnStoredInstanceCallback(
-    OrthancPluginContext*                  context,
-    OrthancPluginOnStoredInstanceCallback  callback)
-  {
-    _OrthancPluginOnStoredInstanceCallback params;
-    params.callback = callback;
-
-    context->InvokeService(context, _OrthancPluginService_RegisterOnStoredInstanceCallback, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              answer;
-    uint32_t                 answerSize;
-    const char*              mimeType;
-  } _OrthancPluginAnswerBuffer;
-
-  /**
-   * @brief Answer to a REST request.
-   *
-   * This function answers to a REST request with the content of a memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the answer.
-   * @param answerSize Number of bytes of the answer.
-   * @param mimeType The MIME type of the answer.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize,
-    const char*              mimeType)
-  {
-    _OrthancPluginAnswerBuffer params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.mimeType = mimeType;
-    context->InvokeService(context, _OrthancPluginService_AnswerBuffer, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput*  output;
-    OrthancPluginPixelFormat  format;
-    uint32_t                  width;
-    uint32_t                  height;
-    uint32_t                  pitch;
-    const void*               buffer;
-  } _OrthancPluginCompressAndAnswerPngImage;
-
-  typedef struct
-  {
-    OrthancPluginRestOutput*  output;
-    OrthancPluginImageFormat  imageFormat;
-    OrthancPluginPixelFormat  pixelFormat;
-    uint32_t                  width;
-    uint32_t                  height;
-    uint32_t                  pitch;
-    const void*               buffer;
-    uint8_t                   quality;
-  } _OrthancPluginCompressAndAnswerImage;
-
-
-  /**
-   * @brief Answer to a REST request with a PNG image.
-   *
-   * This function answers to a REST request with a PNG image. The
-   * parameters of this function describe a memory buffer that
-   * contains an uncompressed image. The image will be automatically compressed
-   * as a PNG image by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerPngImage(
-    OrthancPluginContext*     context,
-    OrthancPluginRestOutput*  output,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    const void*               buffer)
-  {
-    _OrthancPluginCompressAndAnswerImage params;
-    params.output = output;
-    params.imageFormat = OrthancPluginImageFormat_Png;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = 0;  /* No quality for PNG */
-    context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 instanceId;
-  } _OrthancPluginGetDicomForInstance;
-
-  /**
-   * @brief Retrieve a DICOM instance using its Orthanc identifier.
-   * 
-   * Retrieve a DICOM instance using its Orthanc identifier. The DICOM
-   * file is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param instanceId The Orthanc identifier of the DICOM instance of interest.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginGetDicomForInstance(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 instanceId)
-  {
-    _OrthancPluginGetDicomForInstance params;
-    params.target = target;
-    params.instanceId = instanceId;
-    return context->InvokeService(context, _OrthancPluginService_GetDicomForInstance, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-  } _OrthancPluginRestApiGet;
-
-  /**
-   * @brief Make a GET call to the built-in Orthanc REST API.
-   * 
-   * Make a GET call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGetAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGet(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri)
-  {
-    _OrthancPluginRestApiGet params;
-    params.target = target;
-    params.uri = uri;
-    return context->InvokeService(context, _OrthancPluginService_RestApiGet, &params);
-  }
-
-
-
-  /**
-   * @brief Make a GET call to the REST API, as tainted by the plugins.
-   * 
-   * Make a GET call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGet
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGetAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri)
-  {
-    _OrthancPluginRestApiGet params;
-    params.target = target;
-    params.uri = uri;
-    return context->InvokeService(context, _OrthancPluginService_RestApiGetAfterPlugins, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-    const char*                 body;
-    uint32_t                    bodySize;
-  } _OrthancPluginRestApiPostPut;
-
-  /**
-   * @brief Make a POST call to the built-in Orthanc REST API.
-   * 
-   * Make a POST call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the POST request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPostAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPost(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPost, &params);
-  }
-
-
-  /**
-   * @brief Make a POST call to the REST API, as tainted by the plugins.
-   * 
-   * Make a POST call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the POST request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPost
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPostAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPostAfterPlugins, &params);
-  }
-
-
-
-  /**
-   * @brief Make a DELETE call to the built-in Orthanc REST API.
-   * 
-   * Make a DELETE call to the built-in Orthanc REST API.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The URI to delete in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiDeleteAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiDelete(
-    OrthancPluginContext*       context,
-    const char*                 uri)
-  {
-    return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri);
-  }
-
-
-  /**
-   * @brief Make a DELETE call to the REST API, as tainted by the plugins.
-   * 
-   * Make a DELETE call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. 
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The URI to delete in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiDelete
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiDeleteAfterPlugins(
-    OrthancPluginContext*       context,
-    const char*                 uri)
-  {
-    return context->InvokeService(context, _OrthancPluginService_RestApiDeleteAfterPlugins, uri);
-  }
-
-
-
-  /**
-   * @brief Make a PUT call to the built-in Orthanc REST API.
-   * 
-   * Make a PUT call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the PUT request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPutAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPut(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPut, &params);
-  }
-
-
-
-  /**
-   * @brief Make a PUT call to the REST API, as tainted by the plugins.
-   * 
-   * Make a PUT call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the PUT request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPut
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPutAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPutAfterPlugins, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              argument;
-  } _OrthancPluginOutputPlusArgument;
-
-  /**
-   * @brief Redirect a REST request.
-   *
-   * This function answers to a REST request by redirecting the user
-   * to another URI using HTTP status 301.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param redirection Where to redirect.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRedirect(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              redirection)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = redirection;
-    context->InvokeService(context, _OrthancPluginService_Redirect, &params);
-  }
-
-
-
-  typedef struct
-  {
-    char**       result;
-    const char*  argument;
-  } _OrthancPluginRetrieveDynamicString;
-
-  /**
-   * @brief Look for a patient.
-   *
-   * Look for a patient stored in Orthanc, using its Patient ID tag (0x0010, 0x0020).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored patients).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param patientID The Patient ID of interest.
-   * @return The NULL value if the patient is non-existent, or a string containing the 
-   * Orthanc ID of the patient. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupPatient(
-    OrthancPluginContext*  context,
-    const char*            patientID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = patientID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupPatient, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a study.
-   *
-   * Look for a study stored in Orthanc, using its Study Instance UID tag (0x0020, 0x000d).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored studies).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param studyUID The Study Instance UID of interest.
-   * @return The NULL value if the study is non-existent, or a string containing the 
-   * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudy(
-    OrthancPluginContext*  context,
-    const char*            studyUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = studyUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupStudy, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a study, using the accession number.
-   *
-   * Look for a study stored in Orthanc, using its Accession Number tag (0x0008, 0x0050).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored studies).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param accessionNumber The Accession Number of interest.
-   * @return The NULL value if the study is non-existent, or a string containing the 
-   * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudyWithAccessionNumber(
-    OrthancPluginContext*  context,
-    const char*            accessionNumber)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = accessionNumber;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupStudyWithAccessionNumber, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a series.
-   *
-   * Look for a series stored in Orthanc, using its Series Instance UID tag (0x0020, 0x000e).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored series).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param seriesUID The Series Instance UID of interest.
-   * @return The NULL value if the series is non-existent, or a string containing the 
-   * Orthanc ID of the series. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupSeries(
-    OrthancPluginContext*  context,
-    const char*            seriesUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = seriesUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupSeries, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for an instance.
-   *
-   * Look for an instance stored in Orthanc, using its SOP Instance UID tag (0x0008, 0x0018).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored instances).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param sopInstanceUID The SOP Instance UID of interest.
-   * @return The NULL value if the instance is non-existent, or a string containing the 
-   * Orthanc ID of the instance. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupInstance(
-    OrthancPluginContext*  context,
-    const char*            sopInstanceUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = sopInstanceUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupInstance, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    uint16_t                 status;
-  } _OrthancPluginSendHttpStatusCode;
-
-  /**
-   * @brief Send a HTTP status code.
-   *
-   * This function answers to a REST request by sending a HTTP status
-   * code (such as "400 - Bad Request"). Note that:
-   * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer().
-   * - Redirections (status 301) must use ::OrthancPluginRedirect().
-   * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized().
-   * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param status The HTTP status code to be sent.
-   * @ingroup REST
-   * @see OrthancPluginSendHttpStatus()
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatusCode(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    uint16_t                 status)
-  {
-    _OrthancPluginSendHttpStatusCode params;
-    params.output = output;
-    params.status = status;
-    context->InvokeService(context, _OrthancPluginService_SendHttpStatusCode, &params);
-  }
-
-
-  /**
-   * @brief Signal that a REST request is not authorized.
-   *
-   * This function answers to a REST request by signaling that it is
-   * not authorized.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param realm The realm for the authorization process.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendUnauthorized(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              realm)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = realm;
-    context->InvokeService(context, _OrthancPluginService_SendUnauthorized, &params);
-  }
-
-
-  /**
-   * @brief Signal that this URI does not support this HTTP method.
-   *
-   * This function answers to a REST request by signaling that the
-   * queried URI does not support this method.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param allowedMethods The allowed methods for this URI (e.g. "GET,POST" after a PUT or a POST request).
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendMethodNotAllowed(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              allowedMethods)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = allowedMethods;
-    context->InvokeService(context, _OrthancPluginService_SendMethodNotAllowed, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              key;
-    const char*              value;
-  } _OrthancPluginSetHttpHeader;
-
-  /**
-   * @brief Set a cookie.
-   *
-   * This function sets a cookie in the HTTP client.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param cookie The cookie to be set.
-   * @param value The value of the cookie.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetCookie(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              cookie,
-    const char*              value)
-  {
-    _OrthancPluginSetHttpHeader params;
-    params.output = output;
-    params.key = cookie;
-    params.value = value;
-    context->InvokeService(context, _OrthancPluginService_SetCookie, &params);
-  }
-
-
-  /**
-   * @brief Set some HTTP header.
-   *
-   * This function sets a HTTP header in the HTTP answer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param key The HTTP header to be set.
-   * @param value The value of the HTTP header.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetHttpHeader(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              key,
-    const char*              value)
-  {
-    _OrthancPluginSetHttpHeader params;
-    params.output = output;
-    params.key = key;
-    params.value = value;
-    context->InvokeService(context, _OrthancPluginService_SetHttpHeader, &params);
-  }
-
-
-  typedef struct
-  {
-    char**                       resultStringToFree;
-    const char**                 resultString;
-    int64_t*                     resultInt64;
-    const char*                  key;
-    OrthancPluginDicomInstance*  instance;
-    OrthancPluginInstanceOrigin* resultOrigin;   /* New in Orthanc 0.9.5 SDK */
-  } _OrthancPluginAccessDicomInstance;
-
-
-  /**
-   * @brief Get the AET of a DICOM instance.
-   *
-   * This function returns the Application Entity Title (AET) of the
-   * DICOM modality from which a DICOM instance originates.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The AET if success, NULL if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceRemoteAet(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the size of a DICOM file.
-   *
-   * This function returns the number of bytes of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The size of the file, -1 in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int64_t OrthancPluginGetInstanceSize(
-    OrthancPluginContext*       context,
-    OrthancPluginDicomInstance* instance)
-  {
-    int64_t size;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultInt64 = &size;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return -1;
-    }
-    else
-    {
-      return size;
-    }
-  }
-
-
-  /**
-   * @brief Get the data of a DICOM file.
-   *
-   * This function returns a pointer to the content of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The pointer to the DICOM data, NULL in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceData(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the DICOM tag hierarchy as a JSON file.
-   *
-   * This function returns a pointer to a newly created string
-   * containing a JSON file. This JSON file encodes the tag hierarchy
-   * of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The NULL value in case of error, or a string containing the JSON file.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceJson(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultStringToFree = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the DICOM tag hierarchy as a JSON file (with simplification).
-   *
-   * This function returns a pointer to a newly created string
-   * containing a JSON file. This JSON file encodes the tag hierarchy
-   * of the given DICOM instance. In contrast with
-   * ::OrthancPluginGetInstanceJson(), the returned JSON file is in
-   * its simplified version.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The NULL value in case of error, or a string containing the JSON file.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceSimplifiedJson(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultStringToFree = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Check whether a DICOM instance is associated with some metadata.
-   *
-   * This function checks whether the DICOM instance of interest is
-   * associated with some metadata. As of Orthanc 0.8.1, in the
-   * callbacks registered by
-   * ::OrthancPluginRegisterOnStoredInstanceCallback(), the only
-   * possibly available metadata are "ReceptionDate", "RemoteAET" and
-   * "IndexInSeries".
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @param metadata The metadata of interest.
-   * @return 1 if the metadata is present, 0 if it is absent, -1 in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int  OrthancPluginHasInstanceMetadata(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance,
-    const char*                  metadata)
-  {
-    int64_t result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultInt64 = &result;
-    params.instance = instance;
-    params.key = metadata;
-
-    if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return -1;
-    }
-    else
-    {
-      return (result != 0);
-    }
-  }
-
-
-  /**
-   * @brief Get the value of some metadata associated with a given DICOM instance.
-   *
-   * This functions returns the value of some metadata that is associated with the DICOM instance of interest.
-   * Before calling this function, the existence of the metadata must have been checked with
-   * ::OrthancPluginHasInstanceMetadata().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @param metadata The metadata of interest.
-   * @return The metadata value if success, NULL if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceMetadata(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance,
-    const char*                  metadata)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-    params.key = metadata;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageCreate  create;
-    OrthancPluginStorageRead    read;
-    OrthancPluginStorageRemove  remove;
-    OrthancPluginFree           free;
-  } _OrthancPluginRegisterStorageArea;
-
-  /**
-   * @brief Register a custom storage area.
-   *
-   * This function registers a custom storage area, to replace the
-   * built-in way Orthanc stores its files on the filesystem. This
-   * function must be called during the initialization of the plugin,
-   * i.e. inside the OrthancPluginInitialize() public function.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param create The callback function to store a file on the custom storage area.
-   * @param read The callback function to read a file from the custom storage area.
-   * @param remove The callback function to remove a file from the custom storage area.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterStorageArea(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageCreate  create,
-    OrthancPluginStorageRead    read,
-    OrthancPluginStorageRemove  remove)
-  {
-    _OrthancPluginRegisterStorageArea params;
-    params.create = create;
-    params.read = read;
-    params.remove = remove;
-
-#ifdef  __cplusplus
-    params.free = ::free;
-#else
-    params.free = free;
-#endif
-
-    context->InvokeService(context, _OrthancPluginService_RegisterStorageArea, &params);
-  }
-
-
-
-  /**
-   * @brief Return the path to the Orthanc executable.
-   *
-   * This function returns the path to the Orthanc executable.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancPath(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetOrthancPath, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the directory containing the Orthanc.
-   *
-   * This function returns the path to the directory containing the Orthanc executable.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancDirectory(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetOrthancDirectory, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the path to the configuration file(s).
-   *
-   * This function returns the path to the configuration file(s) that
-   * was specified when starting Orthanc. Since version 0.9.1, this
-   * path can refer to a folder that stores a set of configuration
-   * files. This function is deprecated in favor of
-   * OrthancPluginGetConfiguration().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   * @see OrthancPluginGetConfiguration()
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfigurationPath(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetConfigurationPath, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginOnChangeCallback callback;
-  } _OrthancPluginOnChangeCallback;
-
-  /**
-   * @brief Register a callback to monitor changes.
-   *
-   * This function registers a callback function that is called
-   * whenever a change happens to some DICOM resource.
-   *
-   * @warning If your change callback has to call the REST API of
-   * Orthanc, you should make these calls in a separate thread (with
-   * the events passing through a message queue). Otherwise, this
-   * could result in deadlocks in the presence of other plugins or Lua
-   * script.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback function.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback(
-    OrthancPluginContext*          context,
-    OrthancPluginOnChangeCallback  callback)
-  {
-    _OrthancPluginOnChangeCallback params;
-    params.callback = callback;
-
-    context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char* plugin;
-    _OrthancPluginProperty property;
-    const char* value;
-  } _OrthancPluginSetPluginProperty;
-
-
-  /**
-   * @brief Set the URI where the plugin provides its Web interface.
-   *
-   * For plugins that come with a Web interface, this function
-   * declares the entry path where to find this interface. This
-   * information is notably used in the "Plugins" page of Orthanc
-   * Explorer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The root URI for this plugin.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetRootUri(
-    OrthancPluginContext*  context,
-    const char*            uri)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_RootUri;
-    params.value = uri;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  /**
-   * @brief Set a description for this plugin.
-   *
-   * Set a description for this plugin. It is displayed in the
-   * "Plugins" page of Orthanc Explorer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param description The description.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetDescription(
-    OrthancPluginContext*  context,
-    const char*            description)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_Description;
-    params.value = description;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  /**
-   * @brief Extend the JavaScript code of Orthanc Explorer.
-   *
-   * Add JavaScript code to customize the default behavior of Orthanc
-   * Explorer. This can for instance be used to add new buttons.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param javascript The custom JavaScript code.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginExtendOrthancExplorer(
-    OrthancPluginContext*  context,
-    const char*            javascript)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_OrthancExplorer;
-    params.value = javascript;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  typedef struct
-  {
-    char**       result;
-    int32_t      property;
-    const char*  value;
-  } _OrthancPluginGlobalProperty;
-
-
-  /**
-   * @brief Get the value of a global property.
-   *
-   * Get the value of a global property that is stored in the Orthanc database. Global
-   * properties whose index is below 1024 are reserved by Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param property The global property of interest.
-   * @param defaultValue The value to return, if the global property is unset.
-   * @return The value of the global property, or NULL in the case of an error. This
-   * string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetGlobalProperty(
-    OrthancPluginContext*  context,
-    int32_t                property,
-    const char*            defaultValue)
-  {
-    char* result;
-
-    _OrthancPluginGlobalProperty params;
-    params.result = &result;
-    params.property = property;
-    params.value = defaultValue;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetGlobalProperty, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Set the value of a global property.
-   *
-   * Set the value of a global property into the Orthanc
-   * database. Setting a global property can be used by plugins to
-   * save their internal parameters. Plugins are only allowed to set
-   * properties whose index are above or equal to 1024 (properties
-   * below 1024 are read-only and reserved by Orthanc).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param property The global property of interest.
-   * @param value The value to be set in the global property.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSetGlobalProperty(
-    OrthancPluginContext*  context,
-    int32_t                property,
-    const char*            value)
-  {
-    _OrthancPluginGlobalProperty params;
-    params.result = NULL;
-    params.property = property;
-    params.value = value;
-
-    return context->InvokeService(context, _OrthancPluginService_SetGlobalProperty, &params);
-  }
-
-
-
-  typedef struct
-  {
-    int32_t   *resultInt32;
-    uint32_t  *resultUint32;
-    int64_t   *resultInt64;
-    uint64_t  *resultUint64;
-  } _OrthancPluginReturnSingleValue;
-
-  /**
-   * @brief Get the number of command-line arguments.
-   *
-   * Retrieve the number of command-line arguments that were used to launch Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The number of arguments.
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetCommandLineArgumentsCount(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-  /**
-   * @brief Get the value of a command-line argument.
-   *
-   * Get the value of one of the command-line arguments that were used
-   * to launch Orthanc. The number of available arguments can be
-   * retrieved by OrthancPluginGetCommandLineArgumentsCount().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param argument The index of the argument.
-   * @return The value of the argument, or NULL in the case of an error. This
-   * string must be freed by OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetCommandLineArgument(
-    OrthancPluginContext*  context,
-    uint32_t               argument)
-  {
-    char* result;
-
-    _OrthancPluginGlobalProperty params;
-    params.result = &result;
-    params.property = (int32_t) argument;
-    params.value = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgument, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the expected version of the database schema.
-   *
-   * Retrieve the expected version of the database schema.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The version.
-   * @ingroup Callbacks
-   * @deprecated Please instead use IDatabaseBackend::UpgradeDatabase()
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetExpectedDatabaseVersion(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the content of the configuration file(s).
-   *
-   * This function returns the content of the configuration that is
-   * used by Orthanc, formatted as a JSON string.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the configuration. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfiguration(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetConfiguration, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              subType;
-    const char*              contentType;
-  } _OrthancPluginStartMultipartAnswer;
-
-  /**
-   * @brief Start an HTTP multipart answer.
-   *
-   * Initiates a HTTP multipart answer, as the result of a REST request.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param subType The sub-type of the multipart answer ("mixed" or "related").
-   * @param contentType The MIME type of the items in the multipart answer.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginSendMultipartItem(), OrthancPluginSendMultipartItem2()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              subType,
-    const char*              contentType)
-  {
-    _OrthancPluginStartMultipartAnswer params;
-    params.output = output;
-    params.subType = subType;
-    params.contentType = contentType;
-    return context->InvokeService(context, _OrthancPluginService_StartMultipartAnswer, &params);
-  }
-
-
-  /**
-   * @brief Send an item as a part of some HTTP multipart answer.
-   *
-   * This function sends an item as a part of some HTTP multipart
-   * answer that was initiated by OrthancPluginStartMultipartAnswer().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the item.
-   * @param answerSize Number of bytes of the item.
-   * @return 0 if success, or the error code if failure (this notably happens
-   * if the connection is closed by the client).
-   * @see OrthancPluginSendMultipartItem2()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize)
-  {
-    _OrthancPluginAnswerBuffer params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.mimeType = NULL;
-    return context->InvokeService(context, _OrthancPluginService_SendMultipartItem, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*    target;
-    const void*                   source;
-    uint32_t                      size;
-    OrthancPluginCompressionType  compression;
-    uint8_t                       uncompress;
-  } _OrthancPluginBufferCompression;
-
-
-  /**
-   * @brief Compress or decompress a buffer.
-   *
-   * This function compresses or decompresses a buffer, using the
-   * version of the zlib library that is used by the Orthanc core.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param source The source buffer.
-   * @param size The size in bytes of the source buffer.
-   * @param compression The compression algorithm.
-   * @param uncompress If set to "0", the buffer must be compressed. 
-   * If set to "1", the buffer must be uncompressed.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginBufferCompression(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    const void*                   source,
-    uint32_t                      size,
-    OrthancPluginCompressionType  compression,
-    uint8_t                       uncompress)
-  {
-    _OrthancPluginBufferCompression params;
-    params.target = target;
-    params.source = source;
-    params.size = size;
-    params.compression = compression;
-    params.uncompress = uncompress;
-
-    return context->InvokeService(context, _OrthancPluginService_BufferCompression, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 path;
-  } _OrthancPluginReadFile;
-
-  /**
-   * @brief Read a file.
-   * 
-   * Read the content of a file on the filesystem, and returns it into
-   * a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param path The path of the file to be read.
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginReadFile(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 path)
-  {
-    _OrthancPluginReadFile params;
-    params.target = target;
-    params.path = path;
-    return context->InvokeService(context, _OrthancPluginService_ReadFile, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char*  path;
-    const void*  data;
-    uint32_t     size;
-  } _OrthancPluginWriteFile;
-
-  /**
-   * @brief Write a file.
-   * 
-   * Write the content of a memory buffer to the filesystem.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param path The path of the file to be written.
-   * @param data The content of the memory buffer.
-   * @param size The size of the memory buffer.
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWriteFile(
-    OrthancPluginContext*  context,
-    const char*            path,
-    const void*            data,
-    uint32_t               size)
-  {
-    _OrthancPluginWriteFile params;
-    params.path = path;
-    params.data = data;
-    params.size = size;
-    return context->InvokeService(context, _OrthancPluginService_WriteFile, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char**            target;
-    OrthancPluginErrorCode  error;
-  } _OrthancPluginGetErrorDescription;
-
-  /**
-   * @brief Get the description of a given error code.
-   *
-   * This function returns the description of a given error code.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param error The error code of interest.
-   * @return The error description. This is a statically-allocated
-   * string, do not free it.
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetErrorDescription(
-    OrthancPluginContext*    context,
-    OrthancPluginErrorCode   error)
-  {
-    const char* result = NULL;
-
-    _OrthancPluginGetErrorDescription params;
-    params.target = &result;
-    params.error = error;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetErrorDescription, &params) != OrthancPluginErrorCode_Success ||
-        result == NULL)
-    {
-      return "Unknown error code";
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    uint16_t                 status;
-    const char*              body;
-    uint32_t                 bodySize;
-  } _OrthancPluginSendHttpStatus;
-
-  /**
-   * @brief Send a HTTP status, with a custom body.
-   *
-   * This function answers to a HTTP request by sending a HTTP status
-   * code (such as "400 - Bad Request"), together with a body
-   * describing the error. The body will only be returned if the
-   * configuration option "HttpDescribeErrors" of Orthanc is set to "true".
-   * 
-   * Note that:
-   * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer().
-   * - Redirections (status 301) must use ::OrthancPluginRedirect().
-   * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized().
-   * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param status The HTTP status code to be sent.
-   * @param body The body of the answer.
-   * @param bodySize The size of the body.
-   * @see OrthancPluginSendHttpStatusCode()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatus(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    uint16_t                 status,
-    const char*              body,
-    uint32_t                 bodySize)
-  {
-    _OrthancPluginSendHttpStatus params;
-    params.output = output;
-    params.status = status;
-    params.body = body;
-    params.bodySize = bodySize;
-    context->InvokeService(context, _OrthancPluginService_SendHttpStatus, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const OrthancPluginImage*  image;
-    uint32_t*                  resultUint32;
-    OrthancPluginPixelFormat*  resultPixelFormat;
-    void**                     resultBuffer;
-  } _OrthancPluginGetImageInfo;
-
-
-  /**
-   * @brief Return the pixel format of an image.
-   *
-   * This function returns the type of memory layout for the pixels of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pixel format.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat  OrthancPluginGetImagePixelFormat(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    OrthancPluginPixelFormat target;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultPixelFormat = &target;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, &params) != OrthancPluginErrorCode_Success)
-    {
-      return OrthancPluginPixelFormat_Unknown;
-    }
-    else
-    {
-      return (OrthancPluginPixelFormat) target;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the width of an image.
-   *
-   * This function returns the width of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The width.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageWidth(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t width;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &width;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return width;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the height of an image.
-   *
-   * This function returns the height of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The height.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageHeight(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t height;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &height;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return height;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the pitch of an image.
-   *
-   * This function returns the pitch of the given image. The pitch is
-   * defined as the number of bytes between 2 successive lines of the
-   * image in the memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pitch.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImagePitch(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t pitch;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &pitch;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return pitch;
-    }
-  }
-
-
-
-  /**
-   * @brief Return a pointer to the content of an image.
-   *
-   * This function returns a pointer to the memory buffer that
-   * contains the pixels of the image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pointer.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE void*  OrthancPluginGetImageBuffer(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    void* target = NULL;
-
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.resultBuffer = &target;
-    params.image = image;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    const void*                data;
-    uint32_t                   size;
-    OrthancPluginImageFormat   format;
-  } _OrthancPluginUncompressImage;
-
-
-  /**
-   * @brief Decode a compressed image.
-   *
-   * This function decodes a compressed image from a memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param data Pointer to a memory buffer containing the compressed image.
-   * @param size Size of the memory buffer containing the compressed image.
-   * @param format The file format of the compressed image.
-   * @return The uncompressed image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage(
-    OrthancPluginContext*      context,
-    const void*                data,
-    uint32_t                   size,
-    OrthancPluginImageFormat   format)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginUncompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.data = data;
-    params.size = size;
-    params.format = format;
-
-    if (context->InvokeService(context, _OrthancPluginService_UncompressImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage*   image;
-  } _OrthancPluginFreeImage;
-
-  /**
-   * @brief Free an image.
-   *
-   * This function frees an image that was decoded with OrthancPluginUncompressImage().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeImage(
-    OrthancPluginContext* context, 
-    OrthancPluginImage*   image)
-  {
-    _OrthancPluginFreeImage params;
-    params.image = image;
-
-    context->InvokeService(context, _OrthancPluginService_FreeImage, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer* target;
-    OrthancPluginImageFormat   imageFormat;
-    OrthancPluginPixelFormat   pixelFormat;
-    uint32_t                   width;
-    uint32_t                   height;
-    uint32_t                   pitch;
-    const void*                buffer;
-    uint8_t                    quality;
-  } _OrthancPluginCompressImage;
-
-
-  /**
-   * @brief Encode a PNG image.
-   *
-   * This function compresses the given memory buffer containing an
-   * image using the PNG specification, and stores the result of the
-   * compression into a newly allocated memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginCompressAndAnswerPngImage()
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    OrthancPluginPixelFormat      format,
-    uint32_t                      width,
-    uint32_t                      height,
-    uint32_t                      pitch,
-    const void*                   buffer)
-  {
-    _OrthancPluginCompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = target;
-    params.imageFormat = OrthancPluginImageFormat_Png;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = 0;  /* Unused for PNG */
-
-    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
-  }
-
-
-  /**
-   * @brief Encode a JPEG image.
-   *
-   * This function compresses the given memory buffer containing an
-   * image using the JPEG specification, and stores the result of the
-   * compression into a newly allocated memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @param quality The quality of the JPEG encoding, between 1 (worst
-   * quality, best compression) and 100 (best quality, worst
-   * compression).
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    OrthancPluginPixelFormat      format,
-    uint32_t                      width,
-    uint32_t                      height,
-    uint32_t                      pitch,
-    const void*                   buffer,
-    uint8_t                       quality)
-  {
-    _OrthancPluginCompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = target;
-    params.imageFormat = OrthancPluginImageFormat_Jpeg;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = quality;
-
-    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
-  }
-
-
-
-  /**
-   * @brief Answer to a REST request with a JPEG image.
-   *
-   * This function answers to a REST request with a JPEG image. The
-   * parameters of this function describe a memory buffer that
-   * contains an uncompressed image. The image will be automatically compressed
-   * as a JPEG image by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @param quality The quality of the JPEG encoding, between 1 (worst
-   * quality, best compression) and 100 (best quality, worst
-   * compression).
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerJpegImage(
-    OrthancPluginContext*     context,
-    OrthancPluginRestOutput*  output,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    const void*               buffer,
-    uint8_t                   quality)
-  {
-    _OrthancPluginCompressAndAnswerImage params;
-    params.output = output;
-    params.imageFormat = OrthancPluginImageFormat_Jpeg;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = quality;
-    context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    OrthancPluginHttpMethod     method;
-    const char*                 url;
-    const char*                 username;
-    const char*                 password;
-    const char*                 body;
-    uint32_t                    bodySize;
-  } _OrthancPluginCallHttpClient;
-
-
-  /**
-   * @brief Issue a HTTP GET call.
-   * 
-   * Make a HTTP GET call to the given URL. The result to the query is
-   * stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiGet() if calling the built-in REST API of the
-   * Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpGet(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Get;
-    params.url = url;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP POST call.
-   * 
-   * Make a HTTP POST call to the given URL. The result to the query
-   * is stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiPost() if calling the built-in REST API of
-   * the Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param body The content of the body of the request.
-   * @param bodySize The size of the body of the request.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpPost(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 body,
-    uint32_t                    bodySize,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Post;
-    params.url = url;
-    params.body = body;
-    params.bodySize = bodySize;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP PUT call.
-   * 
-   * Make a HTTP PUT call to the given URL. The result to the query is
-   * stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiPut() if calling the built-in REST API of the
-   * Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param body The content of the body of the request.
-   * @param bodySize The size of the body of the request.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpPut(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 body,
-    uint32_t                    bodySize,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Put;
-    params.url = url;
-    params.body = body;
-    params.bodySize = bodySize;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP DELETE call.
-   * 
-   * Make a HTTP DELETE call to the given URL. Favor
-   * OrthancPluginRestApiDelete() if calling the built-in REST API of
-   * the Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param url The URL of interest.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpDelete(
-    OrthancPluginContext*       context,
-    const char*                 url,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.method = OrthancPluginHttpMethod_Delete;
-    params.url = url;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    const OrthancPluginImage*  source;
-    OrthancPluginPixelFormat   targetFormat;
-  } _OrthancPluginConvertPixelFormat;
-
-
-  /**
-   * @brief Change the pixel format of an image.
-   *
-   * This function creates a new image, changing the memory layout of the pixels.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param source The source image.
-   * @param targetFormat The target pixel format.
-   * @return The resulting image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginConvertPixelFormat(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  source,
-    OrthancPluginPixelFormat   targetFormat)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginConvertPixelFormat params;
-    params.target = &target;
-    params.source = source;
-    params.targetFormat = targetFormat;
-
-    if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the number of available fonts.
-   *
-   * This function returns the number of fonts that are built in the
-   * Orthanc core. These fonts can be used to draw texts on images
-   * through OrthancPluginDrawText().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The number of fonts.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontsCount(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-
-  typedef struct
-  {
-    uint32_t      fontIndex; /* in */
-    const char**  name; /* out */
-    uint32_t*     size; /* out */
-  } _OrthancPluginGetFontInfo;
-
-  /**
-   * @brief Return the name of a font.
-   *
-   * This function returns the name of a font that is built in the Orthanc core.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @return The font name. This is a statically-allocated string, do not free it.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetFontName(
-    OrthancPluginContext*  context,
-    uint32_t               fontIndex)
-  {
-    const char* result = NULL;
-
-    _OrthancPluginGetFontInfo params;
-    memset(&params, 0, sizeof(params));
-    params.name = &result;
-    params.fontIndex = fontIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the size of a font.
-   *
-   * This function returns the size of a font that is built in the Orthanc core.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @return The font size.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontSize(
-    OrthancPluginContext*  context,
-    uint32_t               fontIndex)
-  {
-    uint32_t result;
-
-    _OrthancPluginGetFontInfo params;
-    memset(&params, 0, sizeof(params));
-    params.size = &result;
-    params.fontIndex = fontIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage*   image;
-    uint32_t              fontIndex;
-    const char*           utf8Text;
-    int32_t               x;
-    int32_t               y;
-    uint8_t               r;
-    uint8_t               g;
-    uint8_t               b;
-  } _OrthancPluginDrawText;
-
-
-  /**
-   * @brief Draw text on an image.
-   *
-   * This function draws some text on some image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image upon which to draw the text.
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @param utf8Text The text to be drawn, encoded as an UTF-8 zero-terminated string.
-   * @param x The X position of the text over the image.
-   * @param y The Y position of the text over the image.
-   * @param r The value of the red color channel of the text.
-   * @param g The value of the green color channel of the text.
-   * @param b The value of the blue color channel of the text.
-   * @return 0 if success, other value if error.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginDrawText(
-    OrthancPluginContext*  context,
-    OrthancPluginImage*    image,
-    uint32_t               fontIndex,
-    const char*            utf8Text,
-    int32_t                x,
-    int32_t                y,
-    uint8_t                r,
-    uint8_t                g,
-    uint8_t                b)
-  {
-    _OrthancPluginDrawText params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.fontIndex = fontIndex;
-    params.utf8Text = utf8Text;
-    params.x = x;
-    params.y = y;
-    params.r = r;
-    params.g = g;
-    params.b = b;
-
-    return context->InvokeService(context, _OrthancPluginService_DrawText, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    const void*                 content;
-    uint64_t                    size;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaCreate;
-
-
-  /**
-   * @brief Create a file inside the storage area.
-   *
-   * This function creates a new file inside the storage area that is
-   * currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be created.
-   * @param content The content to store in the newly created file.
-   * @param size The size of the content.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaCreate(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    const void*                 content,
-    uint64_t                    size,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaCreate params;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.content = content;
-    params.size = size;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaCreate, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaRead;
-
-
-  /**
-   * @brief Read a file from the storage area.
-   *
-   * This function reads the content of a given file from the storage
-   * area that is currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be read.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaRead(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaRead params;
-    params.target = target;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaRead, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaRemove;
-
-  /**
-   * @brief Remove a file from the storage area.
-   *
-   * This function removes a given file from the storage area that is
-   * currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be removed.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaRemove(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaRemove params;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaRemove, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginErrorCode*  target;
-    int32_t                  code;
-    uint16_t                 httpStatus;
-    const char*              message;
-  } _OrthancPluginRegisterErrorCode;
-  
-  /**
-   * @brief Declare a custom error code for this plugin.
-   *
-   * This function declares a custom error code that can be generated
-   * by this plugin. This declaration is used to enrich the body of
-   * the HTTP answer in the case of an error, and to set the proper
-   * HTTP status code.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param code The error code that is internal to this plugin.
-   * @param httpStatus The HTTP status corresponding to this error.
-   * @param message The description of the error.
-   * @return The error code that has been assigned inside the Orthanc core.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRegisterErrorCode(
-    OrthancPluginContext*    context,
-    int32_t                  code,
-    uint16_t                 httpStatus,
-    const char*              message)
-  {
-    OrthancPluginErrorCode target;
-
-    _OrthancPluginRegisterErrorCode params;
-    params.target = &target;
-    params.code = code;
-    params.httpStatus = httpStatus;
-    params.message = message;
-
-    if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, &params) == OrthancPluginErrorCode_Success)
-    {
-      return target;
-    }
-    else
-    {
-      /* There was an error while assigned the error. Use a generic code. */
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    uint16_t                          group;
-    uint16_t                          element;
-    OrthancPluginValueRepresentation  vr;
-    const char*                       name;
-    uint32_t                          minMultiplicity;
-    uint32_t                          maxMultiplicity;
-  } _OrthancPluginRegisterDictionaryTag;
-  
-  /**
-   * @brief Register a new tag into the DICOM dictionary.
-   *
-   * This function declares a new tag in the dictionary of DICOM tags
-   * that are known to Orthanc. This function should be used in the
-   * OrthancPluginInitialize() callback.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param group The group of the tag.
-   * @param element The element of the tag.
-   * @param vr The value representation of the tag.
-   * @param name The nickname of the tag.
-   * @param minMultiplicity The minimum multiplicity of the tag (must be above 0).
-   * @param maxMultiplicity The maximum multiplicity of the tag. A value of 0 means
-   * an arbitrary multiplicity ("<tt>n</tt>").
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRegisterDictionaryTag(
-    OrthancPluginContext*             context,
-    uint16_t                          group,
-    uint16_t                          element,
-    OrthancPluginValueRepresentation  vr,
-    const char*                       name,
-    uint32_t                          minMultiplicity,
-    uint32_t                          maxMultiplicity)
-  {
-    _OrthancPluginRegisterDictionaryTag params;
-    params.group = group;
-    params.element = element;
-    params.vr = vr;
-    params.name = name;
-    params.minMultiplicity = minMultiplicity;
-    params.maxMultiplicity = maxMultiplicity;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterDictionaryTag, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*  storageArea;
-    OrthancPluginResourceType  level;
-  } _OrthancPluginReconstructMainDicomTags;
-
-  /**
-   * @brief Reconstruct the main DICOM tags.
-   *
-   * This function requests the Orthanc core to reconstruct the main
-   * DICOM tags of all the resources of the given type. This function
-   * can only be used as a part of the upgrade of a custom database
-   * back-end
-   * (cf. OrthancPlugins::IDatabaseBackend::UpgradeDatabase). A
-   * database transaction will be automatically setup.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param level The type of the resources of interest.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginReconstructMainDicomTags(
-    OrthancPluginContext*      context,
-    OrthancPluginStorageArea*  storageArea,
-    OrthancPluginResourceType  level)
-  {
-    _OrthancPluginReconstructMainDicomTags params;
-    params.level = level;
-    params.storageArea = storageArea;
-
-    return context->InvokeService(context, _OrthancPluginService_ReconstructMainDicomTags, &params);
-  }
-
-
-  typedef struct
-  {
-    char**                          result;
-    const char*                     instanceId;
-    const char*                     buffer;
-    uint32_t                        size;
-    OrthancPluginDicomToJsonFormat  format;
-    OrthancPluginDicomToJsonFlags   flags;
-    uint32_t                        maxStringLength;
-  } _OrthancPluginDicomToJson;
-
-
-  /**
-   * @brief Format a DICOM memory buffer as a JSON string.
-   *
-   * This function takes as input a memory buffer containing a DICOM
-   * file, and outputs a JSON string representing the tags of this
-   * DICOM file.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The memory buffer containing the DICOM file.
-   * @param size The size of the memory buffer.
-   * @param format The output format.
-   * @param flags Flags governing the output.
-   * @param maxStringLength The maximum length of a field. Too long fields will
-   * be output as "null". The 0 value means no maximum length.
-   * @return The NULL value if the case of an error, or the JSON
-   * string. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomInstanceToJson
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomBufferToJson(
-    OrthancPluginContext*           context,
-    const char*                     buffer,
-    uint32_t                        size,
-    OrthancPluginDicomToJsonFormat  format,
-    OrthancPluginDicomToJsonFlags   flags, 
-    uint32_t                        maxStringLength)
-  {
-    char* result;
-
-    _OrthancPluginDicomToJson params;
-    memset(&params, 0, sizeof(params));
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-    params.format = format;
-    params.flags = flags;
-    params.maxStringLength = maxStringLength;
-
-    if (context->InvokeService(context, _OrthancPluginService_DicomBufferToJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Format a DICOM instance as a JSON string.
-   *
-   * This function formats a DICOM instance that is stored in Orthanc,
-   * and outputs a JSON string representing the tags of this DICOM
-   * instance.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instanceId The Orthanc identifier of the instance.
-   * @param format The output format.
-   * @param flags Flags governing the output.
-   * @param maxStringLength The maximum length of a field. Too long fields will
-   * be output as "null". The 0 value means no maximum length.
-   * @return The NULL value if the case of an error, or the JSON
-   * string. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomInstanceToJson
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomInstanceToJson(
-    OrthancPluginContext*           context,
-    const char*                     instanceId,
-    OrthancPluginDicomToJsonFormat  format,
-    OrthancPluginDicomToJsonFlags   flags, 
-    uint32_t                        maxStringLength)
-  {
-    char* result;
-
-    _OrthancPluginDicomToJson params;
-    memset(&params, 0, sizeof(params));
-    params.result = &result;
-    params.instanceId = instanceId;
-    params.format = format;
-    params.flags = flags;
-    params.maxStringLength = maxStringLength;
-
-    if (context->InvokeService(context, _OrthancPluginService_DicomInstanceToJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-    uint32_t                    headersCount;
-    const char* const*          headersKeys;
-    const char* const*          headersValues;
-    int32_t                     afterPlugins;
-  } _OrthancPluginRestApiGet2;
-
-  /**
-   * @brief Make a GET call to the Orthanc REST API, with custom HTTP headers.
-   * 
-   * Make a GET call to the Orthanc REST API with extended
-   * parameters. The result to the query is stored into a newly
-   * allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param headersCount The number of HTTP headers.
-   * @param headersKeys Array containing the keys of the HTTP headers.
-   * @param headersValues Array containing the values of the HTTP headers.
-   * @param afterPlugins If 0, the built-in API of Orthanc is used.
-   * If 1, the API is tainted by the plugins.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGet, OrthancPluginRestApiGetAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGet2(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    uint32_t                    headersCount,
-    const char* const*          headersKeys,
-    const char* const*          headersValues,
-    int32_t                     afterPlugins)
-  {
-    _OrthancPluginRestApiGet2 params;
-    params.target = target;
-    params.uri = uri;
-    params.headersCount = headersCount;
-    params.headersKeys = headersKeys;
-    params.headersValues = headersValues;
-    params.afterPlugins = afterPlugins;
-
-    return context->InvokeService(context, _OrthancPluginService_RestApiGet2, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginWorklistCallback callback;
-  } _OrthancPluginWorklistCallback;
-
-  /**
-   * @brief Register a callback to handle modality worklists requests.
-   *
-   * This function registers a callback to handle C-Find SCP requests
-   * on modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterWorklistCallback(
-    OrthancPluginContext*          context,
-    OrthancPluginWorklistCallback  callback)
-  {
-    _OrthancPluginWorklistCallback params;
-    params.callback = callback;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterWorklistCallback, &params);
-  }
-
-
-  
-  typedef struct
-  {
-    OrthancPluginWorklistAnswers*      answers;
-    const OrthancPluginWorklistQuery*  query;
-    const void*                        dicom;
-    uint32_t                           size;
-  } _OrthancPluginWorklistAnswersOperation;
-
-  /**
-   * @brief Add one answer to some modality worklist request.
-   *
-   * This function adds one worklist (encoded as a DICOM file) to the
-   * set of answers corresponding to some C-Find SCP request against
-   * modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param answers The set of answers.
-   * @param query The worklist query, as received by the callback.
-   * @param dicom The worklist to answer, encoded as a DICOM file.
-   * @param size The size of the DICOM file.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistAddAnswer(
-    OrthancPluginContext*             context,
-    OrthancPluginWorklistAnswers*     answers,
-    const OrthancPluginWorklistQuery* query,
-    const void*                       dicom,
-    uint32_t                          size)
-  {
-    _OrthancPluginWorklistAnswersOperation params;
-    params.answers = answers;
-    params.query = query;
-    params.dicom = dicom;
-    params.size = size;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistAddAnswer, &params);
-  }
-
-
-  /**
-   * @brief Mark the set of worklist answers as incomplete.
-   *
-   * This function marks as incomplete the set of answers
-   * corresponding to some C-Find SCP request against modality
-   * worklists. This must be used if canceling the handling of a
-   * request when too many answers are to be returned.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param answers The set of answers.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistMarkIncomplete(
-    OrthancPluginContext*          context,
-    OrthancPluginWorklistAnswers*  answers)
-  {
-    _OrthancPluginWorklistAnswersOperation params;
-    params.answers = answers;
-    params.query = NULL;
-    params.dicom = NULL;
-    params.size = 0;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistMarkIncomplete, &params);
-  }
-
-
-  typedef struct
-  {
-    const OrthancPluginWorklistQuery*  query;
-    const void*                        dicom;
-    uint32_t                           size;
-    int32_t*                           isMatch;
-    OrthancPluginMemoryBuffer*         target;
-  } _OrthancPluginWorklistQueryOperation;
-
-  /**
-   * @brief Test whether a worklist matches the query.
-   *
-   * This function checks whether one worklist (encoded as a DICOM
-   * file) matches the C-Find SCP query against modality
-   * worklists. This function must be called before adding the
-   * worklist as an answer through OrthancPluginWorklistAddAnswer().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param query The worklist query, as received by the callback.
-   * @param dicom The worklist to answer, encoded as a DICOM file.
-   * @param size The size of the DICOM file.
-   * @return 1 if the worklist matches the query, 0 otherwise.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE int32_t  OrthancPluginWorklistIsMatch(
-    OrthancPluginContext*              context,
-    const OrthancPluginWorklistQuery*  query,
-    const void*                        dicom,
-    uint32_t                           size)
-  {
-    int32_t isMatch = 0;
-
-    _OrthancPluginWorklistQueryOperation params;
-    params.query = query;
-    params.dicom = dicom;
-    params.size = size;
-    params.isMatch = &isMatch;
-    params.target = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_WorklistIsMatch, &params) == OrthancPluginErrorCode_Success)
-    {
-      return isMatch;
-    }
-    else
-    {
-      /* Error: Assume non-match */
-      return 0;
-    }
-  }
-
-
-  /**
-   * @brief Retrieve the worklist query as a DICOM file.
-   *
-   * This function retrieves the DICOM file that underlies a C-Find
-   * SCP query against modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target Memory buffer where to store the DICOM file. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param query The worklist query, as received by the callback.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistGetDicomQuery(
-    OrthancPluginContext*              context,
-    OrthancPluginMemoryBuffer*         target,
-    const OrthancPluginWorklistQuery*  query)
-  {
-    _OrthancPluginWorklistQueryOperation params;
-    params.query = query;
-    params.dicom = NULL;
-    params.size = 0;
-    params.isMatch = NULL;
-    params.target = target;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistGetDicomQuery, &params);
-  }
-
-
-  /**
-   * @brief Get the origin of a DICOM file.
-   *
-   * This function returns the origin of a DICOM instance that has been received by Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The origin of the instance.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginInstanceOrigin OrthancPluginGetInstanceOrigin(
-    OrthancPluginContext*       context,
-    OrthancPluginDicomInstance* instance)
-  {
-    OrthancPluginInstanceOrigin origin;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultOrigin = &origin;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return OrthancPluginInstanceOrigin_Unknown;
-    }
-    else
-    {
-      return origin;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*     target;
-    const char*                    json;
-    const OrthancPluginImage*      pixelData;
-    OrthancPluginCreateDicomFlags  flags;
-  } _OrthancPluginCreateDicom;
-
-  /**
-   * @brief Create a DICOM instance from a JSON string and an image.
-   *
-   * This function takes as input a string containing a JSON file
-   * describing the content of a DICOM instance. As an output, it
-   * writes the corresponding DICOM instance to a newly allocated
-   * memory buffer. Additionally, an image to be encoded within the
-   * DICOM instance can also be provided.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param json The input JSON file.
-   * @param pixelData The image. Can be NULL, if the pixel data is encoded inside the JSON with the data URI scheme.
-   * @param flags Flags governing the output.
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomBufferToJson
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCreateDicom(
-    OrthancPluginContext*          context,
-    OrthancPluginMemoryBuffer*     target,
-    const char*                    json,
-    const OrthancPluginImage*      pixelData,
-    OrthancPluginCreateDicomFlags  flags)
-  {
-    _OrthancPluginCreateDicom params;
-    params.target = target;
-    params.json = json;
-    params.pixelData = pixelData;
-    params.flags = flags;
-
-    return context->InvokeService(context, _OrthancPluginService_CreateDicom, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginDecodeImageCallback callback;
-  } _OrthancPluginDecodeImageCallback;
-
-  /**
-   * @brief Register a callback to handle the decoding of DICOM images.
-   *
-   * This function registers a custom callback to the decoding of
-   * DICOM images, replacing the built-in decoder 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 OrthancPluginRegisterDecodeImageCallback(
-    OrthancPluginContext*             context,
-    OrthancPluginDecodeImageCallback  callback)
-  {
-    _OrthancPluginDecodeImageCallback params;
-    params.callback = callback;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterDecodeImageCallback, &params);
-  }
-  
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    OrthancPluginPixelFormat   format;
-    uint32_t                   width;
-    uint32_t                   height;
-    uint32_t                   pitch;
-    void*                      buffer;
-    const void*                constBuffer;
-    uint32_t                   bufferSize;
-    uint32_t                   frameIndex;
-  } _OrthancPluginCreateImage;
-
-
-  /**
-   * @brief Create an image.
-   *
-   * This function creates an image of given size and format.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param format The format of the pixels.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @return The newly allocated image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImage(
-    OrthancPluginContext*     context,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.format = format;
-    params.width = width;
-    params.height = height;
-
-    if (context->InvokeService(context, _OrthancPluginService_CreateImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-  /**
-   * @brief Create an image pointing to a memory buffer.
-   *
-   * This function creates an image whose content points to a memory
-   * buffer managed by the plugin. Note that the buffer is directly
-   * accessed, no memory is allocated and no data is copied.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param format The format of the pixels.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer.
-   * @return The newly allocated image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImageAccessor(
-    OrthancPluginContext*     context,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    void*                     buffer)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.format = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-
-    if (context->InvokeService(context, _OrthancPluginService_CreateImageAccessor, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  /**
-   * @brief Decode one frame from a DICOM instance.
-   *
-   * This function decodes one frame of a DICOM image that is stored
-   * in a memory buffer. This function will give the same result as
-   * OrthancPluginUncompressImage() for single-frame DICOM images.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer Pointer to a memory buffer containing the DICOM image.
-   * @param bufferSize Size of the memory buffer containing the DICOM image.
-   * @param frameIndex The index of the frame of interest in a multi-frame image.
-   * @return The uncompressed image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginDecodeDicomImage(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               bufferSize,
-    uint32_t               frameIndex)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.constBuffer = buffer;
-    params.bufferSize = bufferSize;
-    params.frameIndex = frameIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    char**       result;
-    const void*  buffer;
-    uint32_t     size;
-  } _OrthancPluginComputeHash;
-
-  /**
-   * @brief Compute an MD5 hash.
-   *
-   * This functions computes the MD5 cryptographic hash of the given memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The source memory buffer.
-   * @param size The size in bytes of the source buffer.
-   * @return The NULL value in case of error, or a string containing the cryptographic hash.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeMd5(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               size)
-  {
-    char* result;
-
-    _OrthancPluginComputeHash params;
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-
-    if (context->InvokeService(context, _OrthancPluginService_ComputeMd5, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Compute a SHA-1 hash.
-   *
-   * This functions computes the SHA-1 cryptographic hash of the given memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The source memory buffer.
-   * @param size The size in bytes of the source buffer.
-   * @return The NULL value in case of error, or a string containing the cryptographic hash.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeSha1(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               size)
-  {
-    char* result;
-
-    _OrthancPluginComputeHash params;
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-
-    if (context->InvokeService(context, _OrthancPluginService_ComputeSha1, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginDictionaryEntry* target;
-    const char*                   name;
-  } _OrthancPluginLookupDictionary;
-
-  /**
-   * @brief Get information about the given DICOM tag.
-   *
-   * This functions makes a lookup in the dictionary of DICOM tags
-   * that are known to Orthanc, and returns information about this
-   * tag. The tag can be specified using its human-readable name
-   * (e.g. "PatientName") or a set of two hexadecimal numbers
-   * (e.g. "0010-0020").
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target Where to store the information about the tag.
-   * @param name The name of the DICOM tag.
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginLookupDictionary(
-    OrthancPluginContext*          context,
-    OrthancPluginDictionaryEntry*  target,
-    const char*                    name)
-  {
-    _OrthancPluginLookupDictionary params;
-    params.target = target;
-    params.name = name;
-    return context->InvokeService(context, _OrthancPluginService_LookupDictionary, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              answer;
-    uint32_t                 answerSize;
-    uint32_t                 headersCount;
-    const char* const*       headersKeys;
-    const char* const*       headersValues;
-  } _OrthancPluginSendMultipartItem2;
-
-  /**
-   * @brief Send an item as a part of some HTTP multipart answer, with custom headers.
-   *
-   * This function sends an item as a part of some HTTP multipart
-   * answer that was initiated by OrthancPluginStartMultipartAnswer(). In addition to
-   * OrthancPluginSendMultipartItem(), this function will set HTTP header associated
-   * with the item.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the item.
-   * @param answerSize Number of bytes of the item.
-   * @param headersCount The number of HTTP headers.
-   * @param headersKeys Array containing the keys of the HTTP headers.
-   * @param headersValues Array containing the values of the HTTP headers.
-   * @return 0 if success, or the error code if failure (this notably happens
-   * if the connection is closed by the client).
-   * @see OrthancPluginSendMultipartItem()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem2(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize,
-    uint32_t                 headersCount,
-    const char* const*       headersKeys,
-    const char* const*       headersValues)
-  {
-    _OrthancPluginSendMultipartItem2 params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.headersCount = headersCount;
-    params.headersKeys = headersKeys;
-    params.headersValues = headersValues;    
-
-    return context->InvokeService(context, _OrthancPluginService_SendMultipartItem2, &params);
-  }
-
-
-#ifdef  __cplusplus
-}
-#endif
-
-
-/** @} */
-
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# This is the list of the symbols that must be exported by Orthanc
-# plugins, if targeting OS X
-
-_OrthancPluginInitialize
-_OrthancPluginFinalize
-_OrthancPluginGetName
-_OrthancPluginGetVersion
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3383 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "OrthancPluginCppWrapper.h"
-
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/move/unique_ptr.hpp>
-#include <boost/thread.hpp>
-#include <json/reader.h>
-#include <json/writer.h>
-
-
-#if !ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
-static const OrthancPluginErrorCode OrthancPluginErrorCode_NullPointer = OrthancPluginErrorCode_Plugin;
-#endif
-
-
-namespace OrthancPlugins
-{
-  static OrthancPluginContext* globalContext_ = NULL;
-
-
-  void SetGlobalContext(OrthancPluginContext* context)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
-    }
-    else if (globalContext_ == NULL)
-    {
-      globalContext_ = context;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
-    }
-  }
-
-
-  bool HasGlobalContext()
-  {
-    return globalContext_ != NULL;
-  }
-
-
-  OrthancPluginContext* GetGlobalContext()
-  {
-    if (globalContext_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
-    }
-    else
-    {
-      return globalContext_;
-    }
-  }
-
-
-  void MemoryBuffer::Check(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code)
-  {
-    if (code != OrthancPluginErrorCode_Success)
-    {
-      // Prevent using garbage information
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (code == OrthancPluginErrorCode_UnknownResource ||
-             code == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-
-
-  MemoryBuffer::MemoryBuffer()
-  {
-    buffer_.data = NULL;
-    buffer_.size = 0;
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  MemoryBuffer::MemoryBuffer(const void* buffer,
-                             size_t size)
-  {
-    uint32_t s = static_cast<uint32_t>(size);
-    if (static_cast<size_t>(s) != size)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) !=
-             OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else
-    {
-      memcpy(buffer_.data, buffer, size);
-    }
-  }
-#endif
-
-
-  void MemoryBuffer::Clear()
-  {
-    if (buffer_.data != NULL)
-    {
-      OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &buffer_);
-      buffer_.data = NULL;
-      buffer_.size = 0;
-    }
-  }
-
-
-  void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
-  {
-    Clear();
-
-    buffer_.data = other.data;
-    buffer_.size = other.size;
-
-    other.data = NULL;
-    other.size = 0;
-  }
-
-
-  void MemoryBuffer::Swap(MemoryBuffer& other)
-  {
-    std::swap(buffer_.data, other.buffer_.data);
-    std::swap(buffer_.size, other.buffer_.size);
-  }
-
-
-  OrthancPluginMemoryBuffer MemoryBuffer::Release()
-  {
-    OrthancPluginMemoryBuffer result = buffer_;
-
-    buffer_.data = NULL;
-    buffer_.size = 0;
-
-    return result;
-  }
-
-
-  void MemoryBuffer::ToString(std::string& target) const
-  {
-    if (buffer_.size == 0)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size);
-    }
-  }
-
-
-  void MemoryBuffer::ToJson(Json::Value& target) const
-  {
-    if (buffer_.data == NULL ||
-        buffer_.size == 0)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    const char* tmp = reinterpret_cast<const char*>(buffer_.data);
-
-    Json::Reader reader;
-    if (!reader.parse(tmp, tmp + buffer_.size, target))
-    {
-      LogError("Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiGet(const std::string& uri,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str()));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
-    }
-  }
-
-  bool MemoryBuffer::RestApiGet(const std::string& uri,
-                                const std::map<std::string, std::string>& httpHeaders,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    std::vector<const char*> headersKeys;
-    std::vector<const char*> headersValues;
-    
-    for (std::map<std::string, std::string>::const_iterator
-           it = httpHeaders.begin(); it != httpHeaders.end(); it++)
-    {
-      headersKeys.push_back(it->first.c_str());
-      headersValues.push_back(it->second.c_str());
-    }
-
-    return CheckHttp(OrthancPluginRestApiGet2(
-                       GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(),
-                       (headersKeys.empty() ? NULL : &headersKeys[0]),
-                       (headersValues.empty() ? NULL : &headersValues[0]), applyPlugins));
-  }
-
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const void* body,
-                                 size_t bodySize,
-                                 bool applyPlugins)
-  {
-    Clear();
-    
-    // Cast for compatibility with Orthanc SDK <= 1.5.6
-    const char* b = reinterpret_cast<const char*>(body);
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const void* body,
-                                size_t bodySize,
-                                bool applyPlugins)
-  {
-    Clear();
-
-    // Cast for compatibility with Orthanc SDK <= 1.5.6
-    const char* b = reinterpret_cast<const char*>(body);
-
-    if (applyPlugins)
-    {
-      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-    else
-    {
-      return CheckHttp(OrthancPluginRestApiPut(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
-    }
-  }
-
-
-  bool MemoryBuffer::RestApiPost(const std::string& uri,
-                                 const Json::Value& body,
-                                 bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool MemoryBuffer::RestApiPut(const std::string& uri,
-                                const Json::Value& body,
-                                bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(uri, writer.write(body), applyPlugins);
-  }
-
-
-  void MemoryBuffer::CreateDicom(const Json::Value& tags,
-                                 OrthancPluginCreateDicomFlags flags)
-  {
-    Clear();
-
-    Json::FastWriter writer;
-    std::string s = writer.write(tags);
-
-    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), NULL, flags));
-  }
-
-  void MemoryBuffer::CreateDicom(const Json::Value& tags,
-                                 const OrthancImage& pixelData,
-                                 OrthancPluginCreateDicomFlags flags)
-  {
-    Clear();
-
-    Json::FastWriter writer;
-    std::string s = writer.write(tags);
-
-    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), pixelData.GetObject(), flags));
-  }
-
-
-  void MemoryBuffer::ReadFile(const std::string& path)
-  {
-    Clear();
-    Check(OrthancPluginReadFile(GetGlobalContext(), &buffer_, path.c_str()));
-  }
-
-
-  void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query)
-  {
-    Clear();
-    Check(OrthancPluginWorklistGetDicomQuery(GetGlobalContext(), &buffer_, query));
-  }
-
-
-  void OrthancString::Assign(char* str)
-  {
-    Clear();
-
-    if (str != NULL)
-    {
-      str_ = str;
-    }
-  }
-
-
-  void OrthancString::Clear()
-  {
-    if (str_ != NULL)
-    {
-      OrthancPluginFreeString(GetGlobalContext(), str_);
-      str_ = NULL;
-    }
-  }
-
-
-  void OrthancString::ToString(std::string& target) const
-  {
-    if (str_ == NULL)
-    {
-      target.clear();
-    }
-    else
-    {
-      target.assign(str_);
-    }
-  }
-
-
-  void OrthancString::ToJson(Json::Value& target) const
-  {
-    if (str_ == NULL)
-    {
-      LogError("Cannot convert an empty memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Reader reader;
-    if (!reader.parse(str_, target))
-    {
-      LogError("Cannot convert some memory buffer to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void MemoryBuffer::DicomToJson(Json::Value& target,
-                                 OrthancPluginDicomToJsonFormat format,
-                                 OrthancPluginDicomToJsonFlags flags,
-                                 uint32_t maxStringLength)
-  {
-    OrthancString str;
-    str.Assign(OrthancPluginDicomBufferToJson
-               (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
-    str.ToJson(target);
-  }
-
-
-  bool MemoryBuffer::HttpGet(const std::string& url,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpGet(GetGlobalContext(), &buffer_, url.c_str(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-
-
-  bool MemoryBuffer::HttpPost(const std::string& url,
-                              const std::string& body,
-                              const std::string& username,
-                              const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
-                                           body.c_str(), body.size(),
-                                           username.empty() ? NULL : username.c_str(),
-                                           password.empty() ? NULL : password.c_str()));
-  }
-
-
-  bool MemoryBuffer::HttpPut(const std::string& url,
-                             const std::string& body,
-                             const std::string& username,
-                             const std::string& password)
-  {
-    Clear();
-    return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
-                                          body.empty() ? NULL : body.c_str(),
-                                          body.size(),
-                                          username.empty() ? NULL : username.c_str(),
-                                          password.empty() ? NULL : password.c_str()));
-  }
-
-
-  void MemoryBuffer::GetDicomInstance(const std::string& instanceId)
-  {
-    Clear();
-    Check(OrthancPluginGetDicomForInstance(GetGlobalContext(), &buffer_, instanceId.c_str()));
-  }
-
-
-  bool HttpDelete(const std::string& url,
-                  const std::string& username,
-                  const std::string& password)
-  {
-    OrthancPluginErrorCode error = OrthancPluginHttpDelete
-      (GetGlobalContext(), url.c_str(),
-       username.empty() ? NULL : username.c_str(),
-       password.empty() ? NULL : password.c_str());
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-
-
-  void LogError(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogError(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void LogWarning(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void LogInfo(const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
-    }
-  }
-
-
-  void OrthancConfiguration::LoadConfiguration()
-  {
-    OrthancString str;
-    str.Assign(OrthancPluginGetConfiguration(GetGlobalContext()));
-
-    if (str.GetContent() == NULL)
-    {
-      LogError("Cannot access the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    str.ToJson(configuration_);
-
-    if (configuration_.type() != Json::objectValue)
-    {
-      LogError("Unable to read the Orthanc configuration");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-    
-
-  OrthancConfiguration::OrthancConfiguration()
-  {
-    LoadConfiguration();
-  }
-
-
-  OrthancConfiguration::OrthancConfiguration(bool loadConfiguration)
-  {
-    if (loadConfiguration)
-    {
-      LoadConfiguration();
-    }
-    else
-    {
-      configuration_ = Json::objectValue;
-    }
-  }
-
-
-  std::string OrthancConfiguration::GetPath(const std::string& key) const
-  {
-    if (path_.empty())
-    {
-      return key;
-    }
-    else
-    {
-      return path_ + "." + key;
-    }
-  }
-
-
-  bool OrthancConfiguration::IsSection(const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    return (configuration_.isMember(key) &&
-            configuration_[key].type() == Json::objectValue);
-  }
-
-
-  void OrthancConfiguration::GetSection(OrthancConfiguration& target,
-                                        const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.path_ = GetPath(key);
-
-    if (!configuration_.isMember(key))
-    {
-      target.configuration_ = Json::objectValue;
-    }
-    else
-    {
-      if (configuration_[key].type() != Json::objectValue)
-      {
-        LogError("The configuration section \"" + target.path_ +
-                 "\" is not an associative array as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-
-      target.configuration_ = configuration_[key];
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupStringValue(std::string& target,
-                                               const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::stringValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a string as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asString();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupIntegerValue(int& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::intValue:
-        target = configuration_[key].asInt();
-        return true;
-
-      case Json::uintValue:
-        target = configuration_[key].asUInt();
-        return true;
-
-      default:
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not an integer as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target,
-                                                        const std::string& key) const
-  {
-    int tmp;
-    if (!LookupIntegerValue(tmp, key))
-    {
-      return false;
-    }
-
-    if (tmp < 0)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a positive integer as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-    else
-    {
-      target = static_cast<unsigned int>(tmp);
-      return true;
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupBooleanValue(bool& target,
-                                                const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    if (configuration_[key].type() != Json::booleanValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a Boolean as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    target = configuration_[key].asBool();
-    return true;
-  }
-
-
-  bool OrthancConfiguration::LookupFloatValue(float& target,
-                                              const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::realValue:
-        target = configuration_[key].asFloat();
-        return true;
-
-      case Json::intValue:
-        target = static_cast<float>(configuration_[key].asInt());
-        return true;
-
-      case Json::uintValue:
-        target = static_cast<float>(configuration_[key].asUInt());
-        return true;
-
-      default:
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not an integer as expected");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target,
-                                                 const std::string& key,
-                                                 bool allowSingleString) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.clear();
-
-    if (!configuration_.isMember(key))
-    {
-      return false;
-    }
-
-    switch (configuration_[key].type())
-    {
-      case Json::arrayValue:
-      {
-        bool ok = true;
-
-        for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++)
-        {
-          if (configuration_[key][i].type() == Json::stringValue)
-          {
-            target.push_back(configuration_[key][i].asString());
-          }
-          else
-          {
-            ok = false;
-          }
-        }
-
-        if (ok)
-        {
-          return true;
-        }
-
-        break;
-      }
-
-      case Json::stringValue:
-        if (allowSingleString)
-        {
-          target.push_back(configuration_[key].asString());
-          return true;
-        }
-
-        break;
-
-      default:
-        break;
-    }
-
-    LogError("The configuration option \"" + GetPath(key) +
-             "\" is not a list of strings as expected");
-
-    ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-  }
-
-
-  bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target,
-                                                const std::string& key,
-                                                bool allowSingleString) const
-  {
-    std::list<std::string> lst;
-
-    if (LookupListOfStrings(lst, key, allowSingleString))
-    {
-      target.clear();
-
-      for (std::list<std::string>::const_iterator
-             it = lst.begin(); it != lst.end(); ++it)
-      {
-        target.insert(*it);
-      }
-
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  std::string OrthancConfiguration::GetStringValue(const std::string& key,
-                                                   const std::string& defaultValue) const
-  {
-    std::string tmp;
-    if (LookupStringValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  int OrthancConfiguration::GetIntegerValue(const std::string& key,
-                                            int defaultValue) const
-  {
-    int tmp;
-    if (LookupIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key,
-                                                             unsigned int defaultValue) const
-  {
-    unsigned int tmp;
-    if (LookupUnsignedIntegerValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  bool OrthancConfiguration::GetBooleanValue(const std::string& key,
-                                             bool defaultValue) const
-  {
-    bool tmp;
-    if (LookupBooleanValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  float OrthancConfiguration::GetFloatValue(const std::string& key,
-                                            float defaultValue) const
-  {
-    float tmp;
-    if (LookupFloatValue(tmp, key))
-    {
-      return tmp;
-    }
-    else
-    {
-      return defaultValue;
-    }
-  }
-
-
-  void OrthancConfiguration::GetDictionary(std::map<std::string, std::string>& target,
-                                           const std::string& key) const
-  {
-    assert(configuration_.type() == Json::objectValue);
-
-    target.clear();
-
-    if (!configuration_.isMember(key))
-    {
-      return;
-    }
-
-    if (configuration_[key].type() != Json::objectValue)
-    {
-      LogError("The configuration option \"" + GetPath(key) +
-               "\" is not a string as expected");
-
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-
-    Json::Value::Members members = configuration_[key].getMemberNames();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& value = configuration_[key][members[i]];
-
-      if (value.type() == Json::stringValue)
-      {
-        target[members[i]] = value.asString();
-      }
-      else
-      {
-        LogError("The configuration option \"" + GetPath(key) +
-                 "\" is not a dictionary mapping strings to strings");
-
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-      }
-    }
-  }
-
-
-  void OrthancImage::Clear()
-  {
-    if (image_ != NULL)
-    {
-      OrthancPluginFreeImage(GetGlobalContext(), image_);
-      image_ = NULL;
-    }
-  }
-
-
-  void OrthancImage::CheckImageAvailable() const
-  {
-    if (image_ == NULL)
-    {
-      LogError("Trying to access a NULL image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancImage::OrthancImage() :
-    image_(NULL)
-  {
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginImage*  image) :
-    image_(image)
-  {
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height)
-  {
-    image_ = OrthancPluginCreateImage(GetGlobalContext(), format, width, height);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot create an image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height,
-                             uint32_t                  pitch,
-                             void*                     buffer)
-  {
-    image_ = OrthancPluginCreateImageAccessor
-      (GetGlobalContext(), format, width, height, pitch, buffer);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot create an image accessor");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-  void OrthancImage::UncompressPngImage(const void* data,
-                                        size_t size)
-  {
-    Clear();
-
-    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Png);
-
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a PNG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::UncompressJpegImage(const void* data,
-                                         size_t size)
-  {
-    Clear();
-    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a JPEG image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void OrthancImage::DecodeDicomImage(const void* data,
-                                      size_t size,
-                                      unsigned int frame)
-  {
-    Clear();
-    image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
-    if (image_ == NULL)
-    {
-      LogError("Cannot uncompress a DICOM image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancPluginPixelFormat OrthancImage::GetPixelFormat() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePixelFormat(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetWidth() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageWidth(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetHeight() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageHeight(GetGlobalContext(), image_);
-  }
-
-
-  unsigned int OrthancImage::GetPitch() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImagePitch(GetGlobalContext(), image_);
-  }
-
-
-  void* OrthancImage::GetBuffer() const
-  {
-    CheckImageAvailable();
-    return OrthancPluginGetImageBuffer(GetGlobalContext(), image_);
-  }
-
-
-  void OrthancImage::CompressPngImage(MemoryBuffer& target) const
-  {
-    CheckImageAvailable();
-
-    OrthancPlugins::MemoryBuffer answer;
-    OrthancPluginCompressPngImage(GetGlobalContext(), *answer, GetPixelFormat(),
-                                  GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-
-    target.Swap(answer);
-  }
-
-
-  void OrthancImage::CompressJpegImage(MemoryBuffer& target,
-                                       uint8_t quality) const
-  {
-    CheckImageAvailable();
-
-    OrthancPlugins::MemoryBuffer answer;
-    OrthancPluginCompressJpegImage(GetGlobalContext(), *answer, GetPixelFormat(),
-                                   GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-
-    target.Swap(answer);
-  }
-
-
-  void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output) const
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerPngImage(GetGlobalContext(), output, GetPixelFormat(),
-                                           GetWidth(), GetHeight(), GetPitch(), GetBuffer());
-  }
-
-
-  void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output,
-                                     uint8_t quality) const
-  {
-    CheckImageAvailable();
-    OrthancPluginCompressAndAnswerJpegImage(GetGlobalContext(), output, GetPixelFormat(),
-                                            GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
-  }
-
-
-  OrthancPluginImage* OrthancImage::Release()
-  {
-    CheckImageAvailable();
-    OrthancPluginImage* tmp = image_;
-    image_ = NULL;
-    return tmp;
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
-    matcher_(NULL),
-    worklist_(worklist)
-  {
-    if (worklist_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  void FindMatcher::SetupDicom(const void*  query,
-                               uint32_t     size)
-  {
-    worklist_ = NULL;
-
-    matcher_ = OrthancPluginCreateFindMatcher(GetGlobalContext(), query, size);
-    if (matcher_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-
-  FindMatcher::~FindMatcher()
-  {
-    // The "worklist_" field
-
-    if (matcher_ != NULL)
-    {
-      OrthancPluginFreeFindMatcher(GetGlobalContext(), matcher_);
-    }
-  }
-
-
-
-  bool FindMatcher::IsMatch(const void*  dicom,
-                            uint32_t     size) const
-  {
-    int32_t result;
-
-    if (matcher_ != NULL)
-    {
-      result = OrthancPluginFindMatcherIsMatch(GetGlobalContext(), matcher_, dicom, size);
-    }
-    else if (worklist_ != NULL)
-    {
-      result = OrthancPluginWorklistIsMatch(GetGlobalContext(), worklist_, dicom, size);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    if (result == 0)
-    {
-      return false;
-    }
-    else if (result == 1)
-    {
-      return true;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-  }
-
-#endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
-
-  void AnswerJson(const Json::Value& value,
-                  OrthancPluginRestOutput* output
-    )
-  {
-    Json::StyledWriter writer;
-    std::string bodyString = writer.write(value);
-
-    OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json");
-  }
-
-  void AnswerString(const std::string& answer,
-                    const char* mimeType,
-                    OrthancPluginRestOutput* output
-    )
-  {
-    OrthancPluginAnswerBuffer(GetGlobalContext(), output, answer.c_str(), answer.size(), mimeType);
-  }
-
-  void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output)
-  {
-    OrthancPluginSendHttpStatusCode(GetGlobalContext(), output, httpError);
-  }
-
-  void AnswerMethodNotAllowed(OrthancPluginRestOutput *output, const char* allowedMethods)
-  {
-    OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowedMethods);
-  }
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        bool applyPlugins)
-  {
-    MemoryBuffer answer;
-    if (!answer.RestApiGet(uri, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToString(result);
-      return true;
-    }
-  }
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        const std::map<std::string, std::string>& httpHeaders,
-                        bool applyPlugins)
-  {
-    MemoryBuffer answer;
-    if (!answer.RestApiGet(uri, httpHeaders, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      answer.ToString(result);
-      return true;
-    }
-  }
-
-
-
-  bool RestApiGet(Json::Value& result,
-                  const std::string& uri,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiGet(uri, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(std::string& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        result.assign(answer.GetData(), answer.GetSize());
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty())
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPost(result, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const void* body,
-                  size_t bodySize,
-                  bool applyPlugins)
-  {
-    MemoryBuffer answer;
-
-    if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
-    {
-      return false;
-    }
-    else
-    {
-      if (!answer.IsEmpty()) // i.e, on a PUT to metadata/..., orthanc returns an empty response
-      {
-        answer.ToJson(result);
-      }
-      return true;
-    }
-  }
-
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const Json::Value& body,
-                  bool applyPlugins)
-  {
-    Json::FastWriter writer;
-    return RestApiPut(result, uri, writer.write(body), applyPlugins);
-  }
-
-
-  bool RestApiDelete(const std::string& uri,
-                     bool applyPlugins)
-  {
-    OrthancPluginErrorCode error;
-
-    if (applyPlugins)
-    {
-      error = OrthancPluginRestApiDeleteAfterPlugins(GetGlobalContext(), uri.c_str());
-    }
-    else
-    {
-      error = OrthancPluginRestApiDelete(GetGlobalContext(), uri.c_str());
-    }
-
-    if (error == OrthancPluginErrorCode_Success)
-    {
-      return true;
-    }
-    else if (error == OrthancPluginErrorCode_UnknownResource ||
-             error == OrthancPluginErrorCode_InexistentItem)
-    {
-      return false;
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-
-
-  void ReportMinimalOrthancVersion(unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision)
-  {
-    LogError("Your version of the Orthanc core (" +
-             std::string(GetGlobalContext()->orthancVersion) +
-             ") 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) +
-             " is required)");
-  }
-
-
-  bool CheckMinimalOrthancVersion(unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision)
-  {
-    if (!HasGlobalContext())
-    {
-      LogError("Bad Orthanc context in the plugin");
-      return false;
-    }
-
-    if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
-    {
-      // Assume compatibility with the mainline
-      return true;
-    }
-
-    // Parse the version of the Orthanc core
-    int aa, bb, cc;
-    if (
-#ifdef _MSC_VER
-      sscanf_s
-#else
-      sscanf
-#endif
-      (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
-      aa < 0 ||
-      bb < 0 ||
-      cc < 0)
-    {
-      return false;
-    }
-
-    unsigned int a = static_cast<unsigned int>(aa);
-    unsigned int b = static_cast<unsigned int>(bb);
-    unsigned int c = static_cast<unsigned int>(cc);
-
-    // Check the major version number
-
-    if (a > major)
-    {
-      return true;
-    }
-
-    if (a < major)
-    {
-      return false;
-    }
-
-
-    // Check the minor version number
-    assert(a == major);
-
-    if (b > minor)
-    {
-      return true;
-    }
-
-    if (b < minor)
-    {
-      return false;
-    }
-
-    // Check the patch level version number
-    assert(a == major && b == minor);
-
-    if (c >= revision)
-    {
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-  const char* AutodetectMimeType(const std::string& path)
-  {
-    const char* mime = OrthancPluginAutodetectMimeType(GetGlobalContext(), path.c_str());
-
-    if (mime == NULL)
-    {
-      // Should never happen, just for safety
-      return "application/octet-stream";
-    }
-    else
-    {
-      return mime;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
-  size_t OrthancPeers::GetPeerIndex(const std::string& name) const
-  {
-    size_t index;
-    if (LookupName(index, name))
-    {
-      return index;
-    }
-    else
-    {
-      LogError("Inexistent peer: " + name);
-      ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
-    }
-  }
-
-
-  OrthancPeers::OrthancPeers() :
-    peers_(NULL),
-    timeout_(0)
-  {
-    peers_ = OrthancPluginGetPeers(GetGlobalContext());
-
-    if (peers_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-
-    uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
-
-    for (uint32_t i = 0; i < count; i++)
-    {
-      const char* name = OrthancPluginGetPeerName(GetGlobalContext(), peers_, i);
-      if (name == NULL)
-      {
-        OrthancPluginFreePeers(GetGlobalContext(), peers_);
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-
-      index_[name] = i;
-    }
-  }
-
-
-  OrthancPeers::~OrthancPeers()
-  {
-    if (peers_ != NULL)
-    {
-      OrthancPluginFreePeers(GetGlobalContext(), peers_);
-    }
-  }
-
-
-  bool OrthancPeers::LookupName(size_t& target,
-                                const std::string& name) const
-  {
-    Index::const_iterator found = index_.find(name);
-
-    if (found == index_.end())
-    {
-      return false;
-    }
-    else
-    {
-      target = found->second;
-      return true;
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerName(size_t index) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
-      if (s == NULL)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-      else
-      {
-        return s;
-      }
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerUrl(size_t index) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
-      if (s == NULL)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-      }
-      else
-      {
-        return s;
-      }
-    }
-  }
-
-
-  std::string OrthancPeers::GetPeerUrl(const std::string& name) const
-  {
-    return GetPeerUrl(GetPeerIndex(name));
-  }
-
-
-  bool OrthancPeers::LookupUserProperty(std::string& value,
-                                        size_t index,
-                                        const std::string& key) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-    else
-    {
-      const char* s = OrthancPluginGetPeerUserProperty(GetGlobalContext(), peers_, static_cast<uint32_t>(index), key.c_str());
-      if (s == NULL)
-      {
-        return false;
-      }
-      else
-      {
-        value.assign(s);
-        return true;
-      }
-    }
-  }
-
-
-  bool OrthancPeers::LookupUserProperty(std::string& value,
-                                        const std::string& peer,
-                                        const std::string& key) const
-  {
-    return LookupUserProperty(value, GetPeerIndex(peer), key);
-  }
-
-
-  bool OrthancPeers::DoGet(MemoryBuffer& target,
-                           size_t index,
-                           const std::string& uri) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      target.Swap(answer);
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoGet(MemoryBuffer& target,
-                           const std::string& name,
-                           const std::string& uri) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoGet(target, index, uri));
-  }
-
-
-  bool OrthancPeers::DoGet(Json::Value& target,
-                           size_t index,
-                           const std::string& uri) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoGet(buffer, index, uri))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoGet(Json::Value& target,
-                           const std::string& name,
-                           const std::string& uri) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoGet(buffer, name, uri))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(MemoryBuffer& target,
-                            const std::string& name,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoPost(target, index, uri, body));
-  }
-
-
-  bool OrthancPeers::DoPost(Json::Value& target,
-                            size_t index,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoPost(buffer, index, uri, body))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(Json::Value& target,
-                            const std::string& name,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    MemoryBuffer buffer;
-
-    if (DoPost(buffer, name, uri, body))
-    {
-      buffer.ToJson(target);
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPost(MemoryBuffer& target,
-                            size_t index,
-                            const std::string& uri,
-                            const std::string& body) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      target.Swap(answer);
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPut(size_t index,
-                           const std::string& uri,
-                           const std::string& body) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoPut(const std::string& name,
-                           const std::string& uri,
-                           const std::string& body) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoPut(index, uri, body));
-  }
-
-
-  bool OrthancPeers::DoDelete(size_t index,
-                              const std::string& uri) const
-  {
-    if (index >= index_.size())
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    OrthancPlugins::MemoryBuffer answer;
-    uint16_t status;
-    OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
-       static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      return (status == 200);
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  bool OrthancPeers::DoDelete(const std::string& name,
-                              const std::string& uri) const
-  {
-    size_t index;
-    return (LookupName(index, name) &&
-            DoDelete(index, uri));
-  }
-#endif
-
-
-
-
-
-  /******************************************************************
-   ** JOBS
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_JOB == 1
-  void OrthancJob::CallbackFinalize(void* job)
-  {
-    if (job != NULL)
-    {
-      delete reinterpret_cast<OrthancJob*>(job);
-    }
-  }
-
-
-  float OrthancJob::CallbackGetProgress(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->progress_;
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  const char* OrthancJob::CallbackGetContent(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->content_.c_str();
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  const char* OrthancJob::CallbackGetSerialized(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      const OrthancJob& tmp = *reinterpret_cast<OrthancJob*>(job);
-
-      if (tmp.hasSerialized_)
-      {
-        return tmp.serialized_.c_str();
-      }
-      else
-      {
-        return NULL;
-      }
-    }
-    catch (...)
-    {
-      return 0;
-    }
-  }
-
-
-  OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      return reinterpret_cast<OrthancJob*>(job)->Step();
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
-    {
-      return OrthancPluginJobStepStatus_Failure;
-    }
-    catch (...)
-    {
-      return OrthancPluginJobStepStatus_Failure;
-    }
-  }
-
-
-  OrthancPluginErrorCode OrthancJob::CallbackStop(void* job,
-                                                  OrthancPluginJobStopReason reason)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      reinterpret_cast<OrthancJob*>(job)->Stop(reason);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-  OrthancPluginErrorCode OrthancJob::CallbackReset(void* job)
-  {
-    assert(job != NULL);
-
-    try
-    {
-      reinterpret_cast<OrthancJob*>(job)->Reset();
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-  void OrthancJob::ClearContent()
-  {
-    Json::Value empty = Json::objectValue;
-    UpdateContent(empty);
-  }
-
-
-  void OrthancJob::UpdateContent(const Json::Value& content)
-  {
-    if (content.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
-    }
-    else
-    {
-      Json::FastWriter writer;
-      content_ = writer.write(content);
-    }
-  }
-
-
-  void OrthancJob::ClearSerialized()
-  {
-    hasSerialized_ = false;
-    serialized_.clear();
-  }
-
-
-  void OrthancJob::UpdateSerialized(const Json::Value& serialized)
-  {
-    if (serialized.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
-    }
-    else
-    {
-      Json::FastWriter writer;
-      serialized_ = writer.write(serialized);
-      hasSerialized_ = true;
-    }
-  }
-
-
-  void OrthancJob::UpdateProgress(float progress)
-  {
-    if (progress < 0 ||
-        progress > 1)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
-    }
-
-    progress_ = progress;
-  }
-
-
-  OrthancJob::OrthancJob(const std::string& jobType) :
-    jobType_(jobType),
-    progress_(0)
-  {
-    ClearContent();
-    ClearSerialized();
-  }
-
-
-  OrthancPluginJob* OrthancJob::Create(OrthancJob* job)
-  {
-    if (job == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
-    }
-
-    OrthancPluginJob* orthanc = OrthancPluginCreateJob(
-      GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
-      CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
-      CallbackStep, CallbackStop, CallbackReset);
-
-    if (orthanc == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-    else
-    {
-      return orthanc;
-    }
-  }
-
-
-  std::string OrthancJob::Submit(OrthancJob* job,
-                                 int priority)
-  {
-    if (job == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
-    }
-
-    OrthancPluginJob* orthanc = Create(job);
-
-    char* id = OrthancPluginSubmitJob(GetGlobalContext(), orthanc, priority);
-
-    if (id == NULL)
-    {
-      LogError("Plugin cannot submit job");
-      OrthancPluginFreeJob(GetGlobalContext(), orthanc);
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
-    }
-    else
-    {
-      std::string tmp(id);
-      tmp.assign(id);
-      OrthancPluginFreeString(GetGlobalContext(), id);
-
-      return tmp;
-    }
-  }
-
-
-  void OrthancJob::SubmitAndWait(Json::Value& result,
-                                 OrthancJob* job /* takes ownership */,
-                                 int priority)
-  {
-    std::string id = Submit(job, priority);
-
-    for (;;)
-    {
-      boost::this_thread::sleep(boost::posix_time::milliseconds(100));
-
-      Json::Value status;
-      if (!RestApiGet(status, "/jobs/" + id, false) ||
-          !status.isMember("State") ||
-          status["State"].type() != Json::stringValue)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InexistentItem);        
-      }
-
-      const std::string state = status["State"].asString();
-      if (state == "Success")
-      {
-        if (status.isMember("Content"))
-        {
-          result = status["Content"];
-        }
-        else
-        {
-          result = Json::objectValue;
-        }
-
-        return;
-      }
-      else if (state == "Running")
-      {
-        continue;
-      }
-      else if (!status.isMember("ErrorCode") ||
-               status["ErrorCode"].type() != Json::intValue)
-      {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
-      }
-      else
-      {
-        if (!status.isMember("ErrorDescription") ||
-            status["ErrorDescription"].type() != Json::stringValue)
-        {
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());
-        }
-        else
-        {
-#if HAS_ORTHANC_EXCEPTION == 1
-          throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
-                                          status["ErrorDescription"].asString());
-#else
-          LogError("Exception while executing the job: " + status["ErrorDescription"].asString());
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
-#endif
-        }
-      }
-    }
-  }
-
-
-  void OrthancJob::SubmitFromRestApiPost(OrthancPluginRestOutput* output,
-                                         const Json::Value& body,
-                                         OrthancJob* job)
-  {
-    static const char* KEY_SYNCHRONOUS = "Synchronous";
-    static const char* KEY_ASYNCHRONOUS = "Asynchronous";
-    static const char* KEY_PRIORITY = "Priority";
-
-    boost::movelib::unique_ptr<OrthancJob> protection(job);
-  
-    if (body.type() != Json::objectValue)
-    {
-#if HAS_ORTHANC_EXCEPTION == 1
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                      "Expected a JSON object in the body");
-#else
-      LogError("Expected a JSON object in the body");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-    }
-
-    bool synchronous = true;
-  
-    if (body.isMember(KEY_SYNCHRONOUS))
-    {
-      if (body[KEY_SYNCHRONOUS].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_SYNCHRONOUS) +
-                                        "\" must be Boolean");
-#else
-        LogError("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        synchronous = body[KEY_SYNCHRONOUS].asBool();
-      }
-    }
-
-    if (body.isMember(KEY_ASYNCHRONOUS))
-    {
-      if (body[KEY_ASYNCHRONOUS].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_ASYNCHRONOUS) +
-                                        "\" must be Boolean");
-#else
-        LogError("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        synchronous = !body[KEY_ASYNCHRONOUS].asBool();
-      }
-    }
-
-    int priority = 0;
-
-    if (body.isMember(KEY_PRIORITY))
-    {
-      if (body[KEY_PRIORITY].type() != Json::booleanValue)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
-                                        "Option \"" + std::string(KEY_PRIORITY) +
-                                        "\" must be an integer");
-#else
-        LogError("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer");
-        ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-#endif
-      }
-      else
-      {
-        priority = !body[KEY_PRIORITY].asInt();
-      }
-    }
-  
-    Json::Value result;
-
-    if (synchronous)
-    {
-      OrthancPlugins::OrthancJob::SubmitAndWait(result, protection.release(), priority);
-    }
-    else
-    {
-      std::string id = OrthancPlugins::OrthancJob::Submit(protection.release(), priority);
-
-      result = Json::objectValue;
-      result["ID"] = id;
-      result["Path"] = "/jobs/" + id;
-    }
-
-    std::string s = result.toStyledString();
-    OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(),
-                              s.size(), "application/json");
-  }
-
-#endif
-
-
-
-
-  /******************************************************************
-   ** METRICS
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
-  MetricsTimer::MetricsTimer(const char* name) :
-    name_(name)
-  {
-    start_ = boost::posix_time::microsec_clock::universal_time();
-  }
-  
-  MetricsTimer::~MetricsTimer()
-  {
-    const boost::posix_time::ptime stop = boost::posix_time::microsec_clock::universal_time();
-    const boost::posix_time::time_duration diff = stop - start_;
-    OrthancPluginSetMetricsValue(GetGlobalContext(), name_.c_str(), static_cast<float>(diff.total_milliseconds()),
-                                 OrthancPluginMetricsType_Timer);
-  }
-#endif
-
-
-
-
-  /******************************************************************
-   ** HTTP CLIENT
-   ******************************************************************/
-
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
-  class HttpClient::RequestBodyWrapper : public boost::noncopyable
-  {
-  private:
-    static RequestBodyWrapper& GetObject(void* body)
-    {
-      assert(body != NULL);
-      return *reinterpret_cast<RequestBodyWrapper*>(body);
-    }
-
-    IRequestBody&  body_;
-    bool           done_;
-    std::string    chunk_;
-
-  public:
-    RequestBodyWrapper(IRequestBody& body) :
-      body_(body),
-      done_(false)
-    {
-    }      
-
-    static uint8_t IsDone(void* body)
-    {
-      return GetObject(body).done_;
-    }
-    
-    static const void* GetChunkData(void* body)
-    {
-      return GetObject(body).chunk_.c_str();
-    }
-    
-    static uint32_t GetChunkSize(void* body)
-    {
-      return static_cast<uint32_t>(GetObject(body).chunk_.size());
-    }
-
-    static OrthancPluginErrorCode Next(void* body)
-    {
-      RequestBodyWrapper& that = GetObject(body);
-        
-      if (that.done_)
-      {
-        return OrthancPluginErrorCode_BadSequenceOfCalls;
-      }
-      else
-      {
-        try
-        {
-          that.done_ = !that.body_.ReadNextChunk(that.chunk_);
-          return OrthancPluginErrorCode_Success;
-        }
-        catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-        {
-          return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-        }
-        catch (...)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-      }
-    }    
-  };
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  static OrthancPluginErrorCode AnswerAddHeaderCallback(void* answer,
-                                                        const char* key,
-                                                        const char* value)
-  {
-    assert(answer != NULL && key != NULL && value != NULL);
-
-    try
-    {
-      reinterpret_cast<HttpClient::IAnswer*>(answer)->AddHeader(key, value);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  static OrthancPluginErrorCode AnswerAddChunkCallback(void* answer,
-                                                       const void* data,
-                                                       uint32_t size)
-  {
-    assert(answer != NULL);
-
-    try
-    {
-      reinterpret_cast<HttpClient::IAnswer*>(answer)->AddChunk(data, size);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-  HttpClient::HttpClient() :
-    httpStatus_(0),
-    method_(OrthancPluginHttpMethod_Get),
-    timeout_(0),
-    pkcs11_(false),
-    chunkedBody_(NULL),
-    allowChunkedTransfers_(true)
-  {
-  }
-
-
-  void HttpClient::AddHeaders(const HttpHeaders& headers)
-  {
-    for (HttpHeaders::const_iterator it = headers.begin();
-         it != headers.end(); ++it)
-    {
-      headers_[it->first] = it->second;
-    }
-  }
-
-  
-  void HttpClient::SetCredentials(const std::string& username,
-                                  const std::string& password)
-  {
-    username_ = username;
-    password_ = password;
-  }
-
-  
-  void HttpClient::ClearCredentials()
-  {
-    username_.empty();
-    password_.empty();
-  }
-
-
-  void HttpClient::SetCertificate(const std::string& certificateFile,
-                                  const std::string& keyFile,
-                                  const std::string& keyPassword)
-  {
-    certificateFile_ = certificateFile;
-    certificateKeyFile_ = keyFile;
-    certificateKeyPassword_ = keyPassword;
-  }
-
-  
-  void HttpClient::ClearCertificate()
-  {
-    certificateFile_.clear();
-    certificateKeyFile_.clear();
-    certificateKeyPassword_.clear();
-  }
-
-
-  void HttpClient::ClearBody()
-  {
-    fullBody_.clear();
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SwapBody(std::string& body)
-  {
-    fullBody_.swap(body);
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SetBody(const std::string& body)
-  {
-    fullBody_ = body;
-    chunkedBody_ = NULL;
-  }
-
-  
-  void HttpClient::SetBody(IRequestBody& body)
-  {
-    fullBody_.clear();
-    chunkedBody_ = &body;
-  }
-
-
-  namespace
-  {
-    class HeadersWrapper : public boost::noncopyable
-    {
-    private:
-      std::vector<const char*>  headersKeys_;
-      std::vector<const char*>  headersValues_;
-
-    public:
-      HeadersWrapper(const HttpClient::HttpHeaders& headers)
-      {
-        headersKeys_.reserve(headers.size());
-        headersValues_.reserve(headers.size());
-
-        for (HttpClient::HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); ++it)
-        {
-          headersKeys_.push_back(it->first.c_str());
-          headersValues_.push_back(it->second.c_str());
-        }
-      }
-
-      void AddStaticString(const char* key,
-                           const char* value)
-      {
-        headersKeys_.push_back(key);
-        headersValues_.push_back(value);
-      }
-
-      uint32_t GetCount() const
-      {
-        return headersKeys_.size();
-      }
-
-      const char* const* GetKeys() const
-      {
-        return headersKeys_.empty() ? NULL : &headersKeys_[0];
-      }
-
-      const char* const* GetValues() const
-      {
-        return headersValues_.empty() ? NULL : &headersValues_[0];
-      }
-    };
-
-
-    class MemoryRequestBody : public HttpClient::IRequestBody
-    {
-    private:
-      std::string  body_;
-      bool         done_;
-
-    public:
-      MemoryRequestBody(const std::string& body) :
-        body_(body),
-        done_(false)
-      {
-        if (body_.empty())
-        {
-          done_ = true;
-        }
-      }
-
-      virtual bool ReadNextChunk(std::string& chunk)
-      {
-        if (done_)
-        {
-          return false;
-        }
-        else
-        {
-          chunk.swap(body_);
-          done_ = true;
-          return true;
-        }
-      }
-    };
-
-
-    // This class mimics Orthanc::ChunkedBuffer
-    class ChunkedBuffer : public boost::noncopyable
-    {
-    private:
-      typedef std::list<std::string*>  Content;
-
-      Content  content_;
-      size_t   size_;
-
-    public:
-      ChunkedBuffer() :
-        size_(0)
-      {
-      }
-
-      ~ChunkedBuffer()
-      {
-        Clear();
-      }
-
-      void Clear()
-      {
-        for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
-        {
-          assert(*it != NULL);
-          delete *it;
-        }
-
-        content_.clear();
-      }
-
-      void Flatten(std::string& target) const
-      {
-        target.resize(size_);
-
-        size_t pos = 0;
-
-        for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
-        {
-          assert(*it != NULL);
-          size_t s = (*it)->size();
-
-          if (s != 0)
-          {
-            memcpy(&target[pos], (*it)->c_str(), s);
-            pos += s;
-          }
-        }
-
-        assert(size_ == 0 ||
-               pos == target.size());
-      }
-
-      void AddChunk(const void* data,
-                    size_t size)
-      {
-        content_.push_back(new std::string(reinterpret_cast<const char*>(data), size));
-        size_ += size;
-      }
-
-      void AddChunk(const std::string& chunk)
-      {
-        content_.push_back(new std::string(chunk));
-        size_ += chunk.size();
-      }
-    };
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    class MemoryAnswer : public HttpClient::IAnswer
-    {
-    private:
-      HttpClient::HttpHeaders  headers_;
-      ChunkedBuffer            body_;
-
-    public:
-      const HttpClient::HttpHeaders& GetHeaders() const
-      {
-        return headers_;
-      }
-
-      const ChunkedBuffer& GetBody() const
-      {
-        return body_;
-      }
-
-      virtual void AddHeader(const std::string& key,
-                             const std::string& value)
-      {
-        headers_[key] = value;
-      }
-
-      virtual void AddChunk(const void* data,
-                            size_t size)
-      {
-        body_.AddChunk(data, size);
-      }
-    };
-#endif
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-  void HttpClient::ExecuteWithStream(uint16_t& httpStatus,
-                                     IAnswer& answer,
-                                     IRequestBody& body) const
-  {
-    HeadersWrapper h(headers_);
-
-    if (method_ == OrthancPluginHttpMethod_Post ||
-        method_ == OrthancPluginHttpMethod_Put)
-    {
-      // Automatically set the "Transfer-Encoding" header if absent
-      bool found = false;
-
-      for (HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); ++it)
-      {
-        if (boost::iequals(it->first, "Transfer-Encoding"))
-        {
-          found = true;
-          break;
-        }
-      }
-
-      if (!found)
-      {
-        h.AddStaticString("Transfer-Encoding", "chunked");
-      }
-    }
-
-    RequestBodyWrapper request(body);
-        
-    OrthancPluginErrorCode error = OrthancPluginChunkedHttpClient(
-      GetGlobalContext(),
-      &answer,
-      AnswerAddChunkCallback,
-      AnswerAddHeaderCallback,
-      &httpStatus,
-      method_,
-      url_.c_str(),
-      h.GetCount(),
-      h.GetKeys(),
-      h.GetValues(),
-      &request,
-      RequestBodyWrapper::IsDone,
-      RequestBodyWrapper::GetChunkData,
-      RequestBodyWrapper::GetChunkSize,
-      RequestBodyWrapper::Next,
-      username_.empty() ? NULL : username_.c_str(),
-      password_.empty() ? NULL : password_.c_str(),
-      timeout_,
-      certificateFile_.empty() ? NULL : certificateFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(),
-      pkcs11_ ? 1 : 0);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-  }
-#endif    
-
-
-  void HttpClient::ExecuteWithoutStream(uint16_t& httpStatus,
-                                        HttpHeaders& answerHeaders,
-                                        std::string& answerBody,
-                                        const std::string& body) const
-  {
-    HeadersWrapper headers(headers_);
-
-    MemoryBuffer answerBodyBuffer, answerHeadersBuffer;
-
-    OrthancPluginErrorCode error = OrthancPluginHttpClient(
-      GetGlobalContext(),
-      *answerBodyBuffer,
-      *answerHeadersBuffer,
-      &httpStatus,
-      method_,
-      url_.c_str(),
-      headers.GetCount(),
-      headers.GetKeys(),
-      headers.GetValues(),
-      body.empty() ? NULL : body.c_str(),
-      body.size(),
-      username_.empty() ? NULL : username_.c_str(),
-      password_.empty() ? NULL : password_.c_str(),
-      timeout_,
-      certificateFile_.empty() ? NULL : certificateFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(),
-      certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(),
-      pkcs11_ ? 1 : 0);
-
-    if (error != OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
-    }
-
-    Json::Value v;
-    answerHeadersBuffer.ToJson(v);
-
-    if (v.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Value::Members members = v.getMemberNames();
-    answerHeaders.clear();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& h = v[members[i]];
-      if (h.type() != Json::stringValue)
-      {
-        ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-      }
-      else
-      {
-        answerHeaders[members[i]] = h.asString();
-      }
-    }
-
-    answerBodyBuffer.ToString(answerBody);
-  }
-
-
-  void HttpClient::Execute(IAnswer& answer)
-  {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    if (allowChunkedTransfers_)
-    {
-      if (chunkedBody_ != NULL)
-      {
-        ExecuteWithStream(httpStatus_, answer, *chunkedBody_);
-      }
-      else
-      {
-        MemoryRequestBody wrapper(fullBody_);
-        ExecuteWithStream(httpStatus_, answer, wrapper);
-      }
-
-      return;
-    }
-#endif
-    
-    // Compatibility mode for Orthanc SDK <= 1.5.6 or if chunked
-    // transfers are disabled. This results in higher memory usage
-    // (all chunks from the answer body are sent at once)
-
-    HttpHeaders answerHeaders;
-    std::string answerBody;
-    Execute(answerHeaders, answerBody);
-
-    for (HttpHeaders::const_iterator it = answerHeaders.begin(); 
-         it != answerHeaders.end(); ++it)
-    {
-      answer.AddHeader(it->first, it->second);      
-    }
-
-    if (!answerBody.empty())
-    {
-      answer.AddChunk(answerBody.c_str(), answerBody.size());
-    }
-  }
-
-
-  void HttpClient::Execute(HttpHeaders& answerHeaders /* out */,
-                           std::string& answerBody /* out */)
-  {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    if (allowChunkedTransfers_)
-    {
-      MemoryAnswer answer;
-      Execute(answer);
-      answerHeaders = answer.GetHeaders();
-      answer.GetBody().Flatten(answerBody);
-      return;
-    }
-#endif
-    
-    // Compatibility mode for Orthanc SDK <= 1.5.6 or if chunked
-    // transfers are disabled. This results in higher memory usage
-    // (all chunks from the request body are sent at once)
-
-    if (chunkedBody_ != NULL)
-    {
-      ChunkedBuffer buffer;
-      
-      std::string chunk;
-      while (chunkedBody_->ReadNextChunk(chunk))
-      {
-        buffer.AddChunk(chunk);
-      }
-
-      std::string body;
-      buffer.Flatten(body);
-
-      ExecuteWithoutStream(httpStatus_, answerHeaders, answerBody, body);
-    }
-    else
-    {
-      ExecuteWithoutStream(httpStatus_, answerHeaders, answerBody, fullBody_);
-    }
-  }
-
-
-  void HttpClient::Execute(HttpHeaders& answerHeaders /* out */,
-                           Json::Value& answerBody /* out */)
-  {
-    std::string body;
-    Execute(answerHeaders, body);
-    
-    Json::Reader reader;
-    if (!reader.parse(body, answerBody))
-    {
-      LogError("Cannot convert HTTP answer body to JSON");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
-    }
-  }
-
-
-  void HttpClient::Execute()
-  {
-    HttpHeaders answerHeaders;
-    std::string body;
-    Execute(answerHeaders, body);
-  }
-
-#endif  /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */
-
-
-
-
-
-  /******************************************************************
-   ** CHUNKED HTTP SERVER
-   ******************************************************************/
-
-  namespace Internals
-  {
-    void NullRestCallback(OrthancPluginRestOutput* output,
-                          const char* url,
-                          const OrthancPluginHttpRequest* request)
-    {
-    }
-  
-    IChunkedRequestReader *NullChunkedRestCallback(const char* url,
-                                                   const OrthancPluginHttpRequest* request)
-    {
-      return NULL;
-    }
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-
-    OrthancPluginErrorCode ChunkedRequestReaderAddChunk(
-      OrthancPluginServerChunkedRequestReader* reader,
-      const void*                              data,
-      uint32_t                                 size)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-
-        reinterpret_cast<IChunkedRequestReader*>(reader)->AddChunk(data, size);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    
-    OrthancPluginErrorCode ChunkedRequestReaderExecute(
-      OrthancPluginServerChunkedRequestReader* reader,
-      OrthancPluginRestOutput*                 output)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-
-        reinterpret_cast<IChunkedRequestReader*>(reader)->Execute(output);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    
-    void ChunkedRequestReaderFinalize(
-      OrthancPluginServerChunkedRequestReader* reader)
-    {
-      if (reader != NULL)
-      {
-        delete reinterpret_cast<IChunkedRequestReader*>(reader);
-      }
-    }
-
-#else
-    
-    OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                    const char* url,
-                                                    const OrthancPluginHttpRequest* request,
-                                                    RestCallback         GetHandler,
-                                                    ChunkedRestCallback  PostHandler,
-                                                    RestCallback         DeleteHandler,
-                                                    ChunkedRestCallback  PutHandler)
-    {
-      try
-      {
-        std::string allowed;
-
-        if (GetHandler != Internals::NullRestCallback)
-        {
-          allowed += "GET";
-        }
-
-        if (PostHandler != Internals::NullChunkedRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "POST";
-        }
-
-        if (DeleteHandler != Internals::NullRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "DELETE";
-        }
-
-        if (PutHandler != Internals::NullChunkedRestCallback)
-        {
-          if (!allowed.empty())
-          {
-            allowed += ",";
-          }
-        
-          allowed += "PUT";
-        }
-      
-        switch (request->method)
-        {
-          case OrthancPluginHttpMethod_Get:
-            if (GetHandler == Internals::NullRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              GetHandler(output, url, request);
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Post:
-            if (PostHandler == Internals::NullChunkedRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              boost::movelib::unique_ptr<IChunkedRequestReader> reader(PostHandler(url, request));
-              if (reader.get() == NULL)
-              {
-                ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-              }
-              else
-              {
-                reader->AddChunk(request->body, request->bodySize);
-                reader->Execute(output);
-              }
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Delete:
-            if (DeleteHandler == Internals::NullRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              DeleteHandler(output, url, request);
-            }
-
-            break;
-
-          case OrthancPluginHttpMethod_Put:
-            if (PutHandler == Internals::NullChunkedRestCallback)
-            {
-              OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str());
-            }
-            else
-            {
-              boost::movelib::unique_ptr<IChunkedRequestReader> reader(PutHandler(url, request));
-              if (reader.get() == NULL)
-              {
-                ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-              }
-              else
-              {
-                reader->AddChunk(request->body, request->bodySize);
-                reader->Execute(output);
-              }
-            }
-
-            break;
-
-          default:
-            ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-        }
-
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
-        if (HasGlobalContext() &&
-            e.HasDetails())
-        {
-          // The "false" instructs Orthanc not to log the detailed
-          // error message. This is to avoid duplicating the details,
-          // because "OrthancException" already does it on construction.
-          OrthancPluginSetHttpErrorDetails
-            (GetGlobalContext(), output, e.GetDetails(), false);
-        }
-#endif
-
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-#endif
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  OrthancPluginErrorCode IStorageCommitmentScpHandler::Lookup(
-    OrthancPluginStorageCommitmentFailureReason* target,
-    void* rawHandler,
-    const char* sopClassUid,
-    const char* sopInstanceUid)
-  {
-    assert(target != NULL &&
-           rawHandler != NULL);
-      
-    try
-    {
-      IStorageCommitmentScpHandler& handler = *reinterpret_cast<IStorageCommitmentScpHandler*>(rawHandler);
-      *target = handler.Lookup(sopClassUid, sopInstanceUid);
-      return OrthancPluginErrorCode_Success;
-    }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-    {
-      return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-    }
-    catch (...)
-    {
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  void IStorageCommitmentScpHandler::Destructor(void* rawHandler)
-  {
-    assert(rawHandler != NULL);
-    delete reinterpret_cast<IStorageCommitmentScpHandler*>(rawHandler);
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-  DicomInstance::DicomInstance(const OrthancPluginDicomInstance* instance) :
-    toFree_(false),
-    instance_(instance)
-  {
-  }
-#else
-  DicomInstance::DicomInstance(OrthancPluginDicomInstance* instance) :
-    toFree_(false),
-    instance_(instance)
-  {
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  DicomInstance::DicomInstance(const void* buffer,
-                               size_t size) :
-    toFree_(true),
-    instance_(OrthancPluginCreateDicomInstance(GetGlobalContext(), buffer, size))
-  {
-    if (instance_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
-    }
-  }
-#endif
-
-
-  DicomInstance::~DicomInstance()
-  {
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    if (toFree_ &&
-        instance_ != NULL)
-    {
-      OrthancPluginFreeDicomInstance(
-        GetGlobalContext(), const_cast<OrthancPluginDicomInstance*>(instance_));
-    }
-#endif
-  }
-
-  
-  std::string DicomInstance::GetRemoteAet() const
-  {
-    const char* s = OrthancPluginGetInstanceRemoteAet(GetGlobalContext(), instance_);
-    if (s == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return std::string(s);
-    }
-  }
-
-
-  void DicomInstance::GetJson(Json::Value& target) const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceJson(GetGlobalContext(), instance_));
-    s.ToJson(target);
-  }
-  
-
-  void DicomInstance::GetSimplifiedJson(Json::Value& target) const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceSimplifiedJson(GetGlobalContext(), instance_));
-    s.ToJson(target);
-  }
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-  std::string DicomInstance::GetTransferSyntaxUid() const
-  {
-    OrthancString s;
-    s.Assign(OrthancPluginGetInstanceTransferSyntaxUid(GetGlobalContext(), instance_));
-
-    std::string result;
-    s.ToString(result);
-    return result;
-  }
-#endif
-
-  
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-  bool DicomInstance::HasPixelData() const
-  {
-    int32_t result = OrthancPluginHasInstancePixelData(GetGlobalContext(), instance_);
-    if (result < 0)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return (result != 0);
-    }
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)  
-  void DicomInstance::GetRawFrame(std::string& target,
-                                  unsigned int frameIndex) const
-  {
-    MemoryBuffer buffer;
-    OrthancPluginErrorCode code = OrthancPluginGetInstanceRawFrame(
-      GetGlobalContext(), *buffer, instance_, frameIndex);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      buffer.ToString(target);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)  
-  OrthancImage* DicomInstance::GetDecodedFrame(unsigned int frameIndex) const
-  {
-    OrthancPluginImage* image = OrthancPluginGetInstanceDecodedFrame(
-      GetGlobalContext(), instance_, frameIndex);
-
-    if (image == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return new OrthancImage(image);
-    }
-  }
-#endif  
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  void DicomInstance::Serialize(std::string& target) const
-  {
-    MemoryBuffer buffer;
-    OrthancPluginErrorCode code = OrthancPluginSerializeDicomInstance(
-      GetGlobalContext(), *buffer, instance_);
-
-    if (code == OrthancPluginErrorCode_Success)
-    {
-      buffer.ToString(target);
-    }
-    else
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
-    }
-  }
-#endif
-  
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  DicomInstance* DicomInstance::Transcode(const void* buffer,
-                                          size_t size,
-                                          const std::string& transferSyntax)
-  {
-    OrthancPluginDicomInstance* instance = OrthancPluginTranscodeDicomInstance(
-      GetGlobalContext(), buffer, size, transferSyntax.c_str());
-
-    if (instance == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      boost::movelib::unique_ptr<DicomInstance> result(new DicomInstance(instance));
-      result->toFree_ = true;
-      return result.release();
-    }
-  }
-#endif
-}
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1228 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "OrthancPluginException.h"
-
-#include <orthanc/OrthancCPlugin.h>
-#include <boost/noncopyable.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <json/value.h>
-#include <vector>
-#include <list>
-#include <set>
-#include <map>
-
-
-
-/**
- * The definition of ORTHANC_PLUGINS_VERSION_IS_ABOVE below is for
- * backward compatibility with Orthanc SDK <= 1.3.0.
- * 
- *   $ hg diff -r Orthanc-1.3.0:Orthanc-1.3.1 ../../../Plugins/Include/orthanc/OrthancCPlugin.h
- *
- **/
-#if !defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)
-#define ORTHANC_PLUGINS_VERSION_IS_ABOVE(major, minor, revision)        \
-  (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER > major ||                      \
-   (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER == major &&                    \
-    (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER > minor ||                    \
-     (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER == minor &&                  \
-      ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER >= revision))))
-#endif
-
-
-#if !defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE)
-#define ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(major, minor, revision)      \
-  (ORTHANC_VERSION_MAJOR > major ||                                     \
-   (ORTHANC_VERSION_MAJOR == major &&                                   \
-    (ORTHANC_VERSION_MINOR > minor ||                                   \
-     (ORTHANC_VERSION_MINOR == minor &&                                 \
-      ORTHANC_VERSION_REVISION >= revision))))
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
-// The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  1
-#else
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  0
-#endif
-
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 4, 2)
-#  define HAS_ORTHANC_PLUGIN_PEERS  1
-#  define HAS_ORTHANC_PLUGIN_JOB    1
-#else
-#  define HAS_ORTHANC_PLUGIN_PEERS  0
-#  define HAS_ORTHANC_PLUGIN_JOB    0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  1
-#else
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
-#  define HAS_ORTHANC_PLUGIN_METRICS  1
-#else
-#  define HAS_ORTHANC_PLUGIN_METRICS  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 1, 0)
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  1
-#else
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  1
-#else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  1
-#else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  0
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 0)
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  1
-#else
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  0
-#endif
-
-
-
-namespace OrthancPlugins
-{
-  typedef void (*RestCallback) (OrthancPluginRestOutput* output,
-                                const char* url,
-                                const OrthancPluginHttpRequest* request);
-
-  void SetGlobalContext(OrthancPluginContext* context);
-
-  bool HasGlobalContext();
-
-  OrthancPluginContext* GetGlobalContext();
-
-  
-  class OrthancImage;
-
-
-  class MemoryBuffer : public boost::noncopyable
-  {
-  private:
-    OrthancPluginMemoryBuffer  buffer_;
-
-    void Check(OrthancPluginErrorCode code);
-
-    bool CheckHttp(OrthancPluginErrorCode code);
-
-  public:
-    MemoryBuffer();
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    // This constructor makes a copy of the given buffer in the memory
-    // handled by the Orthanc core
-    MemoryBuffer(const void* buffer,
-                 size_t size);
-#endif
-
-    ~MemoryBuffer()
-    {
-      Clear();
-    }
-
-    OrthancPluginMemoryBuffer* operator*()
-    {
-      return &buffer_;
-    }
-
-    // This transfers ownership from "other" to "this"
-    void Assign(OrthancPluginMemoryBuffer& other);
-
-    void Swap(MemoryBuffer& other);
-
-    OrthancPluginMemoryBuffer Release();
-
-    const char* GetData() const
-    {
-      if (buffer_.size > 0)
-      {
-        return reinterpret_cast<const char*>(buffer_.data);
-      }
-      else
-      {
-        return NULL;
-      }
-    }
-
-    size_t GetSize() const
-    {
-      return buffer_.size;
-    }
-
-    bool IsEmpty() const
-    {
-      return GetSize() == 0 || GetData() == NULL;
-    }
-
-    void Clear();
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-
-    bool RestApiGet(const std::string& uri,
-                    bool applyPlugins);
-
-    bool RestApiGet(const std::string& uri,
-                    const std::map<std::string, std::string>& httpHeaders,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const void* body,
-                     size_t bodySize,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const void* body,
-                    size_t bodySize,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const Json::Value& body,
-                     bool applyPlugins);
-
-    bool RestApiPut(const std::string& uri,
-                    const Json::Value& body,
-                    bool applyPlugins);
-
-    bool RestApiPost(const std::string& uri,
-                     const std::string& body,
-                     bool applyPlugins)
-    {
-      return RestApiPost(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    bool RestApiPut(const std::string& uri,
-                    const std::string& body,
-                    bool applyPlugins)
-    {
-      return RestApiPut(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins);
-    }
-
-    void CreateDicom(const Json::Value& tags,
-                     OrthancPluginCreateDicomFlags flags);
-
-    void CreateDicom(const Json::Value& tags,
-                     const OrthancImage& pixelData,
-                     OrthancPluginCreateDicomFlags flags);
-
-    void ReadFile(const std::string& path);
-
-    void GetDicomQuery(const OrthancPluginWorklistQuery* query);
-
-    void DicomToJson(Json::Value& target,
-                     OrthancPluginDicomToJsonFormat format,
-                     OrthancPluginDicomToJsonFlags flags,
-                     uint32_t maxStringLength);
-
-    bool HttpGet(const std::string& url,
-                 const std::string& username,
-                 const std::string& password);
-
-    bool HttpPost(const std::string& url,
-                  const std::string& body,
-                  const std::string& username,
-                  const std::string& password);
-
-    bool HttpPut(const std::string& url,
-                 const std::string& body,
-                 const std::string& username,
-                 const std::string& password);
-
-    void GetDicomInstance(const std::string& instanceId);
-  };
-
-
-  class OrthancString : public boost::noncopyable
-  {
-  private:
-    char*   str_;
-
-    void Clear();
-
-  public:
-    OrthancString() :
-      str_(NULL)
-    {
-    }
-
-    ~OrthancString()
-    {
-      Clear();
-    }
-
-    // This transfers ownership, warning: The string must have been
-    // allocated by the Orthanc core
-    void Assign(char* str);
-
-    const char* GetContent() const
-    {
-      return str_;
-    }
-
-    void ToString(std::string& target) const;
-
-    void ToJson(Json::Value& target) const;
-  };
-
-
-  class OrthancConfiguration : public boost::noncopyable
-  {
-  private:
-    Json::Value  configuration_;  // Necessarily a Json::objectValue
-    std::string  path_;
-
-    std::string GetPath(const std::string& key) const;
-
-    void LoadConfiguration();
-    
-  public:
-    OrthancConfiguration();
-
-    explicit OrthancConfiguration(bool load);
-
-    const Json::Value& GetJson() const
-    {
-      return configuration_;
-    }
-
-    bool IsSection(const std::string& key) const;
-
-    void GetSection(OrthancConfiguration& target,
-                    const std::string& key) const;
-
-    bool LookupStringValue(std::string& target,
-                           const std::string& key) const;
-    
-    bool LookupIntegerValue(int& target,
-                            const std::string& key) const;
-
-    bool LookupUnsignedIntegerValue(unsigned int& target,
-                                    const std::string& key) const;
-
-    bool LookupBooleanValue(bool& target,
-                            const std::string& key) const;
-
-    bool LookupFloatValue(float& target,
-                          const std::string& key) const;
-
-    bool LookupListOfStrings(std::list<std::string>& target,
-                             const std::string& key,
-                             bool allowSingleString) const;
-
-    bool LookupSetOfStrings(std::set<std::string>& target,
-                            const std::string& key,
-                            bool allowSingleString) const;
-
-    std::string GetStringValue(const std::string& key,
-                               const std::string& defaultValue) const;
-
-    int GetIntegerValue(const std::string& key,
-                        int defaultValue) const;
-
-    unsigned int GetUnsignedIntegerValue(const std::string& key,
-                                         unsigned int defaultValue) const;
-
-    bool GetBooleanValue(const std::string& key,
-                         bool defaultValue) const;
-
-    float GetFloatValue(const std::string& key,
-                        float defaultValue) const;
-
-    void GetDictionary(std::map<std::string, std::string>& target,
-                       const std::string& key) const;
-  };
-
-  class OrthancImage : public boost::noncopyable
-  {
-  private:
-    OrthancPluginImage*    image_;
-
-    void Clear();
-
-    void CheckImageAvailable() const;
-
-  public:
-    OrthancImage();
-
-    explicit OrthancImage(OrthancPluginImage* image);
-
-    OrthancImage(OrthancPluginPixelFormat  format,
-                 uint32_t                  width,
-                 uint32_t                  height);
-
-    OrthancImage(OrthancPluginPixelFormat  format,
-                 uint32_t                  width,
-                 uint32_t                  height,
-                 uint32_t                  pitch,
-                 void*                     buffer);
-
-    ~OrthancImage()
-    {
-      Clear();
-    }
-
-    void UncompressPngImage(const void* data,
-                            size_t size);
-
-    void UncompressJpegImage(const void* data,
-                             size_t size);
-
-    void DecodeDicomImage(const void* data,
-                          size_t size,
-                          unsigned int frame);
-
-    OrthancPluginPixelFormat GetPixelFormat() const;
-
-    unsigned int GetWidth() const;
-
-    unsigned int GetHeight() const;
-
-    unsigned int GetPitch() const;
-    
-    void* GetBuffer() const;
-
-    const OrthancPluginImage* GetObject() const
-    {
-      return image_;
-    }
-
-    void CompressPngImage(MemoryBuffer& target) const;
-
-    void CompressJpegImage(MemoryBuffer& target,
-                           uint8_t quality) const;
-
-    void AnswerPngImage(OrthancPluginRestOutput* output) const;
-
-    void AnswerJpegImage(OrthancPluginRestOutput* output,
-                         uint8_t quality) const;
-    
-    void* GetWriteableBuffer();
-
-    OrthancPluginImage* Release();
-  };
-
-
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  class FindMatcher : public boost::noncopyable
-  {
-  private:
-    OrthancPluginFindMatcher*          matcher_;
-    const OrthancPluginWorklistQuery*  worklist_;
-
-    void SetupDicom(const void*            query,
-                    uint32_t               size);
-
-  public:
-    explicit FindMatcher(const OrthancPluginWorklistQuery*  worklist);
-
-    FindMatcher(const void*  query,
-                uint32_t     size)
-    {
-      SetupDicom(query, size);
-    }
-
-    explicit FindMatcher(const MemoryBuffer&  dicom)
-    {
-      SetupDicom(dicom.GetData(), dicom.GetSize());
-    }
-
-    ~FindMatcher();
-
-    bool IsMatch(const void*  dicom,
-                 uint32_t     size) const;
-
-    bool IsMatch(const MemoryBuffer& dicom) const
-    {
-      return IsMatch(dicom.GetData(), dicom.GetSize());
-    }
-  };
-#endif
-
-
-  bool RestApiGet(Json::Value& result,
-                  const std::string& uri,
-                  bool applyPlugins);
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        bool applyPlugins);
-
-  bool RestApiGetString(std::string& result,
-                        const std::string& uri,
-                        const std::map<std::string, std::string>& httpHeaders,
-                        bool applyPlugins);
-
-  bool RestApiPost(std::string& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const void* body,
-                   size_t bodySize,
-                   bool applyPlugins);
-
-  bool RestApiPost(Json::Value& result,
-                   const std::string& uri,
-                   const Json::Value& body,
-                   bool applyPlugins);
-
-  inline bool RestApiPost(Json::Value& result,
-                          const std::string& uri,
-                          const std::string& body,
-                          bool applyPlugins)
-  {
-    return RestApiPost(result, uri, body.empty() ? NULL : body.c_str(),
-                       body.size(), applyPlugins);
-  }
-
-  inline bool RestApiPost(Json::Value& result,
-                          const std::string& uri,
-                          const MemoryBuffer& body,
-                          bool applyPlugins)
-  {
-    return RestApiPost(result, uri, body.GetData(),
-                       body.GetSize(), applyPlugins);
-  }
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const void* body,
-                  size_t bodySize,
-                  bool applyPlugins);
-
-  bool RestApiPut(Json::Value& result,
-                  const std::string& uri,
-                  const Json::Value& body,
-                  bool applyPlugins);
-
-  inline bool RestApiPut(Json::Value& result,
-                         const std::string& uri,
-                         const std::string& body,
-                         bool applyPlugins)
-  {
-    return RestApiPut(result, uri, body.empty() ? NULL : body.c_str(),
-                      body.size(), applyPlugins);
-  }
-
-  bool RestApiDelete(const std::string& uri,
-                     bool applyPlugins);
-
-  bool HttpDelete(const std::string& url,
-                  const std::string& username,
-                  const std::string& password);
-
-  void AnswerJson(const Json::Value& value,
-                  OrthancPluginRestOutput* output);
-
-  void AnswerString(const std::string& answer,
-                    const char* mimeType,
-                    OrthancPluginRestOutput* output);
-
-  void AnswerHttpError(uint16_t httpError,
-                       OrthancPluginRestOutput* output);
-
-  void AnswerMethodNotAllowed(OrthancPluginRestOutput* output, const char* allowedMethods);
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-  const char* AutodetectMimeType(const std::string& path);
-#endif
-
-  void LogError(const std::string& message);
-
-  void LogWarning(const std::string& message);
-
-  void LogInfo(const std::string& message);
-
-  void ReportMinimalOrthancVersion(unsigned int major,
-                                   unsigned int minor,
-                                   unsigned int revision);
-  
-  bool CheckMinimalOrthancVersion(unsigned int major,
-                                  unsigned int minor,
-                                  unsigned int revision);
-
-
-  namespace Internals
-  {
-    template <RestCallback Callback>
-    static OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output,
-                                          const char* url,
-                                          const OrthancPluginHttpRequest* request)
-    {
-      try
-      {
-        Callback(output, url, request);
-        return OrthancPluginErrorCode_Success;
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
-        if (HasGlobalContext() &&
-            e.HasDetails())
-        {
-          // The "false" instructs Orthanc not to log the detailed
-          // error message. This is to avoid duplicating the details,
-          // because "OrthancException" already does it on construction.
-          OrthancPluginSetHttpErrorDetails
-            (GetGlobalContext(), output, e.GetDetails(), false);
-        }
-#endif
-
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-  }
-
-  
-  template <RestCallback Callback>
-  void RegisterRestCallback(const std::string& uri,
-                            bool isThreadSafe)
-  {
-    if (isThreadSafe)
-    {
-      OrthancPluginRegisterRestCallbackNoLock
-        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
-    }
-    else
-    {
-      OrthancPluginRegisterRestCallback
-        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
-    }
-  }
-
-
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
-  class OrthancPeers : public boost::noncopyable
-  {
-  private:
-    typedef std::map<std::string, uint32_t>   Index;
-
-    OrthancPluginPeers   *peers_;
-    Index                 index_;
-    uint32_t              timeout_;
-
-    size_t GetPeerIndex(const std::string& name) const;
-
-  public:
-    OrthancPeers();
-
-    ~OrthancPeers();
-
-    uint32_t GetTimeout() const
-    {
-      return timeout_;
-    }
-
-    void SetTimeout(uint32_t timeout)
-    {
-      timeout_ = timeout;
-    }
-
-    bool LookupName(size_t& target,
-                    const std::string& name) const;
-
-    std::string GetPeerName(size_t index) const;
-
-    std::string GetPeerUrl(size_t index) const;
-
-    std::string GetPeerUrl(const std::string& name) const;
-
-    size_t GetPeersCount() const
-    {
-      return index_.size();
-    }
-
-    bool LookupUserProperty(std::string& value,
-                            size_t index,
-                            const std::string& key) const;
-
-    bool LookupUserProperty(std::string& value,
-                            const std::string& peer,
-                            const std::string& key) const;
-
-    bool DoGet(MemoryBuffer& target,
-               size_t index,
-               const std::string& uri) const;
-
-    bool DoGet(MemoryBuffer& target,
-               const std::string& name,
-               const std::string& uri) const;
-
-    bool DoGet(Json::Value& target,
-               size_t index,
-               const std::string& uri) const;
-
-    bool DoGet(Json::Value& target,
-               const std::string& name,
-               const std::string& uri) const;
-
-    bool DoPost(MemoryBuffer& target,
-                size_t index,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(MemoryBuffer& target,
-                const std::string& name,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(Json::Value& target,
-                size_t index,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPost(Json::Value& target,
-                const std::string& name,
-                const std::string& uri,
-                const std::string& body) const;
-
-    bool DoPut(size_t index,
-               const std::string& uri,
-               const std::string& body) const;
-
-    bool DoPut(const std::string& name,
-               const std::string& uri,
-               const std::string& body) const;
-
-    bool DoDelete(size_t index,
-                  const std::string& uri) const;
-
-    bool DoDelete(const std::string& name,
-                  const std::string& uri) const;
-  };
-#endif
-
-
-
-#if HAS_ORTHANC_PLUGIN_JOB == 1
-  class OrthancJob : public boost::noncopyable
-  {
-  private:
-    std::string   jobType_;
-    std::string   content_;
-    bool          hasSerialized_;
-    std::string   serialized_;
-    float         progress_;
-
-    static void CallbackFinalize(void* job);
-
-    static float CallbackGetProgress(void* job);
-
-    static const char* CallbackGetContent(void* job);
-
-    static const char* CallbackGetSerialized(void* job);
-
-    static OrthancPluginJobStepStatus CallbackStep(void* job);
-
-    static OrthancPluginErrorCode CallbackStop(void* job,
-                                               OrthancPluginJobStopReason reason);
-
-    static OrthancPluginErrorCode CallbackReset(void* job);
-
-  protected:
-    void ClearContent();
-
-    void UpdateContent(const Json::Value& content);
-
-    void ClearSerialized();
-
-    void UpdateSerialized(const Json::Value& serialized);
-
-    void UpdateProgress(float progress);
-    
-  public:
-    OrthancJob(const std::string& jobType);
-    
-    virtual ~OrthancJob()
-    {
-    }
-
-    virtual OrthancPluginJobStepStatus Step() = 0;
-
-    virtual void Stop(OrthancPluginJobStopReason reason) = 0;
-    
-    virtual void Reset() = 0;
-
-    static OrthancPluginJob* Create(OrthancJob* job /* takes ownership */);
-
-    static std::string Submit(OrthancJob* job /* takes ownership */,
-                              int priority);
-
-    static void SubmitAndWait(Json::Value& result,
-                              OrthancJob* job /* takes ownership */,
-                              int priority);
-
-    // Submit a job from a POST on the REST API with the same
-    // conventions as in the Orthanc core (according to the
-    // "Synchronous" and "Priority" options)
-    static void SubmitFromRestApiPost(OrthancPluginRestOutput* output,
-                                      const Json::Value& body,
-                                      OrthancJob* job);
-  };
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
-  inline void SetMetricsValue(char* name,
-                              float value)
-  {
-    OrthancPluginSetMetricsValue(GetGlobalContext(), name,
-                                 value, OrthancPluginMetricsType_Default);
-  }
-
-  class MetricsTimer : public boost::noncopyable
-  {
-  private:
-    std::string               name_;
-    boost::posix_time::ptime  start_;
-
-  public:
-    explicit MetricsTimer(const char* name);
-
-    ~MetricsTimer();
-  };
-#endif
-
-
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
-  class HttpClient : public boost::noncopyable
-  {
-  public:
-    typedef std::map<std::string, std::string>  HttpHeaders;
-
-    class IRequestBody : public boost::noncopyable
-    {
-    public:
-      virtual ~IRequestBody()
-      {
-      }
-
-      virtual bool ReadNextChunk(std::string& chunk) = 0;
-    };
-
-
-    class IAnswer : public boost::noncopyable
-    {
-    public:
-      virtual ~IAnswer()
-      {
-      }
-
-      virtual void AddHeader(const std::string& key,
-                             const std::string& value) = 0;
-
-      virtual void AddChunk(const void* data,
-                            size_t size) = 0;
-    };
-
-
-  private:
-    class RequestBodyWrapper;
-
-    uint16_t                 httpStatus_;
-    OrthancPluginHttpMethod  method_;
-    std::string              url_;
-    HttpHeaders              headers_;
-    std::string              username_;
-    std::string              password_;
-    uint32_t                 timeout_;
-    std::string              certificateFile_;
-    std::string              certificateKeyFile_;
-    std::string              certificateKeyPassword_;
-    bool                     pkcs11_;
-    std::string              fullBody_;
-    IRequestBody*            chunkedBody_;
-    bool                     allowChunkedTransfers_;
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
-    void ExecuteWithStream(uint16_t& httpStatus,  // out
-                           IAnswer& answer,       // out
-                           IRequestBody& body) const;
-#endif
-
-    void ExecuteWithoutStream(uint16_t& httpStatus,        // out
-                              HttpHeaders& answerHeaders,  // out
-                              std::string& answerBody,     // out
-                              const std::string& body) const;
-    
-  public:
-    HttpClient();
-
-    uint16_t GetHttpStatus() const
-    {
-      return httpStatus_;
-    }
-
-    void SetMethod(OrthancPluginHttpMethod method)
-    {
-      method_ = method;
-    }
-
-    const std::string& GetUrl() const
-    {
-      return url_;
-    }
-
-    void SetUrl(const std::string& url)
-    {
-      url_ = url;
-    }
-
-    void SetHeaders(const HttpHeaders& headers)
-    {
-      headers_ = headers;
-    }
-
-    void AddHeader(const std::string& key,
-                   const std::string& value)
-    {
-      headers_[key] = value;
-    }
-
-    void AddHeaders(const HttpHeaders& headers);
-
-    void SetCredentials(const std::string& username,
-                        const std::string& password);
-
-    void ClearCredentials();
-
-    void SetTimeout(unsigned int timeout)  // 0 for default timeout
-    {
-      timeout_ = timeout;
-    }
-
-    void SetCertificate(const std::string& certificateFile,
-                        const std::string& keyFile,
-                        const std::string& keyPassword);
-
-    void ClearCertificate();
-
-    void SetPkcs11(bool pkcs11)
-    {
-      pkcs11_ = pkcs11;
-    }
-
-    void ClearBody();
-
-    void SwapBody(std::string& body);
-
-    void SetBody(const std::string& body);
-
-    void SetBody(IRequestBody& body);
-
-    // This function can be used to disable chunked transfers if the
-    // remote server is Orthanc with a version <= 1.5.6.
-    void SetChunkedTransfersAllowed(bool allow)
-    {
-      allowChunkedTransfers_ = allow;
-    }
-
-    bool IsChunkedTransfersAllowed() const
-    {
-      return allowChunkedTransfers_;
-    }
-
-    void Execute(IAnswer& answer);
-
-    void Execute(HttpHeaders& answerHeaders /* out */,
-                 std::string& answerBody /* out */);
-
-    void Execute(HttpHeaders& answerHeaders /* out */,
-                 Json::Value& answerBody /* out */);
-
-    void Execute();
-  };
-#endif
-
-
-
-  class IChunkedRequestReader : public boost::noncopyable
-  {
-  public:
-    virtual ~IChunkedRequestReader()
-    {
-    }
-
-    virtual void AddChunk(const void* data,
-                          size_t size) = 0;
-
-    virtual void Execute(OrthancPluginRestOutput* output) = 0;
-  };
-
-
-  typedef IChunkedRequestReader* (*ChunkedRestCallback) (const char* url,
-                                                         const OrthancPluginHttpRequest* request);
-
-
-  namespace Internals
-  {
-    void NullRestCallback(OrthancPluginRestOutput* output,
-                          const char* url,
-                          const OrthancPluginHttpRequest* request);
-  
-    IChunkedRequestReader *NullChunkedRestCallback(const char* url,
-                                                   const OrthancPluginHttpRequest* request);
-
-
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-    template <ChunkedRestCallback Callback>
-    static OrthancPluginErrorCode ChunkedProtect(OrthancPluginServerChunkedRequestReader** reader,
-                                                const char* url,
-                                                const OrthancPluginHttpRequest* request)
-    {
-      try
-      {
-        if (reader == NULL)
-        {
-          return OrthancPluginErrorCode_InternalError;
-        }
-        else
-        {
-          *reader = reinterpret_cast<OrthancPluginServerChunkedRequestReader*>(Callback(url, request));
-          if (*reader == NULL)
-          {
-            return OrthancPluginErrorCode_Plugin;
-          }
-          else
-          {
-            return OrthancPluginErrorCode_Success;
-          }
-        }
-      }
-      catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
-      {
-        return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        return OrthancPluginErrorCode_BadFileFormat;
-      }
-      catch (...)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
-    OrthancPluginErrorCode ChunkedRequestReaderAddChunk(
-      OrthancPluginServerChunkedRequestReader* reader,
-      const void*                              data,
-      uint32_t                                 size);
-
-    OrthancPluginErrorCode ChunkedRequestReaderExecute(
-      OrthancPluginServerChunkedRequestReader* reader,
-      OrthancPluginRestOutput*                 output);
-
-    void ChunkedRequestReaderFinalize(
-      OrthancPluginServerChunkedRequestReader* reader);
-
-#else  
-
-    OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                    const char* url,
-                                                    const OrthancPluginHttpRequest* request,
-                                                    RestCallback GetHandler,
-                                                    ChunkedRestCallback PostHandler,
-                                                    RestCallback DeleteHandler,
-                                                    ChunkedRestCallback PutHandler);
-
-    template<
-      RestCallback         GetHandler,
-      ChunkedRestCallback  PostHandler,
-      RestCallback         DeleteHandler,
-      ChunkedRestCallback  PutHandler
-      >
-    inline OrthancPluginErrorCode ChunkedRestCompatibility(OrthancPluginRestOutput* output,
-                                                           const char* url,
-                                                           const OrthancPluginHttpRequest* request)
-    {
-      return ChunkedRestCompatibility(output, url, request, GetHandler,
-                                      PostHandler, DeleteHandler, PutHandler);
-    }
-#endif
-  }
-
-
-
-  // NB: We use a templated class instead of a templated function, because
-  // default values are only available in functions since C++11
-  template<
-    RestCallback         GetHandler    = Internals::NullRestCallback,
-    ChunkedRestCallback  PostHandler   = Internals::NullChunkedRestCallback,
-    RestCallback         DeleteHandler = Internals::NullRestCallback,
-    ChunkedRestCallback  PutHandler    = Internals::NullChunkedRestCallback
-    >
-  class ChunkedRestRegistration : public boost::noncopyable
-  {
-  public:
-    static void Apply(const std::string& uri)
-    {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
-      OrthancPluginRegisterChunkedRestCallback(
-        GetGlobalContext(), uri.c_str(),
-        GetHandler == Internals::NullRestCallback         ? NULL : Internals::Protect<GetHandler>,
-        PostHandler == Internals::NullChunkedRestCallback ? NULL : Internals::ChunkedProtect<PostHandler>,
-        DeleteHandler == Internals::NullRestCallback      ? NULL : Internals::Protect<DeleteHandler>,
-        PutHandler == Internals::NullChunkedRestCallback  ? NULL : Internals::ChunkedProtect<PutHandler>,
-        Internals::ChunkedRequestReaderAddChunk,
-        Internals::ChunkedRequestReaderExecute,
-        Internals::ChunkedRequestReaderFinalize);
-#else
-      OrthancPluginRegisterRestCallbackNoLock(
-        GetGlobalContext(), uri.c_str(), 
-        Internals::ChunkedRestCompatibility<GetHandler, PostHandler, DeleteHandler, PutHandler>);
-#endif
-    }
-  };
-
-  
-
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
-  class IStorageCommitmentScpHandler : public boost::noncopyable
-  {
-  public:
-    virtual ~IStorageCommitmentScpHandler()
-    {
-    }
-    
-    virtual OrthancPluginStorageCommitmentFailureReason Lookup(const std::string& sopClassUid,
-                                                               const std::string& sopInstanceUid) = 0;
-    
-    static OrthancPluginErrorCode Lookup(OrthancPluginStorageCommitmentFailureReason* target,
-                                         void* rawHandler,
-                                         const char* sopClassUid,
-                                         const char* sopInstanceUid);
-
-    static void Destructor(void* rawHandler);
-  };
-#endif
-
-
-  class DicomInstance : public boost::noncopyable
-  {
-  private:
-    bool toFree_;
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-    const OrthancPluginDicomInstance*  instance_;
-#else
-    OrthancPluginDicomInstance*  instance_;
-#endif
-    
-  public:
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)    
-    explicit DicomInstance(const OrthancPluginDicomInstance* instance);
-#else
-    explicit DicomInstance(OrthancPluginDicomInstance* instance);
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    DicomInstance(const void* buffer,
-                  size_t size);
-#endif
-
-    ~DicomInstance();
-
-    std::string GetRemoteAet() const;
-
-    const void* GetBuffer() const
-    {
-      return OrthancPluginGetInstanceData(GetGlobalContext(), instance_);
-    }
-
-    size_t GetSize() const
-    {
-      return static_cast<size_t>(OrthancPluginGetInstanceSize(GetGlobalContext(), instance_));
-    }
-
-    void GetJson(Json::Value& target) const;
-
-    void GetSimplifiedJson(Json::Value& target) const;
-
-    OrthancPluginInstanceOrigin GetOrigin() const
-    {
-      return OrthancPluginGetInstanceOrigin(GetGlobalContext(), instance_);
-    }
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-    std::string GetTransferSyntaxUid() const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 1)
-    bool HasPixelData() const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    unsigned int GetFramesCount() const
-    {
-      return OrthancPluginGetInstanceFramesCount(GetGlobalContext(), instance_);
-    }
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    void GetRawFrame(std::string& target,
-                     unsigned int frameIndex) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    OrthancImage* GetDecodedFrame(unsigned int frameIndex) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    void Serialize(std::string& target) const;
-#endif
-
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    static DicomInstance* Transcode(const void* buffer,
-                                    size_t size,
-                                    const std::string& transferSyntax);
-#endif
-  };
-}
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginException.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2020 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#if !defined(HAS_ORTHANC_EXCEPTION)
-#  error The macro HAS_ORTHANC_EXCEPTION must be defined
-#endif
-
-
-#if HAS_ORTHANC_EXCEPTION == 1
-#  include <OrthancException.h>
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::Orthanc::ErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::Orthanc::OrthancException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::Orthanc::ErrorCode_ ## code
-#else
-#  include <orthanc/OrthancCPlugin.h>
-#  define ORTHANC_PLUGINS_ERROR_ENUMERATION     ::OrthancPluginErrorCode
-#  define ORTHANC_PLUGINS_EXCEPTION_CLASS       ::OrthancPlugins::PluginException
-#  define ORTHANC_PLUGINS_GET_ERROR_CODE(code)  ::OrthancPluginErrorCode_ ## code
-#endif
-
-
-#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
-
-
-#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
-  throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
-                                                  
-
-#define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
-  if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \
-  {                                                                 \
-    ORTHANC_PLUGINS_THROW_EXCEPTION(code);                          \
-  }
-
-
-namespace OrthancPlugins
-{
-#if HAS_ORTHANC_EXCEPTION == 0
-  class PluginException
-  {
-  private:
-    OrthancPluginErrorCode  code_;
-
-  public:
-    explicit PluginException(OrthancPluginErrorCode code) : code_(code)
-    {
-    }
-
-    OrthancPluginErrorCode GetErrorCode() const
-    {
-      return code_;
-    }
-
-    const char* What(OrthancPluginContext* context) const
-    {
-      const char* description = OrthancPluginGetErrorDescription(context, code_);
-      if (description)
-      {
-        return description;
-      }
-      else
-      {
-        return "No description available";
-      }
-    }
-  };
-#endif
-}
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, Belgium
-# Copyright (C) 2017-2020 Osimis S.A., Belgium
-#
-# This program is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-# In Orthanc <= 1.7.1, the instructions below were part of
-# "Compiler.cmake", and were protected by the (now unused) option
-# "ENABLE_PLUGINS_VERSION_SCRIPT" in CMake
-
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
-    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/VersionScriptPlugins.map")
-elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${CMAKE_CURRENT_LIST_DIR}/ExportedSymbolsPlugins.list")
-endif()
--- a/Applications/StoneWebViewer/Resources/Orthanc/Plugins/VersionScriptPlugins.map	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-# This is a version-script for Orthanc plugins
-
-{
-global:
-  OrthancPluginInitialize;
-  OrthancPluginFinalize;
-  OrthancPluginGetName;
-  OrthancPluginGetVersion;
-
-local:
-  *;
-};
--- a/Applications/StoneWebViewer/Resources/OrthancSdk-1.0.0/orthanc/OrthancCPlugin.h	Tue Aug 11 13:24:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4740 +0,0 @@
-/**
- * \mainpage
- *
- * This C/C++ SDK allows external developers to create plugins that
- * can be loaded into Orthanc to extend its functionality. Each
- * Orthanc plugin must expose 4 public functions with the following
- * signatures:
- * 
- * -# <tt>int32_t OrthancPluginInitialize(const OrthancPluginContext* context)</tt>:
- *    This function is invoked by Orthanc when it loads the plugin on startup.
- *    The plugin must:
- *    - Check its compatibility with the Orthanc version using
- *      ::OrthancPluginCheckVersion().
- *    - Store the context pointer so that it can use the plugin 
- *      services of Orthanc.
- *    - Register all its REST callbacks using ::OrthancPluginRegisterRestCallback().
- *    - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback().
- *    - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback().
- *    - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea().
- *    - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2().
- *    - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback().
- *    - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback().
- * -# <tt>void OrthancPluginFinalize()</tt>:
- *    This function is invoked by Orthanc during its shutdown. The plugin
- *    must free all its memory.
- * -# <tt>const char* OrthancPluginGetName()</tt>:
- *    The plugin must return a short string to identify itself.
- * -# <tt>const char* OrthancPluginGetVersion()</tt>:
- *    The plugin must return a string containing its version number.
- *
- * The name and the version of a plugin is only used to prevent it
- * from being loaded twice. Note that, in C++, it is mandatory to
- * declare these functions within an <tt>extern "C"</tt> section.
- * 
- * To ensure multi-threading safety, the various REST callbacks are
- * guaranteed to be executed in mutual exclusion since Orthanc
- * 0.8.5. If this feature is undesired (notably when developing
- * high-performance plugins handling simultaneous requests), use
- * ::OrthancPluginRegisterRestCallbackNoLock().
- **/
-
-
-
-/**
- * @defgroup Images Images and compression
- * @brief Functions to deal with images and compressed buffers.
- *
- * @defgroup REST REST
- * @brief Functions to answer REST requests in a callback.
- *
- * @defgroup Callbacks Callbacks
- * @brief Functions to register and manage callbacks by the plugins.
- *
- * @defgroup Worklists Worklists
- * @brief Functions to register and manage worklists.
- *
- * @defgroup Orthanc Orthanc
- * @brief Functions to access the content of the Orthanc server.
- **/
-
-
-
-/**
- * @defgroup Toolbox Toolbox
- * @brief Generic functions to help with the creation of plugins.
- **/
-
-
-
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * In addition, as a special exception, the copyright holders of this
- * program give permission to link the code of its release with the
- * OpenSSL project's "OpenSSL" library (or with modified versions of it
- * that use the same license as the "OpenSSL" library), and distribute
- * the linked executables. You must obey the GNU General Public License
- * in all respects for all of the code used other than "OpenSSL". If you
- * modify file(s) with this exception, you may extend this exception to
- * your version of the file(s), but you are not obligated to do so. If
- * you do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source files
- * in the program, then also delete it here.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-
-#pragma once
-
-
-#include <stdio.h>
-#include <string.h>
-
-#ifdef WIN32
-#define ORTHANC_PLUGINS_API __declspec(dllexport)
-#else
-#define ORTHANC_PLUGINS_API
-#endif
-
-#define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER     1
-#define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER     0
-#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER  0
-
-
-
-/********************************************************************
- ** Check that function inlining is properly supported. The use of
- ** inlining is required, to avoid the duplication of object code
- ** between two compilation modules that would use the Orthanc Plugin
- ** API.
- ********************************************************************/
-
-/* If the auto-detection of the "inline" keyword below does not work
-   automatically and that your compiler is known to properly support
-   inlining, uncomment the following #define and adapt the definition
-   of "static inline". */
-
-/* #define ORTHANC_PLUGIN_INLINE static inline */
-
-#ifndef ORTHANC_PLUGIN_INLINE
-#  if __STDC_VERSION__ >= 199901L
-/*   This is C99 or above: http://predef.sourceforge.net/prestd.html */
-#    define ORTHANC_PLUGIN_INLINE static inline
-#  elif defined(__cplusplus)
-/*   This is C++ */
-#    define ORTHANC_PLUGIN_INLINE static inline
-#  elif defined(__GNUC__)
-/*   This is GCC running in C89 mode */
-#    define ORTHANC_PLUGIN_INLINE static __inline
-#  elif defined(_MSC_VER)
-/*   This is Visual Studio running in C89 mode */
-#    define ORTHANC_PLUGIN_INLINE static __inline
-#  else
-#    error Your compiler is not known to support the "inline" keyword
-#  endif
-#endif
-
-
-
-/********************************************************************
- ** Inclusion of standard libraries.
- ********************************************************************/
-
-/**
- * For Microsoft Visual Studio, a compatibility "stdint.h" can be
- * downloaded at the following URL:
- * https://orthanc.googlecode.com/hg/Resources/ThirdParty/VisualStudio/stdint.h
- **/
-#include <stdint.h>
-
-#include <stdlib.h>
-
-
-
-/********************************************************************
- ** Definition of the Orthanc Plugin API.
- ********************************************************************/
-
-/** @{ */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-  /**
-   * The various error codes that can be returned by the Orthanc core.
-   **/
-  typedef enum
-  {
-    OrthancPluginErrorCode_InternalError = -1    /*!< Internal error */,
-    OrthancPluginErrorCode_Success = 0    /*!< Success */,
-    OrthancPluginErrorCode_Plugin = 1    /*!< Error encountered within the plugin engine */,
-    OrthancPluginErrorCode_NotImplemented = 2    /*!< Not implemented yet */,
-    OrthancPluginErrorCode_ParameterOutOfRange = 3    /*!< Parameter out of range */,
-    OrthancPluginErrorCode_NotEnoughMemory = 4    /*!< Not enough memory */,
-    OrthancPluginErrorCode_BadParameterType = 5    /*!< Bad type for a parameter */,
-    OrthancPluginErrorCode_BadSequenceOfCalls = 6    /*!< Bad sequence of calls */,
-    OrthancPluginErrorCode_InexistentItem = 7    /*!< Accessing an inexistent item */,
-    OrthancPluginErrorCode_BadRequest = 8    /*!< Bad request */,
-    OrthancPluginErrorCode_NetworkProtocol = 9    /*!< Error in the network protocol */,
-    OrthancPluginErrorCode_SystemCommand = 10    /*!< Error while calling a system command */,
-    OrthancPluginErrorCode_Database = 11    /*!< Error with the database engine */,
-    OrthancPluginErrorCode_UriSyntax = 12    /*!< Badly formatted URI */,
-    OrthancPluginErrorCode_InexistentFile = 13    /*!< Inexistent file */,
-    OrthancPluginErrorCode_CannotWriteFile = 14    /*!< Cannot write to file */,
-    OrthancPluginErrorCode_BadFileFormat = 15    /*!< Bad file format */,
-    OrthancPluginErrorCode_Timeout = 16    /*!< Timeout */,
-    OrthancPluginErrorCode_UnknownResource = 17    /*!< Unknown resource */,
-    OrthancPluginErrorCode_IncompatibleDatabaseVersion = 18    /*!< Incompatible version of the database */,
-    OrthancPluginErrorCode_FullStorage = 19    /*!< The file storage is full */,
-    OrthancPluginErrorCode_CorruptedFile = 20    /*!< Corrupted file (e.g. inconsistent MD5 hash) */,
-    OrthancPluginErrorCode_InexistentTag = 21    /*!< Inexistent tag */,
-    OrthancPluginErrorCode_ReadOnly = 22    /*!< Cannot modify a read-only data structure */,
-    OrthancPluginErrorCode_IncompatibleImageFormat = 23    /*!< Incompatible format of the images */,
-    OrthancPluginErrorCode_IncompatibleImageSize = 24    /*!< Incompatible size of the images */,
-    OrthancPluginErrorCode_SharedLibrary = 25    /*!< Error while using a shared library (plugin) */,
-    OrthancPluginErrorCode_UnknownPluginService = 26    /*!< Plugin invoking an unknown service */,
-    OrthancPluginErrorCode_UnknownDicomTag = 27    /*!< Unknown DICOM tag */,
-    OrthancPluginErrorCode_BadJson = 28    /*!< Cannot parse a JSON document */,
-    OrthancPluginErrorCode_Unauthorized = 29    /*!< Bad credentials were provided to an HTTP request */,
-    OrthancPluginErrorCode_BadFont = 30    /*!< Badly formatted font file */,
-    OrthancPluginErrorCode_DatabasePlugin = 31    /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */,
-    OrthancPluginErrorCode_StorageAreaPlugin = 32    /*!< Error in the plugin implementing a custom storage area */,
-    OrthancPluginErrorCode_EmptyRequest = 33    /*!< The request is empty */,
-    OrthancPluginErrorCode_NotAcceptable = 34    /*!< Cannot send a response which is acceptable according to the Accept HTTP header */,
-    OrthancPluginErrorCode_SQLiteNotOpened = 1000    /*!< SQLite: The database is not opened */,
-    OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001    /*!< SQLite: Connection is already open */,
-    OrthancPluginErrorCode_SQLiteCannotOpen = 1002    /*!< SQLite: Unable to open the database */,
-    OrthancPluginErrorCode_SQLiteStatementAlreadyUsed = 1003    /*!< SQLite: This cached statement is already being referred to */,
-    OrthancPluginErrorCode_SQLiteExecute = 1004    /*!< SQLite: Cannot execute a command */,
-    OrthancPluginErrorCode_SQLiteRollbackWithoutTransaction = 1005    /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */,
-    OrthancPluginErrorCode_SQLiteCommitWithoutTransaction = 1006    /*!< SQLite: Committing a nonexistent transaction */,
-    OrthancPluginErrorCode_SQLiteRegisterFunction = 1007    /*!< SQLite: Unable to register a function */,
-    OrthancPluginErrorCode_SQLiteFlush = 1008    /*!< SQLite: Unable to flush the database */,
-    OrthancPluginErrorCode_SQLiteCannotRun = 1009    /*!< SQLite: Cannot run a cached statement */,
-    OrthancPluginErrorCode_SQLiteCannotStep = 1010    /*!< SQLite: Cannot step over a cached statement */,
-    OrthancPluginErrorCode_SQLiteBindOutOfRange = 1011    /*!< SQLite: Bing a value while out of range (serious error) */,
-    OrthancPluginErrorCode_SQLitePrepareStatement = 1012    /*!< SQLite: Cannot prepare a cached statement */,
-    OrthancPluginErrorCode_SQLiteTransactionAlreadyStarted = 1013    /*!< SQLite: Beginning the same transaction twice */,
-    OrthancPluginErrorCode_SQLiteTransactionCommit = 1014    /*!< SQLite: Failure when committing the transaction */,
-    OrthancPluginErrorCode_SQLiteTransactionBegin = 1015    /*!< SQLite: Cannot start a transaction */,
-    OrthancPluginErrorCode_DirectoryOverFile = 2000    /*!< The directory to be created is already occupied by a regular file */,
-    OrthancPluginErrorCode_FileStorageCannotWrite = 2001    /*!< Unable to create a subdirectory or a file in the file storage */,
-    OrthancPluginErrorCode_DirectoryExpected = 2002    /*!< The specified path does not point to a directory */,
-    OrthancPluginErrorCode_HttpPortInUse = 2003    /*!< The TCP port of the HTTP server is already in use */,
-    OrthancPluginErrorCode_DicomPortInUse = 2004    /*!< The TCP port of the DICOM server is already in use */,
-    OrthancPluginErrorCode_BadHttpStatusInRest = 2005    /*!< This HTTP status is not allowed in a REST API */,
-    OrthancPluginErrorCode_RegularFileExpected = 2006    /*!< The specified path does not point to a regular file */,
-    OrthancPluginErrorCode_PathToExecutable = 2007    /*!< Unable to get the path to the executable */,
-    OrthancPluginErrorCode_MakeDirectory = 2008    /*!< Cannot create a directory */,
-    OrthancPluginErrorCode_BadApplicationEntityTitle = 2009    /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */,
-    OrthancPluginErrorCode_NoCFindHandler = 2010    /*!< No request handler factory for DICOM C-FIND SCP */,
-    OrthancPluginErrorCode_NoCMoveHandler = 2011    /*!< No request handler factory for DICOM C-MOVE SCP */,
-    OrthancPluginErrorCode_NoCStoreHandler = 2012    /*!< No request handler factory for DICOM C-STORE SCP */,
-    OrthancPluginErrorCode_NoApplicationEntityFilter = 2013    /*!< No application entity filter */,
-    OrthancPluginErrorCode_NoSopClassOrInstance = 2014    /*!< DicomUserConnection: Unable to find the SOP class and instance */,
-    OrthancPluginErrorCode_NoPresentationContext = 2015    /*!< DicomUserConnection: No acceptable presentation context for modality */,
-    OrthancPluginErrorCode_DicomFindUnavailable = 2016    /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */,
-    OrthancPluginErrorCode_DicomMoveUnavailable = 2017    /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */,
-    OrthancPluginErrorCode_CannotStoreInstance = 2018    /*!< Cannot store an instance */,
-    OrthancPluginErrorCode_CreateDicomNotString = 2019    /*!< Only string values are supported when creating DICOM instances */,
-    OrthancPluginErrorCode_CreateDicomOverrideTag = 2020    /*!< Trying to override a value inherited from a parent module */,
-    OrthancPluginErrorCode_CreateDicomUseContent = 2021    /*!< Use \"Content\" to inject an image into a new DICOM instance */,
-    OrthancPluginErrorCode_CreateDicomNoPayload = 2022    /*!< No payload is present for one instance in the series */,
-    OrthancPluginErrorCode_CreateDicomUseDataUriScheme = 2023    /*!< The payload of the DICOM instance must be specified according to Data URI scheme */,
-    OrthancPluginErrorCode_CreateDicomBadParent = 2024    /*!< Trying to attach a new DICOM instance to an inexistent resource */,
-    OrthancPluginErrorCode_CreateDicomParentIsInstance = 2025    /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */,
-    OrthancPluginErrorCode_CreateDicomParentEncoding = 2026    /*!< Unable to get the encoding of the parent resource */,
-    OrthancPluginErrorCode_UnknownModality = 2027    /*!< Unknown modality */,
-    OrthancPluginErrorCode_BadJobOrdering = 2028    /*!< Bad ordering of filters in a job */,
-    OrthancPluginErrorCode_JsonToLuaTable = 2029    /*!< Cannot convert the given JSON object to a Lua table */,
-    OrthancPluginErrorCode_CannotCreateLua = 2030    /*!< Cannot create the Lua context */,
-    OrthancPluginErrorCode_CannotExecuteLua = 2031    /*!< Cannot execute a Lua command */,
-    OrthancPluginErrorCode_LuaAlreadyExecuted = 2032    /*!< Arguments cannot be pushed after the Lua function is executed */,
-    OrthancPluginErrorCode_LuaBadOutput = 2033    /*!< The Lua function does not give the expected number of outputs */,
-    OrthancPluginErrorCode_NotLuaPredicate = 2034    /*!< The Lua function is not a predicate (only true/false outputs allowed) */,
-    OrthancPluginErrorCode_LuaReturnsNoString = 2035    /*!< The Lua function does not return a string */,
-    OrthancPluginErrorCode_StorageAreaAlreadyRegistered = 2036    /*!< Another plugin has already registered a custom storage area */,
-    OrthancPluginErrorCode_DatabaseBackendAlreadyRegistered = 2037    /*!< Another plugin has already registered a custom database back-end */,
-    OrthancPluginErrorCode_DatabaseNotInitialized = 2038    /*!< Plugin trying to call the database during its initialization */,
-    OrthancPluginErrorCode_SslDisabled = 2039    /*!< Orthanc has been built without SSL support */,
-    OrthancPluginErrorCode_CannotOrderSlices = 2040    /*!< Unable to order the slices of the series */,
-    OrthancPluginErrorCode_NoWorklistHandler = 2041    /*!< No request handler factory for DICOM C-Find Modality SCP */,
-
-    _OrthancPluginErrorCode_INTERNAL = 0x7fffffff
-  } OrthancPluginErrorCode;
-
-
-  /**
-   * Forward declaration of one of the mandatory functions for Orthanc
-   * plugins.
-   **/
-  ORTHANC_PLUGINS_API const char* OrthancPluginGetName();
-
-
-  /**
-   * The various HTTP methods for a REST call.
-   **/
-  typedef enum
-  {
-    OrthancPluginHttpMethod_Get = 1,    /*!< GET request */
-    OrthancPluginHttpMethod_Post = 2,   /*!< POST request */
-    OrthancPluginHttpMethod_Put = 3,    /*!< PUT request */
-    OrthancPluginHttpMethod_Delete = 4, /*!< DELETE request */
-
-    _OrthancPluginHttpMethod_INTERNAL = 0x7fffffff
-  } OrthancPluginHttpMethod;
-
-
-  /**
-   * @brief The parameters of a REST request.
-   * @ingroup Callbacks
-   **/
-  typedef struct
-  {
-    /**
-     * @brief The HTTP method.
-     **/
-    OrthancPluginHttpMethod method;    
-
-    /**
-     * @brief The number of groups of the regular expression.
-     **/
-    uint32_t                groupsCount;
-
-    /**
-     * @brief The matched values for the groups of the regular expression.
-     **/
-    const char* const*      groups;
-
-    /**
-     * @brief For a GET request, the number of GET parameters.
-     **/
-    uint32_t                getCount;
-
-    /**
-     * @brief For a GET request, the keys of the GET parameters.
-     **/
-    const char* const*      getKeys;
-
-    /**
-     * @brief For a GET request, the values of the GET parameters.
-     **/
-    const char* const*      getValues;
-
-    /**
-     * @brief For a PUT or POST request, the content of the body.
-     **/
-    const char*             body;
-
-    /**
-     * @brief For a PUT or POST request, the number of bytes of the body.
-     **/
-    uint32_t                bodySize;
-
-
-    /* --------------------------------------------------
-       New in version 0.8.1
-       -------------------------------------------------- */
-
-    /**
-     * @brief The number of HTTP headers.
-     **/
-    uint32_t                headersCount;
-
-    /**
-     * @brief The keys of the HTTP headers (always converted to low-case).
-     **/
-    const char* const*      headersKeys;
-
-    /**
-     * @brief The values of the HTTP headers.
-     **/
-    const char* const*      headersValues;
-
-  } OrthancPluginHttpRequest;
-
-
-  typedef enum 
-  {
-    /* Generic services */
-    _OrthancPluginService_LogInfo = 1,
-    _OrthancPluginService_LogWarning = 2,
-    _OrthancPluginService_LogError = 3,
-    _OrthancPluginService_GetOrthancPath = 4,
-    _OrthancPluginService_GetOrthancDirectory = 5,
-    _OrthancPluginService_GetConfigurationPath = 6,
-    _OrthancPluginService_SetPluginProperty = 7,
-    _OrthancPluginService_GetGlobalProperty = 8,
-    _OrthancPluginService_SetGlobalProperty = 9,
-    _OrthancPluginService_GetCommandLineArgumentsCount = 10,
-    _OrthancPluginService_GetCommandLineArgument = 11,
-    _OrthancPluginService_GetExpectedDatabaseVersion = 12,
-    _OrthancPluginService_GetConfiguration = 13,
-    _OrthancPluginService_BufferCompression = 14,
-    _OrthancPluginService_ReadFile = 15,
-    _OrthancPluginService_WriteFile = 16,
-    _OrthancPluginService_GetErrorDescription = 17,
-    _OrthancPluginService_CallHttpClient = 18,
-    _OrthancPluginService_RegisterErrorCode = 19,
-    _OrthancPluginService_RegisterDictionaryTag = 20,
-    _OrthancPluginService_DicomBufferToJson = 21,
-    _OrthancPluginService_DicomInstanceToJson = 22,
-    _OrthancPluginService_CreateDicom = 23,
-    _OrthancPluginService_ComputeMd5 = 24,
-    _OrthancPluginService_ComputeSha1 = 25,
-    _OrthancPluginService_LookupDictionary = 26,
-
-    /* Registration of callbacks */
-    _OrthancPluginService_RegisterRestCallback = 1000,
-    _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001,
-    _OrthancPluginService_RegisterStorageArea = 1002,
-    _OrthancPluginService_RegisterOnChangeCallback = 1003,
-    _OrthancPluginService_RegisterRestCallbackNoLock = 1004,
-    _OrthancPluginService_RegisterWorklistCallback = 1005,
-    _OrthancPluginService_RegisterDecodeImageCallback = 1006,
-
-    /* Sending answers to REST calls */
-    _OrthancPluginService_AnswerBuffer = 2000,
-    _OrthancPluginService_CompressAndAnswerPngImage = 2001,  /* Unused as of Orthanc 0.9.4 */
-    _OrthancPluginService_Redirect = 2002,
-    _OrthancPluginService_SendHttpStatusCode = 2003,
-    _OrthancPluginService_SendUnauthorized = 2004,
-    _OrthancPluginService_SendMethodNotAllowed = 2005,
-    _OrthancPluginService_SetCookie = 2006,
-    _OrthancPluginService_SetHttpHeader = 2007,
-    _OrthancPluginService_StartMultipartAnswer = 2008,
-    _OrthancPluginService_SendMultipartItem = 2009,
-    _OrthancPluginService_SendHttpStatus = 2010,
-    _OrthancPluginService_CompressAndAnswerImage = 2011,
-    _OrthancPluginService_SendMultipartItem2 = 2012,
-
-    /* Access to the Orthanc database and API */
-    _OrthancPluginService_GetDicomForInstance = 3000,
-    _OrthancPluginService_RestApiGet = 3001,
-    _OrthancPluginService_RestApiPost = 3002,
-    _OrthancPluginService_RestApiDelete = 3003,
-    _OrthancPluginService_RestApiPut = 3004,
-    _OrthancPluginService_LookupPatient = 3005,
-    _OrthancPluginService_LookupStudy = 3006,
-    _OrthancPluginService_LookupSeries = 3007,
-    _OrthancPluginService_LookupInstance = 3008,
-    _OrthancPluginService_LookupStudyWithAccessionNumber = 3009,
-    _OrthancPluginService_RestApiGetAfterPlugins = 3010,
-    _OrthancPluginService_RestApiPostAfterPlugins = 3011,
-    _OrthancPluginService_RestApiDeleteAfterPlugins = 3012,
-    _OrthancPluginService_RestApiPutAfterPlugins = 3013,
-    _OrthancPluginService_ReconstructMainDicomTags = 3014,
-    _OrthancPluginService_RestApiGet2 = 3015,
-
-    /* Access to DICOM instances */
-    _OrthancPluginService_GetInstanceRemoteAet = 4000,
-    _OrthancPluginService_GetInstanceSize = 4001,
-    _OrthancPluginService_GetInstanceData = 4002,
-    _OrthancPluginService_GetInstanceJson = 4003,
-    _OrthancPluginService_GetInstanceSimplifiedJson = 4004,
-    _OrthancPluginService_HasInstanceMetadata = 4005,
-    _OrthancPluginService_GetInstanceMetadata = 4006,
-    _OrthancPluginService_GetInstanceOrigin = 4007,
-
-    /* Services for plugins implementing a database back-end */
-    _OrthancPluginService_RegisterDatabaseBackend = 5000,
-    _OrthancPluginService_DatabaseAnswer = 5001,
-    _OrthancPluginService_RegisterDatabaseBackendV2 = 5002,
-    _OrthancPluginService_StorageAreaCreate = 5003,
-    _OrthancPluginService_StorageAreaRead = 5004,
-    _OrthancPluginService_StorageAreaRemove = 5005,
-
-    /* Primitives for handling images */
-    _OrthancPluginService_GetImagePixelFormat = 6000,
-    _OrthancPluginService_GetImageWidth = 6001,
-    _OrthancPluginService_GetImageHeight = 6002,
-    _OrthancPluginService_GetImagePitch = 6003,
-    _OrthancPluginService_GetImageBuffer = 6004,
-    _OrthancPluginService_UncompressImage = 6005,
-    _OrthancPluginService_FreeImage = 6006,
-    _OrthancPluginService_CompressImage = 6007,
-    _OrthancPluginService_ConvertPixelFormat = 6008,
-    _OrthancPluginService_GetFontsCount = 6009,
-    _OrthancPluginService_GetFontInfo = 6010,
-    _OrthancPluginService_DrawText = 6011,
-    _OrthancPluginService_CreateImage = 6012,
-    _OrthancPluginService_CreateImageAccessor = 6013,
-    _OrthancPluginService_DecodeDicomImage = 6014,
-
-    /* Primitives for handling worklists */
-    _OrthancPluginService_WorklistAddAnswer = 7000,
-    _OrthancPluginService_WorklistMarkIncomplete = 7001,
-    _OrthancPluginService_WorklistIsMatch = 7002,
-    _OrthancPluginService_WorklistGetDicomQuery = 7003,
-
-    _OrthancPluginService_INTERNAL = 0x7fffffff
-  } _OrthancPluginService;
-
-
-  typedef enum
-  {
-    _OrthancPluginProperty_Description = 1,
-    _OrthancPluginProperty_RootUri = 2,
-    _OrthancPluginProperty_OrthancExplorer = 3,
-
-    _OrthancPluginProperty_INTERNAL = 0x7fffffff
-  } _OrthancPluginProperty;
-
-
-
-  /**
-   * The memory layout of the pixels of an image.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    /**
-     * @brief Graylevel 8bpp image.
-     *
-     * The image is graylevel. Each pixel is unsigned and stored in
-     * one byte.
-     **/
-    OrthancPluginPixelFormat_Grayscale8 = 1,
-
-    /**
-     * @brief Graylevel, unsigned 16bpp image.
-     *
-     * The image is graylevel. Each pixel is unsigned and stored in
-     * two bytes.
-     **/
-    OrthancPluginPixelFormat_Grayscale16 = 2,
-
-    /**
-     * @brief Graylevel, signed 16bpp image.
-     *
-     * The image is graylevel. Each pixel is signed and stored in two
-     * bytes.
-     **/
-    OrthancPluginPixelFormat_SignedGrayscale16 = 3,
-
-    /**
-     * @brief Color image in RGB24 format.
-     *
-     * This format describes a color image. The pixels are stored in 3
-     * consecutive bytes. The memory layout is RGB.
-     **/
-    OrthancPluginPixelFormat_RGB24 = 4,
-
-    /**
-     * @brief Color image in RGBA32 format.
-     *
-     * This format describes a color image. The pixels are stored in 4
-     * consecutive bytes. The memory layout is RGBA.
-     **/
-    OrthancPluginPixelFormat_RGBA32 = 5,
-
-    OrthancPluginPixelFormat_Unknown = 6,   /*!< Unknown pixel format */
-
-    _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginPixelFormat;
-
-
-
-  /**
-   * The content types that are supported by Orthanc plugins.
-   **/
-  typedef enum
-  {
-    OrthancPluginContentType_Unknown = 0,      /*!< Unknown content type */
-    OrthancPluginContentType_Dicom = 1,        /*!< DICOM */
-    OrthancPluginContentType_DicomAsJson = 2,  /*!< JSON summary of a DICOM file */
-
-    _OrthancPluginContentType_INTERNAL = 0x7fffffff
-  } OrthancPluginContentType;
-
-
-
-  /**
-   * The supported types of DICOM resources.
-   **/
-  typedef enum
-  {
-    OrthancPluginResourceType_Patient = 0,     /*!< Patient */
-    OrthancPluginResourceType_Study = 1,       /*!< Study */
-    OrthancPluginResourceType_Series = 2,      /*!< Series */
-    OrthancPluginResourceType_Instance = 3,    /*!< Instance */
-    OrthancPluginResourceType_None = 4,        /*!< Unavailable resource type */
-
-    _OrthancPluginResourceType_INTERNAL = 0x7fffffff
-  } OrthancPluginResourceType;
-
-
-
-  /**
-   * The supported types of changes that can happen to DICOM resources.
-   * @ingroup Callbacks
-   **/
-  typedef enum
-  {
-    OrthancPluginChangeType_CompletedSeries = 0,    /*!< Series is now complete */
-    OrthancPluginChangeType_Deleted = 1,            /*!< Deleted resource */
-    OrthancPluginChangeType_NewChildInstance = 2,   /*!< A new instance was added to this resource */
-    OrthancPluginChangeType_NewInstance = 3,        /*!< New instance received */
-    OrthancPluginChangeType_NewPatient = 4,         /*!< New patient created */
-    OrthancPluginChangeType_NewSeries = 5,          /*!< New series created */
-    OrthancPluginChangeType_NewStudy = 6,           /*!< New study created */
-    OrthancPluginChangeType_StablePatient = 7,      /*!< Timeout: No new instance in this patient */
-    OrthancPluginChangeType_StableSeries = 8,       /*!< Timeout: No new instance in this series */
-    OrthancPluginChangeType_StableStudy = 9,        /*!< Timeout: No new instance in this study */
-    OrthancPluginChangeType_OrthancStarted = 10,    /*!< Orthanc has started */
-    OrthancPluginChangeType_OrthancStopped = 11,    /*!< Orthanc is stopping */
-    OrthancPluginChangeType_UpdatedAttachment = 12, /*!< Some user-defined attachment has changed for this resource */
-    OrthancPluginChangeType_UpdatedMetadata = 13,   /*!< Some user-defined metadata has changed for this resource */
-
-    _OrthancPluginChangeType_INTERNAL = 0x7fffffff
-  } OrthancPluginChangeType;
-
-
-  /**
-   * The compression algorithms that are supported by the Orthanc core.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    OrthancPluginCompressionType_Zlib = 0,          /*!< Standard zlib compression */
-    OrthancPluginCompressionType_ZlibWithSize = 1,  /*!< zlib, prefixed with uncompressed size (uint64_t) */
-    OrthancPluginCompressionType_Gzip = 2,          /*!< Standard gzip compression */
-    OrthancPluginCompressionType_GzipWithSize = 3,  /*!< gzip, prefixed with uncompressed size (uint64_t) */
-
-    _OrthancPluginCompressionType_INTERNAL = 0x7fffffff
-  } OrthancPluginCompressionType;
-
-
-  /**
-   * The image formats that are supported by the Orthanc core.
-   * @ingroup Images
-   **/
-  typedef enum
-  {
-    OrthancPluginImageFormat_Png = 0,    /*!< Image compressed using PNG */
-    OrthancPluginImageFormat_Jpeg = 1,   /*!< Image compressed using JPEG */
-    OrthancPluginImageFormat_Dicom = 2,  /*!< Image compressed using DICOM */
-
-    _OrthancPluginImageFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginImageFormat;
-
-
-  /**
-   * The value representations present in the DICOM standard (version 2013).
-   * @ingroup Toolbox
-   **/
-  typedef enum
-  {
-    OrthancPluginValueRepresentation_AE = 1,   /*!< Application Entity */
-    OrthancPluginValueRepresentation_AS = 2,   /*!< Age String */
-    OrthancPluginValueRepresentation_AT = 3,   /*!< Attribute Tag */
-    OrthancPluginValueRepresentation_CS = 4,   /*!< Code String */
-    OrthancPluginValueRepresentation_DA = 5,   /*!< Date */
-    OrthancPluginValueRepresentation_DS = 6,   /*!< Decimal String */
-    OrthancPluginValueRepresentation_DT = 7,   /*!< Date Time */
-    OrthancPluginValueRepresentation_FD = 8,   /*!< Floating Point Double */
-    OrthancPluginValueRepresentation_FL = 9,   /*!< Floating Point Single */
-    OrthancPluginValueRepresentation_IS = 10,  /*!< Integer String */
-    OrthancPluginValueRepresentation_LO = 11,  /*!< Long String */
-    OrthancPluginValueRepresentation_LT = 12,  /*!< Long Text */
-    OrthancPluginValueRepresentation_OB = 13,  /*!< Other Byte String */
-    OrthancPluginValueRepresentation_OF = 14,  /*!< Other Float String */
-    OrthancPluginValueRepresentation_OW = 15,  /*!< Other Word String */
-    OrthancPluginValueRepresentation_PN = 16,  /*!< Person Name */
-    OrthancPluginValueRepresentation_SH = 17,  /*!< Short String */
-    OrthancPluginValueRepresentation_SL = 18,  /*!< Signed Long */
-    OrthancPluginValueRepresentation_SQ = 19,  /*!< Sequence of Items */
-    OrthancPluginValueRepresentation_SS = 20,  /*!< Signed Short */
-    OrthancPluginValueRepresentation_ST = 21,  /*!< Short Text */
-    OrthancPluginValueRepresentation_TM = 22,  /*!< Time */
-    OrthancPluginValueRepresentation_UI = 23,  /*!< Unique Identifier (UID) */
-    OrthancPluginValueRepresentation_UL = 24,  /*!< Unsigned Long */
-    OrthancPluginValueRepresentation_UN = 25,  /*!< Unknown */
-    OrthancPluginValueRepresentation_US = 26,  /*!< Unsigned Short */
-    OrthancPluginValueRepresentation_UT = 27,  /*!< Unlimited Text */
-
-    _OrthancPluginValueRepresentation_INTERNAL = 0x7fffffff
-  } OrthancPluginValueRepresentation;
-
-
-  /**
-   * The possible output formats for a DICOM-to-JSON conversion.
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomToJson()
-   **/
-  typedef enum
-  {
-    OrthancPluginDicomToJsonFormat_Full = 1,    /*!< Full output, with most details */
-    OrthancPluginDicomToJsonFormat_Short = 2,   /*!< Tags output as hexadecimal numbers */
-    OrthancPluginDicomToJsonFormat_Human = 3,   /*!< Human-readable JSON */
-
-    _OrthancPluginDicomToJsonFormat_INTERNAL = 0x7fffffff
-  } OrthancPluginDicomToJsonFormat;
-
-
-  /**
-   * Flags to customize a DICOM-to-JSON conversion. By default, binary
-   * tags are formatted using Data URI scheme.
-   * @ingroup Toolbox
-   **/
-  typedef enum
-  {
-    OrthancPluginDicomToJsonFlags_IncludeBinary         = (1 << 0),  /*!< Include the binary tags */
-    OrthancPluginDicomToJsonFlags_IncludePrivateTags    = (1 << 1),  /*!< Include the private tags */
-    OrthancPluginDicomToJsonFlags_IncludeUnknownTags    = (1 << 2),  /*!< Include the tags unknown by the dictionary */
-    OrthancPluginDicomToJsonFlags_IncludePixelData      = (1 << 3),  /*!< Include the pixel data */
-    OrthancPluginDicomToJsonFlags_ConvertBinaryToAscii  = (1 << 4),  /*!< Output binary tags as-is, dropping non-ASCII */
-    OrthancPluginDicomToJsonFlags_ConvertBinaryToNull   = (1 << 5),  /*!< Signal binary tags as null values */
-
-    _OrthancPluginDicomToJsonFlags_INTERNAL = 0x7fffffff
-  } OrthancPluginDicomToJsonFlags;
-
-
-  /**
-   * Flags to the creation of a DICOM file.
-   * @ingroup Toolbox
-   * @see OrthancPluginCreateDicom()
-   **/
-  typedef enum
-  {
-    OrthancPluginCreateDicomFlags_DecodeDataUriScheme   = (1 << 0),  /*!< Decode fields encoded using data URI scheme */
-    OrthancPluginCreateDicomFlags_GenerateIdentifiers   = (1 << 1),  /*!< Automatically generate DICOM identifiers */
-
-    _OrthancPluginCreateDicomFlags_INTERNAL = 0x7fffffff
-  } OrthancPluginCreateDicomFlags;
-
-
-  /**
-   * The constraints on the DICOM identifiers that must be supported
-   * by the database plugins.
-   **/
-  typedef enum
-  {
-    OrthancPluginIdentifierConstraint_Equal = 1,           /*!< Equal */
-    OrthancPluginIdentifierConstraint_SmallerOrEqual = 2,  /*!< Less or equal */
-    OrthancPluginIdentifierConstraint_GreaterOrEqual = 3,  /*!< More or equal */
-    OrthancPluginIdentifierConstraint_Wildcard = 4,        /*!< Case-sensitive wildcard matching (with * and ?) */
-
-    _OrthancPluginIdentifierConstraint_INTERNAL = 0x7fffffff
-  } OrthancPluginIdentifierConstraint;
-
-
-  /**
-   * The origin of a DICOM instance that has been received by Orthanc.
-   **/
-  typedef enum
-  {
-    OrthancPluginInstanceOrigin_Unknown = 1,        /*!< Unknown origin */
-    OrthancPluginInstanceOrigin_DicomProtocol = 2,  /*!< Instance received through DICOM protocol */
-    OrthancPluginInstanceOrigin_RestApi = 3,        /*!< Instance received through REST API of Orthanc */
-    OrthancPluginInstanceOrigin_Plugin = 4,         /*!< Instance added to Orthanc by a plugin */
-    OrthancPluginInstanceOrigin_Lua = 5,            /*!< Instance added to Orthanc by a Lua script */
-
-    _OrthancPluginInstanceOrigin_INTERNAL = 0x7fffffff
-  } OrthancPluginInstanceOrigin;
-
-
-  /**
-   * @brief A memory buffer allocated by the core system of Orthanc.
-   *
-   * A memory buffer allocated by the core system of Orthanc. When the
-   * content of the buffer is not useful anymore, it must be free by a
-   * call to ::OrthancPluginFreeMemoryBuffer().
-   **/
-  typedef struct
-  {
-    /**
-     * @brief The content of the buffer.
-     **/
-    void*      data;
-
-    /**
-     * @brief The number of bytes in the buffer.
-     **/
-    uint32_t   size;
-  } OrthancPluginMemoryBuffer;
-
-
-
-
-  /**
-   * @brief Opaque structure that represents the HTTP connection to the client application.
-   * @ingroup Callback
-   **/
-  typedef struct _OrthancPluginRestOutput_t OrthancPluginRestOutput;
-
-
-
-  /**
-   * @brief Opaque structure that represents a DICOM instance received by Orthanc.
-   **/
-  typedef struct _OrthancPluginDicomInstance_t OrthancPluginDicomInstance;
-
-
-
-  /**
-   * @brief Opaque structure that represents an image that is uncompressed in memory.
-   * @ingroup Images
-   **/
-  typedef struct _OrthancPluginImage_t OrthancPluginImage;
-
-
-
-  /**
-   * @brief Opaque structure that represents the storage area that is actually used by Orthanc.
-   * @ingroup Images
-   **/
-  typedef struct _OrthancPluginStorageArea_t OrthancPluginStorageArea;
-
-
-
-  /**
-   * @brief Opaque structure to an object that represents a C-Find query.
-   * @ingroup Worklists
-   **/
-  typedef struct _OrthancPluginWorklistQuery_t OrthancPluginWorklistQuery;
-
-
-
-  /**
-   * @brief Opaque structure to an object that represents the answers to a C-Find query.
-   * @ingroup Worklists
-   **/
-  typedef struct _OrthancPluginWorklistAnswers_t OrthancPluginWorklistAnswers;
-
-
-
-  /**
-   * @brief Signature of a callback function that answers to a REST request.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginRestCallback) (
-    OrthancPluginRestOutput* output,
-    const char* url,
-    const OrthancPluginHttpRequest* request);
-
-
-
-  /**
-   * @brief Signature of a callback function that is triggered when Orthanc receives a DICOM instance.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginOnStoredInstanceCallback) (
-    OrthancPluginDicomInstance* instance,
-    const char* instanceId);
-
-
-
-  /**
-   * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginOnChangeCallback) (
-    OrthancPluginChangeType changeType,
-    OrthancPluginResourceType resourceType,
-    const char* resourceId);
-
-
-
-  /**
-   * @brief Signature of a callback function to decode a DICOM instance as an image.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginDecodeImageCallback) (
-    OrthancPluginImage** target,
-    const void* dicom,
-    const uint32_t size,
-    uint32_t frameIndex);
-
-
-
-  /**
-   * @brief Signature of a function to free dynamic memory.
-   **/
-  typedef void (*OrthancPluginFree) (void* buffer);
-
-
-
-  /**
-   * @brief Callback for writing to the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc writes a file to the storage area.
-   *
-   * @param uuid The UUID of the file.
-   * @param content The content of the file.
-   * @param size The size of the file.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageCreate) (
-    const char* uuid,
-    const void* content,
-    int64_t size,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback for reading from the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc reads a file from the storage area.
-   *
-   * @param content The content of the file (output).
-   * @param size The size of the file (output).
-   * @param uuid The UUID of the file of interest.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageRead) (
-    void** content,
-    int64_t* size,
-    const char* uuid,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback for removing a file from the storage area.
-   *
-   * Signature of a callback function that is triggered when Orthanc deletes a file from the storage area.
-   *
-   * @param uuid The UUID of the file to be removed.
-   * @param type The content type corresponding to this file. 
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginStorageRemove) (
-    const char* uuid,
-    OrthancPluginContentType type);
-
-
-
-  /**
-   * @brief Callback to handle the C-Find SCP requests received by Orthanc.
-   *
-   * Signature of a callback function that is triggered when Orthanc
-   * receives a C-Find SCP request against modality worklists.
-   *
-   * @param answers The target structure where answers must be stored.
-   * @param query The worklist query.
-   * @param remoteAet The Application Entity Title (AET) of the modality from which the request originates.
-   * @param calledAet The Application Entity Title (AET) of the modality that is called by the request.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  typedef OrthancPluginErrorCode (*OrthancPluginWorklistCallback) (
-    OrthancPluginWorklistAnswers*     answers,
-    const OrthancPluginWorklistQuery* query,
-    const char*                       remoteAet,
-    const char*                       calledAet);
-
-
-
-  /**
-   * @brief Data structure that contains information about the Orthanc core.
-   **/
-  typedef struct _OrthancPluginContext_t
-  {
-    void*                     pluginsManager;
-    const char*               orthancVersion;
-    OrthancPluginFree         Free;
-    OrthancPluginErrorCode  (*InvokeService) (struct _OrthancPluginContext_t* context,
-                                              _OrthancPluginService service,
-                                              const void* params);
-  } OrthancPluginContext;
-
-
-  
-  /**
-   * @brief An entry in the dictionary of DICOM tags.
-   **/
-  typedef struct
-  {
-    uint16_t                          group;            /*!< The group of the tag */
-    uint16_t                          element;          /*!< The element of the tag */
-    OrthancPluginValueRepresentation  vr;               /*!< The value representation of the tag */
-    uint32_t                          minMultiplicity;  /*!< The minimum multiplicity of the tag */
-    uint32_t                          maxMultiplicity;  /*!< The maximum multiplicity of the tag (0 means arbitrary) */
-  } OrthancPluginDictionaryEntry;
-
-
-
-  /**
-   * @brief Free a string.
-   * 
-   * Free a string that was allocated by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param str The string to be freed.
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeString(
-    OrthancPluginContext* context, 
-    char* str)
-  {
-    if (str != NULL)
-    {
-      context->Free(str);
-    }
-  }
-
-
-  /**
-   * @brief Check the compatibility of the plugin wrt. the version of its hosting Orthanc.
-   * 
-   * This function checks whether the version of this C header is
-   * compatible with the current version of Orthanc. The result of
-   * this function should always be checked in the
-   * OrthancPluginInitialize() entry point of the plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return 1 if and only if the versions are compatible. If the
-   * result is 0, the initialization of the plugin should fail.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int  OrthancPluginCheckVersion(
-    OrthancPluginContext* context)
-  {
-    int major, minor, revision;
-
-    if (sizeof(int32_t) != sizeof(OrthancPluginErrorCode) ||
-        sizeof(int32_t) != sizeof(OrthancPluginHttpMethod) ||
-        sizeof(int32_t) != sizeof(_OrthancPluginService) ||
-        sizeof(int32_t) != sizeof(_OrthancPluginProperty) ||
-        sizeof(int32_t) != sizeof(OrthancPluginPixelFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginContentType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginResourceType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginChangeType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginCompressionType) ||
-        sizeof(int32_t) != sizeof(OrthancPluginImageFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginValueRepresentation) ||
-        sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFormat) ||
-        sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) ||
-        sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) ||
-        sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) ||
-        sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin))
-    {
-      /* Mismatch in the size of the enumerations */
-      return 0;
-    }
-
-    /* Assume compatibility with the mainline */
-    if (!strcmp(context->orthancVersion, "mainline"))
-    {
-      return 1;
-    }
-
-    /* Parse the version of the Orthanc core */
-    if ( 
-#ifdef _MSC_VER
-      sscanf_s
-#else
-      sscanf
-#endif
-      (context->orthancVersion, "%4d.%4d.%4d", &major, &minor, &revision) != 3)
-    {
-      return 0;
-    }
-
-    /* Check the major number of the version */
-
-    if (major > ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER)
-    {
-      return 1;
-    }
-
-    if (major < ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER)
-    {
-      return 0;
-    }
-
-    /* Check the minor number of the version */
-
-    if (minor > ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER)
-    {
-      return 1;
-    }
-
-    if (minor < ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER)
-    {
-      return 0;
-    }
-
-    /* Check the revision number of the version */
-
-    if (revision >= ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER)
-    {
-      return 1;
-    }
-    else
-    {
-      return 0;
-    }
-  }
-
-
-  /**
-   * @brief Free a memory buffer.
-   * 
-   * Free a memory buffer that was allocated by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The memory buffer to release.
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeMemoryBuffer(
-    OrthancPluginContext* context, 
-    OrthancPluginMemoryBuffer* buffer)
-  {
-    context->Free(buffer->data);
-  }
-
-
-  /**
-   * @brief Log an error.
-   *
-   * Log an error message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogError(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogError, message);
-  }
-
-
-  /**
-   * @brief Log a warning.
-   *
-   * Log a warning message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogWarning, message);
-  }
-
-
-  /**
-   * @brief Log an information.
-   *
-   * Log an information message using the Orthanc logging system.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param message The message to be logged.
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo(
-    OrthancPluginContext* context,
-    const char* message)
-  {
-    context->InvokeService(context, _OrthancPluginService_LogInfo, message);
-  }
-
-
-
-  typedef struct
-  {
-    const char* pathRegularExpression;
-    OrthancPluginRestCallback callback;
-  } _OrthancPluginRestCallback;
-
-  /**
-   * @brief Register a REST callback.
-   *
-   * This function registers a REST callback against a regular
-   * expression for a URI. This function must be called during the
-   * initialization of the plugin, i.e. inside the
-   * OrthancPluginInitialize() public function.
-   *
-   * Each REST callback is guaranteed to run in mutual exclusion.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param pathRegularExpression Regular expression for the URI. May contain groups.
-   * @param callback The callback function to handle the REST call.
-   * @see OrthancPluginRegisterRestCallbackNoLock()
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback(
-    OrthancPluginContext*     context,
-    const char*               pathRegularExpression,
-    OrthancPluginRestCallback callback)
-  {
-    _OrthancPluginRestCallback params;
-    params.pathRegularExpression = pathRegularExpression;
-    params.callback = callback;
-    context->InvokeService(context, _OrthancPluginService_RegisterRestCallback, &params);
-  }
-
-
-
-  /**
-   * @brief Register a REST callback, without locking.
-   *
-   * This function registers a REST callback against a regular
-   * expression for a URI. This function must be called during the
-   * initialization of the plugin, i.e. inside the
-   * OrthancPluginInitialize() public function.
-   *
-   * Contrarily to OrthancPluginRegisterRestCallback(), the callback
-   * will NOT be invoked in mutual exclusion. This can be useful for
-   * high-performance plugins that must handle concurrent requests
-   * (Orthanc uses a pool of threads, one thread being assigned to
-   * each incoming HTTP request). Of course, it is up to the plugin to
-   * implement the required locking mechanisms.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param pathRegularExpression Regular expression for the URI. May contain groups.
-   * @param callback The callback function to handle the REST call.
-   * @see OrthancPluginRegisterRestCallback()
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallbackNoLock(
-    OrthancPluginContext*     context,
-    const char*               pathRegularExpression,
-    OrthancPluginRestCallback callback)
-  {
-    _OrthancPluginRestCallback params;
-    params.pathRegularExpression = pathRegularExpression;
-    params.callback = callback;
-    context->InvokeService(context, _OrthancPluginService_RegisterRestCallbackNoLock, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginOnStoredInstanceCallback callback;
-  } _OrthancPluginOnStoredInstanceCallback;
-
-  /**
-   * @brief Register a callback for received instances.
-   *
-   * This function registers a callback function that is called
-   * whenever a new DICOM instance is stored into the Orthanc core.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback function.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnStoredInstanceCallback(
-    OrthancPluginContext*                  context,
-    OrthancPluginOnStoredInstanceCallback  callback)
-  {
-    _OrthancPluginOnStoredInstanceCallback params;
-    params.callback = callback;
-
-    context->InvokeService(context, _OrthancPluginService_RegisterOnStoredInstanceCallback, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              answer;
-    uint32_t                 answerSize;
-    const char*              mimeType;
-  } _OrthancPluginAnswerBuffer;
-
-  /**
-   * @brief Answer to a REST request.
-   *
-   * This function answers to a REST request with the content of a memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the answer.
-   * @param answerSize Number of bytes of the answer.
-   * @param mimeType The MIME type of the answer.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize,
-    const char*              mimeType)
-  {
-    _OrthancPluginAnswerBuffer params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.mimeType = mimeType;
-    context->InvokeService(context, _OrthancPluginService_AnswerBuffer, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput*  output;
-    OrthancPluginPixelFormat  format;
-    uint32_t                  width;
-    uint32_t                  height;
-    uint32_t                  pitch;
-    const void*               buffer;
-  } _OrthancPluginCompressAndAnswerPngImage;
-
-  typedef struct
-  {
-    OrthancPluginRestOutput*  output;
-    OrthancPluginImageFormat  imageFormat;
-    OrthancPluginPixelFormat  pixelFormat;
-    uint32_t                  width;
-    uint32_t                  height;
-    uint32_t                  pitch;
-    const void*               buffer;
-    uint8_t                   quality;
-  } _OrthancPluginCompressAndAnswerImage;
-
-
-  /**
-   * @brief Answer to a REST request with a PNG image.
-   *
-   * This function answers to a REST request with a PNG image. The
-   * parameters of this function describe a memory buffer that
-   * contains an uncompressed image. The image will be automatically compressed
-   * as a PNG image by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerPngImage(
-    OrthancPluginContext*     context,
-    OrthancPluginRestOutput*  output,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    const void*               buffer)
-  {
-    _OrthancPluginCompressAndAnswerImage params;
-    params.output = output;
-    params.imageFormat = OrthancPluginImageFormat_Png;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = 0;  /* No quality for PNG */
-    context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 instanceId;
-  } _OrthancPluginGetDicomForInstance;
-
-  /**
-   * @brief Retrieve a DICOM instance using its Orthanc identifier.
-   * 
-   * Retrieve a DICOM instance using its Orthanc identifier. The DICOM
-   * file is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param instanceId The Orthanc identifier of the DICOM instance of interest.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginGetDicomForInstance(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 instanceId)
-  {
-    _OrthancPluginGetDicomForInstance params;
-    params.target = target;
-    params.instanceId = instanceId;
-    return context->InvokeService(context, _OrthancPluginService_GetDicomForInstance, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-  } _OrthancPluginRestApiGet;
-
-  /**
-   * @brief Make a GET call to the built-in Orthanc REST API.
-   * 
-   * Make a GET call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGetAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGet(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri)
-  {
-    _OrthancPluginRestApiGet params;
-    params.target = target;
-    params.uri = uri;
-    return context->InvokeService(context, _OrthancPluginService_RestApiGet, &params);
-  }
-
-
-
-  /**
-   * @brief Make a GET call to the REST API, as tainted by the plugins.
-   * 
-   * Make a GET call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGet
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGetAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri)
-  {
-    _OrthancPluginRestApiGet params;
-    params.target = target;
-    params.uri = uri;
-    return context->InvokeService(context, _OrthancPluginService_RestApiGetAfterPlugins, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-    const char*                 body;
-    uint32_t                    bodySize;
-  } _OrthancPluginRestApiPostPut;
-
-  /**
-   * @brief Make a POST call to the built-in Orthanc REST API.
-   * 
-   * Make a POST call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the POST request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPostAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPost(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPost, &params);
-  }
-
-
-  /**
-   * @brief Make a POST call to the REST API, as tainted by the plugins.
-   * 
-   * Make a POST call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the POST request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPost
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPostAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPostAfterPlugins, &params);
-  }
-
-
-
-  /**
-   * @brief Make a DELETE call to the built-in Orthanc REST API.
-   * 
-   * Make a DELETE call to the built-in Orthanc REST API.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The URI to delete in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiDeleteAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiDelete(
-    OrthancPluginContext*       context,
-    const char*                 uri)
-  {
-    return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri);
-  }
-
-
-  /**
-   * @brief Make a DELETE call to the REST API, as tainted by the plugins.
-   * 
-   * Make a DELETE call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. 
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The URI to delete in the built-in Orthanc API.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiDelete
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiDeleteAfterPlugins(
-    OrthancPluginContext*       context,
-    const char*                 uri)
-  {
-    return context->InvokeService(context, _OrthancPluginService_RestApiDeleteAfterPlugins, uri);
-  }
-
-
-
-  /**
-   * @brief Make a PUT call to the built-in Orthanc REST API.
-   * 
-   * Make a PUT call to the built-in Orthanc REST API. The result to
-   * the query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the PUT request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPutAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPut(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPut, &params);
-  }
-
-
-
-  /**
-   * @brief Make a PUT call to the REST API, as tainted by the plugins.
-   * 
-   * Make a PUT call to the Orthanc REST API, after all the plugins
-   * are applied. In other words, if some plugin overrides or adds the
-   * called URI to the built-in Orthanc REST API, this call will
-   * return the result provided by this plugin. The result to the
-   * query is stored into a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param body The body of the PUT request.
-   * @param bodySize The size of the body.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiPut
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiPutAfterPlugins(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    const char*                 body,
-    uint32_t                    bodySize)
-  {
-    _OrthancPluginRestApiPostPut params;
-    params.target = target;
-    params.uri = uri;
-    params.body = body;
-    params.bodySize = bodySize;
-    return context->InvokeService(context, _OrthancPluginService_RestApiPutAfterPlugins, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              argument;
-  } _OrthancPluginOutputPlusArgument;
-
-  /**
-   * @brief Redirect a REST request.
-   *
-   * This function answers to a REST request by redirecting the user
-   * to another URI using HTTP status 301.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param redirection Where to redirect.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRedirect(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              redirection)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = redirection;
-    context->InvokeService(context, _OrthancPluginService_Redirect, &params);
-  }
-
-
-
-  typedef struct
-  {
-    char**       result;
-    const char*  argument;
-  } _OrthancPluginRetrieveDynamicString;
-
-  /**
-   * @brief Look for a patient.
-   *
-   * Look for a patient stored in Orthanc, using its Patient ID tag (0x0010, 0x0020).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored patients).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param patientID The Patient ID of interest.
-   * @return The NULL value if the patient is non-existent, or a string containing the 
-   * Orthanc ID of the patient. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupPatient(
-    OrthancPluginContext*  context,
-    const char*            patientID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = patientID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupPatient, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a study.
-   *
-   * Look for a study stored in Orthanc, using its Study Instance UID tag (0x0020, 0x000d).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored studies).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param studyUID The Study Instance UID of interest.
-   * @return The NULL value if the study is non-existent, or a string containing the 
-   * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudy(
-    OrthancPluginContext*  context,
-    const char*            studyUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = studyUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupStudy, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a study, using the accession number.
-   *
-   * Look for a study stored in Orthanc, using its Accession Number tag (0x0008, 0x0050).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored studies).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param accessionNumber The Accession Number of interest.
-   * @return The NULL value if the study is non-existent, or a string containing the 
-   * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudyWithAccessionNumber(
-    OrthancPluginContext*  context,
-    const char*            accessionNumber)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = accessionNumber;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupStudyWithAccessionNumber, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for a series.
-   *
-   * Look for a series stored in Orthanc, using its Series Instance UID tag (0x0020, 0x000e).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored series).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param seriesUID The Series Instance UID of interest.
-   * @return The NULL value if the series is non-existent, or a string containing the 
-   * Orthanc ID of the series. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupSeries(
-    OrthancPluginContext*  context,
-    const char*            seriesUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = seriesUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupSeries, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Look for an instance.
-   *
-   * Look for an instance stored in Orthanc, using its SOP Instance UID tag (0x0008, 0x0018).
-   * This function uses the database index to run as fast as possible (it does not loop
-   * over all the stored instances).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param sopInstanceUID The SOP Instance UID of interest.
-   * @return The NULL value if the instance is non-existent, or a string containing the 
-   * Orthanc ID of the instance. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupInstance(
-    OrthancPluginContext*  context,
-    const char*            sopInstanceUID)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = sopInstanceUID;
-
-    if (context->InvokeService(context, _OrthancPluginService_LookupInstance, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    uint16_t                 status;
-  } _OrthancPluginSendHttpStatusCode;
-
-  /**
-   * @brief Send a HTTP status code.
-   *
-   * This function answers to a REST request by sending a HTTP status
-   * code (such as "400 - Bad Request"). Note that:
-   * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer().
-   * - Redirections (status 301) must use ::OrthancPluginRedirect().
-   * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized().
-   * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param status The HTTP status code to be sent.
-   * @ingroup REST
-   * @see OrthancPluginSendHttpStatus()
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatusCode(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    uint16_t                 status)
-  {
-    _OrthancPluginSendHttpStatusCode params;
-    params.output = output;
-    params.status = status;
-    context->InvokeService(context, _OrthancPluginService_SendHttpStatusCode, &params);
-  }
-
-
-  /**
-   * @brief Signal that a REST request is not authorized.
-   *
-   * This function answers to a REST request by signaling that it is
-   * not authorized.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param realm The realm for the authorization process.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendUnauthorized(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              realm)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = realm;
-    context->InvokeService(context, _OrthancPluginService_SendUnauthorized, &params);
-  }
-
-
-  /**
-   * @brief Signal that this URI does not support this HTTP method.
-   *
-   * This function answers to a REST request by signaling that the
-   * queried URI does not support this method.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param allowedMethods The allowed methods for this URI (e.g. "GET,POST" after a PUT or a POST request).
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendMethodNotAllowed(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              allowedMethods)
-  {
-    _OrthancPluginOutputPlusArgument params;
-    params.output = output;
-    params.argument = allowedMethods;
-    context->InvokeService(context, _OrthancPluginService_SendMethodNotAllowed, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              key;
-    const char*              value;
-  } _OrthancPluginSetHttpHeader;
-
-  /**
-   * @brief Set a cookie.
-   *
-   * This function sets a cookie in the HTTP client.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param cookie The cookie to be set.
-   * @param value The value of the cookie.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetCookie(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              cookie,
-    const char*              value)
-  {
-    _OrthancPluginSetHttpHeader params;
-    params.output = output;
-    params.key = cookie;
-    params.value = value;
-    context->InvokeService(context, _OrthancPluginService_SetCookie, &params);
-  }
-
-
-  /**
-   * @brief Set some HTTP header.
-   *
-   * This function sets a HTTP header in the HTTP answer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param key The HTTP header to be set.
-   * @param value The value of the HTTP header.
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetHttpHeader(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              key,
-    const char*              value)
-  {
-    _OrthancPluginSetHttpHeader params;
-    params.output = output;
-    params.key = key;
-    params.value = value;
-    context->InvokeService(context, _OrthancPluginService_SetHttpHeader, &params);
-  }
-
-
-  typedef struct
-  {
-    char**                       resultStringToFree;
-    const char**                 resultString;
-    int64_t*                     resultInt64;
-    const char*                  key;
-    OrthancPluginDicomInstance*  instance;
-    OrthancPluginInstanceOrigin* resultOrigin;   /* New in Orthanc 0.9.5 SDK */
-  } _OrthancPluginAccessDicomInstance;
-
-
-  /**
-   * @brief Get the AET of a DICOM instance.
-   *
-   * This function returns the Application Entity Title (AET) of the
-   * DICOM modality from which a DICOM instance originates.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The AET if success, NULL if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceRemoteAet(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the size of a DICOM file.
-   *
-   * This function returns the number of bytes of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The size of the file, -1 in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int64_t OrthancPluginGetInstanceSize(
-    OrthancPluginContext*       context,
-    OrthancPluginDicomInstance* instance)
-  {
-    int64_t size;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultInt64 = &size;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return -1;
-    }
-    else
-    {
-      return size;
-    }
-  }
-
-
-  /**
-   * @brief Get the data of a DICOM file.
-   *
-   * This function returns a pointer to the content of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The pointer to the DICOM data, NULL in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceData(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the DICOM tag hierarchy as a JSON file.
-   *
-   * This function returns a pointer to a newly created string
-   * containing a JSON file. This JSON file encodes the tag hierarchy
-   * of the given DICOM instance.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The NULL value in case of error, or a string containing the JSON file.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceJson(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultStringToFree = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the DICOM tag hierarchy as a JSON file (with simplification).
-   *
-   * This function returns a pointer to a newly created string
-   * containing a JSON file. This JSON file encodes the tag hierarchy
-   * of the given DICOM instance. In contrast with
-   * ::OrthancPluginGetInstanceJson(), the returned JSON file is in
-   * its simplified version.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The NULL value in case of error, or a string containing the JSON file.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceSimplifiedJson(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance)
-  {
-    char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultStringToFree = &result;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Check whether a DICOM instance is associated with some metadata.
-   *
-   * This function checks whether the DICOM instance of interest is
-   * associated with some metadata. As of Orthanc 0.8.1, in the
-   * callbacks registered by
-   * ::OrthancPluginRegisterOnStoredInstanceCallback(), the only
-   * possibly available metadata are "ReceptionDate", "RemoteAET" and
-   * "IndexInSeries".
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @param metadata The metadata of interest.
-   * @return 1 if the metadata is present, 0 if it is absent, -1 in case of error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE int  OrthancPluginHasInstanceMetadata(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance,
-    const char*                  metadata)
-  {
-    int64_t result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultInt64 = &result;
-    params.instance = instance;
-    params.key = metadata;
-
-    if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return -1;
-    }
-    else
-    {
-      return (result != 0);
-    }
-  }
-
-
-  /**
-   * @brief Get the value of some metadata associated with a given DICOM instance.
-   *
-   * This functions returns the value of some metadata that is associated with the DICOM instance of interest.
-   * Before calling this function, the existence of the metadata must have been checked with
-   * ::OrthancPluginHasInstanceMetadata().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @param metadata The metadata of interest.
-   * @return The metadata value if success, NULL if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceMetadata(
-    OrthancPluginContext*        context,
-    OrthancPluginDicomInstance*  instance,
-    const char*                  metadata)
-  {
-    const char* result;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultString = &result;
-    params.instance = instance;
-    params.key = metadata;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageCreate  create;
-    OrthancPluginStorageRead    read;
-    OrthancPluginStorageRemove  remove;
-    OrthancPluginFree           free;
-  } _OrthancPluginRegisterStorageArea;
-
-  /**
-   * @brief Register a custom storage area.
-   *
-   * This function registers a custom storage area, to replace the
-   * built-in way Orthanc stores its files on the filesystem. This
-   * function must be called during the initialization of the plugin,
-   * i.e. inside the OrthancPluginInitialize() public function.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param create The callback function to store a file on the custom storage area.
-   * @param read The callback function to read a file from the custom storage area.
-   * @param remove The callback function to remove a file from the custom storage area.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterStorageArea(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageCreate  create,
-    OrthancPluginStorageRead    read,
-    OrthancPluginStorageRemove  remove)
-  {
-    _OrthancPluginRegisterStorageArea params;
-    params.create = create;
-    params.read = read;
-    params.remove = remove;
-
-#ifdef  __cplusplus
-    params.free = ::free;
-#else
-    params.free = free;
-#endif
-
-    context->InvokeService(context, _OrthancPluginService_RegisterStorageArea, &params);
-  }
-
-
-
-  /**
-   * @brief Return the path to the Orthanc executable.
-   *
-   * This function returns the path to the Orthanc executable.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancPath(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetOrthancPath, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the directory containing the Orthanc.
-   *
-   * This function returns the path to the directory containing the Orthanc executable.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancDirectory(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetOrthancDirectory, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the path to the configuration file(s).
-   *
-   * This function returns the path to the configuration file(s) that
-   * was specified when starting Orthanc. Since version 0.9.1, this
-   * path can refer to a folder that stores a set of configuration
-   * files. This function is deprecated in favor of
-   * OrthancPluginGetConfiguration().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the path. This string must be freed by
-   * OrthancPluginFreeString().
-   * @see OrthancPluginGetConfiguration()
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfigurationPath(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetConfigurationPath, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginOnChangeCallback callback;
-  } _OrthancPluginOnChangeCallback;
-
-  /**
-   * @brief Register a callback to monitor changes.
-   *
-   * This function registers a callback function that is called
-   * whenever a change happens to some DICOM resource.
-   *
-   * @warning If your change callback has to call the REST API of
-   * Orthanc, you should make these calls in a separate thread (with
-   * the events passing through a message queue). Otherwise, this
-   * could result in deadlocks in the presence of other plugins or Lua
-   * script.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback function.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback(
-    OrthancPluginContext*          context,
-    OrthancPluginOnChangeCallback  callback)
-  {
-    _OrthancPluginOnChangeCallback params;
-    params.callback = callback;
-
-    context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char* plugin;
-    _OrthancPluginProperty property;
-    const char* value;
-  } _OrthancPluginSetPluginProperty;
-
-
-  /**
-   * @brief Set the URI where the plugin provides its Web interface.
-   *
-   * For plugins that come with a Web interface, this function
-   * declares the entry path where to find this interface. This
-   * information is notably used in the "Plugins" page of Orthanc
-   * Explorer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param uri The root URI for this plugin.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetRootUri(
-    OrthancPluginContext*  context,
-    const char*            uri)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_RootUri;
-    params.value = uri;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  /**
-   * @brief Set a description for this plugin.
-   *
-   * Set a description for this plugin. It is displayed in the
-   * "Plugins" page of Orthanc Explorer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param description The description.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSetDescription(
-    OrthancPluginContext*  context,
-    const char*            description)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_Description;
-    params.value = description;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  /**
-   * @brief Extend the JavaScript code of Orthanc Explorer.
-   *
-   * Add JavaScript code to customize the default behavior of Orthanc
-   * Explorer. This can for instance be used to add new buttons.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param javascript The custom JavaScript code.
-   **/ 
-  ORTHANC_PLUGIN_INLINE void OrthancPluginExtendOrthancExplorer(
-    OrthancPluginContext*  context,
-    const char*            javascript)
-  {
-    _OrthancPluginSetPluginProperty params;
-    params.plugin = OrthancPluginGetName();
-    params.property = _OrthancPluginProperty_OrthancExplorer;
-    params.value = javascript;
-
-    context->InvokeService(context, _OrthancPluginService_SetPluginProperty, &params);
-  }
-
-
-  typedef struct
-  {
-    char**       result;
-    int32_t      property;
-    const char*  value;
-  } _OrthancPluginGlobalProperty;
-
-
-  /**
-   * @brief Get the value of a global property.
-   *
-   * Get the value of a global property that is stored in the Orthanc database. Global
-   * properties whose index is below 1024 are reserved by Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param property The global property of interest.
-   * @param defaultValue The value to return, if the global property is unset.
-   * @return The value of the global property, or NULL in the case of an error. This
-   * string must be freed by OrthancPluginFreeString().
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetGlobalProperty(
-    OrthancPluginContext*  context,
-    int32_t                property,
-    const char*            defaultValue)
-  {
-    char* result;
-
-    _OrthancPluginGlobalProperty params;
-    params.result = &result;
-    params.property = property;
-    params.value = defaultValue;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetGlobalProperty, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Set the value of a global property.
-   *
-   * Set the value of a global property into the Orthanc
-   * database. Setting a global property can be used by plugins to
-   * save their internal parameters. Plugins are only allowed to set
-   * properties whose index are above or equal to 1024 (properties
-   * below 1024 are read-only and reserved by Orthanc).
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param property The global property of interest.
-   * @param value The value to be set in the global property.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSetGlobalProperty(
-    OrthancPluginContext*  context,
-    int32_t                property,
-    const char*            value)
-  {
-    _OrthancPluginGlobalProperty params;
-    params.result = NULL;
-    params.property = property;
-    params.value = value;
-
-    return context->InvokeService(context, _OrthancPluginService_SetGlobalProperty, &params);
-  }
-
-
-
-  typedef struct
-  {
-    int32_t   *resultInt32;
-    uint32_t  *resultUint32;
-    int64_t   *resultInt64;
-    uint64_t  *resultUint64;
-  } _OrthancPluginReturnSingleValue;
-
-  /**
-   * @brief Get the number of command-line arguments.
-   *
-   * Retrieve the number of command-line arguments that were used to launch Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The number of arguments.
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetCommandLineArgumentsCount(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-  /**
-   * @brief Get the value of a command-line argument.
-   *
-   * Get the value of one of the command-line arguments that were used
-   * to launch Orthanc. The number of available arguments can be
-   * retrieved by OrthancPluginGetCommandLineArgumentsCount().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param argument The index of the argument.
-   * @return The value of the argument, or NULL in the case of an error. This
-   * string must be freed by OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginGetCommandLineArgument(
-    OrthancPluginContext*  context,
-    uint32_t               argument)
-  {
-    char* result;
-
-    _OrthancPluginGlobalProperty params;
-    params.result = &result;
-    params.property = (int32_t) argument;
-    params.value = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgument, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Get the expected version of the database schema.
-   *
-   * Retrieve the expected version of the database schema.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The version.
-   * @ingroup Callbacks
-   * @deprecated Please instead use IDatabaseBackend::UpgradeDatabase()
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetExpectedDatabaseVersion(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the content of the configuration file(s).
-   *
-   * This function returns the content of the configuration that is
-   * used by Orthanc, formatted as a JSON string.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return NULL in the case of an error, or a newly allocated string
-   * containing the configuration. This string must be freed by
-   * OrthancPluginFreeString().
-   **/
-  ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfiguration(OrthancPluginContext* context)
-  {
-    char* result;
-
-    _OrthancPluginRetrieveDynamicString params;
-    params.result = &result;
-    params.argument = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetConfiguration, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              subType;
-    const char*              contentType;
-  } _OrthancPluginStartMultipartAnswer;
-
-  /**
-   * @brief Start an HTTP multipart answer.
-   *
-   * Initiates a HTTP multipart answer, as the result of a REST request.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param subType The sub-type of the multipart answer ("mixed" or "related").
-   * @param contentType The MIME type of the items in the multipart answer.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginSendMultipartItem(), OrthancPluginSendMultipartItem2()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              subType,
-    const char*              contentType)
-  {
-    _OrthancPluginStartMultipartAnswer params;
-    params.output = output;
-    params.subType = subType;
-    params.contentType = contentType;
-    return context->InvokeService(context, _OrthancPluginService_StartMultipartAnswer, &params);
-  }
-
-
-  /**
-   * @brief Send an item as a part of some HTTP multipart answer.
-   *
-   * This function sends an item as a part of some HTTP multipart
-   * answer that was initiated by OrthancPluginStartMultipartAnswer().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the item.
-   * @param answerSize Number of bytes of the item.
-   * @return 0 if success, or the error code if failure (this notably happens
-   * if the connection is closed by the client).
-   * @see OrthancPluginSendMultipartItem2()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize)
-  {
-    _OrthancPluginAnswerBuffer params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.mimeType = NULL;
-    return context->InvokeService(context, _OrthancPluginService_SendMultipartItem, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*    target;
-    const void*                   source;
-    uint32_t                      size;
-    OrthancPluginCompressionType  compression;
-    uint8_t                       uncompress;
-  } _OrthancPluginBufferCompression;
-
-
-  /**
-   * @brief Compress or decompress a buffer.
-   *
-   * This function compresses or decompresses a buffer, using the
-   * version of the zlib library that is used by the Orthanc core.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param source The source buffer.
-   * @param size The size in bytes of the source buffer.
-   * @param compression The compression algorithm.
-   * @param uncompress If set to "0", the buffer must be compressed. 
-   * If set to "1", the buffer must be uncompressed.
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginBufferCompression(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    const void*                   source,
-    uint32_t                      size,
-    OrthancPluginCompressionType  compression,
-    uint8_t                       uncompress)
-  {
-    _OrthancPluginBufferCompression params;
-    params.target = target;
-    params.source = source;
-    params.size = size;
-    params.compression = compression;
-    params.uncompress = uncompress;
-
-    return context->InvokeService(context, _OrthancPluginService_BufferCompression, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 path;
-  } _OrthancPluginReadFile;
-
-  /**
-   * @brief Read a file.
-   * 
-   * Read the content of a file on the filesystem, and returns it into
-   * a newly allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param path The path of the file to be read.
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginReadFile(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 path)
-  {
-    _OrthancPluginReadFile params;
-    params.target = target;
-    params.path = path;
-    return context->InvokeService(context, _OrthancPluginService_ReadFile, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char*  path;
-    const void*  data;
-    uint32_t     size;
-  } _OrthancPluginWriteFile;
-
-  /**
-   * @brief Write a file.
-   * 
-   * Write the content of a memory buffer to the filesystem.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param path The path of the file to be written.
-   * @param data The content of the memory buffer.
-   * @param size The size of the memory buffer.
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWriteFile(
-    OrthancPluginContext*  context,
-    const char*            path,
-    const void*            data,
-    uint32_t               size)
-  {
-    _OrthancPluginWriteFile params;
-    params.path = path;
-    params.data = data;
-    params.size = size;
-    return context->InvokeService(context, _OrthancPluginService_WriteFile, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const char**            target;
-    OrthancPluginErrorCode  error;
-  } _OrthancPluginGetErrorDescription;
-
-  /**
-   * @brief Get the description of a given error code.
-   *
-   * This function returns the description of a given error code.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param error The error code of interest.
-   * @return The error description. This is a statically-allocated
-   * string, do not free it.
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetErrorDescription(
-    OrthancPluginContext*    context,
-    OrthancPluginErrorCode   error)
-  {
-    const char* result = NULL;
-
-    _OrthancPluginGetErrorDescription params;
-    params.target = &result;
-    params.error = error;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetErrorDescription, &params) != OrthancPluginErrorCode_Success ||
-        result == NULL)
-    {
-      return "Unknown error code";
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    uint16_t                 status;
-    const char*              body;
-    uint32_t                 bodySize;
-  } _OrthancPluginSendHttpStatus;
-
-  /**
-   * @brief Send a HTTP status, with a custom body.
-   *
-   * This function answers to a HTTP request by sending a HTTP status
-   * code (such as "400 - Bad Request"), together with a body
-   * describing the error. The body will only be returned if the
-   * configuration option "HttpDescribeErrors" of Orthanc is set to "true".
-   * 
-   * Note that:
-   * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer().
-   * - Redirections (status 301) must use ::OrthancPluginRedirect().
-   * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized().
-   * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed().
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param status The HTTP status code to be sent.
-   * @param body The body of the answer.
-   * @param bodySize The size of the body.
-   * @see OrthancPluginSendHttpStatusCode()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatus(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    uint16_t                 status,
-    const char*              body,
-    uint32_t                 bodySize)
-  {
-    _OrthancPluginSendHttpStatus params;
-    params.output = output;
-    params.status = status;
-    params.body = body;
-    params.bodySize = bodySize;
-    context->InvokeService(context, _OrthancPluginService_SendHttpStatus, &params);
-  }
-
-
-
-  typedef struct
-  {
-    const OrthancPluginImage*  image;
-    uint32_t*                  resultUint32;
-    OrthancPluginPixelFormat*  resultPixelFormat;
-    void**                     resultBuffer;
-  } _OrthancPluginGetImageInfo;
-
-
-  /**
-   * @brief Return the pixel format of an image.
-   *
-   * This function returns the type of memory layout for the pixels of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pixel format.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat  OrthancPluginGetImagePixelFormat(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    OrthancPluginPixelFormat target;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultPixelFormat = &target;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, &params) != OrthancPluginErrorCode_Success)
-    {
-      return OrthancPluginPixelFormat_Unknown;
-    }
-    else
-    {
-      return (OrthancPluginPixelFormat) target;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the width of an image.
-   *
-   * This function returns the width of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The width.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageWidth(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t width;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &width;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return width;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the height of an image.
-   *
-   * This function returns the height of the given image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The height.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImageHeight(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t height;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &height;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return height;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the pitch of an image.
-   *
-   * This function returns the pitch of the given image. The pitch is
-   * defined as the number of bytes between 2 successive lines of the
-   * image in the memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pitch.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t  OrthancPluginGetImagePitch(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    uint32_t pitch;
-    
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.resultUint32 = &pitch;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return pitch;
-    }
-  }
-
-
-
-  /**
-   * @brief Return a pointer to the content of an image.
-   *
-   * This function returns a pointer to the memory buffer that
-   * contains the pixels of the image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image of interest.
-   * @return The pointer.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE void*  OrthancPluginGetImageBuffer(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  image)
-  {
-    void* target = NULL;
-
-    _OrthancPluginGetImageInfo params;
-    memset(&params, 0, sizeof(params));
-    params.resultBuffer = &target;
-    params.image = image;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    const void*                data;
-    uint32_t                   size;
-    OrthancPluginImageFormat   format;
-  } _OrthancPluginUncompressImage;
-
-
-  /**
-   * @brief Decode a compressed image.
-   *
-   * This function decodes a compressed image from a memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param data Pointer to a memory buffer containing the compressed image.
-   * @param size Size of the memory buffer containing the compressed image.
-   * @param format The file format of the compressed image.
-   * @return The uncompressed image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage(
-    OrthancPluginContext*      context,
-    const void*                data,
-    uint32_t                   size,
-    OrthancPluginImageFormat   format)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginUncompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.data = data;
-    params.size = size;
-    params.format = format;
-
-    if (context->InvokeService(context, _OrthancPluginService_UncompressImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage*   image;
-  } _OrthancPluginFreeImage;
-
-  /**
-   * @brief Free an image.
-   *
-   * This function frees an image that was decoded with OrthancPluginUncompressImage().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE void  OrthancPluginFreeImage(
-    OrthancPluginContext* context, 
-    OrthancPluginImage*   image)
-  {
-    _OrthancPluginFreeImage params;
-    params.image = image;
-
-    context->InvokeService(context, _OrthancPluginService_FreeImage, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer* target;
-    OrthancPluginImageFormat   imageFormat;
-    OrthancPluginPixelFormat   pixelFormat;
-    uint32_t                   width;
-    uint32_t                   height;
-    uint32_t                   pitch;
-    const void*                buffer;
-    uint8_t                    quality;
-  } _OrthancPluginCompressImage;
-
-
-  /**
-   * @brief Encode a PNG image.
-   *
-   * This function compresses the given memory buffer containing an
-   * image using the PNG specification, and stores the result of the
-   * compression into a newly allocated memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginCompressAndAnswerPngImage()
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    OrthancPluginPixelFormat      format,
-    uint32_t                      width,
-    uint32_t                      height,
-    uint32_t                      pitch,
-    const void*                   buffer)
-  {
-    _OrthancPluginCompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = target;
-    params.imageFormat = OrthancPluginImageFormat_Png;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = 0;  /* Unused for PNG */
-
-    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
-  }
-
-
-  /**
-   * @brief Encode a JPEG image.
-   *
-   * This function compresses the given memory buffer containing an
-   * image using the JPEG specification, and stores the result of the
-   * compression into a newly allocated memory buffer.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @param quality The quality of the JPEG encoding, between 1 (worst
-   * quality, best compression) and 100 (best quality, worst
-   * compression).
-   * @return 0 if success, or the error code if failure.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage(
-    OrthancPluginContext*         context,
-    OrthancPluginMemoryBuffer*    target,
-    OrthancPluginPixelFormat      format,
-    uint32_t                      width,
-    uint32_t                      height,
-    uint32_t                      pitch,
-    const void*                   buffer,
-    uint8_t                       quality)
-  {
-    _OrthancPluginCompressImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = target;
-    params.imageFormat = OrthancPluginImageFormat_Jpeg;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = quality;
-
-    return context->InvokeService(context, _OrthancPluginService_CompressImage, &params);
-  }
-
-
-
-  /**
-   * @brief Answer to a REST request with a JPEG image.
-   *
-   * This function answers to a REST request with a JPEG image. The
-   * parameters of this function describe a memory buffer that
-   * contains an uncompressed image. The image will be automatically compressed
-   * as a JPEG image by the core system of Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param format The memory layout of the uncompressed image.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer containing the uncompressed image.
-   * @param quality The quality of the JPEG encoding, between 1 (worst
-   * quality, best compression) and 100 (best quality, worst
-   * compression).
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerJpegImage(
-    OrthancPluginContext*     context,
-    OrthancPluginRestOutput*  output,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    const void*               buffer,
-    uint8_t                   quality)
-  {
-    _OrthancPluginCompressAndAnswerImage params;
-    params.output = output;
-    params.imageFormat = OrthancPluginImageFormat_Jpeg;
-    params.pixelFormat = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-    params.quality = quality;
-    context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    OrthancPluginHttpMethod     method;
-    const char*                 url;
-    const char*                 username;
-    const char*                 password;
-    const char*                 body;
-    uint32_t                    bodySize;
-  } _OrthancPluginCallHttpClient;
-
-
-  /**
-   * @brief Issue a HTTP GET call.
-   * 
-   * Make a HTTP GET call to the given URL. The result to the query is
-   * stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiGet() if calling the built-in REST API of the
-   * Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpGet(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Get;
-    params.url = url;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP POST call.
-   * 
-   * Make a HTTP POST call to the given URL. The result to the query
-   * is stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiPost() if calling the built-in REST API of
-   * the Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param body The content of the body of the request.
-   * @param bodySize The size of the body of the request.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpPost(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 body,
-    uint32_t                    bodySize,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Post;
-    params.url = url;
-    params.body = body;
-    params.bodySize = bodySize;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP PUT call.
-   * 
-   * Make a HTTP PUT call to the given URL. The result to the query is
-   * stored into a newly allocated memory buffer. Favor
-   * OrthancPluginRestApiPut() if calling the built-in REST API of the
-   * Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param url The URL of interest.
-   * @param body The content of the body of the request.
-   * @param bodySize The size of the body of the request.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpPut(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 url,
-    const char*                 body,
-    uint32_t                    bodySize,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.target = target;
-    params.method = OrthancPluginHttpMethod_Put;
-    params.url = url;
-    params.body = body;
-    params.bodySize = bodySize;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-  /**
-   * @brief Issue a HTTP DELETE call.
-   * 
-   * Make a HTTP DELETE call to the given URL. Favor
-   * OrthancPluginRestApiDelete() if calling the built-in REST API of
-   * the Orthanc instance that hosts this plugin.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param url The URL of interest.
-   * @param username The username (can be <tt>NULL</tt> if no password protection).
-   * @param password The password (can be <tt>NULL</tt> if no password protection).
-   * @return 0 if success, or the error code if failure.
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpDelete(
-    OrthancPluginContext*       context,
-    const char*                 url,
-    const char*                 username,
-    const char*                 password)
-  {
-    _OrthancPluginCallHttpClient params;
-    memset(&params, 0, sizeof(params));
-
-    params.method = OrthancPluginHttpMethod_Delete;
-    params.url = url;
-    params.username = username;
-    params.password = password;
-
-    return context->InvokeService(context, _OrthancPluginService_CallHttpClient, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    const OrthancPluginImage*  source;
-    OrthancPluginPixelFormat   targetFormat;
-  } _OrthancPluginConvertPixelFormat;
-
-
-  /**
-   * @brief Change the pixel format of an image.
-   *
-   * This function creates a new image, changing the memory layout of the pixels.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param source The source image.
-   * @param targetFormat The target pixel format.
-   * @return The resulting image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginConvertPixelFormat(
-    OrthancPluginContext*      context,
-    const OrthancPluginImage*  source,
-    OrthancPluginPixelFormat   targetFormat)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginConvertPixelFormat params;
-    params.target = &target;
-    params.source = source;
-    params.targetFormat = targetFormat;
-
-    if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  /**
-   * @brief Return the number of available fonts.
-   *
-   * This function returns the number of fonts that are built in the
-   * Orthanc core. These fonts can be used to draw texts on images
-   * through OrthancPluginDrawText().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @return The number of fonts.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontsCount(
-    OrthancPluginContext*  context)
-  {
-    uint32_t count = 0;
-
-    _OrthancPluginReturnSingleValue params;
-    memset(&params, 0, sizeof(params));
-    params.resultUint32 = &count;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return 0;
-    }
-    else
-    {
-      return count;
-    }
-  }
-
-
-
-
-  typedef struct
-  {
-    uint32_t      fontIndex; /* in */
-    const char**  name; /* out */
-    uint32_t*     size; /* out */
-  } _OrthancPluginGetFontInfo;
-
-  /**
-   * @brief Return the name of a font.
-   *
-   * This function returns the name of a font that is built in the Orthanc core.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @return The font name. This is a statically-allocated string, do not free it.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetFontName(
-    OrthancPluginContext*  context,
-    uint32_t               fontIndex)
-  {
-    const char* result = NULL;
-
-    _OrthancPluginGetFontInfo params;
-    memset(&params, 0, sizeof(params));
-    params.name = &result;
-    params.fontIndex = fontIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Return the size of a font.
-   *
-   * This function returns the size of a font that is built in the Orthanc core.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @return The font size.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontSize(
-    OrthancPluginContext*  context,
-    uint32_t               fontIndex)
-  {
-    uint32_t result;
-
-    _OrthancPluginGetFontInfo params;
-    memset(&params, 0, sizeof(params));
-    params.size = &result;
-    params.fontIndex = fontIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != OrthancPluginErrorCode_Success)
-    {
-      return 0;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginImage*   image;
-    uint32_t              fontIndex;
-    const char*           utf8Text;
-    int32_t               x;
-    int32_t               y;
-    uint8_t               r;
-    uint8_t               g;
-    uint8_t               b;
-  } _OrthancPluginDrawText;
-
-
-  /**
-   * @brief Draw text on an image.
-   *
-   * This function draws some text on some image.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param image The image upon which to draw the text.
-   * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount().
-   * @param utf8Text The text to be drawn, encoded as an UTF-8 zero-terminated string.
-   * @param x The X position of the text over the image.
-   * @param y The Y position of the text over the image.
-   * @param r The value of the red color channel of the text.
-   * @param g The value of the green color channel of the text.
-   * @param b The value of the blue color channel of the text.
-   * @return 0 if success, other value if error.
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginDrawText(
-    OrthancPluginContext*  context,
-    OrthancPluginImage*    image,
-    uint32_t               fontIndex,
-    const char*            utf8Text,
-    int32_t                x,
-    int32_t                y,
-    uint8_t                r,
-    uint8_t                g,
-    uint8_t                b)
-  {
-    _OrthancPluginDrawText params;
-    memset(&params, 0, sizeof(params));
-    params.image = image;
-    params.fontIndex = fontIndex;
-    params.utf8Text = utf8Text;
-    params.x = x;
-    params.y = y;
-    params.r = r;
-    params.g = g;
-    params.b = b;
-
-    return context->InvokeService(context, _OrthancPluginService_DrawText, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    const void*                 content;
-    uint64_t                    size;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaCreate;
-
-
-  /**
-   * @brief Create a file inside the storage area.
-   *
-   * This function creates a new file inside the storage area that is
-   * currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be created.
-   * @param content The content to store in the newly created file.
-   * @param size The size of the content.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaCreate(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    const void*                 content,
-    uint64_t                    size,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaCreate params;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.content = content;
-    params.size = size;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaCreate, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaRead;
-
-
-  /**
-   * @brief Read a file from the storage area.
-   *
-   * This function reads the content of a given file from the storage
-   * area that is currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be read.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaRead(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaRead params;
-    params.target = target;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaRead, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*   storageArea;
-    const char*                 uuid;
-    OrthancPluginContentType    type;
-  } _OrthancPluginStorageAreaRemove;
-
-  /**
-   * @brief Remove a file from the storage area.
-   *
-   * This function removes a given file from the storage area that is
-   * currently used by Orthanc.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param uuid The identifier of the file to be removed.
-   * @param type The type of the file content.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginStorageAreaRemove(
-    OrthancPluginContext*       context,
-    OrthancPluginStorageArea*   storageArea,
-    const char*                 uuid,
-    OrthancPluginContentType    type)
-  {
-    _OrthancPluginStorageAreaRemove params;
-    params.storageArea = storageArea;
-    params.uuid = uuid;
-    params.type = type;
-
-    return context->InvokeService(context, _OrthancPluginService_StorageAreaRemove, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginErrorCode*  target;
-    int32_t                  code;
-    uint16_t                 httpStatus;
-    const char*              message;
-  } _OrthancPluginRegisterErrorCode;
-  
-  /**
-   * @brief Declare a custom error code for this plugin.
-   *
-   * This function declares a custom error code that can be generated
-   * by this plugin. This declaration is used to enrich the body of
-   * the HTTP answer in the case of an error, and to set the proper
-   * HTTP status code.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param code The error code that is internal to this plugin.
-   * @param httpStatus The HTTP status corresponding to this error.
-   * @param message The description of the error.
-   * @return The error code that has been assigned inside the Orthanc core.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRegisterErrorCode(
-    OrthancPluginContext*    context,
-    int32_t                  code,
-    uint16_t                 httpStatus,
-    const char*              message)
-  {
-    OrthancPluginErrorCode target;
-
-    _OrthancPluginRegisterErrorCode params;
-    params.target = &target;
-    params.code = code;
-    params.httpStatus = httpStatus;
-    params.message = message;
-
-    if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, &params) == OrthancPluginErrorCode_Success)
-    {
-      return target;
-    }
-    else
-    {
-      /* There was an error while assigned the error. Use a generic code. */
-      return OrthancPluginErrorCode_Plugin;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    uint16_t                          group;
-    uint16_t                          element;
-    OrthancPluginValueRepresentation  vr;
-    const char*                       name;
-    uint32_t                          minMultiplicity;
-    uint32_t                          maxMultiplicity;
-  } _OrthancPluginRegisterDictionaryTag;
-  
-  /**
-   * @brief Register a new tag into the DICOM dictionary.
-   *
-   * This function declares a new tag in the dictionary of DICOM tags
-   * that are known to Orthanc. This function should be used in the
-   * OrthancPluginInitialize() callback.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param group The group of the tag.
-   * @param element The element of the tag.
-   * @param vr The value representation of the tag.
-   * @param name The nickname of the tag.
-   * @param minMultiplicity The minimum multiplicity of the tag (must be above 0).
-   * @param maxMultiplicity The maximum multiplicity of the tag. A value of 0 means
-   * an arbitrary multiplicity ("<tt>n</tt>").
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRegisterDictionaryTag(
-    OrthancPluginContext*             context,
-    uint16_t                          group,
-    uint16_t                          element,
-    OrthancPluginValueRepresentation  vr,
-    const char*                       name,
-    uint32_t                          minMultiplicity,
-    uint32_t                          maxMultiplicity)
-  {
-    _OrthancPluginRegisterDictionaryTag params;
-    params.group = group;
-    params.element = element;
-    params.vr = vr;
-    params.name = name;
-    params.minMultiplicity = minMultiplicity;
-    params.maxMultiplicity = maxMultiplicity;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterDictionaryTag, &params);
-  }
-
-
-
-
-  typedef struct
-  {
-    OrthancPluginStorageArea*  storageArea;
-    OrthancPluginResourceType  level;
-  } _OrthancPluginReconstructMainDicomTags;
-
-  /**
-   * @brief Reconstruct the main DICOM tags.
-   *
-   * This function requests the Orthanc core to reconstruct the main
-   * DICOM tags of all the resources of the given type. This function
-   * can only be used as a part of the upgrade of a custom database
-   * back-end
-   * (cf. OrthancPlugins::IDatabaseBackend::UpgradeDatabase). A
-   * database transaction will be automatically setup.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param storageArea The storage area.
-   * @param level The type of the resources of interest.
-   * @return 0 if success, other value if error.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginReconstructMainDicomTags(
-    OrthancPluginContext*      context,
-    OrthancPluginStorageArea*  storageArea,
-    OrthancPluginResourceType  level)
-  {
-    _OrthancPluginReconstructMainDicomTags params;
-    params.level = level;
-    params.storageArea = storageArea;
-
-    return context->InvokeService(context, _OrthancPluginService_ReconstructMainDicomTags, &params);
-  }
-
-
-  typedef struct
-  {
-    char**                          result;
-    const char*                     instanceId;
-    const char*                     buffer;
-    uint32_t                        size;
-    OrthancPluginDicomToJsonFormat  format;
-    OrthancPluginDicomToJsonFlags   flags;
-    uint32_t                        maxStringLength;
-  } _OrthancPluginDicomToJson;
-
-
-  /**
-   * @brief Format a DICOM memory buffer as a JSON string.
-   *
-   * This function takes as input a memory buffer containing a DICOM
-   * file, and outputs a JSON string representing the tags of this
-   * DICOM file.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The memory buffer containing the DICOM file.
-   * @param size The size of the memory buffer.
-   * @param format The output format.
-   * @param flags Flags governing the output.
-   * @param maxStringLength The maximum length of a field. Too long fields will
-   * be output as "null". The 0 value means no maximum length.
-   * @return The NULL value if the case of an error, or the JSON
-   * string. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomInstanceToJson
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomBufferToJson(
-    OrthancPluginContext*           context,
-    const char*                     buffer,
-    uint32_t                        size,
-    OrthancPluginDicomToJsonFormat  format,
-    OrthancPluginDicomToJsonFlags   flags, 
-    uint32_t                        maxStringLength)
-  {
-    char* result;
-
-    _OrthancPluginDicomToJson params;
-    memset(&params, 0, sizeof(params));
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-    params.format = format;
-    params.flags = flags;
-    params.maxStringLength = maxStringLength;
-
-    if (context->InvokeService(context, _OrthancPluginService_DicomBufferToJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Format a DICOM instance as a JSON string.
-   *
-   * This function formats a DICOM instance that is stored in Orthanc,
-   * and outputs a JSON string representing the tags of this DICOM
-   * instance.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instanceId The Orthanc identifier of the instance.
-   * @param format The output format.
-   * @param flags Flags governing the output.
-   * @param maxStringLength The maximum length of a field. Too long fields will
-   * be output as "null". The 0 value means no maximum length.
-   * @return The NULL value if the case of an error, or the JSON
-   * string. This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomInstanceToJson
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomInstanceToJson(
-    OrthancPluginContext*           context,
-    const char*                     instanceId,
-    OrthancPluginDicomToJsonFormat  format,
-    OrthancPluginDicomToJsonFlags   flags, 
-    uint32_t                        maxStringLength)
-  {
-    char* result;
-
-    _OrthancPluginDicomToJson params;
-    memset(&params, 0, sizeof(params));
-    params.result = &result;
-    params.instanceId = instanceId;
-    params.format = format;
-    params.flags = flags;
-    params.maxStringLength = maxStringLength;
-
-    if (context->InvokeService(context, _OrthancPluginService_DicomInstanceToJson, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*  target;
-    const char*                 uri;
-    uint32_t                    headersCount;
-    const char* const*          headersKeys;
-    const char* const*          headersValues;
-    int32_t                     afterPlugins;
-  } _OrthancPluginRestApiGet2;
-
-  /**
-   * @brief Make a GET call to the Orthanc REST API, with custom HTTP headers.
-   * 
-   * Make a GET call to the Orthanc REST API with extended
-   * parameters. The result to the query is stored into a newly
-   * allocated memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param uri The URI in the built-in Orthanc API.
-   * @param headersCount The number of HTTP headers.
-   * @param headersKeys Array containing the keys of the HTTP headers.
-   * @param headersValues Array containing the values of the HTTP headers.
-   * @param afterPlugins If 0, the built-in API of Orthanc is used.
-   * If 1, the API is tainted by the plugins.
-   * @return 0 if success, or the error code if failure.
-   * @see OrthancPluginRestApiGet, OrthancPluginRestApiGetAfterPlugins
-   * @ingroup Orthanc
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginRestApiGet2(
-    OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
-    const char*                 uri,
-    uint32_t                    headersCount,
-    const char* const*          headersKeys,
-    const char* const*          headersValues,
-    int32_t                     afterPlugins)
-  {
-    _OrthancPluginRestApiGet2 params;
-    params.target = target;
-    params.uri = uri;
-    params.headersCount = headersCount;
-    params.headersKeys = headersKeys;
-    params.headersValues = headersValues;
-    params.afterPlugins = afterPlugins;
-
-    return context->InvokeService(context, _OrthancPluginService_RestApiGet2, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginWorklistCallback callback;
-  } _OrthancPluginWorklistCallback;
-
-  /**
-   * @brief Register a callback to handle modality worklists requests.
-   *
-   * This function registers a callback to handle C-Find SCP requests
-   * on modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param callback The callback.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterWorklistCallback(
-    OrthancPluginContext*          context,
-    OrthancPluginWorklistCallback  callback)
-  {
-    _OrthancPluginWorklistCallback params;
-    params.callback = callback;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterWorklistCallback, &params);
-  }
-
-
-  
-  typedef struct
-  {
-    OrthancPluginWorklistAnswers*      answers;
-    const OrthancPluginWorklistQuery*  query;
-    const void*                        dicom;
-    uint32_t                           size;
-  } _OrthancPluginWorklistAnswersOperation;
-
-  /**
-   * @brief Add one answer to some modality worklist request.
-   *
-   * This function adds one worklist (encoded as a DICOM file) to the
-   * set of answers corresponding to some C-Find SCP request against
-   * modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param answers The set of answers.
-   * @param query The worklist query, as received by the callback.
-   * @param dicom The worklist to answer, encoded as a DICOM file.
-   * @param size The size of the DICOM file.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistAddAnswer(
-    OrthancPluginContext*             context,
-    OrthancPluginWorklistAnswers*     answers,
-    const OrthancPluginWorklistQuery* query,
-    const void*                       dicom,
-    uint32_t                          size)
-  {
-    _OrthancPluginWorklistAnswersOperation params;
-    params.answers = answers;
-    params.query = query;
-    params.dicom = dicom;
-    params.size = size;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistAddAnswer, &params);
-  }
-
-
-  /**
-   * @brief Mark the set of worklist answers as incomplete.
-   *
-   * This function marks as incomplete the set of answers
-   * corresponding to some C-Find SCP request against modality
-   * worklists. This must be used if canceling the handling of a
-   * request when too many answers are to be returned.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param answers The set of answers.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistMarkIncomplete(
-    OrthancPluginContext*          context,
-    OrthancPluginWorklistAnswers*  answers)
-  {
-    _OrthancPluginWorklistAnswersOperation params;
-    params.answers = answers;
-    params.query = NULL;
-    params.dicom = NULL;
-    params.size = 0;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistMarkIncomplete, &params);
-  }
-
-
-  typedef struct
-  {
-    const OrthancPluginWorklistQuery*  query;
-    const void*                        dicom;
-    uint32_t                           size;
-    int32_t*                           isMatch;
-    OrthancPluginMemoryBuffer*         target;
-  } _OrthancPluginWorklistQueryOperation;
-
-  /**
-   * @brief Test whether a worklist matches the query.
-   *
-   * This function checks whether one worklist (encoded as a DICOM
-   * file) matches the C-Find SCP query against modality
-   * worklists. This function must be called before adding the
-   * worklist as an answer through OrthancPluginWorklistAddAnswer().
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param query The worklist query, as received by the callback.
-   * @param dicom The worklist to answer, encoded as a DICOM file.
-   * @param size The size of the DICOM file.
-   * @return 1 if the worklist matches the query, 0 otherwise.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE int32_t  OrthancPluginWorklistIsMatch(
-    OrthancPluginContext*              context,
-    const OrthancPluginWorklistQuery*  query,
-    const void*                        dicom,
-    uint32_t                           size)
-  {
-    int32_t isMatch = 0;
-
-    _OrthancPluginWorklistQueryOperation params;
-    params.query = query;
-    params.dicom = dicom;
-    params.size = size;
-    params.isMatch = &isMatch;
-    params.target = NULL;
-
-    if (context->InvokeService(context, _OrthancPluginService_WorklistIsMatch, &params) == OrthancPluginErrorCode_Success)
-    {
-      return isMatch;
-    }
-    else
-    {
-      /* Error: Assume non-match */
-      return 0;
-    }
-  }
-
-
-  /**
-   * @brief Retrieve the worklist query as a DICOM file.
-   *
-   * This function retrieves the DICOM file that underlies a C-Find
-   * SCP query against modality worklists.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target Memory buffer where to store the DICOM file. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param query The worklist query, as received by the callback.
-   * @return 0 if success, other value if error.
-   * @ingroup Worklists
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginWorklistGetDicomQuery(
-    OrthancPluginContext*              context,
-    OrthancPluginMemoryBuffer*         target,
-    const OrthancPluginWorklistQuery*  query)
-  {
-    _OrthancPluginWorklistQueryOperation params;
-    params.query = query;
-    params.dicom = NULL;
-    params.size = 0;
-    params.isMatch = NULL;
-    params.target = target;
-
-    return context->InvokeService(context, _OrthancPluginService_WorklistGetDicomQuery, &params);
-  }
-
-
-  /**
-   * @brief Get the origin of a DICOM file.
-   *
-   * This function returns the origin of a DICOM instance that has been received by Orthanc.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param instance The instance of interest.
-   * @return The origin of the instance.
-   * @ingroup Callbacks
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginInstanceOrigin OrthancPluginGetInstanceOrigin(
-    OrthancPluginContext*       context,
-    OrthancPluginDicomInstance* instance)
-  {
-    OrthancPluginInstanceOrigin origin;
-
-    _OrthancPluginAccessDicomInstance params;
-    memset(&params, 0, sizeof(params));
-    params.resultOrigin = &origin;
-    params.instance = instance;
-
-    if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return OrthancPluginInstanceOrigin_Unknown;
-    }
-    else
-    {
-      return origin;
-    }
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginMemoryBuffer*     target;
-    const char*                    json;
-    const OrthancPluginImage*      pixelData;
-    OrthancPluginCreateDicomFlags  flags;
-  } _OrthancPluginCreateDicom;
-
-  /**
-   * @brief Create a DICOM instance from a JSON string and an image.
-   *
-   * This function takes as input a string containing a JSON file
-   * describing the content of a DICOM instance. As an output, it
-   * writes the corresponding DICOM instance to a newly allocated
-   * memory buffer. Additionally, an image to be encoded within the
-   * DICOM instance can also be provided.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer().
-   * @param json The input JSON file.
-   * @param pixelData The image. Can be NULL, if the pixel data is encoded inside the JSON with the data URI scheme.
-   * @param flags Flags governing the output.
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   * @see OrthancPluginDicomBufferToJson
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCreateDicom(
-    OrthancPluginContext*          context,
-    OrthancPluginMemoryBuffer*     target,
-    const char*                    json,
-    const OrthancPluginImage*      pixelData,
-    OrthancPluginCreateDicomFlags  flags)
-  {
-    _OrthancPluginCreateDicom params;
-    params.target = target;
-    params.json = json;
-    params.pixelData = pixelData;
-    params.flags = flags;
-
-    return context->InvokeService(context, _OrthancPluginService_CreateDicom, &params);
-  }
-
-
-  typedef struct
-  {
-    OrthancPluginDecodeImageCallback callback;
-  } _OrthancPluginDecodeImageCallback;
-
-  /**
-   * @brief Register a callback to handle the decoding of DICOM images.
-   *
-   * This function registers a custom callback to the decoding of
-   * DICOM images, replacing the built-in decoder 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 OrthancPluginRegisterDecodeImageCallback(
-    OrthancPluginContext*             context,
-    OrthancPluginDecodeImageCallback  callback)
-  {
-    _OrthancPluginDecodeImageCallback params;
-    params.callback = callback;
-
-    return context->InvokeService(context, _OrthancPluginService_RegisterDecodeImageCallback, &params);
-  }
-  
-
-
-  typedef struct
-  {
-    OrthancPluginImage**       target;
-    OrthancPluginPixelFormat   format;
-    uint32_t                   width;
-    uint32_t                   height;
-    uint32_t                   pitch;
-    void*                      buffer;
-    const void*                constBuffer;
-    uint32_t                   bufferSize;
-    uint32_t                   frameIndex;
-  } _OrthancPluginCreateImage;
-
-
-  /**
-   * @brief Create an image.
-   *
-   * This function creates an image of given size and format.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param format The format of the pixels.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @return The newly allocated image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImage(
-    OrthancPluginContext*     context,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.format = format;
-    params.width = width;
-    params.height = height;
-
-    if (context->InvokeService(context, _OrthancPluginService_CreateImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-  /**
-   * @brief Create an image pointing to a memory buffer.
-   *
-   * This function creates an image whose content points to a memory
-   * buffer managed by the plugin. Note that the buffer is directly
-   * accessed, no memory is allocated and no data is copied.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param format The format of the pixels.
-   * @param width The width of the image.
-   * @param height The height of the image.
-   * @param pitch The pitch of the image (i.e. the number of bytes
-   * between 2 successive lines of the image in the memory buffer).
-   * @param buffer The memory buffer.
-   * @return The newly allocated image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImageAccessor(
-    OrthancPluginContext*     context,
-    OrthancPluginPixelFormat  format,
-    uint32_t                  width,
-    uint32_t                  height,
-    uint32_t                  pitch,
-    void*                     buffer)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.format = format;
-    params.width = width;
-    params.height = height;
-    params.pitch = pitch;
-    params.buffer = buffer;
-
-    if (context->InvokeService(context, _OrthancPluginService_CreateImageAccessor, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  /**
-   * @brief Decode one frame from a DICOM instance.
-   *
-   * This function decodes one frame of a DICOM image that is stored
-   * in a memory buffer. This function will give the same result as
-   * OrthancPluginUncompressImage() for single-frame DICOM images.
-   *
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer Pointer to a memory buffer containing the DICOM image.
-   * @param bufferSize Size of the memory buffer containing the DICOM image.
-   * @param frameIndex The index of the frame of interest in a multi-frame image.
-   * @return The uncompressed image. It must be freed with OrthancPluginFreeImage().
-   * @ingroup Images
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginDecodeDicomImage(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               bufferSize,
-    uint32_t               frameIndex)
-  {
-    OrthancPluginImage* target = NULL;
-
-    _OrthancPluginCreateImage params;
-    memset(&params, 0, sizeof(params));
-    params.target = &target;
-    params.constBuffer = buffer;
-    params.bufferSize = bufferSize;
-    params.frameIndex = frameIndex;
-
-    if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, &params) != OrthancPluginErrorCode_Success)
-    {
-      return NULL;
-    }
-    else
-    {
-      return target;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    char**       result;
-    const void*  buffer;
-    uint32_t     size;
-  } _OrthancPluginComputeHash;
-
-  /**
-   * @brief Compute an MD5 hash.
-   *
-   * This functions computes the MD5 cryptographic hash of the given memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The source memory buffer.
-   * @param size The size in bytes of the source buffer.
-   * @return The NULL value in case of error, or a string containing the cryptographic hash.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeMd5(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               size)
-  {
-    char* result;
-
-    _OrthancPluginComputeHash params;
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-
-    if (context->InvokeService(context, _OrthancPluginService_ComputeMd5, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-  /**
-   * @brief Compute a SHA-1 hash.
-   *
-   * This functions computes the SHA-1 cryptographic hash of the given memory buffer.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param buffer The source memory buffer.
-   * @param size The size in bytes of the source buffer.
-   * @return The NULL value in case of error, or a string containing the cryptographic hash.
-   * This string must be freed by OrthancPluginFreeString().
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeSha1(
-    OrthancPluginContext*  context,
-    const void*            buffer,
-    uint32_t               size)
-  {
-    char* result;
-
-    _OrthancPluginComputeHash params;
-    params.result = &result;
-    params.buffer = buffer;
-    params.size = size;
-
-    if (context->InvokeService(context, _OrthancPluginService_ComputeSha1, &params) != OrthancPluginErrorCode_Success)
-    {
-      /* Error */
-      return NULL;
-    }
-    else
-    {
-      return result;
-    }
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginDictionaryEntry* target;
-    const char*                   name;
-  } _OrthancPluginLookupDictionary;
-
-  /**
-   * @brief Get information about the given DICOM tag.
-   *
-   * This functions makes a lookup in the dictionary of DICOM tags
-   * that are known to Orthanc, and returns information about this
-   * tag. The tag can be specified using its human-readable name
-   * (e.g. "PatientName") or a set of two hexadecimal numbers
-   * (e.g. "0010-0020").
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target Where to store the information about the tag.
-   * @param name The name of the DICOM tag.
-   * @return 0 if success, other value if error.
-   * @ingroup Toolbox
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginLookupDictionary(
-    OrthancPluginContext*          context,
-    OrthancPluginDictionaryEntry*  target,
-    const char*                    name)
-  {
-    _OrthancPluginLookupDictionary params;
-    params.target = target;
-    params.name = name;
-    return context->InvokeService(context, _OrthancPluginService_LookupDictionary, &params);
-  }
-
-
-
-  typedef struct
-  {
-    OrthancPluginRestOutput* output;
-    const char*              answer;
-    uint32_t                 answerSize;
-    uint32_t                 headersCount;
-    const char* const*       headersKeys;
-    const char* const*       headersValues;
-  } _OrthancPluginSendMultipartItem2;
-
-  /**
-   * @brief Send an item as a part of some HTTP multipart answer, with custom headers.
-   *
-   * This function sends an item as a part of some HTTP multipart
-   * answer that was initiated by OrthancPluginStartMultipartAnswer(). In addition to
-   * OrthancPluginSendMultipartItem(), this function will set HTTP header associated
-   * with the item.
-   * 
-   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param output The HTTP connection to the client application.
-   * @param answer Pointer to the memory buffer containing the item.
-   * @param answerSize Number of bytes of the item.
-   * @param headersCount The number of HTTP headers.
-   * @param headersKeys Array containing the keys of the HTTP headers.
-   * @param headersValues Array containing the values of the HTTP headers.
-   * @return 0 if success, or the error code if failure (this notably happens
-   * if the connection is closed by the client).
-   * @see OrthancPluginSendMultipartItem()
-   * @ingroup REST
-   **/
-  ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem2(
-    OrthancPluginContext*    context,
-    OrthancPluginRestOutput* output,
-    const char*              answer,
-    uint32_t                 answerSize,
-    uint32_t                 headersCount,
-    const char* const*       headersKeys,
-    const char* const*       headersValues)
-  {
-    _OrthancPluginSendMultipartItem2 params;
-    params.output = output;
-    params.answer = answer;
-    params.answerSize = answerSize;
-    params.headersCount = headersCount;
-    params.headersKeys = headersKeys;
-    params.headersValues = headersValues;    
-
-    return context->InvokeService(context, _OrthancPluginService_SendMultipartItem2, &params);
-  }
-
-
-#ifdef  __cplusplus
-}
-#endif
-
-
-/** @} */
-