view Sources/HttpAuthenticationCallback.cpp @ 334:ff7d48d8d51a default tip

added Resources/Samples/SampleHttpAuthentication.py
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Aug 2026 16:32:47 +0200
parents 35d09327ee25
children
line wrap: on
line source

/**
 * SPDX-FileCopyrightText: 2020-2023 Osimis S.A., 2024-2026 Orthanc Team SRL, 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

/**
 * Python plugin for Orthanc
 * Copyright (C) 2020-2023 Osimis S.A., Belgium
 * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
 * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero 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
 * Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 **/


#include "HttpAuthenticationCallback.h"

#include "PythonHeaderWrapper.h"

#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
#include "ICallbackRegistration.h"
#include "PythonString.h"


#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 9)

static PyObject*   httpAuthenticationCallback_ = NULL;


static OrthancPluginErrorCode HttpAuthenticationCallback(
  OrthancPluginHttpAuthenticationStatus*  status,         /* out */
  OrthancPluginMemoryBuffer*              customPayload,  /* out */
  OrthancPluginMemoryBuffer*              redirection,    /* out */
  const char*                             uri,
  const char*                             ip,
  uint32_t                                headersCount,
  const char* const*                      headersKeys,
  const char* const*                      headersValues,
  uint32_t                                getCount,
  const char* const*                      getKeys,
  const char* const*                      getValues)
{
  try
  {
    PythonLock lock;

    PythonObject args(lock, PyTuple_New(4));

    {
      PythonString s(lock, uri);
      PyTuple_SetItem(args.GetPyObject(), 0, s.Release());
    }

    {
      PythonString s(lock, ip);
      PyTuple_SetItem(args.GetPyObject(), 1, s.Release());
    }

    {
      PythonObject headers(lock, PyDict_New());

      for (uint32_t i = 0; i < headersCount; i++)
      {
        PythonString value(lock, headersValues[i]);
        PyDict_SetItemString(headers.GetPyObject(), headersKeys[i], value.GetPyObject());
      }

      PyTuple_SetItem(args.GetPyObject(), 2, headers.Release());
    }

    {
      PythonObject getArguments(lock, PyDict_New());

      for (uint32_t i = 0; i < getCount; i++)
      {
        PythonString value(lock, getValues[i]);
        PyDict_SetItemString(getArguments.GetPyObject(), getKeys[i], value.GetPyObject());
      }

      PyTuple_SetItem(args.GetPyObject(), 3, getArguments.Release());
    }

    PythonObject result(lock, PyObject_CallObject(httpAuthenticationCallback_, args.GetPyObject()));

    OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python HttpAuthentication() callback");

    if (code != OrthancPluginErrorCode_Success)
    {
      return code;
    }
    else
    {
      *status = static_cast<OrthancPluginHttpAuthenticationStatus>(result.GetEnumerationValueFromTuple(0));

      if (result.GetTupleItem(1) == Py_None)
      {
        redirection->size = 0;
        redirection->data = NULL;
      }
      else
      {
        result.GetMemoryBufferFromTuple(customPayload, 1);
      }

      if (result.GetTupleItem(2) == Py_None)
      {
        redirection->size = 0;
        redirection->data = NULL;
      }
      else
      {
        std::string s;
        result.GetUtf8StringFromTuple(s, 2);

        OrthancPlugins::MemoryBuffer buffer;
        buffer.Assign(s);
        *redirection = buffer.Release();
      }

      return OrthancPluginErrorCode_Success;
    }
  }
  catch (OrthancPlugins::PluginException& e)
  {
    return e.GetErrorCode();
  }
}


PyObject* RegisterHttpAuthenticationCallback(PyObject* module, PyObject* args)
{
  // The GIL is locked at this point (no need to create "PythonLock")

  class Registration : public ICallbackRegistration
  {
  public:
    virtual void Register() ORTHANC_OVERRIDE
    {
      OrthancPluginRegisterHttpAuthentication(
        OrthancPlugins::GetGlobalContext(), HttpAuthenticationCallback);
    }
  };

  Registration registration;
  return ICallbackRegistration::Apply(
    registration, args, httpAuthenticationCallback_, "Python received instance callback");
}


void FinalizeHttpAuthenticationCallback()
{
  ICallbackRegistration::Unregister(httpAuthenticationCallback_);
}

#else

#warning OrthancPluginRegisterHttpAuthenticationCallback() is not supported

PyObject* RegisterHttpAuthenticationCallback(PyObject* module, PyObject* args)
{
  PyErr_SetString(PyExc_RuntimeError, "The version of your Orthanc SDK doesn't provide OrthancPluginRegisterHttpAuthenticationCallback()");
  return NULL;
}

void FinalizeHttpAuthenticationCallback()
{
}

#endif