Mercurial > hg > orthanc-education
view Sources/EducationToolbox.cpp @ 104:e81b5ab529fa default tip
set ORTHANC_FRAMEWORK_DEFAULT_VERSION to 1.13.0
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Wed, 19 Aug 2026 14:56:39 +0200 |
| parents | 07e6100a3ea3 |
| children |
line wrap: on
line source
/** * SPDX-FileCopyrightText: 2024-2026 Sebastien Jodogne, EPL UCLouvain, Belgium * SPDX-License-Identifier: AGPL-3.0-or-later */ /** * Orthanc for Education * Copyright (C) 2024-2026 Sebastien Jodogne, EPL 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 "EducationToolbox.h" #include "HttpToolbox.h" #include <OrthancException.h> #include <SerializationToolbox.h> #include <Toolbox.h> #include <cassert> static std::string FormatGetArgument(const std::string& key, const std::string& value) { assert(!key.empty()); if (value.empty()) { return ""; } else { /** * The following implementation is correct if value is an UTF-8 * string: "When a new URI scheme defines a component that * represents textual data consisting of characters from the * Universal Character Set [UCS], the data should first be encoded * as octets according to the UTF-8 character encoding [STD63]; * then only those octets that do not correspond to characters in * the unreserved set should be percent- encoded." * https://www.rfc-editor.org/rfc/rfc3986 **/ std::string tmp; Orthanc::Toolbox::UriEncode(tmp, value); return "&" + key + "=" + tmp; } } static std::string GenerateStudyViewerUrl(const std::string& projectId, ViewerType viewer, const std::string& studyId, const std::string& studyInstanceUid, const std::string& title) { switch (viewer) { case ViewerType_StoneWebViewer: return "stone-webviewer/index.html?study=" + studyInstanceUid; case ViewerType_VolView: return "volview/index.html?names=[archive.zip]&urls=[../studies/" + studyId + "/archive]"; case ViewerType_OHIF_Basic: return "ohif/viewer?StudyInstanceUIDs=" + studyInstanceUid; case ViewerType_OHIF_VolumeRendering: return "ohif/viewer?hangingprotocolId=mprAnd3DVolumeViewport&StudyInstanceUIDs=" + studyInstanceUid; case ViewerType_OHIF_TumorVolume: return "ohif/tmtv?StudyInstanceUIDs=" + studyInstanceUid; case ViewerType_OHIF_Segmentation: return "ohif/segmentation?StudyInstanceUIDs=" + studyInstanceUid; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } static std::string GenerateSeriesViewerUrl(const std::string& projectId, ViewerType viewer, const std::string& seriesId, const std::string& studyInstanceUid, const std::string& seriesInstanceUid, const std::string& title) { switch (viewer) { case ViewerType_StoneWebViewer: return "stone-webviewer/index.html?study=" + studyInstanceUid + "&series=" + seriesInstanceUid; case ViewerType_WholeSlideImaging: return ("wsi/app/viewer.html?series=" + seriesId + FormatGetArgument("project", projectId) + FormatGetArgument("title", title)); case ViewerType_VolView: return "volview/index.html?names=[archive.zip]&urls=[../series/" + seriesId + "/archive]"; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } static std::string GenerateInstanceViewerUrl(const std::string& projectId, ViewerType viewer, const std::string& instanceId, const std::string& studyInstanceUid, const std::string& seriesInstanceUid, const std::string& sopInstanceUid, const std::string& title) { switch (viewer) { case ViewerType_WholeSlideImaging: return ("wsi/app/viewer.html?instance=" + instanceId + FormatGetArgument("project", projectId) + FormatGetArgument("title", title)); default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } static const char* const KEY_LEVEL = "level"; static const char* const KEY_PROJECT = "project"; static const char* const KEY_RESOURCE_ID = "resource-id"; static const char* const KEY_SERIES_INSTANCE_UID = "series-instance-uid"; static const char* const KEY_SOP_INSTANCE_UID = "sop-instance-uid"; static const char* const KEY_STUDY_INSTANCE_UID = "study-instance-uid"; static const char* const KEY_TITLE = "title"; namespace EducationToolbox { std::string GenerateViewerUrlForDeepLinking(ViewerType viewer, const std::map<std::string, std::string>& resource) { const std::string projectId = HttpToolbox::ReadMandatoryString(resource, KEY_PROJECT); if (projectId.empty()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } const std::string levelString = HttpToolbox::ReadMandatoryString(resource, KEY_LEVEL); const Orthanc::ResourceType level = Orthanc::StringToResourceType(levelString.c_str()); switch (level) { case Orthanc::ResourceType_Study: return GenerateStudyViewerUrl(projectId, viewer, HttpToolbox::ReadMandatoryString(resource, KEY_RESOURCE_ID), HttpToolbox::ReadMandatoryString(resource, KEY_STUDY_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_TITLE)); case Orthanc::ResourceType_Series: return GenerateSeriesViewerUrl(projectId, viewer, HttpToolbox::ReadMandatoryString(resource, KEY_RESOURCE_ID), HttpToolbox::ReadMandatoryString(resource, KEY_STUDY_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_SERIES_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_TITLE)); case Orthanc::ResourceType_Instance: return GenerateInstanceViewerUrl(projectId, viewer, HttpToolbox::ReadMandatoryString(resource, KEY_RESOURCE_ID), HttpToolbox::ReadMandatoryString(resource, KEY_STUDY_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_SERIES_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_SOP_INSTANCE_UID), HttpToolbox::ReadMandatoryString(resource, KEY_TITLE)); default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } std::string GenerateViewerUrlGeneric(const std::string& projectId, ViewerType viewer, const Json::Value& resource) { const std::string levelString = Orthanc::SerializationToolbox::ReadString(resource, KEY_LEVEL); const Orthanc::ResourceType level = Orthanc::StringToResourceType(levelString.c_str()); switch (level) { case Orthanc::ResourceType_Study: return GenerateStudyViewerUrl(projectId, viewer, Orthanc::SerializationToolbox::ReadString(resource, KEY_RESOURCE_ID), Orthanc::SerializationToolbox::ReadString(resource, KEY_STUDY_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_TITLE)); case Orthanc::ResourceType_Series: return GenerateSeriesViewerUrl(projectId, viewer, Orthanc::SerializationToolbox::ReadString(resource, KEY_RESOURCE_ID), Orthanc::SerializationToolbox::ReadString(resource, KEY_STUDY_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_SERIES_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_TITLE)); case Orthanc::ResourceType_Instance: return GenerateInstanceViewerUrl(projectId, viewer, Orthanc::SerializationToolbox::ReadString(resource, KEY_RESOURCE_ID), Orthanc::SerializationToolbox::ReadString(resource, KEY_STUDY_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_SERIES_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_SOP_INSTANCE_UID), Orthanc::SerializationToolbox::ReadString(resource, KEY_TITLE)); default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } } }
