New upstream version 0.5+dfsg
jodogne-guest
6 years ago
0 | 0 | repo: d5f45924411123cfd02d035fd50b8e37536eadef |
1 | node: f58f8d749b95d85a792e786a0256d0cc2278cc4d | |
2 | branch: OrthancDicomWeb-0.4 | |
1 | node: b5f71018159133105d5cc1eb60d852a385bab998 | |
2 | branch: OrthancDicomWeb-0.5 | |
3 | 3 | latesttag: null |
4 | latesttagdistance: 179 | |
5 | changessincelatesttag: 189 | |
4 | latesttagdistance: 210 | |
5 | changessincelatesttag: 221 |
13 | 13 | 4000 Liege |
14 | 14 | Belgium |
15 | 15 | |
16 | * Osimis <info@osimis.io> | |
16 | * Osimis S.A. <info@osimis.io> | |
17 | 17 | Rue des Chasseurs Ardennais 3 |
18 | 18 | 4031 Liege |
19 | 19 | Belgium |
0 | 0 | # Orthanc - A Lightweight, RESTful DICOM Store |
1 | 1 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
2 | 2 | # Department, University Hospital of Liege, Belgium |
3 | # Copyright (C) 2017 Osimis, Belgium | |
3 | # Copyright (C) 2017-2018 Osimis S.A., Belgium | |
4 | 4 | # |
5 | 5 | # This program is free software: you can redistribute it and/or |
6 | 6 | # modify it under the terms of the GNU Affero General Public License |
20 | 20 | |
21 | 21 | project(OrthancDicomWeb) |
22 | 22 | |
23 | set(ORTHANC_DICOM_WEB_VERSION "0.4") | |
23 | set(ORTHANC_DICOM_WEB_VERSION "0.5") | |
24 | ||
25 | if (ORTHANC_DICOM_WEB_VERSION STREQUAL "mainline") | |
26 | set(ORTHANC_FRAMEWORK_VERSION "mainline") | |
27 | set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") | |
28 | else() | |
29 | set(ORTHANC_FRAMEWORK_VERSION "1.3.2") | |
30 | set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") | |
31 | endif() | |
24 | 32 | |
25 | 33 | |
26 | 34 | # Parameters of the build |
27 | 35 | set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") |
28 | 36 | set(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages") |
37 | set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") | |
38 | set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") | |
39 | set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") | |
29 | 40 | |
30 | 41 | # Advanced parameters to fine-tune linking against system libraries |
31 | set(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost") | |
32 | 42 | set(USE_SYSTEM_GDCM ON CACHE BOOL "Use the system version of Grassroot DICOM (GDCM)") |
33 | set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test") | |
34 | set(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp") | |
35 | set(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of zlib") | |
36 | set(USE_SYSTEM_PUGIXML ON CACHE BOOL "Use the system version of Pugixml") | |
37 | 43 | set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK") |
38 | 44 | |
39 | # Distribution-specific settings | |
40 | set(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") | |
41 | mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE) | |
42 | 45 | |
43 | set(USE_PUGIXML ON) | |
44 | set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/Orthanc) | |
45 | set(ORTHANC_DISABLE_PATCH ON) # No need for the "patch" command-line tool | |
46 | include(CheckIncludeFiles) | |
47 | include(CheckIncludeFileCXX) | |
48 | include(CheckLibraryExists) | |
49 | include(FindPythonInterp) | |
50 | include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake) | |
51 | include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake) | |
52 | 46 | |
53 | include(${ORTHANC_ROOT}/Resources/CMake/BoostConfiguration.cmake) | |
54 | include(${ORTHANC_ROOT}/Resources/CMake/GoogleTestConfiguration.cmake) | |
55 | include(${ORTHANC_ROOT}/Resources/CMake/JsonCppConfiguration.cmake) | |
56 | include(${ORTHANC_ROOT}/Resources/CMake/ZlibConfiguration.cmake) | |
57 | include(${ORTHANC_ROOT}/Resources/CMake/PugixmlConfiguration.cmake) | |
47 | # Download and setup the Orthanc framework | |
48 | include(${CMAKE_SOURCE_DIR}/Resources/Orthanc/DownloadOrthancFramework.cmake) | |
49 | ||
50 | set(ORTHANC_FRAMEWORK_PLUGIN ON) | |
51 | include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) | |
52 | ||
53 | set(ENABLE_LOCALE ON) # Enable support for locales (notably in Boost) | |
54 | set(ENABLE_GOOGLE_TEST ON) | |
55 | set(ENABLE_PUGIXML ON) | |
56 | set(USE_BOOST_ICONV ON) | |
57 | ||
58 | include(${ORTHANC_ROOT}/Resources/CMake/OrthancFrameworkConfiguration.cmake) | |
59 | include_directories(${ORTHANC_ROOT}) | |
60 | ||
58 | 61 | |
59 | 62 | include(${CMAKE_SOURCE_DIR}/Resources/CMake/GdcmConfiguration.cmake) |
60 | 63 | |
61 | 64 | |
62 | 65 | if (STATIC_BUILD OR NOT USE_SYSTEM_ORTHANC_SDK) |
63 | include_directories(${ORTHANC_ROOT}/Sdk-1.1.0) | |
66 | include_directories(${CMAKE_SOURCE_DIR}/Resources/Orthanc/Sdk-1.1.0) | |
64 | 67 | else () |
65 | 68 | CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H) |
66 | 69 | if (NOT HAVE_ORTHANC_H) |
99 | 102 | endif() |
100 | 103 | |
101 | 104 | |
105 | include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h" | |
106 | ||
102 | 107 | add_definitions( |
103 | -DORTHANC_ENABLE_MD5=0 | |
104 | -DORTHANC_ENABLE_BASE64=0 | |
105 | -DORTHANC_ENABLE_LOGGING=0 | |
106 | -DORTHANC_SANDBOXED=0 | |
107 | 108 | -DHAS_ORTHANC_EXCEPTION=1 |
108 | 109 | ) |
109 | 110 | |
110 | include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h" | |
111 | ||
112 | 111 | set(CORE_SOURCES |
113 | ${BOOST_SOURCES} | |
114 | ${JSONCPP_SOURCES} | |
115 | ${ZLIB_SOURCES} | |
116 | ${PUGIXML_SOURCES} | |
117 | ||
118 | ${ORTHANC_ROOT}/Core/ChunkedBuffer.cpp | |
119 | ${ORTHANC_ROOT}/Core/Enumerations.cpp | |
120 | ${ORTHANC_ROOT}/Core/Toolbox.cpp | |
121 | ${ORTHANC_ROOT}/Core/SystemToolbox.cpp | |
122 | ${ORTHANC_ROOT}/Core/WebServiceParameters.cpp | |
123 | ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp | |
124 | ||
125 | 112 | Plugin/Configuration.cpp |
126 | 113 | Plugin/Dicom.cpp |
127 | 114 | Plugin/DicomResults.cpp |
115 | ||
116 | ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp | |
117 | ${ORTHANC_CORE_SOURCES} | |
128 | 118 | ) |
129 | 119 | |
130 | 120 | add_library(OrthancDicomWeb SHARED ${CORE_SOURCES} |
158 | 148 | |
159 | 149 | add_executable(UnitTests |
160 | 150 | ${CORE_SOURCES} |
161 | ${GTEST_SOURCES} | |
151 | ${GOOGLE_TEST_SOURCES} | |
162 | 152 | ${CMAKE_SOURCE_DIR}/Plugin/DicomWebServers.cpp |
163 | 153 | UnitTestsSources/UnitTestsMain.cpp |
164 | 154 | ) |
165 | 155 | |
166 | target_link_libraries(UnitTests ${GDCM_LIBRARIES}) | |
156 | target_link_libraries(UnitTests | |
157 | ${GDCM_LIBRARIES} | |
158 | ${GOOGLE_TEST_LIBRARIES} | |
159 | ) | |
167 | 160 | |
168 | 161 | if (STATIC_BUILD OR NOT USE_SYSTEM_GDCM) |
169 | 162 | add_dependencies(OrthancDicomWeb GDCM) |
0 | 0 | Pending changes in the mainline |
1 | 1 | =============================== |
2 | ||
3 | ||
4 | Version 0.5 (2018-08-19) | |
5 | ======================== | |
6 | ||
7 | * New option: "QidoCaseSensitive" to make queries to QIDO-RS server case insensitive | |
8 | * Defaults to JSON answers instead of XML | |
9 | * Use of "application/dicom+json" MIME type instead of "application/json" | |
10 | * Added "?expand" argument to "/servers" route | |
11 | * Fix generation of numeric tags part of sequences for ".../metadata" routes | |
12 | * Support for OpenBSD | |
13 | * Support for Linux Standard Base | |
14 | * Upgrade to GDCM 2.8.4 for static builds | |
15 | * Resort to Orthanc framework | |
2 | 16 | |
3 | 17 | |
4 | 18 | Version 0.4 (2017-07-19) |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "PrecompiledHeaders.h" | |
34 | #include "ChunkedBuffer.h" | |
35 | ||
36 | #include <cassert> | |
37 | #include <string.h> | |
38 | ||
39 | ||
40 | namespace Orthanc | |
41 | { | |
42 | void ChunkedBuffer::Clear() | |
43 | { | |
44 | numBytes_ = 0; | |
45 | ||
46 | for (Chunks::iterator it = chunks_.begin(); | |
47 | it != chunks_.end(); ++it) | |
48 | { | |
49 | delete *it; | |
50 | } | |
51 | } | |
52 | ||
53 | ||
54 | void ChunkedBuffer::AddChunk(const void* chunkData, | |
55 | size_t chunkSize) | |
56 | { | |
57 | if (chunkSize == 0) | |
58 | { | |
59 | return; | |
60 | } | |
61 | else | |
62 | { | |
63 | assert(chunkData != NULL); | |
64 | chunks_.push_back(new std::string(reinterpret_cast<const char*>(chunkData), chunkSize)); | |
65 | numBytes_ += chunkSize; | |
66 | } | |
67 | } | |
68 | ||
69 | ||
70 | void ChunkedBuffer::AddChunk(const std::string& chunk) | |
71 | { | |
72 | if (chunk.size() > 0) | |
73 | { | |
74 | AddChunk(&chunk[0], chunk.size()); | |
75 | } | |
76 | } | |
77 | ||
78 | ||
79 | void ChunkedBuffer::Flatten(std::string& result) | |
80 | { | |
81 | result.resize(numBytes_); | |
82 | ||
83 | size_t pos = 0; | |
84 | for (Chunks::iterator it = chunks_.begin(); | |
85 | it != chunks_.end(); ++it) | |
86 | { | |
87 | assert(*it != NULL); | |
88 | ||
89 | size_t s = (*it)->size(); | |
90 | if (s != 0) | |
91 | { | |
92 | memcpy(&result[pos], (*it)->c_str(), s); | |
93 | pos += s; | |
94 | } | |
95 | ||
96 | delete *it; | |
97 | } | |
98 | ||
99 | chunks_.clear(); | |
100 | numBytes_ = 0; | |
101 | } | |
102 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include <list> | |
36 | #include <string> | |
37 | ||
38 | namespace Orthanc | |
39 | { | |
40 | class ChunkedBuffer | |
41 | { | |
42 | private: | |
43 | typedef std::list<std::string*> Chunks; | |
44 | size_t numBytes_; | |
45 | Chunks chunks_; | |
46 | ||
47 | void Clear(); | |
48 | ||
49 | public: | |
50 | ChunkedBuffer() : numBytes_(0) | |
51 | { | |
52 | } | |
53 | ||
54 | ~ChunkedBuffer() | |
55 | { | |
56 | Clear(); | |
57 | } | |
58 | ||
59 | size_t GetNumBytes() const | |
60 | { | |
61 | return numBytes_; | |
62 | } | |
63 | ||
64 | void AddChunk(const void* chunkData, | |
65 | size_t chunkSize); | |
66 | ||
67 | void AddChunk(const std::string& chunk); | |
68 | ||
69 | void Flatten(std::string& result); | |
70 | }; | |
71 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "PrecompiledHeaders.h" | |
34 | #include "Enumerations.h" | |
35 | ||
36 | #include "OrthancException.h" | |
37 | #include "Toolbox.h" | |
38 | #include "Logging.h" | |
39 | ||
40 | #include <string.h> | |
41 | #include <cassert> | |
42 | ||
43 | namespace Orthanc | |
44 | { | |
45 | // This function is autogenerated by the script | |
46 | // "Resources/GenerateErrorCodes.py" | |
47 | const char* EnumerationToString(ErrorCode error) | |
48 | { | |
49 | switch (error) | |
50 | { | |
51 | case ErrorCode_InternalError: | |
52 | return "Internal error"; | |
53 | ||
54 | case ErrorCode_Success: | |
55 | return "Success"; | |
56 | ||
57 | case ErrorCode_Plugin: | |
58 | return "Error encountered within the plugin engine"; | |
59 | ||
60 | case ErrorCode_NotImplemented: | |
61 | return "Not implemented yet"; | |
62 | ||
63 | case ErrorCode_ParameterOutOfRange: | |
64 | return "Parameter out of range"; | |
65 | ||
66 | case ErrorCode_NotEnoughMemory: | |
67 | return "The server hosting Orthanc is running out of memory"; | |
68 | ||
69 | case ErrorCode_BadParameterType: | |
70 | return "Bad type for a parameter"; | |
71 | ||
72 | case ErrorCode_BadSequenceOfCalls: | |
73 | return "Bad sequence of calls"; | |
74 | ||
75 | case ErrorCode_InexistentItem: | |
76 | return "Accessing an inexistent item"; | |
77 | ||
78 | case ErrorCode_BadRequest: | |
79 | return "Bad request"; | |
80 | ||
81 | case ErrorCode_NetworkProtocol: | |
82 | return "Error in the network protocol"; | |
83 | ||
84 | case ErrorCode_SystemCommand: | |
85 | return "Error while calling a system command"; | |
86 | ||
87 | case ErrorCode_Database: | |
88 | return "Error with the database engine"; | |
89 | ||
90 | case ErrorCode_UriSyntax: | |
91 | return "Badly formatted URI"; | |
92 | ||
93 | case ErrorCode_InexistentFile: | |
94 | return "Inexistent file"; | |
95 | ||
96 | case ErrorCode_CannotWriteFile: | |
97 | return "Cannot write to file"; | |
98 | ||
99 | case ErrorCode_BadFileFormat: | |
100 | return "Bad file format"; | |
101 | ||
102 | case ErrorCode_Timeout: | |
103 | return "Timeout"; | |
104 | ||
105 | case ErrorCode_UnknownResource: | |
106 | return "Unknown resource"; | |
107 | ||
108 | case ErrorCode_IncompatibleDatabaseVersion: | |
109 | return "Incompatible version of the database"; | |
110 | ||
111 | case ErrorCode_FullStorage: | |
112 | return "The file storage is full"; | |
113 | ||
114 | case ErrorCode_CorruptedFile: | |
115 | return "Corrupted file (e.g. inconsistent MD5 hash)"; | |
116 | ||
117 | case ErrorCode_InexistentTag: | |
118 | return "Inexistent tag"; | |
119 | ||
120 | case ErrorCode_ReadOnly: | |
121 | return "Cannot modify a read-only data structure"; | |
122 | ||
123 | case ErrorCode_IncompatibleImageFormat: | |
124 | return "Incompatible format of the images"; | |
125 | ||
126 | case ErrorCode_IncompatibleImageSize: | |
127 | return "Incompatible size of the images"; | |
128 | ||
129 | case ErrorCode_SharedLibrary: | |
130 | return "Error while using a shared library (plugin)"; | |
131 | ||
132 | case ErrorCode_UnknownPluginService: | |
133 | return "Plugin invoking an unknown service"; | |
134 | ||
135 | case ErrorCode_UnknownDicomTag: | |
136 | return "Unknown DICOM tag"; | |
137 | ||
138 | case ErrorCode_BadJson: | |
139 | return "Cannot parse a JSON document"; | |
140 | ||
141 | case ErrorCode_Unauthorized: | |
142 | return "Bad credentials were provided to an HTTP request"; | |
143 | ||
144 | case ErrorCode_BadFont: | |
145 | return "Badly formatted font file"; | |
146 | ||
147 | case ErrorCode_DatabasePlugin: | |
148 | return "The plugin implementing a custom database back-end does not fulfill the proper interface"; | |
149 | ||
150 | case ErrorCode_StorageAreaPlugin: | |
151 | return "Error in the plugin implementing a custom storage area"; | |
152 | ||
153 | case ErrorCode_EmptyRequest: | |
154 | return "The request is empty"; | |
155 | ||
156 | case ErrorCode_NotAcceptable: | |
157 | return "Cannot send a response which is acceptable according to the Accept HTTP header"; | |
158 | ||
159 | case ErrorCode_NullPointer: | |
160 | return "Cannot handle a NULL pointer"; | |
161 | ||
162 | case ErrorCode_SQLiteNotOpened: | |
163 | return "SQLite: The database is not opened"; | |
164 | ||
165 | case ErrorCode_SQLiteAlreadyOpened: | |
166 | return "SQLite: Connection is already open"; | |
167 | ||
168 | case ErrorCode_SQLiteCannotOpen: | |
169 | return "SQLite: Unable to open the database"; | |
170 | ||
171 | case ErrorCode_SQLiteStatementAlreadyUsed: | |
172 | return "SQLite: This cached statement is already being referred to"; | |
173 | ||
174 | case ErrorCode_SQLiteExecute: | |
175 | return "SQLite: Cannot execute a command"; | |
176 | ||
177 | case ErrorCode_SQLiteRollbackWithoutTransaction: | |
178 | return "SQLite: Rolling back a nonexistent transaction (have you called Begin()?)"; | |
179 | ||
180 | case ErrorCode_SQLiteCommitWithoutTransaction: | |
181 | return "SQLite: Committing a nonexistent transaction"; | |
182 | ||
183 | case ErrorCode_SQLiteRegisterFunction: | |
184 | return "SQLite: Unable to register a function"; | |
185 | ||
186 | case ErrorCode_SQLiteFlush: | |
187 | return "SQLite: Unable to flush the database"; | |
188 | ||
189 | case ErrorCode_SQLiteCannotRun: | |
190 | return "SQLite: Cannot run a cached statement"; | |
191 | ||
192 | case ErrorCode_SQLiteCannotStep: | |
193 | return "SQLite: Cannot step over a cached statement"; | |
194 | ||
195 | case ErrorCode_SQLiteBindOutOfRange: | |
196 | return "SQLite: Bing a value while out of range (serious error)"; | |
197 | ||
198 | case ErrorCode_SQLitePrepareStatement: | |
199 | return "SQLite: Cannot prepare a cached statement"; | |
200 | ||
201 | case ErrorCode_SQLiteTransactionAlreadyStarted: | |
202 | return "SQLite: Beginning the same transaction twice"; | |
203 | ||
204 | case ErrorCode_SQLiteTransactionCommit: | |
205 | return "SQLite: Failure when committing the transaction"; | |
206 | ||
207 | case ErrorCode_SQLiteTransactionBegin: | |
208 | return "SQLite: Cannot start a transaction"; | |
209 | ||
210 | case ErrorCode_DirectoryOverFile: | |
211 | return "The directory to be created is already occupied by a regular file"; | |
212 | ||
213 | case ErrorCode_FileStorageCannotWrite: | |
214 | return "Unable to create a subdirectory or a file in the file storage"; | |
215 | ||
216 | case ErrorCode_DirectoryExpected: | |
217 | return "The specified path does not point to a directory"; | |
218 | ||
219 | case ErrorCode_HttpPortInUse: | |
220 | return "The TCP port of the HTTP server is privileged or already in use"; | |
221 | ||
222 | case ErrorCode_DicomPortInUse: | |
223 | return "The TCP port of the DICOM server is privileged or already in use"; | |
224 | ||
225 | case ErrorCode_BadHttpStatusInRest: | |
226 | return "This HTTP status is not allowed in a REST API"; | |
227 | ||
228 | case ErrorCode_RegularFileExpected: | |
229 | return "The specified path does not point to a regular file"; | |
230 | ||
231 | case ErrorCode_PathToExecutable: | |
232 | return "Unable to get the path to the executable"; | |
233 | ||
234 | case ErrorCode_MakeDirectory: | |
235 | return "Cannot create a directory"; | |
236 | ||
237 | case ErrorCode_BadApplicationEntityTitle: | |
238 | return "An application entity title (AET) cannot be empty or be longer than 16 characters"; | |
239 | ||
240 | case ErrorCode_NoCFindHandler: | |
241 | return "No request handler factory for DICOM C-FIND SCP"; | |
242 | ||
243 | case ErrorCode_NoCMoveHandler: | |
244 | return "No request handler factory for DICOM C-MOVE SCP"; | |
245 | ||
246 | case ErrorCode_NoCStoreHandler: | |
247 | return "No request handler factory for DICOM C-STORE SCP"; | |
248 | ||
249 | case ErrorCode_NoApplicationEntityFilter: | |
250 | return "No application entity filter"; | |
251 | ||
252 | case ErrorCode_NoSopClassOrInstance: | |
253 | return "DicomUserConnection: Unable to find the SOP class and instance"; | |
254 | ||
255 | case ErrorCode_NoPresentationContext: | |
256 | return "DicomUserConnection: No acceptable presentation context for modality"; | |
257 | ||
258 | case ErrorCode_DicomFindUnavailable: | |
259 | return "DicomUserConnection: The C-FIND command is not supported by the remote SCP"; | |
260 | ||
261 | case ErrorCode_DicomMoveUnavailable: | |
262 | return "DicomUserConnection: The C-MOVE command is not supported by the remote SCP"; | |
263 | ||
264 | case ErrorCode_CannotStoreInstance: | |
265 | return "Cannot store an instance"; | |
266 | ||
267 | case ErrorCode_CreateDicomNotString: | |
268 | return "Only string values are supported when creating DICOM instances"; | |
269 | ||
270 | case ErrorCode_CreateDicomOverrideTag: | |
271 | return "Trying to override a value inherited from a parent module"; | |
272 | ||
273 | case ErrorCode_CreateDicomUseContent: | |
274 | return "Use \"Content\" to inject an image into a new DICOM instance"; | |
275 | ||
276 | case ErrorCode_CreateDicomNoPayload: | |
277 | return "No payload is present for one instance in the series"; | |
278 | ||
279 | case ErrorCode_CreateDicomUseDataUriScheme: | |
280 | return "The payload of the DICOM instance must be specified according to Data URI scheme"; | |
281 | ||
282 | case ErrorCode_CreateDicomBadParent: | |
283 | return "Trying to attach a new DICOM instance to an inexistent resource"; | |
284 | ||
285 | case ErrorCode_CreateDicomParentIsInstance: | |
286 | return "Trying to attach a new DICOM instance to an instance (must be a series, study or patient)"; | |
287 | ||
288 | case ErrorCode_CreateDicomParentEncoding: | |
289 | return "Unable to get the encoding of the parent resource"; | |
290 | ||
291 | case ErrorCode_UnknownModality: | |
292 | return "Unknown modality"; | |
293 | ||
294 | case ErrorCode_BadJobOrdering: | |
295 | return "Bad ordering of filters in a job"; | |
296 | ||
297 | case ErrorCode_JsonToLuaTable: | |
298 | return "Cannot convert the given JSON object to a Lua table"; | |
299 | ||
300 | case ErrorCode_CannotCreateLua: | |
301 | return "Cannot create the Lua context"; | |
302 | ||
303 | case ErrorCode_CannotExecuteLua: | |
304 | return "Cannot execute a Lua command"; | |
305 | ||
306 | case ErrorCode_LuaAlreadyExecuted: | |
307 | return "Arguments cannot be pushed after the Lua function is executed"; | |
308 | ||
309 | case ErrorCode_LuaBadOutput: | |
310 | return "The Lua function does not give the expected number of outputs"; | |
311 | ||
312 | case ErrorCode_NotLuaPredicate: | |
313 | return "The Lua function is not a predicate (only true/false outputs allowed)"; | |
314 | ||
315 | case ErrorCode_LuaReturnsNoString: | |
316 | return "The Lua function does not return a string"; | |
317 | ||
318 | case ErrorCode_StorageAreaAlreadyRegistered: | |
319 | return "Another plugin has already registered a custom storage area"; | |
320 | ||
321 | case ErrorCode_DatabaseBackendAlreadyRegistered: | |
322 | return "Another plugin has already registered a custom database back-end"; | |
323 | ||
324 | case ErrorCode_DatabaseNotInitialized: | |
325 | return "Plugin trying to call the database during its initialization"; | |
326 | ||
327 | case ErrorCode_SslDisabled: | |
328 | return "Orthanc has been built without SSL support"; | |
329 | ||
330 | case ErrorCode_CannotOrderSlices: | |
331 | return "Unable to order the slices of the series"; | |
332 | ||
333 | case ErrorCode_NoWorklistHandler: | |
334 | return "No request handler factory for DICOM C-Find Modality SCP"; | |
335 | ||
336 | case ErrorCode_AlreadyExistingTag: | |
337 | return "Cannot override the value of a tag that already exists"; | |
338 | ||
339 | default: | |
340 | if (error >= ErrorCode_START_PLUGINS) | |
341 | { | |
342 | return "Error encountered within some plugin"; | |
343 | } | |
344 | else | |
345 | { | |
346 | return "Unknown error code"; | |
347 | } | |
348 | } | |
349 | } | |
350 | ||
351 | ||
352 | const char* EnumerationToString(HttpMethod method) | |
353 | { | |
354 | switch (method) | |
355 | { | |
356 | case HttpMethod_Get: | |
357 | return "GET"; | |
358 | ||
359 | case HttpMethod_Post: | |
360 | return "POST"; | |
361 | ||
362 | case HttpMethod_Delete: | |
363 | return "DELETE"; | |
364 | ||
365 | case HttpMethod_Put: | |
366 | return "PUT"; | |
367 | ||
368 | default: | |
369 | return "?"; | |
370 | } | |
371 | } | |
372 | ||
373 | ||
374 | const char* EnumerationToString(HttpStatus status) | |
375 | { | |
376 | switch (status) | |
377 | { | |
378 | case HttpStatus_100_Continue: | |
379 | return "Continue"; | |
380 | ||
381 | case HttpStatus_101_SwitchingProtocols: | |
382 | return "Switching Protocols"; | |
383 | ||
384 | case HttpStatus_102_Processing: | |
385 | return "Processing"; | |
386 | ||
387 | case HttpStatus_200_Ok: | |
388 | return "OK"; | |
389 | ||
390 | case HttpStatus_201_Created: | |
391 | return "Created"; | |
392 | ||
393 | case HttpStatus_202_Accepted: | |
394 | return "Accepted"; | |
395 | ||
396 | case HttpStatus_203_NonAuthoritativeInformation: | |
397 | return "Non-Authoritative Information"; | |
398 | ||
399 | case HttpStatus_204_NoContent: | |
400 | return "No Content"; | |
401 | ||
402 | case HttpStatus_205_ResetContent: | |
403 | return "Reset Content"; | |
404 | ||
405 | case HttpStatus_206_PartialContent: | |
406 | return "Partial Content"; | |
407 | ||
408 | case HttpStatus_207_MultiStatus: | |
409 | return "Multi-Status"; | |
410 | ||
411 | case HttpStatus_208_AlreadyReported: | |
412 | return "Already Reported"; | |
413 | ||
414 | case HttpStatus_226_IMUsed: | |
415 | return "IM Used"; | |
416 | ||
417 | case HttpStatus_300_MultipleChoices: | |
418 | return "Multiple Choices"; | |
419 | ||
420 | case HttpStatus_301_MovedPermanently: | |
421 | return "Moved Permanently"; | |
422 | ||
423 | case HttpStatus_302_Found: | |
424 | return "Found"; | |
425 | ||
426 | case HttpStatus_303_SeeOther: | |
427 | return "See Other"; | |
428 | ||
429 | case HttpStatus_304_NotModified: | |
430 | return "Not Modified"; | |
431 | ||
432 | case HttpStatus_305_UseProxy: | |
433 | return "Use Proxy"; | |
434 | ||
435 | case HttpStatus_307_TemporaryRedirect: | |
436 | return "Temporary Redirect"; | |
437 | ||
438 | case HttpStatus_400_BadRequest: | |
439 | return "Bad Request"; | |
440 | ||
441 | case HttpStatus_401_Unauthorized: | |
442 | return "Unauthorized"; | |
443 | ||
444 | case HttpStatus_402_PaymentRequired: | |
445 | return "Payment Required"; | |
446 | ||
447 | case HttpStatus_403_Forbidden: | |
448 | return "Forbidden"; | |
449 | ||
450 | case HttpStatus_404_NotFound: | |
451 | return "Not Found"; | |
452 | ||
453 | case HttpStatus_405_MethodNotAllowed: | |
454 | return "Method Not Allowed"; | |
455 | ||
456 | case HttpStatus_406_NotAcceptable: | |
457 | return "Not Acceptable"; | |
458 | ||
459 | case HttpStatus_407_ProxyAuthenticationRequired: | |
460 | return "Proxy Authentication Required"; | |
461 | ||
462 | case HttpStatus_408_RequestTimeout: | |
463 | return "Request Timeout"; | |
464 | ||
465 | case HttpStatus_409_Conflict: | |
466 | return "Conflict"; | |
467 | ||
468 | case HttpStatus_410_Gone: | |
469 | return "Gone"; | |
470 | ||
471 | case HttpStatus_411_LengthRequired: | |
472 | return "Length Required"; | |
473 | ||
474 | case HttpStatus_412_PreconditionFailed: | |
475 | return "Precondition Failed"; | |
476 | ||
477 | case HttpStatus_413_RequestEntityTooLarge: | |
478 | return "Request Entity Too Large"; | |
479 | ||
480 | case HttpStatus_414_RequestUriTooLong: | |
481 | return "Request-URI Too Long"; | |
482 | ||
483 | case HttpStatus_415_UnsupportedMediaType: | |
484 | return "Unsupported Media Type"; | |
485 | ||
486 | case HttpStatus_416_RequestedRangeNotSatisfiable: | |
487 | return "Requested Range Not Satisfiable"; | |
488 | ||
489 | case HttpStatus_417_ExpectationFailed: | |
490 | return "Expectation Failed"; | |
491 | ||
492 | case HttpStatus_422_UnprocessableEntity: | |
493 | return "Unprocessable Entity"; | |
494 | ||
495 | case HttpStatus_423_Locked: | |
496 | return "Locked"; | |
497 | ||
498 | case HttpStatus_424_FailedDependency: | |
499 | return "Failed Dependency"; | |
500 | ||
501 | case HttpStatus_426_UpgradeRequired: | |
502 | return "Upgrade Required"; | |
503 | ||
504 | case HttpStatus_500_InternalServerError: | |
505 | return "Internal Server Error"; | |
506 | ||
507 | case HttpStatus_501_NotImplemented: | |
508 | return "Not Implemented"; | |
509 | ||
510 | case HttpStatus_502_BadGateway: | |
511 | return "Bad Gateway"; | |
512 | ||
513 | case HttpStatus_503_ServiceUnavailable: | |
514 | return "Service Unavailable"; | |
515 | ||
516 | case HttpStatus_504_GatewayTimeout: | |
517 | return "Gateway Timeout"; | |
518 | ||
519 | case HttpStatus_505_HttpVersionNotSupported: | |
520 | return "HTTP Version Not Supported"; | |
521 | ||
522 | case HttpStatus_506_VariantAlsoNegotiates: | |
523 | return "Variant Also Negotiates"; | |
524 | ||
525 | case HttpStatus_507_InsufficientStorage: | |
526 | return "Insufficient Storage"; | |
527 | ||
528 | case HttpStatus_509_BandwidthLimitExceeded: | |
529 | return "Bandwidth Limit Exceeded"; | |
530 | ||
531 | case HttpStatus_510_NotExtended: | |
532 | return "Not Extended"; | |
533 | ||
534 | default: | |
535 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
536 | } | |
537 | } | |
538 | ||
539 | ||
540 | const char* EnumerationToString(ResourceType type) | |
541 | { | |
542 | switch (type) | |
543 | { | |
544 | case ResourceType_Patient: | |
545 | return "Patient"; | |
546 | ||
547 | case ResourceType_Study: | |
548 | return "Study"; | |
549 | ||
550 | case ResourceType_Series: | |
551 | return "Series"; | |
552 | ||
553 | case ResourceType_Instance: | |
554 | return "Instance"; | |
555 | ||
556 | default: | |
557 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
558 | } | |
559 | } | |
560 | ||
561 | ||
562 | const char* EnumerationToString(ImageFormat format) | |
563 | { | |
564 | switch (format) | |
565 | { | |
566 | case ImageFormat_Png: | |
567 | return "Png"; | |
568 | ||
569 | default: | |
570 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
571 | } | |
572 | } | |
573 | ||
574 | ||
575 | const char* EnumerationToString(Encoding encoding) | |
576 | { | |
577 | switch (encoding) | |
578 | { | |
579 | case Encoding_Ascii: | |
580 | return "Ascii"; | |
581 | ||
582 | case Encoding_Utf8: | |
583 | return "Utf8"; | |
584 | ||
585 | case Encoding_Latin1: | |
586 | return "Latin1"; | |
587 | ||
588 | case Encoding_Latin2: | |
589 | return "Latin2"; | |
590 | ||
591 | case Encoding_Latin3: | |
592 | return "Latin3"; | |
593 | ||
594 | case Encoding_Latin4: | |
595 | return "Latin4"; | |
596 | ||
597 | case Encoding_Latin5: | |
598 | return "Latin5"; | |
599 | ||
600 | case Encoding_Cyrillic: | |
601 | return "Cyrillic"; | |
602 | ||
603 | case Encoding_Windows1251: | |
604 | return "Windows1251"; | |
605 | ||
606 | case Encoding_Arabic: | |
607 | return "Arabic"; | |
608 | ||
609 | case Encoding_Greek: | |
610 | return "Greek"; | |
611 | ||
612 | case Encoding_Hebrew: | |
613 | return "Hebrew"; | |
614 | ||
615 | case Encoding_Thai: | |
616 | return "Thai"; | |
617 | ||
618 | case Encoding_Japanese: | |
619 | return "Japanese"; | |
620 | ||
621 | case Encoding_Chinese: | |
622 | return "Chinese"; | |
623 | ||
624 | default: | |
625 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
626 | } | |
627 | } | |
628 | ||
629 | ||
630 | const char* EnumerationToString(PhotometricInterpretation photometric) | |
631 | { | |
632 | switch (photometric) | |
633 | { | |
634 | case PhotometricInterpretation_RGB: | |
635 | return "RGB"; | |
636 | ||
637 | case PhotometricInterpretation_Monochrome1: | |
638 | return "MONOCHROME1"; | |
639 | ||
640 | case PhotometricInterpretation_Monochrome2: | |
641 | return "MONOCHROME2"; | |
642 | ||
643 | case PhotometricInterpretation_ARGB: | |
644 | return "ARGB"; | |
645 | ||
646 | case PhotometricInterpretation_CMYK: | |
647 | return "CMYK"; | |
648 | ||
649 | case PhotometricInterpretation_HSV: | |
650 | return "HSV"; | |
651 | ||
652 | case PhotometricInterpretation_Palette: | |
653 | return "PALETTE COLOR"; | |
654 | ||
655 | case PhotometricInterpretation_YBRFull: | |
656 | return "YBR_FULL"; | |
657 | ||
658 | case PhotometricInterpretation_YBRFull422: | |
659 | return "YBR_FULL_422"; | |
660 | ||
661 | case PhotometricInterpretation_YBRPartial420: | |
662 | return "YBR_PARTIAL_420"; | |
663 | ||
664 | case PhotometricInterpretation_YBRPartial422: | |
665 | return "YBR_PARTIAL_422"; | |
666 | ||
667 | case PhotometricInterpretation_YBR_ICT: | |
668 | return "YBR_ICT"; | |
669 | ||
670 | case PhotometricInterpretation_YBR_RCT: | |
671 | return "YBR_RCT"; | |
672 | ||
673 | case PhotometricInterpretation_Unknown: | |
674 | return "Unknown"; | |
675 | ||
676 | default: | |
677 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
678 | } | |
679 | } | |
680 | ||
681 | ||
682 | const char* EnumerationToString(RequestOrigin origin) | |
683 | { | |
684 | switch (origin) | |
685 | { | |
686 | case RequestOrigin_Unknown: | |
687 | return "Unknown"; | |
688 | ||
689 | case RequestOrigin_DicomProtocol: | |
690 | return "DicomProtocol"; | |
691 | ||
692 | case RequestOrigin_RestApi: | |
693 | return "RestApi"; | |
694 | ||
695 | case RequestOrigin_Plugins: | |
696 | return "Plugins"; | |
697 | ||
698 | case RequestOrigin_Lua: | |
699 | return "Lua"; | |
700 | ||
701 | default: | |
702 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
703 | } | |
704 | } | |
705 | ||
706 | ||
707 | const char* EnumerationToString(LogLevel level) | |
708 | { | |
709 | switch (level) | |
710 | { | |
711 | case LogLevel_Error: | |
712 | return "ERROR"; | |
713 | ||
714 | case LogLevel_Warning: | |
715 | return "WARNING"; | |
716 | ||
717 | case LogLevel_Info: | |
718 | return "INFO"; | |
719 | ||
720 | case LogLevel_Trace: | |
721 | return "TRACE"; | |
722 | ||
723 | default: | |
724 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
725 | } | |
726 | } | |
727 | ||
728 | ||
729 | const char* EnumerationToString(PixelFormat format) | |
730 | { | |
731 | switch (format) | |
732 | { | |
733 | case PixelFormat_RGB24: | |
734 | return "RGB24"; | |
735 | ||
736 | case PixelFormat_RGBA32: | |
737 | return "RGBA32"; | |
738 | ||
739 | case PixelFormat_BGRA32: | |
740 | return "BGRA32"; | |
741 | ||
742 | case PixelFormat_Grayscale8: | |
743 | return "Grayscale (unsigned 8bpp)"; | |
744 | ||
745 | case PixelFormat_Grayscale16: | |
746 | return "Grayscale (unsigned 16bpp)"; | |
747 | ||
748 | case PixelFormat_SignedGrayscale16: | |
749 | return "Grayscale (signed 16bpp)"; | |
750 | ||
751 | case PixelFormat_Float32: | |
752 | return "Grayscale (float 32bpp)"; | |
753 | ||
754 | default: | |
755 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
756 | } | |
757 | } | |
758 | ||
759 | ||
760 | Encoding StringToEncoding(const char* encoding) | |
761 | { | |
762 | std::string s(encoding); | |
763 | Toolbox::ToUpperCase(s); | |
764 | ||
765 | if (s == "UTF8") | |
766 | { | |
767 | return Encoding_Utf8; | |
768 | } | |
769 | ||
770 | if (s == "ASCII") | |
771 | { | |
772 | return Encoding_Ascii; | |
773 | } | |
774 | ||
775 | if (s == "LATIN1") | |
776 | { | |
777 | return Encoding_Latin1; | |
778 | } | |
779 | ||
780 | if (s == "LATIN2") | |
781 | { | |
782 | return Encoding_Latin2; | |
783 | } | |
784 | ||
785 | if (s == "LATIN3") | |
786 | { | |
787 | return Encoding_Latin3; | |
788 | } | |
789 | ||
790 | if (s == "LATIN4") | |
791 | { | |
792 | return Encoding_Latin4; | |
793 | } | |
794 | ||
795 | if (s == "LATIN5") | |
796 | { | |
797 | return Encoding_Latin5; | |
798 | } | |
799 | ||
800 | if (s == "CYRILLIC") | |
801 | { | |
802 | return Encoding_Cyrillic; | |
803 | } | |
804 | ||
805 | if (s == "WINDOWS1251") | |
806 | { | |
807 | return Encoding_Windows1251; | |
808 | } | |
809 | ||
810 | if (s == "ARABIC") | |
811 | { | |
812 | return Encoding_Arabic; | |
813 | } | |
814 | ||
815 | if (s == "GREEK") | |
816 | { | |
817 | return Encoding_Greek; | |
818 | } | |
819 | ||
820 | if (s == "HEBREW") | |
821 | { | |
822 | return Encoding_Hebrew; | |
823 | } | |
824 | ||
825 | if (s == "THAI") | |
826 | { | |
827 | return Encoding_Thai; | |
828 | } | |
829 | ||
830 | if (s == "JAPANESE") | |
831 | { | |
832 | return Encoding_Japanese; | |
833 | } | |
834 | ||
835 | if (s == "CHINESE") | |
836 | { | |
837 | return Encoding_Chinese; | |
838 | } | |
839 | ||
840 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
841 | } | |
842 | ||
843 | ||
844 | ResourceType StringToResourceType(const char* type) | |
845 | { | |
846 | std::string s(type); | |
847 | Toolbox::ToUpperCase(s); | |
848 | ||
849 | if (s == "PATIENT" || s == "PATIENTS") | |
850 | { | |
851 | return ResourceType_Patient; | |
852 | } | |
853 | else if (s == "STUDY" || s == "STUDIES") | |
854 | { | |
855 | return ResourceType_Study; | |
856 | } | |
857 | else if (s == "SERIES") | |
858 | { | |
859 | return ResourceType_Series; | |
860 | } | |
861 | else if (s == "INSTANCE" || s == "IMAGE" || | |
862 | s == "INSTANCES" || s == "IMAGES") | |
863 | { | |
864 | return ResourceType_Instance; | |
865 | } | |
866 | ||
867 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
868 | } | |
869 | ||
870 | ||
871 | ImageFormat StringToImageFormat(const char* format) | |
872 | { | |
873 | std::string s(format); | |
874 | Toolbox::ToUpperCase(s); | |
875 | ||
876 | if (s == "PNG") | |
877 | { | |
878 | return ImageFormat_Png; | |
879 | } | |
880 | ||
881 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
882 | } | |
883 | ||
884 | ||
885 | LogLevel StringToLogLevel(const char *level) | |
886 | { | |
887 | if (strcmp(level, "ERROR") == 0) | |
888 | { | |
889 | return LogLevel_Error; | |
890 | } | |
891 | else if (strcmp(level, "WARNING") == 0) | |
892 | { | |
893 | return LogLevel_Warning; | |
894 | } | |
895 | else if (strcmp(level, "INFO") == 0) | |
896 | { | |
897 | return LogLevel_Info; | |
898 | } | |
899 | else if (strcmp(level, "TRACE") == 0) | |
900 | { | |
901 | return LogLevel_Trace; | |
902 | } | |
903 | else | |
904 | { | |
905 | throw OrthancException(ErrorCode_InternalError); | |
906 | } | |
907 | } | |
908 | ||
909 | ||
910 | ValueRepresentation StringToValueRepresentation(const std::string& vr, | |
911 | bool throwIfUnsupported) | |
912 | { | |
913 | if (vr == "AE") | |
914 | { | |
915 | return ValueRepresentation_ApplicationEntity; | |
916 | } | |
917 | else if (vr == "AS") | |
918 | { | |
919 | return ValueRepresentation_AgeString; | |
920 | } | |
921 | else if (vr == "AT") | |
922 | { | |
923 | return ValueRepresentation_AttributeTag; | |
924 | } | |
925 | else if (vr == "CS") | |
926 | { | |
927 | return ValueRepresentation_CodeString; | |
928 | } | |
929 | else if (vr == "DA") | |
930 | { | |
931 | return ValueRepresentation_Date; | |
932 | } | |
933 | else if (vr == "DS") | |
934 | { | |
935 | return ValueRepresentation_DecimalString; | |
936 | } | |
937 | else if (vr == "DT") | |
938 | { | |
939 | return ValueRepresentation_DateTime; | |
940 | } | |
941 | else if (vr == "FL") | |
942 | { | |
943 | return ValueRepresentation_FloatingPointSingle; | |
944 | } | |
945 | else if (vr == "FD") | |
946 | { | |
947 | return ValueRepresentation_FloatingPointDouble; | |
948 | } | |
949 | else if (vr == "IS") | |
950 | { | |
951 | return ValueRepresentation_IntegerString; | |
952 | } | |
953 | else if (vr == "LO") | |
954 | { | |
955 | return ValueRepresentation_LongString; | |
956 | } | |
957 | else if (vr == "LT") | |
958 | { | |
959 | return ValueRepresentation_LongText; | |
960 | } | |
961 | else if (vr == "OB") | |
962 | { | |
963 | return ValueRepresentation_OtherByte; | |
964 | } | |
965 | else if (vr == "OD") | |
966 | { | |
967 | return ValueRepresentation_OtherDouble; | |
968 | } | |
969 | else if (vr == "OF") | |
970 | { | |
971 | return ValueRepresentation_OtherFloat; | |
972 | } | |
973 | else if (vr == "OL") | |
974 | { | |
975 | return ValueRepresentation_OtherLong; | |
976 | } | |
977 | else if (vr == "OW") | |
978 | { | |
979 | return ValueRepresentation_OtherWord; | |
980 | } | |
981 | else if (vr == "PN") | |
982 | { | |
983 | return ValueRepresentation_PersonName; | |
984 | } | |
985 | else if (vr == "SH") | |
986 | { | |
987 | return ValueRepresentation_ShortString; | |
988 | } | |
989 | else if (vr == "SL") | |
990 | { | |
991 | return ValueRepresentation_SignedLong; | |
992 | } | |
993 | else if (vr == "SQ") | |
994 | { | |
995 | return ValueRepresentation_Sequence; | |
996 | } | |
997 | else if (vr == "SS") | |
998 | { | |
999 | return ValueRepresentation_SignedShort; | |
1000 | } | |
1001 | else if (vr == "ST") | |
1002 | { | |
1003 | return ValueRepresentation_ShortText; | |
1004 | } | |
1005 | else if (vr == "TM") | |
1006 | { | |
1007 | return ValueRepresentation_Time; | |
1008 | } | |
1009 | else if (vr == "UC") | |
1010 | { | |
1011 | return ValueRepresentation_UnlimitedCharacters; | |
1012 | } | |
1013 | else if (vr == "UI") | |
1014 | { | |
1015 | return ValueRepresentation_UniqueIdentifier; | |
1016 | } | |
1017 | else if (vr == "UL") | |
1018 | { | |
1019 | return ValueRepresentation_UnsignedLong; | |
1020 | } | |
1021 | else if (vr == "UN") | |
1022 | { | |
1023 | return ValueRepresentation_Unknown; | |
1024 | } | |
1025 | else if (vr == "UR") | |
1026 | { | |
1027 | return ValueRepresentation_UniversalResource; | |
1028 | } | |
1029 | else if (vr == "US") | |
1030 | { | |
1031 | return ValueRepresentation_UnsignedShort; | |
1032 | } | |
1033 | else if (vr == "UT") | |
1034 | { | |
1035 | return ValueRepresentation_UnlimitedText; | |
1036 | } | |
1037 | else | |
1038 | { | |
1039 | std::string s = "Unsupported value representation encountered: " + vr; | |
1040 | ||
1041 | if (throwIfUnsupported) | |
1042 | { | |
1043 | LOG(ERROR) << s; | |
1044 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1045 | } | |
1046 | else | |
1047 | { | |
1048 | LOG(INFO) << s; | |
1049 | return ValueRepresentation_NotSupported; | |
1050 | } | |
1051 | } | |
1052 | } | |
1053 | ||
1054 | ||
1055 | PhotometricInterpretation StringToPhotometricInterpretation(const char* value) | |
1056 | { | |
1057 | // http://dicom.nema.org/medical/dicom/2017a/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2 | |
1058 | std::string s(value); | |
1059 | ||
1060 | if (s == "MONOCHROME1") | |
1061 | { | |
1062 | return PhotometricInterpretation_Monochrome1; | |
1063 | } | |
1064 | ||
1065 | if (s == "MONOCHROME2") | |
1066 | { | |
1067 | return PhotometricInterpretation_Monochrome2; | |
1068 | } | |
1069 | ||
1070 | if (s == "PALETTE COLOR") | |
1071 | { | |
1072 | return PhotometricInterpretation_Palette; | |
1073 | } | |
1074 | ||
1075 | if (s == "RGB") | |
1076 | { | |
1077 | return PhotometricInterpretation_RGB; | |
1078 | } | |
1079 | ||
1080 | if (s == "HSV") | |
1081 | { | |
1082 | return PhotometricInterpretation_HSV; | |
1083 | } | |
1084 | ||
1085 | if (s == "ARGB") | |
1086 | { | |
1087 | return PhotometricInterpretation_ARGB; | |
1088 | } | |
1089 | ||
1090 | if (s == "CMYK") | |
1091 | { | |
1092 | return PhotometricInterpretation_CMYK; | |
1093 | } | |
1094 | ||
1095 | if (s == "YBR_FULL") | |
1096 | { | |
1097 | return PhotometricInterpretation_YBRFull; | |
1098 | } | |
1099 | ||
1100 | if (s == "YBR_FULL_422") | |
1101 | { | |
1102 | return PhotometricInterpretation_YBRFull422; | |
1103 | } | |
1104 | ||
1105 | if (s == "YBR_PARTIAL_422") | |
1106 | { | |
1107 | return PhotometricInterpretation_YBRPartial422; | |
1108 | } | |
1109 | ||
1110 | if (s == "YBR_PARTIAL_420") | |
1111 | { | |
1112 | return PhotometricInterpretation_YBRPartial420; | |
1113 | } | |
1114 | ||
1115 | if (s == "YBR_ICT") | |
1116 | { | |
1117 | return PhotometricInterpretation_YBR_ICT; | |
1118 | } | |
1119 | ||
1120 | if (s == "YBR_RCT") | |
1121 | { | |
1122 | return PhotometricInterpretation_YBR_RCT; | |
1123 | } | |
1124 | ||
1125 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1126 | } | |
1127 | ||
1128 | ||
1129 | unsigned int GetBytesPerPixel(PixelFormat format) | |
1130 | { | |
1131 | switch (format) | |
1132 | { | |
1133 | case PixelFormat_Grayscale8: | |
1134 | return 1; | |
1135 | ||
1136 | case PixelFormat_Grayscale16: | |
1137 | case PixelFormat_SignedGrayscale16: | |
1138 | return 2; | |
1139 | ||
1140 | case PixelFormat_RGB24: | |
1141 | return 3; | |
1142 | ||
1143 | case PixelFormat_RGBA32: | |
1144 | case PixelFormat_BGRA32: | |
1145 | return 4; | |
1146 | ||
1147 | case PixelFormat_Float32: | |
1148 | assert(sizeof(float) == 4); | |
1149 | return 4; | |
1150 | ||
1151 | default: | |
1152 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1153 | } | |
1154 | } | |
1155 | ||
1156 | ||
1157 | bool GetDicomEncoding(Encoding& encoding, | |
1158 | const char* specificCharacterSet) | |
1159 | { | |
1160 | std::string s = Toolbox::StripSpaces(specificCharacterSet); | |
1161 | Toolbox::ToUpperCase(s); | |
1162 | ||
1163 | // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2 | |
1164 | // https://github.com/dcm4che/dcm4che/blob/master/dcm4che-core/src/main/java/org/dcm4che3/data/SpecificCharacterSet.java | |
1165 | if (s == "ISO_IR 6" || | |
1166 | s == "ISO 2022 IR 6") | |
1167 | { | |
1168 | encoding = Encoding_Ascii; | |
1169 | } | |
1170 | else if (s == "ISO_IR 192") | |
1171 | { | |
1172 | encoding = Encoding_Utf8; | |
1173 | } | |
1174 | else if (s == "ISO_IR 100" || | |
1175 | s == "ISO 2022 IR 100") | |
1176 | { | |
1177 | encoding = Encoding_Latin1; | |
1178 | } | |
1179 | else if (s == "ISO_IR 101" || | |
1180 | s == "ISO 2022 IR 101") | |
1181 | { | |
1182 | encoding = Encoding_Latin2; | |
1183 | } | |
1184 | else if (s == "ISO_IR 109" || | |
1185 | s == "ISO 2022 IR 109") | |
1186 | { | |
1187 | encoding = Encoding_Latin3; | |
1188 | } | |
1189 | else if (s == "ISO_IR 110" || | |
1190 | s == "ISO 2022 IR 110") | |
1191 | { | |
1192 | encoding = Encoding_Latin4; | |
1193 | } | |
1194 | else if (s == "ISO_IR 148" || | |
1195 | s == "ISO 2022 IR 148") | |
1196 | { | |
1197 | encoding = Encoding_Latin5; | |
1198 | } | |
1199 | else if (s == "ISO_IR 144" || | |
1200 | s == "ISO 2022 IR 144") | |
1201 | { | |
1202 | encoding = Encoding_Cyrillic; | |
1203 | } | |
1204 | else if (s == "ISO_IR 127" || | |
1205 | s == "ISO 2022 IR 127") | |
1206 | { | |
1207 | encoding = Encoding_Arabic; | |
1208 | } | |
1209 | else if (s == "ISO_IR 126" || | |
1210 | s == "ISO 2022 IR 126") | |
1211 | { | |
1212 | encoding = Encoding_Greek; | |
1213 | } | |
1214 | else if (s == "ISO_IR 138" || | |
1215 | s == "ISO 2022 IR 138") | |
1216 | { | |
1217 | encoding = Encoding_Hebrew; | |
1218 | } | |
1219 | else if (s == "ISO_IR 166" || s == "ISO 2022 IR 166") | |
1220 | { | |
1221 | encoding = Encoding_Thai; | |
1222 | } | |
1223 | else if (s == "ISO_IR 13" || s == "ISO 2022 IR 13") | |
1224 | { | |
1225 | encoding = Encoding_Japanese; | |
1226 | } | |
1227 | else if (s == "GB18030") | |
1228 | { | |
1229 | encoding = Encoding_Chinese; | |
1230 | } | |
1231 | /* | |
1232 | else if (s == "ISO 2022 IR 149") | |
1233 | { | |
1234 | TODO | |
1235 | } | |
1236 | else if (s == "ISO 2022 IR 159") | |
1237 | { | |
1238 | TODO | |
1239 | } | |
1240 | else if (s == "ISO 2022 IR 87") | |
1241 | { | |
1242 | TODO | |
1243 | } | |
1244 | */ | |
1245 | else | |
1246 | { | |
1247 | return false; | |
1248 | } | |
1249 | ||
1250 | // The encoding was properly detected | |
1251 | return true; | |
1252 | } | |
1253 | ||
1254 | ||
1255 | ResourceType GetChildResourceType(ResourceType type) | |
1256 | { | |
1257 | switch (type) | |
1258 | { | |
1259 | case ResourceType_Patient: | |
1260 | return ResourceType_Study; | |
1261 | ||
1262 | case ResourceType_Study: | |
1263 | return ResourceType_Series; | |
1264 | ||
1265 | case ResourceType_Series: | |
1266 | return ResourceType_Instance; | |
1267 | ||
1268 | default: | |
1269 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1270 | } | |
1271 | } | |
1272 | ||
1273 | ||
1274 | ResourceType GetParentResourceType(ResourceType type) | |
1275 | { | |
1276 | switch (type) | |
1277 | { | |
1278 | case ResourceType_Study: | |
1279 | return ResourceType_Patient; | |
1280 | ||
1281 | case ResourceType_Series: | |
1282 | return ResourceType_Study; | |
1283 | ||
1284 | case ResourceType_Instance: | |
1285 | return ResourceType_Series; | |
1286 | ||
1287 | default: | |
1288 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1289 | } | |
1290 | } | |
1291 | ||
1292 | ||
1293 | DicomModule GetModule(ResourceType type) | |
1294 | { | |
1295 | switch (type) | |
1296 | { | |
1297 | case ResourceType_Patient: | |
1298 | return DicomModule_Patient; | |
1299 | ||
1300 | case ResourceType_Study: | |
1301 | return DicomModule_Study; | |
1302 | ||
1303 | case ResourceType_Series: | |
1304 | return DicomModule_Series; | |
1305 | ||
1306 | default: | |
1307 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1308 | } | |
1309 | } | |
1310 | ||
1311 | ||
1312 | ||
1313 | const char* GetDicomSpecificCharacterSet(Encoding encoding) | |
1314 | { | |
1315 | // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2 | |
1316 | switch (encoding) | |
1317 | { | |
1318 | case Encoding_Ascii: | |
1319 | return "ISO_IR 6"; | |
1320 | ||
1321 | case Encoding_Utf8: | |
1322 | return "ISO_IR 192"; | |
1323 | ||
1324 | case Encoding_Latin1: | |
1325 | return "ISO_IR 100"; | |
1326 | ||
1327 | case Encoding_Latin2: | |
1328 | return "ISO_IR 101"; | |
1329 | ||
1330 | case Encoding_Latin3: | |
1331 | return "ISO_IR 109"; | |
1332 | ||
1333 | case Encoding_Latin4: | |
1334 | return "ISO_IR 110"; | |
1335 | ||
1336 | case Encoding_Latin5: | |
1337 | return "ISO_IR 148"; | |
1338 | ||
1339 | case Encoding_Cyrillic: | |
1340 | return "ISO_IR 144"; | |
1341 | ||
1342 | case Encoding_Arabic: | |
1343 | return "ISO_IR 127"; | |
1344 | ||
1345 | case Encoding_Greek: | |
1346 | return "ISO_IR 126"; | |
1347 | ||
1348 | case Encoding_Hebrew: | |
1349 | return "ISO_IR 138"; | |
1350 | ||
1351 | case Encoding_Japanese: | |
1352 | return "ISO_IR 13"; | |
1353 | ||
1354 | case Encoding_Chinese: | |
1355 | return "GB18030"; | |
1356 | ||
1357 | case Encoding_Thai: | |
1358 | return "ISO_IR 166"; | |
1359 | ||
1360 | default: | |
1361 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1362 | } | |
1363 | } | |
1364 | ||
1365 | ||
1366 | // This function is autogenerated by the script | |
1367 | // "Resources/GenerateErrorCodes.py" | |
1368 | HttpStatus ConvertErrorCodeToHttpStatus(ErrorCode error) | |
1369 | { | |
1370 | switch (error) | |
1371 | { | |
1372 | case ErrorCode_Success: | |
1373 | return HttpStatus_200_Ok; | |
1374 | ||
1375 | case ErrorCode_ParameterOutOfRange: | |
1376 | return HttpStatus_400_BadRequest; | |
1377 | ||
1378 | case ErrorCode_BadParameterType: | |
1379 | return HttpStatus_400_BadRequest; | |
1380 | ||
1381 | case ErrorCode_InexistentItem: | |
1382 | return HttpStatus_404_NotFound; | |
1383 | ||
1384 | case ErrorCode_BadRequest: | |
1385 | return HttpStatus_400_BadRequest; | |
1386 | ||
1387 | case ErrorCode_UriSyntax: | |
1388 | return HttpStatus_400_BadRequest; | |
1389 | ||
1390 | case ErrorCode_InexistentFile: | |
1391 | return HttpStatus_404_NotFound; | |
1392 | ||
1393 | case ErrorCode_BadFileFormat: | |
1394 | return HttpStatus_400_BadRequest; | |
1395 | ||
1396 | case ErrorCode_UnknownResource: | |
1397 | return HttpStatus_404_NotFound; | |
1398 | ||
1399 | case ErrorCode_InexistentTag: | |
1400 | return HttpStatus_404_NotFound; | |
1401 | ||
1402 | case ErrorCode_BadJson: | |
1403 | return HttpStatus_400_BadRequest; | |
1404 | ||
1405 | case ErrorCode_Unauthorized: | |
1406 | return HttpStatus_401_Unauthorized; | |
1407 | ||
1408 | case ErrorCode_NotAcceptable: | |
1409 | return HttpStatus_406_NotAcceptable; | |
1410 | ||
1411 | default: | |
1412 | return HttpStatus_500_InternalServerError; | |
1413 | } | |
1414 | } | |
1415 | ||
1416 | ||
1417 | bool IsUserContentType(FileContentType type) | |
1418 | { | |
1419 | return (type >= FileContentType_StartUser && | |
1420 | type <= FileContentType_EndUser); | |
1421 | } | |
1422 | ||
1423 | ||
1424 | bool IsBinaryValueRepresentation(ValueRepresentation vr) | |
1425 | { | |
1426 | // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html | |
1427 | ||
1428 | switch (vr) | |
1429 | { | |
1430 | case ValueRepresentation_ApplicationEntity: // AE | |
1431 | case ValueRepresentation_AgeString: // AS | |
1432 | case ValueRepresentation_CodeString: // CS | |
1433 | case ValueRepresentation_Date: // DA | |
1434 | case ValueRepresentation_DecimalString: // DS | |
1435 | case ValueRepresentation_DateTime: // DT | |
1436 | case ValueRepresentation_IntegerString: // IS | |
1437 | case ValueRepresentation_LongString: // LO | |
1438 | case ValueRepresentation_LongText: // LT | |
1439 | case ValueRepresentation_PersonName: // PN | |
1440 | case ValueRepresentation_ShortString: // SH | |
1441 | case ValueRepresentation_ShortText: // ST | |
1442 | case ValueRepresentation_Time: // TM | |
1443 | case ValueRepresentation_UnlimitedCharacters: // UC | |
1444 | case ValueRepresentation_UniqueIdentifier: // UI (UID) | |
1445 | case ValueRepresentation_UniversalResource: // UR (URI or URL) | |
1446 | case ValueRepresentation_UnlimitedText: // UT | |
1447 | { | |
1448 | return false; | |
1449 | } | |
1450 | ||
1451 | /** | |
1452 | * Below are all the VR whose character repertoire is tagged as | |
1453 | * "not applicable" | |
1454 | **/ | |
1455 | case ValueRepresentation_AttributeTag: // AT (2 x uint16_t) | |
1456 | case ValueRepresentation_FloatingPointSingle: // FL (float) | |
1457 | case ValueRepresentation_FloatingPointDouble: // FD (double) | |
1458 | case ValueRepresentation_OtherByte: // OB | |
1459 | case ValueRepresentation_OtherDouble: // OD | |
1460 | case ValueRepresentation_OtherFloat: // OF | |
1461 | case ValueRepresentation_OtherLong: // OL | |
1462 | case ValueRepresentation_OtherWord: // OW | |
1463 | case ValueRepresentation_SignedLong: // SL (int32_t) | |
1464 | case ValueRepresentation_Sequence: // SQ | |
1465 | case ValueRepresentation_SignedShort: // SS (int16_t) | |
1466 | case ValueRepresentation_UnsignedLong: // UL (uint32_t) | |
1467 | case ValueRepresentation_Unknown: // UN | |
1468 | case ValueRepresentation_UnsignedShort: // US (uint16_t) | |
1469 | { | |
1470 | return true; | |
1471 | } | |
1472 | ||
1473 | case ValueRepresentation_NotSupported: | |
1474 | default: | |
1475 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1476 | } | |
1477 | } | |
1478 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include <string> | |
36 | ||
37 | namespace Orthanc | |
38 | { | |
39 | enum Endianness | |
40 | { | |
41 | Endianness_Unknown, | |
42 | Endianness_Big, | |
43 | Endianness_Little | |
44 | }; | |
45 | ||
46 | // This enumeration is autogenerated by the script | |
47 | // "Resources/GenerateErrorCodes.py" | |
48 | enum ErrorCode | |
49 | { | |
50 | ErrorCode_InternalError = -1 /*!< Internal error */, | |
51 | ErrorCode_Success = 0 /*!< Success */, | |
52 | ErrorCode_Plugin = 1 /*!< Error encountered within the plugin engine */, | |
53 | ErrorCode_NotImplemented = 2 /*!< Not implemented yet */, | |
54 | ErrorCode_ParameterOutOfRange = 3 /*!< Parameter out of range */, | |
55 | ErrorCode_NotEnoughMemory = 4 /*!< The server hosting Orthanc is running out of memory */, | |
56 | ErrorCode_BadParameterType = 5 /*!< Bad type for a parameter */, | |
57 | ErrorCode_BadSequenceOfCalls = 6 /*!< Bad sequence of calls */, | |
58 | ErrorCode_InexistentItem = 7 /*!< Accessing an inexistent item */, | |
59 | ErrorCode_BadRequest = 8 /*!< Bad request */, | |
60 | ErrorCode_NetworkProtocol = 9 /*!< Error in the network protocol */, | |
61 | ErrorCode_SystemCommand = 10 /*!< Error while calling a system command */, | |
62 | ErrorCode_Database = 11 /*!< Error with the database engine */, | |
63 | ErrorCode_UriSyntax = 12 /*!< Badly formatted URI */, | |
64 | ErrorCode_InexistentFile = 13 /*!< Inexistent file */, | |
65 | ErrorCode_CannotWriteFile = 14 /*!< Cannot write to file */, | |
66 | ErrorCode_BadFileFormat = 15 /*!< Bad file format */, | |
67 | ErrorCode_Timeout = 16 /*!< Timeout */, | |
68 | ErrorCode_UnknownResource = 17 /*!< Unknown resource */, | |
69 | ErrorCode_IncompatibleDatabaseVersion = 18 /*!< Incompatible version of the database */, | |
70 | ErrorCode_FullStorage = 19 /*!< The file storage is full */, | |
71 | ErrorCode_CorruptedFile = 20 /*!< Corrupted file (e.g. inconsistent MD5 hash) */, | |
72 | ErrorCode_InexistentTag = 21 /*!< Inexistent tag */, | |
73 | ErrorCode_ReadOnly = 22 /*!< Cannot modify a read-only data structure */, | |
74 | ErrorCode_IncompatibleImageFormat = 23 /*!< Incompatible format of the images */, | |
75 | ErrorCode_IncompatibleImageSize = 24 /*!< Incompatible size of the images */, | |
76 | ErrorCode_SharedLibrary = 25 /*!< Error while using a shared library (plugin) */, | |
77 | ErrorCode_UnknownPluginService = 26 /*!< Plugin invoking an unknown service */, | |
78 | ErrorCode_UnknownDicomTag = 27 /*!< Unknown DICOM tag */, | |
79 | ErrorCode_BadJson = 28 /*!< Cannot parse a JSON document */, | |
80 | ErrorCode_Unauthorized = 29 /*!< Bad credentials were provided to an HTTP request */, | |
81 | ErrorCode_BadFont = 30 /*!< Badly formatted font file */, | |
82 | ErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, | |
83 | ErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, | |
84 | ErrorCode_EmptyRequest = 33 /*!< The request is empty */, | |
85 | ErrorCode_NotAcceptable = 34 /*!< Cannot send a response which is acceptable according to the Accept HTTP header */, | |
86 | ErrorCode_NullPointer = 35 /*!< Cannot handle a NULL pointer */, | |
87 | ErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, | |
88 | ErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, | |
89 | ErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */, | |
90 | ErrorCode_SQLiteStatementAlreadyUsed = 1003 /*!< SQLite: This cached statement is already being referred to */, | |
91 | ErrorCode_SQLiteExecute = 1004 /*!< SQLite: Cannot execute a command */, | |
92 | ErrorCode_SQLiteRollbackWithoutTransaction = 1005 /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */, | |
93 | ErrorCode_SQLiteCommitWithoutTransaction = 1006 /*!< SQLite: Committing a nonexistent transaction */, | |
94 | ErrorCode_SQLiteRegisterFunction = 1007 /*!< SQLite: Unable to register a function */, | |
95 | ErrorCode_SQLiteFlush = 1008 /*!< SQLite: Unable to flush the database */, | |
96 | ErrorCode_SQLiteCannotRun = 1009 /*!< SQLite: Cannot run a cached statement */, | |
97 | ErrorCode_SQLiteCannotStep = 1010 /*!< SQLite: Cannot step over a cached statement */, | |
98 | ErrorCode_SQLiteBindOutOfRange = 1011 /*!< SQLite: Bing a value while out of range (serious error) */, | |
99 | ErrorCode_SQLitePrepareStatement = 1012 /*!< SQLite: Cannot prepare a cached statement */, | |
100 | ErrorCode_SQLiteTransactionAlreadyStarted = 1013 /*!< SQLite: Beginning the same transaction twice */, | |
101 | ErrorCode_SQLiteTransactionCommit = 1014 /*!< SQLite: Failure when committing the transaction */, | |
102 | ErrorCode_SQLiteTransactionBegin = 1015 /*!< SQLite: Cannot start a transaction */, | |
103 | ErrorCode_DirectoryOverFile = 2000 /*!< The directory to be created is already occupied by a regular file */, | |
104 | ErrorCode_FileStorageCannotWrite = 2001 /*!< Unable to create a subdirectory or a file in the file storage */, | |
105 | ErrorCode_DirectoryExpected = 2002 /*!< The specified path does not point to a directory */, | |
106 | ErrorCode_HttpPortInUse = 2003 /*!< The TCP port of the HTTP server is privileged or already in use */, | |
107 | ErrorCode_DicomPortInUse = 2004 /*!< The TCP port of the DICOM server is privileged or already in use */, | |
108 | ErrorCode_BadHttpStatusInRest = 2005 /*!< This HTTP status is not allowed in a REST API */, | |
109 | ErrorCode_RegularFileExpected = 2006 /*!< The specified path does not point to a regular file */, | |
110 | ErrorCode_PathToExecutable = 2007 /*!< Unable to get the path to the executable */, | |
111 | ErrorCode_MakeDirectory = 2008 /*!< Cannot create a directory */, | |
112 | ErrorCode_BadApplicationEntityTitle = 2009 /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */, | |
113 | ErrorCode_NoCFindHandler = 2010 /*!< No request handler factory for DICOM C-FIND SCP */, | |
114 | ErrorCode_NoCMoveHandler = 2011 /*!< No request handler factory for DICOM C-MOVE SCP */, | |
115 | ErrorCode_NoCStoreHandler = 2012 /*!< No request handler factory for DICOM C-STORE SCP */, | |
116 | ErrorCode_NoApplicationEntityFilter = 2013 /*!< No application entity filter */, | |
117 | ErrorCode_NoSopClassOrInstance = 2014 /*!< DicomUserConnection: Unable to find the SOP class and instance */, | |
118 | ErrorCode_NoPresentationContext = 2015 /*!< DicomUserConnection: No acceptable presentation context for modality */, | |
119 | ErrorCode_DicomFindUnavailable = 2016 /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */, | |
120 | ErrorCode_DicomMoveUnavailable = 2017 /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */, | |
121 | ErrorCode_CannotStoreInstance = 2018 /*!< Cannot store an instance */, | |
122 | ErrorCode_CreateDicomNotString = 2019 /*!< Only string values are supported when creating DICOM instances */, | |
123 | ErrorCode_CreateDicomOverrideTag = 2020 /*!< Trying to override a value inherited from a parent module */, | |
124 | ErrorCode_CreateDicomUseContent = 2021 /*!< Use \"Content\" to inject an image into a new DICOM instance */, | |
125 | ErrorCode_CreateDicomNoPayload = 2022 /*!< No payload is present for one instance in the series */, | |
126 | ErrorCode_CreateDicomUseDataUriScheme = 2023 /*!< The payload of the DICOM instance must be specified according to Data URI scheme */, | |
127 | ErrorCode_CreateDicomBadParent = 2024 /*!< Trying to attach a new DICOM instance to an inexistent resource */, | |
128 | ErrorCode_CreateDicomParentIsInstance = 2025 /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */, | |
129 | ErrorCode_CreateDicomParentEncoding = 2026 /*!< Unable to get the encoding of the parent resource */, | |
130 | ErrorCode_UnknownModality = 2027 /*!< Unknown modality */, | |
131 | ErrorCode_BadJobOrdering = 2028 /*!< Bad ordering of filters in a job */, | |
132 | ErrorCode_JsonToLuaTable = 2029 /*!< Cannot convert the given JSON object to a Lua table */, | |
133 | ErrorCode_CannotCreateLua = 2030 /*!< Cannot create the Lua context */, | |
134 | ErrorCode_CannotExecuteLua = 2031 /*!< Cannot execute a Lua command */, | |
135 | ErrorCode_LuaAlreadyExecuted = 2032 /*!< Arguments cannot be pushed after the Lua function is executed */, | |
136 | ErrorCode_LuaBadOutput = 2033 /*!< The Lua function does not give the expected number of outputs */, | |
137 | ErrorCode_NotLuaPredicate = 2034 /*!< The Lua function is not a predicate (only true/false outputs allowed) */, | |
138 | ErrorCode_LuaReturnsNoString = 2035 /*!< The Lua function does not return a string */, | |
139 | ErrorCode_StorageAreaAlreadyRegistered = 2036 /*!< Another plugin has already registered a custom storage area */, | |
140 | ErrorCode_DatabaseBackendAlreadyRegistered = 2037 /*!< Another plugin has already registered a custom database back-end */, | |
141 | ErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, | |
142 | ErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, | |
143 | ErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, | |
144 | ErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, | |
145 | ErrorCode_AlreadyExistingTag = 2042 /*!< Cannot override the value of a tag that already exists */, | |
146 | ErrorCode_START_PLUGINS = 1000000 | |
147 | }; | |
148 | ||
149 | enum LogLevel | |
150 | { | |
151 | LogLevel_Error, | |
152 | LogLevel_Warning, | |
153 | LogLevel_Info, | |
154 | LogLevel_Trace | |
155 | }; | |
156 | ||
157 | ||
158 | /** | |
159 | * {summary}{The memory layout of the pixels (resp. voxels) of a 2D (resp. 3D) image.} | |
160 | **/ | |
161 | enum PixelFormat | |
162 | { | |
163 | /** | |
164 | * {summary}{Color image in RGB24 format.} | |
165 | * {description}{This format describes a color image. The pixels are stored in 3 | |
166 | * consecutive bytes. The memory layout is RGB.} | |
167 | **/ | |
168 | PixelFormat_RGB24 = 1, | |
169 | ||
170 | /** | |
171 | * {summary}{Color image in RGBA32 format.} | |
172 | * {description}{This format describes a color image. The pixels are stored in 4 | |
173 | * consecutive bytes. The memory layout is RGBA.} | |
174 | **/ | |
175 | PixelFormat_RGBA32 = 2, | |
176 | ||
177 | /** | |
178 | * {summary}{Graylevel 8bpp image.} | |
179 | * {description}{The image is graylevel. Each pixel is unsigned and stored in one byte.} | |
180 | **/ | |
181 | PixelFormat_Grayscale8 = 3, | |
182 | ||
183 | /** | |
184 | * {summary}{Graylevel, unsigned 16bpp image.} | |
185 | * {description}{The image is graylevel. Each pixel is unsigned and stored in two bytes.} | |
186 | **/ | |
187 | PixelFormat_Grayscale16 = 4, | |
188 | ||
189 | /** | |
190 | * {summary}{Graylevel, signed 16bpp image.} | |
191 | * {description}{The image is graylevel. Each pixel is signed and stored in two bytes.} | |
192 | **/ | |
193 | PixelFormat_SignedGrayscale16 = 5, | |
194 | ||
195 | /** | |
196 | * {summary}{Graylevel, floating-point image.} | |
197 | * {description}{The image is graylevel. Each pixel is floating-point and stored in 4 bytes.} | |
198 | **/ | |
199 | PixelFormat_Float32 = 6, | |
200 | ||
201 | // This is the memory layout for Cairo | |
202 | PixelFormat_BGRA32 = 7 | |
203 | }; | |
204 | ||
205 | ||
206 | /** | |
207 | * {summary}{The extraction mode specifies the way the values of the pixels are scaled when downloading a 2D image.} | |
208 | **/ | |
209 | enum ImageExtractionMode | |
210 | { | |
211 | /** | |
212 | * {summary}{Rescaled to 8bpp.} | |
213 | * {description}{The minimum value of the image is set to 0, and its maximum value is set to 255.} | |
214 | **/ | |
215 | ImageExtractionMode_Preview = 1, | |
216 | ||
217 | /** | |
218 | * {summary}{Truncation to the [0, 255] range.} | |
219 | **/ | |
220 | ImageExtractionMode_UInt8 = 2, | |
221 | ||
222 | /** | |
223 | * {summary}{Truncation to the [0, 65535] range.} | |
224 | **/ | |
225 | ImageExtractionMode_UInt16 = 3, | |
226 | ||
227 | /** | |
228 | * {summary}{Truncation to the [-32768, 32767] range.} | |
229 | **/ | |
230 | ImageExtractionMode_Int16 = 4 | |
231 | }; | |
232 | ||
233 | ||
234 | /** | |
235 | * Most common, non-joke and non-experimental HTTP status codes | |
236 | * http://en.wikipedia.org/wiki/List_of_HTTP_status_codes | |
237 | **/ | |
238 | enum HttpStatus | |
239 | { | |
240 | HttpStatus_None = -1, | |
241 | ||
242 | // 1xx Informational | |
243 | HttpStatus_100_Continue = 100, | |
244 | HttpStatus_101_SwitchingProtocols = 101, | |
245 | HttpStatus_102_Processing = 102, | |
246 | ||
247 | // 2xx Success | |
248 | HttpStatus_200_Ok = 200, | |
249 | HttpStatus_201_Created = 201, | |
250 | HttpStatus_202_Accepted = 202, | |
251 | HttpStatus_203_NonAuthoritativeInformation = 203, | |
252 | HttpStatus_204_NoContent = 204, | |
253 | HttpStatus_205_ResetContent = 205, | |
254 | HttpStatus_206_PartialContent = 206, | |
255 | HttpStatus_207_MultiStatus = 207, | |
256 | HttpStatus_208_AlreadyReported = 208, | |
257 | HttpStatus_226_IMUsed = 226, | |
258 | ||
259 | // 3xx Redirection | |
260 | HttpStatus_300_MultipleChoices = 300, | |
261 | HttpStatus_301_MovedPermanently = 301, | |
262 | HttpStatus_302_Found = 302, | |
263 | HttpStatus_303_SeeOther = 303, | |
264 | HttpStatus_304_NotModified = 304, | |
265 | HttpStatus_305_UseProxy = 305, | |
266 | HttpStatus_307_TemporaryRedirect = 307, | |
267 | ||
268 | // 4xx Client Error | |
269 | HttpStatus_400_BadRequest = 400, | |
270 | HttpStatus_401_Unauthorized = 401, | |
271 | HttpStatus_402_PaymentRequired = 402, | |
272 | HttpStatus_403_Forbidden = 403, | |
273 | HttpStatus_404_NotFound = 404, | |
274 | HttpStatus_405_MethodNotAllowed = 405, | |
275 | HttpStatus_406_NotAcceptable = 406, | |
276 | HttpStatus_407_ProxyAuthenticationRequired = 407, | |
277 | HttpStatus_408_RequestTimeout = 408, | |
278 | HttpStatus_409_Conflict = 409, | |
279 | HttpStatus_410_Gone = 410, | |
280 | HttpStatus_411_LengthRequired = 411, | |
281 | HttpStatus_412_PreconditionFailed = 412, | |
282 | HttpStatus_413_RequestEntityTooLarge = 413, | |
283 | HttpStatus_414_RequestUriTooLong = 414, | |
284 | HttpStatus_415_UnsupportedMediaType = 415, | |
285 | HttpStatus_416_RequestedRangeNotSatisfiable = 416, | |
286 | HttpStatus_417_ExpectationFailed = 417, | |
287 | HttpStatus_422_UnprocessableEntity = 422, | |
288 | HttpStatus_423_Locked = 423, | |
289 | HttpStatus_424_FailedDependency = 424, | |
290 | HttpStatus_426_UpgradeRequired = 426, | |
291 | ||
292 | // 5xx Server Error | |
293 | HttpStatus_500_InternalServerError = 500, | |
294 | HttpStatus_501_NotImplemented = 501, | |
295 | HttpStatus_502_BadGateway = 502, | |
296 | HttpStatus_503_ServiceUnavailable = 503, | |
297 | HttpStatus_504_GatewayTimeout = 504, | |
298 | HttpStatus_505_HttpVersionNotSupported = 505, | |
299 | HttpStatus_506_VariantAlsoNegotiates = 506, | |
300 | HttpStatus_507_InsufficientStorage = 507, | |
301 | HttpStatus_509_BandwidthLimitExceeded = 509, | |
302 | HttpStatus_510_NotExtended = 510 | |
303 | }; | |
304 | ||
305 | ||
306 | enum HttpMethod | |
307 | { | |
308 | HttpMethod_Get = 0, | |
309 | HttpMethod_Post = 1, | |
310 | HttpMethod_Delete = 2, | |
311 | HttpMethod_Put = 3 | |
312 | }; | |
313 | ||
314 | ||
315 | enum ImageFormat | |
316 | { | |
317 | ImageFormat_Png = 1 | |
318 | }; | |
319 | ||
320 | ||
321 | // https://en.wikipedia.org/wiki/HTTP_compression | |
322 | enum HttpCompression | |
323 | { | |
324 | HttpCompression_None, | |
325 | HttpCompression_Deflate, | |
326 | HttpCompression_Gzip | |
327 | }; | |
328 | ||
329 | ||
330 | // Specific Character Sets | |
331 | // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2 | |
332 | enum Encoding | |
333 | { | |
334 | Encoding_Ascii, | |
335 | Encoding_Utf8, | |
336 | Encoding_Latin1, | |
337 | Encoding_Latin2, | |
338 | Encoding_Latin3, | |
339 | Encoding_Latin4, | |
340 | Encoding_Latin5, // Turkish | |
341 | Encoding_Cyrillic, | |
342 | Encoding_Windows1251, // Windows-1251 (commonly used for Cyrillic) | |
343 | Encoding_Arabic, | |
344 | Encoding_Greek, | |
345 | Encoding_Hebrew, | |
346 | Encoding_Thai, // TIS 620-2533 | |
347 | Encoding_Japanese, // JIS X 0201 (Shift JIS): Katakana | |
348 | Encoding_Chinese // GB18030 - Chinese simplified | |
349 | //Encoding_JapaneseKanji, // Multibyte - JIS X 0208: Kanji | |
350 | //Encoding_JapaneseSupplementaryKanji, // Multibyte - JIS X 0212: Supplementary Kanji set | |
351 | //Encoding_Korean, // Multibyte - KS X 1001: Hangul and Hanja | |
352 | }; | |
353 | ||
354 | ||
355 | // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.7.6.3.1.2 | |
356 | enum PhotometricInterpretation | |
357 | { | |
358 | PhotometricInterpretation_ARGB, // Retired | |
359 | PhotometricInterpretation_CMYK, // Retired | |
360 | PhotometricInterpretation_HSV, // Retired | |
361 | PhotometricInterpretation_Monochrome1, | |
362 | PhotometricInterpretation_Monochrome2, | |
363 | PhotometricInterpretation_Palette, | |
364 | PhotometricInterpretation_RGB, | |
365 | PhotometricInterpretation_YBRFull, | |
366 | PhotometricInterpretation_YBRFull422, | |
367 | PhotometricInterpretation_YBRPartial420, | |
368 | PhotometricInterpretation_YBRPartial422, | |
369 | PhotometricInterpretation_YBR_ICT, | |
370 | PhotometricInterpretation_YBR_RCT, | |
371 | PhotometricInterpretation_Unknown | |
372 | }; | |
373 | ||
374 | enum DicomModule | |
375 | { | |
376 | DicomModule_Patient, | |
377 | DicomModule_Study, | |
378 | DicomModule_Series, | |
379 | DicomModule_Instance, | |
380 | DicomModule_Image | |
381 | }; | |
382 | ||
383 | enum RequestOrigin | |
384 | { | |
385 | RequestOrigin_Unknown, | |
386 | RequestOrigin_DicomProtocol, | |
387 | RequestOrigin_RestApi, | |
388 | RequestOrigin_Plugins, | |
389 | RequestOrigin_Lua | |
390 | }; | |
391 | ||
392 | enum ServerBarrierEvent | |
393 | { | |
394 | ServerBarrierEvent_Stop, | |
395 | ServerBarrierEvent_Reload // SIGHUP signal: reload configuration file | |
396 | }; | |
397 | ||
398 | enum FileMode | |
399 | { | |
400 | FileMode_ReadBinary, | |
401 | FileMode_WriteBinary | |
402 | }; | |
403 | ||
404 | /** | |
405 | * The value representations Orthanc knows about. They correspond to | |
406 | * the DICOM 2016b version of the standard. | |
407 | * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html | |
408 | **/ | |
409 | enum ValueRepresentation | |
410 | { | |
411 | ValueRepresentation_ApplicationEntity = 1, // AE | |
412 | ValueRepresentation_AgeString = 2, // AS | |
413 | ValueRepresentation_AttributeTag = 3, // AT (2 x uint16_t) | |
414 | ValueRepresentation_CodeString = 4, // CS | |
415 | ValueRepresentation_Date = 5, // DA | |
416 | ValueRepresentation_DecimalString = 6, // DS | |
417 | ValueRepresentation_DateTime = 7, // DT | |
418 | ValueRepresentation_FloatingPointSingle = 8, // FL (float) | |
419 | ValueRepresentation_FloatingPointDouble = 9, // FD (double) | |
420 | ValueRepresentation_IntegerString = 10, // IS | |
421 | ValueRepresentation_LongString = 11, // LO | |
422 | ValueRepresentation_LongText = 12, // LT | |
423 | ValueRepresentation_OtherByte = 13, // OB | |
424 | ValueRepresentation_OtherDouble = 14, // OD | |
425 | ValueRepresentation_OtherFloat = 15, // OF | |
426 | ValueRepresentation_OtherLong = 16, // OL | |
427 | ValueRepresentation_OtherWord = 17, // OW | |
428 | ValueRepresentation_PersonName = 18, // PN | |
429 | ValueRepresentation_ShortString = 19, // SH | |
430 | ValueRepresentation_SignedLong = 20, // SL (int32_t) | |
431 | ValueRepresentation_Sequence = 21, // SQ | |
432 | ValueRepresentation_SignedShort = 22, // SS (int16_t) | |
433 | ValueRepresentation_ShortText = 23, // ST | |
434 | ValueRepresentation_Time = 24, // TM | |
435 | ValueRepresentation_UnlimitedCharacters = 25, // UC | |
436 | ValueRepresentation_UniqueIdentifier = 26, // UI (UID) | |
437 | ValueRepresentation_UnsignedLong = 27, // UL (uint32_t) | |
438 | ValueRepresentation_Unknown = 28, // UN | |
439 | ValueRepresentation_UniversalResource = 29, // UR (URI or URL) | |
440 | ValueRepresentation_UnsignedShort = 30, // US (uint16_t) | |
441 | ValueRepresentation_UnlimitedText = 31, // UT | |
442 | ValueRepresentation_NotSupported // Not supported by Orthanc, or tag not in dictionary | |
443 | }; | |
444 | ||
445 | ||
446 | /** | |
447 | * WARNING: Do not change the explicit values in the enumerations | |
448 | * below this point. This would result in incompatible databases | |
449 | * between versions of Orthanc! | |
450 | **/ | |
451 | ||
452 | enum CompressionType | |
453 | { | |
454 | /** | |
455 | * Buffer/file that is stored as-is, in a raw fashion, without | |
456 | * compression. | |
457 | **/ | |
458 | CompressionType_None = 1, | |
459 | ||
460 | /** | |
461 | * Buffer that is compressed using the "deflate" algorithm (RFC | |
462 | * 1951), wrapped inside the zlib data format (RFC 1950), prefixed | |
463 | * with a "uint64_t" (8 bytes) that encodes the size of the | |
464 | * uncompressed buffer. If the compressed buffer is empty, its | |
465 | * represents an empty uncompressed buffer. This format is | |
466 | * internal to Orthanc. If the 8 first bytes are skipped AND the | |
467 | * buffer is non-empty, the buffer is compatible with the | |
468 | * "deflate" HTTP compression. | |
469 | **/ | |
470 | CompressionType_ZlibWithSize = 2 | |
471 | }; | |
472 | ||
473 | enum FileContentType | |
474 | { | |
475 | // If you add a value below, insert it in "PluginStorageArea" in | |
476 | // the file "Plugins/Engine/OrthancPlugins.cpp" | |
477 | FileContentType_Unknown = 0, | |
478 | FileContentType_Dicom = 1, | |
479 | FileContentType_DicomAsJson = 2, | |
480 | ||
481 | // Make sure that the value "65535" can be stored into this enumeration | |
482 | FileContentType_StartUser = 1024, | |
483 | FileContentType_EndUser = 65535 | |
484 | }; | |
485 | ||
486 | enum ResourceType | |
487 | { | |
488 | ResourceType_Patient = 1, | |
489 | ResourceType_Study = 2, | |
490 | ResourceType_Series = 3, | |
491 | ResourceType_Instance = 4 | |
492 | }; | |
493 | ||
494 | ||
495 | const char* EnumerationToString(ErrorCode code); | |
496 | ||
497 | const char* EnumerationToString(HttpMethod method); | |
498 | ||
499 | const char* EnumerationToString(HttpStatus status); | |
500 | ||
501 | const char* EnumerationToString(ResourceType type); | |
502 | ||
503 | const char* EnumerationToString(ImageFormat format); | |
504 | ||
505 | const char* EnumerationToString(Encoding encoding); | |
506 | ||
507 | const char* EnumerationToString(PhotometricInterpretation photometric); | |
508 | ||
509 | const char* EnumerationToString(LogLevel level); | |
510 | ||
511 | const char* EnumerationToString(RequestOrigin origin); | |
512 | ||
513 | const char* EnumerationToString(PixelFormat format); | |
514 | ||
515 | Encoding StringToEncoding(const char* encoding); | |
516 | ||
517 | ResourceType StringToResourceType(const char* type); | |
518 | ||
519 | ImageFormat StringToImageFormat(const char* format); | |
520 | ||
521 | LogLevel StringToLogLevel(const char* level); | |
522 | ||
523 | ValueRepresentation StringToValueRepresentation(const std::string& vr, | |
524 | bool throwIfUnsupported); | |
525 | ||
526 | PhotometricInterpretation StringToPhotometricInterpretation(const char* value); | |
527 | ||
528 | unsigned int GetBytesPerPixel(PixelFormat format); | |
529 | ||
530 | bool GetDicomEncoding(Encoding& encoding, | |
531 | const char* specificCharacterSet); | |
532 | ||
533 | ResourceType GetChildResourceType(ResourceType type); | |
534 | ||
535 | ResourceType GetParentResourceType(ResourceType type); | |
536 | ||
537 | DicomModule GetModule(ResourceType type); | |
538 | ||
539 | const char* GetDicomSpecificCharacterSet(Encoding encoding); | |
540 | ||
541 | HttpStatus ConvertErrorCodeToHttpStatus(ErrorCode error); | |
542 | ||
543 | bool IsUserContentType(FileContentType type); | |
544 | ||
545 | bool IsBinaryValueRepresentation(ValueRepresentation vr); | |
546 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include <iostream> | |
36 | ||
37 | #if !defined(ORTHANC_ENABLE_LOGGING) | |
38 | # error The macro ORTHANC_ENABLE_LOGGING must be defined | |
39 | #endif | |
40 | ||
41 | #if !defined(ORTHANC_ENABLE_LOGGING_PLUGIN) | |
42 | # if ORTHANC_ENABLE_LOGGING == 1 | |
43 | # error The macro ORTHANC_ENABLE_LOGGING_PLUGIN must be defined | |
44 | # else | |
45 | # define ORTHANC_ENABLE_LOGGING_PLUGIN 0 | |
46 | # endif | |
47 | #endif | |
48 | ||
49 | #if ORTHANC_ENABLE_LOGGING_PLUGIN == 1 | |
50 | # include <orthanc/OrthancCPlugin.h> | |
51 | #endif | |
52 | ||
53 | namespace Orthanc | |
54 | { | |
55 | namespace Logging | |
56 | { | |
57 | #if ORTHANC_ENABLE_LOGGING_PLUGIN == 1 | |
58 | void Initialize(OrthancPluginContext* context); | |
59 | #else | |
60 | void Initialize(); | |
61 | #endif | |
62 | ||
63 | void Finalize(); | |
64 | ||
65 | void Reset(); | |
66 | ||
67 | void Flush(); | |
68 | ||
69 | void EnableInfoLevel(bool enabled); | |
70 | ||
71 | void EnableTraceLevel(bool enabled); | |
72 | ||
73 | void SetTargetFile(const std::string& path); | |
74 | ||
75 | void SetTargetFolder(const std::string& path); | |
76 | ||
77 | struct NullStream : public std::ostream | |
78 | { | |
79 | NullStream() : | |
80 | std::ios(0), | |
81 | std::ostream(0) | |
82 | { | |
83 | } | |
84 | ||
85 | std::ostream& operator<< (const std::string& message) | |
86 | { | |
87 | return *this; | |
88 | } | |
89 | ||
90 | // This overload fixes build problems with Visual Studio 2015 | |
91 | std::ostream& operator<< (const char* message) | |
92 | { | |
93 | return *this; | |
94 | } | |
95 | }; | |
96 | } | |
97 | } | |
98 | ||
99 | ||
100 | #if ORTHANC_ENABLE_LOGGING != 1 | |
101 | ||
102 | # define LOG(level) ::Orthanc::Logging::NullStream() | |
103 | # define VLOG(level) ::Orthanc::Logging::NullStream() | |
104 | ||
105 | ||
106 | #elif ORTHANC_ENABLE_LOGGING_PLUGIN == 1 | |
107 | ||
108 | # include <boost/noncopyable.hpp> | |
109 | # define LOG(level) ::Orthanc::Logging::InternalLogger(#level, __FILE__, __LINE__) | |
110 | # define VLOG(level) ::Orthanc::Logging::InternalLogger("TRACE", __FILE__, __LINE__) | |
111 | ||
112 | namespace Orthanc | |
113 | { | |
114 | namespace Logging | |
115 | { | |
116 | class InternalLogger : public boost::noncopyable | |
117 | { | |
118 | private: | |
119 | std::string level_; | |
120 | std::string message_; | |
121 | ||
122 | public: | |
123 | InternalLogger(const char* level, | |
124 | const char* file, | |
125 | int line); | |
126 | ||
127 | ~InternalLogger(); | |
128 | ||
129 | InternalLogger& operator<< (const std::string& message); | |
130 | ||
131 | InternalLogger& operator<< (const char* message); | |
132 | ||
133 | InternalLogger& operator<< (int message); | |
134 | }; | |
135 | } | |
136 | } | |
137 | ||
138 | ||
139 | #else /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && ORTHANC_ENABLE_LOGGING == 1 */ | |
140 | ||
141 | # include <boost/thread/mutex.hpp> | |
142 | # define LOG(level) ::Orthanc::Logging::InternalLogger(#level, __FILE__, __LINE__) | |
143 | # define VLOG(level) ::Orthanc::Logging::InternalLogger("TRACE", __FILE__, __LINE__) | |
144 | ||
145 | namespace Orthanc | |
146 | { | |
147 | namespace Logging | |
148 | { | |
149 | class InternalLogger | |
150 | { | |
151 | private: | |
152 | boost::mutex::scoped_lock lock_; | |
153 | NullStream null_; | |
154 | std::ostream* stream_; | |
155 | ||
156 | public: | |
157 | InternalLogger(const char* level, | |
158 | const char* file, | |
159 | int line); | |
160 | ||
161 | ~InternalLogger(); | |
162 | ||
163 | std::ostream& operator<< (const std::string& message) | |
164 | { | |
165 | return (*stream_) << message; | |
166 | } | |
167 | ||
168 | // This overload fixes build problems with Visual Studio 2015 | |
169 | std::ostream& operator<< (const char* message) | |
170 | { | |
171 | return (*stream_) << message; | |
172 | } | |
173 | }; | |
174 | } | |
175 | } | |
176 | ||
177 | #endif // ORTHANC_ENABLE_LOGGING |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include <stdint.h> | |
36 | #include <string> | |
37 | #include "Enumerations.h" | |
38 | ||
39 | namespace Orthanc | |
40 | { | |
41 | class OrthancException | |
42 | { | |
43 | protected: | |
44 | ErrorCode errorCode_; | |
45 | HttpStatus httpStatus_; | |
46 | ||
47 | public: | |
48 | explicit OrthancException(ErrorCode errorCode) : | |
49 | errorCode_(errorCode), | |
50 | httpStatus_(ConvertErrorCodeToHttpStatus(errorCode)) | |
51 | { | |
52 | } | |
53 | ||
54 | OrthancException(ErrorCode errorCode, | |
55 | HttpStatus httpStatus) : | |
56 | errorCode_(errorCode), | |
57 | httpStatus_(httpStatus) | |
58 | { | |
59 | } | |
60 | ||
61 | ErrorCode GetErrorCode() const | |
62 | { | |
63 | return errorCode_; | |
64 | } | |
65 | ||
66 | HttpStatus GetHttpStatus() const | |
67 | { | |
68 | return httpStatus_; | |
69 | } | |
70 | ||
71 | const char* What() const | |
72 | { | |
73 | return EnumerationToString(errorCode_); | |
74 | } | |
75 | }; | |
76 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #if defined(_WIN32) && !defined(NOMINMAX) | |
36 | #define NOMINMAX | |
37 | #endif | |
38 | ||
39 | #if ORTHANC_USE_PRECOMPILED_HEADERS == 1 | |
40 | ||
41 | #include <boost/date_time/posix_time/posix_time.hpp> | |
42 | #include <boost/filesystem.hpp> | |
43 | #include <boost/lexical_cast.hpp> | |
44 | #include <boost/locale.hpp> | |
45 | #include <boost/regex.hpp> | |
46 | #include <boost/thread.hpp> | |
47 | #include <boost/thread/shared_mutex.hpp> | |
48 | ||
49 | #include <json/value.h> | |
50 | ||
51 | #if ORTHANC_ENABLE_PUGIXML == 1 | |
52 | #include <pugixml.hpp> | |
53 | #endif | |
54 | ||
55 | #include "Enumerations.h" | |
56 | #include "Logging.h" | |
57 | #include "OrthancException.h" | |
58 | #include "Toolbox.h" | |
59 | ||
60 | #endif |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "PrecompiledHeaders.h" | |
34 | #include "SystemToolbox.h" | |
35 | ||
36 | ||
37 | #if BOOST_HAS_DATE_TIME == 1 | |
38 | # include <boost/date_time/posix_time/posix_time.hpp> | |
39 | #endif | |
40 | ||
41 | ||
42 | #if defined(_WIN32) | |
43 | # include <windows.h> | |
44 | # include <process.h> // For "_spawnvp()" and "_getpid()" | |
45 | #else | |
46 | # include <unistd.h> // For "execvp()" | |
47 | # include <sys/wait.h> // For "waitpid()" | |
48 | #endif | |
49 | ||
50 | ||
51 | #if defined(__APPLE__) && defined(__MACH__) | |
52 | # include <mach-o/dyld.h> /* _NSGetExecutablePath */ | |
53 | # include <limits.h> /* PATH_MAX */ | |
54 | #endif | |
55 | ||
56 | ||
57 | #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) | |
58 | # include <limits.h> /* PATH_MAX */ | |
59 | # include <signal.h> | |
60 | # include <unistd.h> | |
61 | #endif | |
62 | ||
63 | ||
64 | // Inclusions for UUID | |
65 | // http://stackoverflow.com/a/1626302 | |
66 | ||
67 | extern "C" | |
68 | { | |
69 | #ifdef WIN32 | |
70 | # include <rpc.h> | |
71 | #else | |
72 | # include <uuid/uuid.h> | |
73 | #endif | |
74 | } | |
75 | ||
76 | ||
77 | #include "Logging.h" | |
78 | #include "OrthancException.h" | |
79 | #include "Toolbox.h" | |
80 | ||
81 | #include <boost/filesystem.hpp> | |
82 | #include <boost/filesystem/fstream.hpp> | |
83 | ||
84 | ||
85 | namespace Orthanc | |
86 | { | |
87 | static bool finish_; | |
88 | static ServerBarrierEvent barrierEvent_; | |
89 | ||
90 | #if defined(_WIN32) | |
91 | static BOOL WINAPI ConsoleControlHandler(DWORD dwCtrlType) | |
92 | { | |
93 | // http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx | |
94 | finish_ = true; | |
95 | return true; | |
96 | } | |
97 | #else | |
98 | static void SignalHandler(int signal) | |
99 | { | |
100 | if (signal == SIGHUP) | |
101 | { | |
102 | barrierEvent_ = ServerBarrierEvent_Reload; | |
103 | } | |
104 | ||
105 | finish_ = true; | |
106 | } | |
107 | #endif | |
108 | ||
109 | ||
110 | static ServerBarrierEvent ServerBarrierInternal(const bool* stopFlag) | |
111 | { | |
112 | #if defined(_WIN32) | |
113 | SetConsoleCtrlHandler(ConsoleControlHandler, true); | |
114 | #else | |
115 | signal(SIGINT, SignalHandler); | |
116 | signal(SIGQUIT, SignalHandler); | |
117 | signal(SIGTERM, SignalHandler); | |
118 | signal(SIGHUP, SignalHandler); | |
119 | #endif | |
120 | ||
121 | // Active loop that awakens every 100ms | |
122 | finish_ = false; | |
123 | barrierEvent_ = ServerBarrierEvent_Stop; | |
124 | while (!(*stopFlag || finish_)) | |
125 | { | |
126 | SystemToolbox::USleep(100 * 1000); | |
127 | } | |
128 | ||
129 | #if defined(_WIN32) | |
130 | SetConsoleCtrlHandler(ConsoleControlHandler, false); | |
131 | #else | |
132 | signal(SIGINT, NULL); | |
133 | signal(SIGQUIT, NULL); | |
134 | signal(SIGTERM, NULL); | |
135 | signal(SIGHUP, NULL); | |
136 | #endif | |
137 | ||
138 | return barrierEvent_; | |
139 | } | |
140 | ||
141 | ||
142 | ServerBarrierEvent SystemToolbox::ServerBarrier(const bool& stopFlag) | |
143 | { | |
144 | return ServerBarrierInternal(&stopFlag); | |
145 | } | |
146 | ||
147 | ||
148 | ServerBarrierEvent SystemToolbox::ServerBarrier() | |
149 | { | |
150 | const bool stopFlag = false; | |
151 | return ServerBarrierInternal(&stopFlag); | |
152 | } | |
153 | ||
154 | ||
155 | void SystemToolbox::USleep(uint64_t microSeconds) | |
156 | { | |
157 | #if defined(_WIN32) | |
158 | ::Sleep(static_cast<DWORD>(microSeconds / static_cast<uint64_t>(1000))); | |
159 | #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__native_client__) | |
160 | usleep(microSeconds); | |
161 | #else | |
162 | #error Support your platform here | |
163 | #endif | |
164 | } | |
165 | ||
166 | ||
167 | static std::streamsize GetStreamSize(std::istream& f) | |
168 | { | |
169 | // http://www.cplusplus.com/reference/iostream/istream/tellg/ | |
170 | f.seekg(0, std::ios::end); | |
171 | std::streamsize size = f.tellg(); | |
172 | f.seekg(0, std::ios::beg); | |
173 | ||
174 | return size; | |
175 | } | |
176 | ||
177 | ||
178 | void SystemToolbox::ReadFile(std::string& content, | |
179 | const std::string& path) | |
180 | { | |
181 | if (!IsRegularFile(path)) | |
182 | { | |
183 | LOG(ERROR) << std::string("The path does not point to a regular file: ") << path; | |
184 | throw OrthancException(ErrorCode_RegularFileExpected); | |
185 | } | |
186 | ||
187 | boost::filesystem::ifstream f; | |
188 | f.open(path, std::ifstream::in | std::ifstream::binary); | |
189 | if (!f.good()) | |
190 | { | |
191 | throw OrthancException(ErrorCode_InexistentFile); | |
192 | } | |
193 | ||
194 | std::streamsize size = GetStreamSize(f); | |
195 | content.resize(size); | |
196 | if (size != 0) | |
197 | { | |
198 | f.read(reinterpret_cast<char*>(&content[0]), size); | |
199 | } | |
200 | ||
201 | f.close(); | |
202 | } | |
203 | ||
204 | ||
205 | bool SystemToolbox::ReadHeader(std::string& header, | |
206 | const std::string& path, | |
207 | size_t headerSize) | |
208 | { | |
209 | if (!IsRegularFile(path)) | |
210 | { | |
211 | LOG(ERROR) << std::string("The path does not point to a regular file: ") << path; | |
212 | throw OrthancException(ErrorCode_RegularFileExpected); | |
213 | } | |
214 | ||
215 | boost::filesystem::ifstream f; | |
216 | f.open(path, std::ifstream::in | std::ifstream::binary); | |
217 | if (!f.good()) | |
218 | { | |
219 | throw OrthancException(ErrorCode_InexistentFile); | |
220 | } | |
221 | ||
222 | bool full = true; | |
223 | ||
224 | { | |
225 | std::streamsize size = GetStreamSize(f); | |
226 | if (size <= 0) | |
227 | { | |
228 | headerSize = 0; | |
229 | full = false; | |
230 | } | |
231 | else if (static_cast<size_t>(size) < headerSize) | |
232 | { | |
233 | headerSize = size; // Truncate to the size of the file | |
234 | full = false; | |
235 | } | |
236 | } | |
237 | ||
238 | header.resize(headerSize); | |
239 | if (headerSize != 0) | |
240 | { | |
241 | f.read(reinterpret_cast<char*>(&header[0]), headerSize); | |
242 | } | |
243 | ||
244 | f.close(); | |
245 | ||
246 | return full; | |
247 | } | |
248 | ||
249 | ||
250 | void SystemToolbox::WriteFile(const void* content, | |
251 | size_t size, | |
252 | const std::string& path) | |
253 | { | |
254 | boost::filesystem::ofstream f; | |
255 | f.open(path, std::ofstream::out | std::ofstream::binary); | |
256 | if (!f.good()) | |
257 | { | |
258 | throw OrthancException(ErrorCode_CannotWriteFile); | |
259 | } | |
260 | ||
261 | if (size != 0) | |
262 | { | |
263 | f.write(reinterpret_cast<const char*>(content), size); | |
264 | ||
265 | if (!f.good()) | |
266 | { | |
267 | f.close(); | |
268 | throw OrthancException(ErrorCode_FileStorageCannotWrite); | |
269 | } | |
270 | } | |
271 | ||
272 | f.close(); | |
273 | } | |
274 | ||
275 | ||
276 | void SystemToolbox::WriteFile(const std::string& content, | |
277 | const std::string& path) | |
278 | { | |
279 | WriteFile(content.size() > 0 ? content.c_str() : NULL, | |
280 | content.size(), path); | |
281 | } | |
282 | ||
283 | ||
284 | void SystemToolbox::RemoveFile(const std::string& path) | |
285 | { | |
286 | if (boost::filesystem::exists(path)) | |
287 | { | |
288 | if (IsRegularFile(path)) | |
289 | { | |
290 | boost::filesystem::remove(path); | |
291 | } | |
292 | else | |
293 | { | |
294 | throw OrthancException(ErrorCode_RegularFileExpected); | |
295 | } | |
296 | } | |
297 | } | |
298 | ||
299 | ||
300 | uint64_t SystemToolbox::GetFileSize(const std::string& path) | |
301 | { | |
302 | try | |
303 | { | |
304 | return static_cast<uint64_t>(boost::filesystem::file_size(path)); | |
305 | } | |
306 | catch (boost::filesystem::filesystem_error&) | |
307 | { | |
308 | throw OrthancException(ErrorCode_InexistentFile); | |
309 | } | |
310 | } | |
311 | ||
312 | ||
313 | void SystemToolbox::MakeDirectory(const std::string& path) | |
314 | { | |
315 | if (boost::filesystem::exists(path)) | |
316 | { | |
317 | if (!boost::filesystem::is_directory(path)) | |
318 | { | |
319 | throw OrthancException(ErrorCode_DirectoryOverFile); | |
320 | } | |
321 | } | |
322 | else | |
323 | { | |
324 | if (!boost::filesystem::create_directories(path)) | |
325 | { | |
326 | throw OrthancException(ErrorCode_MakeDirectory); | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
331 | ||
332 | bool SystemToolbox::IsExistingFile(const std::string& path) | |
333 | { | |
334 | return boost::filesystem::exists(path); | |
335 | } | |
336 | ||
337 | ||
338 | #if defined(_WIN32) | |
339 | static std::string GetPathToExecutableInternal() | |
340 | { | |
341 | // Yes, this is ugly, but there is no simple way to get the | |
342 | // required buffer size, so we use a big constant | |
343 | std::vector<char> buffer(32768); | |
344 | /*int bytes =*/ GetModuleFileNameA(NULL, &buffer[0], static_cast<DWORD>(buffer.size() - 1)); | |
345 | return std::string(&buffer[0]); | |
346 | } | |
347 | ||
348 | #elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__) | |
349 | static std::string GetPathToExecutableInternal() | |
350 | { | |
351 | std::vector<char> buffer(PATH_MAX + 1); | |
352 | ssize_t bytes = readlink("/proc/self/exe", &buffer[0], buffer.size() - 1); | |
353 | if (bytes == 0) | |
354 | { | |
355 | throw OrthancException(ErrorCode_PathToExecutable); | |
356 | } | |
357 | ||
358 | return std::string(&buffer[0]); | |
359 | } | |
360 | ||
361 | #elif defined(__APPLE__) && defined(__MACH__) | |
362 | static std::string GetPathToExecutableInternal() | |
363 | { | |
364 | char pathbuf[PATH_MAX + 1]; | |
365 | unsigned int bufsize = static_cast<int>(sizeof(pathbuf)); | |
366 | ||
367 | _NSGetExecutablePath( pathbuf, &bufsize); | |
368 | ||
369 | return std::string(pathbuf); | |
370 | } | |
371 | ||
372 | #else | |
373 | #error Support your platform here | |
374 | #endif | |
375 | ||
376 | ||
377 | std::string SystemToolbox::GetPathToExecutable() | |
378 | { | |
379 | boost::filesystem::path p(GetPathToExecutableInternal()); | |
380 | return boost::filesystem::absolute(p).string(); | |
381 | } | |
382 | ||
383 | ||
384 | std::string SystemToolbox::GetDirectoryOfExecutable() | |
385 | { | |
386 | boost::filesystem::path p(GetPathToExecutableInternal()); | |
387 | return boost::filesystem::absolute(p.parent_path()).string(); | |
388 | } | |
389 | ||
390 | ||
391 | void SystemToolbox::ExecuteSystemCommand(const std::string& command, | |
392 | const std::vector<std::string>& arguments) | |
393 | { | |
394 | // Convert the arguments as a C array | |
395 | std::vector<char*> args(arguments.size() + 2); | |
396 | ||
397 | args.front() = const_cast<char*>(command.c_str()); | |
398 | ||
399 | for (size_t i = 0; i < arguments.size(); i++) | |
400 | { | |
401 | args[i + 1] = const_cast<char*>(arguments[i].c_str()); | |
402 | } | |
403 | ||
404 | args.back() = NULL; | |
405 | ||
406 | int status; | |
407 | ||
408 | #if defined(_WIN32) | |
409 | // http://msdn.microsoft.com/en-us/library/275khfab.aspx | |
410 | status = static_cast<int>(_spawnvp(_P_OVERLAY, command.c_str(), &args[0])); | |
411 | ||
412 | #else | |
413 | int pid = fork(); | |
414 | ||
415 | if (pid == -1) | |
416 | { | |
417 | // Error in fork() | |
418 | #if ORTHANC_ENABLE_LOGGING == 1 | |
419 | LOG(ERROR) << "Cannot fork a child process"; | |
420 | #endif | |
421 | ||
422 | throw OrthancException(ErrorCode_SystemCommand); | |
423 | } | |
424 | else if (pid == 0) | |
425 | { | |
426 | // Execute the system command in the child process | |
427 | execvp(command.c_str(), &args[0]); | |
428 | ||
429 | // We should never get here | |
430 | _exit(1); | |
431 | } | |
432 | else | |
433 | { | |
434 | // Wait for the system command to exit | |
435 | waitpid(pid, &status, 0); | |
436 | } | |
437 | #endif | |
438 | ||
439 | if (status != 0) | |
440 | { | |
441 | #if ORTHANC_ENABLE_LOGGING == 1 | |
442 | LOG(ERROR) << "System command failed with status code " << status; | |
443 | #endif | |
444 | ||
445 | throw OrthancException(ErrorCode_SystemCommand); | |
446 | } | |
447 | } | |
448 | ||
449 | ||
450 | int SystemToolbox::GetProcessId() | |
451 | { | |
452 | #if defined(_WIN32) | |
453 | return static_cast<int>(_getpid()); | |
454 | #else | |
455 | return static_cast<int>(getpid()); | |
456 | #endif | |
457 | } | |
458 | ||
459 | ||
460 | bool SystemToolbox::IsRegularFile(const std::string& path) | |
461 | { | |
462 | namespace fs = boost::filesystem; | |
463 | ||
464 | try | |
465 | { | |
466 | if (fs::exists(path)) | |
467 | { | |
468 | fs::file_status status = fs::status(path); | |
469 | return (status.type() == boost::filesystem::regular_file || | |
470 | status.type() == boost::filesystem::reparse_file); // Fix BitBucket issue #11 | |
471 | } | |
472 | } | |
473 | catch (fs::filesystem_error&) | |
474 | { | |
475 | } | |
476 | ||
477 | return false; | |
478 | } | |
479 | ||
480 | ||
481 | FILE* SystemToolbox::OpenFile(const std::string& path, | |
482 | FileMode mode) | |
483 | { | |
484 | #if defined(_WIN32) | |
485 | // TODO Deal with special characters by converting to the current locale | |
486 | #endif | |
487 | ||
488 | const char* m; | |
489 | switch (mode) | |
490 | { | |
491 | case FileMode_ReadBinary: | |
492 | m = "rb"; | |
493 | break; | |
494 | ||
495 | case FileMode_WriteBinary: | |
496 | m = "wb"; | |
497 | break; | |
498 | ||
499 | default: | |
500 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
501 | } | |
502 | ||
503 | return fopen(path.c_str(), m); | |
504 | } | |
505 | ||
506 | ||
507 | std::string SystemToolbox::GenerateUuid() | |
508 | { | |
509 | #ifdef WIN32 | |
510 | UUID uuid; | |
511 | UuidCreate ( &uuid ); | |
512 | ||
513 | unsigned char * str; | |
514 | UuidToStringA ( &uuid, &str ); | |
515 | ||
516 | std::string s( ( char* ) str ); | |
517 | ||
518 | RpcStringFreeA ( &str ); | |
519 | #else | |
520 | uuid_t uuid; | |
521 | uuid_generate_random ( uuid ); | |
522 | char s[37]; | |
523 | uuid_unparse ( uuid, s ); | |
524 | #endif | |
525 | return s; | |
526 | } | |
527 | ||
528 | ||
529 | #if BOOST_HAS_DATE_TIME == 1 | |
530 | std::string SystemToolbox::GetNowIsoString() | |
531 | { | |
532 | boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); | |
533 | return boost::posix_time::to_iso_string(now); | |
534 | } | |
535 | ||
536 | void SystemToolbox::GetNowDicom(std::string& date, | |
537 | std::string& time) | |
538 | { | |
539 | boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); | |
540 | tm tm = boost::posix_time::to_tm(now); | |
541 | ||
542 | char s[32]; | |
543 | sprintf(s, "%04d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | |
544 | date.assign(s); | |
545 | ||
546 | // TODO milliseconds | |
547 | sprintf(s, "%02d%02d%02d.%06d", tm.tm_hour, tm.tm_min, tm.tm_sec, 0); | |
548 | time.assign(s); | |
549 | } | |
550 | #endif | |
551 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #if !defined(ORTHANC_SANDBOXED) | |
36 | # error The macro ORTHANC_SANDBOXED must be defined | |
37 | #endif | |
38 | ||
39 | #if ORTHANC_SANDBOXED == 1 | |
40 | # error The namespace SystemToolbox cannot be used in sandboxed environments | |
41 | #endif | |
42 | ||
43 | #include "Enumerations.h" | |
44 | ||
45 | #include <vector> | |
46 | #include <string> | |
47 | #include <stdint.h> | |
48 | ||
49 | namespace Orthanc | |
50 | { | |
51 | namespace SystemToolbox | |
52 | { | |
53 | void USleep(uint64_t microSeconds); | |
54 | ||
55 | ServerBarrierEvent ServerBarrier(const bool& stopFlag); | |
56 | ||
57 | ServerBarrierEvent ServerBarrier(); | |
58 | ||
59 | void ReadFile(std::string& content, | |
60 | const std::string& path); | |
61 | ||
62 | bool ReadHeader(std::string& header, | |
63 | const std::string& path, | |
64 | size_t headerSize); | |
65 | ||
66 | void WriteFile(const void* content, | |
67 | size_t size, | |
68 | const std::string& path); | |
69 | ||
70 | void WriteFile(const std::string& content, | |
71 | const std::string& path); | |
72 | ||
73 | void RemoveFile(const std::string& path); | |
74 | ||
75 | uint64_t GetFileSize(const std::string& path); | |
76 | ||
77 | void MakeDirectory(const std::string& path); | |
78 | ||
79 | bool IsExistingFile(const std::string& path); | |
80 | ||
81 | std::string GetPathToExecutable(); | |
82 | ||
83 | std::string GetDirectoryOfExecutable(); | |
84 | ||
85 | void ExecuteSystemCommand(const std::string& command, | |
86 | const std::vector<std::string>& arguments); | |
87 | ||
88 | int GetProcessId(); | |
89 | ||
90 | bool IsRegularFile(const std::string& path); | |
91 | ||
92 | FILE* OpenFile(const std::string& path, | |
93 | FileMode mode); | |
94 | ||
95 | std::string GenerateUuid(); | |
96 | ||
97 | #if BOOST_HAS_DATE_TIME == 1 | |
98 | std::string GetNowIsoString(); | |
99 | ||
100 | void GetNowDicom(std::string& date, | |
101 | std::string& time); | |
102 | #endif | |
103 | } | |
104 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "PrecompiledHeaders.h" | |
34 | #include "Toolbox.h" | |
35 | ||
36 | #include "OrthancException.h" | |
37 | #include "Logging.h" | |
38 | ||
39 | #include <boost/algorithm/string/replace.hpp> | |
40 | #include <boost/lexical_cast.hpp> | |
41 | #include <boost/locale.hpp> | |
42 | #include <boost/uuid/sha1.hpp> | |
43 | ||
44 | #include <string> | |
45 | #include <stdint.h> | |
46 | #include <string.h> | |
47 | #include <algorithm> | |
48 | #include <ctype.h> | |
49 | ||
50 | #if BOOST_HAS_REGEX == 1 | |
51 | # include <boost/regex.hpp> | |
52 | #endif | |
53 | ||
54 | #if BOOST_HAS_LOCALE != 1 | |
55 | # error Since version 0.7.6, Orthanc entirely relies on boost::locale | |
56 | #endif | |
57 | ||
58 | #if ORTHANC_ENABLE_MD5 == 1 | |
59 | # include "../Resources/ThirdParty/md5/md5.h" | |
60 | #endif | |
61 | ||
62 | #if ORTHANC_ENABLE_BASE64 == 1 | |
63 | # include "../Resources/ThirdParty/base64/base64.h" | |
64 | #endif | |
65 | ||
66 | ||
67 | #if defined(_MSC_VER) && (_MSC_VER < 1800) | |
68 | // Patch for the missing "_strtoll" symbol when compiling with Visual Studio < 2013 | |
69 | extern "C" | |
70 | { | |
71 | int64_t _strtoi64(const char *nptr, char **endptr, int base); | |
72 | int64_t strtoll(const char *nptr, char **endptr, int base) | |
73 | { | |
74 | return _strtoi64(nptr, endptr, base); | |
75 | } | |
76 | } | |
77 | #endif | |
78 | ||
79 | ||
80 | #if defined(_WIN32) | |
81 | # include <windows.h> // For ::Sleep | |
82 | #endif | |
83 | ||
84 | ||
85 | #if ORTHANC_ENABLE_PUGIXML == 1 | |
86 | # include "ChunkedBuffer.h" | |
87 | # include <pugixml.hpp> | |
88 | #endif | |
89 | ||
90 | ||
91 | namespace Orthanc | |
92 | { | |
93 | void Toolbox::ToUpperCase(std::string& s) | |
94 | { | |
95 | std::transform(s.begin(), s.end(), s.begin(), toupper); | |
96 | } | |
97 | ||
98 | ||
99 | void Toolbox::ToLowerCase(std::string& s) | |
100 | { | |
101 | std::transform(s.begin(), s.end(), s.begin(), tolower); | |
102 | } | |
103 | ||
104 | ||
105 | void Toolbox::ToUpperCase(std::string& result, | |
106 | const std::string& source) | |
107 | { | |
108 | result = source; | |
109 | ToUpperCase(result); | |
110 | } | |
111 | ||
112 | void Toolbox::ToLowerCase(std::string& result, | |
113 | const std::string& source) | |
114 | { | |
115 | result = source; | |
116 | ToLowerCase(result); | |
117 | } | |
118 | ||
119 | ||
120 | void Toolbox::SplitUriComponents(UriComponents& components, | |
121 | const std::string& uri) | |
122 | { | |
123 | static const char URI_SEPARATOR = '/'; | |
124 | ||
125 | components.clear(); | |
126 | ||
127 | if (uri.size() == 0 || | |
128 | uri[0] != URI_SEPARATOR) | |
129 | { | |
130 | throw OrthancException(ErrorCode_UriSyntax); | |
131 | } | |
132 | ||
133 | // Count the number of slashes in the URI to make an assumption | |
134 | // about the number of components in the URI | |
135 | unsigned int estimatedSize = 0; | |
136 | for (unsigned int i = 0; i < uri.size(); i++) | |
137 | { | |
138 | if (uri[i] == URI_SEPARATOR) | |
139 | estimatedSize++; | |
140 | } | |
141 | ||
142 | components.reserve(estimatedSize - 1); | |
143 | ||
144 | unsigned int start = 1; | |
145 | unsigned int end = 1; | |
146 | while (end < uri.size()) | |
147 | { | |
148 | // This is the loop invariant | |
149 | assert(uri[start - 1] == '/' && (end >= start)); | |
150 | ||
151 | if (uri[end] == '/') | |
152 | { | |
153 | components.push_back(std::string(&uri[start], end - start)); | |
154 | end++; | |
155 | start = end; | |
156 | } | |
157 | else | |
158 | { | |
159 | end++; | |
160 | } | |
161 | } | |
162 | ||
163 | if (start < uri.size()) | |
164 | { | |
165 | components.push_back(std::string(&uri[start], end - start)); | |
166 | } | |
167 | ||
168 | for (size_t i = 0; i < components.size(); i++) | |
169 | { | |
170 | if (components[i].size() == 0) | |
171 | { | |
172 | // Empty component, as in: "/coucou//e" | |
173 | throw OrthancException(ErrorCode_UriSyntax); | |
174 | } | |
175 | } | |
176 | } | |
177 | ||
178 | ||
179 | void Toolbox::TruncateUri(UriComponents& target, | |
180 | const UriComponents& source, | |
181 | size_t fromLevel) | |
182 | { | |
183 | target.clear(); | |
184 | ||
185 | if (source.size() > fromLevel) | |
186 | { | |
187 | target.resize(source.size() - fromLevel); | |
188 | ||
189 | size_t j = 0; | |
190 | for (size_t i = fromLevel; i < source.size(); i++, j++) | |
191 | { | |
192 | target[j] = source[i]; | |
193 | } | |
194 | ||
195 | assert(j == target.size()); | |
196 | } | |
197 | } | |
198 | ||
199 | ||
200 | ||
201 | bool Toolbox::IsChildUri(const UriComponents& baseUri, | |
202 | const UriComponents& testedUri) | |
203 | { | |
204 | if (testedUri.size() < baseUri.size()) | |
205 | { | |
206 | return false; | |
207 | } | |
208 | ||
209 | for (size_t i = 0; i < baseUri.size(); i++) | |
210 | { | |
211 | if (baseUri[i] != testedUri[i]) | |
212 | return false; | |
213 | } | |
214 | ||
215 | return true; | |
216 | } | |
217 | ||
218 | ||
219 | std::string Toolbox::AutodetectMimeType(const std::string& path) | |
220 | { | |
221 | std::string contentType; | |
222 | size_t lastDot = path.rfind('.'); | |
223 | size_t lastSlash = path.rfind('/'); | |
224 | ||
225 | if (lastDot == std::string::npos || | |
226 | (lastSlash != std::string::npos && lastDot < lastSlash)) | |
227 | { | |
228 | // No trailing dot, unable to detect the content type | |
229 | } | |
230 | else | |
231 | { | |
232 | const char* extension = &path[lastDot + 1]; | |
233 | ||
234 | // http://en.wikipedia.org/wiki/Mime_types | |
235 | // Text types | |
236 | if (!strcmp(extension, "txt")) | |
237 | contentType = "text/plain"; | |
238 | else if (!strcmp(extension, "html")) | |
239 | contentType = "text/html"; | |
240 | else if (!strcmp(extension, "xml")) | |
241 | contentType = "text/xml"; | |
242 | else if (!strcmp(extension, "css")) | |
243 | contentType = "text/css"; | |
244 | ||
245 | // Application types | |
246 | else if (!strcmp(extension, "js")) | |
247 | contentType = "application/javascript"; | |
248 | else if (!strcmp(extension, "json")) | |
249 | contentType = "application/json"; | |
250 | else if (!strcmp(extension, "pdf")) | |
251 | contentType = "application/pdf"; | |
252 | ||
253 | // Images types | |
254 | else if (!strcmp(extension, "jpg") || !strcmp(extension, "jpeg")) | |
255 | contentType = "image/jpeg"; | |
256 | else if (!strcmp(extension, "gif")) | |
257 | contentType = "image/gif"; | |
258 | else if (!strcmp(extension, "png")) | |
259 | contentType = "image/png"; | |
260 | } | |
261 | ||
262 | return contentType; | |
263 | } | |
264 | ||
265 | ||
266 | std::string Toolbox::FlattenUri(const UriComponents& components, | |
267 | size_t fromLevel) | |
268 | { | |
269 | if (components.size() <= fromLevel) | |
270 | { | |
271 | return "/"; | |
272 | } | |
273 | else | |
274 | { | |
275 | std::string r; | |
276 | ||
277 | for (size_t i = fromLevel; i < components.size(); i++) | |
278 | { | |
279 | r += "/" + components[i]; | |
280 | } | |
281 | ||
282 | return r; | |
283 | } | |
284 | } | |
285 | ||
286 | ||
287 | #if ORTHANC_ENABLE_MD5 == 1 | |
288 | static char GetHexadecimalCharacter(uint8_t value) | |
289 | { | |
290 | assert(value < 16); | |
291 | ||
292 | if (value < 10) | |
293 | { | |
294 | return value + '0'; | |
295 | } | |
296 | else | |
297 | { | |
298 | return (value - 10) + 'a'; | |
299 | } | |
300 | } | |
301 | ||
302 | ||
303 | void Toolbox::ComputeMD5(std::string& result, | |
304 | const std::string& data) | |
305 | { | |
306 | if (data.size() > 0) | |
307 | { | |
308 | ComputeMD5(result, &data[0], data.size()); | |
309 | } | |
310 | else | |
311 | { | |
312 | ComputeMD5(result, NULL, 0); | |
313 | } | |
314 | } | |
315 | ||
316 | ||
317 | void Toolbox::ComputeMD5(std::string& result, | |
318 | const void* data, | |
319 | size_t size) | |
320 | { | |
321 | md5_state_s state; | |
322 | md5_init(&state); | |
323 | ||
324 | if (size > 0) | |
325 | { | |
326 | md5_append(&state, | |
327 | reinterpret_cast<const md5_byte_t*>(data), | |
328 | static_cast<int>(size)); | |
329 | } | |
330 | ||
331 | md5_byte_t actualHash[16]; | |
332 | md5_finish(&state, actualHash); | |
333 | ||
334 | result.resize(32); | |
335 | for (unsigned int i = 0; i < 16; i++) | |
336 | { | |
337 | result[2 * i] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] / 16)); | |
338 | result[2 * i + 1] = GetHexadecimalCharacter(static_cast<uint8_t>(actualHash[i] % 16)); | |
339 | } | |
340 | } | |
341 | #endif | |
342 | ||
343 | ||
344 | #if ORTHANC_ENABLE_BASE64 == 1 | |
345 | void Toolbox::EncodeBase64(std::string& result, | |
346 | const std::string& data) | |
347 | { | |
348 | result = base64_encode(data); | |
349 | } | |
350 | ||
351 | void Toolbox::DecodeBase64(std::string& result, | |
352 | const std::string& data) | |
353 | { | |
354 | for (size_t i = 0; i < data.length(); i++) | |
355 | { | |
356 | if (!isalnum(data[i]) && | |
357 | data[i] != '+' && | |
358 | data[i] != '/' && | |
359 | data[i] != '=') | |
360 | { | |
361 | // This is not a valid character for a Base64 string | |
362 | throw OrthancException(ErrorCode_BadFileFormat); | |
363 | } | |
364 | } | |
365 | ||
366 | result = base64_decode(data); | |
367 | } | |
368 | ||
369 | ||
370 | # if BOOST_HAS_REGEX == 1 | |
371 | bool Toolbox::DecodeDataUriScheme(std::string& mime, | |
372 | std::string& content, | |
373 | const std::string& source) | |
374 | { | |
375 | boost::regex pattern("data:([^;]+);base64,([a-zA-Z0-9=+/]*)", | |
376 | boost::regex::icase /* case insensitive search */); | |
377 | ||
378 | boost::cmatch what; | |
379 | if (regex_match(source.c_str(), what, pattern)) | |
380 | { | |
381 | mime = what[1]; | |
382 | DecodeBase64(content, what[2]); | |
383 | return true; | |
384 | } | |
385 | else | |
386 | { | |
387 | return false; | |
388 | } | |
389 | } | |
390 | # endif | |
391 | ||
392 | ||
393 | void Toolbox::EncodeDataUriScheme(std::string& result, | |
394 | const std::string& mime, | |
395 | const std::string& content) | |
396 | { | |
397 | result = "data:" + mime + ";base64," + base64_encode(content); | |
398 | } | |
399 | ||
400 | #endif | |
401 | ||
402 | ||
403 | static const char* GetBoostLocaleEncoding(const Encoding sourceEncoding) | |
404 | { | |
405 | switch (sourceEncoding) | |
406 | { | |
407 | case Encoding_Utf8: | |
408 | return "UTF-8"; | |
409 | ||
410 | case Encoding_Ascii: | |
411 | return "ASCII"; | |
412 | ||
413 | case Encoding_Latin1: | |
414 | return "ISO-8859-1"; | |
415 | break; | |
416 | ||
417 | case Encoding_Latin2: | |
418 | return "ISO-8859-2"; | |
419 | break; | |
420 | ||
421 | case Encoding_Latin3: | |
422 | return "ISO-8859-3"; | |
423 | break; | |
424 | ||
425 | case Encoding_Latin4: | |
426 | return "ISO-8859-4"; | |
427 | break; | |
428 | ||
429 | case Encoding_Latin5: | |
430 | return "ISO-8859-9"; | |
431 | break; | |
432 | ||
433 | case Encoding_Cyrillic: | |
434 | return "ISO-8859-5"; | |
435 | break; | |
436 | ||
437 | case Encoding_Windows1251: | |
438 | return "WINDOWS-1251"; | |
439 | break; | |
440 | ||
441 | case Encoding_Arabic: | |
442 | return "ISO-8859-6"; | |
443 | break; | |
444 | ||
445 | case Encoding_Greek: | |
446 | return "ISO-8859-7"; | |
447 | break; | |
448 | ||
449 | case Encoding_Hebrew: | |
450 | return "ISO-8859-8"; | |
451 | break; | |
452 | ||
453 | case Encoding_Japanese: | |
454 | return "SHIFT-JIS"; | |
455 | break; | |
456 | ||
457 | case Encoding_Chinese: | |
458 | return "GB18030"; | |
459 | break; | |
460 | ||
461 | case Encoding_Thai: | |
462 | return "TIS620.2533-0"; | |
463 | break; | |
464 | ||
465 | default: | |
466 | throw OrthancException(ErrorCode_NotImplemented); | |
467 | } | |
468 | } | |
469 | ||
470 | ||
471 | std::string Toolbox::ConvertToUtf8(const std::string& source, | |
472 | Encoding sourceEncoding) | |
473 | { | |
474 | if (sourceEncoding == Encoding_Utf8) | |
475 | { | |
476 | // Already in UTF-8: No conversion is required | |
477 | return source; | |
478 | } | |
479 | ||
480 | if (sourceEncoding == Encoding_Ascii) | |
481 | { | |
482 | return ConvertToAscii(source); | |
483 | } | |
484 | ||
485 | const char* encoding = GetBoostLocaleEncoding(sourceEncoding); | |
486 | ||
487 | try | |
488 | { | |
489 | return boost::locale::conv::to_utf<char>(source, encoding); | |
490 | } | |
491 | catch (std::runtime_error&) | |
492 | { | |
493 | // Bad input string or bad encoding | |
494 | return ConvertToAscii(source); | |
495 | } | |
496 | } | |
497 | ||
498 | ||
499 | std::string Toolbox::ConvertFromUtf8(const std::string& source, | |
500 | Encoding targetEncoding) | |
501 | { | |
502 | if (targetEncoding == Encoding_Utf8) | |
503 | { | |
504 | // Already in UTF-8: No conversion is required | |
505 | return source; | |
506 | } | |
507 | ||
508 | if (targetEncoding == Encoding_Ascii) | |
509 | { | |
510 | return ConvertToAscii(source); | |
511 | } | |
512 | ||
513 | const char* encoding = GetBoostLocaleEncoding(targetEncoding); | |
514 | ||
515 | try | |
516 | { | |
517 | return boost::locale::conv::from_utf<char>(source, encoding); | |
518 | } | |
519 | catch (std::runtime_error&) | |
520 | { | |
521 | // Bad input string or bad encoding | |
522 | return ConvertToAscii(source); | |
523 | } | |
524 | } | |
525 | ||
526 | ||
527 | bool Toolbox::IsAsciiString(const void* data, | |
528 | size_t size) | |
529 | { | |
530 | const uint8_t* p = reinterpret_cast<const uint8_t*>(data); | |
531 | ||
532 | for (size_t i = 0; i < size; i++, p++) | |
533 | { | |
534 | if (*p > 127 || (*p != 0 && iscntrl(*p))) | |
535 | { | |
536 | return false; | |
537 | } | |
538 | } | |
539 | ||
540 | return true; | |
541 | } | |
542 | ||
543 | ||
544 | std::string Toolbox::ConvertToAscii(const std::string& source) | |
545 | { | |
546 | std::string result; | |
547 | ||
548 | result.reserve(source.size() + 1); | |
549 | for (size_t i = 0; i < source.size(); i++) | |
550 | { | |
551 | if (source[i] <= 127 && source[i] >= 0 && !iscntrl(source[i])) | |
552 | { | |
553 | result.push_back(source[i]); | |
554 | } | |
555 | } | |
556 | ||
557 | return result; | |
558 | } | |
559 | ||
560 | ||
561 | void Toolbox::ComputeSHA1(std::string& result, | |
562 | const void* data, | |
563 | size_t size) | |
564 | { | |
565 | boost::uuids::detail::sha1 sha1; | |
566 | ||
567 | if (size > 0) | |
568 | { | |
569 | sha1.process_bytes(data, size); | |
570 | } | |
571 | ||
572 | unsigned int digest[5]; | |
573 | ||
574 | // Sanity check for the memory layout: A SHA-1 digest is 160 bits wide | |
575 | assert(sizeof(unsigned int) == 4 && sizeof(digest) == (160 / 8)); | |
576 | ||
577 | sha1.get_digest(digest); | |
578 | ||
579 | result.resize(8 * 5 + 4); | |
580 | sprintf(&result[0], "%08x-%08x-%08x-%08x-%08x", | |
581 | digest[0], | |
582 | digest[1], | |
583 | digest[2], | |
584 | digest[3], | |
585 | digest[4]); | |
586 | } | |
587 | ||
588 | void Toolbox::ComputeSHA1(std::string& result, | |
589 | const std::string& data) | |
590 | { | |
591 | if (data.size() > 0) | |
592 | { | |
593 | ComputeSHA1(result, data.c_str(), data.size()); | |
594 | } | |
595 | else | |
596 | { | |
597 | ComputeSHA1(result, NULL, 0); | |
598 | } | |
599 | } | |
600 | ||
601 | ||
602 | bool Toolbox::IsSHA1(const char* str, | |
603 | size_t size) | |
604 | { | |
605 | if (size == 0) | |
606 | { | |
607 | return false; | |
608 | } | |
609 | ||
610 | const char* start = str; | |
611 | const char* end = str + size; | |
612 | ||
613 | // Trim the beginning of the string | |
614 | while (start < end) | |
615 | { | |
616 | if (*start == '\0' || | |
617 | isspace(*start)) | |
618 | { | |
619 | start++; | |
620 | } | |
621 | else | |
622 | { | |
623 | break; | |
624 | } | |
625 | } | |
626 | ||
627 | // Trim the trailing of the string | |
628 | while (start < end) | |
629 | { | |
630 | if (*(end - 1) == '\0' || | |
631 | isspace(*(end - 1))) | |
632 | { | |
633 | end--; | |
634 | } | |
635 | else | |
636 | { | |
637 | break; | |
638 | } | |
639 | } | |
640 | ||
641 | if (end - start != 44) | |
642 | { | |
643 | return false; | |
644 | } | |
645 | ||
646 | for (unsigned int i = 0; i < 44; i++) | |
647 | { | |
648 | if (i == 8 || | |
649 | i == 17 || | |
650 | i == 26 || | |
651 | i == 35) | |
652 | { | |
653 | if (start[i] != '-') | |
654 | return false; | |
655 | } | |
656 | else | |
657 | { | |
658 | if (!isalnum(start[i])) | |
659 | return false; | |
660 | } | |
661 | } | |
662 | ||
663 | return true; | |
664 | } | |
665 | ||
666 | ||
667 | bool Toolbox::IsSHA1(const std::string& s) | |
668 | { | |
669 | if (s.size() == 0) | |
670 | { | |
671 | return false; | |
672 | } | |
673 | else | |
674 | { | |
675 | return IsSHA1(s.c_str(), s.size()); | |
676 | } | |
677 | } | |
678 | ||
679 | ||
680 | std::string Toolbox::StripSpaces(const std::string& source) | |
681 | { | |
682 | size_t first = 0; | |
683 | ||
684 | while (first < source.length() && | |
685 | isspace(source[first])) | |
686 | { | |
687 | first++; | |
688 | } | |
689 | ||
690 | if (first == source.length()) | |
691 | { | |
692 | // String containing only spaces | |
693 | return ""; | |
694 | } | |
695 | ||
696 | size_t last = source.length(); | |
697 | while (last > first && | |
698 | isspace(source[last - 1])) | |
699 | { | |
700 | last--; | |
701 | } | |
702 | ||
703 | assert(first <= last); | |
704 | return source.substr(first, last - first); | |
705 | } | |
706 | ||
707 | ||
708 | static char Hex2Dec(char c) | |
709 | { | |
710 | return ((c >= '0' && c <= '9') ? c - '0' : | |
711 | ((c >= 'a' && c <= 'f') ? c - 'a' + 10 : c - 'A' + 10)); | |
712 | } | |
713 | ||
714 | void Toolbox::UrlDecode(std::string& s) | |
715 | { | |
716 | // http://en.wikipedia.org/wiki/Percent-encoding | |
717 | // http://www.w3schools.com/tags/ref_urlencode.asp | |
718 | // http://stackoverflow.com/questions/154536/encode-decode-urls-in-c | |
719 | ||
720 | if (s.size() == 0) | |
721 | { | |
722 | return; | |
723 | } | |
724 | ||
725 | size_t source = 0; | |
726 | size_t target = 0; | |
727 | ||
728 | while (source < s.size()) | |
729 | { | |
730 | if (s[source] == '%' && | |
731 | source + 2 < s.size() && | |
732 | isalnum(s[source + 1]) && | |
733 | isalnum(s[source + 2])) | |
734 | { | |
735 | s[target] = (Hex2Dec(s[source + 1]) << 4) | Hex2Dec(s[source + 2]); | |
736 | source += 3; | |
737 | target += 1; | |
738 | } | |
739 | else | |
740 | { | |
741 | if (s[source] == '+') | |
742 | s[target] = ' '; | |
743 | else | |
744 | s[target] = s[source]; | |
745 | ||
746 | source++; | |
747 | target++; | |
748 | } | |
749 | } | |
750 | ||
751 | s.resize(target); | |
752 | } | |
753 | ||
754 | ||
755 | Endianness Toolbox::DetectEndianness() | |
756 | { | |
757 | // http://sourceforge.net/p/predef/wiki/Endianness/ | |
758 | ||
759 | uint8_t buffer[4]; | |
760 | ||
761 | buffer[0] = 0x00; | |
762 | buffer[1] = 0x01; | |
763 | buffer[2] = 0x02; | |
764 | buffer[3] = 0x03; | |
765 | ||
766 | switch (*((uint32_t *)buffer)) | |
767 | { | |
768 | case 0x00010203: | |
769 | return Endianness_Big; | |
770 | ||
771 | case 0x03020100: | |
772 | return Endianness_Little; | |
773 | ||
774 | default: | |
775 | throw OrthancException(ErrorCode_NotImplemented); | |
776 | } | |
777 | } | |
778 | ||
779 | ||
780 | #if BOOST_HAS_REGEX == 1 | |
781 | std::string Toolbox::WildcardToRegularExpression(const std::string& source) | |
782 | { | |
783 | // TODO - Speed up this with a regular expression | |
784 | ||
785 | std::string result = source; | |
786 | ||
787 | // Escape all special characters | |
788 | boost::replace_all(result, "\\", "\\\\"); | |
789 | boost::replace_all(result, "^", "\\^"); | |
790 | boost::replace_all(result, ".", "\\."); | |
791 | boost::replace_all(result, "$", "\\$"); | |
792 | boost::replace_all(result, "|", "\\|"); | |
793 | boost::replace_all(result, "(", "\\("); | |
794 | boost::replace_all(result, ")", "\\)"); | |
795 | boost::replace_all(result, "[", "\\["); | |
796 | boost::replace_all(result, "]", "\\]"); | |
797 | boost::replace_all(result, "+", "\\+"); | |
798 | boost::replace_all(result, "/", "\\/"); | |
799 | boost::replace_all(result, "{", "\\{"); | |
800 | boost::replace_all(result, "}", "\\}"); | |
801 | ||
802 | // Convert wildcards '*' and '?' to their regex equivalents | |
803 | boost::replace_all(result, "?", "."); | |
804 | boost::replace_all(result, "*", ".*"); | |
805 | ||
806 | return result; | |
807 | } | |
808 | #endif | |
809 | ||
810 | ||
811 | ||
812 | void Toolbox::TokenizeString(std::vector<std::string>& result, | |
813 | const std::string& value, | |
814 | char separator) | |
815 | { | |
816 | result.clear(); | |
817 | ||
818 | std::string currentItem; | |
819 | ||
820 | for (size_t i = 0; i < value.size(); i++) | |
821 | { | |
822 | if (value[i] == separator) | |
823 | { | |
824 | result.push_back(currentItem); | |
825 | currentItem.clear(); | |
826 | } | |
827 | else | |
828 | { | |
829 | currentItem.push_back(value[i]); | |
830 | } | |
831 | } | |
832 | ||
833 | result.push_back(currentItem); | |
834 | } | |
835 | ||
836 | ||
837 | #if ORTHANC_ENABLE_PUGIXML == 1 | |
838 | class ChunkedBufferWriter : public pugi::xml_writer | |
839 | { | |
840 | private: | |
841 | ChunkedBuffer buffer_; | |
842 | ||
843 | public: | |
844 | virtual void write(const void *data, size_t size) | |
845 | { | |
846 | if (size > 0) | |
847 | { | |
848 | buffer_.AddChunk(reinterpret_cast<const char*>(data), size); | |
849 | } | |
850 | } | |
851 | ||
852 | void Flatten(std::string& s) | |
853 | { | |
854 | buffer_.Flatten(s); | |
855 | } | |
856 | }; | |
857 | ||
858 | ||
859 | static void JsonToXmlInternal(pugi::xml_node& target, | |
860 | const Json::Value& source, | |
861 | const std::string& arrayElement) | |
862 | { | |
863 | // http://jsoncpp.sourceforge.net/value_8h_source.html#l00030 | |
864 | ||
865 | switch (source.type()) | |
866 | { | |
867 | case Json::nullValue: | |
868 | { | |
869 | target.append_child(pugi::node_pcdata).set_value("null"); | |
870 | break; | |
871 | } | |
872 | ||
873 | case Json::intValue: | |
874 | { | |
875 | std::string s = boost::lexical_cast<std::string>(source.asInt()); | |
876 | target.append_child(pugi::node_pcdata).set_value(s.c_str()); | |
877 | break; | |
878 | } | |
879 | ||
880 | case Json::uintValue: | |
881 | { | |
882 | std::string s = boost::lexical_cast<std::string>(source.asUInt()); | |
883 | target.append_child(pugi::node_pcdata).set_value(s.c_str()); | |
884 | break; | |
885 | } | |
886 | ||
887 | case Json::realValue: | |
888 | { | |
889 | std::string s = boost::lexical_cast<std::string>(source.asFloat()); | |
890 | target.append_child(pugi::node_pcdata).set_value(s.c_str()); | |
891 | break; | |
892 | } | |
893 | ||
894 | case Json::stringValue: | |
895 | { | |
896 | target.append_child(pugi::node_pcdata).set_value(source.asString().c_str()); | |
897 | break; | |
898 | } | |
899 | ||
900 | case Json::booleanValue: | |
901 | { | |
902 | target.append_child(pugi::node_pcdata).set_value(source.asBool() ? "true" : "false"); | |
903 | break; | |
904 | } | |
905 | ||
906 | case Json::arrayValue: | |
907 | { | |
908 | for (Json::Value::ArrayIndex i = 0; i < source.size(); i++) | |
909 | { | |
910 | pugi::xml_node node = target.append_child(); | |
911 | node.set_name(arrayElement.c_str()); | |
912 | JsonToXmlInternal(node, source[i], arrayElement); | |
913 | } | |
914 | break; | |
915 | } | |
916 | ||
917 | case Json::objectValue: | |
918 | { | |
919 | Json::Value::Members members = source.getMemberNames(); | |
920 | ||
921 | for (size_t i = 0; i < members.size(); i++) | |
922 | { | |
923 | pugi::xml_node node = target.append_child(); | |
924 | node.set_name(members[i].c_str()); | |
925 | JsonToXmlInternal(node, source[members[i]], arrayElement); | |
926 | } | |
927 | ||
928 | break; | |
929 | } | |
930 | ||
931 | default: | |
932 | throw OrthancException(ErrorCode_NotImplemented); | |
933 | } | |
934 | } | |
935 | ||
936 | ||
937 | void Toolbox::JsonToXml(std::string& target, | |
938 | const Json::Value& source, | |
939 | const std::string& rootElement, | |
940 | const std::string& arrayElement) | |
941 | { | |
942 | pugi::xml_document doc; | |
943 | ||
944 | pugi::xml_node n = doc.append_child(rootElement.c_str()); | |
945 | JsonToXmlInternal(n, source, arrayElement); | |
946 | ||
947 | pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); | |
948 | decl.append_attribute("version").set_value("1.0"); | |
949 | decl.append_attribute("encoding").set_value("utf-8"); | |
950 | ||
951 | ChunkedBufferWriter writer; | |
952 | doc.save(writer, " ", pugi::format_default, pugi::encoding_utf8); | |
953 | writer.Flatten(target); | |
954 | } | |
955 | ||
956 | #endif | |
957 | ||
958 | ||
959 | ||
960 | bool Toolbox::IsInteger(const std::string& str) | |
961 | { | |
962 | std::string s = StripSpaces(str); | |
963 | ||
964 | if (s.size() == 0) | |
965 | { | |
966 | return false; | |
967 | } | |
968 | ||
969 | size_t pos = 0; | |
970 | if (s[0] == '-') | |
971 | { | |
972 | if (s.size() == 1) | |
973 | { | |
974 | return false; | |
975 | } | |
976 | ||
977 | pos = 1; | |
978 | } | |
979 | ||
980 | while (pos < s.size()) | |
981 | { | |
982 | if (!isdigit(s[pos])) | |
983 | { | |
984 | return false; | |
985 | } | |
986 | ||
987 | pos++; | |
988 | } | |
989 | ||
990 | return true; | |
991 | } | |
992 | ||
993 | ||
994 | void Toolbox::CopyJsonWithoutComments(Json::Value& target, | |
995 | const Json::Value& source) | |
996 | { | |
997 | switch (source.type()) | |
998 | { | |
999 | case Json::nullValue: | |
1000 | target = Json::nullValue; | |
1001 | break; | |
1002 | ||
1003 | case Json::intValue: | |
1004 | target = source.asInt64(); | |
1005 | break; | |
1006 | ||
1007 | case Json::uintValue: | |
1008 | target = source.asUInt64(); | |
1009 | break; | |
1010 | ||
1011 | case Json::realValue: | |
1012 | target = source.asDouble(); | |
1013 | break; | |
1014 | ||
1015 | case Json::stringValue: | |
1016 | target = source.asString(); | |
1017 | break; | |
1018 | ||
1019 | case Json::booleanValue: | |
1020 | target = source.asBool(); | |
1021 | break; | |
1022 | ||
1023 | case Json::arrayValue: | |
1024 | { | |
1025 | target = Json::arrayValue; | |
1026 | for (Json::Value::ArrayIndex i = 0; i < source.size(); i++) | |
1027 | { | |
1028 | Json::Value& item = target.append(Json::nullValue); | |
1029 | CopyJsonWithoutComments(item, source[i]); | |
1030 | } | |
1031 | ||
1032 | break; | |
1033 | } | |
1034 | ||
1035 | case Json::objectValue: | |
1036 | { | |
1037 | target = Json::objectValue; | |
1038 | Json::Value::Members members = source.getMemberNames(); | |
1039 | for (Json::Value::ArrayIndex i = 0; i < members.size(); i++) | |
1040 | { | |
1041 | const std::string item = members[i]; | |
1042 | CopyJsonWithoutComments(target[item], source[item]); | |
1043 | } | |
1044 | ||
1045 | break; | |
1046 | } | |
1047 | ||
1048 | default: | |
1049 | break; | |
1050 | } | |
1051 | } | |
1052 | ||
1053 | ||
1054 | bool Toolbox::StartsWith(const std::string& str, | |
1055 | const std::string& prefix) | |
1056 | { | |
1057 | if (str.size() < prefix.size()) | |
1058 | { | |
1059 | return false; | |
1060 | } | |
1061 | else | |
1062 | { | |
1063 | return str.compare(0, prefix.size(), prefix) == 0; | |
1064 | } | |
1065 | } | |
1066 | ||
1067 | ||
1068 | static bool IsUnreservedCharacter(char c) | |
1069 | { | |
1070 | // This function checks whether "c" is an unserved character | |
1071 | // wrt. an URI percent-encoding | |
1072 | // https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding%5Fin%5Fa%5FURI | |
1073 | ||
1074 | return ((c >= 'A' && c <= 'Z') || | |
1075 | (c >= 'a' && c <= 'z') || | |
1076 | (c >= '0' && c <= '9') || | |
1077 | c == '-' || | |
1078 | c == '_' || | |
1079 | c == '.' || | |
1080 | c == '~'); | |
1081 | } | |
1082 | ||
1083 | void Toolbox::UriEncode(std::string& target, | |
1084 | const std::string& source) | |
1085 | { | |
1086 | // Estimate the length of the percent-encoded URI | |
1087 | size_t length = 0; | |
1088 | ||
1089 | for (size_t i = 0; i < source.size(); i++) | |
1090 | { | |
1091 | if (IsUnreservedCharacter(source[i])) | |
1092 | { | |
1093 | length += 1; | |
1094 | } | |
1095 | else | |
1096 | { | |
1097 | // This character must be percent-encoded | |
1098 | length += 3; | |
1099 | } | |
1100 | } | |
1101 | ||
1102 | target.clear(); | |
1103 | target.reserve(length); | |
1104 | ||
1105 | for (size_t i = 0; i < source.size(); i++) | |
1106 | { | |
1107 | if (IsUnreservedCharacter(source[i])) | |
1108 | { | |
1109 | target.push_back(source[i]); | |
1110 | } | |
1111 | else | |
1112 | { | |
1113 | // This character must be percent-encoded | |
1114 | uint8_t byte = static_cast<uint8_t>(source[i]); | |
1115 | uint8_t a = byte >> 4; | |
1116 | uint8_t b = byte & 0x0f; | |
1117 | ||
1118 | target.push_back('%'); | |
1119 | target.push_back(a < 10 ? a + '0' : a - 10 + 'A'); | |
1120 | target.push_back(b < 10 ? b + '0' : b - 10 + 'A'); | |
1121 | } | |
1122 | } | |
1123 | } | |
1124 | ||
1125 | ||
1126 | static bool HasField(const Json::Value& json, | |
1127 | const std::string& key, | |
1128 | Json::ValueType expectedType) | |
1129 | { | |
1130 | if (json.type() != Json::objectValue || | |
1131 | !json.isMember(key)) | |
1132 | { | |
1133 | return false; | |
1134 | } | |
1135 | else if (json[key].type() == expectedType) | |
1136 | { | |
1137 | return true; | |
1138 | } | |
1139 | else | |
1140 | { | |
1141 | throw OrthancException(ErrorCode_BadParameterType); | |
1142 | } | |
1143 | } | |
1144 | ||
1145 | ||
1146 | std::string Toolbox::GetJsonStringField(const Json::Value& json, | |
1147 | const std::string& key, | |
1148 | const std::string& defaultValue) | |
1149 | { | |
1150 | if (HasField(json, key, Json::stringValue)) | |
1151 | { | |
1152 | return json[key].asString(); | |
1153 | } | |
1154 | else | |
1155 | { | |
1156 | return defaultValue; | |
1157 | } | |
1158 | } | |
1159 | ||
1160 | ||
1161 | bool Toolbox::GetJsonBooleanField(const ::Json::Value& json, | |
1162 | const std::string& key, | |
1163 | bool defaultValue) | |
1164 | { | |
1165 | if (HasField(json, key, Json::booleanValue)) | |
1166 | { | |
1167 | return json[key].asBool(); | |
1168 | } | |
1169 | else | |
1170 | { | |
1171 | return defaultValue; | |
1172 | } | |
1173 | } | |
1174 | ||
1175 | ||
1176 | int Toolbox::GetJsonIntegerField(const ::Json::Value& json, | |
1177 | const std::string& key, | |
1178 | int defaultValue) | |
1179 | { | |
1180 | if (HasField(json, key, Json::intValue)) | |
1181 | { | |
1182 | return json[key].asInt(); | |
1183 | } | |
1184 | else | |
1185 | { | |
1186 | return defaultValue; | |
1187 | } | |
1188 | } | |
1189 | ||
1190 | ||
1191 | unsigned int Toolbox::GetJsonUnsignedIntegerField(const ::Json::Value& json, | |
1192 | const std::string& key, | |
1193 | unsigned int defaultValue) | |
1194 | { | |
1195 | int v = GetJsonIntegerField(json, key, defaultValue); | |
1196 | ||
1197 | if (v < 0) | |
1198 | { | |
1199 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1200 | } | |
1201 | else | |
1202 | { | |
1203 | return static_cast<unsigned int>(v); | |
1204 | } | |
1205 | } | |
1206 | ||
1207 | ||
1208 | bool Toolbox::IsUuid(const std::string& str) | |
1209 | { | |
1210 | if (str.size() != 36) | |
1211 | { | |
1212 | return false; | |
1213 | } | |
1214 | ||
1215 | for (size_t i = 0; i < str.length(); i++) | |
1216 | { | |
1217 | if (i == 8 || i == 13 || i == 18 || i == 23) | |
1218 | { | |
1219 | if (str[i] != '-') | |
1220 | return false; | |
1221 | } | |
1222 | else | |
1223 | { | |
1224 | if (!isalnum(str[i])) | |
1225 | return false; | |
1226 | } | |
1227 | } | |
1228 | ||
1229 | return true; | |
1230 | } | |
1231 | ||
1232 | ||
1233 | bool Toolbox::StartsWithUuid(const std::string& str) | |
1234 | { | |
1235 | if (str.size() < 36) | |
1236 | { | |
1237 | return false; | |
1238 | } | |
1239 | ||
1240 | if (str.size() == 36) | |
1241 | { | |
1242 | return IsUuid(str); | |
1243 | } | |
1244 | ||
1245 | assert(str.size() > 36); | |
1246 | if (!isspace(str[36])) | |
1247 | { | |
1248 | return false; | |
1249 | } | |
1250 | ||
1251 | return IsUuid(str.substr(0, 36)); | |
1252 | } | |
1253 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include "Enumerations.h" | |
36 | ||
37 | #include <stdint.h> | |
38 | #include <vector> | |
39 | #include <string> | |
40 | #include <json/json.h> | |
41 | ||
42 | ||
43 | #if !defined(ORTHANC_ENABLE_BASE64) | |
44 | # error The macro ORTHANC_ENABLE_BASE64 must be defined | |
45 | #endif | |
46 | ||
47 | #if !defined(ORTHANC_ENABLE_MD5) | |
48 | # error The macro ORTHANC_ENABLE_MD5 must be defined | |
49 | #endif | |
50 | ||
51 | #if !defined(ORTHANC_ENABLE_PUGIXML) | |
52 | # error The macro ORTHANC_ENABLE_PUGIXML must be defined | |
53 | #endif | |
54 | ||
55 | #if !defined(BOOST_HAS_REGEX) | |
56 | # error The macro BOOST_HAS_REGEX must be defined | |
57 | #endif | |
58 | ||
59 | ||
60 | /** | |
61 | * NOTE: GUID vs. UUID | |
62 | * The simple answer is: no difference, they are the same thing. Treat | |
63 | * them as a 16 byte (128 bits) value that is used as a unique | |
64 | * value. In Microsoft-speak they are called GUIDs, but call them | |
65 | * UUIDs when not using Microsoft-speak. | |
66 | * http://stackoverflow.com/questions/246930/is-there-any-difference-between-a-guid-and-a-uuid | |
67 | **/ | |
68 | ||
69 | ||
70 | ||
71 | namespace Orthanc | |
72 | { | |
73 | typedef std::vector<std::string> UriComponents; | |
74 | ||
75 | class NullType | |
76 | { | |
77 | }; | |
78 | ||
79 | namespace Toolbox | |
80 | { | |
81 | void ToUpperCase(std::string& s); // Inplace version | |
82 | ||
83 | void ToLowerCase(std::string& s); // Inplace version | |
84 | ||
85 | void ToUpperCase(std::string& result, | |
86 | const std::string& source); | |
87 | ||
88 | void ToLowerCase(std::string& result, | |
89 | const std::string& source); | |
90 | ||
91 | void SplitUriComponents(UriComponents& components, | |
92 | const std::string& uri); | |
93 | ||
94 | void TruncateUri(UriComponents& target, | |
95 | const UriComponents& source, | |
96 | size_t fromLevel); | |
97 | ||
98 | bool IsChildUri(const UriComponents& baseUri, | |
99 | const UriComponents& testedUri); | |
100 | ||
101 | std::string AutodetectMimeType(const std::string& path); | |
102 | ||
103 | std::string FlattenUri(const UriComponents& components, | |
104 | size_t fromLevel = 0); | |
105 | ||
106 | #if ORTHANC_ENABLE_MD5 == 1 | |
107 | void ComputeMD5(std::string& result, | |
108 | const std::string& data); | |
109 | ||
110 | void ComputeMD5(std::string& result, | |
111 | const void* data, | |
112 | size_t size); | |
113 | #endif | |
114 | ||
115 | void ComputeSHA1(std::string& result, | |
116 | const std::string& data); | |
117 | ||
118 | void ComputeSHA1(std::string& result, | |
119 | const void* data, | |
120 | size_t size); | |
121 | ||
122 | bool IsSHA1(const char* str, | |
123 | size_t size); | |
124 | ||
125 | bool IsSHA1(const std::string& s); | |
126 | ||
127 | #if ORTHANC_ENABLE_BASE64 == 1 | |
128 | void DecodeBase64(std::string& result, | |
129 | const std::string& data); | |
130 | ||
131 | void EncodeBase64(std::string& result, | |
132 | const std::string& data); | |
133 | ||
134 | # if BOOST_HAS_REGEX == 1 | |
135 | bool DecodeDataUriScheme(std::string& mime, | |
136 | std::string& content, | |
137 | const std::string& source); | |
138 | # endif | |
139 | ||
140 | void EncodeDataUriScheme(std::string& result, | |
141 | const std::string& mime, | |
142 | const std::string& content); | |
143 | #endif | |
144 | ||
145 | std::string ConvertToUtf8(const std::string& source, | |
146 | Encoding sourceEncoding); | |
147 | ||
148 | std::string ConvertFromUtf8(const std::string& source, | |
149 | Encoding targetEncoding); | |
150 | ||
151 | bool IsAsciiString(const void* data, | |
152 | size_t size); | |
153 | ||
154 | std::string ConvertToAscii(const std::string& source); | |
155 | ||
156 | std::string StripSpaces(const std::string& source); | |
157 | ||
158 | // In-place percent-decoding for URL | |
159 | void UrlDecode(std::string& s); | |
160 | ||
161 | Endianness DetectEndianness(); | |
162 | ||
163 | #if BOOST_HAS_REGEX == 1 | |
164 | std::string WildcardToRegularExpression(const std::string& s); | |
165 | #endif | |
166 | ||
167 | void TokenizeString(std::vector<std::string>& result, | |
168 | const std::string& source, | |
169 | char separator); | |
170 | ||
171 | #if ORTHANC_ENABLE_PUGIXML == 1 | |
172 | void JsonToXml(std::string& target, | |
173 | const Json::Value& source, | |
174 | const std::string& rootElement = "root", | |
175 | const std::string& arrayElement = "item"); | |
176 | #endif | |
177 | ||
178 | bool IsInteger(const std::string& str); | |
179 | ||
180 | void CopyJsonWithoutComments(Json::Value& target, | |
181 | const Json::Value& source); | |
182 | ||
183 | bool StartsWith(const std::string& str, | |
184 | const std::string& prefix); | |
185 | ||
186 | void UriEncode(std::string& target, | |
187 | const std::string& source); | |
188 | ||
189 | std::string GetJsonStringField(const ::Json::Value& json, | |
190 | const std::string& key, | |
191 | const std::string& defaultValue); | |
192 | ||
193 | bool GetJsonBooleanField(const ::Json::Value& json, | |
194 | const std::string& key, | |
195 | bool defaultValue); | |
196 | ||
197 | int GetJsonIntegerField(const ::Json::Value& json, | |
198 | const std::string& key, | |
199 | int defaultValue); | |
200 | ||
201 | unsigned int GetJsonUnsignedIntegerField(const ::Json::Value& json, | |
202 | const std::string& key, | |
203 | unsigned int defaultValue); | |
204 | ||
205 | bool IsUuid(const std::string& str); | |
206 | ||
207 | bool StartsWithUuid(const std::string& str); | |
208 | } | |
209 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "PrecompiledHeaders.h" | |
34 | #include "WebServiceParameters.h" | |
35 | ||
36 | #include "../Core/Logging.h" | |
37 | #include "../Core/OrthancException.h" | |
38 | ||
39 | #if ORTHANC_SANDBOXED == 0 | |
40 | # include "../Core/SystemToolbox.h" | |
41 | #endif | |
42 | ||
43 | #include <cassert> | |
44 | ||
45 | namespace Orthanc | |
46 | { | |
47 | WebServiceParameters::WebServiceParameters() : | |
48 | advancedFormat_(false), | |
49 | url_("http://127.0.0.1:8042/"), | |
50 | pkcs11Enabled_(false) | |
51 | { | |
52 | } | |
53 | ||
54 | ||
55 | void WebServiceParameters::ClearClientCertificate() | |
56 | { | |
57 | certificateFile_.clear(); | |
58 | certificateKeyFile_.clear(); | |
59 | certificateKeyPassword_.clear(); | |
60 | } | |
61 | ||
62 | ||
63 | #if ORTHANC_SANDBOXED == 0 | |
64 | void WebServiceParameters::SetClientCertificate(const std::string& certificateFile, | |
65 | const std::string& certificateKeyFile, | |
66 | const std::string& certificateKeyPassword) | |
67 | { | |
68 | if (certificateFile.empty()) | |
69 | { | |
70 | throw OrthancException(ErrorCode_ParameterOutOfRange); | |
71 | } | |
72 | ||
73 | if (!SystemToolbox::IsRegularFile(certificateFile)) | |
74 | { | |
75 | LOG(ERROR) << "Cannot open certificate file: " << certificateFile; | |
76 | throw OrthancException(ErrorCode_InexistentFile); | |
77 | } | |
78 | ||
79 | if (!certificateKeyFile.empty() && | |
80 | !SystemToolbox::IsRegularFile(certificateKeyFile)) | |
81 | { | |
82 | LOG(ERROR) << "Cannot open key file: " << certificateKeyFile; | |
83 | throw OrthancException(ErrorCode_InexistentFile); | |
84 | } | |
85 | ||
86 | advancedFormat_ = true; | |
87 | certificateFile_ = certificateFile; | |
88 | certificateKeyFile_ = certificateKeyFile; | |
89 | certificateKeyPassword_ = certificateKeyPassword; | |
90 | } | |
91 | #endif | |
92 | ||
93 | ||
94 | static void AddTrailingSlash(std::string& url) | |
95 | { | |
96 | if (url.size() != 0 && | |
97 | url[url.size() - 1] != '/') | |
98 | { | |
99 | url += '/'; | |
100 | } | |
101 | } | |
102 | ||
103 | ||
104 | void WebServiceParameters::FromJsonArray(const Json::Value& peer) | |
105 | { | |
106 | assert(peer.isArray()); | |
107 | ||
108 | advancedFormat_ = false; | |
109 | pkcs11Enabled_ = false; | |
110 | ||
111 | if (peer.size() != 1 && | |
112 | peer.size() != 3) | |
113 | { | |
114 | throw OrthancException(ErrorCode_BadFileFormat); | |
115 | } | |
116 | ||
117 | std::string url = peer.get(0u, "").asString(); | |
118 | if (url.empty()) | |
119 | { | |
120 | throw OrthancException(ErrorCode_BadFileFormat); | |
121 | } | |
122 | ||
123 | AddTrailingSlash(url); | |
124 | SetUrl(url); | |
125 | ||
126 | if (peer.size() == 1) | |
127 | { | |
128 | SetUsername(""); | |
129 | SetPassword(""); | |
130 | } | |
131 | else if (peer.size() == 3) | |
132 | { | |
133 | SetUsername(peer.get(1u, "").asString()); | |
134 | SetPassword(peer.get(2u, "").asString()); | |
135 | } | |
136 | else | |
137 | { | |
138 | throw OrthancException(ErrorCode_BadFileFormat); | |
139 | } | |
140 | } | |
141 | ||
142 | ||
143 | static std::string GetStringMember(const Json::Value& peer, | |
144 | const std::string& key, | |
145 | const std::string& defaultValue) | |
146 | { | |
147 | if (!peer.isMember(key)) | |
148 | { | |
149 | return defaultValue; | |
150 | } | |
151 | else if (peer[key].type() != Json::stringValue) | |
152 | { | |
153 | throw OrthancException(ErrorCode_BadFileFormat); | |
154 | } | |
155 | else | |
156 | { | |
157 | return peer[key].asString(); | |
158 | } | |
159 | } | |
160 | ||
161 | ||
162 | void WebServiceParameters::FromJsonObject(const Json::Value& peer) | |
163 | { | |
164 | assert(peer.isObject()); | |
165 | advancedFormat_ = true; | |
166 | ||
167 | std::string url = GetStringMember(peer, "Url", ""); | |
168 | if (url.empty()) | |
169 | { | |
170 | throw OrthancException(ErrorCode_BadFileFormat); | |
171 | } | |
172 | ||
173 | AddTrailingSlash(url); | |
174 | SetUrl(url); | |
175 | ||
176 | SetUsername(GetStringMember(peer, "Username", "")); | |
177 | SetPassword(GetStringMember(peer, "Password", "")); | |
178 | ||
179 | #if ORTHANC_SANDBOXED == 0 | |
180 | if (peer.isMember("CertificateFile")) | |
181 | { | |
182 | SetClientCertificate(GetStringMember(peer, "CertificateFile", ""), | |
183 | GetStringMember(peer, "CertificateKeyFile", ""), | |
184 | GetStringMember(peer, "CertificateKeyPassword", "")); | |
185 | } | |
186 | #endif | |
187 | ||
188 | if (peer.isMember("Pkcs11")) | |
189 | { | |
190 | if (peer["Pkcs11"].type() == Json::booleanValue) | |
191 | { | |
192 | pkcs11Enabled_ = peer["Pkcs11"].asBool(); | |
193 | } | |
194 | else | |
195 | { | |
196 | throw OrthancException(ErrorCode_BadFileFormat); | |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | ||
202 | void WebServiceParameters::FromJson(const Json::Value& peer) | |
203 | { | |
204 | try | |
205 | { | |
206 | if (peer.isArray()) | |
207 | { | |
208 | FromJsonArray(peer); | |
209 | } | |
210 | else if (peer.isObject()) | |
211 | { | |
212 | FromJsonObject(peer); | |
213 | } | |
214 | else | |
215 | { | |
216 | throw OrthancException(ErrorCode_BadFileFormat); | |
217 | } | |
218 | } | |
219 | catch (OrthancException&) | |
220 | { | |
221 | throw; | |
222 | } | |
223 | catch (...) | |
224 | { | |
225 | throw OrthancException(ErrorCode_BadFileFormat); | |
226 | } | |
227 | } | |
228 | ||
229 | ||
230 | void WebServiceParameters::ToJson(Json::Value& value) const | |
231 | { | |
232 | if (advancedFormat_) | |
233 | { | |
234 | value = Json::objectValue; | |
235 | value["Url"] = url_; | |
236 | ||
237 | if (!username_.empty() || | |
238 | !password_.empty()) | |
239 | { | |
240 | value["Username"] = username_; | |
241 | value["Password"] = password_; | |
242 | } | |
243 | ||
244 | if (!certificateFile_.empty()) | |
245 | { | |
246 | value["CertificateFile"] = certificateFile_; | |
247 | } | |
248 | ||
249 | if (!certificateKeyFile_.empty()) | |
250 | { | |
251 | value["CertificateKeyFile"] = certificateKeyFile_; | |
252 | } | |
253 | ||
254 | if (!certificateKeyPassword_.empty()) | |
255 | { | |
256 | value["CertificateKeyPassword"] = certificateKeyPassword_; | |
257 | } | |
258 | } | |
259 | else | |
260 | { | |
261 | value = Json::arrayValue; | |
262 | value.append(url_); | |
263 | ||
264 | if (!username_.empty() || | |
265 | !password_.empty()) | |
266 | { | |
267 | value.append(username_); | |
268 | value.append(password_); | |
269 | } | |
270 | } | |
271 | } | |
272 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #if !defined(ORTHANC_SANDBOXED) | |
36 | # error The macro ORTHANC_SANDBOXED must be defined | |
37 | #endif | |
38 | ||
39 | #include <string> | |
40 | #include <json/json.h> | |
41 | ||
42 | namespace Orthanc | |
43 | { | |
44 | class WebServiceParameters | |
45 | { | |
46 | private: | |
47 | bool advancedFormat_; | |
48 | std::string url_; | |
49 | std::string username_; | |
50 | std::string password_; | |
51 | std::string certificateFile_; | |
52 | std::string certificateKeyFile_; | |
53 | std::string certificateKeyPassword_; | |
54 | bool pkcs11Enabled_; | |
55 | ||
56 | void FromJsonArray(const Json::Value& peer); | |
57 | ||
58 | void FromJsonObject(const Json::Value& peer); | |
59 | ||
60 | public: | |
61 | WebServiceParameters(); | |
62 | ||
63 | const std::string& GetUrl() const | |
64 | { | |
65 | return url_; | |
66 | } | |
67 | ||
68 | void SetUrl(const std::string& url) | |
69 | { | |
70 | url_ = url; | |
71 | } | |
72 | ||
73 | const std::string& GetUsername() const | |
74 | { | |
75 | return username_; | |
76 | } | |
77 | ||
78 | void SetUsername(const std::string& username) | |
79 | { | |
80 | username_ = username; | |
81 | } | |
82 | ||
83 | const std::string& GetPassword() const | |
84 | { | |
85 | return password_; | |
86 | } | |
87 | ||
88 | void SetPassword(const std::string& password) | |
89 | { | |
90 | password_ = password; | |
91 | } | |
92 | ||
93 | void ClearClientCertificate(); | |
94 | ||
95 | #if ORTHANC_SANDBOXED == 0 | |
96 | void SetClientCertificate(const std::string& certificateFile, | |
97 | const std::string& certificateKeyFile, | |
98 | const std::string& certificateKeyPassword); | |
99 | #endif | |
100 | ||
101 | const std::string& GetCertificateFile() const | |
102 | { | |
103 | return certificateFile_; | |
104 | } | |
105 | ||
106 | const std::string& GetCertificateKeyFile() const | |
107 | { | |
108 | return certificateKeyFile_; | |
109 | } | |
110 | ||
111 | const std::string& GetCertificateKeyPassword() const | |
112 | { | |
113 | return certificateKeyPassword_; | |
114 | } | |
115 | ||
116 | void SetPkcs11Enabled(bool pkcs11Enabled) | |
117 | { | |
118 | pkcs11Enabled_ = pkcs11Enabled; | |
119 | } | |
120 | ||
121 | bool IsPkcs11Enabled() const | |
122 | { | |
123 | return pkcs11Enabled_; | |
124 | } | |
125 | ||
126 | void FromJson(const Json::Value& peer); | |
127 | ||
128 | void ToJson(Json::Value& value) const; | |
129 | }; | |
130 | } |
0 | # This is the list of the symbols that must be exported by Orthanc | |
1 | # plugins, if targeting OS X | |
2 | ||
3 | _OrthancPluginInitialize | |
4 | _OrthancPluginFinalize | |
5 | _OrthancPluginGetName | |
6 | _OrthancPluginGetVersion |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #include "OrthancPluginCppWrapper.h" | |
34 | ||
35 | #include <json/reader.h> | |
36 | #include <json/writer.h> | |
37 | ||
38 | ||
39 | namespace OrthancPlugins | |
40 | { | |
41 | void MemoryBuffer::Check(OrthancPluginErrorCode code) | |
42 | { | |
43 | if (code != OrthancPluginErrorCode_Success) | |
44 | { | |
45 | // Prevent using garbage information | |
46 | buffer_.data = NULL; | |
47 | buffer_.size = 0; | |
48 | ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); | |
49 | } | |
50 | } | |
51 | ||
52 | ||
53 | bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code) | |
54 | { | |
55 | if (code != OrthancPluginErrorCode_Success) | |
56 | { | |
57 | // Prevent using garbage information | |
58 | buffer_.data = NULL; | |
59 | buffer_.size = 0; | |
60 | } | |
61 | ||
62 | if (code == OrthancPluginErrorCode_Success) | |
63 | { | |
64 | return true; | |
65 | } | |
66 | else if (code == OrthancPluginErrorCode_UnknownResource || | |
67 | code == OrthancPluginErrorCode_InexistentItem) | |
68 | { | |
69 | return false; | |
70 | } | |
71 | else | |
72 | { | |
73 | ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); | |
74 | } | |
75 | } | |
76 | ||
77 | ||
78 | MemoryBuffer::MemoryBuffer(OrthancPluginContext* context) : | |
79 | context_(context) | |
80 | { | |
81 | buffer_.data = NULL; | |
82 | buffer_.size = 0; | |
83 | } | |
84 | ||
85 | ||
86 | void MemoryBuffer::Clear() | |
87 | { | |
88 | if (buffer_.data != NULL) | |
89 | { | |
90 | OrthancPluginFreeMemoryBuffer(context_, &buffer_); | |
91 | buffer_.data = NULL; | |
92 | buffer_.size = 0; | |
93 | } | |
94 | } | |
95 | ||
96 | ||
97 | void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other) | |
98 | { | |
99 | Clear(); | |
100 | ||
101 | buffer_.data = other.data; | |
102 | buffer_.size = other.size; | |
103 | ||
104 | other.data = NULL; | |
105 | other.size = 0; | |
106 | } | |
107 | ||
108 | ||
109 | void MemoryBuffer::ToString(std::string& target) const | |
110 | { | |
111 | if (buffer_.size == 0) | |
112 | { | |
113 | target.clear(); | |
114 | } | |
115 | else | |
116 | { | |
117 | target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size); | |
118 | } | |
119 | } | |
120 | ||
121 | ||
122 | void MemoryBuffer::ToJson(Json::Value& target) const | |
123 | { | |
124 | if (buffer_.data == NULL || | |
125 | buffer_.size == 0) | |
126 | { | |
127 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
128 | } | |
129 | ||
130 | const char* tmp = reinterpret_cast<const char*>(buffer_.data); | |
131 | ||
132 | Json::Reader reader; | |
133 | if (!reader.parse(tmp, tmp + buffer_.size, target)) | |
134 | { | |
135 | OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON"); | |
136 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
137 | } | |
138 | } | |
139 | ||
140 | ||
141 | bool MemoryBuffer::RestApiGet(const std::string& uri, | |
142 | bool applyPlugins) | |
143 | { | |
144 | Clear(); | |
145 | ||
146 | if (applyPlugins) | |
147 | { | |
148 | return CheckHttp(OrthancPluginRestApiGetAfterPlugins(context_, &buffer_, uri.c_str())); | |
149 | } | |
150 | else | |
151 | { | |
152 | return CheckHttp(OrthancPluginRestApiGet(context_, &buffer_, uri.c_str())); | |
153 | } | |
154 | } | |
155 | ||
156 | ||
157 | bool MemoryBuffer::RestApiPost(const std::string& uri, | |
158 | const char* body, | |
159 | size_t bodySize, | |
160 | bool applyPlugins) | |
161 | { | |
162 | Clear(); | |
163 | ||
164 | if (applyPlugins) | |
165 | { | |
166 | return CheckHttp(OrthancPluginRestApiPostAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize)); | |
167 | } | |
168 | else | |
169 | { | |
170 | return CheckHttp(OrthancPluginRestApiPost(context_, &buffer_, uri.c_str(), body, bodySize)); | |
171 | } | |
172 | } | |
173 | ||
174 | ||
175 | bool MemoryBuffer::RestApiPut(const std::string& uri, | |
176 | const char* body, | |
177 | size_t bodySize, | |
178 | bool applyPlugins) | |
179 | { | |
180 | Clear(); | |
181 | ||
182 | if (applyPlugins) | |
183 | { | |
184 | return CheckHttp(OrthancPluginRestApiPutAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize)); | |
185 | } | |
186 | else | |
187 | { | |
188 | return CheckHttp(OrthancPluginRestApiPut(context_, &buffer_, uri.c_str(), body, bodySize)); | |
189 | } | |
190 | } | |
191 | ||
192 | ||
193 | bool MemoryBuffer::RestApiPost(const std::string& uri, | |
194 | const Json::Value& body, | |
195 | bool applyPlugins) | |
196 | { | |
197 | Json::FastWriter writer; | |
198 | return RestApiPost(uri, writer.write(body), applyPlugins); | |
199 | } | |
200 | ||
201 | ||
202 | bool MemoryBuffer::RestApiPut(const std::string& uri, | |
203 | const Json::Value& body, | |
204 | bool applyPlugins) | |
205 | { | |
206 | Json::FastWriter writer; | |
207 | return RestApiPut(uri, writer.write(body), applyPlugins); | |
208 | } | |
209 | ||
210 | ||
211 | void MemoryBuffer::CreateDicom(const Json::Value& tags, | |
212 | OrthancPluginCreateDicomFlags flags) | |
213 | { | |
214 | Clear(); | |
215 | ||
216 | Json::FastWriter writer; | |
217 | std::string s = writer.write(tags); | |
218 | ||
219 | Check(OrthancPluginCreateDicom(context_, &buffer_, s.c_str(), NULL, flags)); | |
220 | } | |
221 | ||
222 | ||
223 | void MemoryBuffer::ReadFile(const std::string& path) | |
224 | { | |
225 | Clear(); | |
226 | Check(OrthancPluginReadFile(context_, &buffer_, path.c_str())); | |
227 | } | |
228 | ||
229 | ||
230 | void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query) | |
231 | { | |
232 | Clear(); | |
233 | Check(OrthancPluginWorklistGetDicomQuery(context_, &buffer_, query)); | |
234 | } | |
235 | ||
236 | ||
237 | void OrthancString::Assign(char* str) | |
238 | { | |
239 | if (str == NULL) | |
240 | { | |
241 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
242 | } | |
243 | else | |
244 | { | |
245 | Clear(); | |
246 | str_ = str; | |
247 | } | |
248 | } | |
249 | ||
250 | ||
251 | void OrthancString::Clear() | |
252 | { | |
253 | if (str_ != NULL) | |
254 | { | |
255 | OrthancPluginFreeString(context_, str_); | |
256 | str_ = NULL; | |
257 | } | |
258 | } | |
259 | ||
260 | ||
261 | void OrthancString::ToString(std::string& target) const | |
262 | { | |
263 | if (str_ == NULL) | |
264 | { | |
265 | target.clear(); | |
266 | } | |
267 | else | |
268 | { | |
269 | target.assign(str_); | |
270 | } | |
271 | } | |
272 | ||
273 | ||
274 | void OrthancString::ToJson(Json::Value& target) const | |
275 | { | |
276 | if (str_ == NULL) | |
277 | { | |
278 | OrthancPluginLogError(context_, "Cannot convert an empty memory buffer to JSON"); | |
279 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
280 | } | |
281 | ||
282 | Json::Reader reader; | |
283 | if (!reader.parse(str_, target)) | |
284 | { | |
285 | OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON"); | |
286 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
287 | } | |
288 | } | |
289 | ||
290 | ||
291 | void MemoryBuffer::DicomToJson(Json::Value& target, | |
292 | OrthancPluginDicomToJsonFormat format, | |
293 | OrthancPluginDicomToJsonFlags flags, | |
294 | uint32_t maxStringLength) | |
295 | { | |
296 | OrthancString str(context_); | |
297 | str.Assign(OrthancPluginDicomBufferToJson(context_, GetData(), GetSize(), format, flags, maxStringLength)); | |
298 | str.ToJson(target); | |
299 | } | |
300 | ||
301 | ||
302 | bool MemoryBuffer::HttpGet(const std::string& url, | |
303 | const std::string& username, | |
304 | const std::string& password) | |
305 | { | |
306 | Clear(); | |
307 | return CheckHttp(OrthancPluginHttpGet(context_, &buffer_, url.c_str(), | |
308 | username.empty() ? NULL : username.c_str(), | |
309 | password.empty() ? NULL : password.c_str())); | |
310 | } | |
311 | ||
312 | ||
313 | bool MemoryBuffer::HttpPost(const std::string& url, | |
314 | const std::string& body, | |
315 | const std::string& username, | |
316 | const std::string& password) | |
317 | { | |
318 | Clear(); | |
319 | return CheckHttp(OrthancPluginHttpPost(context_, &buffer_, url.c_str(), | |
320 | body.c_str(), body.size(), | |
321 | username.empty() ? NULL : username.c_str(), | |
322 | password.empty() ? NULL : password.c_str())); | |
323 | } | |
324 | ||
325 | ||
326 | bool MemoryBuffer::HttpPut(const std::string& url, | |
327 | const std::string& body, | |
328 | const std::string& username, | |
329 | const std::string& password) | |
330 | { | |
331 | Clear(); | |
332 | return CheckHttp(OrthancPluginHttpPut(context_, &buffer_, url.c_str(), | |
333 | body.empty() ? NULL : body.c_str(), | |
334 | body.size(), | |
335 | username.empty() ? NULL : username.c_str(), | |
336 | password.empty() ? NULL : password.c_str())); | |
337 | } | |
338 | ||
339 | ||
340 | bool HttpDelete(OrthancPluginContext* context_, | |
341 | const std::string& url, | |
342 | const std::string& username, | |
343 | const std::string& password) | |
344 | { | |
345 | OrthancPluginErrorCode error = OrthancPluginHttpDelete | |
346 | (context_, url.c_str(), | |
347 | username.empty() ? NULL : username.c_str(), | |
348 | password.empty() ? NULL : password.c_str()); | |
349 | ||
350 | if (error == OrthancPluginErrorCode_Success) | |
351 | { | |
352 | return true; | |
353 | } | |
354 | else if (error == OrthancPluginErrorCode_UnknownResource || | |
355 | error == OrthancPluginErrorCode_InexistentItem) | |
356 | { | |
357 | return false; | |
358 | } | |
359 | else | |
360 | { | |
361 | ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error); | |
362 | } | |
363 | } | |
364 | ||
365 | ||
366 | OrthancConfiguration::OrthancConfiguration(OrthancPluginContext* context) : | |
367 | context_(context) | |
368 | { | |
369 | OrthancString str(context); | |
370 | str.Assign(OrthancPluginGetConfiguration(context)); | |
371 | ||
372 | if (str.GetContent() == NULL) | |
373 | { | |
374 | OrthancPluginLogError(context, "Cannot access the Orthanc configuration"); | |
375 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
376 | } | |
377 | ||
378 | str.ToJson(configuration_); | |
379 | ||
380 | if (configuration_.type() != Json::objectValue) | |
381 | { | |
382 | OrthancPluginLogError(context, "Unable to read the Orthanc configuration"); | |
383 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
384 | } | |
385 | } | |
386 | ||
387 | ||
388 | OrthancPluginContext* OrthancConfiguration::GetContext() const | |
389 | { | |
390 | if (context_ == NULL) | |
391 | { | |
392 | ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin); | |
393 | } | |
394 | else | |
395 | { | |
396 | return context_; | |
397 | } | |
398 | } | |
399 | ||
400 | ||
401 | std::string OrthancConfiguration::GetPath(const std::string& key) const | |
402 | { | |
403 | if (path_.empty()) | |
404 | { | |
405 | return key; | |
406 | } | |
407 | else | |
408 | { | |
409 | return path_ + "." + key; | |
410 | } | |
411 | } | |
412 | ||
413 | ||
414 | bool OrthancConfiguration::IsSection(const std::string& key) const | |
415 | { | |
416 | assert(configuration_.type() == Json::objectValue); | |
417 | ||
418 | return (configuration_.isMember(key) && | |
419 | configuration_[key].type() == Json::objectValue); | |
420 | } | |
421 | ||
422 | ||
423 | void OrthancConfiguration::GetSection(OrthancConfiguration& target, | |
424 | const std::string& key) const | |
425 | { | |
426 | assert(configuration_.type() == Json::objectValue); | |
427 | ||
428 | target.context_ = context_; | |
429 | target.path_ = GetPath(key); | |
430 | ||
431 | if (!configuration_.isMember(key)) | |
432 | { | |
433 | target.configuration_ = Json::objectValue; | |
434 | } | |
435 | else | |
436 | { | |
437 | if (configuration_[key].type() != Json::objectValue) | |
438 | { | |
439 | if (context_ != NULL) | |
440 | { | |
441 | std::string s = "The configuration section \"" + target.path_ + "\" is not an associative array as expected"; | |
442 | OrthancPluginLogError(context_, s.c_str()); | |
443 | } | |
444 | ||
445 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
446 | } | |
447 | ||
448 | target.configuration_ = configuration_[key]; | |
449 | } | |
450 | } | |
451 | ||
452 | ||
453 | bool OrthancConfiguration::LookupStringValue(std::string& target, | |
454 | const std::string& key) const | |
455 | { | |
456 | assert(configuration_.type() == Json::objectValue); | |
457 | ||
458 | if (!configuration_.isMember(key)) | |
459 | { | |
460 | return false; | |
461 | } | |
462 | ||
463 | if (configuration_[key].type() != Json::stringValue) | |
464 | { | |
465 | if (context_ != NULL) | |
466 | { | |
467 | std::string s = "The configuration option \"" + GetPath(key) + "\" is not a string as expected"; | |
468 | OrthancPluginLogError(context_, s.c_str()); | |
469 | } | |
470 | ||
471 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
472 | } | |
473 | ||
474 | target = configuration_[key].asString(); | |
475 | return true; | |
476 | } | |
477 | ||
478 | ||
479 | bool OrthancConfiguration::LookupIntegerValue(int& target, | |
480 | const std::string& key) const | |
481 | { | |
482 | assert(configuration_.type() == Json::objectValue); | |
483 | ||
484 | if (!configuration_.isMember(key)) | |
485 | { | |
486 | return false; | |
487 | } | |
488 | ||
489 | switch (configuration_[key].type()) | |
490 | { | |
491 | case Json::intValue: | |
492 | target = configuration_[key].asInt(); | |
493 | return true; | |
494 | ||
495 | case Json::uintValue: | |
496 | target = configuration_[key].asUInt(); | |
497 | return true; | |
498 | ||
499 | default: | |
500 | if (context_ != NULL) | |
501 | { | |
502 | std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected"; | |
503 | OrthancPluginLogError(context_, s.c_str()); | |
504 | } | |
505 | ||
506 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
507 | } | |
508 | } | |
509 | ||
510 | ||
511 | bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target, | |
512 | const std::string& key) const | |
513 | { | |
514 | int tmp; | |
515 | if (!LookupIntegerValue(tmp, key)) | |
516 | { | |
517 | return false; | |
518 | } | |
519 | ||
520 | if (tmp < 0) | |
521 | { | |
522 | if (context_ != NULL) | |
523 | { | |
524 | std::string s = "The configuration option \"" + GetPath(key) + "\" is not a positive integer as expected"; | |
525 | OrthancPluginLogError(context_, s.c_str()); | |
526 | } | |
527 | ||
528 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
529 | } | |
530 | else | |
531 | { | |
532 | target = static_cast<unsigned int>(tmp); | |
533 | return true; | |
534 | } | |
535 | } | |
536 | ||
537 | ||
538 | bool OrthancConfiguration::LookupBooleanValue(bool& target, | |
539 | const std::string& key) const | |
540 | { | |
541 | assert(configuration_.type() == Json::objectValue); | |
542 | ||
543 | if (!configuration_.isMember(key)) | |
544 | { | |
545 | return false; | |
546 | } | |
547 | ||
548 | if (configuration_[key].type() != Json::booleanValue) | |
549 | { | |
550 | if (context_ != NULL) | |
551 | { | |
552 | std::string s = "The configuration option \"" + GetPath(key) + "\" is not a Boolean as expected"; | |
553 | OrthancPluginLogError(context_, s.c_str()); | |
554 | } | |
555 | ||
556 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
557 | } | |
558 | ||
559 | target = configuration_[key].asBool(); | |
560 | return true; | |
561 | } | |
562 | ||
563 | ||
564 | bool OrthancConfiguration::LookupFloatValue(float& target, | |
565 | const std::string& key) const | |
566 | { | |
567 | assert(configuration_.type() == Json::objectValue); | |
568 | ||
569 | if (!configuration_.isMember(key)) | |
570 | { | |
571 | return false; | |
572 | } | |
573 | ||
574 | switch (configuration_[key].type()) | |
575 | { | |
576 | case Json::realValue: | |
577 | target = configuration_[key].asFloat(); | |
578 | return true; | |
579 | ||
580 | case Json::intValue: | |
581 | target = static_cast<float>(configuration_[key].asInt()); | |
582 | return true; | |
583 | ||
584 | case Json::uintValue: | |
585 | target = static_cast<float>(configuration_[key].asUInt()); | |
586 | return true; | |
587 | ||
588 | default: | |
589 | if (context_ != NULL) | |
590 | { | |
591 | std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected"; | |
592 | OrthancPluginLogError(context_, s.c_str()); | |
593 | } | |
594 | ||
595 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
596 | } | |
597 | } | |
598 | ||
599 | ||
600 | bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target, | |
601 | const std::string& key, | |
602 | bool allowSingleString) const | |
603 | { | |
604 | assert(configuration_.type() == Json::objectValue); | |
605 | ||
606 | target.clear(); | |
607 | ||
608 | if (!configuration_.isMember(key)) | |
609 | { | |
610 | return false; | |
611 | } | |
612 | ||
613 | switch (configuration_[key].type()) | |
614 | { | |
615 | case Json::arrayValue: | |
616 | { | |
617 | bool ok = true; | |
618 | ||
619 | for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++) | |
620 | { | |
621 | if (configuration_[key][i].type() == Json::stringValue) | |
622 | { | |
623 | target.push_back(configuration_[key][i].asString()); | |
624 | } | |
625 | else | |
626 | { | |
627 | ok = false; | |
628 | } | |
629 | } | |
630 | ||
631 | if (ok) | |
632 | { | |
633 | return true; | |
634 | } | |
635 | ||
636 | break; | |
637 | } | |
638 | ||
639 | case Json::stringValue: | |
640 | if (allowSingleString) | |
641 | { | |
642 | target.push_back(configuration_[key].asString()); | |
643 | return true; | |
644 | } | |
645 | ||
646 | break; | |
647 | ||
648 | default: | |
649 | break; | |
650 | } | |
651 | ||
652 | if (context_ != NULL) | |
653 | { | |
654 | std::string s = ("The configuration option \"" + GetPath(key) + | |
655 | "\" is not a list of strings as expected"); | |
656 | OrthancPluginLogError(context_, s.c_str()); | |
657 | } | |
658 | ||
659 | ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | |
660 | } | |
661 | ||
662 | ||
663 | bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target, | |
664 | const std::string& key, | |
665 | bool allowSingleString) const | |
666 | { | |
667 | std::list<std::string> lst; | |
668 | ||
669 | if (LookupListOfStrings(lst, key, allowSingleString)) | |
670 | { | |
671 | target.clear(); | |
672 | ||
673 | for (std::list<std::string>::const_iterator | |
674 | it = lst.begin(); it != lst.end(); ++it) | |
675 | { | |
676 | target.insert(*it); | |
677 | } | |
678 | ||
679 | return true; | |
680 | } | |
681 | else | |
682 | { | |
683 | return false; | |
684 | } | |
685 | } | |
686 | ||
687 | ||
688 | std::string OrthancConfiguration::GetStringValue(const std::string& key, | |
689 | const std::string& defaultValue) const | |
690 | { | |
691 | std::string tmp; | |
692 | if (LookupStringValue(tmp, key)) | |
693 | { | |
694 | return tmp; | |
695 | } | |
696 | else | |
697 | { | |
698 | return defaultValue; | |
699 | } | |
700 | } | |
701 | ||
702 | ||
703 | int OrthancConfiguration::GetIntegerValue(const std::string& key, | |
704 | int defaultValue) const | |
705 | { | |
706 | int tmp; | |
707 | if (LookupIntegerValue(tmp, key)) | |
708 | { | |
709 | return tmp; | |
710 | } | |
711 | else | |
712 | { | |
713 | return defaultValue; | |
714 | } | |
715 | } | |
716 | ||
717 | ||
718 | unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key, | |
719 | unsigned int defaultValue) const | |
720 | { | |
721 | unsigned int tmp; | |
722 | if (LookupUnsignedIntegerValue(tmp, key)) | |
723 | { | |
724 | return tmp; | |
725 | } | |
726 | else | |
727 | { | |
728 | return defaultValue; | |
729 | } | |
730 | } | |
731 | ||
732 | ||
733 | bool OrthancConfiguration::GetBooleanValue(const std::string& key, | |
734 | bool defaultValue) const | |
735 | { | |
736 | bool tmp; | |
737 | if (LookupBooleanValue(tmp, key)) | |
738 | { | |
739 | return tmp; | |
740 | } | |
741 | else | |
742 | { | |
743 | return defaultValue; | |
744 | } | |
745 | } | |
746 | ||
747 | ||
748 | float OrthancConfiguration::GetFloatValue(const std::string& key, | |
749 | float defaultValue) const | |
750 | { | |
751 | float tmp; | |
752 | if (LookupFloatValue(tmp, key)) | |
753 | { | |
754 | return tmp; | |
755 | } | |
756 | else | |
757 | { | |
758 | return defaultValue; | |
759 | } | |
760 | } | |
761 | ||
762 | ||
763 | void OrthancImage::Clear() | |
764 | { | |
765 | if (image_ != NULL) | |
766 | { | |
767 | OrthancPluginFreeImage(context_, image_); | |
768 | image_ = NULL; | |
769 | } | |
770 | } | |
771 | ||
772 | ||
773 | void OrthancImage::CheckImageAvailable() | |
774 | { | |
775 | if (image_ == NULL) | |
776 | { | |
777 | OrthancPluginLogError(context_, "Trying to access a NULL image"); | |
778 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
779 | } | |
780 | } | |
781 | ||
782 | ||
783 | OrthancImage::OrthancImage(OrthancPluginContext* context) : | |
784 | context_(context), | |
785 | image_(NULL) | |
786 | { | |
787 | if (context == NULL) | |
788 | { | |
789 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
790 | } | |
791 | } | |
792 | ||
793 | ||
794 | OrthancImage::OrthancImage(OrthancPluginContext* context, | |
795 | OrthancPluginImage* image) : | |
796 | context_(context), | |
797 | image_(image) | |
798 | { | |
799 | if (context == NULL) | |
800 | { | |
801 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
802 | } | |
803 | } | |
804 | ||
805 | ||
806 | OrthancImage::OrthancImage(OrthancPluginContext* context, | |
807 | OrthancPluginPixelFormat format, | |
808 | uint32_t width, | |
809 | uint32_t height) : | |
810 | context_(context) | |
811 | { | |
812 | if (context == NULL) | |
813 | { | |
814 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
815 | } | |
816 | else | |
817 | { | |
818 | image_ = OrthancPluginCreateImage(context, format, width, height); | |
819 | } | |
820 | } | |
821 | ||
822 | ||
823 | void OrthancImage::UncompressPngImage(const void* data, | |
824 | size_t size) | |
825 | { | |
826 | Clear(); | |
827 | image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Png); | |
828 | if (image_ == NULL) | |
829 | { | |
830 | OrthancPluginLogError(context_, "Cannot uncompress a PNG image"); | |
831 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
832 | } | |
833 | } | |
834 | ||
835 | ||
836 | void OrthancImage::UncompressJpegImage(const void* data, | |
837 | size_t size) | |
838 | { | |
839 | Clear(); | |
840 | image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Jpeg); | |
841 | if (image_ == NULL) | |
842 | { | |
843 | OrthancPluginLogError(context_, "Cannot uncompress a JPEG image"); | |
844 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
845 | } | |
846 | } | |
847 | ||
848 | ||
849 | void OrthancImage::DecodeDicomImage(const void* data, | |
850 | size_t size, | |
851 | unsigned int frame) | |
852 | { | |
853 | Clear(); | |
854 | image_ = OrthancPluginDecodeDicomImage(context_, data, size, frame); | |
855 | if (image_ == NULL) | |
856 | { | |
857 | OrthancPluginLogError(context_, "Cannot uncompress a DICOM image"); | |
858 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
859 | } | |
860 | } | |
861 | ||
862 | ||
863 | OrthancPluginPixelFormat OrthancImage::GetPixelFormat() | |
864 | { | |
865 | CheckImageAvailable(); | |
866 | return OrthancPluginGetImagePixelFormat(context_, image_); | |
867 | } | |
868 | ||
869 | ||
870 | unsigned int OrthancImage::GetWidth() | |
871 | { | |
872 | CheckImageAvailable(); | |
873 | return OrthancPluginGetImageWidth(context_, image_); | |
874 | } | |
875 | ||
876 | ||
877 | unsigned int OrthancImage::GetHeight() | |
878 | { | |
879 | CheckImageAvailable(); | |
880 | return OrthancPluginGetImageHeight(context_, image_); | |
881 | } | |
882 | ||
883 | ||
884 | unsigned int OrthancImage::GetPitch() | |
885 | { | |
886 | CheckImageAvailable(); | |
887 | return OrthancPluginGetImagePitch(context_, image_); | |
888 | } | |
889 | ||
890 | ||
891 | const void* OrthancImage::GetBuffer() | |
892 | { | |
893 | CheckImageAvailable(); | |
894 | return OrthancPluginGetImageBuffer(context_, image_); | |
895 | } | |
896 | ||
897 | ||
898 | void OrthancImage::CompressPngImage(MemoryBuffer& target) | |
899 | { | |
900 | CheckImageAvailable(); | |
901 | ||
902 | OrthancPluginMemoryBuffer tmp; | |
903 | OrthancPluginCompressPngImage(context_, &tmp, GetPixelFormat(), | |
904 | GetWidth(), GetHeight(), GetPitch(), GetBuffer()); | |
905 | ||
906 | target.Assign(tmp); | |
907 | } | |
908 | ||
909 | ||
910 | void OrthancImage::CompressJpegImage(MemoryBuffer& target, | |
911 | uint8_t quality) | |
912 | { | |
913 | CheckImageAvailable(); | |
914 | ||
915 | OrthancPluginMemoryBuffer tmp; | |
916 | OrthancPluginCompressJpegImage(context_, &tmp, GetPixelFormat(), | |
917 | GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality); | |
918 | ||
919 | target.Assign(tmp); | |
920 | } | |
921 | ||
922 | ||
923 | void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output) | |
924 | { | |
925 | CheckImageAvailable(); | |
926 | OrthancPluginCompressAndAnswerPngImage(context_, output, GetPixelFormat(), | |
927 | GetWidth(), GetHeight(), GetPitch(), GetBuffer()); | |
928 | } | |
929 | ||
930 | ||
931 | void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output, | |
932 | uint8_t quality) | |
933 | { | |
934 | CheckImageAvailable(); | |
935 | OrthancPluginCompressAndAnswerJpegImage(context_, output, GetPixelFormat(), | |
936 | GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality); | |
937 | } | |
938 | ||
939 | ||
940 | ||
941 | #if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 | |
942 | FindMatcher::FindMatcher(OrthancPluginContext* context, | |
943 | const OrthancPluginWorklistQuery* worklist) : | |
944 | context_(context), | |
945 | matcher_(NULL), | |
946 | worklist_(worklist) | |
947 | { | |
948 | if (worklist_ == NULL) | |
949 | { | |
950 | ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange); | |
951 | } | |
952 | } | |
953 | ||
954 | ||
955 | void FindMatcher::SetupDicom(OrthancPluginContext* context, | |
956 | const void* query, | |
957 | uint32_t size) | |
958 | { | |
959 | context_ = context; | |
960 | worklist_ = NULL; | |
961 | ||
962 | matcher_ = OrthancPluginCreateFindMatcher(context_, query, size); | |
963 | if (matcher_ == NULL) | |
964 | { | |
965 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
966 | } | |
967 | } | |
968 | ||
969 | ||
970 | FindMatcher::~FindMatcher() | |
971 | { | |
972 | // The "worklist_" field | |
973 | ||
974 | if (matcher_ != NULL) | |
975 | { | |
976 | OrthancPluginFreeFindMatcher(context_, matcher_); | |
977 | } | |
978 | } | |
979 | ||
980 | ||
981 | ||
982 | bool FindMatcher::IsMatch(const void* dicom, | |
983 | uint32_t size) const | |
984 | { | |
985 | int32_t result; | |
986 | ||
987 | if (matcher_ != NULL) | |
988 | { | |
989 | result = OrthancPluginFindMatcherIsMatch(context_, matcher_, dicom, size); | |
990 | } | |
991 | else if (worklist_ != NULL) | |
992 | { | |
993 | result = OrthancPluginWorklistIsMatch(context_, worklist_, dicom, size); | |
994 | } | |
995 | else | |
996 | { | |
997 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
998 | } | |
999 | ||
1000 | if (result == 0) | |
1001 | { | |
1002 | return false; | |
1003 | } | |
1004 | else if (result == 1) | |
1005 | { | |
1006 | return true; | |
1007 | } | |
1008 | else | |
1009 | { | |
1010 | ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | |
1011 | } | |
1012 | } | |
1013 | ||
1014 | #endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */ | |
1015 | ||
1016 | ||
1017 | bool RestApiGet(Json::Value& result, | |
1018 | OrthancPluginContext* context, | |
1019 | const std::string& uri, | |
1020 | bool applyPlugins) | |
1021 | { | |
1022 | MemoryBuffer answer(context); | |
1023 | if (!answer.RestApiGet(uri, applyPlugins)) | |
1024 | { | |
1025 | return false; | |
1026 | } | |
1027 | else | |
1028 | { | |
1029 | answer.ToJson(result); | |
1030 | return true; | |
1031 | } | |
1032 | } | |
1033 | ||
1034 | ||
1035 | bool RestApiPost(Json::Value& result, | |
1036 | OrthancPluginContext* context, | |
1037 | const std::string& uri, | |
1038 | const char* body, | |
1039 | size_t bodySize, | |
1040 | bool applyPlugins) | |
1041 | { | |
1042 | MemoryBuffer answer(context); | |
1043 | if (!answer.RestApiPost(uri, body, bodySize, applyPlugins)) | |
1044 | { | |
1045 | return false; | |
1046 | } | |
1047 | else | |
1048 | { | |
1049 | answer.ToJson(result); | |
1050 | return true; | |
1051 | } | |
1052 | } | |
1053 | ||
1054 | ||
1055 | bool RestApiPost(Json::Value& result, | |
1056 | OrthancPluginContext* context, | |
1057 | const std::string& uri, | |
1058 | const Json::Value& body, | |
1059 | bool applyPlugins) | |
1060 | { | |
1061 | Json::FastWriter writer; | |
1062 | return RestApiPost(result, context, uri, writer.write(body), applyPlugins); | |
1063 | } | |
1064 | ||
1065 | ||
1066 | bool RestApiPut(Json::Value& result, | |
1067 | OrthancPluginContext* context, | |
1068 | const std::string& uri, | |
1069 | const char* body, | |
1070 | size_t bodySize, | |
1071 | bool applyPlugins) | |
1072 | { | |
1073 | MemoryBuffer answer(context); | |
1074 | if (!answer.RestApiPut(uri, body, bodySize, applyPlugins)) | |
1075 | { | |
1076 | return false; | |
1077 | } | |
1078 | else | |
1079 | { | |
1080 | answer.ToJson(result); | |
1081 | return true; | |
1082 | } | |
1083 | } | |
1084 | ||
1085 | ||
1086 | bool RestApiPut(Json::Value& result, | |
1087 | OrthancPluginContext* context, | |
1088 | const std::string& uri, | |
1089 | const Json::Value& body, | |
1090 | bool applyPlugins) | |
1091 | { | |
1092 | Json::FastWriter writer; | |
1093 | return RestApiPut(result, context, uri, writer.write(body), applyPlugins); | |
1094 | } | |
1095 | ||
1096 | ||
1097 | bool RestApiDelete(OrthancPluginContext* context, | |
1098 | const std::string& uri, | |
1099 | bool applyPlugins) | |
1100 | { | |
1101 | OrthancPluginErrorCode error; | |
1102 | ||
1103 | if (applyPlugins) | |
1104 | { | |
1105 | error = OrthancPluginRestApiDeleteAfterPlugins(context, uri.c_str()); | |
1106 | } | |
1107 | else | |
1108 | { | |
1109 | error = OrthancPluginRestApiDelete(context, uri.c_str()); | |
1110 | } | |
1111 | ||
1112 | if (error == OrthancPluginErrorCode_Success) | |
1113 | { | |
1114 | return true; | |
1115 | } | |
1116 | else if (error == OrthancPluginErrorCode_UnknownResource || | |
1117 | error == OrthancPluginErrorCode_InexistentItem) | |
1118 | { | |
1119 | return false; | |
1120 | } | |
1121 | else | |
1122 | { | |
1123 | ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error); | |
1124 | } | |
1125 | } | |
1126 | ||
1127 | ||
1128 | void ReportMinimalOrthancVersion(OrthancPluginContext* context, | |
1129 | unsigned int major, | |
1130 | unsigned int minor, | |
1131 | unsigned int revision) | |
1132 | { | |
1133 | std::string s = ("Your version of the Orthanc core (" + | |
1134 | std::string(context->orthancVersion) + | |
1135 | ") is too old to run this plugin (version " + | |
1136 | boost::lexical_cast<std::string>(major) + "." + | |
1137 | boost::lexical_cast<std::string>(minor) + "." + | |
1138 | boost::lexical_cast<std::string>(revision) + | |
1139 | " is required)"); | |
1140 | ||
1141 | OrthancPluginLogError(context, s.c_str()); | |
1142 | } | |
1143 | ||
1144 | ||
1145 | bool CheckMinimalOrthancVersion(OrthancPluginContext* context, | |
1146 | unsigned int major, | |
1147 | unsigned int minor, | |
1148 | unsigned int revision) | |
1149 | { | |
1150 | if (context == NULL) | |
1151 | { | |
1152 | OrthancPluginLogError(context, "Bad Orthanc context in the plugin"); | |
1153 | return false; | |
1154 | } | |
1155 | ||
1156 | if (!strcmp(context->orthancVersion, "mainline")) | |
1157 | { | |
1158 | // Assume compatibility with the mainline | |
1159 | return true; | |
1160 | } | |
1161 | ||
1162 | // Parse the version of the Orthanc core | |
1163 | int aa, bb, cc; | |
1164 | if ( | |
1165 | #ifdef _MSC_VER | |
1166 | sscanf_s | |
1167 | #else | |
1168 | sscanf | |
1169 | #endif | |
1170 | (context->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || | |
1171 | aa < 0 || | |
1172 | bb < 0 || | |
1173 | cc < 0) | |
1174 | { | |
1175 | throw false; | |
1176 | } | |
1177 | ||
1178 | unsigned int a = static_cast<unsigned int>(aa); | |
1179 | unsigned int b = static_cast<unsigned int>(bb); | |
1180 | unsigned int c = static_cast<unsigned int>(cc); | |
1181 | ||
1182 | // Check the major version number | |
1183 | ||
1184 | if (a > major) | |
1185 | { | |
1186 | return true; | |
1187 | } | |
1188 | ||
1189 | if (a < major) | |
1190 | { | |
1191 | return false; | |
1192 | } | |
1193 | ||
1194 | ||
1195 | // Check the minor version number | |
1196 | assert(a == major); | |
1197 | ||
1198 | if (b > minor) | |
1199 | { | |
1200 | return true; | |
1201 | } | |
1202 | ||
1203 | if (b < minor) | |
1204 | { | |
1205 | return false; | |
1206 | } | |
1207 | ||
1208 | // Check the patch level version number | |
1209 | assert(a == major && b == minor); | |
1210 | ||
1211 | if (c >= revision) | |
1212 | { | |
1213 | return true; | |
1214 | } | |
1215 | else | |
1216 | { | |
1217 | return false; | |
1218 | } | |
1219 | } | |
1220 | } | |
1221 |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #include "OrthancPluginException.h" | |
36 | ||
37 | #include <orthanc/OrthancCPlugin.h> | |
38 | #include <boost/noncopyable.hpp> | |
39 | #include <boost/lexical_cast.hpp> | |
40 | #include <json/value.h> | |
41 | #include <list> | |
42 | #include <set> | |
43 | ||
44 | ||
45 | ||
46 | #define ORTHANC_PLUGINS_VERSION_IS_ABOVE(major, minor, revision) \ | |
47 | (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER > major || \ | |
48 | (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER == major && \ | |
49 | (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER > minor || \ | |
50 | (ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER == minor && \ | |
51 | ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER >= revision)))) | |
52 | ||
53 | ||
54 | #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0) | |
55 | // The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0 | |
56 | # define HAS_ORTHANC_PLUGIN_FIND_MATCHER 1 | |
57 | #else | |
58 | # define HAS_ORTHANC_PLUGIN_FIND_MATCHER 0 | |
59 | #endif | |
60 | ||
61 | ||
62 | ||
63 | namespace OrthancPlugins | |
64 | { | |
65 | typedef void (*RestCallback) (OrthancPluginRestOutput* output, | |
66 | const char* url, | |
67 | const OrthancPluginHttpRequest* request); | |
68 | ||
69 | class MemoryBuffer : public boost::noncopyable | |
70 | { | |
71 | private: | |
72 | OrthancPluginContext* context_; | |
73 | OrthancPluginMemoryBuffer buffer_; | |
74 | ||
75 | void Check(OrthancPluginErrorCode code); | |
76 | ||
77 | bool CheckHttp(OrthancPluginErrorCode code); | |
78 | ||
79 | public: | |
80 | MemoryBuffer(OrthancPluginContext* context); | |
81 | ||
82 | ~MemoryBuffer() | |
83 | { | |
84 | Clear(); | |
85 | } | |
86 | ||
87 | OrthancPluginMemoryBuffer* operator*() | |
88 | { | |
89 | return &buffer_; | |
90 | } | |
91 | ||
92 | // This transfers ownership | |
93 | void Assign(OrthancPluginMemoryBuffer& other); | |
94 | ||
95 | const char* GetData() const | |
96 | { | |
97 | if (buffer_.size > 0) | |
98 | { | |
99 | return reinterpret_cast<const char*>(buffer_.data); | |
100 | } | |
101 | else | |
102 | { | |
103 | return NULL; | |
104 | } | |
105 | } | |
106 | ||
107 | size_t GetSize() const | |
108 | { | |
109 | return buffer_.size; | |
110 | } | |
111 | ||
112 | void Clear(); | |
113 | ||
114 | void ToString(std::string& target) const; | |
115 | ||
116 | void ToJson(Json::Value& target) const; | |
117 | ||
118 | bool RestApiGet(const std::string& uri, | |
119 | bool applyPlugins); | |
120 | ||
121 | bool RestApiPost(const std::string& uri, | |
122 | const char* body, | |
123 | size_t bodySize, | |
124 | bool applyPlugins); | |
125 | ||
126 | bool RestApiPut(const std::string& uri, | |
127 | const char* body, | |
128 | size_t bodySize, | |
129 | bool applyPlugins); | |
130 | ||
131 | bool RestApiPost(const std::string& uri, | |
132 | const Json::Value& body, | |
133 | bool applyPlugins); | |
134 | ||
135 | bool RestApiPut(const std::string& uri, | |
136 | const Json::Value& body, | |
137 | bool applyPlugins); | |
138 | ||
139 | bool RestApiPost(const std::string& uri, | |
140 | const std::string& body, | |
141 | bool applyPlugins) | |
142 | { | |
143 | return RestApiPost(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins); | |
144 | } | |
145 | ||
146 | bool RestApiPut(const std::string& uri, | |
147 | const std::string& body, | |
148 | bool applyPlugins) | |
149 | { | |
150 | return RestApiPut(uri, body.empty() ? NULL : body.c_str(), body.size(), applyPlugins); | |
151 | } | |
152 | ||
153 | void CreateDicom(const Json::Value& tags, | |
154 | OrthancPluginCreateDicomFlags flags); | |
155 | ||
156 | void ReadFile(const std::string& path); | |
157 | ||
158 | void GetDicomQuery(const OrthancPluginWorklistQuery* query); | |
159 | ||
160 | void DicomToJson(Json::Value& target, | |
161 | OrthancPluginDicomToJsonFormat format, | |
162 | OrthancPluginDicomToJsonFlags flags, | |
163 | uint32_t maxStringLength); | |
164 | ||
165 | bool HttpGet(const std::string& url, | |
166 | const std::string& username, | |
167 | const std::string& password); | |
168 | ||
169 | bool HttpPost(const std::string& url, | |
170 | const std::string& body, | |
171 | const std::string& username, | |
172 | const std::string& password); | |
173 | ||
174 | bool HttpPut(const std::string& url, | |
175 | const std::string& body, | |
176 | const std::string& username, | |
177 | const std::string& password); | |
178 | }; | |
179 | ||
180 | ||
181 | class OrthancString : public boost::noncopyable | |
182 | { | |
183 | private: | |
184 | OrthancPluginContext* context_; | |
185 | char* str_; | |
186 | ||
187 | void Clear(); | |
188 | ||
189 | public: | |
190 | OrthancString(OrthancPluginContext* context) : | |
191 | context_(context), | |
192 | str_(NULL) | |
193 | { | |
194 | } | |
195 | ||
196 | ~OrthancString() | |
197 | { | |
198 | Clear(); | |
199 | } | |
200 | ||
201 | // This transfers ownership, warning: The string must have been | |
202 | // allocated by the Orthanc core | |
203 | void Assign(char* str); | |
204 | ||
205 | const char* GetContent() const | |
206 | { | |
207 | return str_; | |
208 | } | |
209 | ||
210 | void ToString(std::string& target) const; | |
211 | ||
212 | void ToJson(Json::Value& target) const; | |
213 | }; | |
214 | ||
215 | ||
216 | class OrthancConfiguration : public boost::noncopyable | |
217 | { | |
218 | private: | |
219 | OrthancPluginContext* context_; | |
220 | Json::Value configuration_; // Necessarily a Json::objectValue | |
221 | std::string path_; | |
222 | ||
223 | std::string GetPath(const std::string& key) const; | |
224 | ||
225 | public: | |
226 | OrthancConfiguration() : context_(NULL) | |
227 | { | |
228 | } | |
229 | ||
230 | OrthancConfiguration(OrthancPluginContext* context); | |
231 | ||
232 | OrthancPluginContext* GetContext() const; | |
233 | ||
234 | const Json::Value& GetJson() const | |
235 | { | |
236 | return configuration_; | |
237 | } | |
238 | ||
239 | bool IsSection(const std::string& key) const; | |
240 | ||
241 | void GetSection(OrthancConfiguration& target, | |
242 | const std::string& key) const; | |
243 | ||
244 | bool LookupStringValue(std::string& target, | |
245 | const std::string& key) const; | |
246 | ||
247 | bool LookupIntegerValue(int& target, | |
248 | const std::string& key) const; | |
249 | ||
250 | bool LookupUnsignedIntegerValue(unsigned int& target, | |
251 | const std::string& key) const; | |
252 | ||
253 | bool LookupBooleanValue(bool& target, | |
254 | const std::string& key) const; | |
255 | ||
256 | bool LookupFloatValue(float& target, | |
257 | const std::string& key) const; | |
258 | ||
259 | bool LookupListOfStrings(std::list<std::string>& target, | |
260 | const std::string& key, | |
261 | bool allowSingleString) const; | |
262 | ||
263 | bool LookupSetOfStrings(std::set<std::string>& target, | |
264 | const std::string& key, | |
265 | bool allowSingleString) const; | |
266 | ||
267 | std::string GetStringValue(const std::string& key, | |
268 | const std::string& defaultValue) const; | |
269 | ||
270 | int GetIntegerValue(const std::string& key, | |
271 | int defaultValue) const; | |
272 | ||
273 | unsigned int GetUnsignedIntegerValue(const std::string& key, | |
274 | unsigned int defaultValue) const; | |
275 | ||
276 | bool GetBooleanValue(const std::string& key, | |
277 | bool defaultValue) const; | |
278 | ||
279 | float GetFloatValue(const std::string& key, | |
280 | float defaultValue) const; | |
281 | }; | |
282 | ||
283 | class OrthancImage : public boost::noncopyable | |
284 | { | |
285 | private: | |
286 | OrthancPluginContext* context_; | |
287 | OrthancPluginImage* image_; | |
288 | ||
289 | void Clear(); | |
290 | ||
291 | void CheckImageAvailable(); | |
292 | ||
293 | public: | |
294 | OrthancImage(OrthancPluginContext* context); | |
295 | ||
296 | OrthancImage(OrthancPluginContext* context, | |
297 | OrthancPluginImage* image); | |
298 | ||
299 | OrthancImage(OrthancPluginContext* context, | |
300 | OrthancPluginPixelFormat format, | |
301 | uint32_t width, | |
302 | uint32_t height); | |
303 | ||
304 | ~OrthancImage() | |
305 | { | |
306 | Clear(); | |
307 | } | |
308 | ||
309 | void UncompressPngImage(const void* data, | |
310 | size_t size); | |
311 | ||
312 | void UncompressJpegImage(const void* data, | |
313 | size_t size); | |
314 | ||
315 | void DecodeDicomImage(const void* data, | |
316 | size_t size, | |
317 | unsigned int frame); | |
318 | ||
319 | OrthancPluginPixelFormat GetPixelFormat(); | |
320 | ||
321 | unsigned int GetWidth(); | |
322 | ||
323 | unsigned int GetHeight(); | |
324 | ||
325 | unsigned int GetPitch(); | |
326 | ||
327 | const void* GetBuffer(); | |
328 | ||
329 | void CompressPngImage(MemoryBuffer& target); | |
330 | ||
331 | void CompressJpegImage(MemoryBuffer& target, | |
332 | uint8_t quality); | |
333 | ||
334 | void AnswerPngImage(OrthancPluginRestOutput* output); | |
335 | ||
336 | void AnswerJpegImage(OrthancPluginRestOutput* output, | |
337 | uint8_t quality); | |
338 | }; | |
339 | ||
340 | ||
341 | #if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 | |
342 | class FindMatcher : public boost::noncopyable | |
343 | { | |
344 | private: | |
345 | OrthancPluginContext* context_; | |
346 | OrthancPluginFindMatcher* matcher_; | |
347 | const OrthancPluginWorklistQuery* worklist_; | |
348 | ||
349 | void SetupDicom(OrthancPluginContext* context, | |
350 | const void* query, | |
351 | uint32_t size); | |
352 | ||
353 | public: | |
354 | FindMatcher(OrthancPluginContext* context, | |
355 | const OrthancPluginWorklistQuery* worklist); | |
356 | ||
357 | FindMatcher(OrthancPluginContext* context, | |
358 | const void* query, | |
359 | uint32_t size) | |
360 | { | |
361 | SetupDicom(context, query, size); | |
362 | } | |
363 | ||
364 | FindMatcher(OrthancPluginContext* context, | |
365 | const MemoryBuffer& dicom) | |
366 | { | |
367 | SetupDicom(context, dicom.GetData(), dicom.GetSize()); | |
368 | } | |
369 | ||
370 | ~FindMatcher(); | |
371 | ||
372 | bool IsMatch(const void* dicom, | |
373 | uint32_t size) const; | |
374 | ||
375 | bool IsMatch(const MemoryBuffer& dicom) const | |
376 | { | |
377 | return IsMatch(dicom.GetData(), dicom.GetSize()); | |
378 | } | |
379 | }; | |
380 | #endif | |
381 | ||
382 | ||
383 | bool RestApiGet(Json::Value& result, | |
384 | OrthancPluginContext* context, | |
385 | const std::string& uri, | |
386 | bool applyPlugins); | |
387 | ||
388 | bool RestApiPost(Json::Value& result, | |
389 | OrthancPluginContext* context, | |
390 | const std::string& uri, | |
391 | const char* body, | |
392 | size_t bodySize, | |
393 | bool applyPlugins); | |
394 | ||
395 | bool RestApiPost(Json::Value& result, | |
396 | OrthancPluginContext* context, | |
397 | const std::string& uri, | |
398 | const Json::Value& body, | |
399 | bool applyPlugins); | |
400 | ||
401 | inline bool RestApiPost(Json::Value& result, | |
402 | OrthancPluginContext* context, | |
403 | const std::string& uri, | |
404 | const std::string& body, | |
405 | bool applyPlugins) | |
406 | { | |
407 | return RestApiPost(result, context, uri, body.empty() ? NULL : body.c_str(), | |
408 | body.size(), applyPlugins); | |
409 | } | |
410 | ||
411 | bool RestApiPut(Json::Value& result, | |
412 | OrthancPluginContext* context, | |
413 | const std::string& uri, | |
414 | const char* body, | |
415 | size_t bodySize, | |
416 | bool applyPlugins); | |
417 | ||
418 | bool RestApiPut(Json::Value& result, | |
419 | OrthancPluginContext* context, | |
420 | const std::string& uri, | |
421 | const Json::Value& body, | |
422 | bool applyPlugins); | |
423 | ||
424 | inline bool RestApiPut(Json::Value& result, | |
425 | OrthancPluginContext* context, | |
426 | const std::string& uri, | |
427 | const std::string& body, | |
428 | bool applyPlugins) | |
429 | { | |
430 | return RestApiPut(result, context, uri, body.empty() ? NULL : body.c_str(), | |
431 | body.size(), applyPlugins); | |
432 | } | |
433 | ||
434 | bool RestApiDelete(OrthancPluginContext* context, | |
435 | const std::string& uri, | |
436 | bool applyPlugins); | |
437 | ||
438 | bool HttpDelete(OrthancPluginContext* context, | |
439 | const std::string& url, | |
440 | const std::string& username, | |
441 | const std::string& password); | |
442 | ||
443 | inline void LogError(OrthancPluginContext* context, | |
444 | const std::string& message) | |
445 | { | |
446 | if (context != NULL) | |
447 | { | |
448 | OrthancPluginLogError(context, message.c_str()); | |
449 | } | |
450 | } | |
451 | ||
452 | inline void LogWarning(OrthancPluginContext* context, | |
453 | const std::string& message) | |
454 | { | |
455 | if (context != NULL) | |
456 | { | |
457 | OrthancPluginLogWarning(context, message.c_str()); | |
458 | } | |
459 | } | |
460 | ||
461 | inline void LogInfo(OrthancPluginContext* context, | |
462 | const std::string& message) | |
463 | { | |
464 | if (context != NULL) | |
465 | { | |
466 | OrthancPluginLogInfo(context, message.c_str()); | |
467 | } | |
468 | } | |
469 | ||
470 | void ReportMinimalOrthancVersion(OrthancPluginContext* context, | |
471 | unsigned int major, | |
472 | unsigned int minor, | |
473 | unsigned int revision); | |
474 | ||
475 | bool CheckMinimalOrthancVersion(OrthancPluginContext* context, | |
476 | unsigned int major, | |
477 | unsigned int minor, | |
478 | unsigned int revision); | |
479 | ||
480 | ||
481 | namespace Internals | |
482 | { | |
483 | template <RestCallback Callback> | |
484 | OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output, | |
485 | const char* url, | |
486 | const OrthancPluginHttpRequest* request) | |
487 | { | |
488 | try | |
489 | { | |
490 | Callback(output, url, request); | |
491 | return OrthancPluginErrorCode_Success; | |
492 | } | |
493 | catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | |
494 | { | |
495 | return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); | |
496 | } | |
497 | catch (boost::bad_lexical_cast&) | |
498 | { | |
499 | return OrthancPluginErrorCode_BadFileFormat; | |
500 | } | |
501 | catch (...) | |
502 | { | |
503 | return OrthancPluginErrorCode_Plugin; | |
504 | } | |
505 | } | |
506 | } | |
507 | ||
508 | ||
509 | template <RestCallback Callback> | |
510 | void RegisterRestCallback(OrthancPluginContext* context, | |
511 | const std::string& uri, | |
512 | bool isThreadSafe) | |
513 | { | |
514 | if (isThreadSafe) | |
515 | { | |
516 | OrthancPluginRegisterRestCallbackNoLock(context, uri.c_str(), Internals::Protect<Callback>); | |
517 | } | |
518 | else | |
519 | { | |
520 | OrthancPluginRegisterRestCallback(context, uri.c_str(), Internals::Protect<Callback>); | |
521 | } | |
522 | } | |
523 | } |
0 | /** | |
1 | * Orthanc - A Lightweight, RESTful DICOM Store | |
2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
3 | * Department, University Hospital of Liege, Belgium | |
4 | * Copyright (C) 2017 Osimis, Belgium | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, either version 3 of the | |
9 | * License, or (at your option) any later version. | |
10 | * | |
11 | * In addition, as a special exception, the copyright holders of this | |
12 | * program give permission to link the code of its release with the | |
13 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 | * that use the same license as the "OpenSSL" library), and distribute | |
15 | * the linked executables. You must obey the GNU General Public License | |
16 | * in all respects for all of the code used other than "OpenSSL". If you | |
17 | * modify file(s) with this exception, you may extend this exception to | |
18 | * your version of the file(s), but you are not obligated to do so. If | |
19 | * you do not wish to do so, delete this exception statement from your | |
20 | * version. If you delete this exception statement from all source files | |
21 | * in the program, then also delete it here. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 | **/ | |
31 | ||
32 | ||
33 | #pragma once | |
34 | ||
35 | #if !defined(HAS_ORTHANC_EXCEPTION) | |
36 | # error The macro HAS_ORTHANC_EXCEPTION must be defined | |
37 | #endif | |
38 | ||
39 | ||
40 | #if HAS_ORTHANC_EXCEPTION == 1 | |
41 | # include "../../../Core/OrthancException.h" | |
42 | # define ORTHANC_PLUGINS_ERROR_ENUMERATION ::Orthanc::ErrorCode | |
43 | # define ORTHANC_PLUGINS_EXCEPTION_CLASS ::Orthanc::OrthancException | |
44 | # define ORTHANC_PLUGINS_GET_ERROR_CODE(code) ::Orthanc::ErrorCode_ ## code | |
45 | #else | |
46 | # include <orthanc/OrthancCPlugin.h> | |
47 | # define ORTHANC_PLUGINS_ERROR_ENUMERATION ::OrthancPluginErrorCode | |
48 | # define ORTHANC_PLUGINS_EXCEPTION_CLASS ::OrthancPlugins::PluginException | |
49 | # define ORTHANC_PLUGINS_GET_ERROR_CODE(code) ::OrthancPluginErrorCode_ ## code | |
50 | #endif | |
51 | ||
52 | ||
53 | #define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code) \ | |
54 | throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code)); | |
55 | ||
56 | ||
57 | #define ORTHANC_PLUGINS_THROW_EXCEPTION(code) \ | |
58 | throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code)); | |
59 | ||
60 | ||
61 | #define ORTHANC_PLUGINS_CHECK_ERROR(code) \ | |
62 | if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success)) \ | |
63 | { \ | |
64 | ORTHANC_PLUGINS_THROW_EXCEPTION(code); \ | |
65 | } | |
66 | ||
67 | ||
68 | namespace OrthancPlugins | |
69 | { | |
70 | #if HAS_ORTHANC_EXCEPTION == 0 | |
71 | class PluginException | |
72 | { | |
73 | private: | |
74 | OrthancPluginErrorCode code_; | |
75 | ||
76 | public: | |
77 | explicit PluginException(OrthancPluginErrorCode code) : code_(code) | |
78 | { | |
79 | } | |
80 | ||
81 | OrthancPluginErrorCode GetErrorCode() const | |
82 | { | |
83 | return code_; | |
84 | } | |
85 | ||
86 | const char* What(OrthancPluginContext* context) const | |
87 | { | |
88 | const char* description = OrthancPluginGetErrorDescription(context, code_); | |
89 | if (description) | |
90 | { | |
91 | return description; | |
92 | } | |
93 | else | |
94 | { | |
95 | return "No description available"; | |
96 | } | |
97 | } | |
98 | }; | |
99 | #endif | |
100 | } |
0 | # This is a version-script for Orthanc plugins | |
1 | ||
2 | { | |
3 | global: | |
4 | OrthancPluginInitialize; | |
5 | OrthancPluginFinalize; | |
6 | OrthancPluginGetName; | |
7 | OrthancPluginGetVersion; | |
8 | ||
9 | local: | |
10 | *; | |
11 | }; |
0 | if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST) | |
1 | set(BOOST_STATIC 1) | |
2 | else() | |
3 | include(FindBoost) | |
4 | ||
5 | set(BOOST_STATIC 0) | |
6 | #set(Boost_DEBUG 1) | |
7 | #set(Boost_USE_STATIC_LIBS ON) | |
8 | ||
9 | find_package(Boost | |
10 | COMPONENTS filesystem thread system date_time regex locale ${ORTHANC_BOOST_COMPONENTS}) | |
11 | ||
12 | if (NOT Boost_FOUND) | |
13 | message(FATAL_ERROR "Unable to locate Boost on this system") | |
14 | endif() | |
15 | ||
16 | # Boost releases 1.44 through 1.47 supply both V2 and V3 filesystem | |
17 | # http://www.boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/index.htm | |
18 | if (${Boost_VERSION} LESS 104400) | |
19 | add_definitions( | |
20 | -DBOOST_HAS_FILESYSTEM_V3=0 | |
21 | ) | |
22 | else() | |
23 | add_definitions( | |
24 | -DBOOST_HAS_FILESYSTEM_V3=1 | |
25 | -DBOOST_FILESYSTEM_VERSION=3 | |
26 | ) | |
27 | endif() | |
28 | ||
29 | #if (${Boost_VERSION} LESS 104800) | |
30 | # boost::locale is only available from 1.48.00 | |
31 | #message("Too old version of Boost (${Boost_LIB_VERSION}): Building the static version") | |
32 | # set(BOOST_STATIC 1) | |
33 | #endif() | |
34 | ||
35 | include_directories(${Boost_INCLUDE_DIRS}) | |
36 | link_libraries(${Boost_LIBRARIES}) | |
37 | endif() | |
38 | ||
39 | ||
40 | if (BOOST_STATIC) | |
41 | # Parameters for Boost 1.60.0 | |
42 | set(BOOST_NAME boost_1_60_0) | |
43 | set(BOOST_BCP_SUFFIX bcpdigest-1.0.1) | |
44 | set(BOOST_MD5 "a789f8ec2056ad1c2d5f0cb64687cc7b") | |
45 | set(BOOST_URL "http://www.orthanc-server.com/downloads/third-party/${BOOST_NAME}_${BOOST_BCP_SUFFIX}.tar.gz") | |
46 | set(BOOST_FILESYSTEM_SOURCES_DIR "${BOOST_NAME}/libs/filesystem/src") | |
47 | set(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME}) | |
48 | ||
49 | DownloadPackage(${BOOST_MD5} ${BOOST_URL} "${BOOST_SOURCES_DIR}") | |
50 | ||
51 | set(BOOST_SOURCES) | |
52 | ||
53 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR | |
54 | ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR | |
55 | ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR | |
56 | ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR | |
57 | ${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR | |
58 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR | |
59 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64") | |
60 | list(APPEND BOOST_SOURCES | |
61 | ${BOOST_SOURCES_DIR}/libs/atomic/src/lockpool.cpp | |
62 | ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/once.cpp | |
63 | ${BOOST_SOURCES_DIR}/libs/thread/src/pthread/thread.cpp | |
64 | ) | |
65 | add_definitions( | |
66 | -DBOOST_LOCALE_WITH_ICONV=1 | |
67 | -DBOOST_LOCALE_NO_WINAPI_BACKEND=1 | |
68 | -DBOOST_LOCALE_NO_STD_BACKEND=1 | |
69 | ) | |
70 | ||
71 | if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase" OR | |
72 | ${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR | |
73 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR | |
74 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64") | |
75 | add_definitions(-DBOOST_HAS_SCHED_YIELD=1) | |
76 | endif() | |
77 | ||
78 | elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") | |
79 | list(APPEND BOOST_SOURCES | |
80 | ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_dll.cpp | |
81 | ${BOOST_SOURCES_DIR}/libs/thread/src/win32/thread.cpp | |
82 | ${BOOST_SOURCES_DIR}/libs/thread/src/win32/tss_pe.cpp | |
83 | ${BOOST_FILESYSTEM_SOURCES_DIR}/windows_file_codecvt.cpp | |
84 | ) | |
85 | ||
86 | # Starting with release 0.8.2, Orthanc statically links against | |
87 | # libiconv, even on Windows. Indeed, the "WCONV" library of | |
88 | # Windows XP seems not to support properly several codepages | |
89 | # (notably "Latin3", "Hebrew", and "Arabic"). | |
90 | ||
91 | if (USE_BOOST_ICONV) | |
92 | include(${ORTHANC_ROOT}/Resources/CMake/LibIconvConfiguration.cmake) | |
93 | else() | |
94 | add_definitions(-DBOOST_LOCALE_WITH_WCONV=1) | |
95 | endif() | |
96 | ||
97 | add_definitions( | |
98 | -DBOOST_LOCALE_NO_POSIX_BACKEND=1 | |
99 | -DBOOST_LOCALE_NO_STD_BACKEND=1 | |
100 | ) | |
101 | ||
102 | elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") | |
103 | add_definitions( | |
104 | -DBOOST_LOCALE_NO_POSIX_BACKEND=1 | |
105 | -DBOOST_LOCALE_NO_STD_BACKEND=1 | |
106 | ) | |
107 | ||
108 | else() | |
109 | message(FATAL_ERROR "Support your platform here") | |
110 | endif() | |
111 | ||
112 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") | |
113 | list(APPEND BOOST_SOURCES | |
114 | ${BOOST_SOURCES_DIR}/libs/filesystem/src/utf8_codecvt_facet.cpp | |
115 | ) | |
116 | endif() | |
117 | ||
118 | aux_source_directory(${BOOST_SOURCES_DIR}/libs/regex/src BOOST_REGEX_SOURCES) | |
119 | ||
120 | list(APPEND BOOST_SOURCES | |
121 | ${BOOST_REGEX_SOURCES} | |
122 | ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp | |
123 | ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp | |
124 | ) | |
125 | ||
126 | if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") | |
127 | list(APPEND BOOST_SOURCES | |
128 | ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.cpp | |
129 | ) | |
130 | endif() | |
131 | ||
132 | if (${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR | |
133 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR | |
134 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64") | |
135 | # boost::filesystem is not available on PNaCl | |
136 | add_definitions( | |
137 | -DBOOST_HAS_FILESYSTEM_V3=0 | |
138 | -D__INTEGRITY=1 | |
139 | ) | |
140 | else() | |
141 | add_definitions( | |
142 | -DBOOST_HAS_FILESYSTEM_V3=1 | |
143 | ) | |
144 | list(APPEND BOOST_SOURCES | |
145 | ${BOOST_FILESYSTEM_SOURCES_DIR}/codecvt_error_category.cpp | |
146 | ${BOOST_FILESYSTEM_SOURCES_DIR}/operations.cpp | |
147 | ${BOOST_FILESYSTEM_SOURCES_DIR}/path.cpp | |
148 | ${BOOST_FILESYSTEM_SOURCES_DIR}/path_traits.cpp | |
149 | ) | |
150 | endif() | |
151 | ||
152 | if (USE_BOOST_LOCALE_BACKENDS) | |
153 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR | |
154 | ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR | |
155 | ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR | |
156 | ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR | |
157 | ${CMAKE_SYSTEM_NAME} STREQUAL "PNaCl" OR | |
158 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl32" OR | |
159 | ${CMAKE_SYSTEM_NAME} STREQUAL "NaCl64") | |
160 | list(APPEND BOOST_SOURCES | |
161 | ${BOOST_SOURCES_DIR}/libs/locale/src/posix/codecvt.cpp | |
162 | ${BOOST_SOURCES_DIR}/libs/locale/src/posix/collate.cpp | |
163 | ${BOOST_SOURCES_DIR}/libs/locale/src/posix/converter.cpp | |
164 | ${BOOST_SOURCES_DIR}/libs/locale/src/posix/numeric.cpp | |
165 | ${BOOST_SOURCES_DIR}/libs/locale/src/posix/posix_backend.cpp | |
166 | ) | |
167 | elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") | |
168 | list(APPEND BOOST_SOURCES | |
169 | ${BOOST_SOURCES_DIR}/libs/locale/src/win32/collate.cpp | |
170 | ${BOOST_SOURCES_DIR}/libs/locale/src/win32/converter.cpp | |
171 | ${BOOST_SOURCES_DIR}/libs/locale/src/win32/lcid.cpp | |
172 | ${BOOST_SOURCES_DIR}/libs/locale/src/win32/numeric.cpp | |
173 | ${BOOST_SOURCES_DIR}/libs/locale/src/win32/win_backend.cpp | |
174 | ) | |
175 | else() | |
176 | message(FATAL_ERROR "Support your platform here") | |
177 | endif() | |
178 | ||
179 | list(APPEND BOOST_SOURCES | |
180 | ${BOOST_REGEX_SOURCES} | |
181 | ${BOOST_SOURCES_DIR}/libs/date_time/src/gregorian/greg_month.cpp | |
182 | ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp | |
183 | ||
184 | ${BOOST_FILESYSTEM_SOURCES_DIR}/codecvt_error_category.cpp | |
185 | ${BOOST_FILESYSTEM_SOURCES_DIR}/operations.cpp | |
186 | ${BOOST_FILESYSTEM_SOURCES_DIR}/path.cpp | |
187 | ${BOOST_FILESYSTEM_SOURCES_DIR}/path_traits.cpp | |
188 | ||
189 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/generator.cpp | |
190 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/date_time.cpp | |
191 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/formatting.cpp | |
192 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/ids.cpp | |
193 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/localization_backend.cpp | |
194 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/message.cpp | |
195 | ${BOOST_SOURCES_DIR}/libs/locale/src/shared/mo_lambda.cpp | |
196 | ${BOOST_SOURCES_DIR}/libs/locale/src/util/codecvt_converter.cpp | |
197 | ${BOOST_SOURCES_DIR}/libs/locale/src/util/default_locale.cpp | |
198 | ${BOOST_SOURCES_DIR}/libs/locale/src/util/gregorian.cpp | |
199 | ${BOOST_SOURCES_DIR}/libs/locale/src/util/info.cpp | |
200 | ${BOOST_SOURCES_DIR}/libs/locale/src/util/locale_data.cpp | |
201 | ) | |
202 | endif() | |
203 | ||
204 | add_definitions( | |
205 | # Static build of Boost | |
206 | -DBOOST_ALL_NO_LIB | |
207 | -DBOOST_ALL_NOLIB | |
208 | -DBOOST_DATE_TIME_NO_LIB | |
209 | -DBOOST_THREAD_BUILD_LIB | |
210 | -DBOOST_PROGRAM_OPTIONS_NO_LIB | |
211 | -DBOOST_REGEX_NO_LIB | |
212 | -DBOOST_SYSTEM_NO_LIB | |
213 | -DBOOST_LOCALE_NO_LIB | |
214 | -DBOOST_HAS_LOCALE=1 | |
215 | ) | |
216 | ||
217 | if (CMAKE_COMPILER_IS_GNUCXX) | |
218 | add_definitions(-isystem ${BOOST_SOURCES_DIR}) | |
219 | endif() | |
220 | ||
221 | include_directories( | |
222 | ${BOOST_SOURCES_DIR} | |
223 | ) | |
224 | ||
225 | source_group(ThirdParty\\boost REGULAR_EXPRESSION ${BOOST_SOURCES_DIR}/.*) | |
226 | ||
227 | else() | |
228 | add_definitions( | |
229 | -DBOOST_HAS_LOCALE=1 | |
230 | ) | |
231 | endif() | |
232 | ||
233 | ||
234 | add_definitions( | |
235 | -DBOOST_HAS_DATE_TIME=1 | |
236 | -DBOOST_HAS_REGEX=1 | |
237 | ) |
0 | # This file sets all the compiler-related flags | |
1 | ||
2 | if (CMAKE_CROSSCOMPILING) | |
3 | # Cross-compilation necessarily implies standalone and static build | |
4 | SET(STATIC_BUILD ON) | |
5 | SET(STANDALONE_BUILD ON) | |
6 | endif() | |
7 | ||
8 | if (CMAKE_COMPILER_IS_GNUCXX) | |
9 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -Wno-implicit-function-declaration") | |
10 | # --std=c99 makes libcurl not to compile | |
11 | # -pedantic gives a lot of warnings on OpenSSL | |
12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -Wno-variadic-macros") | |
13 | ||
14 | if (CMAKE_CROSSCOMPILING) | |
15 | # http://stackoverflow.com/a/3543845/881731 | |
16 | set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff -I<CMAKE_CURRENT_SOURCE_DIR> <SOURCE> <OBJECT>") | |
17 | endif() | |
18 | ||
19 | elseif (MSVC) | |
20 | # Use static runtime under Visual Studio | |
21 | # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace | |
22 | # http://stackoverflow.com/a/6510446 | |
23 | foreach(flag_var | |
24 | CMAKE_C_FLAGS_DEBUG | |
25 | CMAKE_CXX_FLAGS_DEBUG | |
26 | CMAKE_C_FLAGS_RELEASE | |
27 | CMAKE_CXX_FLAGS_RELEASE | |
28 | CMAKE_C_FLAGS_MINSIZEREL | |
29 | CMAKE_CXX_FLAGS_MINSIZEREL | |
30 | CMAKE_C_FLAGS_RELWITHDEBINFO | |
31 | CMAKE_CXX_FLAGS_RELWITHDEBINFO) | |
32 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") | |
33 | string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") | |
34 | endforeach(flag_var) | |
35 | ||
36 | # Add /Zm256 compiler option to Visual Studio to fix PCH errors | |
37 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm256") | |
38 | ||
39 | add_definitions( | |
40 | -D_CRT_SECURE_NO_WARNINGS=1 | |
41 | -D_CRT_SECURE_NO_DEPRECATE=1 | |
42 | ) | |
43 | ||
44 | if (MSVC_VERSION LESS 1600) | |
45 | # Starting with Visual Studio >= 2010 (i.e. macro _MSC_VER >= | |
46 | # 1600), Microsoft ships a standard-compliant <stdint.h> | |
47 | # header. For earlier versions of Visual Studio, give access to a | |
48 | # compatibility header. | |
49 | # http://stackoverflow.com/a/70630/881731 | |
50 | # https://en.wikibooks.org/wiki/C_Programming/C_Reference/stdint.h#External_links | |
51 | include_directories(${ORTHANC_ROOT}/Resources/ThirdParty/VisualStudio) | |
52 | endif() | |
53 | ||
54 | link_libraries(netapi32) | |
55 | endif() | |
56 | ||
57 | ||
58 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR | |
59 | ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR | |
60 | ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") | |
61 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") | |
62 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") | |
63 | ||
64 | if (NOT DEFINED ENABLE_PLUGINS_VERSION_SCRIPT OR | |
65 | ENABLE_PLUGINS_VERSION_SCRIPT) | |
66 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${ORTHANC_ROOT}/Plugins/Samples/Common/VersionScript.map") | |
67 | endif() | |
68 | ||
69 | # Remove the "-rdynamic" option | |
70 | # http://www.mail-archive.com/cmake@cmake.org/msg08837.html | |
71 | set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") | |
72 | link_libraries(uuid pthread rt) | |
73 | ||
74 | if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") | |
75 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") | |
76 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed") | |
77 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed") | |
78 | add_definitions( | |
79 | -D_LARGEFILE64_SOURCE=1 | |
80 | -D_FILE_OFFSET_BITS=64 | |
81 | ) | |
82 | link_libraries(dl) | |
83 | endif() | |
84 | ||
85 | CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H) | |
86 | if (NOT HAVE_UUID_H) | |
87 | message(FATAL_ERROR "Please install the uuid-dev package") | |
88 | endif() | |
89 | ||
90 | elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") | |
91 | if (MSVC) | |
92 | message("MSVC compiler version = " ${MSVC_VERSION} "\n") | |
93 | # Starting Visual Studio 2013 (version 1800), it is not possible | |
94 | # to target Windows XP anymore | |
95 | if (MSVC_VERSION LESS 1800) | |
96 | add_definitions( | |
97 | -DWINVER=0x0501 | |
98 | -D_WIN32_WINNT=0x0501 | |
99 | ) | |
100 | endif() | |
101 | else() | |
102 | add_definitions( | |
103 | -DWINVER=0x0501 | |
104 | -D_WIN32_WINNT=0x0501 | |
105 | ) | |
106 | endif() | |
107 | ||
108 | add_definitions( | |
109 | -D_CRT_SECURE_NO_WARNINGS=1 | |
110 | ) | |
111 | link_libraries(rpcrt4 ws2_32) | |
112 | ||
113 | if (CMAKE_COMPILER_IS_GNUCXX) | |
114 | # Some additional C/C++ compiler flags for MinGW | |
115 | SET(MINGW_NO_WARNINGS "-Wno-unused-function -Wno-unused-variable") | |
116 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MINGW_NO_WARNINGS} -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast") | |
117 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MINGW_NO_WARNINGS}") | |
118 | ||
119 | # This is a patch for MinGW64 | |
120 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++") | |
121 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++") | |
122 | ||
123 | CHECK_LIBRARY_EXISTS(winpthread pthread_create "" HAVE_WIN_PTHREAD) | |
124 | if (HAVE_WIN_PTHREAD) | |
125 | # This line is necessary to compile with recent versions of MinGW, | |
126 | # otherwise "libwinpthread-1.dll" is not statically linked. | |
127 | SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic") | |
128 | add_definitions(-DHAVE_WIN_PTHREAD=1) | |
129 | else() | |
130 | add_definitions(-DHAVE_WIN_PTHREAD=0) | |
131 | endif() | |
132 | endif() | |
133 | ||
134 | elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") | |
135 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${ORTHANC_ROOT}/Plugins/Samples/Common/ExportedSymbols.list") | |
136 | ||
137 | add_definitions( | |
138 | -D_XOPEN_SOURCE=1 | |
139 | ) | |
140 | link_libraries(iconv) | |
141 | ||
142 | CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H) | |
143 | if (NOT HAVE_UUID_H) | |
144 | message(FATAL_ERROR "Please install the uuid-dev package") | |
145 | endif() | |
146 | ||
147 | endif() | |
148 | ||
149 | ||
150 | if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase") | |
151 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include") | |
152 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward -fpermissive") | |
153 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH}") | |
154 | endif() | |
155 | ||
156 | ||
157 | if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") | |
158 | # In FreeBSD, the "/usr/local/" folder contains the ports and need to be imported | |
159 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include") | |
160 | SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include") | |
161 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib") | |
162 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/lib") | |
163 | endif() | |
164 | ||
165 | ||
166 | if (DEFINED ENABLE_PROFILING AND ENABLE_PROFILING) | |
167 | if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") | |
168 | message(WARNING "Enabling profiling on a non-debug build will not produce full information") | |
169 | endif() | |
170 | ||
171 | if (CMAKE_COMPILER_IS_GNUCXX) | |
172 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") | |
173 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") | |
174 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") | |
175 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pg") | |
176 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg") | |
177 | else() | |
178 | message(FATAL_ERROR "Don't know how to enable profiling on your configuration") | |
179 | endif() | |
180 | endif() | |
181 | ||
182 | ||
183 | if (STATIC_BUILD) | |
184 | add_definitions(-DORTHANC_STATIC=1) | |
185 | else() | |
186 | add_definitions(-DORTHANC_STATIC=0) | |
187 | endif() |
0 | macro(GetUrlFilename TargetVariable Url) | |
1 | string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}") | |
2 | endmacro() | |
3 | ||
4 | ||
5 | macro(GetUrlExtension TargetVariable Url) | |
6 | #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}") | |
7 | string(REGEX REPLACE "^.*\\." "" TMP "${Url}") | |
8 | string(TOLOWER "${TMP}" "${TargetVariable}") | |
9 | endmacro() | |
10 | ||
11 | ||
12 | ||
13 | ## | |
14 | ## Setup the patch command-line tool | |
15 | ## | |
16 | ||
17 | if (NOT ORTHANC_DISABLE_PATCH) | |
18 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") | |
19 | set(PATCH_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/../ThirdParty/patch/patch.exe) | |
20 | if (NOT EXISTS ${PATCH_EXECUTABLE}) | |
21 | message(FATAL_ERROR "Unable to find the patch.exe tool that is shipped with Orthanc") | |
22 | endif() | |
23 | ||
24 | else () | |
25 | find_program(PATCH_EXECUTABLE patch) | |
26 | if (${PATCH_EXECUTABLE} MATCHES "PATCH_EXECUTABLE-NOTFOUND") | |
27 | message(FATAL_ERROR "Please install the 'patch' standard command-line tool") | |
28 | endif() | |
29 | endif() | |
30 | endif() | |
31 | ||
32 | ||
33 | ||
34 | ## | |
35 | ## Check the existence of the required decompression tools | |
36 | ## | |
37 | ||
38 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") | |
39 | find_program(ZIP_EXECUTABLE 7z | |
40 | PATHS | |
41 | "$ENV{ProgramFiles}/7-Zip" | |
42 | "$ENV{ProgramW6432}/7-Zip" | |
43 | ) | |
44 | ||
45 | if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND") | |
46 | message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)") | |
47 | endif() | |
48 | ||
49 | else() | |
50 | find_program(UNZIP_EXECUTABLE unzip) | |
51 | if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND") | |
52 | message(FATAL_ERROR "Please install the 'unzip' package") | |
53 | endif() | |
54 | ||
55 | find_program(TAR_EXECUTABLE tar) | |
56 | if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND") | |
57 | message(FATAL_ERROR "Please install the 'tar' package") | |
58 | endif() | |
59 | endif() | |
60 | ||
61 | ||
62 | macro(DownloadPackage MD5 Url TargetDirectory) | |
63 | if (NOT IS_DIRECTORY "${TargetDirectory}") | |
64 | GetUrlFilename(TMP_FILENAME "${Url}") | |
65 | ||
66 | set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}") | |
67 | if (NOT EXISTS "${TMP_PATH}") | |
68 | message("Downloading ${Url}") | |
69 | ||
70 | # This fixes issue 6: "I think cmake shouldn't download the | |
71 | # packages which are not in the system, it should stop and let | |
72 | # user know." | |
73 | # https://code.google.com/p/orthanc/issues/detail?id=6 | |
74 | if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS) | |
75 | message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") | |
76 | endif() | |
77 | ||
78 | file(DOWNLOAD "${Url}" "${TMP_PATH}" | |
79 | SHOW_PROGRESS EXPECTED_MD5 "${MD5}" | |
80 | TIMEOUT 60 INACTIVITY_TIMEOUT 60) | |
81 | else() | |
82 | message("Using local copy of ${Url}") | |
83 | endif() | |
84 | ||
85 | GetUrlExtension(TMP_EXTENSION "${Url}") | |
86 | #message(${TMP_EXTENSION}) | |
87 | message("Uncompressing ${TMP_FILENAME}") | |
88 | ||
89 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") | |
90 | # How to silently extract files using 7-zip | |
91 | # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly | |
92 | ||
93 | if (("${TMP_EXTENSION}" STREQUAL "gz") OR | |
94 | ("${TMP_EXTENSION}" STREQUAL "tgz") OR | |
95 | ("${TMP_EXTENSION}" STREQUAL "xz")) | |
96 | execute_process( | |
97 | COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH} | |
98 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
99 | RESULT_VARIABLE Failure | |
100 | OUTPUT_QUIET | |
101 | ) | |
102 | ||
103 | if (Failure) | |
104 | message(FATAL_ERROR "Error while running the uncompression tool") | |
105 | endif() | |
106 | ||
107 | if ("${TMP_EXTENSION}" STREQUAL "tgz") | |
108 | string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}") | |
109 | elseif ("${TMP_EXTENSION}" STREQUAL "gz") | |
110 | string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}") | |
111 | elseif ("${TMP_EXTENSION}" STREQUAL "xz") | |
112 | string(REGEX REPLACE ".xz" "" TMP_FILENAME2 "${TMP_FILENAME}") | |
113 | endif() | |
114 | ||
115 | execute_process( | |
116 | COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2} | |
117 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
118 | RESULT_VARIABLE Failure | |
119 | OUTPUT_QUIET | |
120 | ) | |
121 | elseif ("${TMP_EXTENSION}" STREQUAL "zip") | |
122 | execute_process( | |
123 | COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH} | |
124 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
125 | RESULT_VARIABLE Failure | |
126 | OUTPUT_QUIET | |
127 | ) | |
128 | else() | |
129 | message(FATAL_ERROR "Support your platform here") | |
130 | endif() | |
131 | ||
132 | else() | |
133 | if ("${TMP_EXTENSION}" STREQUAL "zip") | |
134 | execute_process( | |
135 | COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}" | |
136 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
137 | RESULT_VARIABLE Failure | |
138 | ) | |
139 | elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) | |
140 | #message("tar xvfz ${TMP_PATH}") | |
141 | execute_process( | |
142 | COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}" | |
143 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
144 | RESULT_VARIABLE Failure | |
145 | ) | |
146 | elseif ("${TMP_EXTENSION}" STREQUAL "bz2") | |
147 | execute_process( | |
148 | COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}" | |
149 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
150 | RESULT_VARIABLE Failure | |
151 | ) | |
152 | elseif ("${TMP_EXTENSION}" STREQUAL "xz") | |
153 | execute_process( | |
154 | COMMAND sh -c "${TAR_EXECUTABLE} xf ${TMP_PATH}" | |
155 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
156 | RESULT_VARIABLE Failure | |
157 | ) | |
158 | else() | |
159 | message(FATAL_ERROR "Unknown package format.") | |
160 | endif() | |
161 | endif() | |
162 | ||
163 | if (Failure) | |
164 | message(FATAL_ERROR "Error while running the uncompression tool") | |
165 | endif() | |
166 | ||
167 | if (NOT IS_DIRECTORY "${TargetDirectory}") | |
168 | message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.") | |
169 | endif() | |
170 | endif() | |
171 | endmacro() |
0 | if (USE_GTEST_DEBIAN_SOURCE_PACKAGE) | |
1 | find_path(GTEST_DEBIAN_SOURCES_DIR | |
2 | NAMES src/gtest-all.cc | |
3 | PATHS | |
4 | /usr/src/gtest | |
5 | /usr/src/googletest/googletest | |
6 | PATH_SUFFIXES src | |
7 | ) | |
8 | ||
9 | find_path(GTEST_DEBIAN_INCLUDE_DIR | |
10 | NAMES gtest.h | |
11 | PATHS | |
12 | /usr/include/gtest | |
13 | ) | |
14 | ||
15 | message("Path to the Debian Google Test sources: ${GTEST_DEBIAN_SOURCES_DIR}") | |
16 | message("Path to the Debian Google Test includes: ${GTEST_DEBIAN_INCLUDE_DIR}") | |
17 | ||
18 | set(GTEST_SOURCES ${GTEST_DEBIAN_SOURCES_DIR}/src/gtest-all.cc) | |
19 | include_directories(${GTEST_DEBIAN_SOURCES_DIR}) | |
20 | ||
21 | if (NOT EXISTS ${GTEST_SOURCES} OR | |
22 | NOT EXISTS ${GTEST_DEBIAN_INCLUDE_DIR}/gtest.h) | |
23 | message(FATAL_ERROR "Please install the libgtest-dev package") | |
24 | endif() | |
25 | ||
26 | elseif (STATIC_BUILD OR NOT USE_SYSTEM_GOOGLE_TEST) | |
27 | set(GTEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/gtest-1.7.0) | |
28 | set(GTEST_URL "http://www.orthanc-server.com/downloads/third-party/gtest-1.7.0.zip") | |
29 | set(GTEST_MD5 "2d6ec8ccdf5c46b05ba54a9fd1d130d7") | |
30 | ||
31 | DownloadPackage(${GTEST_MD5} ${GTEST_URL} "${GTEST_SOURCES_DIR}") | |
32 | ||
33 | include_directories( | |
34 | ${GTEST_SOURCES_DIR}/include | |
35 | ${GTEST_SOURCES_DIR} | |
36 | ) | |
37 | ||
38 | set(GTEST_SOURCES | |
39 | ${GTEST_SOURCES_DIR}/src/gtest-all.cc | |
40 | ) | |
41 | ||
42 | # https://code.google.com/p/googletest/issues/detail?id=412 | |
43 | if (MSVC) # VS2012 does not support tuples correctly yet | |
44 | add_definitions(/D _VARIADIC_MAX=10) | |
45 | endif() | |
46 | ||
47 | source_group(ThirdParty\\GoogleTest REGULAR_EXPRESSION ${GTEST_SOURCES_DIR}/.*) | |
48 | ||
49 | else() | |
50 | include(FindGTest) | |
51 | if (NOT GTEST_FOUND) | |
52 | message(FATAL_ERROR "Unable to find GoogleTest") | |
53 | endif() | |
54 | ||
55 | include_directories(${GTEST_INCLUDE_DIRS}) | |
56 | link_libraries(${GTEST_LIBRARIES}) | |
57 | endif() |
0 | if (STATIC_BUILD OR NOT USE_SYSTEM_JSONCPP) | |
1 | set(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-0.10.5) | |
2 | set(JSONCPP_URL "http://www.orthanc-server.com/downloads/third-party/jsoncpp-0.10.5.tar.gz") | |
3 | set(JSONCPP_MD5 "db146bac5a126ded9bd728ab7b61ed6b") | |
4 | ||
5 | DownloadPackage(${JSONCPP_MD5} ${JSONCPP_URL} "${JSONCPP_SOURCES_DIR}") | |
6 | ||
7 | set(JSONCPP_SOURCES | |
8 | ${JSONCPP_SOURCES_DIR}/src/lib_json/json_reader.cpp | |
9 | ${JSONCPP_SOURCES_DIR}/src/lib_json/json_value.cpp | |
10 | ${JSONCPP_SOURCES_DIR}/src/lib_json/json_writer.cpp | |
11 | ) | |
12 | ||
13 | include_directories( | |
14 | ${JSONCPP_SOURCES_DIR}/include | |
15 | ) | |
16 | ||
17 | source_group(ThirdParty\\JsonCpp REGULAR_EXPRESSION ${JSONCPP_SOURCES_DIR}/.*) | |
18 | ||
19 | else() | |
20 | find_path(JSONCPP_INCLUDE_DIR json/reader.h | |
21 | /usr/include/jsoncpp | |
22 | /usr/local/include/jsoncpp | |
23 | ) | |
24 | ||
25 | message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}") | |
26 | include_directories(${JSONCPP_INCLUDE_DIR}) | |
27 | link_libraries(jsoncpp) | |
28 | ||
29 | CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H) | |
30 | if (NOT HAVE_JSONCPP_H) | |
31 | message(FATAL_ERROR "Please install the libjsoncpp-dev package") | |
32 | endif() | |
33 | ||
34 | # Switch to the C++11 standard if the version of JsonCpp is 1.y.z | |
35 | if (EXISTS ${JSONCPP_INCLUDE_DIR}/json/version.h) | |
36 | file(STRINGS | |
37 | "${JSONCPP_INCLUDE_DIR}/json/version.h" | |
38 | JSONCPP_VERSION_MAJOR1 REGEX | |
39 | ".*define JSONCPP_VERSION_MAJOR.*") | |
40 | ||
41 | if (NOT JSONCPP_VERSION_MAJOR1) | |
42 | message(FATAL_ERROR "Unable to extract the major version of JsonCpp") | |
43 | endif() | |
44 | ||
45 | string(REGEX REPLACE | |
46 | ".*JSONCPP_VERSION_MAJOR.*([0-9]+)$" "\\1" | |
47 | JSONCPP_VERSION_MAJOR ${JSONCPP_VERSION_MAJOR1}) | |
48 | message("JsonCpp major version: ${JSONCPP_VERSION_MAJOR}") | |
49 | ||
50 | if (CMAKE_COMPILER_IS_GNUCXX AND | |
51 | JSONCPP_VERSION_MAJOR GREATER 0) | |
52 | message("Switching to C++11 standard, as version of JsonCpp is >= 1.0.0") | |
53 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-deprecated-declarations") | |
54 | endif() | |
55 | else() | |
56 | message("Unable to detect the major version of JsonCpp, assuming < 1.0.0") | |
57 | endif() | |
58 | ||
59 | endif() |
0 | if (USE_PUGIXML) | |
1 | add_definitions(-DORTHANC_ENABLE_PUGIXML=1) | |
2 | ||
3 | if (STATIC_BUILD OR NOT USE_SYSTEM_PUGIXML) | |
4 | set(PUGIXML_SOURCES_DIR ${CMAKE_BINARY_DIR}/pugixml-1.4) | |
5 | set(PUGIXML_MD5 "7c56c91cfe3ecdee248a8e4892ef5781") | |
6 | set(PUGIXML_URL "http://www.orthanc-server.com/downloads/third-party/pugixml-1.4.tar.gz") | |
7 | ||
8 | DownloadPackage(${PUGIXML_MD5} ${PUGIXML_URL} "${PUGIXML_SOURCES_DIR}") | |
9 | ||
10 | include_directories( | |
11 | ${PUGIXML_SOURCES_DIR}/src | |
12 | ) | |
13 | ||
14 | set(PUGIXML_SOURCES | |
15 | #${PUGIXML_SOURCES_DIR}/src/vlog_is_on.cc | |
16 | ${PUGIXML_SOURCES_DIR}/src/pugixml.cpp | |
17 | ) | |
18 | ||
19 | else() | |
20 | CHECK_INCLUDE_FILE_CXX(pugixml.hpp HAVE_PUGIXML_H) | |
21 | if (NOT HAVE_PUGIXML_H) | |
22 | message(FATAL_ERROR "Please install the libpugixml-dev package") | |
23 | endif() | |
24 | ||
25 | link_libraries(pugixml) | |
26 | endif() | |
27 | ||
28 | source_group(ThirdParty\\pugixml REGULAR_EXPRESSION ${PUGIXML_SOURCES_DIR}/.*) | |
29 | ||
30 | else() | |
31 | add_definitions(-DORTHANC_ENABLE_PUGIXML=0) | |
32 | endif() |
0 | if (STATIC_BUILD OR NOT USE_SYSTEM_ZLIB) | |
1 | SET(ZLIB_SOURCES_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.7) | |
2 | SET(ZLIB_URL "http://www.orthanc-server.com/downloads/third-party/zlib-1.2.7.tar.gz") | |
3 | SET(ZLIB_MD5 "60df6a37c56e7c1366cca812414f7b85") | |
4 | ||
5 | DownloadPackage(${ZLIB_MD5} ${ZLIB_URL} "${ZLIB_SOURCES_DIR}") | |
6 | ||
7 | include_directories( | |
8 | ${ZLIB_SOURCES_DIR} | |
9 | ) | |
10 | ||
11 | list(APPEND ZLIB_SOURCES | |
12 | ${ZLIB_SOURCES_DIR}/adler32.c | |
13 | ${ZLIB_SOURCES_DIR}/compress.c | |
14 | ${ZLIB_SOURCES_DIR}/crc32.c | |
15 | ${ZLIB_SOURCES_DIR}/deflate.c | |
16 | ${ZLIB_SOURCES_DIR}/gzclose.c | |
17 | ${ZLIB_SOURCES_DIR}/gzlib.c | |
18 | ${ZLIB_SOURCES_DIR}/gzread.c | |
19 | ${ZLIB_SOURCES_DIR}/gzwrite.c | |
20 | ${ZLIB_SOURCES_DIR}/infback.c | |
21 | ${ZLIB_SOURCES_DIR}/inffast.c | |
22 | ${ZLIB_SOURCES_DIR}/inflate.c | |
23 | ${ZLIB_SOURCES_DIR}/inftrees.c | |
24 | ${ZLIB_SOURCES_DIR}/trees.c | |
25 | ${ZLIB_SOURCES_DIR}/uncompr.c | |
26 | ${ZLIB_SOURCES_DIR}/zutil.c | |
27 | ) | |
28 | ||
29 | source_group(ThirdParty\\zlib REGULAR_EXPRESSION ${ZLIB_SOURCES_DIR}/.*) | |
30 | ||
31 | else() | |
32 | include(FindZLIB) | |
33 | include_directories(${ZLIB_INCLUDE_DIRS}) | |
34 | link_libraries(${ZLIB_LIBRARIES}) | |
35 | endif() |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) | |
5 | set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) | |
6 | set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) | |
5 | set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) | |
6 | set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) | |
5 | set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) | |
6 | set(CMAKE_RC_COMPILER i586-mingw32msvc-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
0 | // ISO C9x compliant stdint.h for Microsoft Visual Studio | |
1 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 | |
2 | // | |
3 | // Copyright (c) 2006-2013 Alexander Chemeris | |
4 | // | |
5 | // Redistribution and use in source and binary forms, with or without | |
6 | // modification, are permitted provided that the following conditions are met: | |
7 | // | |
8 | // 1. Redistributions of source code must retain the above copyright notice, | |
9 | // this list of conditions and the following disclaimer. | |
10 | // | |
11 | // 2. Redistributions in binary form must reproduce the above copyright | |
12 | // notice, this list of conditions and the following disclaimer in the | |
13 | // documentation and/or other materials provided with the distribution. | |
14 | // | |
15 | // 3. Neither the name of the product nor the names of its contributors may | |
16 | // be used to endorse or promote products derived from this software | |
17 | // without specific prior written permission. | |
18 | // | |
19 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
20 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
22 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
24 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
25 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
26 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
27 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
28 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | // | |
30 | /////////////////////////////////////////////////////////////////////////////// | |
31 | ||
32 | #ifndef _MSC_VER // [ | |
33 | #error "Use this header only with Microsoft Visual C++ compilers!" | |
34 | #endif // _MSC_VER ] | |
35 | ||
36 | #ifndef _MSC_STDINT_H_ // [ | |
37 | #define _MSC_STDINT_H_ | |
38 | ||
39 | #if _MSC_VER > 1000 | |
40 | #pragma once | |
41 | #endif | |
42 | ||
43 | #if _MSC_VER >= 1600 // [ | |
44 | #include <stdint.h> | |
45 | #else // ] _MSC_VER >= 1600 [ | |
46 | ||
47 | #include <limits.h> | |
48 | ||
49 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when | |
50 | // compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' | |
51 | // or compiler give many errors like this: | |
52 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed | |
53 | #ifdef __cplusplus | |
54 | extern "C" { | |
55 | #endif | |
56 | # include <wchar.h> | |
57 | #ifdef __cplusplus | |
58 | } | |
59 | #endif | |
60 | ||
61 | // Define _W64 macros to mark types changing their size, like intptr_t. | |
62 | #ifndef _W64 | |
63 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 | |
64 | # define _W64 __w64 | |
65 | # else | |
66 | # define _W64 | |
67 | # endif | |
68 | #endif | |
69 | ||
70 | ||
71 | // 7.18.1 Integer types | |
72 | ||
73 | // 7.18.1.1 Exact-width integer types | |
74 | ||
75 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't | |
76 | // realize that, e.g. char has the same size as __int8 | |
77 | // so we give up on __intX for them. | |
78 | #if (_MSC_VER < 1300) | |
79 | typedef signed char int8_t; | |
80 | typedef signed short int16_t; | |
81 | typedef signed int int32_t; | |
82 | typedef unsigned char uint8_t; | |
83 | typedef unsigned short uint16_t; | |
84 | typedef unsigned int uint32_t; | |
85 | #else | |
86 | typedef signed __int8 int8_t; | |
87 | typedef signed __int16 int16_t; | |
88 | typedef signed __int32 int32_t; | |
89 | typedef unsigned __int8 uint8_t; | |
90 | typedef unsigned __int16 uint16_t; | |
91 | typedef unsigned __int32 uint32_t; | |
92 | #endif | |
93 | typedef signed __int64 int64_t; | |
94 | typedef unsigned __int64 uint64_t; | |
95 | ||
96 | ||
97 | // 7.18.1.2 Minimum-width integer types | |
98 | typedef int8_t int_least8_t; | |
99 | typedef int16_t int_least16_t; | |
100 | typedef int32_t int_least32_t; | |
101 | typedef int64_t int_least64_t; | |
102 | typedef uint8_t uint_least8_t; | |
103 | typedef uint16_t uint_least16_t; | |
104 | typedef uint32_t uint_least32_t; | |
105 | typedef uint64_t uint_least64_t; | |
106 | ||
107 | // 7.18.1.3 Fastest minimum-width integer types | |
108 | typedef int8_t int_fast8_t; | |
109 | typedef int16_t int_fast16_t; | |
110 | typedef int32_t int_fast32_t; | |
111 | typedef int64_t int_fast64_t; | |
112 | typedef uint8_t uint_fast8_t; | |
113 | typedef uint16_t uint_fast16_t; | |
114 | typedef uint32_t uint_fast32_t; | |
115 | typedef uint64_t uint_fast64_t; | |
116 | ||
117 | // 7.18.1.4 Integer types capable of holding object pointers | |
118 | #ifdef _WIN64 // [ | |
119 | typedef signed __int64 intptr_t; | |
120 | typedef unsigned __int64 uintptr_t; | |
121 | #else // _WIN64 ][ | |
122 | typedef _W64 signed int intptr_t; | |
123 | typedef _W64 unsigned int uintptr_t; | |
124 | #endif // _WIN64 ] | |
125 | ||
126 | // 7.18.1.5 Greatest-width integer types | |
127 | typedef int64_t intmax_t; | |
128 | typedef uint64_t uintmax_t; | |
129 | ||
130 | ||
131 | // 7.18.2 Limits of specified-width integer types | |
132 | ||
133 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 | |
134 | ||
135 | // 7.18.2.1 Limits of exact-width integer types | |
136 | #define INT8_MIN ((int8_t)_I8_MIN) | |
137 | #define INT8_MAX _I8_MAX | |
138 | #define INT16_MIN ((int16_t)_I16_MIN) | |
139 | #define INT16_MAX _I16_MAX | |
140 | #define INT32_MIN ((int32_t)_I32_MIN) | |
141 | #define INT32_MAX _I32_MAX | |
142 | #define INT64_MIN ((int64_t)_I64_MIN) | |
143 | #define INT64_MAX _I64_MAX | |
144 | #define UINT8_MAX _UI8_MAX | |
145 | #define UINT16_MAX _UI16_MAX | |
146 | #define UINT32_MAX _UI32_MAX | |
147 | #define UINT64_MAX _UI64_MAX | |
148 | ||
149 | // 7.18.2.2 Limits of minimum-width integer types | |
150 | #define INT_LEAST8_MIN INT8_MIN | |
151 | #define INT_LEAST8_MAX INT8_MAX | |
152 | #define INT_LEAST16_MIN INT16_MIN | |
153 | #define INT_LEAST16_MAX INT16_MAX | |
154 | #define INT_LEAST32_MIN INT32_MIN | |
155 | #define INT_LEAST32_MAX INT32_MAX | |
156 | #define INT_LEAST64_MIN INT64_MIN | |
157 | #define INT_LEAST64_MAX INT64_MAX | |
158 | #define UINT_LEAST8_MAX UINT8_MAX | |
159 | #define UINT_LEAST16_MAX UINT16_MAX | |
160 | #define UINT_LEAST32_MAX UINT32_MAX | |
161 | #define UINT_LEAST64_MAX UINT64_MAX | |
162 | ||
163 | // 7.18.2.3 Limits of fastest minimum-width integer types | |
164 | #define INT_FAST8_MIN INT8_MIN | |
165 | #define INT_FAST8_MAX INT8_MAX | |
166 | #define INT_FAST16_MIN INT16_MIN | |
167 | #define INT_FAST16_MAX INT16_MAX | |
168 | #define INT_FAST32_MIN INT32_MIN | |
169 | #define INT_FAST32_MAX INT32_MAX | |
170 | #define INT_FAST64_MIN INT64_MIN | |
171 | #define INT_FAST64_MAX INT64_MAX | |
172 | #define UINT_FAST8_MAX UINT8_MAX | |
173 | #define UINT_FAST16_MAX UINT16_MAX | |
174 | #define UINT_FAST32_MAX UINT32_MAX | |
175 | #define UINT_FAST64_MAX UINT64_MAX | |
176 | ||
177 | // 7.18.2.4 Limits of integer types capable of holding object pointers | |
178 | #ifdef _WIN64 // [ | |
179 | # define INTPTR_MIN INT64_MIN | |
180 | # define INTPTR_MAX INT64_MAX | |
181 | # define UINTPTR_MAX UINT64_MAX | |
182 | #else // _WIN64 ][ | |
183 | # define INTPTR_MIN INT32_MIN | |
184 | # define INTPTR_MAX INT32_MAX | |
185 | # define UINTPTR_MAX UINT32_MAX | |
186 | #endif // _WIN64 ] | |
187 | ||
188 | // 7.18.2.5 Limits of greatest-width integer types | |
189 | #define INTMAX_MIN INT64_MIN | |
190 | #define INTMAX_MAX INT64_MAX | |
191 | #define UINTMAX_MAX UINT64_MAX | |
192 | ||
193 | // 7.18.3 Limits of other integer types | |
194 | ||
195 | #ifdef _WIN64 // [ | |
196 | # define PTRDIFF_MIN _I64_MIN | |
197 | # define PTRDIFF_MAX _I64_MAX | |
198 | #else // _WIN64 ][ | |
199 | # define PTRDIFF_MIN _I32_MIN | |
200 | # define PTRDIFF_MAX _I32_MAX | |
201 | #endif // _WIN64 ] | |
202 | ||
203 | #define SIG_ATOMIC_MIN INT_MIN | |
204 | #define SIG_ATOMIC_MAX INT_MAX | |
205 | ||
206 | #ifndef SIZE_MAX // [ | |
207 | # ifdef _WIN64 // [ | |
208 | # define SIZE_MAX _UI64_MAX | |
209 | # else // _WIN64 ][ | |
210 | # define SIZE_MAX _UI32_MAX | |
211 | # endif // _WIN64 ] | |
212 | #endif // SIZE_MAX ] | |
213 | ||
214 | // WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> | |
215 | #ifndef WCHAR_MIN // [ | |
216 | # define WCHAR_MIN 0 | |
217 | #endif // WCHAR_MIN ] | |
218 | #ifndef WCHAR_MAX // [ | |
219 | # define WCHAR_MAX _UI16_MAX | |
220 | #endif // WCHAR_MAX ] | |
221 | ||
222 | #define WINT_MIN 0 | |
223 | #define WINT_MAX _UI16_MAX | |
224 | ||
225 | #endif // __STDC_LIMIT_MACROS ] | |
226 | ||
227 | ||
228 | // 7.18.4 Limits of other integer types | |
229 | ||
230 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 | |
231 | ||
232 | // 7.18.4.1 Macros for minimum-width integer constants | |
233 | ||
234 | #define INT8_C(val) val##i8 | |
235 | #define INT16_C(val) val##i16 | |
236 | #define INT32_C(val) val##i32 | |
237 | #define INT64_C(val) val##i64 | |
238 | ||
239 | #define UINT8_C(val) val##ui8 | |
240 | #define UINT16_C(val) val##ui16 | |
241 | #define UINT32_C(val) val##ui32 | |
242 | #define UINT64_C(val) val##ui64 | |
243 | ||
244 | // 7.18.4.2 Macros for greatest-width integer constants | |
245 | // These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. | |
246 | // Check out Issue 9 for the details. | |
247 | #ifndef INTMAX_C // [ | |
248 | # define INTMAX_C INT64_C | |
249 | #endif // INTMAX_C ] | |
250 | #ifndef UINTMAX_C // [ | |
251 | # define UINTMAX_C UINT64_C | |
252 | #endif // UINTMAX_C ] | |
253 | ||
254 | #endif // __STDC_CONSTANT_MACROS ] | |
255 | ||
256 | #endif // _MSC_VER >= 1600 ] | |
257 | ||
258 | #endif // _MSC_STDINT_H_ ] |
0 | #!/usr/bin/python | |
1 | ||
2 | # Orthanc - A Lightweight, RESTful DICOM Store | |
3 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 | # Department, University Hospital of Liege, Belgium | |
5 | # Copyright (C) 2017 Osimis, Belgium | |
6 | # | |
7 | # This program is free software: you can redistribute it and/or | |
8 | # modify it under the terms of the GNU General Public License as | |
9 | # published by the Free Software Foundation, either version 3 of the | |
10 | # License, or (at your option) any later version. | |
11 | # | |
12 | # In addition, as a special exception, the copyright holders of this | |
13 | # program give permission to link the code of its release with the | |
14 | # OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 | # that use the same license as the "OpenSSL" library), and distribute | |
16 | # the linked executables. You must obey the GNU General Public License | |
17 | # in all respects for all of the code used other than "OpenSSL". If you | |
18 | # modify file(s) with this exception, you may extend this exception to | |
19 | # your version of the file(s), but you are not obligated to do so. If | |
20 | # you do not wish to do so, delete this exception statement from your | |
21 | # version. If you delete this exception statement from all source files | |
22 | # in the program, then also delete it here. | |
23 | # | |
24 | # This program is distributed in the hope that it will be useful, but | |
25 | # WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 | # General Public License for more details. | |
28 | # | |
29 | # You should have received a copy of the GNU General Public License | |
30 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 | ||
32 | ||
33 | import os | |
34 | import sys | |
35 | import datetime | |
36 | ||
37 | if len(sys.argv) != 5: | |
38 | sys.stderr.write('Usage: %s <Version> <ProductName> <Filename> <Description>\n\n' % sys.argv[0]) | |
39 | sys.stderr.write('Example: %s 0.9.1 Orthanc Orthanc.exe "Lightweight, RESTful DICOM server for medical imaging"\n' % sys.argv[0]) | |
40 | sys.exit(-1) | |
41 | ||
42 | SOURCE = os.path.join(os.path.dirname(__file__), 'WindowsResources.rc') | |
43 | ||
44 | VERSION = sys.argv[1] | |
45 | PRODUCT = sys.argv[2] | |
46 | FILENAME = sys.argv[3] | |
47 | DESCRIPTION = sys.argv[4] | |
48 | ||
49 | if VERSION == 'mainline': | |
50 | VERSION = '999.999.999' | |
51 | RELEASE = 'This is a mainline build, not an official release' | |
52 | else: | |
53 | RELEASE = 'Release %s' % VERSION | |
54 | ||
55 | v = VERSION.split('.') | |
56 | if len(v) != 2 and len(v) != 3: | |
57 | sys.stderr.write('Bad version number: %s\n' % VERSION) | |
58 | sys.exit(-1) | |
59 | ||
60 | if len(v) == 2: | |
61 | v.append('0') | |
62 | ||
63 | extension = os.path.splitext(FILENAME)[1] | |
64 | if extension.lower() == '.dll': | |
65 | BLOCK = '040904E4' | |
66 | TYPE = 'VFT_DLL' | |
67 | elif extension.lower() == '.exe': | |
68 | #BLOCK = '040904B0' # LANG_ENGLISH/SUBLANG_ENGLISH_US, | |
69 | BLOCK = '040904E4' # Lang=US English, CharSet=Windows Multilingual | |
70 | TYPE = 'VFT_APP' | |
71 | else: | |
72 | sys.stderr.write('Unsupported extension (.EXE or .DLL only): %s\n' % extension) | |
73 | sys.exit(-1) | |
74 | ||
75 | ||
76 | with open(SOURCE, 'r') as source: | |
77 | content = source.read() | |
78 | content = content.replace('${VERSION_MAJOR}', v[0]) | |
79 | content = content.replace('${VERSION_MINOR}', v[1]) | |
80 | content = content.replace('${VERSION_PATCH}', v[2]) | |
81 | content = content.replace('${RELEASE}', RELEASE) | |
82 | content = content.replace('${DESCRIPTION}', DESCRIPTION) | |
83 | content = content.replace('${PRODUCT}', PRODUCT) | |
84 | content = content.replace('${FILENAME}', FILENAME) | |
85 | content = content.replace('${YEAR}', str(datetime.datetime.now().year)) | |
86 | content = content.replace('${BLOCK}', BLOCK) | |
87 | content = content.replace('${TYPE}', TYPE) | |
88 | ||
89 | sys.stdout.write(content) |
0 | #include <winver.h> | |
1 | ||
2 | VS_VERSION_INFO VERSIONINFO | |
3 | FILEVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,${VERSION_PATCH} | |
4 | PRODUCTVERSION ${VERSION_MAJOR},${VERSION_MINOR},0,0 | |
5 | FILEOS VOS_NT_WINDOWS32 | |
6 | FILETYPE ${TYPE} | |
7 | BEGIN | |
8 | BLOCK "StringFileInfo" | |
9 | BEGIN | |
10 | BLOCK "${BLOCK}" | |
11 | BEGIN | |
12 | VALUE "Comments", "${RELEASE}" | |
13 | VALUE "CompanyName", "University Hospital of Liege, Belgium" | |
14 | VALUE "FileDescription", "${DESCRIPTION}" | |
15 | VALUE "FileVersion", "${VERSION_MAJOR}.${VERSION_MINOR}.0.${VERSION_PATCH}" | |
16 | VALUE "InternalName", "${PRODUCT}" | |
17 | VALUE "LegalCopyright", "(c) 2012-${YEAR}, Sebastien Jodogne, University Hospital of Liege, Belgium" | |
18 | VALUE "LegalTrademarks", "Licensing information is available at http://www.orthanc-server.com/" | |
19 | VALUE "OriginalFilename", "${FILENAME}" | |
20 | VALUE "ProductName", "${PRODUCT}" | |
21 | VALUE "ProductVersion", "${VERSION_MAJOR}.${VERSION_MINOR}" | |
22 | END | |
23 | END | |
24 | ||
25 | BLOCK "VarFileInfo" | |
26 | BEGIN | |
27 | VALUE "Translation", 0x409, 1252 // U.S. English | |
28 | END | |
29 | END |
0 | /** | |
1 | * \mainpage | |
2 | * | |
3 | * This C/C++ SDK allows external developers to create plugins that | |
4 | * can be loaded into Orthanc to extend its functionality. Each | |
5 | * Orthanc plugin must expose 4 public functions with the following | |
6 | * signatures: | |
7 | * | |
8 | * -# <tt>int32_t OrthancPluginInitialize(const OrthancPluginContext* context)</tt>: | |
9 | * This function is invoked by Orthanc when it loads the plugin on startup. | |
10 | * The plugin must: | |
11 | * - Check its compatibility with the Orthanc version using | |
12 | * ::OrthancPluginCheckVersion(). | |
13 | * - Store the context pointer so that it can use the plugin | |
14 | * services of Orthanc. | |
15 | * - Register all its REST callbacks using ::OrthancPluginRegisterRestCallback(). | |
16 | * - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback(). | |
17 | * - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback(). | |
18 | * - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea(). | |
19 | * - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2(). | |
20 | * - Possibly register a handler for C-Find SCP using OrthancPluginRegisterFindCallback(). | |
21 | * - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback(). | |
22 | * - Possibly register a handler for C-Move SCP using OrthancPluginRegisterMoveCallback(). | |
23 | * - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback(). | |
24 | * - Possibly register a callback to filter incoming HTTP requests using OrthancPluginRegisterIncomingHttpRequestFilter(). | |
25 | * -# <tt>void OrthancPluginFinalize()</tt>: | |
26 | * This function is invoked by Orthanc during its shutdown. The plugin | |
27 | * must free all its memory. | |
28 | * -# <tt>const char* OrthancPluginGetName()</tt>: | |
29 | * The plugin must return a short string to identify itself. | |
30 | * -# <tt>const char* OrthancPluginGetVersion()</tt>: | |
31 | * The plugin must return a string containing its version number. | |
32 | * | |
33 | * The name and the version of a plugin is only used to prevent it | |
34 | * from being loaded twice. Note that, in C++, it is mandatory to | |
35 | * declare these functions within an <tt>extern "C"</tt> section. | |
36 | * | |
37 | * To ensure multi-threading safety, the various REST callbacks are | |
38 | * guaranteed to be executed in mutual exclusion since Orthanc | |
39 | * 0.8.5. If this feature is undesired (notably when developing | |
40 | * high-performance plugins handling simultaneous requests), use | |
41 | * ::OrthancPluginRegisterRestCallbackNoLock(). | |
42 | **/ | |
43 | ||
44 | ||
45 | ||
46 | /** | |
47 | * @defgroup Images Images and compression | |
48 | * @brief Functions to deal with images and compressed buffers. | |
49 | * | |
50 | * @defgroup REST REST | |
51 | * @brief Functions to answer REST requests in a callback. | |
52 | * | |
53 | * @defgroup Callbacks Callbacks | |
54 | * @brief Functions to register and manage callbacks by the plugins. | |
55 | * | |
56 | * @defgroup DicomCallbaks DicomCallbaks | |
57 | * @brief Functions to register and manage DICOM callbacks (worklists, C-Find, C-MOVE). | |
58 | * | |
59 | * @defgroup Orthanc Orthanc | |
60 | * @brief Functions to access the content of the Orthanc server. | |
61 | **/ | |
62 | ||
63 | ||
64 | ||
65 | /** | |
66 | * @defgroup Toolbox Toolbox | |
67 | * @brief Generic functions to help with the creation of plugins. | |
68 | **/ | |
69 | ||
70 | ||
71 | ||
72 | /** | |
73 | * Orthanc - A Lightweight, RESTful DICOM Store | |
74 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
75 | * Department, University Hospital of Liege, Belgium | |
76 | * | |
77 | * This program is free software: you can redistribute it and/or | |
78 | * modify it under the terms of the GNU General Public License as | |
79 | * published by the Free Software Foundation, either version 3 of the | |
80 | * License, or (at your option) any later version. | |
81 | * | |
82 | * In addition, as a special exception, the copyright holders of this | |
83 | * program give permission to link the code of its release with the | |
84 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
85 | * that use the same license as the "OpenSSL" library), and distribute | |
86 | * the linked executables. You must obey the GNU General Public License | |
87 | * in all respects for all of the code used other than "OpenSSL". If you | |
88 | * modify file(s) with this exception, you may extend this exception to | |
89 | * your version of the file(s), but you are not obligated to do so. If | |
90 | * you do not wish to do so, delete this exception statement from your | |
91 | * version. If you delete this exception statement from all source files | |
92 | * in the program, then also delete it here. | |
93 | * | |
94 | * This program is distributed in the hope that it will be useful, but | |
95 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
96 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
97 | * General Public License for more details. | |
98 | * | |
99 | * You should have received a copy of the GNU General Public License | |
100 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
101 | **/ | |
102 | ||
103 | ||
104 | ||
105 | #pragma once | |
106 | ||
107 | ||
108 | #include <stdio.h> | |
109 | #include <string.h> | |
110 | ||
111 | #ifdef WIN32 | |
112 | #define ORTHANC_PLUGINS_API __declspec(dllexport) | |
113 | #else | |
114 | #define ORTHANC_PLUGINS_API | |
115 | #endif | |
116 | ||
117 | #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER 1 | |
118 | #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER 1 | |
119 | #define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 0 | |
120 | ||
121 | ||
122 | ||
123 | /******************************************************************** | |
124 | ** Check that function inlining is properly supported. The use of | |
125 | ** inlining is required, to avoid the duplication of object code | |
126 | ** between two compilation modules that would use the Orthanc Plugin | |
127 | ** API. | |
128 | ********************************************************************/ | |
129 | ||
130 | /* If the auto-detection of the "inline" keyword below does not work | |
131 | automatically and that your compiler is known to properly support | |
132 | inlining, uncomment the following #define and adapt the definition | |
133 | of "static inline". */ | |
134 | ||
135 | /* #define ORTHANC_PLUGIN_INLINE static inline */ | |
136 | ||
137 | #ifndef ORTHANC_PLUGIN_INLINE | |
138 | # if __STDC_VERSION__ >= 199901L | |
139 | /* This is C99 or above: http://predef.sourceforge.net/prestd.html */ | |
140 | # define ORTHANC_PLUGIN_INLINE static inline | |
141 | # elif defined(__cplusplus) | |
142 | /* This is C++ */ | |
143 | # define ORTHANC_PLUGIN_INLINE static inline | |
144 | # elif defined(__GNUC__) | |
145 | /* This is GCC running in C89 mode */ | |
146 | # define ORTHANC_PLUGIN_INLINE static __inline | |
147 | # elif defined(_MSC_VER) | |
148 | /* This is Visual Studio running in C89 mode */ | |
149 | # define ORTHANC_PLUGIN_INLINE static __inline | |
150 | # else | |
151 | # error Your compiler is not known to support the "inline" keyword | |
152 | # endif | |
153 | #endif | |
154 | ||
155 | ||
156 | ||
157 | /******************************************************************** | |
158 | ** Inclusion of standard libraries. | |
159 | ********************************************************************/ | |
160 | ||
161 | /** | |
162 | * For Microsoft Visual Studio, a compatibility "stdint.h" can be | |
163 | * downloaded at the following URL: | |
164 | * https://orthanc.googlecode.com/hg/Resources/ThirdParty/VisualStudio/stdint.h | |
165 | **/ | |
166 | #include <stdint.h> | |
167 | ||
168 | #include <stdlib.h> | |
169 | ||
170 | ||
171 | ||
172 | /******************************************************************** | |
173 | ** Definition of the Orthanc Plugin API. | |
174 | ********************************************************************/ | |
175 | ||
176 | /** @{ */ | |
177 | ||
178 | #ifdef __cplusplus | |
179 | extern "C" | |
180 | { | |
181 | #endif | |
182 | ||
183 | /** | |
184 | * The various error codes that can be returned by the Orthanc core. | |
185 | **/ | |
186 | typedef enum | |
187 | { | |
188 | OrthancPluginErrorCode_InternalError = -1 /*!< Internal error */, | |
189 | OrthancPluginErrorCode_Success = 0 /*!< Success */, | |
190 | OrthancPluginErrorCode_Plugin = 1 /*!< Error encountered within the plugin engine */, | |
191 | OrthancPluginErrorCode_NotImplemented = 2 /*!< Not implemented yet */, | |
192 | OrthancPluginErrorCode_ParameterOutOfRange = 3 /*!< Parameter out of range */, | |
193 | OrthancPluginErrorCode_NotEnoughMemory = 4 /*!< Not enough memory */, | |
194 | OrthancPluginErrorCode_BadParameterType = 5 /*!< Bad type for a parameter */, | |
195 | OrthancPluginErrorCode_BadSequenceOfCalls = 6 /*!< Bad sequence of calls */, | |
196 | OrthancPluginErrorCode_InexistentItem = 7 /*!< Accessing an inexistent item */, | |
197 | OrthancPluginErrorCode_BadRequest = 8 /*!< Bad request */, | |
198 | OrthancPluginErrorCode_NetworkProtocol = 9 /*!< Error in the network protocol */, | |
199 | OrthancPluginErrorCode_SystemCommand = 10 /*!< Error while calling a system command */, | |
200 | OrthancPluginErrorCode_Database = 11 /*!< Error with the database engine */, | |
201 | OrthancPluginErrorCode_UriSyntax = 12 /*!< Badly formatted URI */, | |
202 | OrthancPluginErrorCode_InexistentFile = 13 /*!< Inexistent file */, | |
203 | OrthancPluginErrorCode_CannotWriteFile = 14 /*!< Cannot write to file */, | |
204 | OrthancPluginErrorCode_BadFileFormat = 15 /*!< Bad file format */, | |
205 | OrthancPluginErrorCode_Timeout = 16 /*!< Timeout */, | |
206 | OrthancPluginErrorCode_UnknownResource = 17 /*!< Unknown resource */, | |
207 | OrthancPluginErrorCode_IncompatibleDatabaseVersion = 18 /*!< Incompatible version of the database */, | |
208 | OrthancPluginErrorCode_FullStorage = 19 /*!< The file storage is full */, | |
209 | OrthancPluginErrorCode_CorruptedFile = 20 /*!< Corrupted file (e.g. inconsistent MD5 hash) */, | |
210 | OrthancPluginErrorCode_InexistentTag = 21 /*!< Inexistent tag */, | |
211 | OrthancPluginErrorCode_ReadOnly = 22 /*!< Cannot modify a read-only data structure */, | |
212 | OrthancPluginErrorCode_IncompatibleImageFormat = 23 /*!< Incompatible format of the images */, | |
213 | OrthancPluginErrorCode_IncompatibleImageSize = 24 /*!< Incompatible size of the images */, | |
214 | OrthancPluginErrorCode_SharedLibrary = 25 /*!< Error while using a shared library (plugin) */, | |
215 | OrthancPluginErrorCode_UnknownPluginService = 26 /*!< Plugin invoking an unknown service */, | |
216 | OrthancPluginErrorCode_UnknownDicomTag = 27 /*!< Unknown DICOM tag */, | |
217 | OrthancPluginErrorCode_BadJson = 28 /*!< Cannot parse a JSON document */, | |
218 | OrthancPluginErrorCode_Unauthorized = 29 /*!< Bad credentials were provided to an HTTP request */, | |
219 | OrthancPluginErrorCode_BadFont = 30 /*!< Badly formatted font file */, | |
220 | OrthancPluginErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, | |
221 | OrthancPluginErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, | |
222 | OrthancPluginErrorCode_EmptyRequest = 33 /*!< The request is empty */, | |
223 | OrthancPluginErrorCode_NotAcceptable = 34 /*!< Cannot send a response which is acceptable according to the Accept HTTP header */, | |
224 | OrthancPluginErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, | |
225 | OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, | |
226 | OrthancPluginErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */, | |
227 | OrthancPluginErrorCode_SQLiteStatementAlreadyUsed = 1003 /*!< SQLite: This cached statement is already being referred to */, | |
228 | OrthancPluginErrorCode_SQLiteExecute = 1004 /*!< SQLite: Cannot execute a command */, | |
229 | OrthancPluginErrorCode_SQLiteRollbackWithoutTransaction = 1005 /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */, | |
230 | OrthancPluginErrorCode_SQLiteCommitWithoutTransaction = 1006 /*!< SQLite: Committing a nonexistent transaction */, | |
231 | OrthancPluginErrorCode_SQLiteRegisterFunction = 1007 /*!< SQLite: Unable to register a function */, | |
232 | OrthancPluginErrorCode_SQLiteFlush = 1008 /*!< SQLite: Unable to flush the database */, | |
233 | OrthancPluginErrorCode_SQLiteCannotRun = 1009 /*!< SQLite: Cannot run a cached statement */, | |
234 | OrthancPluginErrorCode_SQLiteCannotStep = 1010 /*!< SQLite: Cannot step over a cached statement */, | |
235 | OrthancPluginErrorCode_SQLiteBindOutOfRange = 1011 /*!< SQLite: Bing a value while out of range (serious error) */, | |
236 | OrthancPluginErrorCode_SQLitePrepareStatement = 1012 /*!< SQLite: Cannot prepare a cached statement */, | |
237 | OrthancPluginErrorCode_SQLiteTransactionAlreadyStarted = 1013 /*!< SQLite: Beginning the same transaction twice */, | |
238 | OrthancPluginErrorCode_SQLiteTransactionCommit = 1014 /*!< SQLite: Failure when committing the transaction */, | |
239 | OrthancPluginErrorCode_SQLiteTransactionBegin = 1015 /*!< SQLite: Cannot start a transaction */, | |
240 | OrthancPluginErrorCode_DirectoryOverFile = 2000 /*!< The directory to be created is already occupied by a regular file */, | |
241 | OrthancPluginErrorCode_FileStorageCannotWrite = 2001 /*!< Unable to create a subdirectory or a file in the file storage */, | |
242 | OrthancPluginErrorCode_DirectoryExpected = 2002 /*!< The specified path does not point to a directory */, | |
243 | OrthancPluginErrorCode_HttpPortInUse = 2003 /*!< The TCP port of the HTTP server is privileged or already in use */, | |
244 | OrthancPluginErrorCode_DicomPortInUse = 2004 /*!< The TCP port of the DICOM server is privileged or already in use */, | |
245 | OrthancPluginErrorCode_BadHttpStatusInRest = 2005 /*!< This HTTP status is not allowed in a REST API */, | |
246 | OrthancPluginErrorCode_RegularFileExpected = 2006 /*!< The specified path does not point to a regular file */, | |
247 | OrthancPluginErrorCode_PathToExecutable = 2007 /*!< Unable to get the path to the executable */, | |
248 | OrthancPluginErrorCode_MakeDirectory = 2008 /*!< Cannot create a directory */, | |
249 | OrthancPluginErrorCode_BadApplicationEntityTitle = 2009 /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */, | |
250 | OrthancPluginErrorCode_NoCFindHandler = 2010 /*!< No request handler factory for DICOM C-FIND SCP */, | |
251 | OrthancPluginErrorCode_NoCMoveHandler = 2011 /*!< No request handler factory for DICOM C-MOVE SCP */, | |
252 | OrthancPluginErrorCode_NoCStoreHandler = 2012 /*!< No request handler factory for DICOM C-STORE SCP */, | |
253 | OrthancPluginErrorCode_NoApplicationEntityFilter = 2013 /*!< No application entity filter */, | |
254 | OrthancPluginErrorCode_NoSopClassOrInstance = 2014 /*!< DicomUserConnection: Unable to find the SOP class and instance */, | |
255 | OrthancPluginErrorCode_NoPresentationContext = 2015 /*!< DicomUserConnection: No acceptable presentation context for modality */, | |
256 | OrthancPluginErrorCode_DicomFindUnavailable = 2016 /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */, | |
257 | OrthancPluginErrorCode_DicomMoveUnavailable = 2017 /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */, | |
258 | OrthancPluginErrorCode_CannotStoreInstance = 2018 /*!< Cannot store an instance */, | |
259 | OrthancPluginErrorCode_CreateDicomNotString = 2019 /*!< Only string values are supported when creating DICOM instances */, | |
260 | OrthancPluginErrorCode_CreateDicomOverrideTag = 2020 /*!< Trying to override a value inherited from a parent module */, | |
261 | OrthancPluginErrorCode_CreateDicomUseContent = 2021 /*!< Use \"Content\" to inject an image into a new DICOM instance */, | |
262 | OrthancPluginErrorCode_CreateDicomNoPayload = 2022 /*!< No payload is present for one instance in the series */, | |
263 | OrthancPluginErrorCode_CreateDicomUseDataUriScheme = 2023 /*!< The payload of the DICOM instance must be specified according to Data URI scheme */, | |
264 | OrthancPluginErrorCode_CreateDicomBadParent = 2024 /*!< Trying to attach a new DICOM instance to an inexistent resource */, | |
265 | OrthancPluginErrorCode_CreateDicomParentIsInstance = 2025 /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */, | |
266 | OrthancPluginErrorCode_CreateDicomParentEncoding = 2026 /*!< Unable to get the encoding of the parent resource */, | |
267 | OrthancPluginErrorCode_UnknownModality = 2027 /*!< Unknown modality */, | |
268 | OrthancPluginErrorCode_BadJobOrdering = 2028 /*!< Bad ordering of filters in a job */, | |
269 | OrthancPluginErrorCode_JsonToLuaTable = 2029 /*!< Cannot convert the given JSON object to a Lua table */, | |
270 | OrthancPluginErrorCode_CannotCreateLua = 2030 /*!< Cannot create the Lua context */, | |
271 | OrthancPluginErrorCode_CannotExecuteLua = 2031 /*!< Cannot execute a Lua command */, | |
272 | OrthancPluginErrorCode_LuaAlreadyExecuted = 2032 /*!< Arguments cannot be pushed after the Lua function is executed */, | |
273 | OrthancPluginErrorCode_LuaBadOutput = 2033 /*!< The Lua function does not give the expected number of outputs */, | |
274 | OrthancPluginErrorCode_NotLuaPredicate = 2034 /*!< The Lua function is not a predicate (only true/false outputs allowed) */, | |
275 | OrthancPluginErrorCode_LuaReturnsNoString = 2035 /*!< The Lua function does not return a string */, | |
276 | OrthancPluginErrorCode_StorageAreaAlreadyRegistered = 2036 /*!< Another plugin has already registered a custom storage area */, | |
277 | OrthancPluginErrorCode_DatabaseBackendAlreadyRegistered = 2037 /*!< Another plugin has already registered a custom database back-end */, | |
278 | OrthancPluginErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, | |
279 | OrthancPluginErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, | |
280 | OrthancPluginErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, | |
281 | OrthancPluginErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, | |
282 | OrthancPluginErrorCode_AlreadyExistingTag = 2042 /*!< Cannot override the value of a tag that already exists */, | |
283 | ||
284 | _OrthancPluginErrorCode_INTERNAL = 0x7fffffff | |
285 | } OrthancPluginErrorCode; | |
286 | ||
287 | ||
288 | /** | |
289 | * Forward declaration of one of the mandatory functions for Orthanc | |
290 | * plugins. | |
291 | **/ | |
292 | ORTHANC_PLUGINS_API const char* OrthancPluginGetName(); | |
293 | ||
294 | ||
295 | /** | |
296 | * The various HTTP methods for a REST call. | |
297 | **/ | |
298 | typedef enum | |
299 | { | |
300 | OrthancPluginHttpMethod_Get = 1, /*!< GET request */ | |
301 | OrthancPluginHttpMethod_Post = 2, /*!< POST request */ | |
302 | OrthancPluginHttpMethod_Put = 3, /*!< PUT request */ | |
303 | OrthancPluginHttpMethod_Delete = 4, /*!< DELETE request */ | |
304 | ||
305 | _OrthancPluginHttpMethod_INTERNAL = 0x7fffffff | |
306 | } OrthancPluginHttpMethod; | |
307 | ||
308 | ||
309 | /** | |
310 | * @brief The parameters of a REST request. | |
311 | * @ingroup Callbacks | |
312 | **/ | |
313 | typedef struct | |
314 | { | |
315 | /** | |
316 | * @brief The HTTP method. | |
317 | **/ | |
318 | OrthancPluginHttpMethod method; | |
319 | ||
320 | /** | |
321 | * @brief The number of groups of the regular expression. | |
322 | **/ | |
323 | uint32_t groupsCount; | |
324 | ||
325 | /** | |
326 | * @brief The matched values for the groups of the regular expression. | |
327 | **/ | |
328 | const char* const* groups; | |
329 | ||
330 | /** | |
331 | * @brief For a GET request, the number of GET parameters. | |
332 | **/ | |
333 | uint32_t getCount; | |
334 | ||
335 | /** | |
336 | * @brief For a GET request, the keys of the GET parameters. | |
337 | **/ | |
338 | const char* const* getKeys; | |
339 | ||
340 | /** | |
341 | * @brief For a GET request, the values of the GET parameters. | |
342 | **/ | |
343 | const char* const* getValues; | |
344 | ||
345 | /** | |
346 | * @brief For a PUT or POST request, the content of the body. | |
347 | **/ | |
348 | const char* body; | |
349 | ||
350 | /** | |
351 | * @brief For a PUT or POST request, the number of bytes of the body. | |
352 | **/ | |
353 | uint32_t bodySize; | |
354 | ||
355 | ||
356 | /* -------------------------------------------------- | |
357 | New in version 0.8.1 | |
358 | -------------------------------------------------- */ | |
359 | ||
360 | /** | |
361 | * @brief The number of HTTP headers. | |
362 | **/ | |
363 | uint32_t headersCount; | |
364 | ||
365 | /** | |
366 | * @brief The keys of the HTTP headers (always converted to low-case). | |
367 | **/ | |
368 | const char* const* headersKeys; | |
369 | ||
370 | /** | |
371 | * @brief The values of the HTTP headers. | |
372 | **/ | |
373 | const char* const* headersValues; | |
374 | ||
375 | } OrthancPluginHttpRequest; | |
376 | ||
377 | ||
378 | typedef enum | |
379 | { | |
380 | /* Generic services */ | |
381 | _OrthancPluginService_LogInfo = 1, | |
382 | _OrthancPluginService_LogWarning = 2, | |
383 | _OrthancPluginService_LogError = 3, | |
384 | _OrthancPluginService_GetOrthancPath = 4, | |
385 | _OrthancPluginService_GetOrthancDirectory = 5, | |
386 | _OrthancPluginService_GetConfigurationPath = 6, | |
387 | _OrthancPluginService_SetPluginProperty = 7, | |
388 | _OrthancPluginService_GetGlobalProperty = 8, | |
389 | _OrthancPluginService_SetGlobalProperty = 9, | |
390 | _OrthancPluginService_GetCommandLineArgumentsCount = 10, | |
391 | _OrthancPluginService_GetCommandLineArgument = 11, | |
392 | _OrthancPluginService_GetExpectedDatabaseVersion = 12, | |
393 | _OrthancPluginService_GetConfiguration = 13, | |
394 | _OrthancPluginService_BufferCompression = 14, | |
395 | _OrthancPluginService_ReadFile = 15, | |
396 | _OrthancPluginService_WriteFile = 16, | |
397 | _OrthancPluginService_GetErrorDescription = 17, | |
398 | _OrthancPluginService_CallHttpClient = 18, | |
399 | _OrthancPluginService_RegisterErrorCode = 19, | |
400 | _OrthancPluginService_RegisterDictionaryTag = 20, | |
401 | _OrthancPluginService_DicomBufferToJson = 21, | |
402 | _OrthancPluginService_DicomInstanceToJson = 22, | |
403 | _OrthancPluginService_CreateDicom = 23, | |
404 | _OrthancPluginService_ComputeMd5 = 24, | |
405 | _OrthancPluginService_ComputeSha1 = 25, | |
406 | _OrthancPluginService_LookupDictionary = 26, | |
407 | _OrthancPluginService_CallHttpClient2 = 27, | |
408 | _OrthancPluginService_GenerateUuid = 28, | |
409 | ||
410 | /* Registration of callbacks */ | |
411 | _OrthancPluginService_RegisterRestCallback = 1000, | |
412 | _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001, | |
413 | _OrthancPluginService_RegisterStorageArea = 1002, | |
414 | _OrthancPluginService_RegisterOnChangeCallback = 1003, | |
415 | _OrthancPluginService_RegisterRestCallbackNoLock = 1004, | |
416 | _OrthancPluginService_RegisterWorklistCallback = 1005, | |
417 | _OrthancPluginService_RegisterDecodeImageCallback = 1006, | |
418 | _OrthancPluginService_RegisterIncomingHttpRequestFilter = 1007, | |
419 | _OrthancPluginService_RegisterFindCallback = 1008, | |
420 | _OrthancPluginService_RegisterMoveCallback = 1009, | |
421 | ||
422 | /* Sending answers to REST calls */ | |
423 | _OrthancPluginService_AnswerBuffer = 2000, | |
424 | _OrthancPluginService_CompressAndAnswerPngImage = 2001, /* Unused as of Orthanc 0.9.4 */ | |
425 | _OrthancPluginService_Redirect = 2002, | |
426 | _OrthancPluginService_SendHttpStatusCode = 2003, | |
427 | _OrthancPluginService_SendUnauthorized = 2004, | |
428 | _OrthancPluginService_SendMethodNotAllowed = 2005, | |
429 | _OrthancPluginService_SetCookie = 2006, | |
430 | _OrthancPluginService_SetHttpHeader = 2007, | |
431 | _OrthancPluginService_StartMultipartAnswer = 2008, | |
432 | _OrthancPluginService_SendMultipartItem = 2009, | |
433 | _OrthancPluginService_SendHttpStatus = 2010, | |
434 | _OrthancPluginService_CompressAndAnswerImage = 2011, | |
435 | _OrthancPluginService_SendMultipartItem2 = 2012, | |
436 | ||
437 | /* Access to the Orthanc database and API */ | |
438 | _OrthancPluginService_GetDicomForInstance = 3000, | |
439 | _OrthancPluginService_RestApiGet = 3001, | |
440 | _OrthancPluginService_RestApiPost = 3002, | |
441 | _OrthancPluginService_RestApiDelete = 3003, | |
442 | _OrthancPluginService_RestApiPut = 3004, | |
443 | _OrthancPluginService_LookupPatient = 3005, | |
444 | _OrthancPluginService_LookupStudy = 3006, | |
445 | _OrthancPluginService_LookupSeries = 3007, | |
446 | _OrthancPluginService_LookupInstance = 3008, | |
447 | _OrthancPluginService_LookupStudyWithAccessionNumber = 3009, | |
448 | _OrthancPluginService_RestApiGetAfterPlugins = 3010, | |
449 | _OrthancPluginService_RestApiPostAfterPlugins = 3011, | |
450 | _OrthancPluginService_RestApiDeleteAfterPlugins = 3012, | |
451 | _OrthancPluginService_RestApiPutAfterPlugins = 3013, | |
452 | _OrthancPluginService_ReconstructMainDicomTags = 3014, | |
453 | _OrthancPluginService_RestApiGet2 = 3015, | |
454 | ||
455 | /* Access to DICOM instances */ | |
456 | _OrthancPluginService_GetInstanceRemoteAet = 4000, | |
457 | _OrthancPluginService_GetInstanceSize = 4001, | |
458 | _OrthancPluginService_GetInstanceData = 4002, | |
459 | _OrthancPluginService_GetInstanceJson = 4003, | |
460 | _OrthancPluginService_GetInstanceSimplifiedJson = 4004, | |
461 | _OrthancPluginService_HasInstanceMetadata = 4005, | |
462 | _OrthancPluginService_GetInstanceMetadata = 4006, | |
463 | _OrthancPluginService_GetInstanceOrigin = 4007, | |
464 | ||
465 | /* Services for plugins implementing a database back-end */ | |
466 | _OrthancPluginService_RegisterDatabaseBackend = 5000, | |
467 | _OrthancPluginService_DatabaseAnswer = 5001, | |
468 | _OrthancPluginService_RegisterDatabaseBackendV2 = 5002, | |
469 | _OrthancPluginService_StorageAreaCreate = 5003, | |
470 | _OrthancPluginService_StorageAreaRead = 5004, | |
471 | _OrthancPluginService_StorageAreaRemove = 5005, | |
472 | ||
473 | /* Primitives for handling images */ | |
474 | _OrthancPluginService_GetImagePixelFormat = 6000, | |
475 | _OrthancPluginService_GetImageWidth = 6001, | |
476 | _OrthancPluginService_GetImageHeight = 6002, | |
477 | _OrthancPluginService_GetImagePitch = 6003, | |
478 | _OrthancPluginService_GetImageBuffer = 6004, | |
479 | _OrthancPluginService_UncompressImage = 6005, | |
480 | _OrthancPluginService_FreeImage = 6006, | |
481 | _OrthancPluginService_CompressImage = 6007, | |
482 | _OrthancPluginService_ConvertPixelFormat = 6008, | |
483 | _OrthancPluginService_GetFontsCount = 6009, | |
484 | _OrthancPluginService_GetFontInfo = 6010, | |
485 | _OrthancPluginService_DrawText = 6011, | |
486 | _OrthancPluginService_CreateImage = 6012, | |
487 | _OrthancPluginService_CreateImageAccessor = 6013, | |
488 | _OrthancPluginService_DecodeDicomImage = 6014, | |
489 | ||
490 | /* Primitives for handling C-Find, C-Move and worklists */ | |
491 | _OrthancPluginService_WorklistAddAnswer = 7000, | |
492 | _OrthancPluginService_WorklistMarkIncomplete = 7001, | |
493 | _OrthancPluginService_WorklistIsMatch = 7002, | |
494 | _OrthancPluginService_WorklistGetDicomQuery = 7003, | |
495 | _OrthancPluginService_FindAddAnswer = 7004, | |
496 | _OrthancPluginService_FindMarkIncomplete = 7005, | |
497 | _OrthancPluginService_GetFindQuerySize = 7006, | |
498 | _OrthancPluginService_GetFindQueryTag = 7007, | |
499 | _OrthancPluginService_GetFindQueryTagName = 7008, | |
500 | _OrthancPluginService_GetFindQueryValue = 7009, | |
501 | ||
502 | _OrthancPluginService_INTERNAL = 0x7fffffff | |
503 | } _OrthancPluginService; | |
504 | ||
505 | ||
506 | typedef enum | |
507 | { | |
508 | _OrthancPluginProperty_Description = 1, | |
509 | _OrthancPluginProperty_RootUri = 2, | |
510 | _OrthancPluginProperty_OrthancExplorer = 3, | |
511 | ||
512 | _OrthancPluginProperty_INTERNAL = 0x7fffffff | |
513 | } _OrthancPluginProperty; | |
514 | ||
515 | ||
516 | ||
517 | /** | |
518 | * The memory layout of the pixels of an image. | |
519 | * @ingroup Images | |
520 | **/ | |
521 | typedef enum | |
522 | { | |
523 | /** | |
524 | * @brief Graylevel 8bpp image. | |
525 | * | |
526 | * The image is graylevel. Each pixel is unsigned and stored in | |
527 | * one byte. | |
528 | **/ | |
529 | OrthancPluginPixelFormat_Grayscale8 = 1, | |
530 | ||
531 | /** | |
532 | * @brief Graylevel, unsigned 16bpp image. | |
533 | * | |
534 | * The image is graylevel. Each pixel is unsigned and stored in | |
535 | * two bytes. | |
536 | **/ | |
537 | OrthancPluginPixelFormat_Grayscale16 = 2, | |
538 | ||
539 | /** | |
540 | * @brief Graylevel, signed 16bpp image. | |
541 | * | |
542 | * The image is graylevel. Each pixel is signed and stored in two | |
543 | * bytes. | |
544 | **/ | |
545 | OrthancPluginPixelFormat_SignedGrayscale16 = 3, | |
546 | ||
547 | /** | |
548 | * @brief Color image in RGB24 format. | |
549 | * | |
550 | * This format describes a color image. The pixels are stored in 3 | |
551 | * consecutive bytes. The memory layout is RGB. | |
552 | **/ | |
553 | OrthancPluginPixelFormat_RGB24 = 4, | |
554 | ||
555 | /** | |
556 | * @brief Color image in RGBA32 format. | |
557 | * | |
558 | * This format describes a color image. The pixels are stored in 4 | |
559 | * consecutive bytes. The memory layout is RGBA. | |
560 | **/ | |
561 | OrthancPluginPixelFormat_RGBA32 = 5, | |
562 | ||
563 | OrthancPluginPixelFormat_Unknown = 6, /*!< Unknown pixel format */ | |
564 | ||
565 | _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff | |
566 | } OrthancPluginPixelFormat; | |
567 | ||
568 | ||
569 | ||
570 | /** | |
571 | * The content types that are supported by Orthanc plugins. | |
572 | **/ | |
573 | typedef enum | |
574 | { | |
575 | OrthancPluginContentType_Unknown = 0, /*!< Unknown content type */ | |
576 | OrthancPluginContentType_Dicom = 1, /*!< DICOM */ | |
577 | OrthancPluginContentType_DicomAsJson = 2, /*!< JSON summary of a DICOM file */ | |
578 | ||
579 | _OrthancPluginContentType_INTERNAL = 0x7fffffff | |
580 | } OrthancPluginContentType; | |
581 | ||
582 | ||
583 | ||
584 | /** | |
585 | * The supported types of DICOM resources. | |
586 | **/ | |
587 | typedef enum | |
588 | { | |
589 | OrthancPluginResourceType_Patient = 0, /*!< Patient */ | |
590 | OrthancPluginResourceType_Study = 1, /*!< Study */ | |
591 | OrthancPluginResourceType_Series = 2, /*!< Series */ | |
592 | OrthancPluginResourceType_Instance = 3, /*!< Instance */ | |
593 | OrthancPluginResourceType_None = 4, /*!< Unavailable resource type */ | |
594 | ||
595 | _OrthancPluginResourceType_INTERNAL = 0x7fffffff | |
596 | } OrthancPluginResourceType; | |
597 | ||
598 | ||
599 | ||
600 | /** | |
601 | * The supported types of changes that can happen to DICOM resources. | |
602 | * @ingroup Callbacks | |
603 | **/ | |
604 | typedef enum | |
605 | { | |
606 | OrthancPluginChangeType_CompletedSeries = 0, /*!< Series is now complete */ | |
607 | OrthancPluginChangeType_Deleted = 1, /*!< Deleted resource */ | |
608 | OrthancPluginChangeType_NewChildInstance = 2, /*!< A new instance was added to this resource */ | |
609 | OrthancPluginChangeType_NewInstance = 3, /*!< New instance received */ | |
610 | OrthancPluginChangeType_NewPatient = 4, /*!< New patient created */ | |
611 | OrthancPluginChangeType_NewSeries = 5, /*!< New series created */ | |
612 | OrthancPluginChangeType_NewStudy = 6, /*!< New study created */ | |
613 | OrthancPluginChangeType_StablePatient = 7, /*!< Timeout: No new instance in this patient */ | |
614 | OrthancPluginChangeType_StableSeries = 8, /*!< Timeout: No new instance in this series */ | |
615 | OrthancPluginChangeType_StableStudy = 9, /*!< Timeout: No new instance in this study */ | |
616 | OrthancPluginChangeType_OrthancStarted = 10, /*!< Orthanc has started */ | |
617 | OrthancPluginChangeType_OrthancStopped = 11, /*!< Orthanc is stopping */ | |
618 | OrthancPluginChangeType_UpdatedAttachment = 12, /*!< Some user-defined attachment has changed for this resource */ | |
619 | OrthancPluginChangeType_UpdatedMetadata = 13, /*!< Some user-defined metadata has changed for this resource */ | |
620 | ||
621 | _OrthancPluginChangeType_INTERNAL = 0x7fffffff | |
622 | } OrthancPluginChangeType; | |
623 | ||
624 | ||
625 | /** | |
626 | * The compression algorithms that are supported by the Orthanc core. | |
627 | * @ingroup Images | |
628 | **/ | |
629 | typedef enum | |
630 | { | |
631 | OrthancPluginCompressionType_Zlib = 0, /*!< Standard zlib compression */ | |
632 | OrthancPluginCompressionType_ZlibWithSize = 1, /*!< zlib, prefixed with uncompressed size (uint64_t) */ | |
633 | OrthancPluginCompressionType_Gzip = 2, /*!< Standard gzip compression */ | |
634 | OrthancPluginCompressionType_GzipWithSize = 3, /*!< gzip, prefixed with uncompressed size (uint64_t) */ | |
635 | ||
636 | _OrthancPluginCompressionType_INTERNAL = 0x7fffffff | |
637 | } OrthancPluginCompressionType; | |
638 | ||
639 | ||
640 | /** | |
641 | * The image formats that are supported by the Orthanc core. | |
642 | * @ingroup Images | |
643 | **/ | |
644 | typedef enum | |
645 | { | |
646 | OrthancPluginImageFormat_Png = 0, /*!< Image compressed using PNG */ | |
647 | OrthancPluginImageFormat_Jpeg = 1, /*!< Image compressed using JPEG */ | |
648 | OrthancPluginImageFormat_Dicom = 2, /*!< Image compressed using DICOM */ | |
649 | ||
650 | _OrthancPluginImageFormat_INTERNAL = 0x7fffffff | |
651 | } OrthancPluginImageFormat; | |
652 | ||
653 | ||
654 | /** | |
655 | * The value representations present in the DICOM standard (version 2013). | |
656 | * @ingroup Toolbox | |
657 | **/ | |
658 | typedef enum | |
659 | { | |
660 | OrthancPluginValueRepresentation_AE = 1, /*!< Application Entity */ | |
661 | OrthancPluginValueRepresentation_AS = 2, /*!< Age String */ | |
662 | OrthancPluginValueRepresentation_AT = 3, /*!< Attribute Tag */ | |
663 | OrthancPluginValueRepresentation_CS = 4, /*!< Code String */ | |
664 | OrthancPluginValueRepresentation_DA = 5, /*!< Date */ | |
665 | OrthancPluginValueRepresentation_DS = 6, /*!< Decimal String */ | |
666 | OrthancPluginValueRepresentation_DT = 7, /*!< Date Time */ | |
667 | OrthancPluginValueRepresentation_FD = 8, /*!< Floating Point Double */ | |
668 | OrthancPluginValueRepresentation_FL = 9, /*!< Floating Point Single */ | |
669 | OrthancPluginValueRepresentation_IS = 10, /*!< Integer String */ | |
670 | OrthancPluginValueRepresentation_LO = 11, /*!< Long String */ | |
671 | OrthancPluginValueRepresentation_LT = 12, /*!< Long Text */ | |
672 | OrthancPluginValueRepresentation_OB = 13, /*!< Other Byte String */ | |
673 | OrthancPluginValueRepresentation_OF = 14, /*!< Other Float String */ | |
674 | OrthancPluginValueRepresentation_OW = 15, /*!< Other Word String */ | |
675 | OrthancPluginValueRepresentation_PN = 16, /*!< Person Name */ | |
676 | OrthancPluginValueRepresentation_SH = 17, /*!< Short String */ | |
677 | OrthancPluginValueRepresentation_SL = 18, /*!< Signed Long */ | |
678 | OrthancPluginValueRepresentation_SQ = 19, /*!< Sequence of Items */ | |
679 | OrthancPluginValueRepresentation_SS = 20, /*!< Signed Short */ | |
680 | OrthancPluginValueRepresentation_ST = 21, /*!< Short Text */ | |
681 | OrthancPluginValueRepresentation_TM = 22, /*!< Time */ | |
682 | OrthancPluginValueRepresentation_UI = 23, /*!< Unique Identifier (UID) */ | |
683 | OrthancPluginValueRepresentation_UL = 24, /*!< Unsigned Long */ | |
684 | OrthancPluginValueRepresentation_UN = 25, /*!< Unknown */ | |
685 | OrthancPluginValueRepresentation_US = 26, /*!< Unsigned Short */ | |
686 | OrthancPluginValueRepresentation_UT = 27, /*!< Unlimited Text */ | |
687 | ||
688 | _OrthancPluginValueRepresentation_INTERNAL = 0x7fffffff | |
689 | } OrthancPluginValueRepresentation; | |
690 | ||
691 | ||
692 | /** | |
693 | * The possible output formats for a DICOM-to-JSON conversion. | |
694 | * @ingroup Toolbox | |
695 | * @see OrthancPluginDicomToJson() | |
696 | **/ | |
697 | typedef enum | |
698 | { | |
699 | OrthancPluginDicomToJsonFormat_Full = 1, /*!< Full output, with most details */ | |
700 | OrthancPluginDicomToJsonFormat_Short = 2, /*!< Tags output as hexadecimal numbers */ | |
701 | OrthancPluginDicomToJsonFormat_Human = 3, /*!< Human-readable JSON */ | |
702 | ||
703 | _OrthancPluginDicomToJsonFormat_INTERNAL = 0x7fffffff | |
704 | } OrthancPluginDicomToJsonFormat; | |
705 | ||
706 | ||
707 | /** | |
708 | * Flags to customize a DICOM-to-JSON conversion. By default, binary | |
709 | * tags are formatted using Data URI scheme. | |
710 | * @ingroup Toolbox | |
711 | **/ | |
712 | typedef enum | |
713 | { | |
714 | OrthancPluginDicomToJsonFlags_IncludeBinary = (1 << 0), /*!< Include the binary tags */ | |
715 | OrthancPluginDicomToJsonFlags_IncludePrivateTags = (1 << 1), /*!< Include the private tags */ | |
716 | OrthancPluginDicomToJsonFlags_IncludeUnknownTags = (1 << 2), /*!< Include the tags unknown by the dictionary */ | |
717 | OrthancPluginDicomToJsonFlags_IncludePixelData = (1 << 3), /*!< Include the pixel data */ | |
718 | OrthancPluginDicomToJsonFlags_ConvertBinaryToAscii = (1 << 4), /*!< Output binary tags as-is, dropping non-ASCII */ | |
719 | OrthancPluginDicomToJsonFlags_ConvertBinaryToNull = (1 << 5), /*!< Signal binary tags as null values */ | |
720 | ||
721 | _OrthancPluginDicomToJsonFlags_INTERNAL = 0x7fffffff | |
722 | } OrthancPluginDicomToJsonFlags; | |
723 | ||
724 | ||
725 | /** | |
726 | * Flags to the creation of a DICOM file. | |
727 | * @ingroup Toolbox | |
728 | * @see OrthancPluginCreateDicom() | |
729 | **/ | |
730 | typedef enum | |
731 | { | |
732 | OrthancPluginCreateDicomFlags_DecodeDataUriScheme = (1 << 0), /*!< Decode fields encoded using data URI scheme */ | |
733 | OrthancPluginCreateDicomFlags_GenerateIdentifiers = (1 << 1), /*!< Automatically generate DICOM identifiers */ | |
734 | ||
735 | _OrthancPluginCreateDicomFlags_INTERNAL = 0x7fffffff | |
736 | } OrthancPluginCreateDicomFlags; | |
737 | ||
738 | ||
739 | /** | |
740 | * The constraints on the DICOM identifiers that must be supported | |
741 | * by the database plugins. | |
742 | **/ | |
743 | typedef enum | |
744 | { | |
745 | OrthancPluginIdentifierConstraint_Equal = 1, /*!< Equal */ | |
746 | OrthancPluginIdentifierConstraint_SmallerOrEqual = 2, /*!< Less or equal */ | |
747 | OrthancPluginIdentifierConstraint_GreaterOrEqual = 3, /*!< More or equal */ | |
748 | OrthancPluginIdentifierConstraint_Wildcard = 4, /*!< Case-sensitive wildcard matching (with * and ?) */ | |
749 | ||
750 | _OrthancPluginIdentifierConstraint_INTERNAL = 0x7fffffff | |
751 | } OrthancPluginIdentifierConstraint; | |
752 | ||
753 | ||
754 | /** | |
755 | * The origin of a DICOM instance that has been received by Orthanc. | |
756 | **/ | |
757 | typedef enum | |
758 | { | |
759 | OrthancPluginInstanceOrigin_Unknown = 1, /*!< Unknown origin */ | |
760 | OrthancPluginInstanceOrigin_DicomProtocol = 2, /*!< Instance received through DICOM protocol */ | |
761 | OrthancPluginInstanceOrigin_RestApi = 3, /*!< Instance received through REST API of Orthanc */ | |
762 | OrthancPluginInstanceOrigin_Plugin = 4, /*!< Instance added to Orthanc by a plugin */ | |
763 | OrthancPluginInstanceOrigin_Lua = 5, /*!< Instance added to Orthanc by a Lua script */ | |
764 | ||
765 | _OrthancPluginInstanceOrigin_INTERNAL = 0x7fffffff | |
766 | } OrthancPluginInstanceOrigin; | |
767 | ||
768 | ||
769 | /** | |
770 | * @brief A memory buffer allocated by the core system of Orthanc. | |
771 | * | |
772 | * A memory buffer allocated by the core system of Orthanc. When the | |
773 | * content of the buffer is not useful anymore, it must be free by a | |
774 | * call to ::OrthancPluginFreeMemoryBuffer(). | |
775 | **/ | |
776 | typedef struct | |
777 | { | |
778 | /** | |
779 | * @brief The content of the buffer. | |
780 | **/ | |
781 | void* data; | |
782 | ||
783 | /** | |
784 | * @brief The number of bytes in the buffer. | |
785 | **/ | |
786 | uint32_t size; | |
787 | } OrthancPluginMemoryBuffer; | |
788 | ||
789 | ||
790 | ||
791 | ||
792 | /** | |
793 | * @brief Opaque structure that represents the HTTP connection to the client application. | |
794 | * @ingroup Callback | |
795 | **/ | |
796 | typedef struct _OrthancPluginRestOutput_t OrthancPluginRestOutput; | |
797 | ||
798 | ||
799 | ||
800 | /** | |
801 | * @brief Opaque structure that represents a DICOM instance received by Orthanc. | |
802 | **/ | |
803 | typedef struct _OrthancPluginDicomInstance_t OrthancPluginDicomInstance; | |
804 | ||
805 | ||
806 | ||
807 | /** | |
808 | * @brief Opaque structure that represents an image that is uncompressed in memory. | |
809 | * @ingroup Images | |
810 | **/ | |
811 | typedef struct _OrthancPluginImage_t OrthancPluginImage; | |
812 | ||
813 | ||
814 | ||
815 | /** | |
816 | * @brief Opaque structure that represents the storage area that is actually used by Orthanc. | |
817 | * @ingroup Images | |
818 | **/ | |
819 | typedef struct _OrthancPluginStorageArea_t OrthancPluginStorageArea; | |
820 | ||
821 | ||
822 | ||
823 | /** | |
824 | * @brief Opaque structure to an object that represents a C-Find query for worklists. | |
825 | * @ingroup DicomCallbacks | |
826 | **/ | |
827 | typedef struct _OrthancPluginWorklistQuery_t OrthancPluginWorklistQuery; | |
828 | ||
829 | ||
830 | ||
831 | /** | |
832 | * @brief Opaque structure to an object that represents the answers to a C-Find query for worklists. | |
833 | * @ingroup DicomCallbacks | |
834 | **/ | |
835 | typedef struct _OrthancPluginWorklistAnswers_t OrthancPluginWorklistAnswers; | |
836 | ||
837 | ||
838 | ||
839 | /** | |
840 | * @brief Opaque structure to an object that represents a C-Find query. | |
841 | * @ingroup DicomCallbacks | |
842 | **/ | |
843 | typedef struct _OrthancPluginFindQuery_t OrthancPluginFindQuery; | |
844 | ||
845 | ||
846 | ||
847 | /** | |
848 | * @brief Opaque structure to an object that represents the answers to a C-Find query for worklists. | |
849 | * @ingroup DicomCallbacks | |
850 | **/ | |
851 | typedef struct _OrthancPluginFindAnswers_t OrthancPluginFindAnswers; | |
852 | ||
853 | ||
854 | ||
855 | /** | |
856 | * @brief Signature of a callback function that answers to a REST request. | |
857 | * @ingroup Callbacks | |
858 | **/ | |
859 | typedef OrthancPluginErrorCode (*OrthancPluginRestCallback) ( | |
860 | OrthancPluginRestOutput* output, | |
861 | const char* url, | |
862 | const OrthancPluginHttpRequest* request); | |
863 | ||
864 | ||
865 | ||
866 | /** | |
867 | * @brief Signature of a callback function that is triggered when Orthanc receives a DICOM instance. | |
868 | * @ingroup Callbacks | |
869 | **/ | |
870 | typedef OrthancPluginErrorCode (*OrthancPluginOnStoredInstanceCallback) ( | |
871 | OrthancPluginDicomInstance* instance, | |
872 | const char* instanceId); | |
873 | ||
874 | ||
875 | ||
876 | /** | |
877 | * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource. | |
878 | * @ingroup Callbacks | |
879 | **/ | |
880 | typedef OrthancPluginErrorCode (*OrthancPluginOnChangeCallback) ( | |
881 | OrthancPluginChangeType changeType, | |
882 | OrthancPluginResourceType resourceType, | |
883 | const char* resourceId); | |
884 | ||
885 | ||
886 | ||
887 | /** | |
888 | * @brief Signature of a callback function to decode a DICOM instance as an image. | |
889 | * @ingroup Callbacks | |
890 | **/ | |
891 | typedef OrthancPluginErrorCode (*OrthancPluginDecodeImageCallback) ( | |
892 | OrthancPluginImage** target, | |
893 | const void* dicom, | |
894 | const uint32_t size, | |
895 | uint32_t frameIndex); | |
896 | ||
897 | ||
898 | ||
899 | /** | |
900 | * @brief Signature of a function to free dynamic memory. | |
901 | **/ | |
902 | typedef void (*OrthancPluginFree) (void* buffer); | |
903 | ||
904 | ||
905 | ||
906 | /** | |
907 | * @brief Callback for writing to the storage area. | |
908 | * | |
909 | * Signature of a callback function that is triggered when Orthanc writes a file to the storage area. | |
910 | * | |
911 | * @param uuid The UUID of the file. | |
912 | * @param content The content of the file. | |
913 | * @param size The size of the file. | |
914 | * @param type The content type corresponding to this file. | |
915 | * @return 0 if success, other value if error. | |
916 | * @ingroup Callbacks | |
917 | **/ | |
918 | typedef OrthancPluginErrorCode (*OrthancPluginStorageCreate) ( | |
919 | const char* uuid, | |
920 | const void* content, | |
921 | int64_t size, | |
922 | OrthancPluginContentType type); | |
923 | ||
924 | ||
925 | ||
926 | /** | |
927 | * @brief Callback for reading from the storage area. | |
928 | * | |
929 | * Signature of a callback function that is triggered when Orthanc reads a file from the storage area. | |
930 | * | |
931 | * @param content The content of the file (output). | |
932 | * @param size The size of the file (output). | |
933 | * @param uuid The UUID of the file of interest. | |
934 | * @param type The content type corresponding to this file. | |
935 | * @return 0 if success, other value if error. | |
936 | * @ingroup Callbacks | |
937 | **/ | |
938 | typedef OrthancPluginErrorCode (*OrthancPluginStorageRead) ( | |
939 | void** content, | |
940 | int64_t* size, | |
941 | const char* uuid, | |
942 | OrthancPluginContentType type); | |
943 | ||
944 | ||
945 | ||
946 | /** | |
947 | * @brief Callback for removing a file from the storage area. | |
948 | * | |
949 | * Signature of a callback function that is triggered when Orthanc deletes a file from the storage area. | |
950 | * | |
951 | * @param uuid The UUID of the file to be removed. | |
952 | * @param type The content type corresponding to this file. | |
953 | * @return 0 if success, other value if error. | |
954 | * @ingroup Callbacks | |
955 | **/ | |
956 | typedef OrthancPluginErrorCode (*OrthancPluginStorageRemove) ( | |
957 | const char* uuid, | |
958 | OrthancPluginContentType type); | |
959 | ||
960 | ||
961 | ||
962 | /** | |
963 | * @brief Callback to handle the C-Find SCP requests for worklists. | |
964 | * | |
965 | * Signature of a callback function that is triggered when Orthanc | |
966 | * receives a C-Find SCP request against modality worklists. | |
967 | * | |
968 | * @param answers The target structure where answers must be stored. | |
969 | * @param query The worklist query. | |
970 | * @param issuerAet The Application Entity Title (AET) of the modality from which the request originates. | |
971 | * @param calledAet The Application Entity Title (AET) of the modality that is called by the request. | |
972 | * @return 0 if success, other value if error. | |
973 | * @ingroup DicomCallbacks | |
974 | **/ | |
975 | typedef OrthancPluginErrorCode (*OrthancPluginWorklistCallback) ( | |
976 | OrthancPluginWorklistAnswers* answers, | |
977 | const OrthancPluginWorklistQuery* query, | |
978 | const char* issuerAet, | |
979 | const char* calledAet); | |
980 | ||
981 | ||
982 | ||
983 | /** | |
984 | * @brief Callback to filter incoming HTTP requests received by Orthanc. | |
985 | * | |
986 | * Signature of a callback function that is triggered whenever | |
987 | * Orthanc receives an HTTP/REST request, and that answers whether | |
988 | * this request should be allowed. If the callback returns "0" | |
989 | * ("false"), the server answers with HTTP status code 403 | |
990 | * (Forbidden). | |
991 | * | |
992 | * @param method The HTTP method used by the request. | |
993 | * @param uri The URI of interest. | |
994 | * @param ip The IP address of the HTTP client. | |
995 | * @param headersCount The number of HTTP headers. | |
996 | * @param headersKeys The keys of the HTTP headers (always converted to low-case). | |
997 | * @param headersValues The values of the HTTP headers. | |
998 | * @return 0 if forbidden access, 1 if allowed access, -1 if error. | |
999 | * @ingroup Callback | |
1000 | **/ | |
1001 | typedef int32_t (*OrthancPluginIncomingHttpRequestFilter) ( | |
1002 | OrthancPluginHttpMethod method, | |
1003 | const char* uri, | |
1004 | const char* ip, | |
1005 | uint32_t headersCount, | |
1006 | const char* const* headersKeys, | |
1007 | const char* const* headersValues); | |
1008 | ||
1009 | ||
1010 | ||
1011 | /** | |
1012 | * @brief Callback to handle incoming C-Find SCP requests. | |
1013 | * | |
1014 | * Signature of a callback function that is triggered whenever | |
1015 | * Orthanc receives a C-Find SCP request not concerning modality | |
1016 | * worklists. | |
1017 | * | |
1018 | * @param answers The target structure where answers must be stored. | |
1019 | * @param query The worklist query. | |
1020 | * @param issuerAet The Application Entity Title (AET) of the modality from which the request originates. | |
1021 | * @param calledAet The Application Entity Title (AET) of the modality that is called by the request. | |
1022 | * @return 0 if success, other value if error. | |
1023 | * @ingroup DicomCallbacks | |
1024 | **/ | |
1025 | typedef OrthancPluginErrorCode (*OrthancPluginFindCallback) ( | |
1026 | OrthancPluginFindAnswers* answers, | |
1027 | const OrthancPluginFindQuery* query, | |
1028 | const char* issuerAet, | |
1029 | const char* calledAet); | |
1030 | ||
1031 | ||
1032 | ||
1033 | /** | |
1034 | * @brief Callback to handle incoming C-Move SCP requests. | |
1035 | * | |
1036 | * Signature of a callback function that is triggered whenever | |
1037 | * Orthanc receives a C-Move SCP request. The callback receives the | |
1038 | * type of the resource of interest (study, series, instance...) | |
1039 | * together with the DICOM tags containing its identifiers. In turn, | |
1040 | * the plugin must create a driver object that will be responsible | |
1041 | * for driving the successive move suboperations. | |
1042 | * | |
1043 | * @param resourceType The type of the resource of interest. Note | |
1044 | * that this might be set to ResourceType_None if the | |
1045 | * QueryRetrieveLevel (0008,0052) tag was not provided by the | |
1046 | * issuer. | |
1047 | * @param patientId Content of the PatientID (0x0010, 0x0020) tag of the resource of interest. Might be NULL. | |
1048 | * @param accessionNumber Content of the AccessionNumber (0x0008, 0x0050) tag. Might be NULL. | |
1049 | * @param studyInstanceUid Content of the StudyInstanceUID (0x0020, 0x000d) tag. Might be NULL. | |
1050 | * @param seriesInstanceUid Content of the SeriesInstanceUID (0x0020, 0x000e) tag. Might be NULL. | |
1051 | * @param sopInstanceUid Content of the SOPInstanceUID (0x0008, 0x0018) tag. Might be NULL. | |
1052 | * @param issuerAet The Application Entity Title (AET) of the | |
1053 | * modality from which the request originates. | |
1054 | * @param sourceAet The Application Entity Title (AET) of the | |
1055 | * modality that should send its DICOM files to another modality. | |
1056 | * @param targetAet The Application Entity Title (AET) of the | |
1057 | * modality that should receive the DICOM files. | |
1058 | * | |
1059 | * @return The NULL value if the plugin cannot deal with this query, | |
1060 | * or a pointer to the driver object that is responsible for | |
1061 | * handling the successive move suboperations. | |
1062 | * | |
1063 | * @note If targetAet equals sourceAet, this is actually a query/retrieve operation. | |
1064 | * @ingroup DicomCallbacks | |
1065 | **/ | |
1066 | typedef void* (*OrthancPluginMoveCallback) ( | |
1067 | OrthancPluginResourceType resourceType, | |
1068 | const char* patientId, | |
1069 | const char* accessionNumber, | |
1070 | const char* studyInstanceUid, | |
1071 | const char* seriesInstanceUid, | |
1072 | const char* sopInstanceUid, | |
1073 | const char* issuerAet, | |
1074 | const char* sourceAet, | |
1075 | const char* targetAet, | |
1076 | uint16_t moveOriginatorId); | |
1077 | ||
1078 | ||
1079 | /** | |
1080 | * @brief Callback to read the size of a C-Move driver. | |
1081 | * | |
1082 | * Signature of a callback function that returns the number of | |
1083 | * C-Move suboperations that are to be achieved by the given C-Move | |
1084 | * driver. This driver is the return value of a previous call to the | |
1085 | * OrthancPluginMoveCallback() callback. | |
1086 | * | |
1087 | * @param moveDriver The C-Move driver of interest. | |
1088 | * @return The number of suboperations. | |
1089 | **/ | |
1090 | typedef uint32_t (*OrthancPluginGetMoveSize) (void* moveDriver); | |
1091 | ||
1092 | ||
1093 | /** | |
1094 | * @brief Callback to apply one C-Move suboperation. | |
1095 | * | |
1096 | * Signature of a callback function that applies the next C-Move | |
1097 | * suboperation that os to be achieved by the given C-Move | |
1098 | * driver. This driver is the return value of a previous call to the | |
1099 | * OrthancPluginMoveCallback() callback. | |
1100 | * | |
1101 | * @param moveDriver The C-Move driver of interest. | |
1102 | * @return 0 if success, or the error code if failure. | |
1103 | **/ | |
1104 | typedef OrthancPluginErrorCode (*OrthancPluginApplyMove) (void* moveDriver); | |
1105 | ||
1106 | ||
1107 | /** | |
1108 | * @brief Callback to free one C-Move driver. | |
1109 | * | |
1110 | * Signature of a callback function that releases the resources | |
1111 | * allocated by the given C-Move driver. This driver is the return | |
1112 | * value of a previous call to the OrthancPluginMoveCallback() | |
1113 | * callback. | |
1114 | * | |
1115 | * @param moveDriver The C-Move driver of interest. | |
1116 | **/ | |
1117 | typedef void (*OrthancPluginFreeMove) (void* moveDriver); | |
1118 | ||
1119 | ||
1120 | ||
1121 | /** | |
1122 | * @brief Data structure that contains information about the Orthanc core. | |
1123 | **/ | |
1124 | typedef struct _OrthancPluginContext_t | |
1125 | { | |
1126 | void* pluginsManager; | |
1127 | const char* orthancVersion; | |
1128 | OrthancPluginFree Free; | |
1129 | OrthancPluginErrorCode (*InvokeService) (struct _OrthancPluginContext_t* context, | |
1130 | _OrthancPluginService service, | |
1131 | const void* params); | |
1132 | } OrthancPluginContext; | |
1133 | ||
1134 | ||
1135 | ||
1136 | /** | |
1137 | * @brief An entry in the dictionary of DICOM tags. | |
1138 | **/ | |
1139 | typedef struct | |
1140 | { | |
1141 | uint16_t group; /*!< The group of the tag */ | |
1142 | uint16_t element; /*!< The element of the tag */ | |
1143 | OrthancPluginValueRepresentation vr; /*!< The value representation of the tag */ | |
1144 | uint32_t minMultiplicity; /*!< The minimum multiplicity of the tag */ | |
1145 | uint32_t maxMultiplicity; /*!< The maximum multiplicity of the tag (0 means arbitrary) */ | |
1146 | } OrthancPluginDictionaryEntry; | |
1147 | ||
1148 | ||
1149 | ||
1150 | /** | |
1151 | * @brief Free a string. | |
1152 | * | |
1153 | * Free a string that was allocated by the core system of Orthanc. | |
1154 | * | |
1155 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1156 | * @param str The string to be freed. | |
1157 | **/ | |
1158 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeString( | |
1159 | OrthancPluginContext* context, | |
1160 | char* str) | |
1161 | { | |
1162 | if (str != NULL) | |
1163 | { | |
1164 | context->Free(str); | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | ||
1169 | /** | |
1170 | * @brief Check the compatibility of the plugin wrt. the version of its hosting Orthanc. | |
1171 | * | |
1172 | * This function checks whether the version of this C header is | |
1173 | * compatible with the current version of Orthanc. The result of | |
1174 | * this function should always be checked in the | |
1175 | * OrthancPluginInitialize() entry point of the plugin. | |
1176 | * | |
1177 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1178 | * @return 1 if and only if the versions are compatible. If the | |
1179 | * result is 0, the initialization of the plugin should fail. | |
1180 | * @ingroup Callbacks | |
1181 | **/ | |
1182 | ORTHANC_PLUGIN_INLINE int OrthancPluginCheckVersion( | |
1183 | OrthancPluginContext* context) | |
1184 | { | |
1185 | int major, minor, revision; | |
1186 | ||
1187 | if (sizeof(int32_t) != sizeof(OrthancPluginErrorCode) || | |
1188 | sizeof(int32_t) != sizeof(OrthancPluginHttpMethod) || | |
1189 | sizeof(int32_t) != sizeof(_OrthancPluginService) || | |
1190 | sizeof(int32_t) != sizeof(_OrthancPluginProperty) || | |
1191 | sizeof(int32_t) != sizeof(OrthancPluginPixelFormat) || | |
1192 | sizeof(int32_t) != sizeof(OrthancPluginContentType) || | |
1193 | sizeof(int32_t) != sizeof(OrthancPluginResourceType) || | |
1194 | sizeof(int32_t) != sizeof(OrthancPluginChangeType) || | |
1195 | sizeof(int32_t) != sizeof(OrthancPluginCompressionType) || | |
1196 | sizeof(int32_t) != sizeof(OrthancPluginImageFormat) || | |
1197 | sizeof(int32_t) != sizeof(OrthancPluginValueRepresentation) || | |
1198 | sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFormat) || | |
1199 | sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) || | |
1200 | sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) || | |
1201 | sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) || | |
1202 | sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin)) | |
1203 | { | |
1204 | /* Mismatch in the size of the enumerations */ | |
1205 | return 0; | |
1206 | } | |
1207 | ||
1208 | /* Assume compatibility with the mainline */ | |
1209 | if (!strcmp(context->orthancVersion, "mainline")) | |
1210 | { | |
1211 | return 1; | |
1212 | } | |
1213 | ||
1214 | /* Parse the version of the Orthanc core */ | |
1215 | if ( | |
1216 | #ifdef _MSC_VER | |
1217 | sscanf_s | |
1218 | #else | |
1219 | sscanf | |
1220 | #endif | |
1221 | (context->orthancVersion, "%4d.%4d.%4d", &major, &minor, &revision) != 3) | |
1222 | { | |
1223 | return 0; | |
1224 | } | |
1225 | ||
1226 | /* Check the major number of the version */ | |
1227 | ||
1228 | if (major > ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) | |
1229 | { | |
1230 | return 1; | |
1231 | } | |
1232 | ||
1233 | if (major < ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) | |
1234 | { | |
1235 | return 0; | |
1236 | } | |
1237 | ||
1238 | /* Check the minor number of the version */ | |
1239 | ||
1240 | if (minor > ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) | |
1241 | { | |
1242 | return 1; | |
1243 | } | |
1244 | ||
1245 | if (minor < ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) | |
1246 | { | |
1247 | return 0; | |
1248 | } | |
1249 | ||
1250 | /* Check the revision number of the version */ | |
1251 | ||
1252 | if (revision >= ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER) | |
1253 | { | |
1254 | return 1; | |
1255 | } | |
1256 | else | |
1257 | { | |
1258 | return 0; | |
1259 | } | |
1260 | } | |
1261 | ||
1262 | ||
1263 | /** | |
1264 | * @brief Free a memory buffer. | |
1265 | * | |
1266 | * Free a memory buffer that was allocated by the core system of Orthanc. | |
1267 | * | |
1268 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1269 | * @param buffer The memory buffer to release. | |
1270 | **/ | |
1271 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeMemoryBuffer( | |
1272 | OrthancPluginContext* context, | |
1273 | OrthancPluginMemoryBuffer* buffer) | |
1274 | { | |
1275 | context->Free(buffer->data); | |
1276 | } | |
1277 | ||
1278 | ||
1279 | /** | |
1280 | * @brief Log an error. | |
1281 | * | |
1282 | * Log an error message using the Orthanc logging system. | |
1283 | * | |
1284 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1285 | * @param message The message to be logged. | |
1286 | **/ | |
1287 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogError( | |
1288 | OrthancPluginContext* context, | |
1289 | const char* message) | |
1290 | { | |
1291 | context->InvokeService(context, _OrthancPluginService_LogError, message); | |
1292 | } | |
1293 | ||
1294 | ||
1295 | /** | |
1296 | * @brief Log a warning. | |
1297 | * | |
1298 | * Log a warning message using the Orthanc logging system. | |
1299 | * | |
1300 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1301 | * @param message The message to be logged. | |
1302 | **/ | |
1303 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning( | |
1304 | OrthancPluginContext* context, | |
1305 | const char* message) | |
1306 | { | |
1307 | context->InvokeService(context, _OrthancPluginService_LogWarning, message); | |
1308 | } | |
1309 | ||
1310 | ||
1311 | /** | |
1312 | * @brief Log an information. | |
1313 | * | |
1314 | * Log an information message using the Orthanc logging system. | |
1315 | * | |
1316 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1317 | * @param message The message to be logged. | |
1318 | **/ | |
1319 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo( | |
1320 | OrthancPluginContext* context, | |
1321 | const char* message) | |
1322 | { | |
1323 | context->InvokeService(context, _OrthancPluginService_LogInfo, message); | |
1324 | } | |
1325 | ||
1326 | ||
1327 | ||
1328 | typedef struct | |
1329 | { | |
1330 | const char* pathRegularExpression; | |
1331 | OrthancPluginRestCallback callback; | |
1332 | } _OrthancPluginRestCallback; | |
1333 | ||
1334 | /** | |
1335 | * @brief Register a REST callback. | |
1336 | * | |
1337 | * This function registers a REST callback against a regular | |
1338 | * expression for a URI. This function must be called during the | |
1339 | * initialization of the plugin, i.e. inside the | |
1340 | * OrthancPluginInitialize() public function. | |
1341 | * | |
1342 | * Each REST callback is guaranteed to run in mutual exclusion. | |
1343 | * | |
1344 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1345 | * @param pathRegularExpression Regular expression for the URI. May contain groups. | |
1346 | * @param callback The callback function to handle the REST call. | |
1347 | * @see OrthancPluginRegisterRestCallbackNoLock() | |
1348 | * @ingroup Callbacks | |
1349 | **/ | |
1350 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback( | |
1351 | OrthancPluginContext* context, | |
1352 | const char* pathRegularExpression, | |
1353 | OrthancPluginRestCallback callback) | |
1354 | { | |
1355 | _OrthancPluginRestCallback params; | |
1356 | params.pathRegularExpression = pathRegularExpression; | |
1357 | params.callback = callback; | |
1358 | context->InvokeService(context, _OrthancPluginService_RegisterRestCallback, ¶ms); | |
1359 | } | |
1360 | ||
1361 | ||
1362 | ||
1363 | /** | |
1364 | * @brief Register a REST callback, without locking. | |
1365 | * | |
1366 | * This function registers a REST callback against a regular | |
1367 | * expression for a URI. This function must be called during the | |
1368 | * initialization of the plugin, i.e. inside the | |
1369 | * OrthancPluginInitialize() public function. | |
1370 | * | |
1371 | * Contrarily to OrthancPluginRegisterRestCallback(), the callback | |
1372 | * will NOT be invoked in mutual exclusion. This can be useful for | |
1373 | * high-performance plugins that must handle concurrent requests | |
1374 | * (Orthanc uses a pool of threads, one thread being assigned to | |
1375 | * each incoming HTTP request). Of course, it is up to the plugin to | |
1376 | * implement the required locking mechanisms. | |
1377 | * | |
1378 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1379 | * @param pathRegularExpression Regular expression for the URI. May contain groups. | |
1380 | * @param callback The callback function to handle the REST call. | |
1381 | * @see OrthancPluginRegisterRestCallback() | |
1382 | * @ingroup Callbacks | |
1383 | **/ | |
1384 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallbackNoLock( | |
1385 | OrthancPluginContext* context, | |
1386 | const char* pathRegularExpression, | |
1387 | OrthancPluginRestCallback callback) | |
1388 | { | |
1389 | _OrthancPluginRestCallback params; | |
1390 | params.pathRegularExpression = pathRegularExpression; | |
1391 | params.callback = callback; | |
1392 | context->InvokeService(context, _OrthancPluginService_RegisterRestCallbackNoLock, ¶ms); | |
1393 | } | |
1394 | ||
1395 | ||
1396 | ||
1397 | typedef struct | |
1398 | { | |
1399 | OrthancPluginOnStoredInstanceCallback callback; | |
1400 | } _OrthancPluginOnStoredInstanceCallback; | |
1401 | ||
1402 | /** | |
1403 | * @brief Register a callback for received instances. | |
1404 | * | |
1405 | * This function registers a callback function that is called | |
1406 | * whenever a new DICOM instance is stored into the Orthanc core. | |
1407 | * | |
1408 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1409 | * @param callback The callback function. | |
1410 | * @ingroup Callbacks | |
1411 | **/ | |
1412 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnStoredInstanceCallback( | |
1413 | OrthancPluginContext* context, | |
1414 | OrthancPluginOnStoredInstanceCallback callback) | |
1415 | { | |
1416 | _OrthancPluginOnStoredInstanceCallback params; | |
1417 | params.callback = callback; | |
1418 | ||
1419 | context->InvokeService(context, _OrthancPluginService_RegisterOnStoredInstanceCallback, ¶ms); | |
1420 | } | |
1421 | ||
1422 | ||
1423 | ||
1424 | typedef struct | |
1425 | { | |
1426 | OrthancPluginRestOutput* output; | |
1427 | const char* answer; | |
1428 | uint32_t answerSize; | |
1429 | const char* mimeType; | |
1430 | } _OrthancPluginAnswerBuffer; | |
1431 | ||
1432 | /** | |
1433 | * @brief Answer to a REST request. | |
1434 | * | |
1435 | * This function answers to a REST request with the content of a memory buffer. | |
1436 | * | |
1437 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1438 | * @param output The HTTP connection to the client application. | |
1439 | * @param answer Pointer to the memory buffer containing the answer. | |
1440 | * @param answerSize Number of bytes of the answer. | |
1441 | * @param mimeType The MIME type of the answer. | |
1442 | * @ingroup REST | |
1443 | **/ | |
1444 | ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer( | |
1445 | OrthancPluginContext* context, | |
1446 | OrthancPluginRestOutput* output, | |
1447 | const char* answer, | |
1448 | uint32_t answerSize, | |
1449 | const char* mimeType) | |
1450 | { | |
1451 | _OrthancPluginAnswerBuffer params; | |
1452 | params.output = output; | |
1453 | params.answer = answer; | |
1454 | params.answerSize = answerSize; | |
1455 | params.mimeType = mimeType; | |
1456 | context->InvokeService(context, _OrthancPluginService_AnswerBuffer, ¶ms); | |
1457 | } | |
1458 | ||
1459 | ||
1460 | typedef struct | |
1461 | { | |
1462 | OrthancPluginRestOutput* output; | |
1463 | OrthancPluginPixelFormat format; | |
1464 | uint32_t width; | |
1465 | uint32_t height; | |
1466 | uint32_t pitch; | |
1467 | const void* buffer; | |
1468 | } _OrthancPluginCompressAndAnswerPngImage; | |
1469 | ||
1470 | typedef struct | |
1471 | { | |
1472 | OrthancPluginRestOutput* output; | |
1473 | OrthancPluginImageFormat imageFormat; | |
1474 | OrthancPluginPixelFormat pixelFormat; | |
1475 | uint32_t width; | |
1476 | uint32_t height; | |
1477 | uint32_t pitch; | |
1478 | const void* buffer; | |
1479 | uint8_t quality; | |
1480 | } _OrthancPluginCompressAndAnswerImage; | |
1481 | ||
1482 | ||
1483 | /** | |
1484 | * @brief Answer to a REST request with a PNG image. | |
1485 | * | |
1486 | * This function answers to a REST request with a PNG image. The | |
1487 | * parameters of this function describe a memory buffer that | |
1488 | * contains an uncompressed image. The image will be automatically compressed | |
1489 | * as a PNG image by the core system of Orthanc. | |
1490 | * | |
1491 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1492 | * @param output The HTTP connection to the client application. | |
1493 | * @param format The memory layout of the uncompressed image. | |
1494 | * @param width The width of the image. | |
1495 | * @param height The height of the image. | |
1496 | * @param pitch The pitch of the image (i.e. the number of bytes | |
1497 | * between 2 successive lines of the image in the memory buffer). | |
1498 | * @param buffer The memory buffer containing the uncompressed image. | |
1499 | * @ingroup REST | |
1500 | **/ | |
1501 | ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerPngImage( | |
1502 | OrthancPluginContext* context, | |
1503 | OrthancPluginRestOutput* output, | |
1504 | OrthancPluginPixelFormat format, | |
1505 | uint32_t width, | |
1506 | uint32_t height, | |
1507 | uint32_t pitch, | |
1508 | const void* buffer) | |
1509 | { | |
1510 | _OrthancPluginCompressAndAnswerImage params; | |
1511 | params.output = output; | |
1512 | params.imageFormat = OrthancPluginImageFormat_Png; | |
1513 | params.pixelFormat = format; | |
1514 | params.width = width; | |
1515 | params.height = height; | |
1516 | params.pitch = pitch; | |
1517 | params.buffer = buffer; | |
1518 | params.quality = 0; /* No quality for PNG */ | |
1519 | context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); | |
1520 | } | |
1521 | ||
1522 | ||
1523 | ||
1524 | typedef struct | |
1525 | { | |
1526 | OrthancPluginMemoryBuffer* target; | |
1527 | const char* instanceId; | |
1528 | } _OrthancPluginGetDicomForInstance; | |
1529 | ||
1530 | /** | |
1531 | * @brief Retrieve a DICOM instance using its Orthanc identifier. | |
1532 | * | |
1533 | * Retrieve a DICOM instance using its Orthanc identifier. The DICOM | |
1534 | * file is stored into a newly allocated memory buffer. | |
1535 | * | |
1536 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1537 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1538 | * @param instanceId The Orthanc identifier of the DICOM instance of interest. | |
1539 | * @return 0 if success, or the error code if failure. | |
1540 | * @ingroup Orthanc | |
1541 | **/ | |
1542 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetDicomForInstance( | |
1543 | OrthancPluginContext* context, | |
1544 | OrthancPluginMemoryBuffer* target, | |
1545 | const char* instanceId) | |
1546 | { | |
1547 | _OrthancPluginGetDicomForInstance params; | |
1548 | params.target = target; | |
1549 | params.instanceId = instanceId; | |
1550 | return context->InvokeService(context, _OrthancPluginService_GetDicomForInstance, ¶ms); | |
1551 | } | |
1552 | ||
1553 | ||
1554 | ||
1555 | typedef struct | |
1556 | { | |
1557 | OrthancPluginMemoryBuffer* target; | |
1558 | const char* uri; | |
1559 | } _OrthancPluginRestApiGet; | |
1560 | ||
1561 | /** | |
1562 | * @brief Make a GET call to the built-in Orthanc REST API. | |
1563 | * | |
1564 | * Make a GET call to the built-in Orthanc REST API. The result to | |
1565 | * the query is stored into a newly allocated memory buffer. | |
1566 | * | |
1567 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1568 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1569 | * @param uri The URI in the built-in Orthanc API. | |
1570 | * @return 0 if success, or the error code if failure. | |
1571 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1572 | * @see OrthancPluginRestApiGetAfterPlugins | |
1573 | * @ingroup Orthanc | |
1574 | **/ | |
1575 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet( | |
1576 | OrthancPluginContext* context, | |
1577 | OrthancPluginMemoryBuffer* target, | |
1578 | const char* uri) | |
1579 | { | |
1580 | _OrthancPluginRestApiGet params; | |
1581 | params.target = target; | |
1582 | params.uri = uri; | |
1583 | return context->InvokeService(context, _OrthancPluginService_RestApiGet, ¶ms); | |
1584 | } | |
1585 | ||
1586 | ||
1587 | ||
1588 | /** | |
1589 | * @brief Make a GET call to the REST API, as tainted by the plugins. | |
1590 | * | |
1591 | * Make a GET call to the Orthanc REST API, after all the plugins | |
1592 | * are applied. In other words, if some plugin overrides or adds the | |
1593 | * called URI to the built-in Orthanc REST API, this call will | |
1594 | * return the result provided by this plugin. The result to the | |
1595 | * query is stored into a newly allocated memory buffer. | |
1596 | * | |
1597 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1598 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1599 | * @param uri The URI in the built-in Orthanc API. | |
1600 | * @return 0 if success, or the error code if failure. | |
1601 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1602 | * @see OrthancPluginRestApiGet | |
1603 | * @ingroup Orthanc | |
1604 | **/ | |
1605 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGetAfterPlugins( | |
1606 | OrthancPluginContext* context, | |
1607 | OrthancPluginMemoryBuffer* target, | |
1608 | const char* uri) | |
1609 | { | |
1610 | _OrthancPluginRestApiGet params; | |
1611 | params.target = target; | |
1612 | params.uri = uri; | |
1613 | return context->InvokeService(context, _OrthancPluginService_RestApiGetAfterPlugins, ¶ms); | |
1614 | } | |
1615 | ||
1616 | ||
1617 | ||
1618 | typedef struct | |
1619 | { | |
1620 | OrthancPluginMemoryBuffer* target; | |
1621 | const char* uri; | |
1622 | const char* body; | |
1623 | uint32_t bodySize; | |
1624 | } _OrthancPluginRestApiPostPut; | |
1625 | ||
1626 | /** | |
1627 | * @brief Make a POST call to the built-in Orthanc REST API. | |
1628 | * | |
1629 | * Make a POST call to the built-in Orthanc REST API. The result to | |
1630 | * the query is stored into a newly allocated memory buffer. | |
1631 | * | |
1632 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1633 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1634 | * @param uri The URI in the built-in Orthanc API. | |
1635 | * @param body The body of the POST request. | |
1636 | * @param bodySize The size of the body. | |
1637 | * @return 0 if success, or the error code if failure. | |
1638 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1639 | * @see OrthancPluginRestApiPostAfterPlugins | |
1640 | * @ingroup Orthanc | |
1641 | **/ | |
1642 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPost( | |
1643 | OrthancPluginContext* context, | |
1644 | OrthancPluginMemoryBuffer* target, | |
1645 | const char* uri, | |
1646 | const char* body, | |
1647 | uint32_t bodySize) | |
1648 | { | |
1649 | _OrthancPluginRestApiPostPut params; | |
1650 | params.target = target; | |
1651 | params.uri = uri; | |
1652 | params.body = body; | |
1653 | params.bodySize = bodySize; | |
1654 | return context->InvokeService(context, _OrthancPluginService_RestApiPost, ¶ms); | |
1655 | } | |
1656 | ||
1657 | ||
1658 | /** | |
1659 | * @brief Make a POST call to the REST API, as tainted by the plugins. | |
1660 | * | |
1661 | * Make a POST call to the Orthanc REST API, after all the plugins | |
1662 | * are applied. In other words, if some plugin overrides or adds the | |
1663 | * called URI to the built-in Orthanc REST API, this call will | |
1664 | * return the result provided by this plugin. The result to the | |
1665 | * query is stored into a newly allocated memory buffer. | |
1666 | * | |
1667 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1668 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1669 | * @param uri The URI in the built-in Orthanc API. | |
1670 | * @param body The body of the POST request. | |
1671 | * @param bodySize The size of the body. | |
1672 | * @return 0 if success, or the error code if failure. | |
1673 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1674 | * @see OrthancPluginRestApiPost | |
1675 | * @ingroup Orthanc | |
1676 | **/ | |
1677 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPostAfterPlugins( | |
1678 | OrthancPluginContext* context, | |
1679 | OrthancPluginMemoryBuffer* target, | |
1680 | const char* uri, | |
1681 | const char* body, | |
1682 | uint32_t bodySize) | |
1683 | { | |
1684 | _OrthancPluginRestApiPostPut params; | |
1685 | params.target = target; | |
1686 | params.uri = uri; | |
1687 | params.body = body; | |
1688 | params.bodySize = bodySize; | |
1689 | return context->InvokeService(context, _OrthancPluginService_RestApiPostAfterPlugins, ¶ms); | |
1690 | } | |
1691 | ||
1692 | ||
1693 | ||
1694 | /** | |
1695 | * @brief Make a DELETE call to the built-in Orthanc REST API. | |
1696 | * | |
1697 | * Make a DELETE call to the built-in Orthanc REST API. | |
1698 | * | |
1699 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1700 | * @param uri The URI to delete in the built-in Orthanc API. | |
1701 | * @return 0 if success, or the error code if failure. | |
1702 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1703 | * @see OrthancPluginRestApiDeleteAfterPlugins | |
1704 | * @ingroup Orthanc | |
1705 | **/ | |
1706 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDelete( | |
1707 | OrthancPluginContext* context, | |
1708 | const char* uri) | |
1709 | { | |
1710 | return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri); | |
1711 | } | |
1712 | ||
1713 | ||
1714 | /** | |
1715 | * @brief Make a DELETE call to the REST API, as tainted by the plugins. | |
1716 | * | |
1717 | * Make a DELETE call to the Orthanc REST API, after all the plugins | |
1718 | * are applied. In other words, if some plugin overrides or adds the | |
1719 | * called URI to the built-in Orthanc REST API, this call will | |
1720 | * return the result provided by this plugin. | |
1721 | * | |
1722 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1723 | * @param uri The URI to delete in the built-in Orthanc API. | |
1724 | * @return 0 if success, or the error code if failure. | |
1725 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1726 | * @see OrthancPluginRestApiDelete | |
1727 | * @ingroup Orthanc | |
1728 | **/ | |
1729 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDeleteAfterPlugins( | |
1730 | OrthancPluginContext* context, | |
1731 | const char* uri) | |
1732 | { | |
1733 | return context->InvokeService(context, _OrthancPluginService_RestApiDeleteAfterPlugins, uri); | |
1734 | } | |
1735 | ||
1736 | ||
1737 | ||
1738 | /** | |
1739 | * @brief Make a PUT call to the built-in Orthanc REST API. | |
1740 | * | |
1741 | * Make a PUT call to the built-in Orthanc REST API. The result to | |
1742 | * the query is stored into a newly allocated memory buffer. | |
1743 | * | |
1744 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1745 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1746 | * @param uri The URI in the built-in Orthanc API. | |
1747 | * @param body The body of the PUT request. | |
1748 | * @param bodySize The size of the body. | |
1749 | * @return 0 if success, or the error code if failure. | |
1750 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1751 | * @see OrthancPluginRestApiPutAfterPlugins | |
1752 | * @ingroup Orthanc | |
1753 | **/ | |
1754 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPut( | |
1755 | OrthancPluginContext* context, | |
1756 | OrthancPluginMemoryBuffer* target, | |
1757 | const char* uri, | |
1758 | const char* body, | |
1759 | uint32_t bodySize) | |
1760 | { | |
1761 | _OrthancPluginRestApiPostPut params; | |
1762 | params.target = target; | |
1763 | params.uri = uri; | |
1764 | params.body = body; | |
1765 | params.bodySize = bodySize; | |
1766 | return context->InvokeService(context, _OrthancPluginService_RestApiPut, ¶ms); | |
1767 | } | |
1768 | ||
1769 | ||
1770 | ||
1771 | /** | |
1772 | * @brief Make a PUT call to the REST API, as tainted by the plugins. | |
1773 | * | |
1774 | * Make a PUT call to the Orthanc REST API, after all the plugins | |
1775 | * are applied. In other words, if some plugin overrides or adds the | |
1776 | * called URI to the built-in Orthanc REST API, this call will | |
1777 | * return the result provided by this plugin. The result to the | |
1778 | * query is stored into a newly allocated memory buffer. | |
1779 | * | |
1780 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1781 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1782 | * @param uri The URI in the built-in Orthanc API. | |
1783 | * @param body The body of the PUT request. | |
1784 | * @param bodySize The size of the body. | |
1785 | * @return 0 if success, or the error code if failure. | |
1786 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1787 | * @see OrthancPluginRestApiPut | |
1788 | * @ingroup Orthanc | |
1789 | **/ | |
1790 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPutAfterPlugins( | |
1791 | OrthancPluginContext* context, | |
1792 | OrthancPluginMemoryBuffer* target, | |
1793 | const char* uri, | |
1794 | const char* body, | |
1795 | uint32_t bodySize) | |
1796 | { | |
1797 | _OrthancPluginRestApiPostPut params; | |
1798 | params.target = target; | |
1799 | params.uri = uri; | |
1800 | params.body = body; | |
1801 | params.bodySize = bodySize; | |
1802 | return context->InvokeService(context, _OrthancPluginService_RestApiPutAfterPlugins, ¶ms); | |
1803 | } | |
1804 | ||
1805 | ||
1806 | ||
1807 | typedef struct | |
1808 | { | |
1809 | OrthancPluginRestOutput* output; | |
1810 | const char* argument; | |
1811 | } _OrthancPluginOutputPlusArgument; | |
1812 | ||
1813 | /** | |
1814 | * @brief Redirect a REST request. | |
1815 | * | |
1816 | * This function answers to a REST request by redirecting the user | |
1817 | * to another URI using HTTP status 301. | |
1818 | * | |
1819 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1820 | * @param output The HTTP connection to the client application. | |
1821 | * @param redirection Where to redirect. | |
1822 | * @ingroup REST | |
1823 | **/ | |
1824 | ORTHANC_PLUGIN_INLINE void OrthancPluginRedirect( | |
1825 | OrthancPluginContext* context, | |
1826 | OrthancPluginRestOutput* output, | |
1827 | const char* redirection) | |
1828 | { | |
1829 | _OrthancPluginOutputPlusArgument params; | |
1830 | params.output = output; | |
1831 | params.argument = redirection; | |
1832 | context->InvokeService(context, _OrthancPluginService_Redirect, ¶ms); | |
1833 | } | |
1834 | ||
1835 | ||
1836 | ||
1837 | typedef struct | |
1838 | { | |
1839 | char** result; | |
1840 | const char* argument; | |
1841 | } _OrthancPluginRetrieveDynamicString; | |
1842 | ||
1843 | /** | |
1844 | * @brief Look for a patient. | |
1845 | * | |
1846 | * Look for a patient stored in Orthanc, using its Patient ID tag (0x0010, 0x0020). | |
1847 | * This function uses the database index to run as fast as possible (it does not loop | |
1848 | * over all the stored patients). | |
1849 | * | |
1850 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1851 | * @param patientID The Patient ID of interest. | |
1852 | * @return The NULL value if the patient is non-existent, or a string containing the | |
1853 | * Orthanc ID of the patient. This string must be freed by OrthancPluginFreeString(). | |
1854 | * @ingroup Orthanc | |
1855 | **/ | |
1856 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupPatient( | |
1857 | OrthancPluginContext* context, | |
1858 | const char* patientID) | |
1859 | { | |
1860 | char* result; | |
1861 | ||
1862 | _OrthancPluginRetrieveDynamicString params; | |
1863 | params.result = &result; | |
1864 | params.argument = patientID; | |
1865 | ||
1866 | if (context->InvokeService(context, _OrthancPluginService_LookupPatient, ¶ms) != OrthancPluginErrorCode_Success) | |
1867 | { | |
1868 | /* Error */ | |
1869 | return NULL; | |
1870 | } | |
1871 | else | |
1872 | { | |
1873 | return result; | |
1874 | } | |
1875 | } | |
1876 | ||
1877 | ||
1878 | /** | |
1879 | * @brief Look for a study. | |
1880 | * | |
1881 | * Look for a study stored in Orthanc, using its Study Instance UID tag (0x0020, 0x000d). | |
1882 | * This function uses the database index to run as fast as possible (it does not loop | |
1883 | * over all the stored studies). | |
1884 | * | |
1885 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1886 | * @param studyUID The Study Instance UID of interest. | |
1887 | * @return The NULL value if the study is non-existent, or a string containing the | |
1888 | * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). | |
1889 | * @ingroup Orthanc | |
1890 | **/ | |
1891 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudy( | |
1892 | OrthancPluginContext* context, | |
1893 | const char* studyUID) | |
1894 | { | |
1895 | char* result; | |
1896 | ||
1897 | _OrthancPluginRetrieveDynamicString params; | |
1898 | params.result = &result; | |
1899 | params.argument = studyUID; | |
1900 | ||
1901 | if (context->InvokeService(context, _OrthancPluginService_LookupStudy, ¶ms) != OrthancPluginErrorCode_Success) | |
1902 | { | |
1903 | /* Error */ | |
1904 | return NULL; | |
1905 | } | |
1906 | else | |
1907 | { | |
1908 | return result; | |
1909 | } | |
1910 | } | |
1911 | ||
1912 | ||
1913 | /** | |
1914 | * @brief Look for a study, using the accession number. | |
1915 | * | |
1916 | * Look for a study stored in Orthanc, using its Accession Number tag (0x0008, 0x0050). | |
1917 | * This function uses the database index to run as fast as possible (it does not loop | |
1918 | * over all the stored studies). | |
1919 | * | |
1920 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1921 | * @param accessionNumber The Accession Number of interest. | |
1922 | * @return The NULL value if the study is non-existent, or a string containing the | |
1923 | * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). | |
1924 | * @ingroup Orthanc | |
1925 | **/ | |
1926 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudyWithAccessionNumber( | |
1927 | OrthancPluginContext* context, | |
1928 | const char* accessionNumber) | |
1929 | { | |
1930 | char* result; | |
1931 | ||
1932 | _OrthancPluginRetrieveDynamicString params; | |
1933 | params.result = &result; | |
1934 | params.argument = accessionNumber; | |
1935 | ||
1936 | if (context->InvokeService(context, _OrthancPluginService_LookupStudyWithAccessionNumber, ¶ms) != OrthancPluginErrorCode_Success) | |
1937 | { | |
1938 | /* Error */ | |
1939 | return NULL; | |
1940 | } | |
1941 | else | |
1942 | { | |
1943 | return result; | |
1944 | } | |
1945 | } | |
1946 | ||
1947 | ||
1948 | /** | |
1949 | * @brief Look for a series. | |
1950 | * | |
1951 | * Look for a series stored in Orthanc, using its Series Instance UID tag (0x0020, 0x000e). | |
1952 | * This function uses the database index to run as fast as possible (it does not loop | |
1953 | * over all the stored series). | |
1954 | * | |
1955 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1956 | * @param seriesUID The Series Instance UID of interest. | |
1957 | * @return The NULL value if the series is non-existent, or a string containing the | |
1958 | * Orthanc ID of the series. This string must be freed by OrthancPluginFreeString(). | |
1959 | * @ingroup Orthanc | |
1960 | **/ | |
1961 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupSeries( | |
1962 | OrthancPluginContext* context, | |
1963 | const char* seriesUID) | |
1964 | { | |
1965 | char* result; | |
1966 | ||
1967 | _OrthancPluginRetrieveDynamicString params; | |
1968 | params.result = &result; | |
1969 | params.argument = seriesUID; | |
1970 | ||
1971 | if (context->InvokeService(context, _OrthancPluginService_LookupSeries, ¶ms) != OrthancPluginErrorCode_Success) | |
1972 | { | |
1973 | /* Error */ | |
1974 | return NULL; | |
1975 | } | |
1976 | else | |
1977 | { | |
1978 | return result; | |
1979 | } | |
1980 | } | |
1981 | ||
1982 | ||
1983 | /** | |
1984 | * @brief Look for an instance. | |
1985 | * | |
1986 | * Look for an instance stored in Orthanc, using its SOP Instance UID tag (0x0008, 0x0018). | |
1987 | * This function uses the database index to run as fast as possible (it does not loop | |
1988 | * over all the stored instances). | |
1989 | * | |
1990 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1991 | * @param sopInstanceUID The SOP Instance UID of interest. | |
1992 | * @return The NULL value if the instance is non-existent, or a string containing the | |
1993 | * Orthanc ID of the instance. This string must be freed by OrthancPluginFreeString(). | |
1994 | * @ingroup Orthanc | |
1995 | **/ | |
1996 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupInstance( | |
1997 | OrthancPluginContext* context, | |
1998 | const char* sopInstanceUID) | |
1999 | { | |
2000 | char* result; | |
2001 | ||
2002 | _OrthancPluginRetrieveDynamicString params; | |
2003 | params.result = &result; | |
2004 | params.argument = sopInstanceUID; | |
2005 | ||
2006 | if (context->InvokeService(context, _OrthancPluginService_LookupInstance, ¶ms) != OrthancPluginErrorCode_Success) | |
2007 | { | |
2008 | /* Error */ | |
2009 | return NULL; | |
2010 | } | |
2011 | else | |
2012 | { | |
2013 | return result; | |
2014 | } | |
2015 | } | |
2016 | ||
2017 | ||
2018 | ||
2019 | typedef struct | |
2020 | { | |
2021 | OrthancPluginRestOutput* output; | |
2022 | uint16_t status; | |
2023 | } _OrthancPluginSendHttpStatusCode; | |
2024 | ||
2025 | /** | |
2026 | * @brief Send a HTTP status code. | |
2027 | * | |
2028 | * This function answers to a REST request by sending a HTTP status | |
2029 | * code (such as "400 - Bad Request"). Note that: | |
2030 | * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). | |
2031 | * - Redirections (status 301) must use ::OrthancPluginRedirect(). | |
2032 | * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). | |
2033 | * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). | |
2034 | * | |
2035 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2036 | * @param output The HTTP connection to the client application. | |
2037 | * @param status The HTTP status code to be sent. | |
2038 | * @ingroup REST | |
2039 | * @see OrthancPluginSendHttpStatus() | |
2040 | **/ | |
2041 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatusCode( | |
2042 | OrthancPluginContext* context, | |
2043 | OrthancPluginRestOutput* output, | |
2044 | uint16_t status) | |
2045 | { | |
2046 | _OrthancPluginSendHttpStatusCode params; | |
2047 | params.output = output; | |
2048 | params.status = status; | |
2049 | context->InvokeService(context, _OrthancPluginService_SendHttpStatusCode, ¶ms); | |
2050 | } | |
2051 | ||
2052 | ||
2053 | /** | |
2054 | * @brief Signal that a REST request is not authorized. | |
2055 | * | |
2056 | * This function answers to a REST request by signaling that it is | |
2057 | * not authorized. | |
2058 | * | |
2059 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2060 | * @param output The HTTP connection to the client application. | |
2061 | * @param realm The realm for the authorization process. | |
2062 | * @ingroup REST | |
2063 | **/ | |
2064 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendUnauthorized( | |
2065 | OrthancPluginContext* context, | |
2066 | OrthancPluginRestOutput* output, | |
2067 | const char* realm) | |
2068 | { | |
2069 | _OrthancPluginOutputPlusArgument params; | |
2070 | params.output = output; | |
2071 | params.argument = realm; | |
2072 | context->InvokeService(context, _OrthancPluginService_SendUnauthorized, ¶ms); | |
2073 | } | |
2074 | ||
2075 | ||
2076 | /** | |
2077 | * @brief Signal that this URI does not support this HTTP method. | |
2078 | * | |
2079 | * This function answers to a REST request by signaling that the | |
2080 | * queried URI does not support this method. | |
2081 | * | |
2082 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2083 | * @param output The HTTP connection to the client application. | |
2084 | * @param allowedMethods The allowed methods for this URI (e.g. "GET,POST" after a PUT or a POST request). | |
2085 | * @ingroup REST | |
2086 | **/ | |
2087 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendMethodNotAllowed( | |
2088 | OrthancPluginContext* context, | |
2089 | OrthancPluginRestOutput* output, | |
2090 | const char* allowedMethods) | |
2091 | { | |
2092 | _OrthancPluginOutputPlusArgument params; | |
2093 | params.output = output; | |
2094 | params.argument = allowedMethods; | |
2095 | context->InvokeService(context, _OrthancPluginService_SendMethodNotAllowed, ¶ms); | |
2096 | } | |
2097 | ||
2098 | ||
2099 | typedef struct | |
2100 | { | |
2101 | OrthancPluginRestOutput* output; | |
2102 | const char* key; | |
2103 | const char* value; | |
2104 | } _OrthancPluginSetHttpHeader; | |
2105 | ||
2106 | /** | |
2107 | * @brief Set a cookie. | |
2108 | * | |
2109 | * This function sets a cookie in the HTTP client. | |
2110 | * | |
2111 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2112 | * @param output The HTTP connection to the client application. | |
2113 | * @param cookie The cookie to be set. | |
2114 | * @param value The value of the cookie. | |
2115 | * @ingroup REST | |
2116 | **/ | |
2117 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetCookie( | |
2118 | OrthancPluginContext* context, | |
2119 | OrthancPluginRestOutput* output, | |
2120 | const char* cookie, | |
2121 | const char* value) | |
2122 | { | |
2123 | _OrthancPluginSetHttpHeader params; | |
2124 | params.output = output; | |
2125 | params.key = cookie; | |
2126 | params.value = value; | |
2127 | context->InvokeService(context, _OrthancPluginService_SetCookie, ¶ms); | |
2128 | } | |
2129 | ||
2130 | ||
2131 | /** | |
2132 | * @brief Set some HTTP header. | |
2133 | * | |
2134 | * This function sets a HTTP header in the HTTP answer. | |
2135 | * | |
2136 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2137 | * @param output The HTTP connection to the client application. | |
2138 | * @param key The HTTP header to be set. | |
2139 | * @param value The value of the HTTP header. | |
2140 | * @ingroup REST | |
2141 | **/ | |
2142 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetHttpHeader( | |
2143 | OrthancPluginContext* context, | |
2144 | OrthancPluginRestOutput* output, | |
2145 | const char* key, | |
2146 | const char* value) | |
2147 | { | |
2148 | _OrthancPluginSetHttpHeader params; | |
2149 | params.output = output; | |
2150 | params.key = key; | |
2151 | params.value = value; | |
2152 | context->InvokeService(context, _OrthancPluginService_SetHttpHeader, ¶ms); | |
2153 | } | |
2154 | ||
2155 | ||
2156 | typedef struct | |
2157 | { | |
2158 | char** resultStringToFree; | |
2159 | const char** resultString; | |
2160 | int64_t* resultInt64; | |
2161 | const char* key; | |
2162 | OrthancPluginDicomInstance* instance; | |
2163 | OrthancPluginInstanceOrigin* resultOrigin; /* New in Orthanc 0.9.5 SDK */ | |
2164 | } _OrthancPluginAccessDicomInstance; | |
2165 | ||
2166 | ||
2167 | /** | |
2168 | * @brief Get the AET of a DICOM instance. | |
2169 | * | |
2170 | * This function returns the Application Entity Title (AET) of the | |
2171 | * DICOM modality from which a DICOM instance originates. | |
2172 | * | |
2173 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2174 | * @param instance The instance of interest. | |
2175 | * @return The AET if success, NULL if error. | |
2176 | * @ingroup Callbacks | |
2177 | **/ | |
2178 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceRemoteAet( | |
2179 | OrthancPluginContext* context, | |
2180 | OrthancPluginDicomInstance* instance) | |
2181 | { | |
2182 | const char* result; | |
2183 | ||
2184 | _OrthancPluginAccessDicomInstance params; | |
2185 | memset(¶ms, 0, sizeof(params)); | |
2186 | params.resultString = &result; | |
2187 | params.instance = instance; | |
2188 | ||
2189 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, ¶ms) != OrthancPluginErrorCode_Success) | |
2190 | { | |
2191 | /* Error */ | |
2192 | return NULL; | |
2193 | } | |
2194 | else | |
2195 | { | |
2196 | return result; | |
2197 | } | |
2198 | } | |
2199 | ||
2200 | ||
2201 | /** | |
2202 | * @brief Get the size of a DICOM file. | |
2203 | * | |
2204 | * This function returns the number of bytes of the given DICOM instance. | |
2205 | * | |
2206 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2207 | * @param instance The instance of interest. | |
2208 | * @return The size of the file, -1 in case of error. | |
2209 | * @ingroup Callbacks | |
2210 | **/ | |
2211 | ORTHANC_PLUGIN_INLINE int64_t OrthancPluginGetInstanceSize( | |
2212 | OrthancPluginContext* context, | |
2213 | OrthancPluginDicomInstance* instance) | |
2214 | { | |
2215 | int64_t size; | |
2216 | ||
2217 | _OrthancPluginAccessDicomInstance params; | |
2218 | memset(¶ms, 0, sizeof(params)); | |
2219 | params.resultInt64 = &size; | |
2220 | params.instance = instance; | |
2221 | ||
2222 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, ¶ms) != OrthancPluginErrorCode_Success) | |
2223 | { | |
2224 | /* Error */ | |
2225 | return -1; | |
2226 | } | |
2227 | else | |
2228 | { | |
2229 | return size; | |
2230 | } | |
2231 | } | |
2232 | ||
2233 | ||
2234 | /** | |
2235 | * @brief Get the data of a DICOM file. | |
2236 | * | |
2237 | * This function returns a pointer to the content of the given DICOM instance. | |
2238 | * | |
2239 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2240 | * @param instance The instance of interest. | |
2241 | * @return The pointer to the DICOM data, NULL in case of error. | |
2242 | * @ingroup Callbacks | |
2243 | **/ | |
2244 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceData( | |
2245 | OrthancPluginContext* context, | |
2246 | OrthancPluginDicomInstance* instance) | |
2247 | { | |
2248 | const char* result; | |
2249 | ||
2250 | _OrthancPluginAccessDicomInstance params; | |
2251 | memset(¶ms, 0, sizeof(params)); | |
2252 | params.resultString = &result; | |
2253 | params.instance = instance; | |
2254 | ||
2255 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, ¶ms) != OrthancPluginErrorCode_Success) | |
2256 | { | |
2257 | /* Error */ | |
2258 | return NULL; | |
2259 | } | |
2260 | else | |
2261 | { | |
2262 | return result; | |
2263 | } | |
2264 | } | |
2265 | ||
2266 | ||
2267 | /** | |
2268 | * @brief Get the DICOM tag hierarchy as a JSON file. | |
2269 | * | |
2270 | * This function returns a pointer to a newly created string | |
2271 | * containing a JSON file. This JSON file encodes the tag hierarchy | |
2272 | * of the given DICOM instance. | |
2273 | * | |
2274 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2275 | * @param instance The instance of interest. | |
2276 | * @return The NULL value in case of error, or a string containing the JSON file. | |
2277 | * This string must be freed by OrthancPluginFreeString(). | |
2278 | * @ingroup Callbacks | |
2279 | **/ | |
2280 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceJson( | |
2281 | OrthancPluginContext* context, | |
2282 | OrthancPluginDicomInstance* instance) | |
2283 | { | |
2284 | char* result; | |
2285 | ||
2286 | _OrthancPluginAccessDicomInstance params; | |
2287 | memset(¶ms, 0, sizeof(params)); | |
2288 | params.resultStringToFree = &result; | |
2289 | params.instance = instance; | |
2290 | ||
2291 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, ¶ms) != OrthancPluginErrorCode_Success) | |
2292 | { | |
2293 | /* Error */ | |
2294 | return NULL; | |
2295 | } | |
2296 | else | |
2297 | { | |
2298 | return result; | |
2299 | } | |
2300 | } | |
2301 | ||
2302 | ||
2303 | /** | |
2304 | * @brief Get the DICOM tag hierarchy as a JSON file (with simplification). | |
2305 | * | |
2306 | * This function returns a pointer to a newly created string | |
2307 | * containing a JSON file. This JSON file encodes the tag hierarchy | |
2308 | * of the given DICOM instance. In contrast with | |
2309 | * ::OrthancPluginGetInstanceJson(), the returned JSON file is in | |
2310 | * its simplified version. | |
2311 | * | |
2312 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2313 | * @param instance The instance of interest. | |
2314 | * @return The NULL value in case of error, or a string containing the JSON file. | |
2315 | * This string must be freed by OrthancPluginFreeString(). | |
2316 | * @ingroup Callbacks | |
2317 | **/ | |
2318 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceSimplifiedJson( | |
2319 | OrthancPluginContext* context, | |
2320 | OrthancPluginDicomInstance* instance) | |
2321 | { | |
2322 | char* result; | |
2323 | ||
2324 | _OrthancPluginAccessDicomInstance params; | |
2325 | memset(¶ms, 0, sizeof(params)); | |
2326 | params.resultStringToFree = &result; | |
2327 | params.instance = instance; | |
2328 | ||
2329 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, ¶ms) != OrthancPluginErrorCode_Success) | |
2330 | { | |
2331 | /* Error */ | |
2332 | return NULL; | |
2333 | } | |
2334 | else | |
2335 | { | |
2336 | return result; | |
2337 | } | |
2338 | } | |
2339 | ||
2340 | ||
2341 | /** | |
2342 | * @brief Check whether a DICOM instance is associated with some metadata. | |
2343 | * | |
2344 | * This function checks whether the DICOM instance of interest is | |
2345 | * associated with some metadata. As of Orthanc 0.8.1, in the | |
2346 | * callbacks registered by | |
2347 | * ::OrthancPluginRegisterOnStoredInstanceCallback(), the only | |
2348 | * possibly available metadata are "ReceptionDate", "RemoteAET" and | |
2349 | * "IndexInSeries". | |
2350 | * | |
2351 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2352 | * @param instance The instance of interest. | |
2353 | * @param metadata The metadata of interest. | |
2354 | * @return 1 if the metadata is present, 0 if it is absent, -1 in case of error. | |
2355 | * @ingroup Callbacks | |
2356 | **/ | |
2357 | ORTHANC_PLUGIN_INLINE int OrthancPluginHasInstanceMetadata( | |
2358 | OrthancPluginContext* context, | |
2359 | OrthancPluginDicomInstance* instance, | |
2360 | const char* metadata) | |
2361 | { | |
2362 | int64_t result; | |
2363 | ||
2364 | _OrthancPluginAccessDicomInstance params; | |
2365 | memset(¶ms, 0, sizeof(params)); | |
2366 | params.resultInt64 = &result; | |
2367 | params.instance = instance; | |
2368 | params.key = metadata; | |
2369 | ||
2370 | if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) | |
2371 | { | |
2372 | /* Error */ | |
2373 | return -1; | |
2374 | } | |
2375 | else | |
2376 | { | |
2377 | return (result != 0); | |
2378 | } | |
2379 | } | |
2380 | ||
2381 | ||
2382 | /** | |
2383 | * @brief Get the value of some metadata associated with a given DICOM instance. | |
2384 | * | |
2385 | * This functions returns the value of some metadata that is associated with the DICOM instance of interest. | |
2386 | * Before calling this function, the existence of the metadata must have been checked with | |
2387 | * ::OrthancPluginHasInstanceMetadata(). | |
2388 | * | |
2389 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2390 | * @param instance The instance of interest. | |
2391 | * @param metadata The metadata of interest. | |
2392 | * @return The metadata value if success, NULL if error. | |
2393 | * @ingroup Callbacks | |
2394 | **/ | |
2395 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceMetadata( | |
2396 | OrthancPluginContext* context, | |
2397 | OrthancPluginDicomInstance* instance, | |
2398 | const char* metadata) | |
2399 | { | |
2400 | const char* result; | |
2401 | ||
2402 | _OrthancPluginAccessDicomInstance params; | |
2403 | memset(¶ms, 0, sizeof(params)); | |
2404 | params.resultString = &result; | |
2405 | params.instance = instance; | |
2406 | params.key = metadata; | |
2407 | ||
2408 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) | |
2409 | { | |
2410 | /* Error */ | |
2411 | return NULL; | |
2412 | } | |
2413 | else | |
2414 | { | |
2415 | return result; | |
2416 | } | |
2417 | } | |
2418 | ||
2419 | ||
2420 | ||
2421 | typedef struct | |
2422 | { | |
2423 | OrthancPluginStorageCreate create; | |
2424 | OrthancPluginStorageRead read; | |
2425 | OrthancPluginStorageRemove remove; | |
2426 | OrthancPluginFree free; | |
2427 | } _OrthancPluginRegisterStorageArea; | |
2428 | ||
2429 | /** | |
2430 | * @brief Register a custom storage area. | |
2431 | * | |
2432 | * This function registers a custom storage area, to replace the | |
2433 | * built-in way Orthanc stores its files on the filesystem. This | |
2434 | * function must be called during the initialization of the plugin, | |
2435 | * i.e. inside the OrthancPluginInitialize() public function. | |
2436 | * | |
2437 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2438 | * @param create The callback function to store a file on the custom storage area. | |
2439 | * @param read The callback function to read a file from the custom storage area. | |
2440 | * @param remove The callback function to remove a file from the custom storage area. | |
2441 | * @ingroup Callbacks | |
2442 | **/ | |
2443 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterStorageArea( | |
2444 | OrthancPluginContext* context, | |
2445 | OrthancPluginStorageCreate create, | |
2446 | OrthancPluginStorageRead read, | |
2447 | OrthancPluginStorageRemove remove) | |
2448 | { | |
2449 | _OrthancPluginRegisterStorageArea params; | |
2450 | params.create = create; | |
2451 | params.read = read; | |
2452 | params.remove = remove; | |
2453 | ||
2454 | #ifdef __cplusplus | |
2455 | params.free = ::free; | |
2456 | #else | |
2457 | params.free = free; | |
2458 | #endif | |
2459 | ||
2460 | context->InvokeService(context, _OrthancPluginService_RegisterStorageArea, ¶ms); | |
2461 | } | |
2462 | ||
2463 | ||
2464 | ||
2465 | /** | |
2466 | * @brief Return the path to the Orthanc executable. | |
2467 | * | |
2468 | * This function returns the path to the Orthanc executable. | |
2469 | * | |
2470 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2471 | * @return NULL in the case of an error, or a newly allocated string | |
2472 | * containing the path. This string must be freed by | |
2473 | * OrthancPluginFreeString(). | |
2474 | **/ | |
2475 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancPath(OrthancPluginContext* context) | |
2476 | { | |
2477 | char* result; | |
2478 | ||
2479 | _OrthancPluginRetrieveDynamicString params; | |
2480 | params.result = &result; | |
2481 | params.argument = NULL; | |
2482 | ||
2483 | if (context->InvokeService(context, _OrthancPluginService_GetOrthancPath, ¶ms) != OrthancPluginErrorCode_Success) | |
2484 | { | |
2485 | /* Error */ | |
2486 | return NULL; | |
2487 | } | |
2488 | else | |
2489 | { | |
2490 | return result; | |
2491 | } | |
2492 | } | |
2493 | ||
2494 | ||
2495 | /** | |
2496 | * @brief Return the directory containing the Orthanc. | |
2497 | * | |
2498 | * This function returns the path to the directory containing the Orthanc executable. | |
2499 | * | |
2500 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2501 | * @return NULL in the case of an error, or a newly allocated string | |
2502 | * containing the path. This string must be freed by | |
2503 | * OrthancPluginFreeString(). | |
2504 | **/ | |
2505 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancDirectory(OrthancPluginContext* context) | |
2506 | { | |
2507 | char* result; | |
2508 | ||
2509 | _OrthancPluginRetrieveDynamicString params; | |
2510 | params.result = &result; | |
2511 | params.argument = NULL; | |
2512 | ||
2513 | if (context->InvokeService(context, _OrthancPluginService_GetOrthancDirectory, ¶ms) != OrthancPluginErrorCode_Success) | |
2514 | { | |
2515 | /* Error */ | |
2516 | return NULL; | |
2517 | } | |
2518 | else | |
2519 | { | |
2520 | return result; | |
2521 | } | |
2522 | } | |
2523 | ||
2524 | ||
2525 | /** | |
2526 | * @brief Return the path to the configuration file(s). | |
2527 | * | |
2528 | * This function returns the path to the configuration file(s) that | |
2529 | * was specified when starting Orthanc. Since version 0.9.1, this | |
2530 | * path can refer to a folder that stores a set of configuration | |
2531 | * files. This function is deprecated in favor of | |
2532 | * OrthancPluginGetConfiguration(). | |
2533 | * | |
2534 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2535 | * @return NULL in the case of an error, or a newly allocated string | |
2536 | * containing the path. This string must be freed by | |
2537 | * OrthancPluginFreeString(). | |
2538 | * @see OrthancPluginGetConfiguration() | |
2539 | **/ | |
2540 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfigurationPath(OrthancPluginContext* context) | |
2541 | { | |
2542 | char* result; | |
2543 | ||
2544 | _OrthancPluginRetrieveDynamicString params; | |
2545 | params.result = &result; | |
2546 | params.argument = NULL; | |
2547 | ||
2548 | if (context->InvokeService(context, _OrthancPluginService_GetConfigurationPath, ¶ms) != OrthancPluginErrorCode_Success) | |
2549 | { | |
2550 | /* Error */ | |
2551 | return NULL; | |
2552 | } | |
2553 | else | |
2554 | { | |
2555 | return result; | |
2556 | } | |
2557 | } | |
2558 | ||
2559 | ||
2560 | ||
2561 | typedef struct | |
2562 | { | |
2563 | OrthancPluginOnChangeCallback callback; | |
2564 | } _OrthancPluginOnChangeCallback; | |
2565 | ||
2566 | /** | |
2567 | * @brief Register a callback to monitor changes. | |
2568 | * | |
2569 | * This function registers a callback function that is called | |
2570 | * whenever a change happens to some DICOM resource. | |
2571 | * | |
2572 | * @warning If your change callback has to call the REST API of | |
2573 | * Orthanc, you should make these calls in a separate thread (with | |
2574 | * the events passing through a message queue). Otherwise, this | |
2575 | * could result in deadlocks in the presence of other plugins or Lua | |
2576 | * scripts. | |
2577 | * | |
2578 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2579 | * @param callback The callback function. | |
2580 | * @ingroup Callbacks | |
2581 | **/ | |
2582 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback( | |
2583 | OrthancPluginContext* context, | |
2584 | OrthancPluginOnChangeCallback callback) | |
2585 | { | |
2586 | _OrthancPluginOnChangeCallback params; | |
2587 | params.callback = callback; | |
2588 | ||
2589 | context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, ¶ms); | |
2590 | } | |
2591 | ||
2592 | ||
2593 | ||
2594 | typedef struct | |
2595 | { | |
2596 | const char* plugin; | |
2597 | _OrthancPluginProperty property; | |
2598 | const char* value; | |
2599 | } _OrthancPluginSetPluginProperty; | |
2600 | ||
2601 | ||
2602 | /** | |
2603 | * @brief Set the URI where the plugin provides its Web interface. | |
2604 | * | |
2605 | * For plugins that come with a Web interface, this function | |
2606 | * declares the entry path where to find this interface. This | |
2607 | * information is notably used in the "Plugins" page of Orthanc | |
2608 | * Explorer. | |
2609 | * | |
2610 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2611 | * @param uri The root URI for this plugin. | |
2612 | **/ | |
2613 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetRootUri( | |
2614 | OrthancPluginContext* context, | |
2615 | const char* uri) | |
2616 | { | |
2617 | _OrthancPluginSetPluginProperty params; | |
2618 | params.plugin = OrthancPluginGetName(); | |
2619 | params.property = _OrthancPluginProperty_RootUri; | |
2620 | params.value = uri; | |
2621 | ||
2622 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2623 | } | |
2624 | ||
2625 | ||
2626 | /** | |
2627 | * @brief Set a description for this plugin. | |
2628 | * | |
2629 | * Set a description for this plugin. It is displayed in the | |
2630 | * "Plugins" page of Orthanc Explorer. | |
2631 | * | |
2632 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2633 | * @param description The description. | |
2634 | **/ | |
2635 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetDescription( | |
2636 | OrthancPluginContext* context, | |
2637 | const char* description) | |
2638 | { | |
2639 | _OrthancPluginSetPluginProperty params; | |
2640 | params.plugin = OrthancPluginGetName(); | |
2641 | params.property = _OrthancPluginProperty_Description; | |
2642 | params.value = description; | |
2643 | ||
2644 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2645 | } | |
2646 | ||
2647 | ||
2648 | /** | |
2649 | * @brief Extend the JavaScript code of Orthanc Explorer. | |
2650 | * | |
2651 | * Add JavaScript code to customize the default behavior of Orthanc | |
2652 | * Explorer. This can for instance be used to add new buttons. | |
2653 | * | |
2654 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2655 | * @param javascript The custom JavaScript code. | |
2656 | **/ | |
2657 | ORTHANC_PLUGIN_INLINE void OrthancPluginExtendOrthancExplorer( | |
2658 | OrthancPluginContext* context, | |
2659 | const char* javascript) | |
2660 | { | |
2661 | _OrthancPluginSetPluginProperty params; | |
2662 | params.plugin = OrthancPluginGetName(); | |
2663 | params.property = _OrthancPluginProperty_OrthancExplorer; | |
2664 | params.value = javascript; | |
2665 | ||
2666 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2667 | } | |
2668 | ||
2669 | ||
2670 | typedef struct | |
2671 | { | |
2672 | char** result; | |
2673 | int32_t property; | |
2674 | const char* value; | |
2675 | } _OrthancPluginGlobalProperty; | |
2676 | ||
2677 | ||
2678 | /** | |
2679 | * @brief Get the value of a global property. | |
2680 | * | |
2681 | * Get the value of a global property that is stored in the Orthanc database. Global | |
2682 | * properties whose index is below 1024 are reserved by Orthanc. | |
2683 | * | |
2684 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2685 | * @param property The global property of interest. | |
2686 | * @param defaultValue The value to return, if the global property is unset. | |
2687 | * @return The value of the global property, or NULL in the case of an error. This | |
2688 | * string must be freed by OrthancPluginFreeString(). | |
2689 | * @ingroup Orthanc | |
2690 | **/ | |
2691 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetGlobalProperty( | |
2692 | OrthancPluginContext* context, | |
2693 | int32_t property, | |
2694 | const char* defaultValue) | |
2695 | { | |
2696 | char* result; | |
2697 | ||
2698 | _OrthancPluginGlobalProperty params; | |
2699 | params.result = &result; | |
2700 | params.property = property; | |
2701 | params.value = defaultValue; | |
2702 | ||
2703 | if (context->InvokeService(context, _OrthancPluginService_GetGlobalProperty, ¶ms) != OrthancPluginErrorCode_Success) | |
2704 | { | |
2705 | /* Error */ | |
2706 | return NULL; | |
2707 | } | |
2708 | else | |
2709 | { | |
2710 | return result; | |
2711 | } | |
2712 | } | |
2713 | ||
2714 | ||
2715 | /** | |
2716 | * @brief Set the value of a global property. | |
2717 | * | |
2718 | * Set the value of a global property into the Orthanc | |
2719 | * database. Setting a global property can be used by plugins to | |
2720 | * save their internal parameters. Plugins are only allowed to set | |
2721 | * properties whose index are above or equal to 1024 (properties | |
2722 | * below 1024 are read-only and reserved by Orthanc). | |
2723 | * | |
2724 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2725 | * @param property The global property of interest. | |
2726 | * @param value The value to be set in the global property. | |
2727 | * @return 0 if success, or the error code if failure. | |
2728 | * @ingroup Orthanc | |
2729 | **/ | |
2730 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSetGlobalProperty( | |
2731 | OrthancPluginContext* context, | |
2732 | int32_t property, | |
2733 | const char* value) | |
2734 | { | |
2735 | _OrthancPluginGlobalProperty params; | |
2736 | params.result = NULL; | |
2737 | params.property = property; | |
2738 | params.value = value; | |
2739 | ||
2740 | return context->InvokeService(context, _OrthancPluginService_SetGlobalProperty, ¶ms); | |
2741 | } | |
2742 | ||
2743 | ||
2744 | ||
2745 | typedef struct | |
2746 | { | |
2747 | int32_t *resultInt32; | |
2748 | uint32_t *resultUint32; | |
2749 | int64_t *resultInt64; | |
2750 | uint64_t *resultUint64; | |
2751 | } _OrthancPluginReturnSingleValue; | |
2752 | ||
2753 | /** | |
2754 | * @brief Get the number of command-line arguments. | |
2755 | * | |
2756 | * Retrieve the number of command-line arguments that were used to launch Orthanc. | |
2757 | * | |
2758 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2759 | * @return The number of arguments. | |
2760 | **/ | |
2761 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetCommandLineArgumentsCount( | |
2762 | OrthancPluginContext* context) | |
2763 | { | |
2764 | uint32_t count = 0; | |
2765 | ||
2766 | _OrthancPluginReturnSingleValue params; | |
2767 | memset(¶ms, 0, sizeof(params)); | |
2768 | params.resultUint32 = &count; | |
2769 | ||
2770 | if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, ¶ms) != OrthancPluginErrorCode_Success) | |
2771 | { | |
2772 | /* Error */ | |
2773 | return 0; | |
2774 | } | |
2775 | else | |
2776 | { | |
2777 | return count; | |
2778 | } | |
2779 | } | |
2780 | ||
2781 | ||
2782 | ||
2783 | /** | |
2784 | * @brief Get the value of a command-line argument. | |
2785 | * | |
2786 | * Get the value of one of the command-line arguments that were used | |
2787 | * to launch Orthanc. The number of available arguments can be | |
2788 | * retrieved by OrthancPluginGetCommandLineArgumentsCount(). | |
2789 | * | |
2790 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2791 | * @param argument The index of the argument. | |
2792 | * @return The value of the argument, or NULL in the case of an error. This | |
2793 | * string must be freed by OrthancPluginFreeString(). | |
2794 | **/ | |
2795 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetCommandLineArgument( | |
2796 | OrthancPluginContext* context, | |
2797 | uint32_t argument) | |
2798 | { | |
2799 | char* result; | |
2800 | ||
2801 | _OrthancPluginGlobalProperty params; | |
2802 | params.result = &result; | |
2803 | params.property = (int32_t) argument; | |
2804 | params.value = NULL; | |
2805 | ||
2806 | if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgument, ¶ms) != OrthancPluginErrorCode_Success) | |
2807 | { | |
2808 | /* Error */ | |
2809 | return NULL; | |
2810 | } | |
2811 | else | |
2812 | { | |
2813 | return result; | |
2814 | } | |
2815 | } | |
2816 | ||
2817 | ||
2818 | /** | |
2819 | * @brief Get the expected version of the database schema. | |
2820 | * | |
2821 | * Retrieve the expected version of the database schema. | |
2822 | * | |
2823 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2824 | * @return The version. | |
2825 | * @ingroup Callbacks | |
2826 | * @deprecated Please instead use IDatabaseBackend::UpgradeDatabase() | |
2827 | **/ | |
2828 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetExpectedDatabaseVersion( | |
2829 | OrthancPluginContext* context) | |
2830 | { | |
2831 | uint32_t count = 0; | |
2832 | ||
2833 | _OrthancPluginReturnSingleValue params; | |
2834 | memset(¶ms, 0, sizeof(params)); | |
2835 | params.resultUint32 = &count; | |
2836 | ||
2837 | if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, ¶ms) != OrthancPluginErrorCode_Success) | |
2838 | { | |
2839 | /* Error */ | |
2840 | return 0; | |
2841 | } | |
2842 | else | |
2843 | { | |
2844 | return count; | |
2845 | } | |
2846 | } | |
2847 | ||
2848 | ||
2849 | ||
2850 | /** | |
2851 | * @brief Return the content of the configuration file(s). | |
2852 | * | |
2853 | * This function returns the content of the configuration that is | |
2854 | * used by Orthanc, formatted as a JSON string. | |
2855 | * | |
2856 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2857 | * @return NULL in the case of an error, or a newly allocated string | |
2858 | * containing the configuration. This string must be freed by | |
2859 | * OrthancPluginFreeString(). | |
2860 | **/ | |
2861 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfiguration(OrthancPluginContext* context) | |
2862 | { | |
2863 | char* result; | |
2864 | ||
2865 | _OrthancPluginRetrieveDynamicString params; | |
2866 | params.result = &result; | |
2867 | params.argument = NULL; | |
2868 | ||
2869 | if (context->InvokeService(context, _OrthancPluginService_GetConfiguration, ¶ms) != OrthancPluginErrorCode_Success) | |
2870 | { | |
2871 | /* Error */ | |
2872 | return NULL; | |
2873 | } | |
2874 | else | |
2875 | { | |
2876 | return result; | |
2877 | } | |
2878 | } | |
2879 | ||
2880 | ||
2881 | ||
2882 | typedef struct | |
2883 | { | |
2884 | OrthancPluginRestOutput* output; | |
2885 | const char* subType; | |
2886 | const char* contentType; | |
2887 | } _OrthancPluginStartMultipartAnswer; | |
2888 | ||
2889 | /** | |
2890 | * @brief Start an HTTP multipart answer. | |
2891 | * | |
2892 | * Initiates a HTTP multipart answer, as the result of a REST request. | |
2893 | * | |
2894 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2895 | * @param output The HTTP connection to the client application. | |
2896 | * @param subType The sub-type of the multipart answer ("mixed" or "related"). | |
2897 | * @param contentType The MIME type of the items in the multipart answer. | |
2898 | * @return 0 if success, or the error code if failure. | |
2899 | * @see OrthancPluginSendMultipartItem(), OrthancPluginSendMultipartItem2() | |
2900 | * @ingroup REST | |
2901 | **/ | |
2902 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer( | |
2903 | OrthancPluginContext* context, | |
2904 | OrthancPluginRestOutput* output, | |
2905 | const char* subType, | |
2906 | const char* contentType) | |
2907 | { | |
2908 | _OrthancPluginStartMultipartAnswer params; | |
2909 | params.output = output; | |
2910 | params.subType = subType; | |
2911 | params.contentType = contentType; | |
2912 | return context->InvokeService(context, _OrthancPluginService_StartMultipartAnswer, ¶ms); | |
2913 | } | |
2914 | ||
2915 | ||
2916 | /** | |
2917 | * @brief Send an item as a part of some HTTP multipart answer. | |
2918 | * | |
2919 | * This function sends an item as a part of some HTTP multipart | |
2920 | * answer that was initiated by OrthancPluginStartMultipartAnswer(). | |
2921 | * | |
2922 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2923 | * @param output The HTTP connection to the client application. | |
2924 | * @param answer Pointer to the memory buffer containing the item. | |
2925 | * @param answerSize Number of bytes of the item. | |
2926 | * @return 0 if success, or the error code if failure (this notably happens | |
2927 | * if the connection is closed by the client). | |
2928 | * @see OrthancPluginSendMultipartItem2() | |
2929 | * @ingroup REST | |
2930 | **/ | |
2931 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem( | |
2932 | OrthancPluginContext* context, | |
2933 | OrthancPluginRestOutput* output, | |
2934 | const char* answer, | |
2935 | uint32_t answerSize) | |
2936 | { | |
2937 | _OrthancPluginAnswerBuffer params; | |
2938 | params.output = output; | |
2939 | params.answer = answer; | |
2940 | params.answerSize = answerSize; | |
2941 | params.mimeType = NULL; | |
2942 | return context->InvokeService(context, _OrthancPluginService_SendMultipartItem, ¶ms); | |
2943 | } | |
2944 | ||
2945 | ||
2946 | ||
2947 | typedef struct | |
2948 | { | |
2949 | OrthancPluginMemoryBuffer* target; | |
2950 | const void* source; | |
2951 | uint32_t size; | |
2952 | OrthancPluginCompressionType compression; | |
2953 | uint8_t uncompress; | |
2954 | } _OrthancPluginBufferCompression; | |
2955 | ||
2956 | ||
2957 | /** | |
2958 | * @brief Compress or decompress a buffer. | |
2959 | * | |
2960 | * This function compresses or decompresses a buffer, using the | |
2961 | * version of the zlib library that is used by the Orthanc core. | |
2962 | * | |
2963 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2964 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
2965 | * @param source The source buffer. | |
2966 | * @param size The size in bytes of the source buffer. | |
2967 | * @param compression The compression algorithm. | |
2968 | * @param uncompress If set to "0", the buffer must be compressed. | |
2969 | * If set to "1", the buffer must be uncompressed. | |
2970 | * @return 0 if success, or the error code if failure. | |
2971 | * @ingroup Images | |
2972 | **/ | |
2973 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginBufferCompression( | |
2974 | OrthancPluginContext* context, | |
2975 | OrthancPluginMemoryBuffer* target, | |
2976 | const void* source, | |
2977 | uint32_t size, | |
2978 | OrthancPluginCompressionType compression, | |
2979 | uint8_t uncompress) | |
2980 | { | |
2981 | _OrthancPluginBufferCompression params; | |
2982 | params.target = target; | |
2983 | params.source = source; | |
2984 | params.size = size; | |
2985 | params.compression = compression; | |
2986 | params.uncompress = uncompress; | |
2987 | ||
2988 | return context->InvokeService(context, _OrthancPluginService_BufferCompression, ¶ms); | |
2989 | } | |
2990 | ||
2991 | ||
2992 | ||
2993 | typedef struct | |
2994 | { | |
2995 | OrthancPluginMemoryBuffer* target; | |
2996 | const char* path; | |
2997 | } _OrthancPluginReadFile; | |
2998 | ||
2999 | /** | |
3000 | * @brief Read a file. | |
3001 | * | |
3002 | * Read the content of a file on the filesystem, and returns it into | |
3003 | * a newly allocated memory buffer. | |
3004 | * | |
3005 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3006 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3007 | * @param path The path of the file to be read. | |
3008 | * @return 0 if success, or the error code if failure. | |
3009 | **/ | |
3010 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReadFile( | |
3011 | OrthancPluginContext* context, | |
3012 | OrthancPluginMemoryBuffer* target, | |
3013 | const char* path) | |
3014 | { | |
3015 | _OrthancPluginReadFile params; | |
3016 | params.target = target; | |
3017 | params.path = path; | |
3018 | return context->InvokeService(context, _OrthancPluginService_ReadFile, ¶ms); | |
3019 | } | |
3020 | ||
3021 | ||
3022 | ||
3023 | typedef struct | |
3024 | { | |
3025 | const char* path; | |
3026 | const void* data; | |
3027 | uint32_t size; | |
3028 | } _OrthancPluginWriteFile; | |
3029 | ||
3030 | /** | |
3031 | * @brief Write a file. | |
3032 | * | |
3033 | * Write the content of a memory buffer to the filesystem. | |
3034 | * | |
3035 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3036 | * @param path The path of the file to be written. | |
3037 | * @param data The content of the memory buffer. | |
3038 | * @param size The size of the memory buffer. | |
3039 | * @return 0 if success, or the error code if failure. | |
3040 | **/ | |
3041 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWriteFile( | |
3042 | OrthancPluginContext* context, | |
3043 | const char* path, | |
3044 | const void* data, | |
3045 | uint32_t size) | |
3046 | { | |
3047 | _OrthancPluginWriteFile params; | |
3048 | params.path = path; | |
3049 | params.data = data; | |
3050 | params.size = size; | |
3051 | return context->InvokeService(context, _OrthancPluginService_WriteFile, ¶ms); | |
3052 | } | |
3053 | ||
3054 | ||
3055 | ||
3056 | typedef struct | |
3057 | { | |
3058 | const char** target; | |
3059 | OrthancPluginErrorCode error; | |
3060 | } _OrthancPluginGetErrorDescription; | |
3061 | ||
3062 | /** | |
3063 | * @brief Get the description of a given error code. | |
3064 | * | |
3065 | * This function returns the description of a given error code. | |
3066 | * | |
3067 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3068 | * @param error The error code of interest. | |
3069 | * @return The error description. This is a statically-allocated | |
3070 | * string, do not free it. | |
3071 | **/ | |
3072 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetErrorDescription( | |
3073 | OrthancPluginContext* context, | |
3074 | OrthancPluginErrorCode error) | |
3075 | { | |
3076 | const char* result = NULL; | |
3077 | ||
3078 | _OrthancPluginGetErrorDescription params; | |
3079 | params.target = &result; | |
3080 | params.error = error; | |
3081 | ||
3082 | if (context->InvokeService(context, _OrthancPluginService_GetErrorDescription, ¶ms) != OrthancPluginErrorCode_Success || | |
3083 | result == NULL) | |
3084 | { | |
3085 | return "Unknown error code"; | |
3086 | } | |
3087 | else | |
3088 | { | |
3089 | return result; | |
3090 | } | |
3091 | } | |
3092 | ||
3093 | ||
3094 | ||
3095 | typedef struct | |
3096 | { | |
3097 | OrthancPluginRestOutput* output; | |
3098 | uint16_t status; | |
3099 | const char* body; | |
3100 | uint32_t bodySize; | |
3101 | } _OrthancPluginSendHttpStatus; | |
3102 | ||
3103 | /** | |
3104 | * @brief Send a HTTP status, with a custom body. | |
3105 | * | |
3106 | * This function answers to a HTTP request by sending a HTTP status | |
3107 | * code (such as "400 - Bad Request"), together with a body | |
3108 | * describing the error. The body will only be returned if the | |
3109 | * configuration option "HttpDescribeErrors" of Orthanc is set to "true". | |
3110 | * | |
3111 | * Note that: | |
3112 | * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). | |
3113 | * - Redirections (status 301) must use ::OrthancPluginRedirect(). | |
3114 | * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). | |
3115 | * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). | |
3116 | * | |
3117 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3118 | * @param output The HTTP connection to the client application. | |
3119 | * @param status The HTTP status code to be sent. | |
3120 | * @param body The body of the answer. | |
3121 | * @param bodySize The size of the body. | |
3122 | * @see OrthancPluginSendHttpStatusCode() | |
3123 | * @ingroup REST | |
3124 | **/ | |
3125 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatus( | |
3126 | OrthancPluginContext* context, | |
3127 | OrthancPluginRestOutput* output, | |
3128 | uint16_t status, | |
3129 | const char* body, | |
3130 | uint32_t bodySize) | |
3131 | { | |
3132 | _OrthancPluginSendHttpStatus params; | |
3133 | params.output = output; | |
3134 | params.status = status; | |
3135 | params.body = body; | |
3136 | params.bodySize = bodySize; | |
3137 | context->InvokeService(context, _OrthancPluginService_SendHttpStatus, ¶ms); | |
3138 | } | |
3139 | ||
3140 | ||
3141 | ||
3142 | typedef struct | |
3143 | { | |
3144 | const OrthancPluginImage* image; | |
3145 | uint32_t* resultUint32; | |
3146 | OrthancPluginPixelFormat* resultPixelFormat; | |
3147 | void** resultBuffer; | |
3148 | } _OrthancPluginGetImageInfo; | |
3149 | ||
3150 | ||
3151 | /** | |
3152 | * @brief Return the pixel format of an image. | |
3153 | * | |
3154 | * This function returns the type of memory layout for the pixels of the given image. | |
3155 | * | |
3156 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3157 | * @param image The image of interest. | |
3158 | * @return The pixel format. | |
3159 | * @ingroup Images | |
3160 | **/ | |
3161 | ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat OrthancPluginGetImagePixelFormat( | |
3162 | OrthancPluginContext* context, | |
3163 | const OrthancPluginImage* image) | |
3164 | { | |
3165 | OrthancPluginPixelFormat target; | |
3166 | ||
3167 | _OrthancPluginGetImageInfo params; | |
3168 | memset(¶ms, 0, sizeof(params)); | |
3169 | params.image = image; | |
3170 | params.resultPixelFormat = ⌖ | |
3171 | ||
3172 | if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, ¶ms) != OrthancPluginErrorCode_Success) | |
3173 | { | |
3174 | return OrthancPluginPixelFormat_Unknown; | |
3175 | } | |
3176 | else | |
3177 | { | |
3178 | return (OrthancPluginPixelFormat) target; | |
3179 | } | |
3180 | } | |
3181 | ||
3182 | ||
3183 | ||
3184 | /** | |
3185 | * @brief Return the width of an image. | |
3186 | * | |
3187 | * This function returns the width of the given image. | |
3188 | * | |
3189 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3190 | * @param image The image of interest. | |
3191 | * @return The width. | |
3192 | * @ingroup Images | |
3193 | **/ | |
3194 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageWidth( | |
3195 | OrthancPluginContext* context, | |
3196 | const OrthancPluginImage* image) | |
3197 | { | |
3198 | uint32_t width; | |
3199 | ||
3200 | _OrthancPluginGetImageInfo params; | |
3201 | memset(¶ms, 0, sizeof(params)); | |
3202 | params.image = image; | |
3203 | params.resultUint32 = &width; | |
3204 | ||
3205 | if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, ¶ms) != OrthancPluginErrorCode_Success) | |
3206 | { | |
3207 | return 0; | |
3208 | } | |
3209 | else | |
3210 | { | |
3211 | return width; | |
3212 | } | |
3213 | } | |
3214 | ||
3215 | ||
3216 | ||
3217 | /** | |
3218 | * @brief Return the height of an image. | |
3219 | * | |
3220 | * This function returns the height of the given image. | |
3221 | * | |
3222 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3223 | * @param image The image of interest. | |
3224 | * @return The height. | |
3225 | * @ingroup Images | |
3226 | **/ | |
3227 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageHeight( | |
3228 | OrthancPluginContext* context, | |
3229 | const OrthancPluginImage* image) | |
3230 | { | |
3231 | uint32_t height; | |
3232 | ||
3233 | _OrthancPluginGetImageInfo params; | |
3234 | memset(¶ms, 0, sizeof(params)); | |
3235 | params.image = image; | |
3236 | params.resultUint32 = &height; | |
3237 | ||
3238 | if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, ¶ms) != OrthancPluginErrorCode_Success) | |
3239 | { | |
3240 | return 0; | |
3241 | } | |
3242 | else | |
3243 | { | |
3244 | return height; | |
3245 | } | |
3246 | } | |
3247 | ||
3248 | ||
3249 | ||
3250 | /** | |
3251 | * @brief Return the pitch of an image. | |
3252 | * | |
3253 | * This function returns the pitch of the given image. The pitch is | |
3254 | * defined as the number of bytes between 2 successive lines of the | |
3255 | * image in the memory buffer. | |
3256 | * | |
3257 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3258 | * @param image The image of interest. | |
3259 | * @return The pitch. | |
3260 | * @ingroup Images | |
3261 | **/ | |
3262 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImagePitch( | |
3263 | OrthancPluginContext* context, | |
3264 | const OrthancPluginImage* image) | |
3265 | { | |
3266 | uint32_t pitch; | |
3267 | ||
3268 | _OrthancPluginGetImageInfo params; | |
3269 | memset(¶ms, 0, sizeof(params)); | |
3270 | params.image = image; | |
3271 | params.resultUint32 = &pitch; | |
3272 | ||
3273 | if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, ¶ms) != OrthancPluginErrorCode_Success) | |
3274 | { | |
3275 | return 0; | |
3276 | } | |
3277 | else | |
3278 | { | |
3279 | return pitch; | |
3280 | } | |
3281 | } | |
3282 | ||
3283 | ||
3284 | ||
3285 | /** | |
3286 | * @brief Return a pointer to the content of an image. | |
3287 | * | |
3288 | * This function returns a pointer to the memory buffer that | |
3289 | * contains the pixels of the image. | |
3290 | * | |
3291 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3292 | * @param image The image of interest. | |
3293 | * @return The pointer. | |
3294 | * @ingroup Images | |
3295 | **/ | |
3296 | ORTHANC_PLUGIN_INLINE void* OrthancPluginGetImageBuffer( | |
3297 | OrthancPluginContext* context, | |
3298 | const OrthancPluginImage* image) | |
3299 | { | |
3300 | void* target = NULL; | |
3301 | ||
3302 | _OrthancPluginGetImageInfo params; | |
3303 | memset(¶ms, 0, sizeof(params)); | |
3304 | params.resultBuffer = ⌖ | |
3305 | params.image = image; | |
3306 | ||
3307 | if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, ¶ms) != OrthancPluginErrorCode_Success) | |
3308 | { | |
3309 | return NULL; | |
3310 | } | |
3311 | else | |
3312 | { | |
3313 | return target; | |
3314 | } | |
3315 | } | |
3316 | ||
3317 | ||
3318 | typedef struct | |
3319 | { | |
3320 | OrthancPluginImage** target; | |
3321 | const void* data; | |
3322 | uint32_t size; | |
3323 | OrthancPluginImageFormat format; | |
3324 | } _OrthancPluginUncompressImage; | |
3325 | ||
3326 | ||
3327 | /** | |
3328 | * @brief Decode a compressed image. | |
3329 | * | |
3330 | * This function decodes a compressed image from a memory buffer. | |
3331 | * | |
3332 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3333 | * @param data Pointer to a memory buffer containing the compressed image. | |
3334 | * @param size Size of the memory buffer containing the compressed image. | |
3335 | * @param format The file format of the compressed image. | |
3336 | * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). | |
3337 | * @ingroup Images | |
3338 | **/ | |
3339 | ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage( | |
3340 | OrthancPluginContext* context, | |
3341 | const void* data, | |
3342 | uint32_t size, | |
3343 | OrthancPluginImageFormat format) | |
3344 | { | |
3345 | OrthancPluginImage* target = NULL; | |
3346 | ||
3347 | _OrthancPluginUncompressImage params; | |
3348 | memset(¶ms, 0, sizeof(params)); | |
3349 | params.target = ⌖ | |
3350 | params.data = data; | |
3351 | params.size = size; | |
3352 | params.format = format; | |
3353 | ||
3354 | if (context->InvokeService(context, _OrthancPluginService_UncompressImage, ¶ms) != OrthancPluginErrorCode_Success) | |
3355 | { | |
3356 | return NULL; | |
3357 | } | |
3358 | else | |
3359 | { | |
3360 | return target; | |
3361 | } | |
3362 | } | |
3363 | ||
3364 | ||
3365 | ||
3366 | ||
3367 | typedef struct | |
3368 | { | |
3369 | OrthancPluginImage* image; | |
3370 | } _OrthancPluginFreeImage; | |
3371 | ||
3372 | /** | |
3373 | * @brief Free an image. | |
3374 | * | |
3375 | * This function frees an image that was decoded with OrthancPluginUncompressImage(). | |
3376 | * | |
3377 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3378 | * @param image The image. | |
3379 | * @ingroup Images | |
3380 | **/ | |
3381 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeImage( | |
3382 | OrthancPluginContext* context, | |
3383 | OrthancPluginImage* image) | |
3384 | { | |
3385 | _OrthancPluginFreeImage params; | |
3386 | params.image = image; | |
3387 | ||
3388 | context->InvokeService(context, _OrthancPluginService_FreeImage, ¶ms); | |
3389 | } | |
3390 | ||
3391 | ||
3392 | ||
3393 | ||
3394 | typedef struct | |
3395 | { | |
3396 | OrthancPluginMemoryBuffer* target; | |
3397 | OrthancPluginImageFormat imageFormat; | |
3398 | OrthancPluginPixelFormat pixelFormat; | |
3399 | uint32_t width; | |
3400 | uint32_t height; | |
3401 | uint32_t pitch; | |
3402 | const void* buffer; | |
3403 | uint8_t quality; | |
3404 | } _OrthancPluginCompressImage; | |
3405 | ||
3406 | ||
3407 | /** | |
3408 | * @brief Encode a PNG image. | |
3409 | * | |
3410 | * This function compresses the given memory buffer containing an | |
3411 | * image using the PNG specification, and stores the result of the | |
3412 | * compression into a newly allocated memory buffer. | |
3413 | * | |
3414 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3415 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3416 | * @param format The memory layout of the uncompressed image. | |
3417 | * @param width The width of the image. | |
3418 | * @param height The height of the image. | |
3419 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3420 | * between 2 successive lines of the image in the memory buffer). | |
3421 | * @param buffer The memory buffer containing the uncompressed image. | |
3422 | * @return 0 if success, or the error code if failure. | |
3423 | * @see OrthancPluginCompressAndAnswerPngImage() | |
3424 | * @ingroup Images | |
3425 | **/ | |
3426 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage( | |
3427 | OrthancPluginContext* context, | |
3428 | OrthancPluginMemoryBuffer* target, | |
3429 | OrthancPluginPixelFormat format, | |
3430 | uint32_t width, | |
3431 | uint32_t height, | |
3432 | uint32_t pitch, | |
3433 | const void* buffer) | |
3434 | { | |
3435 | _OrthancPluginCompressImage params; | |
3436 | memset(¶ms, 0, sizeof(params)); | |
3437 | params.target = target; | |
3438 | params.imageFormat = OrthancPluginImageFormat_Png; | |
3439 | params.pixelFormat = format; | |
3440 | params.width = width; | |
3441 | params.height = height; | |
3442 | params.pitch = pitch; | |
3443 | params.buffer = buffer; | |
3444 | params.quality = 0; /* Unused for PNG */ | |
3445 | ||
3446 | return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); | |
3447 | } | |
3448 | ||
3449 | ||
3450 | /** | |
3451 | * @brief Encode a JPEG image. | |
3452 | * | |
3453 | * This function compresses the given memory buffer containing an | |
3454 | * image using the JPEG specification, and stores the result of the | |
3455 | * compression into a newly allocated memory buffer. | |
3456 | * | |
3457 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3458 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3459 | * @param format The memory layout of the uncompressed image. | |
3460 | * @param width The width of the image. | |
3461 | * @param height The height of the image. | |
3462 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3463 | * between 2 successive lines of the image in the memory buffer). | |
3464 | * @param buffer The memory buffer containing the uncompressed image. | |
3465 | * @param quality The quality of the JPEG encoding, between 1 (worst | |
3466 | * quality, best compression) and 100 (best quality, worst | |
3467 | * compression). | |
3468 | * @return 0 if success, or the error code if failure. | |
3469 | * @ingroup Images | |
3470 | **/ | |
3471 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage( | |
3472 | OrthancPluginContext* context, | |
3473 | OrthancPluginMemoryBuffer* target, | |
3474 | OrthancPluginPixelFormat format, | |
3475 | uint32_t width, | |
3476 | uint32_t height, | |
3477 | uint32_t pitch, | |
3478 | const void* buffer, | |
3479 | uint8_t quality) | |
3480 | { | |
3481 | _OrthancPluginCompressImage params; | |
3482 | memset(¶ms, 0, sizeof(params)); | |
3483 | params.target = target; | |
3484 | params.imageFormat = OrthancPluginImageFormat_Jpeg; | |
3485 | params.pixelFormat = format; | |
3486 | params.width = width; | |
3487 | params.height = height; | |
3488 | params.pitch = pitch; | |
3489 | params.buffer = buffer; | |
3490 | params.quality = quality; | |
3491 | ||
3492 | return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); | |
3493 | } | |
3494 | ||
3495 | ||
3496 | ||
3497 | /** | |
3498 | * @brief Answer to a REST request with a JPEG image. | |
3499 | * | |
3500 | * This function answers to a REST request with a JPEG image. The | |
3501 | * parameters of this function describe a memory buffer that | |
3502 | * contains an uncompressed image. The image will be automatically compressed | |
3503 | * as a JPEG image by the core system of Orthanc. | |
3504 | * | |
3505 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3506 | * @param output The HTTP connection to the client application. | |
3507 | * @param format The memory layout of the uncompressed image. | |
3508 | * @param width The width of the image. | |
3509 | * @param height The height of the image. | |
3510 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3511 | * between 2 successive lines of the image in the memory buffer). | |
3512 | * @param buffer The memory buffer containing the uncompressed image. | |
3513 | * @param quality The quality of the JPEG encoding, between 1 (worst | |
3514 | * quality, best compression) and 100 (best quality, worst | |
3515 | * compression). | |
3516 | * @ingroup REST | |
3517 | **/ | |
3518 | ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerJpegImage( | |
3519 | OrthancPluginContext* context, | |
3520 | OrthancPluginRestOutput* output, | |
3521 | OrthancPluginPixelFormat format, | |
3522 | uint32_t width, | |
3523 | uint32_t height, | |
3524 | uint32_t pitch, | |
3525 | const void* buffer, | |
3526 | uint8_t quality) | |
3527 | { | |
3528 | _OrthancPluginCompressAndAnswerImage params; | |
3529 | params.output = output; | |
3530 | params.imageFormat = OrthancPluginImageFormat_Jpeg; | |
3531 | params.pixelFormat = format; | |
3532 | params.width = width; | |
3533 | params.height = height; | |
3534 | params.pitch = pitch; | |
3535 | params.buffer = buffer; | |
3536 | params.quality = quality; | |
3537 | context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); | |
3538 | } | |
3539 | ||
3540 | ||
3541 | ||
3542 | ||
3543 | typedef struct | |
3544 | { | |
3545 | OrthancPluginMemoryBuffer* target; | |
3546 | OrthancPluginHttpMethod method; | |
3547 | const char* url; | |
3548 | const char* username; | |
3549 | const char* password; | |
3550 | const char* body; | |
3551 | uint32_t bodySize; | |
3552 | } _OrthancPluginCallHttpClient; | |
3553 | ||
3554 | ||
3555 | /** | |
3556 | * @brief Issue a HTTP GET call. | |
3557 | * | |
3558 | * Make a HTTP GET call to the given URL. The result to the query is | |
3559 | * stored into a newly allocated memory buffer. Favor | |
3560 | * OrthancPluginRestApiGet() if calling the built-in REST API of the | |
3561 | * Orthanc instance that hosts this plugin. | |
3562 | * | |
3563 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3564 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3565 | * @param url The URL of interest. | |
3566 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3567 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3568 | * @return 0 if success, or the error code if failure. | |
3569 | **/ | |
3570 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpGet( | |
3571 | OrthancPluginContext* context, | |
3572 | OrthancPluginMemoryBuffer* target, | |
3573 | const char* url, | |
3574 | const char* username, | |
3575 | const char* password) | |
3576 | { | |
3577 | _OrthancPluginCallHttpClient params; | |
3578 | memset(¶ms, 0, sizeof(params)); | |
3579 | ||
3580 | params.target = target; | |
3581 | params.method = OrthancPluginHttpMethod_Get; | |
3582 | params.url = url; | |
3583 | params.username = username; | |
3584 | params.password = password; | |
3585 | ||
3586 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3587 | } | |
3588 | ||
3589 | ||
3590 | /** | |
3591 | * @brief Issue a HTTP POST call. | |
3592 | * | |
3593 | * Make a HTTP POST call to the given URL. The result to the query | |
3594 | * is stored into a newly allocated memory buffer. Favor | |
3595 | * OrthancPluginRestApiPost() if calling the built-in REST API of | |
3596 | * the Orthanc instance that hosts this plugin. | |
3597 | * | |
3598 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3599 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3600 | * @param url The URL of interest. | |
3601 | * @param body The content of the body of the request. | |
3602 | * @param bodySize The size of the body of the request. | |
3603 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3604 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3605 | * @return 0 if success, or the error code if failure. | |
3606 | **/ | |
3607 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPost( | |
3608 | OrthancPluginContext* context, | |
3609 | OrthancPluginMemoryBuffer* target, | |
3610 | const char* url, | |
3611 | const char* body, | |
3612 | uint32_t bodySize, | |
3613 | const char* username, | |
3614 | const char* password) | |
3615 | { | |
3616 | _OrthancPluginCallHttpClient params; | |
3617 | memset(¶ms, 0, sizeof(params)); | |
3618 | ||
3619 | params.target = target; | |
3620 | params.method = OrthancPluginHttpMethod_Post; | |
3621 | params.url = url; | |
3622 | params.body = body; | |
3623 | params.bodySize = bodySize; | |
3624 | params.username = username; | |
3625 | params.password = password; | |
3626 | ||
3627 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3628 | } | |
3629 | ||
3630 | ||
3631 | /** | |
3632 | * @brief Issue a HTTP PUT call. | |
3633 | * | |
3634 | * Make a HTTP PUT call to the given URL. The result to the query is | |
3635 | * stored into a newly allocated memory buffer. Favor | |
3636 | * OrthancPluginRestApiPut() if calling the built-in REST API of the | |
3637 | * Orthanc instance that hosts this plugin. | |
3638 | * | |
3639 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3640 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3641 | * @param url The URL of interest. | |
3642 | * @param body The content of the body of the request. | |
3643 | * @param bodySize The size of the body of the request. | |
3644 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3645 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3646 | * @return 0 if success, or the error code if failure. | |
3647 | **/ | |
3648 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPut( | |
3649 | OrthancPluginContext* context, | |
3650 | OrthancPluginMemoryBuffer* target, | |
3651 | const char* url, | |
3652 | const char* body, | |
3653 | uint32_t bodySize, | |
3654 | const char* username, | |
3655 | const char* password) | |
3656 | { | |
3657 | _OrthancPluginCallHttpClient params; | |
3658 | memset(¶ms, 0, sizeof(params)); | |
3659 | ||
3660 | params.target = target; | |
3661 | params.method = OrthancPluginHttpMethod_Put; | |
3662 | params.url = url; | |
3663 | params.body = body; | |
3664 | params.bodySize = bodySize; | |
3665 | params.username = username; | |
3666 | params.password = password; | |
3667 | ||
3668 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3669 | } | |
3670 | ||
3671 | ||
3672 | /** | |
3673 | * @brief Issue a HTTP DELETE call. | |
3674 | * | |
3675 | * Make a HTTP DELETE call to the given URL. Favor | |
3676 | * OrthancPluginRestApiDelete() if calling the built-in REST API of | |
3677 | * the Orthanc instance that hosts this plugin. | |
3678 | * | |
3679 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3680 | * @param url The URL of interest. | |
3681 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3682 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3683 | * @return 0 if success, or the error code if failure. | |
3684 | **/ | |
3685 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpDelete( | |
3686 | OrthancPluginContext* context, | |
3687 | const char* url, | |
3688 | const char* username, | |
3689 | const char* password) | |
3690 | { | |
3691 | _OrthancPluginCallHttpClient params; | |
3692 | memset(¶ms, 0, sizeof(params)); | |
3693 | ||
3694 | params.method = OrthancPluginHttpMethod_Delete; | |
3695 | params.url = url; | |
3696 | params.username = username; | |
3697 | params.password = password; | |
3698 | ||
3699 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3700 | } | |
3701 | ||
3702 | ||
3703 | ||
3704 | typedef struct | |
3705 | { | |
3706 | OrthancPluginImage** target; | |
3707 | const OrthancPluginImage* source; | |
3708 | OrthancPluginPixelFormat targetFormat; | |
3709 | } _OrthancPluginConvertPixelFormat; | |
3710 | ||
3711 | ||
3712 | /** | |
3713 | * @brief Change the pixel format of an image. | |
3714 | * | |
3715 | * This function creates a new image, changing the memory layout of the pixels. | |
3716 | * | |
3717 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3718 | * @param source The source image. | |
3719 | * @param targetFormat The target pixel format. | |
3720 | * @return The resulting image. It must be freed with OrthancPluginFreeImage(). | |
3721 | * @ingroup Images | |
3722 | **/ | |
3723 | ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginConvertPixelFormat( | |
3724 | OrthancPluginContext* context, | |
3725 | const OrthancPluginImage* source, | |
3726 | OrthancPluginPixelFormat targetFormat) | |
3727 | { | |
3728 | OrthancPluginImage* target = NULL; | |
3729 | ||
3730 | _OrthancPluginConvertPixelFormat params; | |
3731 | params.target = ⌖ | |
3732 | params.source = source; | |
3733 | params.targetFormat = targetFormat; | |
3734 | ||
3735 | if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, ¶ms) != OrthancPluginErrorCode_Success) | |
3736 | { | |
3737 | return NULL; | |
3738 | } | |
3739 | else | |
3740 | { | |
3741 | return target; | |
3742 | } | |
3743 | } | |
3744 | ||
3745 | ||
3746 | ||
3747 | /** | |
3748 | * @brief Return the number of available fonts. | |
3749 | * | |
3750 | * This function returns the number of fonts that are built in the | |
3751 | * Orthanc core. These fonts can be used to draw texts on images | |
3752 | * through OrthancPluginDrawText(). | |
3753 | * | |
3754 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3755 | * @return The number of fonts. | |
3756 | * @ingroup Images | |
3757 | **/ | |
3758 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontsCount( | |
3759 | OrthancPluginContext* context) | |
3760 | { | |
3761 | uint32_t count = 0; | |
3762 | ||
3763 | _OrthancPluginReturnSingleValue params; | |
3764 | memset(¶ms, 0, sizeof(params)); | |
3765 | params.resultUint32 = &count; | |
3766 | ||
3767 | if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, ¶ms) != OrthancPluginErrorCode_Success) | |
3768 | { | |
3769 | /* Error */ | |
3770 | return 0; | |
3771 | } | |
3772 | else | |
3773 | { | |
3774 | return count; | |
3775 | } | |
3776 | } | |
3777 | ||
3778 | ||
3779 | ||
3780 | ||
3781 | typedef struct | |
3782 | { | |
3783 | uint32_t fontIndex; /* in */ | |
3784 | const char** name; /* out */ | |
3785 | uint32_t* size; /* out */ | |
3786 | } _OrthancPluginGetFontInfo; | |
3787 | ||
3788 | /** | |
3789 | * @brief Return the name of a font. | |
3790 | * | |
3791 | * This function returns the name of a font that is built in the Orthanc core. | |
3792 | * | |
3793 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3794 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3795 | * @return The font name. This is a statically-allocated string, do not free it. | |
3796 | * @ingroup Images | |
3797 | **/ | |
3798 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetFontName( | |
3799 | OrthancPluginContext* context, | |
3800 | uint32_t fontIndex) | |
3801 | { | |
3802 | const char* result = NULL; | |
3803 | ||
3804 | _OrthancPluginGetFontInfo params; | |
3805 | memset(¶ms, 0, sizeof(params)); | |
3806 | params.name = &result; | |
3807 | params.fontIndex = fontIndex; | |
3808 | ||
3809 | if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) | |
3810 | { | |
3811 | return NULL; | |
3812 | } | |
3813 | else | |
3814 | { | |
3815 | return result; | |
3816 | } | |
3817 | } | |
3818 | ||
3819 | ||
3820 | /** | |
3821 | * @brief Return the size of a font. | |
3822 | * | |
3823 | * This function returns the size of a font that is built in the Orthanc core. | |
3824 | * | |
3825 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3826 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3827 | * @return The font size. | |
3828 | * @ingroup Images | |
3829 | **/ | |
3830 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontSize( | |
3831 | OrthancPluginContext* context, | |
3832 | uint32_t fontIndex) | |
3833 | { | |
3834 | uint32_t result; | |
3835 | ||
3836 | _OrthancPluginGetFontInfo params; | |
3837 | memset(¶ms, 0, sizeof(params)); | |
3838 | params.size = &result; | |
3839 | params.fontIndex = fontIndex; | |
3840 | ||
3841 | if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) | |
3842 | { | |
3843 | return 0; | |
3844 | } | |
3845 | else | |
3846 | { | |
3847 | return result; | |
3848 | } | |
3849 | } | |
3850 | ||
3851 | ||
3852 | ||
3853 | typedef struct | |
3854 | { | |
3855 | OrthancPluginImage* image; | |
3856 | uint32_t fontIndex; | |
3857 | const char* utf8Text; | |
3858 | int32_t x; | |
3859 | int32_t y; | |
3860 | uint8_t r; | |
3861 | uint8_t g; | |
3862 | uint8_t b; | |
3863 | } _OrthancPluginDrawText; | |
3864 | ||
3865 | ||
3866 | /** | |
3867 | * @brief Draw text on an image. | |
3868 | * | |
3869 | * This function draws some text on some image. | |
3870 | * | |
3871 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3872 | * @param image The image upon which to draw the text. | |
3873 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3874 | * @param utf8Text The text to be drawn, encoded as an UTF-8 zero-terminated string. | |
3875 | * @param x The X position of the text over the image. | |
3876 | * @param y The Y position of the text over the image. | |
3877 | * @param r The value of the red color channel of the text. | |
3878 | * @param g The value of the green color channel of the text. | |
3879 | * @param b The value of the blue color channel of the text. | |
3880 | * @return 0 if success, other value if error. | |
3881 | * @ingroup Images | |
3882 | **/ | |
3883 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginDrawText( | |
3884 | OrthancPluginContext* context, | |
3885 | OrthancPluginImage* image, | |
3886 | uint32_t fontIndex, | |
3887 | const char* utf8Text, | |
3888 | int32_t x, | |
3889 | int32_t y, | |
3890 | uint8_t r, | |
3891 | uint8_t g, | |
3892 | uint8_t b) | |
3893 | { | |
3894 | _OrthancPluginDrawText params; | |
3895 | memset(¶ms, 0, sizeof(params)); | |
3896 | params.image = image; | |
3897 | params.fontIndex = fontIndex; | |
3898 | params.utf8Text = utf8Text; | |
3899 | params.x = x; | |
3900 | params.y = y; | |
3901 | params.r = r; | |
3902 | params.g = g; | |
3903 | params.b = b; | |
3904 | ||
3905 | return context->InvokeService(context, _OrthancPluginService_DrawText, ¶ms); | |
3906 | } | |
3907 | ||
3908 | ||
3909 | ||
3910 | typedef struct | |
3911 | { | |
3912 | OrthancPluginStorageArea* storageArea; | |
3913 | const char* uuid; | |
3914 | const void* content; | |
3915 | uint64_t size; | |
3916 | OrthancPluginContentType type; | |
3917 | } _OrthancPluginStorageAreaCreate; | |
3918 | ||
3919 | ||
3920 | /** | |
3921 | * @brief Create a file inside the storage area. | |
3922 | * | |
3923 | * This function creates a new file inside the storage area that is | |
3924 | * currently used by Orthanc. | |
3925 | * | |
3926 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3927 | * @param storageArea The storage area. | |
3928 | * @param uuid The identifier of the file to be created. | |
3929 | * @param content The content to store in the newly created file. | |
3930 | * @param size The size of the content. | |
3931 | * @param type The type of the file content. | |
3932 | * @return 0 if success, other value if error. | |
3933 | * @ingroup Callbacks | |
3934 | **/ | |
3935 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaCreate( | |
3936 | OrthancPluginContext* context, | |
3937 | OrthancPluginStorageArea* storageArea, | |
3938 | const char* uuid, | |
3939 | const void* content, | |
3940 | uint64_t size, | |
3941 | OrthancPluginContentType type) | |
3942 | { | |
3943 | _OrthancPluginStorageAreaCreate params; | |
3944 | params.storageArea = storageArea; | |
3945 | params.uuid = uuid; | |
3946 | params.content = content; | |
3947 | params.size = size; | |
3948 | params.type = type; | |
3949 | ||
3950 | return context->InvokeService(context, _OrthancPluginService_StorageAreaCreate, ¶ms); | |
3951 | } | |
3952 | ||
3953 | ||
3954 | typedef struct | |
3955 | { | |
3956 | OrthancPluginMemoryBuffer* target; | |
3957 | OrthancPluginStorageArea* storageArea; | |
3958 | const char* uuid; | |
3959 | OrthancPluginContentType type; | |
3960 | } _OrthancPluginStorageAreaRead; | |
3961 | ||
3962 | ||
3963 | /** | |
3964 | * @brief Read a file from the storage area. | |
3965 | * | |
3966 | * This function reads the content of a given file from the storage | |
3967 | * area that is currently used by Orthanc. | |
3968 | * | |
3969 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3970 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3971 | * @param storageArea The storage area. | |
3972 | * @param uuid The identifier of the file to be read. | |
3973 | * @param type The type of the file content. | |
3974 | * @return 0 if success, other value if error. | |
3975 | * @ingroup Callbacks | |
3976 | **/ | |
3977 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRead( | |
3978 | OrthancPluginContext* context, | |
3979 | OrthancPluginMemoryBuffer* target, | |
3980 | OrthancPluginStorageArea* storageArea, | |
3981 | const char* uuid, | |
3982 | OrthancPluginContentType type) | |
3983 | { | |
3984 | _OrthancPluginStorageAreaRead params; | |
3985 | params.target = target; | |
3986 | params.storageArea = storageArea; | |
3987 | params.uuid = uuid; | |
3988 | params.type = type; | |
3989 | ||
3990 | return context->InvokeService(context, _OrthancPluginService_StorageAreaRead, ¶ms); | |
3991 | } | |
3992 | ||
3993 | ||
3994 | typedef struct | |
3995 | { | |
3996 | OrthancPluginStorageArea* storageArea; | |
3997 | const char* uuid; | |
3998 | OrthancPluginContentType type; | |
3999 | } _OrthancPluginStorageAreaRemove; | |
4000 | ||
4001 | /** | |
4002 | * @brief Remove a file from the storage area. | |
4003 | * | |
4004 | * This function removes a given file from the storage area that is | |
4005 | * currently used by Orthanc. | |
4006 | * | |
4007 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4008 | * @param storageArea The storage area. | |
4009 | * @param uuid The identifier of the file to be removed. | |
4010 | * @param type The type of the file content. | |
4011 | * @return 0 if success, other value if error. | |
4012 | * @ingroup Callbacks | |
4013 | **/ | |
4014 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRemove( | |
4015 | OrthancPluginContext* context, | |
4016 | OrthancPluginStorageArea* storageArea, | |
4017 | const char* uuid, | |
4018 | OrthancPluginContentType type) | |
4019 | { | |
4020 | _OrthancPluginStorageAreaRemove params; | |
4021 | params.storageArea = storageArea; | |
4022 | params.uuid = uuid; | |
4023 | params.type = type; | |
4024 | ||
4025 | return context->InvokeService(context, _OrthancPluginService_StorageAreaRemove, ¶ms); | |
4026 | } | |
4027 | ||
4028 | ||
4029 | ||
4030 | typedef struct | |
4031 | { | |
4032 | OrthancPluginErrorCode* target; | |
4033 | int32_t code; | |
4034 | uint16_t httpStatus; | |
4035 | const char* message; | |
4036 | } _OrthancPluginRegisterErrorCode; | |
4037 | ||
4038 | /** | |
4039 | * @brief Declare a custom error code for this plugin. | |
4040 | * | |
4041 | * This function declares a custom error code that can be generated | |
4042 | * by this plugin. This declaration is used to enrich the body of | |
4043 | * the HTTP answer in the case of an error, and to set the proper | |
4044 | * HTTP status code. | |
4045 | * | |
4046 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4047 | * @param code The error code that is internal to this plugin. | |
4048 | * @param httpStatus The HTTP status corresponding to this error. | |
4049 | * @param message The description of the error. | |
4050 | * @return The error code that has been assigned inside the Orthanc core. | |
4051 | * @ingroup Toolbox | |
4052 | **/ | |
4053 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterErrorCode( | |
4054 | OrthancPluginContext* context, | |
4055 | int32_t code, | |
4056 | uint16_t httpStatus, | |
4057 | const char* message) | |
4058 | { | |
4059 | OrthancPluginErrorCode target; | |
4060 | ||
4061 | _OrthancPluginRegisterErrorCode params; | |
4062 | params.target = ⌖ | |
4063 | params.code = code; | |
4064 | params.httpStatus = httpStatus; | |
4065 | params.message = message; | |
4066 | ||
4067 | if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, ¶ms) == OrthancPluginErrorCode_Success) | |
4068 | { | |
4069 | return target; | |
4070 | } | |
4071 | else | |
4072 | { | |
4073 | /* There was an error while assigned the error. Use a generic code. */ | |
4074 | return OrthancPluginErrorCode_Plugin; | |
4075 | } | |
4076 | } | |
4077 | ||
4078 | ||
4079 | ||
4080 | typedef struct | |
4081 | { | |
4082 | uint16_t group; | |
4083 | uint16_t element; | |
4084 | OrthancPluginValueRepresentation vr; | |
4085 | const char* name; | |
4086 | uint32_t minMultiplicity; | |
4087 | uint32_t maxMultiplicity; | |
4088 | } _OrthancPluginRegisterDictionaryTag; | |
4089 | ||
4090 | /** | |
4091 | * @brief Register a new tag into the DICOM dictionary. | |
4092 | * | |
4093 | * This function declares a new tag in the dictionary of DICOM tags | |
4094 | * that are known to Orthanc. This function should be used in the | |
4095 | * OrthancPluginInitialize() callback. | |
4096 | * | |
4097 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4098 | * @param group The group of the tag. | |
4099 | * @param element The element of the tag. | |
4100 | * @param vr The value representation of the tag. | |
4101 | * @param name The nickname of the tag. | |
4102 | * @param minMultiplicity The minimum multiplicity of the tag (must be above 0). | |
4103 | * @param maxMultiplicity The maximum multiplicity of the tag. A value of 0 means | |
4104 | * an arbitrary multiplicity ("<tt>n</tt>"). | |
4105 | * @return 0 if success, other value if error. | |
4106 | * @ingroup Toolbox | |
4107 | **/ | |
4108 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDictionaryTag( | |
4109 | OrthancPluginContext* context, | |
4110 | uint16_t group, | |
4111 | uint16_t element, | |
4112 | OrthancPluginValueRepresentation vr, | |
4113 | const char* name, | |
4114 | uint32_t minMultiplicity, | |
4115 | uint32_t maxMultiplicity) | |
4116 | { | |
4117 | _OrthancPluginRegisterDictionaryTag params; | |
4118 | params.group = group; | |
4119 | params.element = element; | |
4120 | params.vr = vr; | |
4121 | params.name = name; | |
4122 | params.minMultiplicity = minMultiplicity; | |
4123 | params.maxMultiplicity = maxMultiplicity; | |
4124 | ||
4125 | return context->InvokeService(context, _OrthancPluginService_RegisterDictionaryTag, ¶ms); | |
4126 | } | |
4127 | ||
4128 | ||
4129 | ||
4130 | ||
4131 | typedef struct | |
4132 | { | |
4133 | OrthancPluginStorageArea* storageArea; | |
4134 | OrthancPluginResourceType level; | |
4135 | } _OrthancPluginReconstructMainDicomTags; | |
4136 | ||
4137 | /** | |
4138 | * @brief Reconstruct the main DICOM tags. | |
4139 | * | |
4140 | * This function requests the Orthanc core to reconstruct the main | |
4141 | * DICOM tags of all the resources of the given type. This function | |
4142 | * can only be used as a part of the upgrade of a custom database | |
4143 | * back-end | |
4144 | * (cf. OrthancPlugins::IDatabaseBackend::UpgradeDatabase). A | |
4145 | * database transaction will be automatically setup. | |
4146 | * | |
4147 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4148 | * @param storageArea The storage area. | |
4149 | * @param level The type of the resources of interest. | |
4150 | * @return 0 if success, other value if error. | |
4151 | * @ingroup Callbacks | |
4152 | **/ | |
4153 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReconstructMainDicomTags( | |
4154 | OrthancPluginContext* context, | |
4155 | OrthancPluginStorageArea* storageArea, | |
4156 | OrthancPluginResourceType level) | |
4157 | { | |
4158 | _OrthancPluginReconstructMainDicomTags params; | |
4159 | params.level = level; | |
4160 | params.storageArea = storageArea; | |
4161 | ||
4162 | return context->InvokeService(context, _OrthancPluginService_ReconstructMainDicomTags, ¶ms); | |
4163 | } | |
4164 | ||
4165 | ||
4166 | typedef struct | |
4167 | { | |
4168 | char** result; | |
4169 | const char* instanceId; | |
4170 | const void* buffer; | |
4171 | uint32_t size; | |
4172 | OrthancPluginDicomToJsonFormat format; | |
4173 | OrthancPluginDicomToJsonFlags flags; | |
4174 | uint32_t maxStringLength; | |
4175 | } _OrthancPluginDicomToJson; | |
4176 | ||
4177 | ||
4178 | /** | |
4179 | * @brief Format a DICOM memory buffer as a JSON string. | |
4180 | * | |
4181 | * This function takes as input a memory buffer containing a DICOM | |
4182 | * file, and outputs a JSON string representing the tags of this | |
4183 | * DICOM file. | |
4184 | * | |
4185 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4186 | * @param buffer The memory buffer containing the DICOM file. | |
4187 | * @param size The size of the memory buffer. | |
4188 | * @param format The output format. | |
4189 | * @param flags Flags governing the output. | |
4190 | * @param maxStringLength The maximum length of a field. Too long fields will | |
4191 | * be output as "null". The 0 value means no maximum length. | |
4192 | * @return The NULL value if the case of an error, or the JSON | |
4193 | * string. This string must be freed by OrthancPluginFreeString(). | |
4194 | * @ingroup Toolbox | |
4195 | * @see OrthancPluginDicomInstanceToJson | |
4196 | **/ | |
4197 | ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomBufferToJson( | |
4198 | OrthancPluginContext* context, | |
4199 | const void* buffer, | |
4200 | uint32_t size, | |
4201 | OrthancPluginDicomToJsonFormat format, | |
4202 | OrthancPluginDicomToJsonFlags flags, | |
4203 | uint32_t maxStringLength) | |
4204 | { | |
4205 | char* result; | |
4206 | ||
4207 | _OrthancPluginDicomToJson params; | |
4208 | memset(¶ms, 0, sizeof(params)); | |
4209 | params.result = &result; | |
4210 | params.buffer = buffer; | |
4211 | params.size = size; | |
4212 | params.format = format; | |
4213 | params.flags = flags; | |
4214 | params.maxStringLength = maxStringLength; | |
4215 | ||
4216 | if (context->InvokeService(context, _OrthancPluginService_DicomBufferToJson, ¶ms) != OrthancPluginErrorCode_Success) | |
4217 | { | |
4218 | /* Error */ | |
4219 | return NULL; | |
4220 | } | |
4221 | else | |
4222 | { | |
4223 | return result; | |
4224 | } | |
4225 | } | |
4226 | ||
4227 | ||
4228 | /** | |
4229 | * @brief Format a DICOM instance as a JSON string. | |
4230 | * | |
4231 | * This function formats a DICOM instance that is stored in Orthanc, | |
4232 | * and outputs a JSON string representing the tags of this DICOM | |
4233 | * instance. | |
4234 | * | |
4235 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4236 | * @param instanceId The Orthanc identifier of the instance. | |
4237 | * @param format The output format. | |
4238 | * @param flags Flags governing the output. | |
4239 | * @param maxStringLength The maximum length of a field. Too long fields will | |
4240 | * be output as "null". The 0 value means no maximum length. | |
4241 | * @return The NULL value if the case of an error, or the JSON | |
4242 | * string. This string must be freed by OrthancPluginFreeString(). | |
4243 | * @ingroup Toolbox | |
4244 | * @see OrthancPluginDicomInstanceToJson | |
4245 | **/ | |
4246 | ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomInstanceToJson( | |
4247 | OrthancPluginContext* context, | |
4248 | const char* instanceId, | |
4249 | OrthancPluginDicomToJsonFormat format, | |
4250 | OrthancPluginDicomToJsonFlags flags, | |
4251 | uint32_t maxStringLength) | |
4252 | { | |
4253 | char* result; | |
4254 | ||
4255 | _OrthancPluginDicomToJson params; | |
4256 | memset(¶ms, 0, sizeof(params)); | |
4257 | params.result = &result; | |
4258 | params.instanceId = instanceId; | |
4259 | params.format = format; | |
4260 | params.flags = flags; | |
4261 | params.maxStringLength = maxStringLength; | |
4262 | ||
4263 | if (context->InvokeService(context, _OrthancPluginService_DicomInstanceToJson, ¶ms) != OrthancPluginErrorCode_Success) | |
4264 | { | |
4265 | /* Error */ | |
4266 | return NULL; | |
4267 | } | |
4268 | else | |
4269 | { | |
4270 | return result; | |
4271 | } | |
4272 | } | |
4273 | ||
4274 | ||
4275 | typedef struct | |
4276 | { | |
4277 | OrthancPluginMemoryBuffer* target; | |
4278 | const char* uri; | |
4279 | uint32_t headersCount; | |
4280 | const char* const* headersKeys; | |
4281 | const char* const* headersValues; | |
4282 | int32_t afterPlugins; | |
4283 | } _OrthancPluginRestApiGet2; | |
4284 | ||
4285 | /** | |
4286 | * @brief Make a GET call to the Orthanc REST API, with custom HTTP headers. | |
4287 | * | |
4288 | * Make a GET call to the Orthanc REST API with extended | |
4289 | * parameters. The result to the query is stored into a newly | |
4290 | * allocated memory buffer. | |
4291 | * | |
4292 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4293 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4294 | * @param uri The URI in the built-in Orthanc API. | |
4295 | * @param headersCount The number of HTTP headers. | |
4296 | * @param headersKeys Array containing the keys of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4297 | * @param headersValues Array containing the values of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4298 | * @param afterPlugins If 0, the built-in API of Orthanc is used. | |
4299 | * If 1, the API is tainted by the plugins. | |
4300 | * @return 0 if success, or the error code if failure. | |
4301 | * @see OrthancPluginRestApiGet, OrthancPluginRestApiGetAfterPlugins | |
4302 | * @ingroup Orthanc | |
4303 | **/ | |
4304 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet2( | |
4305 | OrthancPluginContext* context, | |
4306 | OrthancPluginMemoryBuffer* target, | |
4307 | const char* uri, | |
4308 | uint32_t headersCount, | |
4309 | const char* const* headersKeys, | |
4310 | const char* const* headersValues, | |
4311 | int32_t afterPlugins) | |
4312 | { | |
4313 | _OrthancPluginRestApiGet2 params; | |
4314 | params.target = target; | |
4315 | params.uri = uri; | |
4316 | params.headersCount = headersCount; | |
4317 | params.headersKeys = headersKeys; | |
4318 | params.headersValues = headersValues; | |
4319 | params.afterPlugins = afterPlugins; | |
4320 | ||
4321 | return context->InvokeService(context, _OrthancPluginService_RestApiGet2, ¶ms); | |
4322 | } | |
4323 | ||
4324 | ||
4325 | ||
4326 | typedef struct | |
4327 | { | |
4328 | OrthancPluginWorklistCallback callback; | |
4329 | } _OrthancPluginWorklistCallback; | |
4330 | ||
4331 | /** | |
4332 | * @brief Register a callback to handle modality worklists requests. | |
4333 | * | |
4334 | * This function registers a callback to handle C-Find SCP requests | |
4335 | * on modality worklists. | |
4336 | * | |
4337 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4338 | * @param callback The callback. | |
4339 | * @return 0 if success, other value if error. | |
4340 | * @ingroup DicomCallbacks | |
4341 | **/ | |
4342 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterWorklistCallback( | |
4343 | OrthancPluginContext* context, | |
4344 | OrthancPluginWorklistCallback callback) | |
4345 | { | |
4346 | _OrthancPluginWorklistCallback params; | |
4347 | params.callback = callback; | |
4348 | ||
4349 | return context->InvokeService(context, _OrthancPluginService_RegisterWorklistCallback, ¶ms); | |
4350 | } | |
4351 | ||
4352 | ||
4353 | ||
4354 | typedef struct | |
4355 | { | |
4356 | OrthancPluginWorklistAnswers* answers; | |
4357 | const OrthancPluginWorklistQuery* query; | |
4358 | const void* dicom; | |
4359 | uint32_t size; | |
4360 | } _OrthancPluginWorklistAnswersOperation; | |
4361 | ||
4362 | /** | |
4363 | * @brief Add one answer to some modality worklist request. | |
4364 | * | |
4365 | * This function adds one worklist (encoded as a DICOM file) to the | |
4366 | * set of answers corresponding to some C-Find SCP request against | |
4367 | * modality worklists. | |
4368 | * | |
4369 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4370 | * @param answers The set of answers. | |
4371 | * @param query The worklist query, as received by the callback. | |
4372 | * @param dicom The worklist to answer, encoded as a DICOM file. | |
4373 | * @param size The size of the DICOM file. | |
4374 | * @return 0 if success, other value if error. | |
4375 | * @ingroup DicomCallbacks | |
4376 | * @see OrthancPluginCreateDicom() | |
4377 | **/ | |
4378 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistAddAnswer( | |
4379 | OrthancPluginContext* context, | |
4380 | OrthancPluginWorklistAnswers* answers, | |
4381 | const OrthancPluginWorklistQuery* query, | |
4382 | const void* dicom, | |
4383 | uint32_t size) | |
4384 | { | |
4385 | _OrthancPluginWorklistAnswersOperation params; | |
4386 | params.answers = answers; | |
4387 | params.query = query; | |
4388 | params.dicom = dicom; | |
4389 | params.size = size; | |
4390 | ||
4391 | return context->InvokeService(context, _OrthancPluginService_WorklistAddAnswer, ¶ms); | |
4392 | } | |
4393 | ||
4394 | ||
4395 | /** | |
4396 | * @brief Mark the set of worklist answers as incomplete. | |
4397 | * | |
4398 | * This function marks as incomplete the set of answers | |
4399 | * corresponding to some C-Find SCP request against modality | |
4400 | * worklists. This must be used if canceling the handling of a | |
4401 | * request when too many answers are to be returned. | |
4402 | * | |
4403 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4404 | * @param answers The set of answers. | |
4405 | * @return 0 if success, other value if error. | |
4406 | * @ingroup DicomCallbacks | |
4407 | **/ | |
4408 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistMarkIncomplete( | |
4409 | OrthancPluginContext* context, | |
4410 | OrthancPluginWorklistAnswers* answers) | |
4411 | { | |
4412 | _OrthancPluginWorklistAnswersOperation params; | |
4413 | params.answers = answers; | |
4414 | params.query = NULL; | |
4415 | params.dicom = NULL; | |
4416 | params.size = 0; | |
4417 | ||
4418 | return context->InvokeService(context, _OrthancPluginService_WorklistMarkIncomplete, ¶ms); | |
4419 | } | |
4420 | ||
4421 | ||
4422 | typedef struct | |
4423 | { | |
4424 | const OrthancPluginWorklistQuery* query; | |
4425 | const void* dicom; | |
4426 | uint32_t size; | |
4427 | int32_t* isMatch; | |
4428 | OrthancPluginMemoryBuffer* target; | |
4429 | } _OrthancPluginWorklistQueryOperation; | |
4430 | ||
4431 | /** | |
4432 | * @brief Test whether a worklist matches the query. | |
4433 | * | |
4434 | * This function checks whether one worklist (encoded as a DICOM | |
4435 | * file) matches the C-Find SCP query against modality | |
4436 | * worklists. This function must be called before adding the | |
4437 | * worklist as an answer through OrthancPluginWorklistAddAnswer(). | |
4438 | * | |
4439 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4440 | * @param query The worklist query, as received by the callback. | |
4441 | * @param dicom The worklist to answer, encoded as a DICOM file. | |
4442 | * @param size The size of the DICOM file. | |
4443 | * @return 1 if the worklist matches the query, 0 otherwise. | |
4444 | * @ingroup DicomCallbacks | |
4445 | **/ | |
4446 | ORTHANC_PLUGIN_INLINE int32_t OrthancPluginWorklistIsMatch( | |
4447 | OrthancPluginContext* context, | |
4448 | const OrthancPluginWorklistQuery* query, | |
4449 | const void* dicom, | |
4450 | uint32_t size) | |
4451 | { | |
4452 | int32_t isMatch = 0; | |
4453 | ||
4454 | _OrthancPluginWorklistQueryOperation params; | |
4455 | params.query = query; | |
4456 | params.dicom = dicom; | |
4457 | params.size = size; | |
4458 | params.isMatch = &isMatch; | |
4459 | params.target = NULL; | |
4460 | ||
4461 | if (context->InvokeService(context, _OrthancPluginService_WorklistIsMatch, ¶ms) == OrthancPluginErrorCode_Success) | |
4462 | { | |
4463 | return isMatch; | |
4464 | } | |
4465 | else | |
4466 | { | |
4467 | /* Error: Assume non-match */ | |
4468 | return 0; | |
4469 | } | |
4470 | } | |
4471 | ||
4472 | ||
4473 | /** | |
4474 | * @brief Retrieve the worklist query as a DICOM file. | |
4475 | * | |
4476 | * This function retrieves the DICOM file that underlies a C-Find | |
4477 | * SCP query against modality worklists. | |
4478 | * | |
4479 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4480 | * @param target Memory buffer where to store the DICOM file. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4481 | * @param query The worklist query, as received by the callback. | |
4482 | * @return 0 if success, other value if error. | |
4483 | * @ingroup DicomCallbacks | |
4484 | **/ | |
4485 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistGetDicomQuery( | |
4486 | OrthancPluginContext* context, | |
4487 | OrthancPluginMemoryBuffer* target, | |
4488 | const OrthancPluginWorklistQuery* query) | |
4489 | { | |
4490 | _OrthancPluginWorklistQueryOperation params; | |
4491 | params.query = query; | |
4492 | params.dicom = NULL; | |
4493 | params.size = 0; | |
4494 | params.isMatch = NULL; | |
4495 | params.target = target; | |
4496 | ||
4497 | return context->InvokeService(context, _OrthancPluginService_WorklistGetDicomQuery, ¶ms); | |
4498 | } | |
4499 | ||
4500 | ||
4501 | /** | |
4502 | * @brief Get the origin of a DICOM file. | |
4503 | * | |
4504 | * This function returns the origin of a DICOM instance that has been received by Orthanc. | |
4505 | * | |
4506 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4507 | * @param instance The instance of interest. | |
4508 | * @return The origin of the instance. | |
4509 | * @ingroup Callbacks | |
4510 | **/ | |
4511 | ORTHANC_PLUGIN_INLINE OrthancPluginInstanceOrigin OrthancPluginGetInstanceOrigin( | |
4512 | OrthancPluginContext* context, | |
4513 | OrthancPluginDicomInstance* instance) | |
4514 | { | |
4515 | OrthancPluginInstanceOrigin origin; | |
4516 | ||
4517 | _OrthancPluginAccessDicomInstance params; | |
4518 | memset(¶ms, 0, sizeof(params)); | |
4519 | params.resultOrigin = &origin; | |
4520 | params.instance = instance; | |
4521 | ||
4522 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, ¶ms) != OrthancPluginErrorCode_Success) | |
4523 | { | |
4524 | /* Error */ | |
4525 | return OrthancPluginInstanceOrigin_Unknown; | |
4526 | } | |
4527 | else | |
4528 | { | |
4529 | return origin; | |
4530 | } | |
4531 | } | |
4532 | ||
4533 | ||
4534 | typedef struct | |
4535 | { | |
4536 | OrthancPluginMemoryBuffer* target; | |
4537 | const char* json; | |
4538 | const OrthancPluginImage* pixelData; | |
4539 | OrthancPluginCreateDicomFlags flags; | |
4540 | } _OrthancPluginCreateDicom; | |
4541 | ||
4542 | /** | |
4543 | * @brief Create a DICOM instance from a JSON string and an image. | |
4544 | * | |
4545 | * This function takes as input a string containing a JSON file | |
4546 | * describing the content of a DICOM instance. As an output, it | |
4547 | * writes the corresponding DICOM instance to a newly allocated | |
4548 | * memory buffer. Additionally, an image to be encoded within the | |
4549 | * DICOM instance can also be provided. | |
4550 | * | |
4551 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4552 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4553 | * @param json The input JSON file. | |
4554 | * @param pixelData The image. Can be NULL, if the pixel data is encoded inside the JSON with the data URI scheme. | |
4555 | * @param flags Flags governing the output. | |
4556 | * @return 0 if success, other value if error. | |
4557 | * @ingroup Toolbox | |
4558 | * @see OrthancPluginDicomBufferToJson | |
4559 | **/ | |
4560 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCreateDicom( | |
4561 | OrthancPluginContext* context, | |
4562 | OrthancPluginMemoryBuffer* target, | |
4563 | const char* json, | |
4564 | const OrthancPluginImage* pixelData, | |
4565 | OrthancPluginCreateDicomFlags flags) | |
4566 | { | |
4567 | _OrthancPluginCreateDicom params; | |
4568 | params.target = target; | |
4569 | params.json = json; | |
4570 | params.pixelData = pixelData; | |
4571 | params.flags = flags; | |
4572 | ||
4573 | return context->InvokeService(context, _OrthancPluginService_CreateDicom, ¶ms); | |
4574 | } | |
4575 | ||
4576 | ||
4577 | typedef struct | |
4578 | { | |
4579 | OrthancPluginDecodeImageCallback callback; | |
4580 | } _OrthancPluginDecodeImageCallback; | |
4581 | ||
4582 | /** | |
4583 | * @brief Register a callback to handle the decoding of DICOM images. | |
4584 | * | |
4585 | * This function registers a custom callback to the decoding of | |
4586 | * DICOM images, replacing the built-in decoder of Orthanc. | |
4587 | * | |
4588 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4589 | * @param callback The callback. | |
4590 | * @return 0 if success, other value if error. | |
4591 | * @ingroup Callbacks | |
4592 | **/ | |
4593 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDecodeImageCallback( | |
4594 | OrthancPluginContext* context, | |
4595 | OrthancPluginDecodeImageCallback callback) | |
4596 | { | |
4597 | _OrthancPluginDecodeImageCallback params; | |
4598 | params.callback = callback; | |
4599 | ||
4600 | return context->InvokeService(context, _OrthancPluginService_RegisterDecodeImageCallback, ¶ms); | |
4601 | } | |
4602 | ||
4603 | ||
4604 | ||
4605 | typedef struct | |
4606 | { | |
4607 | OrthancPluginImage** target; | |
4608 | OrthancPluginPixelFormat format; | |
4609 | uint32_t width; | |
4610 | uint32_t height; | |
4611 | uint32_t pitch; | |
4612 | void* buffer; | |
4613 | const void* constBuffer; | |
4614 | uint32_t bufferSize; | |
4615 | uint32_t frameIndex; | |
4616 | } _OrthancPluginCreateImage; | |
4617 | ||
4618 | ||
4619 | /** | |
4620 | * @brief Create an image. | |
4621 | * | |
4622 | * This function creates an image of given size and format. | |
4623 | * | |
4624 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4625 | * @param format The format of the pixels. | |
4626 | * @param width The width of the image. | |
4627 | * @param height The height of the image. | |
4628 | * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). | |
4629 | * @ingroup Images | |
4630 | **/ | |
4631 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImage( | |
4632 | OrthancPluginContext* context, | |
4633 | OrthancPluginPixelFormat format, | |
4634 | uint32_t width, | |
4635 | uint32_t height) | |
4636 | { | |
4637 | OrthancPluginImage* target = NULL; | |
4638 | ||
4639 | _OrthancPluginCreateImage params; | |
4640 | memset(¶ms, 0, sizeof(params)); | |
4641 | params.target = ⌖ | |
4642 | params.format = format; | |
4643 | params.width = width; | |
4644 | params.height = height; | |
4645 | ||
4646 | if (context->InvokeService(context, _OrthancPluginService_CreateImage, ¶ms) != OrthancPluginErrorCode_Success) | |
4647 | { | |
4648 | return NULL; | |
4649 | } | |
4650 | else | |
4651 | { | |
4652 | return target; | |
4653 | } | |
4654 | } | |
4655 | ||
4656 | ||
4657 | /** | |
4658 | * @brief Create an image pointing to a memory buffer. | |
4659 | * | |
4660 | * This function creates an image whose content points to a memory | |
4661 | * buffer managed by the plugin. Note that the buffer is directly | |
4662 | * accessed, no memory is allocated and no data is copied. | |
4663 | * | |
4664 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4665 | * @param format The format of the pixels. | |
4666 | * @param width The width of the image. | |
4667 | * @param height The height of the image. | |
4668 | * @param pitch The pitch of the image (i.e. the number of bytes | |
4669 | * between 2 successive lines of the image in the memory buffer). | |
4670 | * @param buffer The memory buffer. | |
4671 | * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). | |
4672 | * @ingroup Images | |
4673 | **/ | |
4674 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImageAccessor( | |
4675 | OrthancPluginContext* context, | |
4676 | OrthancPluginPixelFormat format, | |
4677 | uint32_t width, | |
4678 | uint32_t height, | |
4679 | uint32_t pitch, | |
4680 | void* buffer) | |
4681 | { | |
4682 | OrthancPluginImage* target = NULL; | |
4683 | ||
4684 | _OrthancPluginCreateImage params; | |
4685 | memset(¶ms, 0, sizeof(params)); | |
4686 | params.target = ⌖ | |
4687 | params.format = format; | |
4688 | params.width = width; | |
4689 | params.height = height; | |
4690 | params.pitch = pitch; | |
4691 | params.buffer = buffer; | |
4692 | ||
4693 | if (context->InvokeService(context, _OrthancPluginService_CreateImageAccessor, ¶ms) != OrthancPluginErrorCode_Success) | |
4694 | { | |
4695 | return NULL; | |
4696 | } | |
4697 | else | |
4698 | { | |
4699 | return target; | |
4700 | } | |
4701 | } | |
4702 | ||
4703 | ||
4704 | ||
4705 | /** | |
4706 | * @brief Decode one frame from a DICOM instance. | |
4707 | * | |
4708 | * This function decodes one frame of a DICOM image that is stored | |
4709 | * in a memory buffer. This function will give the same result as | |
4710 | * OrthancPluginUncompressImage() for single-frame DICOM images. | |
4711 | * | |
4712 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4713 | * @param buffer Pointer to a memory buffer containing the DICOM image. | |
4714 | * @param bufferSize Size of the memory buffer containing the DICOM image. | |
4715 | * @param frameIndex The index of the frame of interest in a multi-frame image. | |
4716 | * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). | |
4717 | * @ingroup Images | |
4718 | **/ | |
4719 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginDecodeDicomImage( | |
4720 | OrthancPluginContext* context, | |
4721 | const void* buffer, | |
4722 | uint32_t bufferSize, | |
4723 | uint32_t frameIndex) | |
4724 | { | |
4725 | OrthancPluginImage* target = NULL; | |
4726 | ||
4727 | _OrthancPluginCreateImage params; | |
4728 | memset(¶ms, 0, sizeof(params)); | |
4729 | params.target = ⌖ | |
4730 | params.constBuffer = buffer; | |
4731 | params.bufferSize = bufferSize; | |
4732 | params.frameIndex = frameIndex; | |
4733 | ||
4734 | if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, ¶ms) != OrthancPluginErrorCode_Success) | |
4735 | { | |
4736 | return NULL; | |
4737 | } | |
4738 | else | |
4739 | { | |
4740 | return target; | |
4741 | } | |
4742 | } | |
4743 | ||
4744 | ||
4745 | ||
4746 | typedef struct | |
4747 | { | |
4748 | char** result; | |
4749 | const void* buffer; | |
4750 | uint32_t size; | |
4751 | } _OrthancPluginComputeHash; | |
4752 | ||
4753 | /** | |
4754 | * @brief Compute an MD5 hash. | |
4755 | * | |
4756 | * This functions computes the MD5 cryptographic hash of the given memory buffer. | |
4757 | * | |
4758 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4759 | * @param buffer The source memory buffer. | |
4760 | * @param size The size in bytes of the source buffer. | |
4761 | * @return The NULL value in case of error, or a string containing the cryptographic hash. | |
4762 | * This string must be freed by OrthancPluginFreeString(). | |
4763 | * @ingroup Toolbox | |
4764 | **/ | |
4765 | ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeMd5( | |
4766 | OrthancPluginContext* context, | |
4767 | const void* buffer, | |
4768 | uint32_t size) | |
4769 | { | |
4770 | char* result; | |
4771 | ||
4772 | _OrthancPluginComputeHash params; | |
4773 | params.result = &result; | |
4774 | params.buffer = buffer; | |
4775 | params.size = size; | |
4776 | ||
4777 | if (context->InvokeService(context, _OrthancPluginService_ComputeMd5, ¶ms) != OrthancPluginErrorCode_Success) | |
4778 | { | |
4779 | /* Error */ | |
4780 | return NULL; | |
4781 | } | |
4782 | else | |
4783 | { | |
4784 | return result; | |
4785 | } | |
4786 | } | |
4787 | ||
4788 | ||
4789 | /** | |
4790 | * @brief Compute a SHA-1 hash. | |
4791 | * | |
4792 | * This functions computes the SHA-1 cryptographic hash of the given memory buffer. | |
4793 | * | |
4794 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4795 | * @param buffer The source memory buffer. | |
4796 | * @param size The size in bytes of the source buffer. | |
4797 | * @return The NULL value in case of error, or a string containing the cryptographic hash. | |
4798 | * This string must be freed by OrthancPluginFreeString(). | |
4799 | * @ingroup Toolbox | |
4800 | **/ | |
4801 | ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeSha1( | |
4802 | OrthancPluginContext* context, | |
4803 | const void* buffer, | |
4804 | uint32_t size) | |
4805 | { | |
4806 | char* result; | |
4807 | ||
4808 | _OrthancPluginComputeHash params; | |
4809 | params.result = &result; | |
4810 | params.buffer = buffer; | |
4811 | params.size = size; | |
4812 | ||
4813 | if (context->InvokeService(context, _OrthancPluginService_ComputeSha1, ¶ms) != OrthancPluginErrorCode_Success) | |
4814 | { | |
4815 | /* Error */ | |
4816 | return NULL; | |
4817 | } | |
4818 | else | |
4819 | { | |
4820 | return result; | |
4821 | } | |
4822 | } | |
4823 | ||
4824 | ||
4825 | ||
4826 | typedef struct | |
4827 | { | |
4828 | OrthancPluginDictionaryEntry* target; | |
4829 | const char* name; | |
4830 | } _OrthancPluginLookupDictionary; | |
4831 | ||
4832 | /** | |
4833 | * @brief Get information about the given DICOM tag. | |
4834 | * | |
4835 | * This functions makes a lookup in the dictionary of DICOM tags | |
4836 | * that are known to Orthanc, and returns information about this | |
4837 | * tag. The tag can be specified using its human-readable name | |
4838 | * (e.g. "PatientName") or a set of two hexadecimal numbers | |
4839 | * (e.g. "0010-0020"). | |
4840 | * | |
4841 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4842 | * @param target Where to store the information about the tag. | |
4843 | * @param name The name of the DICOM tag. | |
4844 | * @return 0 if success, other value if error. | |
4845 | * @ingroup Toolbox | |
4846 | **/ | |
4847 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginLookupDictionary( | |
4848 | OrthancPluginContext* context, | |
4849 | OrthancPluginDictionaryEntry* target, | |
4850 | const char* name) | |
4851 | { | |
4852 | _OrthancPluginLookupDictionary params; | |
4853 | params.target = target; | |
4854 | params.name = name; | |
4855 | return context->InvokeService(context, _OrthancPluginService_LookupDictionary, ¶ms); | |
4856 | } | |
4857 | ||
4858 | ||
4859 | ||
4860 | typedef struct | |
4861 | { | |
4862 | OrthancPluginRestOutput* output; | |
4863 | const char* answer; | |
4864 | uint32_t answerSize; | |
4865 | uint32_t headersCount; | |
4866 | const char* const* headersKeys; | |
4867 | const char* const* headersValues; | |
4868 | } _OrthancPluginSendMultipartItem2; | |
4869 | ||
4870 | /** | |
4871 | * @brief Send an item as a part of some HTTP multipart answer, with custom headers. | |
4872 | * | |
4873 | * This function sends an item as a part of some HTTP multipart | |
4874 | * answer that was initiated by OrthancPluginStartMultipartAnswer(). In addition to | |
4875 | * OrthancPluginSendMultipartItem(), this function will set HTTP header associated | |
4876 | * with the item. | |
4877 | * | |
4878 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4879 | * @param output The HTTP connection to the client application. | |
4880 | * @param answer Pointer to the memory buffer containing the item. | |
4881 | * @param answerSize Number of bytes of the item. | |
4882 | * @param headersCount The number of HTTP headers. | |
4883 | * @param headersKeys Array containing the keys of the HTTP headers. | |
4884 | * @param headersValues Array containing the values of the HTTP headers. | |
4885 | * @return 0 if success, or the error code if failure (this notably happens | |
4886 | * if the connection is closed by the client). | |
4887 | * @see OrthancPluginSendMultipartItem() | |
4888 | * @ingroup REST | |
4889 | **/ | |
4890 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem2( | |
4891 | OrthancPluginContext* context, | |
4892 | OrthancPluginRestOutput* output, | |
4893 | const char* answer, | |
4894 | uint32_t answerSize, | |
4895 | uint32_t headersCount, | |
4896 | const char* const* headersKeys, | |
4897 | const char* const* headersValues) | |
4898 | { | |
4899 | _OrthancPluginSendMultipartItem2 params; | |
4900 | params.output = output; | |
4901 | params.answer = answer; | |
4902 | params.answerSize = answerSize; | |
4903 | params.headersCount = headersCount; | |
4904 | params.headersKeys = headersKeys; | |
4905 | params.headersValues = headersValues; | |
4906 | ||
4907 | return context->InvokeService(context, _OrthancPluginService_SendMultipartItem2, ¶ms); | |
4908 | } | |
4909 | ||
4910 | ||
4911 | typedef struct | |
4912 | { | |
4913 | OrthancPluginIncomingHttpRequestFilter callback; | |
4914 | } _OrthancPluginIncomingHttpRequestFilter; | |
4915 | ||
4916 | /** | |
4917 | * @brief Register a callback to filter incoming HTTP requests. | |
4918 | * | |
4919 | * This function registers a custom callback to filter incoming HTTP/REST | |
4920 | * requests received by the HTTP server of Orthanc. | |
4921 | * | |
4922 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4923 | * @param callback The callback. | |
4924 | * @return 0 if success, other value if error. | |
4925 | * @ingroup Callbacks | |
4926 | **/ | |
4927 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingHttpRequestFilter( | |
4928 | OrthancPluginContext* context, | |
4929 | OrthancPluginIncomingHttpRequestFilter callback) | |
4930 | { | |
4931 | _OrthancPluginIncomingHttpRequestFilter params; | |
4932 | params.callback = callback; | |
4933 | ||
4934 | return context->InvokeService(context, _OrthancPluginService_RegisterIncomingHttpRequestFilter, ¶ms); | |
4935 | } | |
4936 | ||
4937 | ||
4938 | ||
4939 | typedef struct | |
4940 | { | |
4941 | OrthancPluginMemoryBuffer* answerBody; | |
4942 | OrthancPluginMemoryBuffer* answerHeaders; | |
4943 | uint16_t* httpStatus; | |
4944 | OrthancPluginHttpMethod method; | |
4945 | const char* url; | |
4946 | uint32_t headersCount; | |
4947 | const char* const* headersKeys; | |
4948 | const char* const* headersValues; | |
4949 | const char* body; | |
4950 | uint32_t bodySize; | |
4951 | const char* username; | |
4952 | const char* password; | |
4953 | uint32_t timeout; | |
4954 | const char* certificateFile; | |
4955 | const char* certificateKeyFile; | |
4956 | const char* certificateKeyPassword; | |
4957 | uint8_t pkcs11; | |
4958 | } _OrthancPluginCallHttpClient2; | |
4959 | ||
4960 | ||
4961 | ||
4962 | /** | |
4963 | * @brief Issue a HTTP call with full flexibility. | |
4964 | * | |
4965 | * Make a HTTP call to the given URL. The result to the query is | |
4966 | * stored into a newly allocated memory buffer. The HTTP request | |
4967 | * will be done accordingly to the global configuration of Orthanc | |
4968 | * (in particular, the options "HttpProxy", "HttpTimeout", | |
4969 | * "HttpsVerifyPeers", "HttpsCACertificates", and "Pkcs11" will be | |
4970 | * taken into account). | |
4971 | * | |
4972 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4973 | * @param answerBody The target memory buffer (out argument). | |
4974 | * It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4975 | * @param answerHeaders The target memory buffer for the HTTP headers in the answers (out argument). | |
4976 | * The answer headers are formatted as a JSON object (associative array). | |
4977 | * The buffer must be freed with OrthancPluginFreeMemoryBuffer(). | |
4978 | * This argument can be set to NULL if the plugin has no interest in the HTTP headers. | |
4979 | * @param httpStatus The HTTP status after the execution of the request (out argument). | |
4980 | * @param method HTTP method to be used. | |
4981 | * @param url The URL of interest. | |
4982 | * @param headersCount The number of HTTP headers. | |
4983 | * @param headersKeys Array containing the keys of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4984 | * @param headersValues Array containing the values of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4985 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
4986 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
4987 | * @param body The body of the POST request. | |
4988 | * @param bodySize The size of the body. | |
4989 | * @param timeout Timeout in seconds (0 for default timeout). | |
4990 | * @param certificateFile Path to the client certificate for HTTPS, in PEM format | |
4991 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4992 | * @param certificateKeyFile Path to the key of the client certificate for HTTPS, in PEM format | |
4993 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4994 | * @param certificateKeyPassword Password to unlock the key of the client certificate | |
4995 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4996 | * @param pkcs11 Enable PKCS#11 client authentication for hardware security modules and smart cards. | |
4997 | * @return 0 if success, or the error code if failure. | |
4998 | **/ | |
4999 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpClient( | |
5000 | OrthancPluginContext* context, | |
5001 | OrthancPluginMemoryBuffer* answerBody, | |
5002 | OrthancPluginMemoryBuffer* answerHeaders, | |
5003 | uint16_t* httpStatus, | |
5004 | OrthancPluginHttpMethod method, | |
5005 | const char* url, | |
5006 | uint32_t headersCount, | |
5007 | const char* const* headersKeys, | |
5008 | const char* const* headersValues, | |
5009 | const char* body, | |
5010 | uint32_t bodySize, | |
5011 | const char* username, | |
5012 | const char* password, | |
5013 | uint32_t timeout, | |
5014 | const char* certificateFile, | |
5015 | const char* certificateKeyFile, | |
5016 | const char* certificateKeyPassword, | |
5017 | uint8_t pkcs11) | |
5018 | { | |
5019 | _OrthancPluginCallHttpClient2 params; | |
5020 | memset(¶ms, 0, sizeof(params)); | |
5021 | ||
5022 | params.answerBody = answerBody; | |
5023 | params.answerHeaders = answerHeaders; | |
5024 | params.httpStatus = httpStatus; | |
5025 | params.method = method; | |
5026 | params.url = url; | |
5027 | params.headersCount = headersCount; | |
5028 | params.headersKeys = headersKeys; | |
5029 | params.headersValues = headersValues; | |
5030 | params.body = body; | |
5031 | params.bodySize = bodySize; | |
5032 | params.username = username; | |
5033 | params.password = password; | |
5034 | params.timeout = timeout; | |
5035 | params.certificateFile = certificateFile; | |
5036 | params.certificateKeyFile = certificateKeyFile; | |
5037 | params.certificateKeyPassword = certificateKeyPassword; | |
5038 | params.pkcs11 = pkcs11; | |
5039 | ||
5040 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient2, ¶ms); | |
5041 | } | |
5042 | ||
5043 | ||
5044 | /** | |
5045 | * @brief Generate an UUID. | |
5046 | * | |
5047 | * Generate a random GUID/UUID (globally unique identifier). | |
5048 | * | |
5049 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5050 | * @return NULL in the case of an error, or a newly allocated string | |
5051 | * containing the UUID. This string must be freed by OrthancPluginFreeString(). | |
5052 | * @ingroup Toolbox | |
5053 | **/ | |
5054 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGenerateUuid( | |
5055 | OrthancPluginContext* context) | |
5056 | { | |
5057 | char* result; | |
5058 | ||
5059 | _OrthancPluginRetrieveDynamicString params; | |
5060 | params.result = &result; | |
5061 | params.argument = NULL; | |
5062 | ||
5063 | if (context->InvokeService(context, _OrthancPluginService_GenerateUuid, ¶ms) != OrthancPluginErrorCode_Success) | |
5064 | { | |
5065 | /* Error */ | |
5066 | return NULL; | |
5067 | } | |
5068 | else | |
5069 | { | |
5070 | return result; | |
5071 | } | |
5072 | } | |
5073 | ||
5074 | ||
5075 | ||
5076 | ||
5077 | typedef struct | |
5078 | { | |
5079 | OrthancPluginFindCallback callback; | |
5080 | } _OrthancPluginFindCallback; | |
5081 | ||
5082 | /** | |
5083 | * @brief Register a callback to handle C-Find requests. | |
5084 | * | |
5085 | * This function registers a callback to handle C-Find SCP requests | |
5086 | * that are not related to modality worklists. | |
5087 | * | |
5088 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5089 | * @param callback The callback. | |
5090 | * @return 0 if success, other value if error. | |
5091 | * @ingroup DicomCallbacks | |
5092 | **/ | |
5093 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterFindCallback( | |
5094 | OrthancPluginContext* context, | |
5095 | OrthancPluginFindCallback callback) | |
5096 | { | |
5097 | _OrthancPluginFindCallback params; | |
5098 | params.callback = callback; | |
5099 | ||
5100 | return context->InvokeService(context, _OrthancPluginService_RegisterFindCallback, ¶ms); | |
5101 | } | |
5102 | ||
5103 | ||
5104 | typedef struct | |
5105 | { | |
5106 | OrthancPluginFindAnswers *answers; | |
5107 | const OrthancPluginFindQuery *query; | |
5108 | const void *dicom; | |
5109 | uint32_t size; | |
5110 | uint32_t index; | |
5111 | uint32_t *resultUint32; | |
5112 | uint16_t *resultGroup; | |
5113 | uint16_t *resultElement; | |
5114 | char **resultString; | |
5115 | } _OrthancPluginFindOperation; | |
5116 | ||
5117 | /** | |
5118 | * @brief Add one answer to some C-Find request. | |
5119 | * | |
5120 | * This function adds one answer (encoded as a DICOM file) to the | |
5121 | * set of answers corresponding to some C-Find SCP request that is | |
5122 | * not related to modality worklists. | |
5123 | * | |
5124 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5125 | * @param answers The set of answers. | |
5126 | * @param dicom The answer to be added, encoded as a DICOM file. | |
5127 | * @param size The size of the DICOM file. | |
5128 | * @return 0 if success, other value if error. | |
5129 | * @ingroup DicomCallbacks | |
5130 | * @see OrthancPluginCreateDicom() | |
5131 | **/ | |
5132 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginFindAddAnswer( | |
5133 | OrthancPluginContext* context, | |
5134 | OrthancPluginFindAnswers* answers, | |
5135 | const void* dicom, | |
5136 | uint32_t size) | |
5137 | { | |
5138 | _OrthancPluginFindOperation params; | |
5139 | memset(¶ms, 0, sizeof(params)); | |
5140 | params.answers = answers; | |
5141 | params.dicom = dicom; | |
5142 | params.size = size; | |
5143 | ||
5144 | return context->InvokeService(context, _OrthancPluginService_FindAddAnswer, ¶ms); | |
5145 | } | |
5146 | ||
5147 | ||
5148 | /** | |
5149 | * @brief Mark the set of C-Find answers as incomplete. | |
5150 | * | |
5151 | * This function marks as incomplete the set of answers | |
5152 | * corresponding to some C-Find SCP request that is not related to | |
5153 | * modality worklists. This must be used if canceling the handling | |
5154 | * of a request when too many answers are to be returned. | |
5155 | * | |
5156 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5157 | * @param answers The set of answers. | |
5158 | * @return 0 if success, other value if error. | |
5159 | * @ingroup DicomCallbacks | |
5160 | **/ | |
5161 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginFindMarkIncomplete( | |
5162 | OrthancPluginContext* context, | |
5163 | OrthancPluginFindAnswers* answers) | |
5164 | { | |
5165 | _OrthancPluginFindOperation params; | |
5166 | memset(¶ms, 0, sizeof(params)); | |
5167 | params.answers = answers; | |
5168 | ||
5169 | return context->InvokeService(context, _OrthancPluginService_FindMarkIncomplete, ¶ms); | |
5170 | } | |
5171 | ||
5172 | ||
5173 | ||
5174 | /** | |
5175 | * @brief Get the number of tags in a C-Find query. | |
5176 | * | |
5177 | * This function returns the number of tags that are contained in | |
5178 | * the given C-Find query. | |
5179 | * | |
5180 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5181 | * @param query The C-Find query. | |
5182 | * @return The number of tags. | |
5183 | * @ingroup DicomCallbacks | |
5184 | **/ | |
5185 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFindQuerySize( | |
5186 | OrthancPluginContext* context, | |
5187 | const OrthancPluginFindQuery* query) | |
5188 | { | |
5189 | uint32_t count = 0; | |
5190 | ||
5191 | _OrthancPluginFindOperation params; | |
5192 | memset(¶ms, 0, sizeof(params)); | |
5193 | params.query = query; | |
5194 | params.resultUint32 = &count; | |
5195 | ||
5196 | if (context->InvokeService(context, _OrthancPluginService_GetFindQuerySize, ¶ms) != OrthancPluginErrorCode_Success) | |
5197 | { | |
5198 | /* Error */ | |
5199 | return 0; | |
5200 | } | |
5201 | else | |
5202 | { | |
5203 | return count; | |
5204 | } | |
5205 | } | |
5206 | ||
5207 | ||
5208 | /** | |
5209 | * @brief Get one tag in a C-Find query. | |
5210 | * | |
5211 | * This function returns the group and the element of one DICOM tag | |
5212 | * in the given C-Find query. | |
5213 | * | |
5214 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5215 | * @param group The group of the tag (output). | |
5216 | * @param element The element of the tag (output). | |
5217 | * @param query The C-Find query. | |
5218 | * @param index The index of the tag of interest. | |
5219 | * @return 0 if success, other value if error. | |
5220 | * @ingroup DicomCallbacks | |
5221 | **/ | |
5222 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetFindQueryTag( | |
5223 | OrthancPluginContext* context, | |
5224 | uint16_t* group, | |
5225 | uint16_t* element, | |
5226 | const OrthancPluginFindQuery* query, | |
5227 | uint32_t index) | |
5228 | { | |
5229 | _OrthancPluginFindOperation params; | |
5230 | memset(¶ms, 0, sizeof(params)); | |
5231 | params.query = query; | |
5232 | params.index = index; | |
5233 | params.resultGroup = group; | |
5234 | params.resultElement = element; | |
5235 | ||
5236 | return context->InvokeService(context, _OrthancPluginService_GetFindQueryTag, ¶ms); | |
5237 | } | |
5238 | ||
5239 | ||
5240 | /** | |
5241 | * @brief Get the symbolic name of one tag in a C-Find query. | |
5242 | * | |
5243 | * This function returns the symbolic name of one DICOM tag in the | |
5244 | * given C-Find query. | |
5245 | * | |
5246 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5247 | * @param query The C-Find query. | |
5248 | * @param index The index of the tag of interest. | |
5249 | * @return The NULL value in case of error, or a string containing the name of the tag. | |
5250 | * @return 0 if success, other value if error. | |
5251 | * @ingroup DicomCallbacks | |
5252 | **/ | |
5253 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetFindQueryTagName( | |
5254 | OrthancPluginContext* context, | |
5255 | const OrthancPluginFindQuery* query, | |
5256 | uint32_t index) | |
5257 | { | |
5258 | char* result; | |
5259 | ||
5260 | _OrthancPluginFindOperation params; | |
5261 | memset(¶ms, 0, sizeof(params)); | |
5262 | params.query = query; | |
5263 | params.index = index; | |
5264 | params.resultString = &result; | |
5265 | ||
5266 | if (context->InvokeService(context, _OrthancPluginService_GetFindQueryTagName, ¶ms) != OrthancPluginErrorCode_Success) | |
5267 | { | |
5268 | /* Error */ | |
5269 | return NULL; | |
5270 | } | |
5271 | else | |
5272 | { | |
5273 | return result; | |
5274 | } | |
5275 | } | |
5276 | ||
5277 | ||
5278 | /** | |
5279 | * @brief Get the value associated with one tag in a C-Find query. | |
5280 | * | |
5281 | * This function returns the value associated with one tag in the | |
5282 | * given C-Find query. | |
5283 | * | |
5284 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5285 | * @param query The C-Find query. | |
5286 | * @param index The index of the tag of interest. | |
5287 | * @return The NULL value in case of error, or a string containing the value of the tag. | |
5288 | * @return 0 if success, other value if error. | |
5289 | * @ingroup DicomCallbacks | |
5290 | **/ | |
5291 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetFindQueryValue( | |
5292 | OrthancPluginContext* context, | |
5293 | const OrthancPluginFindQuery* query, | |
5294 | uint32_t index) | |
5295 | { | |
5296 | char* result; | |
5297 | ||
5298 | _OrthancPluginFindOperation params; | |
5299 | memset(¶ms, 0, sizeof(params)); | |
5300 | params.query = query; | |
5301 | params.index = index; | |
5302 | params.resultString = &result; | |
5303 | ||
5304 | if (context->InvokeService(context, _OrthancPluginService_GetFindQueryValue, ¶ms) != OrthancPluginErrorCode_Success) | |
5305 | { | |
5306 | /* Error */ | |
5307 | return NULL; | |
5308 | } | |
5309 | else | |
5310 | { | |
5311 | return result; | |
5312 | } | |
5313 | } | |
5314 | ||
5315 | ||
5316 | ||
5317 | ||
5318 | typedef struct | |
5319 | { | |
5320 | OrthancPluginMoveCallback callback; | |
5321 | OrthancPluginGetMoveSize getMoveSize; | |
5322 | OrthancPluginApplyMove applyMove; | |
5323 | OrthancPluginFreeMove freeMove; | |
5324 | } _OrthancPluginMoveCallback; | |
5325 | ||
5326 | /** | |
5327 | * @brief Register a callback to handle C-Move requests. | |
5328 | * | |
5329 | * This function registers a callback to handle C-Move SCP requests. | |
5330 | * | |
5331 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5332 | * @param callback The main callback. | |
5333 | * @param getMoveSize Callback to read the number of C-Move suboperations. | |
5334 | * @param applyMove Callback to apply one C-Move suboperations. | |
5335 | * @param freeMove Callback to free the C-Move driver. | |
5336 | * @return 0 if success, other value if error. | |
5337 | * @ingroup DicomCallbacks | |
5338 | **/ | |
5339 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterMoveCallback( | |
5340 | OrthancPluginContext* context, | |
5341 | OrthancPluginMoveCallback callback, | |
5342 | OrthancPluginGetMoveSize getMoveSize, | |
5343 | OrthancPluginApplyMove applyMove, | |
5344 | OrthancPluginFreeMove freeMove) | |
5345 | { | |
5346 | _OrthancPluginMoveCallback params; | |
5347 | params.callback = callback; | |
5348 | params.getMoveSize = getMoveSize; | |
5349 | params.applyMove = applyMove; | |
5350 | params.freeMove = freeMove; | |
5351 | ||
5352 | return context->InvokeService(context, _OrthancPluginService_RegisterMoveCallback, ¶ms); | |
5353 | } | |
5354 | ||
5355 | ||
5356 | ||
5357 | ||
5358 | #ifdef __cplusplus | |
5359 | } | |
5360 | #endif | |
5361 | ||
5362 | ||
5363 | /** @} */ | |
5364 |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
27 | 27 | |
28 | 28 | #include "Plugin.h" |
29 | 29 | #include "DicomWebServers.h" |
30 | #include "../Orthanc/Core/Toolbox.h" | |
30 | ||
31 | #include <Core/Toolbox.h> | |
31 | 32 | |
32 | 33 | namespace OrthancPlugins |
33 | 34 | { |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
20 | 20 | |
21 | 21 | #pragma once |
22 | 22 | |
23 | #include "../Orthanc/Core/Enumerations.h" | |
23 | #include <Core/Enumerations.h> | |
24 | 24 | |
25 | 25 | #include <orthanc/OrthancCPlugin.h> |
26 | 26 | #include <json/value.h> |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
23 | 23 | #include "Plugin.h" |
24 | 24 | #include "ChunkedBuffer.h" |
25 | 25 | |
26 | #include "../Orthanc/Core/Toolbox.h" | |
26 | #include <Core/Toolbox.h> | |
27 | 27 | |
28 | 28 | #include <gdcmDictEntry.h> |
29 | 29 | #include <gdcmStringFilter.h> |
116 | 116 | } |
117 | 117 | |
118 | 118 | |
119 | template <int T> | |
120 | static void ConvertNumberTag(std::string& target, | |
121 | const gdcm::DataElement& source) | |
122 | { | |
123 | if (source.IsEmpty()) | |
124 | { | |
125 | target.clear(); | |
126 | } | |
127 | else | |
128 | { | |
129 | typename gdcm::Element<T, gdcm::VM::VM1_n> element; | |
130 | ||
131 | element.Set(source.GetValue()); | |
132 | ||
133 | for (unsigned int i = 0; i < element.GetLength(); i++) | |
134 | { | |
135 | if (i != 0) | |
136 | { | |
137 | target += "\\"; | |
138 | } | |
139 | ||
140 | target = boost::lexical_cast<std::string>(element.GetValue()); | |
141 | } | |
142 | } | |
143 | } | |
144 | ||
145 | ||
119 | 146 | static bool ConvertDicomStringToUtf8(std::string& result, |
120 | 147 | const gdcm::Dict& dictionary, |
121 | const gdcm::File* file, | |
122 | 148 | const gdcm::DataElement& element, |
123 | 149 | const Orthanc::Encoding sourceEncoding) |
124 | 150 | { |
128 | 154 | return false; |
129 | 155 | } |
130 | 156 | |
131 | if (file != NULL) | |
132 | { | |
133 | bool isSequence; | |
134 | std::string vr = GetVRName(isSequence, dictionary, element); | |
135 | if (!isSequence && ( | |
136 | vr == "FL" || | |
137 | vr == "FD" || | |
138 | vr == "SL" || | |
139 | vr == "SS" || | |
140 | vr == "UL" || | |
141 | vr == "US" | |
142 | )) | |
143 | { | |
144 | gdcm::StringFilter f; | |
145 | f.SetFile(*file); | |
146 | result = f.ToString(element.GetTag()); | |
157 | bool isSequence; | |
158 | std::string vr = GetVRName(isSequence, dictionary, element); | |
159 | ||
160 | if (!isSequence) | |
161 | { | |
162 | if (vr == "FL") | |
163 | { | |
164 | ConvertNumberTag<gdcm::VR::FL>(result, element); | |
165 | return true; | |
166 | } | |
167 | else if (vr == "FD") | |
168 | { | |
169 | ConvertNumberTag<gdcm::VR::FD>(result, element); | |
170 | return true; | |
171 | } | |
172 | else if (vr == "SL") | |
173 | { | |
174 | ConvertNumberTag<gdcm::VR::SL>(result, element); | |
175 | return true; | |
176 | } | |
177 | else if (vr == "SS") | |
178 | { | |
179 | ConvertNumberTag<gdcm::VR::SS>(result, element); | |
180 | return true; | |
181 | } | |
182 | else if (vr == "UL") | |
183 | { | |
184 | ConvertNumberTag<gdcm::VR::UL>(result, element); | |
185 | return true; | |
186 | } | |
187 | else if (vr == "US") | |
188 | { | |
189 | ConvertNumberTag<gdcm::VR::US>(result, element); | |
147 | 190 | return true; |
148 | 191 | } |
149 | 192 | } |
258 | 301 | |
259 | 302 | const gdcm::DataElement& element = GetDataSet().GetDataElement(tag); |
260 | 303 | |
261 | if (!ConvertDicomStringToUtf8(result, dictionary, &GetFile(), element, GetEncoding())) | |
304 | if (!ConvertDicomStringToUtf8(result, dictionary, element, GetEncoding())) | |
262 | 305 | { |
263 | 306 | return false; |
264 | 307 | } |
407 | 450 | |
408 | 451 | static void DicomToXmlInternal(pugi::xml_node& target, |
409 | 452 | const gdcm::Dict& dictionary, |
410 | const gdcm::File* file, | |
411 | 453 | const gdcm::DataSet& dicom, |
412 | 454 | const Orthanc::Encoding sourceEncoding, |
413 | 455 | const std::string& bulkUri) |
458 | 500 | childUri = bulkUri + std::string(path) + "/" + number + "/"; |
459 | 501 | } |
460 | 502 | |
461 | DicomToXmlInternal(item, dictionary, file, seq->GetItem(i).GetNestedDataSet(), sourceEncoding, childUri); | |
503 | DicomToXmlInternal(item, dictionary, seq->GetItem(i).GetNestedDataSet(), sourceEncoding, childUri); | |
462 | 504 | } |
463 | 505 | } |
464 | 506 | } |
479 | 521 | value.append_attribute("number").set_value("1"); |
480 | 522 | |
481 | 523 | std::string tmp; |
482 | if (ConvertDicomStringToUtf8(tmp, dictionary, file, *it, sourceEncoding)) | |
524 | if (ConvertDicomStringToUtf8(tmp, dictionary, *it, sourceEncoding)) | |
483 | 525 | { |
484 | 526 | value.append_child(pugi::node_pcdata).set_value(tmp.c_str()); |
485 | 527 | } |
494 | 536 | |
495 | 537 | static void DicomToXml(pugi::xml_document& target, |
496 | 538 | const gdcm::Dict& dictionary, |
497 | const gdcm::File* file, | |
498 | 539 | const gdcm::DataSet& dicom, |
499 | 540 | const std::string& bulkUriRoot) |
500 | 541 | { |
504 | 545 | root.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance"); |
505 | 546 | |
506 | 547 | Orthanc::Encoding encoding = DetectEncoding(dicom); |
507 | DicomToXmlInternal(root, dictionary, file, dicom, encoding, bulkUriRoot); | |
548 | DicomToXmlInternal(root, dictionary, dicom, encoding, bulkUriRoot); | |
508 | 549 | |
509 | 550 | pugi::xml_node decl = target.prepend_child(pugi::node_declaration); |
510 | 551 | decl.append_attribute("version").set_value("1.0"); |
514 | 555 | |
515 | 556 | static void DicomToJsonInternal(Json::Value& target, |
516 | 557 | const gdcm::Dict& dictionary, |
517 | const gdcm::File* file, | |
518 | 558 | const gdcm::DataSet& dicom, |
519 | 559 | const std::string& bulkUri, |
520 | 560 | Orthanc::Encoding sourceEncoding) |
563 | 603 | childUri = bulkUri + std::string(path) + "/" + number + "/"; |
564 | 604 | } |
565 | 605 | |
566 | DicomToJsonInternal(child, dictionary, file, seq->GetItem(i).GetNestedDataSet(), childUri, sourceEncoding); | |
606 | DicomToJsonInternal(child, dictionary, seq->GetItem(i).GetNestedDataSet(), childUri, sourceEncoding); | |
567 | 607 | node["Value"].append(child); |
568 | 608 | } |
569 | 609 | } |
585 | 625 | node["Value"] = Json::arrayValue; |
586 | 626 | |
587 | 627 | std::string value; |
588 | if (ConvertDicomStringToUtf8(value, dictionary, file, *it, sourceEncoding)) | |
628 | if (ConvertDicomStringToUtf8(value, dictionary, *it, sourceEncoding)) | |
589 | 629 | { |
590 | 630 | node["Value"].append(value.c_str()); |
591 | 631 | } |
607 | 647 | |
608 | 648 | static void DicomToJson(Json::Value& target, |
609 | 649 | const gdcm::Dict& dictionary, |
610 | const gdcm::File* file, | |
611 | 650 | const gdcm::DataSet& dicom, |
612 | 651 | const std::string& bulkUriRoot) |
613 | 652 | { |
614 | 653 | Orthanc::Encoding encoding = DetectEncoding(dicom); |
615 | DicomToJsonInternal(target, dictionary, file, dicom, bulkUriRoot, encoding); | |
654 | DicomToJsonInternal(target, dictionary, dicom, bulkUriRoot, encoding); | |
616 | 655 | } |
617 | 656 | |
618 | 657 | |
619 | 658 | void GenerateSingleDicomAnswer(std::string& result, |
620 | 659 | const std::string& wadoBase, |
621 | 660 | const gdcm::Dict& dictionary, |
622 | const gdcm::File* file, // Can be NULL | |
623 | 661 | const gdcm::DataSet& dicom, |
624 | 662 | bool isXml, |
625 | 663 | bool isBulkAccessible) |
633 | 671 | if (isXml) |
634 | 672 | { |
635 | 673 | pugi::xml_document doc; |
636 | DicomToXml(doc, dictionary, file, dicom, bulkUriRoot); | |
674 | DicomToXml(doc, dictionary, dicom, bulkUriRoot); | |
637 | 675 | |
638 | 676 | ChunkedBufferWriter writer; |
639 | 677 | doc.save(writer, " ", pugi::format_default, pugi::encoding_utf8); |
643 | 681 | else |
644 | 682 | { |
645 | 683 | Json::Value v; |
646 | DicomToJson(v, dictionary, file, dicom, bulkUriRoot); | |
684 | DicomToJson(v, dictionary, dicom, bulkUriRoot); | |
647 | 685 | |
648 | 686 | Json::FastWriter writer; |
649 | 687 | result = writer.write(v); |
660 | 698 | bool isBulkAccessible) |
661 | 699 | { |
662 | 700 | std::string answer; |
663 | GenerateSingleDicomAnswer(answer, wadoBase, dictionary, NULL, dicom, isXml, isBulkAccessible); | |
701 | GenerateSingleDicomAnswer(answer, wadoBase, dictionary, dicom, isXml, isBulkAccessible); | |
664 | 702 | OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), |
665 | isXml ? "application/dicom+xml" : "application/json"); | |
703 | isXml ? "application/dicom+xml" : "application/dicom+json"); | |
666 | 704 | } |
667 | 705 | |
668 | 706 |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
22 | 22 | |
23 | 23 | #include "Configuration.h" |
24 | 24 | |
25 | #include "../Orthanc/Core/ChunkedBuffer.h" | |
26 | #include "../Orthanc/Core/Enumerations.h" | |
27 | #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h" | |
25 | #include <Core/ChunkedBuffer.h> | |
26 | #include <Core/Enumerations.h> | |
27 | #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> | |
28 | 28 | |
29 | 29 | #include <gdcmReader.h> |
30 | 30 | #include <gdcmDataSet.h> |
62 | 62 | void Setup(const std::string& dicom); |
63 | 63 | |
64 | 64 | public: |
65 | ParsedDicomFile(const OrthancPlugins::MultipartItem& item); | |
65 | explicit ParsedDicomFile(const OrthancPlugins::MultipartItem& item); | |
66 | 66 | |
67 | ParsedDicomFile(const OrthancPlugins::MemoryBuffer& item); | |
67 | explicit ParsedDicomFile(const OrthancPlugins::MemoryBuffer& item); | |
68 | 68 | |
69 | ParsedDicomFile(const std::string& dicom) | |
69 | explicit ParsedDicomFile(const std::string& dicom) | |
70 | 70 | { |
71 | 71 | Setup(dicom); |
72 | 72 | } |
111 | 111 | void GenerateSingleDicomAnswer(std::string& result, |
112 | 112 | const std::string& wadoBase, |
113 | 113 | const gdcm::Dict& dictionary, |
114 | const gdcm::File* file, // Can be NULL | |
115 | 114 | const gdcm::DataSet& dicom, |
116 | 115 | bool isXml, |
117 | 116 | bool isBulkAccessible); |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
21 | 21 | #include "DicomResults.h" |
22 | 22 | |
23 | 23 | #include "Dicom.h" |
24 | #include "../Orthanc/Core/Toolbox.h" | |
25 | #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h" | |
24 | ||
25 | #include <Core/Toolbox.h> | |
26 | #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> | |
26 | 27 | |
27 | 28 | #include <boost/lexical_cast.hpp> |
28 | 29 | #include <boost/noncopyable.hpp> |
78 | 79 | } |
79 | 80 | |
80 | 81 | |
81 | void DicomResults::AddInternal(const gdcm::File* file, | |
82 | const gdcm::DataSet& dicom) | |
82 | void DicomResults::AddInternal(const gdcm::DataSet& dicom) | |
83 | 83 | { |
84 | 84 | std::string item; |
85 | 85 | |
86 | 86 | if (isXml_) |
87 | 87 | { |
88 | GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, file, dicom, true, isBulkAccessible_); | |
88 | GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, dicom, true, isBulkAccessible_); | |
89 | 89 | } |
90 | 90 | else |
91 | 91 | { |
92 | GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, file, dicom, false, isBulkAccessible_); | |
92 | GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, dicom, false, isBulkAccessible_); | |
93 | 93 | } |
94 | 94 | |
95 | 95 | AddInternal(item); |
419 | 419 | |
420 | 420 | std::string answer; |
421 | 421 | jsonWriter_.Flatten(answer); |
422 | OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/json"); | |
422 | OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/dicom+json"); | |
423 | 423 | } |
424 | 424 | } |
425 | 425 | } |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
44 | 44 | |
45 | 45 | void AddInternal(const std::string& item); |
46 | 46 | |
47 | void AddInternal(const gdcm::File* file, | |
48 | const gdcm::DataSet& dicom); | |
47 | void AddInternal(const gdcm::DataSet& dicom); | |
49 | 48 | |
50 | 49 | public: |
51 | 50 | DicomResults(OrthancPluginContext* context, |
57 | 56 | |
58 | 57 | void Add(const gdcm::File& file) |
59 | 58 | { |
60 | AddInternal(&file, file.GetDataSet()); | |
59 | AddInternal(file.GetDataSet()); | |
61 | 60 | } |
62 | 61 | |
63 | void Add(const gdcm::File& file, | |
64 | const gdcm::DataSet& subset) | |
62 | void Add(const gdcm::DataSet& subset) | |
65 | 63 | { |
66 | AddInternal(&file, subset); | |
64 | AddInternal(subset); | |
67 | 65 | } |
68 | 66 | |
69 | 67 | void AddFromOrthanc(const Json::Value& dicom, |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
28 | 28 | #include <set> |
29 | 29 | #include <boost/lexical_cast.hpp> |
30 | 30 | |
31 | #include "../Orthanc/Core/ChunkedBuffer.h" | |
32 | #include "../Orthanc/Core/Toolbox.h" | |
31 | #include <Core/ChunkedBuffer.h> | |
32 | #include <Core/Toolbox.h> | |
33 | 33 | |
34 | 34 | |
35 | 35 | static void AddInstance(std::list<std::string>& target, |
284 | 284 | |
285 | 285 | std::map<std::string, std::string> queryArguments; |
286 | 286 | std::map<std::string, std::string> httpHeaders; |
287 | httpHeaders["Accept"] = "application/json"; | |
287 | httpHeaders["Accept"] = "application/dicom+json"; | |
288 | 288 | httpHeaders["Expect"] = ""; |
289 | 289 | httpHeaders["Content-Type"] = mime; |
290 | 290 | |
297 | 297 | Orthanc::ChunkedBuffer chunks; |
298 | 298 | size_t countInstances = 0; |
299 | 299 | |
300 | for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); it++) | |
300 | for (std::list<std::string>::const_iterator it = instances.begin(); it != instances.end(); ++it) | |
301 | 301 | { |
302 | 302 | OrthancPlugins::MemoryBuffer dicom(context); |
303 | 303 | if (dicom.RestApiGet("/instances/" + *it + "/file", false)) |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
21 | 21 | #include "DicomWebServers.h" |
22 | 22 | |
23 | 23 | #include "Configuration.h" |
24 | #include "../Orthanc/Core/Toolbox.h" | |
24 | ||
25 | #include <Core/Toolbox.h> | |
25 | 26 | |
26 | 27 | namespace OrthancPlugins |
27 | 28 | { |
142 | 143 | assert(!url.empty() && url[url.size() - 1] == '/'); |
143 | 144 | |
144 | 145 | // Remove the leading "/" in the URI if need be |
145 | std::string tmp; | |
146 | 146 | if (!uri.empty() && |
147 | 147 | uri[0] == '/') |
148 | 148 | { |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
19 | 19 | |
20 | 20 | #pragma once |
21 | 21 | |
22 | #include "../Orthanc/Core/WebServiceParameters.h" | |
23 | #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h" | |
22 | #include <Core/WebServiceParameters.h> | |
23 | #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> | |
24 | 24 | |
25 | 25 | #include <list> |
26 | 26 | #include <string> |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
28 | 28 | #include "Configuration.h" |
29 | 29 | #include "DicomWebServers.h" |
30 | 30 | |
31 | #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h" | |
32 | #include "../Orthanc/Core/Toolbox.h" | |
31 | #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> | |
32 | #include <Core/Toolbox.h> | |
33 | 33 | |
34 | 34 | #include <gdcmDictEntry.h> |
35 | 35 | #include <gdcmDict.h> |
86 | 86 | } |
87 | 87 | } |
88 | 88 | |
89 | bool RequestHasKey(const OrthancPluginHttpRequest* request, const char* key) | |
90 | { | |
91 | for (uint32_t i = 0; i < request->getCount; i++) | |
92 | { | |
93 | if (strcmp(key, request->getKeys[i]) == 0) | |
94 | return true; | |
95 | } | |
96 | return false; | |
97 | } | |
98 | ||
89 | 99 | |
90 | 100 | void ListServers(OrthancPluginRestOutput* output, |
91 | 101 | const char* url, |
102 | 112 | std::list<std::string> servers; |
103 | 113 | OrthancPlugins::DicomWebServers::GetInstance().ListServers(servers); |
104 | 114 | |
105 | Json::Value json = Json::arrayValue; | |
106 | for (std::list<std::string>::const_iterator it = servers.begin(); it != servers.end(); ++it) | |
107 | { | |
108 | json.append(*it); | |
109 | } | |
110 | ||
111 | std::string answer = json.toStyledString(); | |
112 | OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/json"); | |
113 | } | |
114 | } | |
115 | ||
115 | if (RequestHasKey(request, "expand")) | |
116 | { | |
117 | Json::Value result = Json::objectValue; | |
118 | for (std::list<std::string>::const_iterator it = servers.begin(); it != servers.end(); ++it) | |
119 | { | |
120 | Orthanc::WebServiceParameters server = OrthancPlugins::DicomWebServers::GetInstance().GetServer(*it); | |
121 | Json::Value jsonServer; | |
122 | // only return the minimum information to identify the destination, do not include "security" information like passwords | |
123 | jsonServer["Url"] = server.GetUrl(); | |
124 | if (!server.GetUsername().empty()) | |
125 | { | |
126 | jsonServer["Username"] = server.GetUsername(); | |
127 | } | |
128 | result[*it] = jsonServer; | |
129 | } | |
130 | ||
131 | std::string answer = result.toStyledString(); | |
132 | OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/json"); | |
133 | } | |
134 | else // if expand is not present, keep backward compatibility and return an array of server names | |
135 | { | |
136 | Json::Value json = Json::arrayValue; | |
137 | for (std::list<std::string>::const_iterator it = servers.begin(); it != servers.end(); ++it) | |
138 | { | |
139 | json.append(*it); | |
140 | } | |
141 | ||
142 | std::string answer = json.toStyledString(); | |
143 | OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/json"); | |
144 | } | |
145 | } | |
146 | } | |
116 | 147 | |
117 | 148 | void ListServerOperations(OrthancPluginRestOutput* output, |
118 | 149 | const char* /*url*/, |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
20 | 20 | |
21 | 21 | #pragma once |
22 | 22 | |
23 | #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h" | |
23 | #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h> | |
24 | 24 | |
25 | 25 | #include <gdcmDict.h> |
26 | 26 |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
25 | 25 | #include "Dicom.h" |
26 | 26 | #include "DicomResults.h" |
27 | 27 | #include "Configuration.h" |
28 | #include "../Orthanc/Core/Toolbox.h" | |
28 | ||
29 | #include <Core/Toolbox.h> | |
29 | 30 | |
30 | 31 | #include <gdcmTag.h> |
31 | 32 | #include <list> |
156 | 157 | |
157 | 158 | |
158 | 159 | public: |
159 | ModuleMatcher(const OrthancPluginHttpRequest* request) : | |
160 | fuzzy_(false), | |
161 | offset_(0), | |
162 | limit_(0), | |
163 | includeAllFields_(false) | |
160 | explicit ModuleMatcher(const OrthancPluginHttpRequest* request) : | |
161 | fuzzy_(false), | |
162 | offset_(0), | |
163 | limit_(0), | |
164 | includeAllFields_(false) | |
164 | 165 | { |
165 | 166 | std::string args; |
166 | 167 | |
196 | 197 | } |
197 | 198 | else if (key == "includefield") |
198 | 199 | { |
199 | if (key == "all") | |
200 | if (value == "all") | |
200 | 201 | { |
201 | 202 | includeAllFields_ = true; |
202 | 203 | } |
269 | 270 | } |
270 | 271 | |
271 | 272 | result["Expand"] = false; |
272 | result["CaseSensitive"] = true; | |
273 | result["CaseSensitive"] = OrthancPlugins::Configuration::GetBooleanValue("QidoCaseSensitive", true); | |
273 | 274 | result["Query"] = Json::objectValue; |
274 | 275 | result["Limit"] = limit_; |
275 | 276 | result["Since"] = offset_; |
276 | 277 | |
277 | 278 | if (offset_ != 0 && |
278 | 279 | !OrthancPlugins::CheckMinimalOrthancVersion( |
279 | OrthancPlugins::Configuration::GetContext(), 1, 2, 1)) | |
280 | OrthancPlugins::Configuration::GetContext(), 1, 3, 0)) | |
280 | 281 | { |
281 | 282 | OrthancPlugins::Configuration::LogError( |
282 | 283 | "QIDO-RS request with \"offset\" argument: " |
283 | "Only available if the Orthanc core version is >= 1.2.1"); | |
284 | "Only available if the Orthanc core version is >= 1.3.0"); | |
284 | 285 | } |
285 | 286 | |
286 | 287 | for (Filters::const_iterator it = filters_.begin(); |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
23 | 23 | |
24 | 24 | #include "Configuration.h" |
25 | 25 | #include "Dicom.h" |
26 | #include "../Orthanc/Core/Toolbox.h" | |
26 | ||
27 | #include <Core/Toolbox.h> | |
27 | 28 | |
28 | 29 | #include <stdexcept> |
29 | 30 | |
60 | 61 | |
61 | 62 | if (!OrthancPlugins::LookupHttpHeader(accept, request, "accept")) |
62 | 63 | { |
63 | return true; // By default, return XML Native DICOM Model | |
64 | return false; // By default, return DICOM+JSON | |
64 | 65 | } |
65 | 66 | |
66 | 67 | Orthanc::Toolbox::ToLowerCase(accept); |
67 | if (accept == "application/json") | |
68 | if (accept == "application/dicom+json" || | |
69 | accept == "application/json" || | |
70 | accept == "*/*") | |
68 | 71 | { |
69 | 72 | return false; |
70 | 73 | } |
71 | ||
72 | if (accept != "application/dicom+xml" && | |
73 | accept != "application/xml" && | |
74 | accept != "text/xml" && | |
75 | accept != "*/*") | |
76 | { | |
77 | OrthancPlugins::Configuration::LogError("Unsupported return MIME type: " + accept + ", will return XML"); | |
78 | } | |
79 | ||
80 | return true; | |
74 | else if (accept == "application/dicom+xml" || | |
75 | accept == "application/xml" || | |
76 | accept == "text/xml") | |
77 | { | |
78 | return true; | |
79 | } | |
80 | else | |
81 | { | |
82 | OrthancPlugins::Configuration::LogError("Unsupported return MIME type: " + accept + | |
83 | ", will return DICOM+JSON"); | |
84 | return false; | |
85 | } | |
81 | 86 | } |
82 | 87 | |
83 | 88 |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
23 | 23 | #include "Configuration.h" |
24 | 24 | #include "Dicom.h" |
25 | 25 | #include "DicomResults.h" |
26 | #include "../Orthanc/Core/Toolbox.h" | |
26 | ||
27 | #include <Core/Toolbox.h> | |
27 | 28 | |
28 | 29 | #include <memory> |
29 | 30 | |
74 | 75 | static bool AcceptMetadata(const OrthancPluginHttpRequest* request, |
75 | 76 | bool& isXml) |
76 | 77 | { |
77 | isXml = true; | |
78 | isXml = false; // By default, return application/dicom+json | |
78 | 79 | |
79 | 80 | std::string accept; |
80 | ||
81 | 81 | if (!OrthancPlugins::LookupHttpHeader(accept, request, "accept")) |
82 | 82 | { |
83 | // By default, return "multipart/related; type=application/dicom+xml;" | |
84 | 83 | return true; |
85 | 84 | } |
86 | 85 | |
88 | 87 | std::map<std::string, std::string> attributes; |
89 | 88 | OrthancPlugins::ParseContentType(application, attributes, accept); |
90 | 89 | |
91 | if (application == "application/json") | |
92 | { | |
93 | isXml = false; | |
90 | if (application == "application/json" || | |
91 | application == "application/dicom+json" || | |
92 | application == "*/*") | |
93 | { | |
94 | 94 | return true; |
95 | 95 | } |
96 | 96 | |
97 | if (application != "multipart/related" && | |
98 | application != "*/*") | |
97 | if (application != "multipart/related") | |
99 | 98 | { |
100 | 99 | OrthancPlugins::Configuration::LogError("This WADO-RS plugin cannot generate the following content type: " + accept); |
101 | 100 | return false; |
105 | 104 | { |
106 | 105 | std::string s = attributes["type"]; |
107 | 106 | Orthanc::Toolbox::ToLowerCase(s); |
108 | if (s != "application/dicom+xml") | |
109 | { | |
110 | OrthancPlugins::Configuration::LogError("This WADO-RS plugin only supports application/json or " | |
111 | "application/dicom+xml return types for metadata (" + accept + ")"); | |
107 | if (s == "application/dicom+xml") | |
108 | { | |
109 | isXml = true; | |
110 | } | |
111 | else | |
112 | { | |
113 | OrthancPlugins::Configuration::LogError("This WADO-RS plugin only supports application/dicom+xml " | |
114 | "type for multipart/related accept (" + accept + ")"); | |
112 | 115 | return false; |
113 | 116 | } |
117 | } | |
118 | else | |
119 | { | |
120 | OrthancPlugins::Configuration::LogError("Missing \"type\" in multipart/related accept type (" + accept + ")"); | |
121 | return false; | |
114 | 122 | } |
115 | 123 | |
116 | 124 | if (attributes.find("transfer-syntax") != attributes.end()) |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
20 | 20 | |
21 | 21 | #include "WadoRs.h" |
22 | 22 | |
23 | #include "../Orthanc/Core/Toolbox.h" | |
24 | 23 | #include "Dicom.h" |
25 | 24 | #include "Plugin.h" |
25 | ||
26 | #include <Core/Toolbox.h> | |
26 | 27 | |
27 | 28 | #include <memory> |
28 | 29 | #include <list> |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
2 | 2 | |
3 | 3 | # mkdir Build |
4 | 4 | # cd Build |
5 | # cmake .. -DCMAKE_BUILD_TYPE=Debug -DALLOW_DOWNLOADS=ON -DSTATIC_BUILD=ON | |
5 | # cmake .. -DCMAKE_BUILD_TYPE=Debug -DSTATIC_BUILD=ON | |
6 | 6 | # make |
7 | 7 | |
8 | 8 | |
11 | 11 | |
12 | 12 | # mkdir Build |
13 | 13 | # cd Build |
14 | # cmake .. -DCMAKE_BUILD_TYPE=Debug -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON | |
14 | # cmake .. -DCMAKE_BUILD_TYPE=Debug -DUSE_GOOGLE_TEST_DEBIAN_PACKAGE=ON -DUSE_SYSTEM_ORTHANC_SDK=OFF | |
15 | 15 | # make |
16 | 16 | |
17 | 17 | |
24 | 24 | -DALLOW_DOWNLOADS=ON \ |
25 | 25 | -DUSE_SYSTEM_JSONCPP=OFF \ |
26 | 26 | -DUSE_SYSTEM_PUGIXML=OFF \ |
27 | -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON | |
27 | -DUSE_GOOGLE_TEST_DEBIAN_SOURCE_PACKAGE=ON | |
28 | 28 | # make |
29 | 29 | |
30 | 30 |
0 | 0 | # Orthanc - A Lightweight, RESTful DICOM Store |
1 | 1 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
2 | 2 | # Department, University Hospital of Liege, Belgium |
3 | # Copyright (C) 2017 Osimis, Belgium | |
3 | # Copyright (C) 2017-2018 Osimis S.A., Belgium | |
4 | 4 | # |
5 | 5 | # This program is free software: you can redistribute it and/or |
6 | 6 | # modify it under the terms of the GNU Affero General Public License |
17 | 17 | |
18 | 18 | |
19 | 19 | if (STATIC_BUILD OR NOT USE_SYSTEM_GDCM) |
20 | # If using gcc, build GDCM with the "-fPIC" argument to allow its | |
21 | # embedding into the shared library containing the Orthanc plugin | |
22 | 20 | if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR |
23 | 21 | ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR |
24 | 22 | ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD") |
23 | # If using gcc, build GDCM with the "-fPIC" argument to allow its | |
24 | # embedding into the shared library containing the Orthanc plugin | |
25 | 25 | set(AdditionalFlags "-fPIC") |
26 | elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") | |
27 | # This definition is necessary to compile | |
28 | # "Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx" | |
29 | set(AdditionalFlags "-Doff64_t=off_t") | |
26 | 30 | endif() |
27 | 31 | |
28 | 32 | set(Flags |
39 | 43 | ) |
40 | 44 | |
41 | 45 | if (CMAKE_TOOLCHAIN_FILE) |
42 | list(APPEND Flags -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}) | |
46 | # Take absolute path to the toolchain | |
47 | get_filename_component(TMP ${CMAKE_TOOLCHAIN_FILE} REALPATH BASE ${CMAKE_SOURCE_DIR}) | |
48 | list(APPEND Flags -DCMAKE_TOOLCHAIN_FILE=${TMP}) | |
49 | endif() | |
50 | ||
51 | # Don't build manpages (since gdcm 2.8.4) | |
52 | list(APPEND Flags -DGDCM_BUILD_DOCBOOK_MANPAGES=OFF) | |
53 | ||
54 | if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase") | |
55 | # Trick to disable the compilation of socket++ by gdcm, which is | |
56 | # incompatible with LSB, but fortunately only required for DICOM | |
57 | # Networking | |
58 | list(APPEND Flags -DGDCM_USE_SYSTEM_SOCKETXX=ON) | |
59 | ||
60 | # Detect the number of CPU cores to run "make" with as much | |
61 | # parallelism as possible | |
62 | include(ProcessorCount) | |
63 | ProcessorCount(N) | |
64 | if (NOT N EQUAL 0) | |
65 | set(MAKE_PARALLEL -j${N}) | |
66 | endif() | |
67 | ||
68 | # For Linux Standard Base, avoid building incompatible target gdcmMEXD (*) | |
69 | set(BUILD_COMMAND BUILD_COMMAND | |
70 | ${CMAKE_MAKE_PROGRAM} ${MAKE_PARALLEL} | |
71 | gdcmMSFF gdcmcharls gdcmDICT gdcmDSED gdcmIOD gdcmjpeg8 | |
72 | gdcmjpeg12 gdcmjpeg16 gdcmopenjp2 gdcmzlib gdcmCommon gdcmexpat gdcmuuid) | |
43 | 73 | endif() |
44 | 74 | |
45 | 75 | include(ExternalProject) |
46 | 76 | externalproject_add(GDCM |
47 | URL "http://www.orthanc-server.com/downloads/third-party/gdcm-2.6.0.tar.gz" | |
48 | URL_MD5 "978afe57af448b1c97c9f116790aca9c" | |
77 | URL "http://www.orthanc-server.com/downloads/third-party/gdcm-2.8.4.tar.gz" | |
78 | URL_MD5 "ce957b0bc1be4e8019162a10ca15432f" | |
49 | 79 | TIMEOUT 60 |
50 | 80 | CMAKE_ARGS -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} ${Flags} |
51 | #-DLIBRARY_OUTPUT_PATH=${CMAKE_CURRENT_BINARY_DIR} | |
81 | ${BUILD_COMMAND} # Customize "make", only for Linux Standard Base (*) | |
52 | 82 | INSTALL_COMMAND "" # Skip the install step |
53 | 83 | ) |
54 | 84 | |
60 | 90 | list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix) |
61 | 91 | endif() |
62 | 92 | |
63 | set(GDCM_LIBRARIES | |
93 | set(GDCM_LIBRARIES | |
94 | # WARNING: The order of the libraries below *is* important! | |
64 | 95 | ${Prefix}gdcmMSFF${Suffix} |
65 | 96 | ${Prefix}gdcmcharls${Suffix} |
66 | 97 | ${Prefix}gdcmDICT${Suffix} |
69 | 100 | ${Prefix}gdcmjpeg8${Suffix} |
70 | 101 | ${Prefix}gdcmjpeg12${Suffix} |
71 | 102 | ${Prefix}gdcmjpeg16${Suffix} |
72 | ${Prefix}gdcmMEXD${Suffix} | |
73 | ${Prefix}gdcmopenjpeg${Suffix} | |
103 | ${Prefix}gdcmopenjp2${Suffix} | |
74 | 104 | ${Prefix}gdcmzlib${Suffix} |
75 | ${Prefix}socketxx${Suffix} | |
76 | 105 | ${Prefix}gdcmCommon${Suffix} |
77 | 106 | ${Prefix}gdcmexpat${Suffix} |
78 | 107 | |
108 | #${Prefix}socketxx${Suffix} | |
109 | #${Prefix}gdcmMEXD${Suffix} # DICOM Networking, unneeded by Orthanc plugins | |
79 | 110 | #${Prefix}gdcmgetopt${Suffix} |
80 | 111 | ) |
81 | 112 |
0 | # Orthanc - A Lightweight, RESTful DICOM Store | |
1 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
2 | # Department, University Hospital of Liege, Belgium | |
3 | # Copyright (C) 2017-2018 Osimis S.A., Belgium | |
4 | # | |
5 | # This program is free software: you can redistribute it and/or | |
6 | # modify it under the terms of the GNU General Public License as | |
7 | # published by the Free Software Foundation, either version 3 of the | |
8 | # License, or (at your option) any later version. | |
9 | # | |
10 | # In addition, as a special exception, the copyright holders of this | |
11 | # program give permission to link the code of its release with the | |
12 | # OpenSSL project's "OpenSSL" library (or with modified versions of it | |
13 | # that use the same license as the "OpenSSL" library), and distribute | |
14 | # the linked executables. You must obey the GNU General Public License | |
15 | # in all respects for all of the code used other than "OpenSSL". If you | |
16 | # modify file(s) with this exception, you may extend this exception to | |
17 | # your version of the file(s), but you are not obligated to do so. If | |
18 | # you do not wish to do so, delete this exception statement from your | |
19 | # version. If you delete this exception statement from all source files | |
20 | # in the program, then also delete it here. | |
21 | # | |
22 | # This program is distributed in the hope that it will be useful, but | |
23 | # WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
25 | # General Public License for more details. | |
26 | # | |
27 | # You should have received a copy of the GNU General Public License | |
28 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
29 | ||
30 | ||
31 | ||
32 | ## | |
33 | ## Check whether the parent script sets the mandatory variables | |
34 | ## | |
35 | ||
36 | if (NOT DEFINED ORTHANC_FRAMEWORK_SOURCE OR | |
37 | (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND | |
38 | NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "web" AND | |
39 | NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" AND | |
40 | NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "path")) | |
41 | message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"hg\", \"web\", \"archive\" or \"path\"") | |
42 | endif() | |
43 | ||
44 | ||
45 | ## | |
46 | ## Detection of the requested version | |
47 | ## | |
48 | ||
49 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR | |
50 | ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR | |
51 | ORTHANC_FRAMEWORK_SOURCE STREQUAL "web") | |
52 | if (NOT DEFINED ORTHANC_FRAMEWORK_VERSION) | |
53 | message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_VERSION must be set") | |
54 | endif() | |
55 | ||
56 | if (DEFINED ORTHANC_FRAMEWORK_MAJOR OR | |
57 | DEFINED ORTHANC_FRAMEWORK_MINOR OR | |
58 | DEFINED ORTHANC_FRAMEWORK_REVISION OR | |
59 | DEFINED ORTHANC_FRAMEWORK_MD5) | |
60 | message(FATAL_ERROR "Some internal variable has been set") | |
61 | endif() | |
62 | ||
63 | set(ORTHANC_FRAMEWORK_MD5 "") | |
64 | ||
65 | if (ORTHANC_FRAMEWORK_VERSION STREQUAL "mainline") | |
66 | set(ORTHANC_FRAMEWORK_BRANCH "default") | |
67 | ||
68 | else() | |
69 | set(ORTHANC_FRAMEWORK_BRANCH "Orthanc-${ORTHANC_FRAMEWORK_VERSION}") | |
70 | ||
71 | set(RE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$") | |
72 | string(REGEX REPLACE ${RE} "\\1" ORTHANC_FRAMEWORK_MAJOR ${ORTHANC_FRAMEWORK_VERSION}) | |
73 | string(REGEX REPLACE ${RE} "\\2" ORTHANC_FRAMEWORK_MINOR ${ORTHANC_FRAMEWORK_VERSION}) | |
74 | string(REGEX REPLACE ${RE} "\\3" ORTHANC_FRAMEWORK_REVISION ${ORTHANC_FRAMEWORK_VERSION}) | |
75 | ||
76 | if (NOT ORTHANC_FRAMEWORK_MAJOR MATCHES "^[0-9]+$" OR | |
77 | NOT ORTHANC_FRAMEWORK_MINOR MATCHES "^[0-9]+$" OR | |
78 | NOT ORTHANC_FRAMEWORK_REVISION MATCHES "^[0-9]+$") | |
79 | message("Bad version of the Orthanc framework: ${ORTHANC_FRAMEWORK_VERSION}") | |
80 | endif() | |
81 | ||
82 | if (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.1") | |
83 | set(ORTHANC_FRAMEWORK_MD5 "dac95bd6cf86fb19deaf4e612961f378") | |
84 | elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.2") | |
85 | set(ORTHANC_FRAMEWORK_MD5 "d0ccdf68e855d8224331f13774992750") | |
86 | endif() | |
87 | endif() | |
88 | endif() | |
89 | ||
90 | ||
91 | ||
92 | ## | |
93 | ## Detection of the third-party software | |
94 | ## | |
95 | ||
96 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg") | |
97 | find_program(ORTHANC_FRAMEWORK_HG hg) | |
98 | ||
99 | if (${ORTHANC_FRAMEWORK_HG} MATCHES "ORTHANC_FRAMEWORK_HG-NOTFOUND") | |
100 | message(FATAL_ERROR "Please install Mercurial") | |
101 | endif() | |
102 | endif() | |
103 | ||
104 | ||
105 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR | |
106 | ORTHANC_FRAMEWORK_SOURCE STREQUAL "web") | |
107 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") | |
108 | find_program(ORTHANC_FRAMEWORK_7ZIP 7z | |
109 | PATHS | |
110 | "$ENV{ProgramFiles}/7-Zip" | |
111 | "$ENV{ProgramW6432}/7-Zip" | |
112 | ) | |
113 | ||
114 | if (${ORTHANC_FRAMEWORK_7ZIP} MATCHES "ORTHANC_FRAMEWORK_7ZIP-NOTFOUND") | |
115 | message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)") | |
116 | endif() | |
117 | ||
118 | else() | |
119 | find_program(ORTHANC_FRAMEWORK_TAR tar) | |
120 | if (${ORTHANC_FRAMEWORK_TAR} MATCHES "ORTHANC_FRAMEWORK_TAR-NOTFOUND") | |
121 | message(FATAL_ERROR "Please install the 'tar' package") | |
122 | endif() | |
123 | endif() | |
124 | endif() | |
125 | ||
126 | ||
127 | ||
128 | ## | |
129 | ## Case of the Orthanc framework specified as a path on the filesystem | |
130 | ## | |
131 | ||
132 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path") | |
133 | if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT) | |
134 | message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ROOT must provide the path to the sources of Orthanc") | |
135 | endif() | |
136 | ||
137 | if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}) | |
138 | message(FATAL_ERROR "Non-existing directory: ${ORTHANC_FRAMEWORK_ROOT}") | |
139 | endif() | |
140 | ||
141 | if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake) | |
142 | message(FATAL_ERROR "Directory not containing the source code of Orthanc: ${ORTHANC_FRAMEWORK_ROOT}") | |
143 | endif() | |
144 | ||
145 | set(ORTHANC_ROOT ${ORTHANC_FRAMEWORK_ROOT}) | |
146 | endif() | |
147 | ||
148 | ||
149 | ||
150 | ## | |
151 | ## Case of the Orthanc framework cloned using Mercurial | |
152 | ## | |
153 | ||
154 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg") | |
155 | if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS) | |
156 | message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") | |
157 | endif() | |
158 | ||
159 | set(ORTHANC_ROOT ${CMAKE_BINARY_DIR}/orthanc) | |
160 | ||
161 | if (EXISTS ${ORTHANC_ROOT}) | |
162 | message("Updating the Orthanc source repository using Mercurial") | |
163 | execute_process( | |
164 | COMMAND ${ORTHANC_FRAMEWORK_HG} pull | |
165 | WORKING_DIRECTORY ${ORTHANC_ROOT} | |
166 | RESULT_VARIABLE Failure | |
167 | ) | |
168 | else() | |
169 | message("Forking the Orthanc source repository using Mercurial") | |
170 | execute_process( | |
171 | COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://bitbucket.org/sjodogne/orthanc" | |
172 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
173 | RESULT_VARIABLE Failure | |
174 | ) | |
175 | endif() | |
176 | ||
177 | if (Failure OR NOT EXISTS ${ORTHANC_ROOT}) | |
178 | message(FATAL_ERROR "Cannot fork the Orthanc repository") | |
179 | endif() | |
180 | ||
181 | message("Setting branch of the Orthanc repository to: ${ORTHANC_FRAMEWORK_BRANCH}") | |
182 | ||
183 | execute_process( | |
184 | COMMAND ${ORTHANC_FRAMEWORK_HG} update -c ${ORTHANC_FRAMEWORK_BRANCH} | |
185 | WORKING_DIRECTORY ${ORTHANC_ROOT} | |
186 | RESULT_VARIABLE Failure | |
187 | ) | |
188 | ||
189 | if (Failure) | |
190 | message(FATAL_ERROR "Error while running Mercurial") | |
191 | endif() | |
192 | endif() | |
193 | ||
194 | ||
195 | ||
196 | ## | |
197 | ## Case of the Orthanc framework provided as a source archive on the | |
198 | ## filesystem | |
199 | ## | |
200 | ||
201 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive") | |
202 | if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE) | |
203 | message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ARCHIVE must provide the path to the sources of Orthanc") | |
204 | endif() | |
205 | endif() | |
206 | ||
207 | ||
208 | ||
209 | ## | |
210 | ## Case of the Orthanc framework downloaded from the Web | |
211 | ## | |
212 | ||
213 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "web") | |
214 | if (DEFINED ORTHANC_FRAMEWORK_URL) | |
215 | string(REGEX REPLACE "^.*/" "" ORTHANC_FRAMEMORK_FILENAME "${ORTHANC_FRAMEWORK_URL}") | |
216 | else() | |
217 | # Default case: Download from the official Web site | |
218 | set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz) | |
219 | #set(ORTHANC_FRAMEWORK_URL "https://www.orthanc-server.com/downloads/get.php?path=/orthanc/${ORTHANC_FRAMEMORK_FILENAME}") | |
220 | set(ORTHANC_FRAMEWORK_URL "https://www.orthanc-server.com/downloads/third-party/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}") | |
221 | endif() | |
222 | ||
223 | set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}") | |
224 | ||
225 | if (NOT EXISTS "${ORTHANC_FRAMEWORK_ARCHIVE}") | |
226 | if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS) | |
227 | message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") | |
228 | endif() | |
229 | ||
230 | message("Downloading: ${ORTHANC_FRAMEWORK_URL}") | |
231 | ||
232 | file(DOWNLOAD | |
233 | "${ORTHANC_FRAMEWORK_URL}" "${ORTHANC_FRAMEWORK_ARCHIVE}" | |
234 | SHOW_PROGRESS EXPECTED_MD5 "${ORTHANC_FRAMEWORK_MD5}" | |
235 | TIMEOUT 60 | |
236 | INACTIVITY_TIMEOUT 60 | |
237 | ) | |
238 | else() | |
239 | message("Using local copy of: ${ORTHANC_FRAMEWORK_URL}") | |
240 | endif() | |
241 | endif() | |
242 | ||
243 | ||
244 | ||
245 | ||
246 | ## | |
247 | ## Uncompressing the Orthanc framework, if it was retrieved from a | |
248 | ## source archive on the filesystem, or from the official Web site | |
249 | ## | |
250 | ||
251 | if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR | |
252 | ORTHANC_FRAMEWORK_SOURCE STREQUAL "web") | |
253 | ||
254 | if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE OR | |
255 | NOT DEFINED ORTHANC_FRAMEWORK_VERSION OR | |
256 | NOT DEFINED ORTHANC_FRAMEWORK_MD5) | |
257 | message(FATAL_ERROR "Internal error") | |
258 | endif() | |
259 | ||
260 | if (ORTHANC_FRAMEWORK_MD5 STREQUAL "") | |
261 | message(FATAL_ERROR "Unknown release of Orthanc: ${ORTHANC_FRAMEWORK_VERSION}") | |
262 | endif() | |
263 | ||
264 | file(MD5 ${ORTHANC_FRAMEWORK_ARCHIVE} ActualMD5) | |
265 | ||
266 | if (NOT "${ActualMD5}" STREQUAL "${ORTHANC_FRAMEWORK_MD5}") | |
267 | message(FATAL_ERROR "The MD5 hash of the Orthanc archive is invalid: ${ORTHANC_FRAMEWORK_ARCHIVE}") | |
268 | endif() | |
269 | ||
270 | set(ORTHANC_ROOT "${CMAKE_BINARY_DIR}/Orthanc-${ORTHANC_FRAMEWORK_VERSION}") | |
271 | ||
272 | if (NOT IS_DIRECTORY "${ORTHANC_ROOT}") | |
273 | if (NOT ORTHANC_FRAMEWORK_ARCHIVE MATCHES ".tar.gz$") | |
274 | message(FATAL_ERROR "Archive should have the \".tar.gz\" extension: ${ORTHANC_FRAMEWORK_ARCHIVE}") | |
275 | endif() | |
276 | ||
277 | message("Uncompressing: ${ORTHANC_FRAMEWORK_ARCHIVE}") | |
278 | ||
279 | if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") | |
280 | # How to silently extract files using 7-zip | |
281 | # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly | |
282 | ||
283 | execute_process( | |
284 | COMMAND ${ORTHANC_FRAMEWORK_7ZIP} e -y ${ORTHANC_FRAMEWORK_ARCHIVE} | |
285 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
286 | RESULT_VARIABLE Failure | |
287 | OUTPUT_QUIET | |
288 | ) | |
289 | ||
290 | if (Failure) | |
291 | message(FATAL_ERROR "Error while running the uncompression tool") | |
292 | endif() | |
293 | ||
294 | string(REGEX REPLACE ".gz$" "" TMP "${ORTHANC_FRAMEWORK_ARCHIVE}") | |
295 | ||
296 | execute_process( | |
297 | COMMAND ${ORTHANC_FRAMEWORK_7ZIP} x -y ${TMP_FILENAME2} | |
298 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
299 | RESULT_VARIABLE Failure | |
300 | OUTPUT_QUIET | |
301 | ) | |
302 | ||
303 | else() | |
304 | execute_process( | |
305 | COMMAND sh -c "${ORTHANC_FRAMEWORK_TAR} xfz ${ORTHANC_FRAMEWORK_ARCHIVE}" | |
306 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | |
307 | RESULT_VARIABLE Failure | |
308 | ) | |
309 | endif() | |
310 | ||
311 | if (Failure) | |
312 | message(FATAL_ERROR "Error while running the uncompression tool") | |
313 | endif() | |
314 | ||
315 | if (NOT IS_DIRECTORY "${ORTHANC_ROOT}") | |
316 | message(FATAL_ERROR "The Orthanc framework was not uncompressed at the proper location. Check the CMake instructions.") | |
317 | endif() | |
318 | endif() | |
319 | endif() |
0 | # LSB_CC=gcc-4.8 LSB_CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../Resources/LinuxStandardBaseToolchain.cmake -DUSE_LEGACY_JSONCPP=ON | |
1 | ||
2 | INCLUDE(CMakeForceCompiler) | |
3 | ||
4 | SET(LSB_PATH $ENV{LSB_PATH}) | |
5 | SET(LSB_CC $ENV{LSB_CC}) | |
6 | SET(LSB_CXX $ENV{LSB_CXX}) | |
7 | SET(LSB_TARGET_VERSION "4.0") | |
8 | ||
9 | IF ("${LSB_PATH}" STREQUAL "") | |
10 | SET(LSB_PATH "/opt/lsb") | |
11 | ENDIF() | |
12 | ||
13 | IF (EXISTS ${LSB_PATH}/lib64) | |
14 | SET(LSB_TARGET_PROCESSOR "x86_64") | |
15 | SET(LSB_LIBPATH ${LSB_PATH}/lib64-${LSB_TARGET_VERSION}) | |
16 | ELSEIF (EXISTS ${LSB_PATH}/lib) | |
17 | SET(LSB_TARGET_PROCESSOR "x86") | |
18 | SET(LSB_LIBPATH ${LSB_PATH}/lib-${LSB_TARGET_VERSION}) | |
19 | ELSE() | |
20 | MESSAGE(FATAL_ERROR "Unable to detect the target processor architecture. Check the LSB_PATH environment variable.") | |
21 | ENDIF() | |
22 | ||
23 | SET(LSB_CPPPATH ${LSB_PATH}/include) | |
24 | SET(PKG_CONFIG_PATH ${LSB_LIBPATH}/pkgconfig/) | |
25 | ||
26 | # the name of the target operating system | |
27 | SET(CMAKE_SYSTEM_NAME Linux) | |
28 | SET(CMAKE_SYSTEM_VERSION LinuxStandardBase) | |
29 | SET(CMAKE_SYSTEM_PROCESSOR ${LSB_TARGET_PROCESSOR}) | |
30 | ||
31 | # which compilers to use for C and C++ | |
32 | SET(CMAKE_C_COMPILER ${LSB_PATH}/bin/lsbcc) | |
33 | CMAKE_FORCE_CXX_COMPILER(${LSB_PATH}/bin/lsbc++ GNU) | |
34 | ||
35 | # here is the target environment located | |
36 | SET(CMAKE_FIND_ROOT_PATH ${LSB_PATH}) | |
37 | ||
38 | # adjust the default behaviour of the FIND_XXX() commands: | |
39 | # search headers and libraries in the target environment, search | |
40 | # programs in the host environment | |
41 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
42 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) | |
43 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) | |
44 | ||
45 | SET(CMAKE_CROSSCOMPILING OFF) | |
46 | ||
47 | ||
48 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -I${LSB_PATH}/include" CACHE INTERNAL "" FORCE) | |
49 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -nostdinc++ -I${LSB_PATH}/include -I${LSB_PATH}/include/c++ -I${LSB_PATH}/include/c++/backward" CACHE INTERNAL "" FORCE) | |
50 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE) | |
51 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-target-version=${LSB_TARGET_VERSION} -L${LSB_LIBPATH} --lsb-besteffort" CACHE INTERNAL "" FORCE) | |
52 | ||
53 | if (NOT "${LSB_CXX}" STREQUAL "") | |
54 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cxx=${LSB_CXX}") | |
55 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}") | |
56 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cxx=${LSB_CXX}") | |
57 | endif() | |
58 | ||
59 | if (NOT "${LSB_CC}" STREQUAL "") | |
60 | SET(CMAKE_C_FLAGS "${CMAKE_CC_FLAGS} --lsb-cc=${LSB_CC}") | |
61 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --lsb-cc=${LSB_CC}") | |
62 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --lsb-cc=${LSB_CC}") | |
63 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --lsb-cc=${LSB_CC}") | |
64 | endif() | |
65 |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) | |
5 | set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) | |
6 | set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) | |
5 | set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) | |
6 | set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
0 | # the name of the target operating system | |
1 | set(CMAKE_SYSTEM_NAME Windows) | |
2 | ||
3 | # which compilers to use for C and C++ | |
4 | set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) | |
5 | set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) | |
6 | set(CMAKE_RC_COMPILER i586-mingw32msvc-windres) | |
7 | ||
8 | # here is the target environment located | |
9 | set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) | |
10 | ||
11 | # adjust the default behaviour of the FIND_XXX() commands: | |
12 | # search headers and libraries in the target environment, search | |
13 | # programs in the host environment | |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | |
17 | ||
18 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTACK_SIZE_PARAM_IS_A_RESERVATION=0x10000" CACHE INTERNAL "" FORCE) | |
19 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTACK_SIZE_PARAM_IS_A_RESERVATION=0x10000" CACHE INTERNAL "" FORCE) |
0 | This folder contains an excerpt of the source code of Orthanc. It is | |
1 | automatically generated using the "../Resources/SyncOrthancFolder.py" | |
2 | script. |
0 | /** | |
1 | * \mainpage | |
2 | * | |
3 | * This C/C++ SDK allows external developers to create plugins that | |
4 | * can be loaded into Orthanc to extend its functionality. Each | |
5 | * Orthanc plugin must expose 4 public functions with the following | |
6 | * signatures: | |
7 | * | |
8 | * -# <tt>int32_t OrthancPluginInitialize(const OrthancPluginContext* context)</tt>: | |
9 | * This function is invoked by Orthanc when it loads the plugin on startup. | |
10 | * The plugin must: | |
11 | * - Check its compatibility with the Orthanc version using | |
12 | * ::OrthancPluginCheckVersion(). | |
13 | * - Store the context pointer so that it can use the plugin | |
14 | * services of Orthanc. | |
15 | * - Register all its REST callbacks using ::OrthancPluginRegisterRestCallback(). | |
16 | * - Possibly register its callback for received DICOM instances using ::OrthancPluginRegisterOnStoredInstanceCallback(). | |
17 | * - Possibly register its callback for changes to the DICOM store using ::OrthancPluginRegisterOnChangeCallback(). | |
18 | * - Possibly register a custom storage area using ::OrthancPluginRegisterStorageArea(). | |
19 | * - Possibly register a custom database back-end area using OrthancPluginRegisterDatabaseBackendV2(). | |
20 | * - Possibly register a handler for C-Find SCP using OrthancPluginRegisterFindCallback(). | |
21 | * - Possibly register a handler for C-Find SCP against DICOM worklists using OrthancPluginRegisterWorklistCallback(). | |
22 | * - Possibly register a handler for C-Move SCP using OrthancPluginRegisterMoveCallback(). | |
23 | * - Possibly register a custom decoder for DICOM images using OrthancPluginRegisterDecodeImageCallback(). | |
24 | * - Possibly register a callback to filter incoming HTTP requests using OrthancPluginRegisterIncomingHttpRequestFilter(). | |
25 | * -# <tt>void OrthancPluginFinalize()</tt>: | |
26 | * This function is invoked by Orthanc during its shutdown. The plugin | |
27 | * must free all its memory. | |
28 | * -# <tt>const char* OrthancPluginGetName()</tt>: | |
29 | * The plugin must return a short string to identify itself. | |
30 | * -# <tt>const char* OrthancPluginGetVersion()</tt>: | |
31 | * The plugin must return a string containing its version number. | |
32 | * | |
33 | * The name and the version of a plugin is only used to prevent it | |
34 | * from being loaded twice. Note that, in C++, it is mandatory to | |
35 | * declare these functions within an <tt>extern "C"</tt> section. | |
36 | * | |
37 | * To ensure multi-threading safety, the various REST callbacks are | |
38 | * guaranteed to be executed in mutual exclusion since Orthanc | |
39 | * 0.8.5. If this feature is undesired (notably when developing | |
40 | * high-performance plugins handling simultaneous requests), use | |
41 | * ::OrthancPluginRegisterRestCallbackNoLock(). | |
42 | **/ | |
43 | ||
44 | ||
45 | ||
46 | /** | |
47 | * @defgroup Images Images and compression | |
48 | * @brief Functions to deal with images and compressed buffers. | |
49 | * | |
50 | * @defgroup REST REST | |
51 | * @brief Functions to answer REST requests in a callback. | |
52 | * | |
53 | * @defgroup Callbacks Callbacks | |
54 | * @brief Functions to register and manage callbacks by the plugins. | |
55 | * | |
56 | * @defgroup DicomCallbaks DicomCallbaks | |
57 | * @brief Functions to register and manage DICOM callbacks (worklists, C-Find, C-MOVE). | |
58 | * | |
59 | * @defgroup Orthanc Orthanc | |
60 | * @brief Functions to access the content of the Orthanc server. | |
61 | **/ | |
62 | ||
63 | ||
64 | ||
65 | /** | |
66 | * @defgroup Toolbox Toolbox | |
67 | * @brief Generic functions to help with the creation of plugins. | |
68 | **/ | |
69 | ||
70 | ||
71 | ||
72 | /** | |
73 | * Orthanc - A Lightweight, RESTful DICOM Store | |
74 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
75 | * Department, University Hospital of Liege, Belgium | |
76 | * | |
77 | * This program is free software: you can redistribute it and/or | |
78 | * modify it under the terms of the GNU General Public License as | |
79 | * published by the Free Software Foundation, either version 3 of the | |
80 | * License, or (at your option) any later version. | |
81 | * | |
82 | * In addition, as a special exception, the copyright holders of this | |
83 | * program give permission to link the code of its release with the | |
84 | * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
85 | * that use the same license as the "OpenSSL" library), and distribute | |
86 | * the linked executables. You must obey the GNU General Public License | |
87 | * in all respects for all of the code used other than "OpenSSL". If you | |
88 | * modify file(s) with this exception, you may extend this exception to | |
89 | * your version of the file(s), but you are not obligated to do so. If | |
90 | * you do not wish to do so, delete this exception statement from your | |
91 | * version. If you delete this exception statement from all source files | |
92 | * in the program, then also delete it here. | |
93 | * | |
94 | * This program is distributed in the hope that it will be useful, but | |
95 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
96 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
97 | * General Public License for more details. | |
98 | * | |
99 | * You should have received a copy of the GNU General Public License | |
100 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
101 | **/ | |
102 | ||
103 | ||
104 | ||
105 | #pragma once | |
106 | ||
107 | ||
108 | #include <stdio.h> | |
109 | #include <string.h> | |
110 | ||
111 | #ifdef WIN32 | |
112 | #define ORTHANC_PLUGINS_API __declspec(dllexport) | |
113 | #else | |
114 | #define ORTHANC_PLUGINS_API | |
115 | #endif | |
116 | ||
117 | #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER 1 | |
118 | #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER 1 | |
119 | #define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 0 | |
120 | ||
121 | ||
122 | ||
123 | /******************************************************************** | |
124 | ** Check that function inlining is properly supported. The use of | |
125 | ** inlining is required, to avoid the duplication of object code | |
126 | ** between two compilation modules that would use the Orthanc Plugin | |
127 | ** API. | |
128 | ********************************************************************/ | |
129 | ||
130 | /* If the auto-detection of the "inline" keyword below does not work | |
131 | automatically and that your compiler is known to properly support | |
132 | inlining, uncomment the following #define and adapt the definition | |
133 | of "static inline". */ | |
134 | ||
135 | /* #define ORTHANC_PLUGIN_INLINE static inline */ | |
136 | ||
137 | #ifndef ORTHANC_PLUGIN_INLINE | |
138 | # if __STDC_VERSION__ >= 199901L | |
139 | /* This is C99 or above: http://predef.sourceforge.net/prestd.html */ | |
140 | # define ORTHANC_PLUGIN_INLINE static inline | |
141 | # elif defined(__cplusplus) | |
142 | /* This is C++ */ | |
143 | # define ORTHANC_PLUGIN_INLINE static inline | |
144 | # elif defined(__GNUC__) | |
145 | /* This is GCC running in C89 mode */ | |
146 | # define ORTHANC_PLUGIN_INLINE static __inline | |
147 | # elif defined(_MSC_VER) | |
148 | /* This is Visual Studio running in C89 mode */ | |
149 | # define ORTHANC_PLUGIN_INLINE static __inline | |
150 | # else | |
151 | # error Your compiler is not known to support the "inline" keyword | |
152 | # endif | |
153 | #endif | |
154 | ||
155 | ||
156 | ||
157 | /******************************************************************** | |
158 | ** Inclusion of standard libraries. | |
159 | ********************************************************************/ | |
160 | ||
161 | /** | |
162 | * For Microsoft Visual Studio, a compatibility "stdint.h" can be | |
163 | * downloaded at the following URL: | |
164 | * https://orthanc.googlecode.com/hg/Resources/ThirdParty/VisualStudio/stdint.h | |
165 | **/ | |
166 | #include <stdint.h> | |
167 | ||
168 | #include <stdlib.h> | |
169 | ||
170 | ||
171 | ||
172 | /******************************************************************** | |
173 | ** Definition of the Orthanc Plugin API. | |
174 | ********************************************************************/ | |
175 | ||
176 | /** @{ */ | |
177 | ||
178 | #ifdef __cplusplus | |
179 | extern "C" | |
180 | { | |
181 | #endif | |
182 | ||
183 | /** | |
184 | * The various error codes that can be returned by the Orthanc core. | |
185 | **/ | |
186 | typedef enum | |
187 | { | |
188 | OrthancPluginErrorCode_InternalError = -1 /*!< Internal error */, | |
189 | OrthancPluginErrorCode_Success = 0 /*!< Success */, | |
190 | OrthancPluginErrorCode_Plugin = 1 /*!< Error encountered within the plugin engine */, | |
191 | OrthancPluginErrorCode_NotImplemented = 2 /*!< Not implemented yet */, | |
192 | OrthancPluginErrorCode_ParameterOutOfRange = 3 /*!< Parameter out of range */, | |
193 | OrthancPluginErrorCode_NotEnoughMemory = 4 /*!< Not enough memory */, | |
194 | OrthancPluginErrorCode_BadParameterType = 5 /*!< Bad type for a parameter */, | |
195 | OrthancPluginErrorCode_BadSequenceOfCalls = 6 /*!< Bad sequence of calls */, | |
196 | OrthancPluginErrorCode_InexistentItem = 7 /*!< Accessing an inexistent item */, | |
197 | OrthancPluginErrorCode_BadRequest = 8 /*!< Bad request */, | |
198 | OrthancPluginErrorCode_NetworkProtocol = 9 /*!< Error in the network protocol */, | |
199 | OrthancPluginErrorCode_SystemCommand = 10 /*!< Error while calling a system command */, | |
200 | OrthancPluginErrorCode_Database = 11 /*!< Error with the database engine */, | |
201 | OrthancPluginErrorCode_UriSyntax = 12 /*!< Badly formatted URI */, | |
202 | OrthancPluginErrorCode_InexistentFile = 13 /*!< Inexistent file */, | |
203 | OrthancPluginErrorCode_CannotWriteFile = 14 /*!< Cannot write to file */, | |
204 | OrthancPluginErrorCode_BadFileFormat = 15 /*!< Bad file format */, | |
205 | OrthancPluginErrorCode_Timeout = 16 /*!< Timeout */, | |
206 | OrthancPluginErrorCode_UnknownResource = 17 /*!< Unknown resource */, | |
207 | OrthancPluginErrorCode_IncompatibleDatabaseVersion = 18 /*!< Incompatible version of the database */, | |
208 | OrthancPluginErrorCode_FullStorage = 19 /*!< The file storage is full */, | |
209 | OrthancPluginErrorCode_CorruptedFile = 20 /*!< Corrupted file (e.g. inconsistent MD5 hash) */, | |
210 | OrthancPluginErrorCode_InexistentTag = 21 /*!< Inexistent tag */, | |
211 | OrthancPluginErrorCode_ReadOnly = 22 /*!< Cannot modify a read-only data structure */, | |
212 | OrthancPluginErrorCode_IncompatibleImageFormat = 23 /*!< Incompatible format of the images */, | |
213 | OrthancPluginErrorCode_IncompatibleImageSize = 24 /*!< Incompatible size of the images */, | |
214 | OrthancPluginErrorCode_SharedLibrary = 25 /*!< Error while using a shared library (plugin) */, | |
215 | OrthancPluginErrorCode_UnknownPluginService = 26 /*!< Plugin invoking an unknown service */, | |
216 | OrthancPluginErrorCode_UnknownDicomTag = 27 /*!< Unknown DICOM tag */, | |
217 | OrthancPluginErrorCode_BadJson = 28 /*!< Cannot parse a JSON document */, | |
218 | OrthancPluginErrorCode_Unauthorized = 29 /*!< Bad credentials were provided to an HTTP request */, | |
219 | OrthancPluginErrorCode_BadFont = 30 /*!< Badly formatted font file */, | |
220 | OrthancPluginErrorCode_DatabasePlugin = 31 /*!< The plugin implementing a custom database back-end does not fulfill the proper interface */, | |
221 | OrthancPluginErrorCode_StorageAreaPlugin = 32 /*!< Error in the plugin implementing a custom storage area */, | |
222 | OrthancPluginErrorCode_EmptyRequest = 33 /*!< The request is empty */, | |
223 | OrthancPluginErrorCode_NotAcceptable = 34 /*!< Cannot send a response which is acceptable according to the Accept HTTP header */, | |
224 | OrthancPluginErrorCode_SQLiteNotOpened = 1000 /*!< SQLite: The database is not opened */, | |
225 | OrthancPluginErrorCode_SQLiteAlreadyOpened = 1001 /*!< SQLite: Connection is already open */, | |
226 | OrthancPluginErrorCode_SQLiteCannotOpen = 1002 /*!< SQLite: Unable to open the database */, | |
227 | OrthancPluginErrorCode_SQLiteStatementAlreadyUsed = 1003 /*!< SQLite: This cached statement is already being referred to */, | |
228 | OrthancPluginErrorCode_SQLiteExecute = 1004 /*!< SQLite: Cannot execute a command */, | |
229 | OrthancPluginErrorCode_SQLiteRollbackWithoutTransaction = 1005 /*!< SQLite: Rolling back a nonexistent transaction (have you called Begin()?) */, | |
230 | OrthancPluginErrorCode_SQLiteCommitWithoutTransaction = 1006 /*!< SQLite: Committing a nonexistent transaction */, | |
231 | OrthancPluginErrorCode_SQLiteRegisterFunction = 1007 /*!< SQLite: Unable to register a function */, | |
232 | OrthancPluginErrorCode_SQLiteFlush = 1008 /*!< SQLite: Unable to flush the database */, | |
233 | OrthancPluginErrorCode_SQLiteCannotRun = 1009 /*!< SQLite: Cannot run a cached statement */, | |
234 | OrthancPluginErrorCode_SQLiteCannotStep = 1010 /*!< SQLite: Cannot step over a cached statement */, | |
235 | OrthancPluginErrorCode_SQLiteBindOutOfRange = 1011 /*!< SQLite: Bing a value while out of range (serious error) */, | |
236 | OrthancPluginErrorCode_SQLitePrepareStatement = 1012 /*!< SQLite: Cannot prepare a cached statement */, | |
237 | OrthancPluginErrorCode_SQLiteTransactionAlreadyStarted = 1013 /*!< SQLite: Beginning the same transaction twice */, | |
238 | OrthancPluginErrorCode_SQLiteTransactionCommit = 1014 /*!< SQLite: Failure when committing the transaction */, | |
239 | OrthancPluginErrorCode_SQLiteTransactionBegin = 1015 /*!< SQLite: Cannot start a transaction */, | |
240 | OrthancPluginErrorCode_DirectoryOverFile = 2000 /*!< The directory to be created is already occupied by a regular file */, | |
241 | OrthancPluginErrorCode_FileStorageCannotWrite = 2001 /*!< Unable to create a subdirectory or a file in the file storage */, | |
242 | OrthancPluginErrorCode_DirectoryExpected = 2002 /*!< The specified path does not point to a directory */, | |
243 | OrthancPluginErrorCode_HttpPortInUse = 2003 /*!< The TCP port of the HTTP server is privileged or already in use */, | |
244 | OrthancPluginErrorCode_DicomPortInUse = 2004 /*!< The TCP port of the DICOM server is privileged or already in use */, | |
245 | OrthancPluginErrorCode_BadHttpStatusInRest = 2005 /*!< This HTTP status is not allowed in a REST API */, | |
246 | OrthancPluginErrorCode_RegularFileExpected = 2006 /*!< The specified path does not point to a regular file */, | |
247 | OrthancPluginErrorCode_PathToExecutable = 2007 /*!< Unable to get the path to the executable */, | |
248 | OrthancPluginErrorCode_MakeDirectory = 2008 /*!< Cannot create a directory */, | |
249 | OrthancPluginErrorCode_BadApplicationEntityTitle = 2009 /*!< An application entity title (AET) cannot be empty or be longer than 16 characters */, | |
250 | OrthancPluginErrorCode_NoCFindHandler = 2010 /*!< No request handler factory for DICOM C-FIND SCP */, | |
251 | OrthancPluginErrorCode_NoCMoveHandler = 2011 /*!< No request handler factory for DICOM C-MOVE SCP */, | |
252 | OrthancPluginErrorCode_NoCStoreHandler = 2012 /*!< No request handler factory for DICOM C-STORE SCP */, | |
253 | OrthancPluginErrorCode_NoApplicationEntityFilter = 2013 /*!< No application entity filter */, | |
254 | OrthancPluginErrorCode_NoSopClassOrInstance = 2014 /*!< DicomUserConnection: Unable to find the SOP class and instance */, | |
255 | OrthancPluginErrorCode_NoPresentationContext = 2015 /*!< DicomUserConnection: No acceptable presentation context for modality */, | |
256 | OrthancPluginErrorCode_DicomFindUnavailable = 2016 /*!< DicomUserConnection: The C-FIND command is not supported by the remote SCP */, | |
257 | OrthancPluginErrorCode_DicomMoveUnavailable = 2017 /*!< DicomUserConnection: The C-MOVE command is not supported by the remote SCP */, | |
258 | OrthancPluginErrorCode_CannotStoreInstance = 2018 /*!< Cannot store an instance */, | |
259 | OrthancPluginErrorCode_CreateDicomNotString = 2019 /*!< Only string values are supported when creating DICOM instances */, | |
260 | OrthancPluginErrorCode_CreateDicomOverrideTag = 2020 /*!< Trying to override a value inherited from a parent module */, | |
261 | OrthancPluginErrorCode_CreateDicomUseContent = 2021 /*!< Use \"Content\" to inject an image into a new DICOM instance */, | |
262 | OrthancPluginErrorCode_CreateDicomNoPayload = 2022 /*!< No payload is present for one instance in the series */, | |
263 | OrthancPluginErrorCode_CreateDicomUseDataUriScheme = 2023 /*!< The payload of the DICOM instance must be specified according to Data URI scheme */, | |
264 | OrthancPluginErrorCode_CreateDicomBadParent = 2024 /*!< Trying to attach a new DICOM instance to an inexistent resource */, | |
265 | OrthancPluginErrorCode_CreateDicomParentIsInstance = 2025 /*!< Trying to attach a new DICOM instance to an instance (must be a series, study or patient) */, | |
266 | OrthancPluginErrorCode_CreateDicomParentEncoding = 2026 /*!< Unable to get the encoding of the parent resource */, | |
267 | OrthancPluginErrorCode_UnknownModality = 2027 /*!< Unknown modality */, | |
268 | OrthancPluginErrorCode_BadJobOrdering = 2028 /*!< Bad ordering of filters in a job */, | |
269 | OrthancPluginErrorCode_JsonToLuaTable = 2029 /*!< Cannot convert the given JSON object to a Lua table */, | |
270 | OrthancPluginErrorCode_CannotCreateLua = 2030 /*!< Cannot create the Lua context */, | |
271 | OrthancPluginErrorCode_CannotExecuteLua = 2031 /*!< Cannot execute a Lua command */, | |
272 | OrthancPluginErrorCode_LuaAlreadyExecuted = 2032 /*!< Arguments cannot be pushed after the Lua function is executed */, | |
273 | OrthancPluginErrorCode_LuaBadOutput = 2033 /*!< The Lua function does not give the expected number of outputs */, | |
274 | OrthancPluginErrorCode_NotLuaPredicate = 2034 /*!< The Lua function is not a predicate (only true/false outputs allowed) */, | |
275 | OrthancPluginErrorCode_LuaReturnsNoString = 2035 /*!< The Lua function does not return a string */, | |
276 | OrthancPluginErrorCode_StorageAreaAlreadyRegistered = 2036 /*!< Another plugin has already registered a custom storage area */, | |
277 | OrthancPluginErrorCode_DatabaseBackendAlreadyRegistered = 2037 /*!< Another plugin has already registered a custom database back-end */, | |
278 | OrthancPluginErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, | |
279 | OrthancPluginErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, | |
280 | OrthancPluginErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, | |
281 | OrthancPluginErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, | |
282 | OrthancPluginErrorCode_AlreadyExistingTag = 2042 /*!< Cannot override the value of a tag that already exists */, | |
283 | ||
284 | _OrthancPluginErrorCode_INTERNAL = 0x7fffffff | |
285 | } OrthancPluginErrorCode; | |
286 | ||
287 | ||
288 | /** | |
289 | * Forward declaration of one of the mandatory functions for Orthanc | |
290 | * plugins. | |
291 | **/ | |
292 | ORTHANC_PLUGINS_API const char* OrthancPluginGetName(); | |
293 | ||
294 | ||
295 | /** | |
296 | * The various HTTP methods for a REST call. | |
297 | **/ | |
298 | typedef enum | |
299 | { | |
300 | OrthancPluginHttpMethod_Get = 1, /*!< GET request */ | |
301 | OrthancPluginHttpMethod_Post = 2, /*!< POST request */ | |
302 | OrthancPluginHttpMethod_Put = 3, /*!< PUT request */ | |
303 | OrthancPluginHttpMethod_Delete = 4, /*!< DELETE request */ | |
304 | ||
305 | _OrthancPluginHttpMethod_INTERNAL = 0x7fffffff | |
306 | } OrthancPluginHttpMethod; | |
307 | ||
308 | ||
309 | /** | |
310 | * @brief The parameters of a REST request. | |
311 | * @ingroup Callbacks | |
312 | **/ | |
313 | typedef struct | |
314 | { | |
315 | /** | |
316 | * @brief The HTTP method. | |
317 | **/ | |
318 | OrthancPluginHttpMethod method; | |
319 | ||
320 | /** | |
321 | * @brief The number of groups of the regular expression. | |
322 | **/ | |
323 | uint32_t groupsCount; | |
324 | ||
325 | /** | |
326 | * @brief The matched values for the groups of the regular expression. | |
327 | **/ | |
328 | const char* const* groups; | |
329 | ||
330 | /** | |
331 | * @brief For a GET request, the number of GET parameters. | |
332 | **/ | |
333 | uint32_t getCount; | |
334 | ||
335 | /** | |
336 | * @brief For a GET request, the keys of the GET parameters. | |
337 | **/ | |
338 | const char* const* getKeys; | |
339 | ||
340 | /** | |
341 | * @brief For a GET request, the values of the GET parameters. | |
342 | **/ | |
343 | const char* const* getValues; | |
344 | ||
345 | /** | |
346 | * @brief For a PUT or POST request, the content of the body. | |
347 | **/ | |
348 | const char* body; | |
349 | ||
350 | /** | |
351 | * @brief For a PUT or POST request, the number of bytes of the body. | |
352 | **/ | |
353 | uint32_t bodySize; | |
354 | ||
355 | ||
356 | /* -------------------------------------------------- | |
357 | New in version 0.8.1 | |
358 | -------------------------------------------------- */ | |
359 | ||
360 | /** | |
361 | * @brief The number of HTTP headers. | |
362 | **/ | |
363 | uint32_t headersCount; | |
364 | ||
365 | /** | |
366 | * @brief The keys of the HTTP headers (always converted to low-case). | |
367 | **/ | |
368 | const char* const* headersKeys; | |
369 | ||
370 | /** | |
371 | * @brief The values of the HTTP headers. | |
372 | **/ | |
373 | const char* const* headersValues; | |
374 | ||
375 | } OrthancPluginHttpRequest; | |
376 | ||
377 | ||
378 | typedef enum | |
379 | { | |
380 | /* Generic services */ | |
381 | _OrthancPluginService_LogInfo = 1, | |
382 | _OrthancPluginService_LogWarning = 2, | |
383 | _OrthancPluginService_LogError = 3, | |
384 | _OrthancPluginService_GetOrthancPath = 4, | |
385 | _OrthancPluginService_GetOrthancDirectory = 5, | |
386 | _OrthancPluginService_GetConfigurationPath = 6, | |
387 | _OrthancPluginService_SetPluginProperty = 7, | |
388 | _OrthancPluginService_GetGlobalProperty = 8, | |
389 | _OrthancPluginService_SetGlobalProperty = 9, | |
390 | _OrthancPluginService_GetCommandLineArgumentsCount = 10, | |
391 | _OrthancPluginService_GetCommandLineArgument = 11, | |
392 | _OrthancPluginService_GetExpectedDatabaseVersion = 12, | |
393 | _OrthancPluginService_GetConfiguration = 13, | |
394 | _OrthancPluginService_BufferCompression = 14, | |
395 | _OrthancPluginService_ReadFile = 15, | |
396 | _OrthancPluginService_WriteFile = 16, | |
397 | _OrthancPluginService_GetErrorDescription = 17, | |
398 | _OrthancPluginService_CallHttpClient = 18, | |
399 | _OrthancPluginService_RegisterErrorCode = 19, | |
400 | _OrthancPluginService_RegisterDictionaryTag = 20, | |
401 | _OrthancPluginService_DicomBufferToJson = 21, | |
402 | _OrthancPluginService_DicomInstanceToJson = 22, | |
403 | _OrthancPluginService_CreateDicom = 23, | |
404 | _OrthancPluginService_ComputeMd5 = 24, | |
405 | _OrthancPluginService_ComputeSha1 = 25, | |
406 | _OrthancPluginService_LookupDictionary = 26, | |
407 | _OrthancPluginService_CallHttpClient2 = 27, | |
408 | _OrthancPluginService_GenerateUuid = 28, | |
409 | ||
410 | /* Registration of callbacks */ | |
411 | _OrthancPluginService_RegisterRestCallback = 1000, | |
412 | _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001, | |
413 | _OrthancPluginService_RegisterStorageArea = 1002, | |
414 | _OrthancPluginService_RegisterOnChangeCallback = 1003, | |
415 | _OrthancPluginService_RegisterRestCallbackNoLock = 1004, | |
416 | _OrthancPluginService_RegisterWorklistCallback = 1005, | |
417 | _OrthancPluginService_RegisterDecodeImageCallback = 1006, | |
418 | _OrthancPluginService_RegisterIncomingHttpRequestFilter = 1007, | |
419 | _OrthancPluginService_RegisterFindCallback = 1008, | |
420 | _OrthancPluginService_RegisterMoveCallback = 1009, | |
421 | ||
422 | /* Sending answers to REST calls */ | |
423 | _OrthancPluginService_AnswerBuffer = 2000, | |
424 | _OrthancPluginService_CompressAndAnswerPngImage = 2001, /* Unused as of Orthanc 0.9.4 */ | |
425 | _OrthancPluginService_Redirect = 2002, | |
426 | _OrthancPluginService_SendHttpStatusCode = 2003, | |
427 | _OrthancPluginService_SendUnauthorized = 2004, | |
428 | _OrthancPluginService_SendMethodNotAllowed = 2005, | |
429 | _OrthancPluginService_SetCookie = 2006, | |
430 | _OrthancPluginService_SetHttpHeader = 2007, | |
431 | _OrthancPluginService_StartMultipartAnswer = 2008, | |
432 | _OrthancPluginService_SendMultipartItem = 2009, | |
433 | _OrthancPluginService_SendHttpStatus = 2010, | |
434 | _OrthancPluginService_CompressAndAnswerImage = 2011, | |
435 | _OrthancPluginService_SendMultipartItem2 = 2012, | |
436 | ||
437 | /* Access to the Orthanc database and API */ | |
438 | _OrthancPluginService_GetDicomForInstance = 3000, | |
439 | _OrthancPluginService_RestApiGet = 3001, | |
440 | _OrthancPluginService_RestApiPost = 3002, | |
441 | _OrthancPluginService_RestApiDelete = 3003, | |
442 | _OrthancPluginService_RestApiPut = 3004, | |
443 | _OrthancPluginService_LookupPatient = 3005, | |
444 | _OrthancPluginService_LookupStudy = 3006, | |
445 | _OrthancPluginService_LookupSeries = 3007, | |
446 | _OrthancPluginService_LookupInstance = 3008, | |
447 | _OrthancPluginService_LookupStudyWithAccessionNumber = 3009, | |
448 | _OrthancPluginService_RestApiGetAfterPlugins = 3010, | |
449 | _OrthancPluginService_RestApiPostAfterPlugins = 3011, | |
450 | _OrthancPluginService_RestApiDeleteAfterPlugins = 3012, | |
451 | _OrthancPluginService_RestApiPutAfterPlugins = 3013, | |
452 | _OrthancPluginService_ReconstructMainDicomTags = 3014, | |
453 | _OrthancPluginService_RestApiGet2 = 3015, | |
454 | ||
455 | /* Access to DICOM instances */ | |
456 | _OrthancPluginService_GetInstanceRemoteAet = 4000, | |
457 | _OrthancPluginService_GetInstanceSize = 4001, | |
458 | _OrthancPluginService_GetInstanceData = 4002, | |
459 | _OrthancPluginService_GetInstanceJson = 4003, | |
460 | _OrthancPluginService_GetInstanceSimplifiedJson = 4004, | |
461 | _OrthancPluginService_HasInstanceMetadata = 4005, | |
462 | _OrthancPluginService_GetInstanceMetadata = 4006, | |
463 | _OrthancPluginService_GetInstanceOrigin = 4007, | |
464 | ||
465 | /* Services for plugins implementing a database back-end */ | |
466 | _OrthancPluginService_RegisterDatabaseBackend = 5000, | |
467 | _OrthancPluginService_DatabaseAnswer = 5001, | |
468 | _OrthancPluginService_RegisterDatabaseBackendV2 = 5002, | |
469 | _OrthancPluginService_StorageAreaCreate = 5003, | |
470 | _OrthancPluginService_StorageAreaRead = 5004, | |
471 | _OrthancPluginService_StorageAreaRemove = 5005, | |
472 | ||
473 | /* Primitives for handling images */ | |
474 | _OrthancPluginService_GetImagePixelFormat = 6000, | |
475 | _OrthancPluginService_GetImageWidth = 6001, | |
476 | _OrthancPluginService_GetImageHeight = 6002, | |
477 | _OrthancPluginService_GetImagePitch = 6003, | |
478 | _OrthancPluginService_GetImageBuffer = 6004, | |
479 | _OrthancPluginService_UncompressImage = 6005, | |
480 | _OrthancPluginService_FreeImage = 6006, | |
481 | _OrthancPluginService_CompressImage = 6007, | |
482 | _OrthancPluginService_ConvertPixelFormat = 6008, | |
483 | _OrthancPluginService_GetFontsCount = 6009, | |
484 | _OrthancPluginService_GetFontInfo = 6010, | |
485 | _OrthancPluginService_DrawText = 6011, | |
486 | _OrthancPluginService_CreateImage = 6012, | |
487 | _OrthancPluginService_CreateImageAccessor = 6013, | |
488 | _OrthancPluginService_DecodeDicomImage = 6014, | |
489 | ||
490 | /* Primitives for handling C-Find, C-Move and worklists */ | |
491 | _OrthancPluginService_WorklistAddAnswer = 7000, | |
492 | _OrthancPluginService_WorklistMarkIncomplete = 7001, | |
493 | _OrthancPluginService_WorklistIsMatch = 7002, | |
494 | _OrthancPluginService_WorklistGetDicomQuery = 7003, | |
495 | _OrthancPluginService_FindAddAnswer = 7004, | |
496 | _OrthancPluginService_FindMarkIncomplete = 7005, | |
497 | _OrthancPluginService_GetFindQuerySize = 7006, | |
498 | _OrthancPluginService_GetFindQueryTag = 7007, | |
499 | _OrthancPluginService_GetFindQueryTagName = 7008, | |
500 | _OrthancPluginService_GetFindQueryValue = 7009, | |
501 | ||
502 | _OrthancPluginService_INTERNAL = 0x7fffffff | |
503 | } _OrthancPluginService; | |
504 | ||
505 | ||
506 | typedef enum | |
507 | { | |
508 | _OrthancPluginProperty_Description = 1, | |
509 | _OrthancPluginProperty_RootUri = 2, | |
510 | _OrthancPluginProperty_OrthancExplorer = 3, | |
511 | ||
512 | _OrthancPluginProperty_INTERNAL = 0x7fffffff | |
513 | } _OrthancPluginProperty; | |
514 | ||
515 | ||
516 | ||
517 | /** | |
518 | * The memory layout of the pixels of an image. | |
519 | * @ingroup Images | |
520 | **/ | |
521 | typedef enum | |
522 | { | |
523 | /** | |
524 | * @brief Graylevel 8bpp image. | |
525 | * | |
526 | * The image is graylevel. Each pixel is unsigned and stored in | |
527 | * one byte. | |
528 | **/ | |
529 | OrthancPluginPixelFormat_Grayscale8 = 1, | |
530 | ||
531 | /** | |
532 | * @brief Graylevel, unsigned 16bpp image. | |
533 | * | |
534 | * The image is graylevel. Each pixel is unsigned and stored in | |
535 | * two bytes. | |
536 | **/ | |
537 | OrthancPluginPixelFormat_Grayscale16 = 2, | |
538 | ||
539 | /** | |
540 | * @brief Graylevel, signed 16bpp image. | |
541 | * | |
542 | * The image is graylevel. Each pixel is signed and stored in two | |
543 | * bytes. | |
544 | **/ | |
545 | OrthancPluginPixelFormat_SignedGrayscale16 = 3, | |
546 | ||
547 | /** | |
548 | * @brief Color image in RGB24 format. | |
549 | * | |
550 | * This format describes a color image. The pixels are stored in 3 | |
551 | * consecutive bytes. The memory layout is RGB. | |
552 | **/ | |
553 | OrthancPluginPixelFormat_RGB24 = 4, | |
554 | ||
555 | /** | |
556 | * @brief Color image in RGBA32 format. | |
557 | * | |
558 | * This format describes a color image. The pixels are stored in 4 | |
559 | * consecutive bytes. The memory layout is RGBA. | |
560 | **/ | |
561 | OrthancPluginPixelFormat_RGBA32 = 5, | |
562 | ||
563 | OrthancPluginPixelFormat_Unknown = 6, /*!< Unknown pixel format */ | |
564 | ||
565 | _OrthancPluginPixelFormat_INTERNAL = 0x7fffffff | |
566 | } OrthancPluginPixelFormat; | |
567 | ||
568 | ||
569 | ||
570 | /** | |
571 | * The content types that are supported by Orthanc plugins. | |
572 | **/ | |
573 | typedef enum | |
574 | { | |
575 | OrthancPluginContentType_Unknown = 0, /*!< Unknown content type */ | |
576 | OrthancPluginContentType_Dicom = 1, /*!< DICOM */ | |
577 | OrthancPluginContentType_DicomAsJson = 2, /*!< JSON summary of a DICOM file */ | |
578 | ||
579 | _OrthancPluginContentType_INTERNAL = 0x7fffffff | |
580 | } OrthancPluginContentType; | |
581 | ||
582 | ||
583 | ||
584 | /** | |
585 | * The supported types of DICOM resources. | |
586 | **/ | |
587 | typedef enum | |
588 | { | |
589 | OrthancPluginResourceType_Patient = 0, /*!< Patient */ | |
590 | OrthancPluginResourceType_Study = 1, /*!< Study */ | |
591 | OrthancPluginResourceType_Series = 2, /*!< Series */ | |
592 | OrthancPluginResourceType_Instance = 3, /*!< Instance */ | |
593 | OrthancPluginResourceType_None = 4, /*!< Unavailable resource type */ | |
594 | ||
595 | _OrthancPluginResourceType_INTERNAL = 0x7fffffff | |
596 | } OrthancPluginResourceType; | |
597 | ||
598 | ||
599 | ||
600 | /** | |
601 | * The supported types of changes that can happen to DICOM resources. | |
602 | * @ingroup Callbacks | |
603 | **/ | |
604 | typedef enum | |
605 | { | |
606 | OrthancPluginChangeType_CompletedSeries = 0, /*!< Series is now complete */ | |
607 | OrthancPluginChangeType_Deleted = 1, /*!< Deleted resource */ | |
608 | OrthancPluginChangeType_NewChildInstance = 2, /*!< A new instance was added to this resource */ | |
609 | OrthancPluginChangeType_NewInstance = 3, /*!< New instance received */ | |
610 | OrthancPluginChangeType_NewPatient = 4, /*!< New patient created */ | |
611 | OrthancPluginChangeType_NewSeries = 5, /*!< New series created */ | |
612 | OrthancPluginChangeType_NewStudy = 6, /*!< New study created */ | |
613 | OrthancPluginChangeType_StablePatient = 7, /*!< Timeout: No new instance in this patient */ | |
614 | OrthancPluginChangeType_StableSeries = 8, /*!< Timeout: No new instance in this series */ | |
615 | OrthancPluginChangeType_StableStudy = 9, /*!< Timeout: No new instance in this study */ | |
616 | OrthancPluginChangeType_OrthancStarted = 10, /*!< Orthanc has started */ | |
617 | OrthancPluginChangeType_OrthancStopped = 11, /*!< Orthanc is stopping */ | |
618 | OrthancPluginChangeType_UpdatedAttachment = 12, /*!< Some user-defined attachment has changed for this resource */ | |
619 | OrthancPluginChangeType_UpdatedMetadata = 13, /*!< Some user-defined metadata has changed for this resource */ | |
620 | ||
621 | _OrthancPluginChangeType_INTERNAL = 0x7fffffff | |
622 | } OrthancPluginChangeType; | |
623 | ||
624 | ||
625 | /** | |
626 | * The compression algorithms that are supported by the Orthanc core. | |
627 | * @ingroup Images | |
628 | **/ | |
629 | typedef enum | |
630 | { | |
631 | OrthancPluginCompressionType_Zlib = 0, /*!< Standard zlib compression */ | |
632 | OrthancPluginCompressionType_ZlibWithSize = 1, /*!< zlib, prefixed with uncompressed size (uint64_t) */ | |
633 | OrthancPluginCompressionType_Gzip = 2, /*!< Standard gzip compression */ | |
634 | OrthancPluginCompressionType_GzipWithSize = 3, /*!< gzip, prefixed with uncompressed size (uint64_t) */ | |
635 | ||
636 | _OrthancPluginCompressionType_INTERNAL = 0x7fffffff | |
637 | } OrthancPluginCompressionType; | |
638 | ||
639 | ||
640 | /** | |
641 | * The image formats that are supported by the Orthanc core. | |
642 | * @ingroup Images | |
643 | **/ | |
644 | typedef enum | |
645 | { | |
646 | OrthancPluginImageFormat_Png = 0, /*!< Image compressed using PNG */ | |
647 | OrthancPluginImageFormat_Jpeg = 1, /*!< Image compressed using JPEG */ | |
648 | OrthancPluginImageFormat_Dicom = 2, /*!< Image compressed using DICOM */ | |
649 | ||
650 | _OrthancPluginImageFormat_INTERNAL = 0x7fffffff | |
651 | } OrthancPluginImageFormat; | |
652 | ||
653 | ||
654 | /** | |
655 | * The value representations present in the DICOM standard (version 2013). | |
656 | * @ingroup Toolbox | |
657 | **/ | |
658 | typedef enum | |
659 | { | |
660 | OrthancPluginValueRepresentation_AE = 1, /*!< Application Entity */ | |
661 | OrthancPluginValueRepresentation_AS = 2, /*!< Age String */ | |
662 | OrthancPluginValueRepresentation_AT = 3, /*!< Attribute Tag */ | |
663 | OrthancPluginValueRepresentation_CS = 4, /*!< Code String */ | |
664 | OrthancPluginValueRepresentation_DA = 5, /*!< Date */ | |
665 | OrthancPluginValueRepresentation_DS = 6, /*!< Decimal String */ | |
666 | OrthancPluginValueRepresentation_DT = 7, /*!< Date Time */ | |
667 | OrthancPluginValueRepresentation_FD = 8, /*!< Floating Point Double */ | |
668 | OrthancPluginValueRepresentation_FL = 9, /*!< Floating Point Single */ | |
669 | OrthancPluginValueRepresentation_IS = 10, /*!< Integer String */ | |
670 | OrthancPluginValueRepresentation_LO = 11, /*!< Long String */ | |
671 | OrthancPluginValueRepresentation_LT = 12, /*!< Long Text */ | |
672 | OrthancPluginValueRepresentation_OB = 13, /*!< Other Byte String */ | |
673 | OrthancPluginValueRepresentation_OF = 14, /*!< Other Float String */ | |
674 | OrthancPluginValueRepresentation_OW = 15, /*!< Other Word String */ | |
675 | OrthancPluginValueRepresentation_PN = 16, /*!< Person Name */ | |
676 | OrthancPluginValueRepresentation_SH = 17, /*!< Short String */ | |
677 | OrthancPluginValueRepresentation_SL = 18, /*!< Signed Long */ | |
678 | OrthancPluginValueRepresentation_SQ = 19, /*!< Sequence of Items */ | |
679 | OrthancPluginValueRepresentation_SS = 20, /*!< Signed Short */ | |
680 | OrthancPluginValueRepresentation_ST = 21, /*!< Short Text */ | |
681 | OrthancPluginValueRepresentation_TM = 22, /*!< Time */ | |
682 | OrthancPluginValueRepresentation_UI = 23, /*!< Unique Identifier (UID) */ | |
683 | OrthancPluginValueRepresentation_UL = 24, /*!< Unsigned Long */ | |
684 | OrthancPluginValueRepresentation_UN = 25, /*!< Unknown */ | |
685 | OrthancPluginValueRepresentation_US = 26, /*!< Unsigned Short */ | |
686 | OrthancPluginValueRepresentation_UT = 27, /*!< Unlimited Text */ | |
687 | ||
688 | _OrthancPluginValueRepresentation_INTERNAL = 0x7fffffff | |
689 | } OrthancPluginValueRepresentation; | |
690 | ||
691 | ||
692 | /** | |
693 | * The possible output formats for a DICOM-to-JSON conversion. | |
694 | * @ingroup Toolbox | |
695 | * @see OrthancPluginDicomToJson() | |
696 | **/ | |
697 | typedef enum | |
698 | { | |
699 | OrthancPluginDicomToJsonFormat_Full = 1, /*!< Full output, with most details */ | |
700 | OrthancPluginDicomToJsonFormat_Short = 2, /*!< Tags output as hexadecimal numbers */ | |
701 | OrthancPluginDicomToJsonFormat_Human = 3, /*!< Human-readable JSON */ | |
702 | ||
703 | _OrthancPluginDicomToJsonFormat_INTERNAL = 0x7fffffff | |
704 | } OrthancPluginDicomToJsonFormat; | |
705 | ||
706 | ||
707 | /** | |
708 | * Flags to customize a DICOM-to-JSON conversion. By default, binary | |
709 | * tags are formatted using Data URI scheme. | |
710 | * @ingroup Toolbox | |
711 | **/ | |
712 | typedef enum | |
713 | { | |
714 | OrthancPluginDicomToJsonFlags_IncludeBinary = (1 << 0), /*!< Include the binary tags */ | |
715 | OrthancPluginDicomToJsonFlags_IncludePrivateTags = (1 << 1), /*!< Include the private tags */ | |
716 | OrthancPluginDicomToJsonFlags_IncludeUnknownTags = (1 << 2), /*!< Include the tags unknown by the dictionary */ | |
717 | OrthancPluginDicomToJsonFlags_IncludePixelData = (1 << 3), /*!< Include the pixel data */ | |
718 | OrthancPluginDicomToJsonFlags_ConvertBinaryToAscii = (1 << 4), /*!< Output binary tags as-is, dropping non-ASCII */ | |
719 | OrthancPluginDicomToJsonFlags_ConvertBinaryToNull = (1 << 5), /*!< Signal binary tags as null values */ | |
720 | ||
721 | _OrthancPluginDicomToJsonFlags_INTERNAL = 0x7fffffff | |
722 | } OrthancPluginDicomToJsonFlags; | |
723 | ||
724 | ||
725 | /** | |
726 | * Flags to the creation of a DICOM file. | |
727 | * @ingroup Toolbox | |
728 | * @see OrthancPluginCreateDicom() | |
729 | **/ | |
730 | typedef enum | |
731 | { | |
732 | OrthancPluginCreateDicomFlags_DecodeDataUriScheme = (1 << 0), /*!< Decode fields encoded using data URI scheme */ | |
733 | OrthancPluginCreateDicomFlags_GenerateIdentifiers = (1 << 1), /*!< Automatically generate DICOM identifiers */ | |
734 | ||
735 | _OrthancPluginCreateDicomFlags_INTERNAL = 0x7fffffff | |
736 | } OrthancPluginCreateDicomFlags; | |
737 | ||
738 | ||
739 | /** | |
740 | * The constraints on the DICOM identifiers that must be supported | |
741 | * by the database plugins. | |
742 | **/ | |
743 | typedef enum | |
744 | { | |
745 | OrthancPluginIdentifierConstraint_Equal = 1, /*!< Equal */ | |
746 | OrthancPluginIdentifierConstraint_SmallerOrEqual = 2, /*!< Less or equal */ | |
747 | OrthancPluginIdentifierConstraint_GreaterOrEqual = 3, /*!< More or equal */ | |
748 | OrthancPluginIdentifierConstraint_Wildcard = 4, /*!< Case-sensitive wildcard matching (with * and ?) */ | |
749 | ||
750 | _OrthancPluginIdentifierConstraint_INTERNAL = 0x7fffffff | |
751 | } OrthancPluginIdentifierConstraint; | |
752 | ||
753 | ||
754 | /** | |
755 | * The origin of a DICOM instance that has been received by Orthanc. | |
756 | **/ | |
757 | typedef enum | |
758 | { | |
759 | OrthancPluginInstanceOrigin_Unknown = 1, /*!< Unknown origin */ | |
760 | OrthancPluginInstanceOrigin_DicomProtocol = 2, /*!< Instance received through DICOM protocol */ | |
761 | OrthancPluginInstanceOrigin_RestApi = 3, /*!< Instance received through REST API of Orthanc */ | |
762 | OrthancPluginInstanceOrigin_Plugin = 4, /*!< Instance added to Orthanc by a plugin */ | |
763 | OrthancPluginInstanceOrigin_Lua = 5, /*!< Instance added to Orthanc by a Lua script */ | |
764 | ||
765 | _OrthancPluginInstanceOrigin_INTERNAL = 0x7fffffff | |
766 | } OrthancPluginInstanceOrigin; | |
767 | ||
768 | ||
769 | /** | |
770 | * @brief A memory buffer allocated by the core system of Orthanc. | |
771 | * | |
772 | * A memory buffer allocated by the core system of Orthanc. When the | |
773 | * content of the buffer is not useful anymore, it must be free by a | |
774 | * call to ::OrthancPluginFreeMemoryBuffer(). | |
775 | **/ | |
776 | typedef struct | |
777 | { | |
778 | /** | |
779 | * @brief The content of the buffer. | |
780 | **/ | |
781 | void* data; | |
782 | ||
783 | /** | |
784 | * @brief The number of bytes in the buffer. | |
785 | **/ | |
786 | uint32_t size; | |
787 | } OrthancPluginMemoryBuffer; | |
788 | ||
789 | ||
790 | ||
791 | ||
792 | /** | |
793 | * @brief Opaque structure that represents the HTTP connection to the client application. | |
794 | * @ingroup Callback | |
795 | **/ | |
796 | typedef struct _OrthancPluginRestOutput_t OrthancPluginRestOutput; | |
797 | ||
798 | ||
799 | ||
800 | /** | |
801 | * @brief Opaque structure that represents a DICOM instance received by Orthanc. | |
802 | **/ | |
803 | typedef struct _OrthancPluginDicomInstance_t OrthancPluginDicomInstance; | |
804 | ||
805 | ||
806 | ||
807 | /** | |
808 | * @brief Opaque structure that represents an image that is uncompressed in memory. | |
809 | * @ingroup Images | |
810 | **/ | |
811 | typedef struct _OrthancPluginImage_t OrthancPluginImage; | |
812 | ||
813 | ||
814 | ||
815 | /** | |
816 | * @brief Opaque structure that represents the storage area that is actually used by Orthanc. | |
817 | * @ingroup Images | |
818 | **/ | |
819 | typedef struct _OrthancPluginStorageArea_t OrthancPluginStorageArea; | |
820 | ||
821 | ||
822 | ||
823 | /** | |
824 | * @brief Opaque structure to an object that represents a C-Find query for worklists. | |
825 | * @ingroup DicomCallbacks | |
826 | **/ | |
827 | typedef struct _OrthancPluginWorklistQuery_t OrthancPluginWorklistQuery; | |
828 | ||
829 | ||
830 | ||
831 | /** | |
832 | * @brief Opaque structure to an object that represents the answers to a C-Find query for worklists. | |
833 | * @ingroup DicomCallbacks | |
834 | **/ | |
835 | typedef struct _OrthancPluginWorklistAnswers_t OrthancPluginWorklistAnswers; | |
836 | ||
837 | ||
838 | ||
839 | /** | |
840 | * @brief Opaque structure to an object that represents a C-Find query. | |
841 | * @ingroup DicomCallbacks | |
842 | **/ | |
843 | typedef struct _OrthancPluginFindQuery_t OrthancPluginFindQuery; | |
844 | ||
845 | ||
846 | ||
847 | /** | |
848 | * @brief Opaque structure to an object that represents the answers to a C-Find query for worklists. | |
849 | * @ingroup DicomCallbacks | |
850 | **/ | |
851 | typedef struct _OrthancPluginFindAnswers_t OrthancPluginFindAnswers; | |
852 | ||
853 | ||
854 | ||
855 | /** | |
856 | * @brief Signature of a callback function that answers to a REST request. | |
857 | * @ingroup Callbacks | |
858 | **/ | |
859 | typedef OrthancPluginErrorCode (*OrthancPluginRestCallback) ( | |
860 | OrthancPluginRestOutput* output, | |
861 | const char* url, | |
862 | const OrthancPluginHttpRequest* request); | |
863 | ||
864 | ||
865 | ||
866 | /** | |
867 | * @brief Signature of a callback function that is triggered when Orthanc receives a DICOM instance. | |
868 | * @ingroup Callbacks | |
869 | **/ | |
870 | typedef OrthancPluginErrorCode (*OrthancPluginOnStoredInstanceCallback) ( | |
871 | OrthancPluginDicomInstance* instance, | |
872 | const char* instanceId); | |
873 | ||
874 | ||
875 | ||
876 | /** | |
877 | * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource. | |
878 | * @ingroup Callbacks | |
879 | **/ | |
880 | typedef OrthancPluginErrorCode (*OrthancPluginOnChangeCallback) ( | |
881 | OrthancPluginChangeType changeType, | |
882 | OrthancPluginResourceType resourceType, | |
883 | const char* resourceId); | |
884 | ||
885 | ||
886 | ||
887 | /** | |
888 | * @brief Signature of a callback function to decode a DICOM instance as an image. | |
889 | * @ingroup Callbacks | |
890 | **/ | |
891 | typedef OrthancPluginErrorCode (*OrthancPluginDecodeImageCallback) ( | |
892 | OrthancPluginImage** target, | |
893 | const void* dicom, | |
894 | const uint32_t size, | |
895 | uint32_t frameIndex); | |
896 | ||
897 | ||
898 | ||
899 | /** | |
900 | * @brief Signature of a function to free dynamic memory. | |
901 | **/ | |
902 | typedef void (*OrthancPluginFree) (void* buffer); | |
903 | ||
904 | ||
905 | ||
906 | /** | |
907 | * @brief Callback for writing to the storage area. | |
908 | * | |
909 | * Signature of a callback function that is triggered when Orthanc writes a file to the storage area. | |
910 | * | |
911 | * @param uuid The UUID of the file. | |
912 | * @param content The content of the file. | |
913 | * @param size The size of the file. | |
914 | * @param type The content type corresponding to this file. | |
915 | * @return 0 if success, other value if error. | |
916 | * @ingroup Callbacks | |
917 | **/ | |
918 | typedef OrthancPluginErrorCode (*OrthancPluginStorageCreate) ( | |
919 | const char* uuid, | |
920 | const void* content, | |
921 | int64_t size, | |
922 | OrthancPluginContentType type); | |
923 | ||
924 | ||
925 | ||
926 | /** | |
927 | * @brief Callback for reading from the storage area. | |
928 | * | |
929 | * Signature of a callback function that is triggered when Orthanc reads a file from the storage area. | |
930 | * | |
931 | * @param content The content of the file (output). | |
932 | * @param size The size of the file (output). | |
933 | * @param uuid The UUID of the file of interest. | |
934 | * @param type The content type corresponding to this file. | |
935 | * @return 0 if success, other value if error. | |
936 | * @ingroup Callbacks | |
937 | **/ | |
938 | typedef OrthancPluginErrorCode (*OrthancPluginStorageRead) ( | |
939 | void** content, | |
940 | int64_t* size, | |
941 | const char* uuid, | |
942 | OrthancPluginContentType type); | |
943 | ||
944 | ||
945 | ||
946 | /** | |
947 | * @brief Callback for removing a file from the storage area. | |
948 | * | |
949 | * Signature of a callback function that is triggered when Orthanc deletes a file from the storage area. | |
950 | * | |
951 | * @param uuid The UUID of the file to be removed. | |
952 | * @param type The content type corresponding to this file. | |
953 | * @return 0 if success, other value if error. | |
954 | * @ingroup Callbacks | |
955 | **/ | |
956 | typedef OrthancPluginErrorCode (*OrthancPluginStorageRemove) ( | |
957 | const char* uuid, | |
958 | OrthancPluginContentType type); | |
959 | ||
960 | ||
961 | ||
962 | /** | |
963 | * @brief Callback to handle the C-Find SCP requests for worklists. | |
964 | * | |
965 | * Signature of a callback function that is triggered when Orthanc | |
966 | * receives a C-Find SCP request against modality worklists. | |
967 | * | |
968 | * @param answers The target structure where answers must be stored. | |
969 | * @param query The worklist query. | |
970 | * @param issuerAet The Application Entity Title (AET) of the modality from which the request originates. | |
971 | * @param calledAet The Application Entity Title (AET) of the modality that is called by the request. | |
972 | * @return 0 if success, other value if error. | |
973 | * @ingroup DicomCallbacks | |
974 | **/ | |
975 | typedef OrthancPluginErrorCode (*OrthancPluginWorklistCallback) ( | |
976 | OrthancPluginWorklistAnswers* answers, | |
977 | const OrthancPluginWorklistQuery* query, | |
978 | const char* issuerAet, | |
979 | const char* calledAet); | |
980 | ||
981 | ||
982 | ||
983 | /** | |
984 | * @brief Callback to filter incoming HTTP requests received by Orthanc. | |
985 | * | |
986 | * Signature of a callback function that is triggered whenever | |
987 | * Orthanc receives an HTTP/REST request, and that answers whether | |
988 | * this request should be allowed. If the callback returns "0" | |
989 | * ("false"), the server answers with HTTP status code 403 | |
990 | * (Forbidden). | |
991 | * | |
992 | * @param method The HTTP method used by the request. | |
993 | * @param uri The URI of interest. | |
994 | * @param ip The IP address of the HTTP client. | |
995 | * @param headersCount The number of HTTP headers. | |
996 | * @param headersKeys The keys of the HTTP headers (always converted to low-case). | |
997 | * @param headersValues The values of the HTTP headers. | |
998 | * @return 0 if forbidden access, 1 if allowed access, -1 if error. | |
999 | * @ingroup Callback | |
1000 | **/ | |
1001 | typedef int32_t (*OrthancPluginIncomingHttpRequestFilter) ( | |
1002 | OrthancPluginHttpMethod method, | |
1003 | const char* uri, | |
1004 | const char* ip, | |
1005 | uint32_t headersCount, | |
1006 | const char* const* headersKeys, | |
1007 | const char* const* headersValues); | |
1008 | ||
1009 | ||
1010 | ||
1011 | /** | |
1012 | * @brief Callback to handle incoming C-Find SCP requests. | |
1013 | * | |
1014 | * Signature of a callback function that is triggered whenever | |
1015 | * Orthanc receives a C-Find SCP request not concerning modality | |
1016 | * worklists. | |
1017 | * | |
1018 | * @param answers The target structure where answers must be stored. | |
1019 | * @param query The worklist query. | |
1020 | * @param issuerAet The Application Entity Title (AET) of the modality from which the request originates. | |
1021 | * @param calledAet The Application Entity Title (AET) of the modality that is called by the request. | |
1022 | * @return 0 if success, other value if error. | |
1023 | * @ingroup DicomCallbacks | |
1024 | **/ | |
1025 | typedef OrthancPluginErrorCode (*OrthancPluginFindCallback) ( | |
1026 | OrthancPluginFindAnswers* answers, | |
1027 | const OrthancPluginFindQuery* query, | |
1028 | const char* issuerAet, | |
1029 | const char* calledAet); | |
1030 | ||
1031 | ||
1032 | ||
1033 | /** | |
1034 | * @brief Callback to handle incoming C-Move SCP requests. | |
1035 | * | |
1036 | * Signature of a callback function that is triggered whenever | |
1037 | * Orthanc receives a C-Move SCP request. The callback receives the | |
1038 | * type of the resource of interest (study, series, instance...) | |
1039 | * together with the DICOM tags containing its identifiers. In turn, | |
1040 | * the plugin must create a driver object that will be responsible | |
1041 | * for driving the successive move suboperations. | |
1042 | * | |
1043 | * @param resourceType The type of the resource of interest. Note | |
1044 | * that this might be set to ResourceType_None if the | |
1045 | * QueryRetrieveLevel (0008,0052) tag was not provided by the | |
1046 | * issuer. | |
1047 | * @param patientId Content of the PatientID (0x0010, 0x0020) tag of the resource of interest. Might be NULL. | |
1048 | * @param accessionNumber Content of the AccessionNumber (0x0008, 0x0050) tag. Might be NULL. | |
1049 | * @param studyInstanceUid Content of the StudyInstanceUID (0x0020, 0x000d) tag. Might be NULL. | |
1050 | * @param seriesInstanceUid Content of the SeriesInstanceUID (0x0020, 0x000e) tag. Might be NULL. | |
1051 | * @param sopInstanceUid Content of the SOPInstanceUID (0x0008, 0x0018) tag. Might be NULL. | |
1052 | * @param issuerAet The Application Entity Title (AET) of the | |
1053 | * modality from which the request originates. | |
1054 | * @param sourceAet The Application Entity Title (AET) of the | |
1055 | * modality that should send its DICOM files to another modality. | |
1056 | * @param targetAet The Application Entity Title (AET) of the | |
1057 | * modality that should receive the DICOM files. | |
1058 | * | |
1059 | * @return The NULL value if the plugin cannot deal with this query, | |
1060 | * or a pointer to the driver object that is responsible for | |
1061 | * handling the successive move suboperations. | |
1062 | * | |
1063 | * @note If targetAet equals sourceAet, this is actually a query/retrieve operation. | |
1064 | * @ingroup DicomCallbacks | |
1065 | **/ | |
1066 | typedef void* (*OrthancPluginMoveCallback) ( | |
1067 | OrthancPluginResourceType resourceType, | |
1068 | const char* patientId, | |
1069 | const char* accessionNumber, | |
1070 | const char* studyInstanceUid, | |
1071 | const char* seriesInstanceUid, | |
1072 | const char* sopInstanceUid, | |
1073 | const char* issuerAet, | |
1074 | const char* sourceAet, | |
1075 | const char* targetAet, | |
1076 | uint16_t moveOriginatorId); | |
1077 | ||
1078 | ||
1079 | /** | |
1080 | * @brief Callback to read the size of a C-Move driver. | |
1081 | * | |
1082 | * Signature of a callback function that returns the number of | |
1083 | * C-Move suboperations that are to be achieved by the given C-Move | |
1084 | * driver. This driver is the return value of a previous call to the | |
1085 | * OrthancPluginMoveCallback() callback. | |
1086 | * | |
1087 | * @param moveDriver The C-Move driver of interest. | |
1088 | * @return The number of suboperations. | |
1089 | **/ | |
1090 | typedef uint32_t (*OrthancPluginGetMoveSize) (void* moveDriver); | |
1091 | ||
1092 | ||
1093 | /** | |
1094 | * @brief Callback to apply one C-Move suboperation. | |
1095 | * | |
1096 | * Signature of a callback function that applies the next C-Move | |
1097 | * suboperation that os to be achieved by the given C-Move | |
1098 | * driver. This driver is the return value of a previous call to the | |
1099 | * OrthancPluginMoveCallback() callback. | |
1100 | * | |
1101 | * @param moveDriver The C-Move driver of interest. | |
1102 | * @return 0 if success, or the error code if failure. | |
1103 | **/ | |
1104 | typedef OrthancPluginErrorCode (*OrthancPluginApplyMove) (void* moveDriver); | |
1105 | ||
1106 | ||
1107 | /** | |
1108 | * @brief Callback to free one C-Move driver. | |
1109 | * | |
1110 | * Signature of a callback function that releases the resources | |
1111 | * allocated by the given C-Move driver. This driver is the return | |
1112 | * value of a previous call to the OrthancPluginMoveCallback() | |
1113 | * callback. | |
1114 | * | |
1115 | * @param moveDriver The C-Move driver of interest. | |
1116 | **/ | |
1117 | typedef void (*OrthancPluginFreeMove) (void* moveDriver); | |
1118 | ||
1119 | ||
1120 | ||
1121 | /** | |
1122 | * @brief Data structure that contains information about the Orthanc core. | |
1123 | **/ | |
1124 | typedef struct _OrthancPluginContext_t | |
1125 | { | |
1126 | void* pluginsManager; | |
1127 | const char* orthancVersion; | |
1128 | OrthancPluginFree Free; | |
1129 | OrthancPluginErrorCode (*InvokeService) (struct _OrthancPluginContext_t* context, | |
1130 | _OrthancPluginService service, | |
1131 | const void* params); | |
1132 | } OrthancPluginContext; | |
1133 | ||
1134 | ||
1135 | ||
1136 | /** | |
1137 | * @brief An entry in the dictionary of DICOM tags. | |
1138 | **/ | |
1139 | typedef struct | |
1140 | { | |
1141 | uint16_t group; /*!< The group of the tag */ | |
1142 | uint16_t element; /*!< The element of the tag */ | |
1143 | OrthancPluginValueRepresentation vr; /*!< The value representation of the tag */ | |
1144 | uint32_t minMultiplicity; /*!< The minimum multiplicity of the tag */ | |
1145 | uint32_t maxMultiplicity; /*!< The maximum multiplicity of the tag (0 means arbitrary) */ | |
1146 | } OrthancPluginDictionaryEntry; | |
1147 | ||
1148 | ||
1149 | ||
1150 | /** | |
1151 | * @brief Free a string. | |
1152 | * | |
1153 | * Free a string that was allocated by the core system of Orthanc. | |
1154 | * | |
1155 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1156 | * @param str The string to be freed. | |
1157 | **/ | |
1158 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeString( | |
1159 | OrthancPluginContext* context, | |
1160 | char* str) | |
1161 | { | |
1162 | if (str != NULL) | |
1163 | { | |
1164 | context->Free(str); | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | ||
1169 | /** | |
1170 | * @brief Check the compatibility of the plugin wrt. the version of its hosting Orthanc. | |
1171 | * | |
1172 | * This function checks whether the version of this C header is | |
1173 | * compatible with the current version of Orthanc. The result of | |
1174 | * this function should always be checked in the | |
1175 | * OrthancPluginInitialize() entry point of the plugin. | |
1176 | * | |
1177 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1178 | * @return 1 if and only if the versions are compatible. If the | |
1179 | * result is 0, the initialization of the plugin should fail. | |
1180 | * @ingroup Callbacks | |
1181 | **/ | |
1182 | ORTHANC_PLUGIN_INLINE int OrthancPluginCheckVersion( | |
1183 | OrthancPluginContext* context) | |
1184 | { | |
1185 | int major, minor, revision; | |
1186 | ||
1187 | if (sizeof(int32_t) != sizeof(OrthancPluginErrorCode) || | |
1188 | sizeof(int32_t) != sizeof(OrthancPluginHttpMethod) || | |
1189 | sizeof(int32_t) != sizeof(_OrthancPluginService) || | |
1190 | sizeof(int32_t) != sizeof(_OrthancPluginProperty) || | |
1191 | sizeof(int32_t) != sizeof(OrthancPluginPixelFormat) || | |
1192 | sizeof(int32_t) != sizeof(OrthancPluginContentType) || | |
1193 | sizeof(int32_t) != sizeof(OrthancPluginResourceType) || | |
1194 | sizeof(int32_t) != sizeof(OrthancPluginChangeType) || | |
1195 | sizeof(int32_t) != sizeof(OrthancPluginCompressionType) || | |
1196 | sizeof(int32_t) != sizeof(OrthancPluginImageFormat) || | |
1197 | sizeof(int32_t) != sizeof(OrthancPluginValueRepresentation) || | |
1198 | sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFormat) || | |
1199 | sizeof(int32_t) != sizeof(OrthancPluginDicomToJsonFlags) || | |
1200 | sizeof(int32_t) != sizeof(OrthancPluginCreateDicomFlags) || | |
1201 | sizeof(int32_t) != sizeof(OrthancPluginIdentifierConstraint) || | |
1202 | sizeof(int32_t) != sizeof(OrthancPluginInstanceOrigin)) | |
1203 | { | |
1204 | /* Mismatch in the size of the enumerations */ | |
1205 | return 0; | |
1206 | } | |
1207 | ||
1208 | /* Assume compatibility with the mainline */ | |
1209 | if (!strcmp(context->orthancVersion, "mainline")) | |
1210 | { | |
1211 | return 1; | |
1212 | } | |
1213 | ||
1214 | /* Parse the version of the Orthanc core */ | |
1215 | if ( | |
1216 | #ifdef _MSC_VER | |
1217 | sscanf_s | |
1218 | #else | |
1219 | sscanf | |
1220 | #endif | |
1221 | (context->orthancVersion, "%4d.%4d.%4d", &major, &minor, &revision) != 3) | |
1222 | { | |
1223 | return 0; | |
1224 | } | |
1225 | ||
1226 | /* Check the major number of the version */ | |
1227 | ||
1228 | if (major > ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) | |
1229 | { | |
1230 | return 1; | |
1231 | } | |
1232 | ||
1233 | if (major < ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER) | |
1234 | { | |
1235 | return 0; | |
1236 | } | |
1237 | ||
1238 | /* Check the minor number of the version */ | |
1239 | ||
1240 | if (minor > ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) | |
1241 | { | |
1242 | return 1; | |
1243 | } | |
1244 | ||
1245 | if (minor < ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER) | |
1246 | { | |
1247 | return 0; | |
1248 | } | |
1249 | ||
1250 | /* Check the revision number of the version */ | |
1251 | ||
1252 | if (revision >= ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER) | |
1253 | { | |
1254 | return 1; | |
1255 | } | |
1256 | else | |
1257 | { | |
1258 | return 0; | |
1259 | } | |
1260 | } | |
1261 | ||
1262 | ||
1263 | /** | |
1264 | * @brief Free a memory buffer. | |
1265 | * | |
1266 | * Free a memory buffer that was allocated by the core system of Orthanc. | |
1267 | * | |
1268 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1269 | * @param buffer The memory buffer to release. | |
1270 | **/ | |
1271 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeMemoryBuffer( | |
1272 | OrthancPluginContext* context, | |
1273 | OrthancPluginMemoryBuffer* buffer) | |
1274 | { | |
1275 | context->Free(buffer->data); | |
1276 | } | |
1277 | ||
1278 | ||
1279 | /** | |
1280 | * @brief Log an error. | |
1281 | * | |
1282 | * Log an error message using the Orthanc logging system. | |
1283 | * | |
1284 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1285 | * @param message The message to be logged. | |
1286 | **/ | |
1287 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogError( | |
1288 | OrthancPluginContext* context, | |
1289 | const char* message) | |
1290 | { | |
1291 | context->InvokeService(context, _OrthancPluginService_LogError, message); | |
1292 | } | |
1293 | ||
1294 | ||
1295 | /** | |
1296 | * @brief Log a warning. | |
1297 | * | |
1298 | * Log a warning message using the Orthanc logging system. | |
1299 | * | |
1300 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1301 | * @param message The message to be logged. | |
1302 | **/ | |
1303 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogWarning( | |
1304 | OrthancPluginContext* context, | |
1305 | const char* message) | |
1306 | { | |
1307 | context->InvokeService(context, _OrthancPluginService_LogWarning, message); | |
1308 | } | |
1309 | ||
1310 | ||
1311 | /** | |
1312 | * @brief Log an information. | |
1313 | * | |
1314 | * Log an information message using the Orthanc logging system. | |
1315 | * | |
1316 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1317 | * @param message The message to be logged. | |
1318 | **/ | |
1319 | ORTHANC_PLUGIN_INLINE void OrthancPluginLogInfo( | |
1320 | OrthancPluginContext* context, | |
1321 | const char* message) | |
1322 | { | |
1323 | context->InvokeService(context, _OrthancPluginService_LogInfo, message); | |
1324 | } | |
1325 | ||
1326 | ||
1327 | ||
1328 | typedef struct | |
1329 | { | |
1330 | const char* pathRegularExpression; | |
1331 | OrthancPluginRestCallback callback; | |
1332 | } _OrthancPluginRestCallback; | |
1333 | ||
1334 | /** | |
1335 | * @brief Register a REST callback. | |
1336 | * | |
1337 | * This function registers a REST callback against a regular | |
1338 | * expression for a URI. This function must be called during the | |
1339 | * initialization of the plugin, i.e. inside the | |
1340 | * OrthancPluginInitialize() public function. | |
1341 | * | |
1342 | * Each REST callback is guaranteed to run in mutual exclusion. | |
1343 | * | |
1344 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1345 | * @param pathRegularExpression Regular expression for the URI. May contain groups. | |
1346 | * @param callback The callback function to handle the REST call. | |
1347 | * @see OrthancPluginRegisterRestCallbackNoLock() | |
1348 | * @ingroup Callbacks | |
1349 | **/ | |
1350 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallback( | |
1351 | OrthancPluginContext* context, | |
1352 | const char* pathRegularExpression, | |
1353 | OrthancPluginRestCallback callback) | |
1354 | { | |
1355 | _OrthancPluginRestCallback params; | |
1356 | params.pathRegularExpression = pathRegularExpression; | |
1357 | params.callback = callback; | |
1358 | context->InvokeService(context, _OrthancPluginService_RegisterRestCallback, ¶ms); | |
1359 | } | |
1360 | ||
1361 | ||
1362 | ||
1363 | /** | |
1364 | * @brief Register a REST callback, without locking. | |
1365 | * | |
1366 | * This function registers a REST callback against a regular | |
1367 | * expression for a URI. This function must be called during the | |
1368 | * initialization of the plugin, i.e. inside the | |
1369 | * OrthancPluginInitialize() public function. | |
1370 | * | |
1371 | * Contrarily to OrthancPluginRegisterRestCallback(), the callback | |
1372 | * will NOT be invoked in mutual exclusion. This can be useful for | |
1373 | * high-performance plugins that must handle concurrent requests | |
1374 | * (Orthanc uses a pool of threads, one thread being assigned to | |
1375 | * each incoming HTTP request). Of course, it is up to the plugin to | |
1376 | * implement the required locking mechanisms. | |
1377 | * | |
1378 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1379 | * @param pathRegularExpression Regular expression for the URI. May contain groups. | |
1380 | * @param callback The callback function to handle the REST call. | |
1381 | * @see OrthancPluginRegisterRestCallback() | |
1382 | * @ingroup Callbacks | |
1383 | **/ | |
1384 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterRestCallbackNoLock( | |
1385 | OrthancPluginContext* context, | |
1386 | const char* pathRegularExpression, | |
1387 | OrthancPluginRestCallback callback) | |
1388 | { | |
1389 | _OrthancPluginRestCallback params; | |
1390 | params.pathRegularExpression = pathRegularExpression; | |
1391 | params.callback = callback; | |
1392 | context->InvokeService(context, _OrthancPluginService_RegisterRestCallbackNoLock, ¶ms); | |
1393 | } | |
1394 | ||
1395 | ||
1396 | ||
1397 | typedef struct | |
1398 | { | |
1399 | OrthancPluginOnStoredInstanceCallback callback; | |
1400 | } _OrthancPluginOnStoredInstanceCallback; | |
1401 | ||
1402 | /** | |
1403 | * @brief Register a callback for received instances. | |
1404 | * | |
1405 | * This function registers a callback function that is called | |
1406 | * whenever a new DICOM instance is stored into the Orthanc core. | |
1407 | * | |
1408 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1409 | * @param callback The callback function. | |
1410 | * @ingroup Callbacks | |
1411 | **/ | |
1412 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnStoredInstanceCallback( | |
1413 | OrthancPluginContext* context, | |
1414 | OrthancPluginOnStoredInstanceCallback callback) | |
1415 | { | |
1416 | _OrthancPluginOnStoredInstanceCallback params; | |
1417 | params.callback = callback; | |
1418 | ||
1419 | context->InvokeService(context, _OrthancPluginService_RegisterOnStoredInstanceCallback, ¶ms); | |
1420 | } | |
1421 | ||
1422 | ||
1423 | ||
1424 | typedef struct | |
1425 | { | |
1426 | OrthancPluginRestOutput* output; | |
1427 | const char* answer; | |
1428 | uint32_t answerSize; | |
1429 | const char* mimeType; | |
1430 | } _OrthancPluginAnswerBuffer; | |
1431 | ||
1432 | /** | |
1433 | * @brief Answer to a REST request. | |
1434 | * | |
1435 | * This function answers to a REST request with the content of a memory buffer. | |
1436 | * | |
1437 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1438 | * @param output The HTTP connection to the client application. | |
1439 | * @param answer Pointer to the memory buffer containing the answer. | |
1440 | * @param answerSize Number of bytes of the answer. | |
1441 | * @param mimeType The MIME type of the answer. | |
1442 | * @ingroup REST | |
1443 | **/ | |
1444 | ORTHANC_PLUGIN_INLINE void OrthancPluginAnswerBuffer( | |
1445 | OrthancPluginContext* context, | |
1446 | OrthancPluginRestOutput* output, | |
1447 | const char* answer, | |
1448 | uint32_t answerSize, | |
1449 | const char* mimeType) | |
1450 | { | |
1451 | _OrthancPluginAnswerBuffer params; | |
1452 | params.output = output; | |
1453 | params.answer = answer; | |
1454 | params.answerSize = answerSize; | |
1455 | params.mimeType = mimeType; | |
1456 | context->InvokeService(context, _OrthancPluginService_AnswerBuffer, ¶ms); | |
1457 | } | |
1458 | ||
1459 | ||
1460 | typedef struct | |
1461 | { | |
1462 | OrthancPluginRestOutput* output; | |
1463 | OrthancPluginPixelFormat format; | |
1464 | uint32_t width; | |
1465 | uint32_t height; | |
1466 | uint32_t pitch; | |
1467 | const void* buffer; | |
1468 | } _OrthancPluginCompressAndAnswerPngImage; | |
1469 | ||
1470 | typedef struct | |
1471 | { | |
1472 | OrthancPluginRestOutput* output; | |
1473 | OrthancPluginImageFormat imageFormat; | |
1474 | OrthancPluginPixelFormat pixelFormat; | |
1475 | uint32_t width; | |
1476 | uint32_t height; | |
1477 | uint32_t pitch; | |
1478 | const void* buffer; | |
1479 | uint8_t quality; | |
1480 | } _OrthancPluginCompressAndAnswerImage; | |
1481 | ||
1482 | ||
1483 | /** | |
1484 | * @brief Answer to a REST request with a PNG image. | |
1485 | * | |
1486 | * This function answers to a REST request with a PNG image. The | |
1487 | * parameters of this function describe a memory buffer that | |
1488 | * contains an uncompressed image. The image will be automatically compressed | |
1489 | * as a PNG image by the core system of Orthanc. | |
1490 | * | |
1491 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1492 | * @param output The HTTP connection to the client application. | |
1493 | * @param format The memory layout of the uncompressed image. | |
1494 | * @param width The width of the image. | |
1495 | * @param height The height of the image. | |
1496 | * @param pitch The pitch of the image (i.e. the number of bytes | |
1497 | * between 2 successive lines of the image in the memory buffer). | |
1498 | * @param buffer The memory buffer containing the uncompressed image. | |
1499 | * @ingroup REST | |
1500 | **/ | |
1501 | ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerPngImage( | |
1502 | OrthancPluginContext* context, | |
1503 | OrthancPluginRestOutput* output, | |
1504 | OrthancPluginPixelFormat format, | |
1505 | uint32_t width, | |
1506 | uint32_t height, | |
1507 | uint32_t pitch, | |
1508 | const void* buffer) | |
1509 | { | |
1510 | _OrthancPluginCompressAndAnswerImage params; | |
1511 | params.output = output; | |
1512 | params.imageFormat = OrthancPluginImageFormat_Png; | |
1513 | params.pixelFormat = format; | |
1514 | params.width = width; | |
1515 | params.height = height; | |
1516 | params.pitch = pitch; | |
1517 | params.buffer = buffer; | |
1518 | params.quality = 0; /* No quality for PNG */ | |
1519 | context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); | |
1520 | } | |
1521 | ||
1522 | ||
1523 | ||
1524 | typedef struct | |
1525 | { | |
1526 | OrthancPluginMemoryBuffer* target; | |
1527 | const char* instanceId; | |
1528 | } _OrthancPluginGetDicomForInstance; | |
1529 | ||
1530 | /** | |
1531 | * @brief Retrieve a DICOM instance using its Orthanc identifier. | |
1532 | * | |
1533 | * Retrieve a DICOM instance using its Orthanc identifier. The DICOM | |
1534 | * file is stored into a newly allocated memory buffer. | |
1535 | * | |
1536 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1537 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1538 | * @param instanceId The Orthanc identifier of the DICOM instance of interest. | |
1539 | * @return 0 if success, or the error code if failure. | |
1540 | * @ingroup Orthanc | |
1541 | **/ | |
1542 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetDicomForInstance( | |
1543 | OrthancPluginContext* context, | |
1544 | OrthancPluginMemoryBuffer* target, | |
1545 | const char* instanceId) | |
1546 | { | |
1547 | _OrthancPluginGetDicomForInstance params; | |
1548 | params.target = target; | |
1549 | params.instanceId = instanceId; | |
1550 | return context->InvokeService(context, _OrthancPluginService_GetDicomForInstance, ¶ms); | |
1551 | } | |
1552 | ||
1553 | ||
1554 | ||
1555 | typedef struct | |
1556 | { | |
1557 | OrthancPluginMemoryBuffer* target; | |
1558 | const char* uri; | |
1559 | } _OrthancPluginRestApiGet; | |
1560 | ||
1561 | /** | |
1562 | * @brief Make a GET call to the built-in Orthanc REST API. | |
1563 | * | |
1564 | * Make a GET call to the built-in Orthanc REST API. The result to | |
1565 | * the query is stored into a newly allocated memory buffer. | |
1566 | * | |
1567 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1568 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1569 | * @param uri The URI in the built-in Orthanc API. | |
1570 | * @return 0 if success, or the error code if failure. | |
1571 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1572 | * @see OrthancPluginRestApiGetAfterPlugins | |
1573 | * @ingroup Orthanc | |
1574 | **/ | |
1575 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet( | |
1576 | OrthancPluginContext* context, | |
1577 | OrthancPluginMemoryBuffer* target, | |
1578 | const char* uri) | |
1579 | { | |
1580 | _OrthancPluginRestApiGet params; | |
1581 | params.target = target; | |
1582 | params.uri = uri; | |
1583 | return context->InvokeService(context, _OrthancPluginService_RestApiGet, ¶ms); | |
1584 | } | |
1585 | ||
1586 | ||
1587 | ||
1588 | /** | |
1589 | * @brief Make a GET call to the REST API, as tainted by the plugins. | |
1590 | * | |
1591 | * Make a GET call to the Orthanc REST API, after all the plugins | |
1592 | * are applied. In other words, if some plugin overrides or adds the | |
1593 | * called URI to the built-in Orthanc REST API, this call will | |
1594 | * return the result provided by this plugin. The result to the | |
1595 | * query is stored into a newly allocated memory buffer. | |
1596 | * | |
1597 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1598 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1599 | * @param uri The URI in the built-in Orthanc API. | |
1600 | * @return 0 if success, or the error code if failure. | |
1601 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1602 | * @see OrthancPluginRestApiGet | |
1603 | * @ingroup Orthanc | |
1604 | **/ | |
1605 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGetAfterPlugins( | |
1606 | OrthancPluginContext* context, | |
1607 | OrthancPluginMemoryBuffer* target, | |
1608 | const char* uri) | |
1609 | { | |
1610 | _OrthancPluginRestApiGet params; | |
1611 | params.target = target; | |
1612 | params.uri = uri; | |
1613 | return context->InvokeService(context, _OrthancPluginService_RestApiGetAfterPlugins, ¶ms); | |
1614 | } | |
1615 | ||
1616 | ||
1617 | ||
1618 | typedef struct | |
1619 | { | |
1620 | OrthancPluginMemoryBuffer* target; | |
1621 | const char* uri; | |
1622 | const char* body; | |
1623 | uint32_t bodySize; | |
1624 | } _OrthancPluginRestApiPostPut; | |
1625 | ||
1626 | /** | |
1627 | * @brief Make a POST call to the built-in Orthanc REST API. | |
1628 | * | |
1629 | * Make a POST call to the built-in Orthanc REST API. The result to | |
1630 | * the query is stored into a newly allocated memory buffer. | |
1631 | * | |
1632 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1633 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1634 | * @param uri The URI in the built-in Orthanc API. | |
1635 | * @param body The body of the POST request. | |
1636 | * @param bodySize The size of the body. | |
1637 | * @return 0 if success, or the error code if failure. | |
1638 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1639 | * @see OrthancPluginRestApiPostAfterPlugins | |
1640 | * @ingroup Orthanc | |
1641 | **/ | |
1642 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPost( | |
1643 | OrthancPluginContext* context, | |
1644 | OrthancPluginMemoryBuffer* target, | |
1645 | const char* uri, | |
1646 | const char* body, | |
1647 | uint32_t bodySize) | |
1648 | { | |
1649 | _OrthancPluginRestApiPostPut params; | |
1650 | params.target = target; | |
1651 | params.uri = uri; | |
1652 | params.body = body; | |
1653 | params.bodySize = bodySize; | |
1654 | return context->InvokeService(context, _OrthancPluginService_RestApiPost, ¶ms); | |
1655 | } | |
1656 | ||
1657 | ||
1658 | /** | |
1659 | * @brief Make a POST call to the REST API, as tainted by the plugins. | |
1660 | * | |
1661 | * Make a POST call to the Orthanc REST API, after all the plugins | |
1662 | * are applied. In other words, if some plugin overrides or adds the | |
1663 | * called URI to the built-in Orthanc REST API, this call will | |
1664 | * return the result provided by this plugin. The result to the | |
1665 | * query is stored into a newly allocated memory buffer. | |
1666 | * | |
1667 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1668 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1669 | * @param uri The URI in the built-in Orthanc API. | |
1670 | * @param body The body of the POST request. | |
1671 | * @param bodySize The size of the body. | |
1672 | * @return 0 if success, or the error code if failure. | |
1673 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1674 | * @see OrthancPluginRestApiPost | |
1675 | * @ingroup Orthanc | |
1676 | **/ | |
1677 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPostAfterPlugins( | |
1678 | OrthancPluginContext* context, | |
1679 | OrthancPluginMemoryBuffer* target, | |
1680 | const char* uri, | |
1681 | const char* body, | |
1682 | uint32_t bodySize) | |
1683 | { | |
1684 | _OrthancPluginRestApiPostPut params; | |
1685 | params.target = target; | |
1686 | params.uri = uri; | |
1687 | params.body = body; | |
1688 | params.bodySize = bodySize; | |
1689 | return context->InvokeService(context, _OrthancPluginService_RestApiPostAfterPlugins, ¶ms); | |
1690 | } | |
1691 | ||
1692 | ||
1693 | ||
1694 | /** | |
1695 | * @brief Make a DELETE call to the built-in Orthanc REST API. | |
1696 | * | |
1697 | * Make a DELETE call to the built-in Orthanc REST API. | |
1698 | * | |
1699 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1700 | * @param uri The URI to delete in the built-in Orthanc API. | |
1701 | * @return 0 if success, or the error code if failure. | |
1702 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1703 | * @see OrthancPluginRestApiDeleteAfterPlugins | |
1704 | * @ingroup Orthanc | |
1705 | **/ | |
1706 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDelete( | |
1707 | OrthancPluginContext* context, | |
1708 | const char* uri) | |
1709 | { | |
1710 | return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri); | |
1711 | } | |
1712 | ||
1713 | ||
1714 | /** | |
1715 | * @brief Make a DELETE call to the REST API, as tainted by the plugins. | |
1716 | * | |
1717 | * Make a DELETE call to the Orthanc REST API, after all the plugins | |
1718 | * are applied. In other words, if some plugin overrides or adds the | |
1719 | * called URI to the built-in Orthanc REST API, this call will | |
1720 | * return the result provided by this plugin. | |
1721 | * | |
1722 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1723 | * @param uri The URI to delete in the built-in Orthanc API. | |
1724 | * @return 0 if success, or the error code if failure. | |
1725 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1726 | * @see OrthancPluginRestApiDelete | |
1727 | * @ingroup Orthanc | |
1728 | **/ | |
1729 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiDeleteAfterPlugins( | |
1730 | OrthancPluginContext* context, | |
1731 | const char* uri) | |
1732 | { | |
1733 | return context->InvokeService(context, _OrthancPluginService_RestApiDeleteAfterPlugins, uri); | |
1734 | } | |
1735 | ||
1736 | ||
1737 | ||
1738 | /** | |
1739 | * @brief Make a PUT call to the built-in Orthanc REST API. | |
1740 | * | |
1741 | * Make a PUT call to the built-in Orthanc REST API. The result to | |
1742 | * the query is stored into a newly allocated memory buffer. | |
1743 | * | |
1744 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1745 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1746 | * @param uri The URI in the built-in Orthanc API. | |
1747 | * @param body The body of the PUT request. | |
1748 | * @param bodySize The size of the body. | |
1749 | * @return 0 if success, or the error code if failure. | |
1750 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1751 | * @see OrthancPluginRestApiPutAfterPlugins | |
1752 | * @ingroup Orthanc | |
1753 | **/ | |
1754 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPut( | |
1755 | OrthancPluginContext* context, | |
1756 | OrthancPluginMemoryBuffer* target, | |
1757 | const char* uri, | |
1758 | const char* body, | |
1759 | uint32_t bodySize) | |
1760 | { | |
1761 | _OrthancPluginRestApiPostPut params; | |
1762 | params.target = target; | |
1763 | params.uri = uri; | |
1764 | params.body = body; | |
1765 | params.bodySize = bodySize; | |
1766 | return context->InvokeService(context, _OrthancPluginService_RestApiPut, ¶ms); | |
1767 | } | |
1768 | ||
1769 | ||
1770 | ||
1771 | /** | |
1772 | * @brief Make a PUT call to the REST API, as tainted by the plugins. | |
1773 | * | |
1774 | * Make a PUT call to the Orthanc REST API, after all the plugins | |
1775 | * are applied. In other words, if some plugin overrides or adds the | |
1776 | * called URI to the built-in Orthanc REST API, this call will | |
1777 | * return the result provided by this plugin. The result to the | |
1778 | * query is stored into a newly allocated memory buffer. | |
1779 | * | |
1780 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1781 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
1782 | * @param uri The URI in the built-in Orthanc API. | |
1783 | * @param body The body of the PUT request. | |
1784 | * @param bodySize The size of the body. | |
1785 | * @return 0 if success, or the error code if failure. | |
1786 | * @note If the resource is not existing (error 404), the error code will be OrthancPluginErrorCode_UnknownResource. | |
1787 | * @see OrthancPluginRestApiPut | |
1788 | * @ingroup Orthanc | |
1789 | **/ | |
1790 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiPutAfterPlugins( | |
1791 | OrthancPluginContext* context, | |
1792 | OrthancPluginMemoryBuffer* target, | |
1793 | const char* uri, | |
1794 | const char* body, | |
1795 | uint32_t bodySize) | |
1796 | { | |
1797 | _OrthancPluginRestApiPostPut params; | |
1798 | params.target = target; | |
1799 | params.uri = uri; | |
1800 | params.body = body; | |
1801 | params.bodySize = bodySize; | |
1802 | return context->InvokeService(context, _OrthancPluginService_RestApiPutAfterPlugins, ¶ms); | |
1803 | } | |
1804 | ||
1805 | ||
1806 | ||
1807 | typedef struct | |
1808 | { | |
1809 | OrthancPluginRestOutput* output; | |
1810 | const char* argument; | |
1811 | } _OrthancPluginOutputPlusArgument; | |
1812 | ||
1813 | /** | |
1814 | * @brief Redirect a REST request. | |
1815 | * | |
1816 | * This function answers to a REST request by redirecting the user | |
1817 | * to another URI using HTTP status 301. | |
1818 | * | |
1819 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1820 | * @param output The HTTP connection to the client application. | |
1821 | * @param redirection Where to redirect. | |
1822 | * @ingroup REST | |
1823 | **/ | |
1824 | ORTHANC_PLUGIN_INLINE void OrthancPluginRedirect( | |
1825 | OrthancPluginContext* context, | |
1826 | OrthancPluginRestOutput* output, | |
1827 | const char* redirection) | |
1828 | { | |
1829 | _OrthancPluginOutputPlusArgument params; | |
1830 | params.output = output; | |
1831 | params.argument = redirection; | |
1832 | context->InvokeService(context, _OrthancPluginService_Redirect, ¶ms); | |
1833 | } | |
1834 | ||
1835 | ||
1836 | ||
1837 | typedef struct | |
1838 | { | |
1839 | char** result; | |
1840 | const char* argument; | |
1841 | } _OrthancPluginRetrieveDynamicString; | |
1842 | ||
1843 | /** | |
1844 | * @brief Look for a patient. | |
1845 | * | |
1846 | * Look for a patient stored in Orthanc, using its Patient ID tag (0x0010, 0x0020). | |
1847 | * This function uses the database index to run as fast as possible (it does not loop | |
1848 | * over all the stored patients). | |
1849 | * | |
1850 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1851 | * @param patientID The Patient ID of interest. | |
1852 | * @return The NULL value if the patient is non-existent, or a string containing the | |
1853 | * Orthanc ID of the patient. This string must be freed by OrthancPluginFreeString(). | |
1854 | * @ingroup Orthanc | |
1855 | **/ | |
1856 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupPatient( | |
1857 | OrthancPluginContext* context, | |
1858 | const char* patientID) | |
1859 | { | |
1860 | char* result; | |
1861 | ||
1862 | _OrthancPluginRetrieveDynamicString params; | |
1863 | params.result = &result; | |
1864 | params.argument = patientID; | |
1865 | ||
1866 | if (context->InvokeService(context, _OrthancPluginService_LookupPatient, ¶ms) != OrthancPluginErrorCode_Success) | |
1867 | { | |
1868 | /* Error */ | |
1869 | return NULL; | |
1870 | } | |
1871 | else | |
1872 | { | |
1873 | return result; | |
1874 | } | |
1875 | } | |
1876 | ||
1877 | ||
1878 | /** | |
1879 | * @brief Look for a study. | |
1880 | * | |
1881 | * Look for a study stored in Orthanc, using its Study Instance UID tag (0x0020, 0x000d). | |
1882 | * This function uses the database index to run as fast as possible (it does not loop | |
1883 | * over all the stored studies). | |
1884 | * | |
1885 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1886 | * @param studyUID The Study Instance UID of interest. | |
1887 | * @return The NULL value if the study is non-existent, or a string containing the | |
1888 | * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). | |
1889 | * @ingroup Orthanc | |
1890 | **/ | |
1891 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudy( | |
1892 | OrthancPluginContext* context, | |
1893 | const char* studyUID) | |
1894 | { | |
1895 | char* result; | |
1896 | ||
1897 | _OrthancPluginRetrieveDynamicString params; | |
1898 | params.result = &result; | |
1899 | params.argument = studyUID; | |
1900 | ||
1901 | if (context->InvokeService(context, _OrthancPluginService_LookupStudy, ¶ms) != OrthancPluginErrorCode_Success) | |
1902 | { | |
1903 | /* Error */ | |
1904 | return NULL; | |
1905 | } | |
1906 | else | |
1907 | { | |
1908 | return result; | |
1909 | } | |
1910 | } | |
1911 | ||
1912 | ||
1913 | /** | |
1914 | * @brief Look for a study, using the accession number. | |
1915 | * | |
1916 | * Look for a study stored in Orthanc, using its Accession Number tag (0x0008, 0x0050). | |
1917 | * This function uses the database index to run as fast as possible (it does not loop | |
1918 | * over all the stored studies). | |
1919 | * | |
1920 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1921 | * @param accessionNumber The Accession Number of interest. | |
1922 | * @return The NULL value if the study is non-existent, or a string containing the | |
1923 | * Orthanc ID of the study. This string must be freed by OrthancPluginFreeString(). | |
1924 | * @ingroup Orthanc | |
1925 | **/ | |
1926 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupStudyWithAccessionNumber( | |
1927 | OrthancPluginContext* context, | |
1928 | const char* accessionNumber) | |
1929 | { | |
1930 | char* result; | |
1931 | ||
1932 | _OrthancPluginRetrieveDynamicString params; | |
1933 | params.result = &result; | |
1934 | params.argument = accessionNumber; | |
1935 | ||
1936 | if (context->InvokeService(context, _OrthancPluginService_LookupStudyWithAccessionNumber, ¶ms) != OrthancPluginErrorCode_Success) | |
1937 | { | |
1938 | /* Error */ | |
1939 | return NULL; | |
1940 | } | |
1941 | else | |
1942 | { | |
1943 | return result; | |
1944 | } | |
1945 | } | |
1946 | ||
1947 | ||
1948 | /** | |
1949 | * @brief Look for a series. | |
1950 | * | |
1951 | * Look for a series stored in Orthanc, using its Series Instance UID tag (0x0020, 0x000e). | |
1952 | * This function uses the database index to run as fast as possible (it does not loop | |
1953 | * over all the stored series). | |
1954 | * | |
1955 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1956 | * @param seriesUID The Series Instance UID of interest. | |
1957 | * @return The NULL value if the series is non-existent, or a string containing the | |
1958 | * Orthanc ID of the series. This string must be freed by OrthancPluginFreeString(). | |
1959 | * @ingroup Orthanc | |
1960 | **/ | |
1961 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupSeries( | |
1962 | OrthancPluginContext* context, | |
1963 | const char* seriesUID) | |
1964 | { | |
1965 | char* result; | |
1966 | ||
1967 | _OrthancPluginRetrieveDynamicString params; | |
1968 | params.result = &result; | |
1969 | params.argument = seriesUID; | |
1970 | ||
1971 | if (context->InvokeService(context, _OrthancPluginService_LookupSeries, ¶ms) != OrthancPluginErrorCode_Success) | |
1972 | { | |
1973 | /* Error */ | |
1974 | return NULL; | |
1975 | } | |
1976 | else | |
1977 | { | |
1978 | return result; | |
1979 | } | |
1980 | } | |
1981 | ||
1982 | ||
1983 | /** | |
1984 | * @brief Look for an instance. | |
1985 | * | |
1986 | * Look for an instance stored in Orthanc, using its SOP Instance UID tag (0x0008, 0x0018). | |
1987 | * This function uses the database index to run as fast as possible (it does not loop | |
1988 | * over all the stored instances). | |
1989 | * | |
1990 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
1991 | * @param sopInstanceUID The SOP Instance UID of interest. | |
1992 | * @return The NULL value if the instance is non-existent, or a string containing the | |
1993 | * Orthanc ID of the instance. This string must be freed by OrthancPluginFreeString(). | |
1994 | * @ingroup Orthanc | |
1995 | **/ | |
1996 | ORTHANC_PLUGIN_INLINE char* OrthancPluginLookupInstance( | |
1997 | OrthancPluginContext* context, | |
1998 | const char* sopInstanceUID) | |
1999 | { | |
2000 | char* result; | |
2001 | ||
2002 | _OrthancPluginRetrieveDynamicString params; | |
2003 | params.result = &result; | |
2004 | params.argument = sopInstanceUID; | |
2005 | ||
2006 | if (context->InvokeService(context, _OrthancPluginService_LookupInstance, ¶ms) != OrthancPluginErrorCode_Success) | |
2007 | { | |
2008 | /* Error */ | |
2009 | return NULL; | |
2010 | } | |
2011 | else | |
2012 | { | |
2013 | return result; | |
2014 | } | |
2015 | } | |
2016 | ||
2017 | ||
2018 | ||
2019 | typedef struct | |
2020 | { | |
2021 | OrthancPluginRestOutput* output; | |
2022 | uint16_t status; | |
2023 | } _OrthancPluginSendHttpStatusCode; | |
2024 | ||
2025 | /** | |
2026 | * @brief Send a HTTP status code. | |
2027 | * | |
2028 | * This function answers to a REST request by sending a HTTP status | |
2029 | * code (such as "400 - Bad Request"). Note that: | |
2030 | * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). | |
2031 | * - Redirections (status 301) must use ::OrthancPluginRedirect(). | |
2032 | * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). | |
2033 | * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). | |
2034 | * | |
2035 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2036 | * @param output The HTTP connection to the client application. | |
2037 | * @param status The HTTP status code to be sent. | |
2038 | * @ingroup REST | |
2039 | * @see OrthancPluginSendHttpStatus() | |
2040 | **/ | |
2041 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatusCode( | |
2042 | OrthancPluginContext* context, | |
2043 | OrthancPluginRestOutput* output, | |
2044 | uint16_t status) | |
2045 | { | |
2046 | _OrthancPluginSendHttpStatusCode params; | |
2047 | params.output = output; | |
2048 | params.status = status; | |
2049 | context->InvokeService(context, _OrthancPluginService_SendHttpStatusCode, ¶ms); | |
2050 | } | |
2051 | ||
2052 | ||
2053 | /** | |
2054 | * @brief Signal that a REST request is not authorized. | |
2055 | * | |
2056 | * This function answers to a REST request by signaling that it is | |
2057 | * not authorized. | |
2058 | * | |
2059 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2060 | * @param output The HTTP connection to the client application. | |
2061 | * @param realm The realm for the authorization process. | |
2062 | * @ingroup REST | |
2063 | **/ | |
2064 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendUnauthorized( | |
2065 | OrthancPluginContext* context, | |
2066 | OrthancPluginRestOutput* output, | |
2067 | const char* realm) | |
2068 | { | |
2069 | _OrthancPluginOutputPlusArgument params; | |
2070 | params.output = output; | |
2071 | params.argument = realm; | |
2072 | context->InvokeService(context, _OrthancPluginService_SendUnauthorized, ¶ms); | |
2073 | } | |
2074 | ||
2075 | ||
2076 | /** | |
2077 | * @brief Signal that this URI does not support this HTTP method. | |
2078 | * | |
2079 | * This function answers to a REST request by signaling that the | |
2080 | * queried URI does not support this method. | |
2081 | * | |
2082 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2083 | * @param output The HTTP connection to the client application. | |
2084 | * @param allowedMethods The allowed methods for this URI (e.g. "GET,POST" after a PUT or a POST request). | |
2085 | * @ingroup REST | |
2086 | **/ | |
2087 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendMethodNotAllowed( | |
2088 | OrthancPluginContext* context, | |
2089 | OrthancPluginRestOutput* output, | |
2090 | const char* allowedMethods) | |
2091 | { | |
2092 | _OrthancPluginOutputPlusArgument params; | |
2093 | params.output = output; | |
2094 | params.argument = allowedMethods; | |
2095 | context->InvokeService(context, _OrthancPluginService_SendMethodNotAllowed, ¶ms); | |
2096 | } | |
2097 | ||
2098 | ||
2099 | typedef struct | |
2100 | { | |
2101 | OrthancPluginRestOutput* output; | |
2102 | const char* key; | |
2103 | const char* value; | |
2104 | } _OrthancPluginSetHttpHeader; | |
2105 | ||
2106 | /** | |
2107 | * @brief Set a cookie. | |
2108 | * | |
2109 | * This function sets a cookie in the HTTP client. | |
2110 | * | |
2111 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2112 | * @param output The HTTP connection to the client application. | |
2113 | * @param cookie The cookie to be set. | |
2114 | * @param value The value of the cookie. | |
2115 | * @ingroup REST | |
2116 | **/ | |
2117 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetCookie( | |
2118 | OrthancPluginContext* context, | |
2119 | OrthancPluginRestOutput* output, | |
2120 | const char* cookie, | |
2121 | const char* value) | |
2122 | { | |
2123 | _OrthancPluginSetHttpHeader params; | |
2124 | params.output = output; | |
2125 | params.key = cookie; | |
2126 | params.value = value; | |
2127 | context->InvokeService(context, _OrthancPluginService_SetCookie, ¶ms); | |
2128 | } | |
2129 | ||
2130 | ||
2131 | /** | |
2132 | * @brief Set some HTTP header. | |
2133 | * | |
2134 | * This function sets a HTTP header in the HTTP answer. | |
2135 | * | |
2136 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2137 | * @param output The HTTP connection to the client application. | |
2138 | * @param key The HTTP header to be set. | |
2139 | * @param value The value of the HTTP header. | |
2140 | * @ingroup REST | |
2141 | **/ | |
2142 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetHttpHeader( | |
2143 | OrthancPluginContext* context, | |
2144 | OrthancPluginRestOutput* output, | |
2145 | const char* key, | |
2146 | const char* value) | |
2147 | { | |
2148 | _OrthancPluginSetHttpHeader params; | |
2149 | params.output = output; | |
2150 | params.key = key; | |
2151 | params.value = value; | |
2152 | context->InvokeService(context, _OrthancPluginService_SetHttpHeader, ¶ms); | |
2153 | } | |
2154 | ||
2155 | ||
2156 | typedef struct | |
2157 | { | |
2158 | char** resultStringToFree; | |
2159 | const char** resultString; | |
2160 | int64_t* resultInt64; | |
2161 | const char* key; | |
2162 | OrthancPluginDicomInstance* instance; | |
2163 | OrthancPluginInstanceOrigin* resultOrigin; /* New in Orthanc 0.9.5 SDK */ | |
2164 | } _OrthancPluginAccessDicomInstance; | |
2165 | ||
2166 | ||
2167 | /** | |
2168 | * @brief Get the AET of a DICOM instance. | |
2169 | * | |
2170 | * This function returns the Application Entity Title (AET) of the | |
2171 | * DICOM modality from which a DICOM instance originates. | |
2172 | * | |
2173 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2174 | * @param instance The instance of interest. | |
2175 | * @return The AET if success, NULL if error. | |
2176 | * @ingroup Callbacks | |
2177 | **/ | |
2178 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceRemoteAet( | |
2179 | OrthancPluginContext* context, | |
2180 | OrthancPluginDicomInstance* instance) | |
2181 | { | |
2182 | const char* result; | |
2183 | ||
2184 | _OrthancPluginAccessDicomInstance params; | |
2185 | memset(¶ms, 0, sizeof(params)); | |
2186 | params.resultString = &result; | |
2187 | params.instance = instance; | |
2188 | ||
2189 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, ¶ms) != OrthancPluginErrorCode_Success) | |
2190 | { | |
2191 | /* Error */ | |
2192 | return NULL; | |
2193 | } | |
2194 | else | |
2195 | { | |
2196 | return result; | |
2197 | } | |
2198 | } | |
2199 | ||
2200 | ||
2201 | /** | |
2202 | * @brief Get the size of a DICOM file. | |
2203 | * | |
2204 | * This function returns the number of bytes of the given DICOM instance. | |
2205 | * | |
2206 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2207 | * @param instance The instance of interest. | |
2208 | * @return The size of the file, -1 in case of error. | |
2209 | * @ingroup Callbacks | |
2210 | **/ | |
2211 | ORTHANC_PLUGIN_INLINE int64_t OrthancPluginGetInstanceSize( | |
2212 | OrthancPluginContext* context, | |
2213 | OrthancPluginDicomInstance* instance) | |
2214 | { | |
2215 | int64_t size; | |
2216 | ||
2217 | _OrthancPluginAccessDicomInstance params; | |
2218 | memset(¶ms, 0, sizeof(params)); | |
2219 | params.resultInt64 = &size; | |
2220 | params.instance = instance; | |
2221 | ||
2222 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, ¶ms) != OrthancPluginErrorCode_Success) | |
2223 | { | |
2224 | /* Error */ | |
2225 | return -1; | |
2226 | } | |
2227 | else | |
2228 | { | |
2229 | return size; | |
2230 | } | |
2231 | } | |
2232 | ||
2233 | ||
2234 | /** | |
2235 | * @brief Get the data of a DICOM file. | |
2236 | * | |
2237 | * This function returns a pointer to the content of the given DICOM instance. | |
2238 | * | |
2239 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2240 | * @param instance The instance of interest. | |
2241 | * @return The pointer to the DICOM data, NULL in case of error. | |
2242 | * @ingroup Callbacks | |
2243 | **/ | |
2244 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceData( | |
2245 | OrthancPluginContext* context, | |
2246 | OrthancPluginDicomInstance* instance) | |
2247 | { | |
2248 | const char* result; | |
2249 | ||
2250 | _OrthancPluginAccessDicomInstance params; | |
2251 | memset(¶ms, 0, sizeof(params)); | |
2252 | params.resultString = &result; | |
2253 | params.instance = instance; | |
2254 | ||
2255 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, ¶ms) != OrthancPluginErrorCode_Success) | |
2256 | { | |
2257 | /* Error */ | |
2258 | return NULL; | |
2259 | } | |
2260 | else | |
2261 | { | |
2262 | return result; | |
2263 | } | |
2264 | } | |
2265 | ||
2266 | ||
2267 | /** | |
2268 | * @brief Get the DICOM tag hierarchy as a JSON file. | |
2269 | * | |
2270 | * This function returns a pointer to a newly created string | |
2271 | * containing a JSON file. This JSON file encodes the tag hierarchy | |
2272 | * of the given DICOM instance. | |
2273 | * | |
2274 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2275 | * @param instance The instance of interest. | |
2276 | * @return The NULL value in case of error, or a string containing the JSON file. | |
2277 | * This string must be freed by OrthancPluginFreeString(). | |
2278 | * @ingroup Callbacks | |
2279 | **/ | |
2280 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceJson( | |
2281 | OrthancPluginContext* context, | |
2282 | OrthancPluginDicomInstance* instance) | |
2283 | { | |
2284 | char* result; | |
2285 | ||
2286 | _OrthancPluginAccessDicomInstance params; | |
2287 | memset(¶ms, 0, sizeof(params)); | |
2288 | params.resultStringToFree = &result; | |
2289 | params.instance = instance; | |
2290 | ||
2291 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, ¶ms) != OrthancPluginErrorCode_Success) | |
2292 | { | |
2293 | /* Error */ | |
2294 | return NULL; | |
2295 | } | |
2296 | else | |
2297 | { | |
2298 | return result; | |
2299 | } | |
2300 | } | |
2301 | ||
2302 | ||
2303 | /** | |
2304 | * @brief Get the DICOM tag hierarchy as a JSON file (with simplification). | |
2305 | * | |
2306 | * This function returns a pointer to a newly created string | |
2307 | * containing a JSON file. This JSON file encodes the tag hierarchy | |
2308 | * of the given DICOM instance. In contrast with | |
2309 | * ::OrthancPluginGetInstanceJson(), the returned JSON file is in | |
2310 | * its simplified version. | |
2311 | * | |
2312 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2313 | * @param instance The instance of interest. | |
2314 | * @return The NULL value in case of error, or a string containing the JSON file. | |
2315 | * This string must be freed by OrthancPluginFreeString(). | |
2316 | * @ingroup Callbacks | |
2317 | **/ | |
2318 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetInstanceSimplifiedJson( | |
2319 | OrthancPluginContext* context, | |
2320 | OrthancPluginDicomInstance* instance) | |
2321 | { | |
2322 | char* result; | |
2323 | ||
2324 | _OrthancPluginAccessDicomInstance params; | |
2325 | memset(¶ms, 0, sizeof(params)); | |
2326 | params.resultStringToFree = &result; | |
2327 | params.instance = instance; | |
2328 | ||
2329 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, ¶ms) != OrthancPluginErrorCode_Success) | |
2330 | { | |
2331 | /* Error */ | |
2332 | return NULL; | |
2333 | } | |
2334 | else | |
2335 | { | |
2336 | return result; | |
2337 | } | |
2338 | } | |
2339 | ||
2340 | ||
2341 | /** | |
2342 | * @brief Check whether a DICOM instance is associated with some metadata. | |
2343 | * | |
2344 | * This function checks whether the DICOM instance of interest is | |
2345 | * associated with some metadata. As of Orthanc 0.8.1, in the | |
2346 | * callbacks registered by | |
2347 | * ::OrthancPluginRegisterOnStoredInstanceCallback(), the only | |
2348 | * possibly available metadata are "ReceptionDate", "RemoteAET" and | |
2349 | * "IndexInSeries". | |
2350 | * | |
2351 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2352 | * @param instance The instance of interest. | |
2353 | * @param metadata The metadata of interest. | |
2354 | * @return 1 if the metadata is present, 0 if it is absent, -1 in case of error. | |
2355 | * @ingroup Callbacks | |
2356 | **/ | |
2357 | ORTHANC_PLUGIN_INLINE int OrthancPluginHasInstanceMetadata( | |
2358 | OrthancPluginContext* context, | |
2359 | OrthancPluginDicomInstance* instance, | |
2360 | const char* metadata) | |
2361 | { | |
2362 | int64_t result; | |
2363 | ||
2364 | _OrthancPluginAccessDicomInstance params; | |
2365 | memset(¶ms, 0, sizeof(params)); | |
2366 | params.resultInt64 = &result; | |
2367 | params.instance = instance; | |
2368 | params.key = metadata; | |
2369 | ||
2370 | if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) | |
2371 | { | |
2372 | /* Error */ | |
2373 | return -1; | |
2374 | } | |
2375 | else | |
2376 | { | |
2377 | return (result != 0); | |
2378 | } | |
2379 | } | |
2380 | ||
2381 | ||
2382 | /** | |
2383 | * @brief Get the value of some metadata associated with a given DICOM instance. | |
2384 | * | |
2385 | * This functions returns the value of some metadata that is associated with the DICOM instance of interest. | |
2386 | * Before calling this function, the existence of the metadata must have been checked with | |
2387 | * ::OrthancPluginHasInstanceMetadata(). | |
2388 | * | |
2389 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2390 | * @param instance The instance of interest. | |
2391 | * @param metadata The metadata of interest. | |
2392 | * @return The metadata value if success, NULL if error. | |
2393 | * @ingroup Callbacks | |
2394 | **/ | |
2395 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetInstanceMetadata( | |
2396 | OrthancPluginContext* context, | |
2397 | OrthancPluginDicomInstance* instance, | |
2398 | const char* metadata) | |
2399 | { | |
2400 | const char* result; | |
2401 | ||
2402 | _OrthancPluginAccessDicomInstance params; | |
2403 | memset(¶ms, 0, sizeof(params)); | |
2404 | params.resultString = &result; | |
2405 | params.instance = instance; | |
2406 | params.key = metadata; | |
2407 | ||
2408 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, ¶ms) != OrthancPluginErrorCode_Success) | |
2409 | { | |
2410 | /* Error */ | |
2411 | return NULL; | |
2412 | } | |
2413 | else | |
2414 | { | |
2415 | return result; | |
2416 | } | |
2417 | } | |
2418 | ||
2419 | ||
2420 | ||
2421 | typedef struct | |
2422 | { | |
2423 | OrthancPluginStorageCreate create; | |
2424 | OrthancPluginStorageRead read; | |
2425 | OrthancPluginStorageRemove remove; | |
2426 | OrthancPluginFree free; | |
2427 | } _OrthancPluginRegisterStorageArea; | |
2428 | ||
2429 | /** | |
2430 | * @brief Register a custom storage area. | |
2431 | * | |
2432 | * This function registers a custom storage area, to replace the | |
2433 | * built-in way Orthanc stores its files on the filesystem. This | |
2434 | * function must be called during the initialization of the plugin, | |
2435 | * i.e. inside the OrthancPluginInitialize() public function. | |
2436 | * | |
2437 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2438 | * @param create The callback function to store a file on the custom storage area. | |
2439 | * @param read The callback function to read a file from the custom storage area. | |
2440 | * @param remove The callback function to remove a file from the custom storage area. | |
2441 | * @ingroup Callbacks | |
2442 | **/ | |
2443 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterStorageArea( | |
2444 | OrthancPluginContext* context, | |
2445 | OrthancPluginStorageCreate create, | |
2446 | OrthancPluginStorageRead read, | |
2447 | OrthancPluginStorageRemove remove) | |
2448 | { | |
2449 | _OrthancPluginRegisterStorageArea params; | |
2450 | params.create = create; | |
2451 | params.read = read; | |
2452 | params.remove = remove; | |
2453 | ||
2454 | #ifdef __cplusplus | |
2455 | params.free = ::free; | |
2456 | #else | |
2457 | params.free = free; | |
2458 | #endif | |
2459 | ||
2460 | context->InvokeService(context, _OrthancPluginService_RegisterStorageArea, ¶ms); | |
2461 | } | |
2462 | ||
2463 | ||
2464 | ||
2465 | /** | |
2466 | * @brief Return the path to the Orthanc executable. | |
2467 | * | |
2468 | * This function returns the path to the Orthanc executable. | |
2469 | * | |
2470 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2471 | * @return NULL in the case of an error, or a newly allocated string | |
2472 | * containing the path. This string must be freed by | |
2473 | * OrthancPluginFreeString(). | |
2474 | **/ | |
2475 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancPath(OrthancPluginContext* context) | |
2476 | { | |
2477 | char* result; | |
2478 | ||
2479 | _OrthancPluginRetrieveDynamicString params; | |
2480 | params.result = &result; | |
2481 | params.argument = NULL; | |
2482 | ||
2483 | if (context->InvokeService(context, _OrthancPluginService_GetOrthancPath, ¶ms) != OrthancPluginErrorCode_Success) | |
2484 | { | |
2485 | /* Error */ | |
2486 | return NULL; | |
2487 | } | |
2488 | else | |
2489 | { | |
2490 | return result; | |
2491 | } | |
2492 | } | |
2493 | ||
2494 | ||
2495 | /** | |
2496 | * @brief Return the directory containing the Orthanc. | |
2497 | * | |
2498 | * This function returns the path to the directory containing the Orthanc executable. | |
2499 | * | |
2500 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2501 | * @return NULL in the case of an error, or a newly allocated string | |
2502 | * containing the path. This string must be freed by | |
2503 | * OrthancPluginFreeString(). | |
2504 | **/ | |
2505 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetOrthancDirectory(OrthancPluginContext* context) | |
2506 | { | |
2507 | char* result; | |
2508 | ||
2509 | _OrthancPluginRetrieveDynamicString params; | |
2510 | params.result = &result; | |
2511 | params.argument = NULL; | |
2512 | ||
2513 | if (context->InvokeService(context, _OrthancPluginService_GetOrthancDirectory, ¶ms) != OrthancPluginErrorCode_Success) | |
2514 | { | |
2515 | /* Error */ | |
2516 | return NULL; | |
2517 | } | |
2518 | else | |
2519 | { | |
2520 | return result; | |
2521 | } | |
2522 | } | |
2523 | ||
2524 | ||
2525 | /** | |
2526 | * @brief Return the path to the configuration file(s). | |
2527 | * | |
2528 | * This function returns the path to the configuration file(s) that | |
2529 | * was specified when starting Orthanc. Since version 0.9.1, this | |
2530 | * path can refer to a folder that stores a set of configuration | |
2531 | * files. This function is deprecated in favor of | |
2532 | * OrthancPluginGetConfiguration(). | |
2533 | * | |
2534 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2535 | * @return NULL in the case of an error, or a newly allocated string | |
2536 | * containing the path. This string must be freed by | |
2537 | * OrthancPluginFreeString(). | |
2538 | * @see OrthancPluginGetConfiguration() | |
2539 | **/ | |
2540 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfigurationPath(OrthancPluginContext* context) | |
2541 | { | |
2542 | char* result; | |
2543 | ||
2544 | _OrthancPluginRetrieveDynamicString params; | |
2545 | params.result = &result; | |
2546 | params.argument = NULL; | |
2547 | ||
2548 | if (context->InvokeService(context, _OrthancPluginService_GetConfigurationPath, ¶ms) != OrthancPluginErrorCode_Success) | |
2549 | { | |
2550 | /* Error */ | |
2551 | return NULL; | |
2552 | } | |
2553 | else | |
2554 | { | |
2555 | return result; | |
2556 | } | |
2557 | } | |
2558 | ||
2559 | ||
2560 | ||
2561 | typedef struct | |
2562 | { | |
2563 | OrthancPluginOnChangeCallback callback; | |
2564 | } _OrthancPluginOnChangeCallback; | |
2565 | ||
2566 | /** | |
2567 | * @brief Register a callback to monitor changes. | |
2568 | * | |
2569 | * This function registers a callback function that is called | |
2570 | * whenever a change happens to some DICOM resource. | |
2571 | * | |
2572 | * @warning If your change callback has to call the REST API of | |
2573 | * Orthanc, you should make these calls in a separate thread (with | |
2574 | * the events passing through a message queue). Otherwise, this | |
2575 | * could result in deadlocks in the presence of other plugins or Lua | |
2576 | * scripts. | |
2577 | * | |
2578 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2579 | * @param callback The callback function. | |
2580 | * @ingroup Callbacks | |
2581 | **/ | |
2582 | ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback( | |
2583 | OrthancPluginContext* context, | |
2584 | OrthancPluginOnChangeCallback callback) | |
2585 | { | |
2586 | _OrthancPluginOnChangeCallback params; | |
2587 | params.callback = callback; | |
2588 | ||
2589 | context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, ¶ms); | |
2590 | } | |
2591 | ||
2592 | ||
2593 | ||
2594 | typedef struct | |
2595 | { | |
2596 | const char* plugin; | |
2597 | _OrthancPluginProperty property; | |
2598 | const char* value; | |
2599 | } _OrthancPluginSetPluginProperty; | |
2600 | ||
2601 | ||
2602 | /** | |
2603 | * @brief Set the URI where the plugin provides its Web interface. | |
2604 | * | |
2605 | * For plugins that come with a Web interface, this function | |
2606 | * declares the entry path where to find this interface. This | |
2607 | * information is notably used in the "Plugins" page of Orthanc | |
2608 | * Explorer. | |
2609 | * | |
2610 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2611 | * @param uri The root URI for this plugin. | |
2612 | **/ | |
2613 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetRootUri( | |
2614 | OrthancPluginContext* context, | |
2615 | const char* uri) | |
2616 | { | |
2617 | _OrthancPluginSetPluginProperty params; | |
2618 | params.plugin = OrthancPluginGetName(); | |
2619 | params.property = _OrthancPluginProperty_RootUri; | |
2620 | params.value = uri; | |
2621 | ||
2622 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2623 | } | |
2624 | ||
2625 | ||
2626 | /** | |
2627 | * @brief Set a description for this plugin. | |
2628 | * | |
2629 | * Set a description for this plugin. It is displayed in the | |
2630 | * "Plugins" page of Orthanc Explorer. | |
2631 | * | |
2632 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2633 | * @param description The description. | |
2634 | **/ | |
2635 | ORTHANC_PLUGIN_INLINE void OrthancPluginSetDescription( | |
2636 | OrthancPluginContext* context, | |
2637 | const char* description) | |
2638 | { | |
2639 | _OrthancPluginSetPluginProperty params; | |
2640 | params.plugin = OrthancPluginGetName(); | |
2641 | params.property = _OrthancPluginProperty_Description; | |
2642 | params.value = description; | |
2643 | ||
2644 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2645 | } | |
2646 | ||
2647 | ||
2648 | /** | |
2649 | * @brief Extend the JavaScript code of Orthanc Explorer. | |
2650 | * | |
2651 | * Add JavaScript code to customize the default behavior of Orthanc | |
2652 | * Explorer. This can for instance be used to add new buttons. | |
2653 | * | |
2654 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2655 | * @param javascript The custom JavaScript code. | |
2656 | **/ | |
2657 | ORTHANC_PLUGIN_INLINE void OrthancPluginExtendOrthancExplorer( | |
2658 | OrthancPluginContext* context, | |
2659 | const char* javascript) | |
2660 | { | |
2661 | _OrthancPluginSetPluginProperty params; | |
2662 | params.plugin = OrthancPluginGetName(); | |
2663 | params.property = _OrthancPluginProperty_OrthancExplorer; | |
2664 | params.value = javascript; | |
2665 | ||
2666 | context->InvokeService(context, _OrthancPluginService_SetPluginProperty, ¶ms); | |
2667 | } | |
2668 | ||
2669 | ||
2670 | typedef struct | |
2671 | { | |
2672 | char** result; | |
2673 | int32_t property; | |
2674 | const char* value; | |
2675 | } _OrthancPluginGlobalProperty; | |
2676 | ||
2677 | ||
2678 | /** | |
2679 | * @brief Get the value of a global property. | |
2680 | * | |
2681 | * Get the value of a global property that is stored in the Orthanc database. Global | |
2682 | * properties whose index is below 1024 are reserved by Orthanc. | |
2683 | * | |
2684 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2685 | * @param property The global property of interest. | |
2686 | * @param defaultValue The value to return, if the global property is unset. | |
2687 | * @return The value of the global property, or NULL in the case of an error. This | |
2688 | * string must be freed by OrthancPluginFreeString(). | |
2689 | * @ingroup Orthanc | |
2690 | **/ | |
2691 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetGlobalProperty( | |
2692 | OrthancPluginContext* context, | |
2693 | int32_t property, | |
2694 | const char* defaultValue) | |
2695 | { | |
2696 | char* result; | |
2697 | ||
2698 | _OrthancPluginGlobalProperty params; | |
2699 | params.result = &result; | |
2700 | params.property = property; | |
2701 | params.value = defaultValue; | |
2702 | ||
2703 | if (context->InvokeService(context, _OrthancPluginService_GetGlobalProperty, ¶ms) != OrthancPluginErrorCode_Success) | |
2704 | { | |
2705 | /* Error */ | |
2706 | return NULL; | |
2707 | } | |
2708 | else | |
2709 | { | |
2710 | return result; | |
2711 | } | |
2712 | } | |
2713 | ||
2714 | ||
2715 | /** | |
2716 | * @brief Set the value of a global property. | |
2717 | * | |
2718 | * Set the value of a global property into the Orthanc | |
2719 | * database. Setting a global property can be used by plugins to | |
2720 | * save their internal parameters. Plugins are only allowed to set | |
2721 | * properties whose index are above or equal to 1024 (properties | |
2722 | * below 1024 are read-only and reserved by Orthanc). | |
2723 | * | |
2724 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2725 | * @param property The global property of interest. | |
2726 | * @param value The value to be set in the global property. | |
2727 | * @return 0 if success, or the error code if failure. | |
2728 | * @ingroup Orthanc | |
2729 | **/ | |
2730 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSetGlobalProperty( | |
2731 | OrthancPluginContext* context, | |
2732 | int32_t property, | |
2733 | const char* value) | |
2734 | { | |
2735 | _OrthancPluginGlobalProperty params; | |
2736 | params.result = NULL; | |
2737 | params.property = property; | |
2738 | params.value = value; | |
2739 | ||
2740 | return context->InvokeService(context, _OrthancPluginService_SetGlobalProperty, ¶ms); | |
2741 | } | |
2742 | ||
2743 | ||
2744 | ||
2745 | typedef struct | |
2746 | { | |
2747 | int32_t *resultInt32; | |
2748 | uint32_t *resultUint32; | |
2749 | int64_t *resultInt64; | |
2750 | uint64_t *resultUint64; | |
2751 | } _OrthancPluginReturnSingleValue; | |
2752 | ||
2753 | /** | |
2754 | * @brief Get the number of command-line arguments. | |
2755 | * | |
2756 | * Retrieve the number of command-line arguments that were used to launch Orthanc. | |
2757 | * | |
2758 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2759 | * @return The number of arguments. | |
2760 | **/ | |
2761 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetCommandLineArgumentsCount( | |
2762 | OrthancPluginContext* context) | |
2763 | { | |
2764 | uint32_t count = 0; | |
2765 | ||
2766 | _OrthancPluginReturnSingleValue params; | |
2767 | memset(¶ms, 0, sizeof(params)); | |
2768 | params.resultUint32 = &count; | |
2769 | ||
2770 | if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, ¶ms) != OrthancPluginErrorCode_Success) | |
2771 | { | |
2772 | /* Error */ | |
2773 | return 0; | |
2774 | } | |
2775 | else | |
2776 | { | |
2777 | return count; | |
2778 | } | |
2779 | } | |
2780 | ||
2781 | ||
2782 | ||
2783 | /** | |
2784 | * @brief Get the value of a command-line argument. | |
2785 | * | |
2786 | * Get the value of one of the command-line arguments that were used | |
2787 | * to launch Orthanc. The number of available arguments can be | |
2788 | * retrieved by OrthancPluginGetCommandLineArgumentsCount(). | |
2789 | * | |
2790 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2791 | * @param argument The index of the argument. | |
2792 | * @return The value of the argument, or NULL in the case of an error. This | |
2793 | * string must be freed by OrthancPluginFreeString(). | |
2794 | **/ | |
2795 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetCommandLineArgument( | |
2796 | OrthancPluginContext* context, | |
2797 | uint32_t argument) | |
2798 | { | |
2799 | char* result; | |
2800 | ||
2801 | _OrthancPluginGlobalProperty params; | |
2802 | params.result = &result; | |
2803 | params.property = (int32_t) argument; | |
2804 | params.value = NULL; | |
2805 | ||
2806 | if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgument, ¶ms) != OrthancPluginErrorCode_Success) | |
2807 | { | |
2808 | /* Error */ | |
2809 | return NULL; | |
2810 | } | |
2811 | else | |
2812 | { | |
2813 | return result; | |
2814 | } | |
2815 | } | |
2816 | ||
2817 | ||
2818 | /** | |
2819 | * @brief Get the expected version of the database schema. | |
2820 | * | |
2821 | * Retrieve the expected version of the database schema. | |
2822 | * | |
2823 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2824 | * @return The version. | |
2825 | * @ingroup Callbacks | |
2826 | * @deprecated Please instead use IDatabaseBackend::UpgradeDatabase() | |
2827 | **/ | |
2828 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetExpectedDatabaseVersion( | |
2829 | OrthancPluginContext* context) | |
2830 | { | |
2831 | uint32_t count = 0; | |
2832 | ||
2833 | _OrthancPluginReturnSingleValue params; | |
2834 | memset(¶ms, 0, sizeof(params)); | |
2835 | params.resultUint32 = &count; | |
2836 | ||
2837 | if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, ¶ms) != OrthancPluginErrorCode_Success) | |
2838 | { | |
2839 | /* Error */ | |
2840 | return 0; | |
2841 | } | |
2842 | else | |
2843 | { | |
2844 | return count; | |
2845 | } | |
2846 | } | |
2847 | ||
2848 | ||
2849 | ||
2850 | /** | |
2851 | * @brief Return the content of the configuration file(s). | |
2852 | * | |
2853 | * This function returns the content of the configuration that is | |
2854 | * used by Orthanc, formatted as a JSON string. | |
2855 | * | |
2856 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2857 | * @return NULL in the case of an error, or a newly allocated string | |
2858 | * containing the configuration. This string must be freed by | |
2859 | * OrthancPluginFreeString(). | |
2860 | **/ | |
2861 | ORTHANC_PLUGIN_INLINE char *OrthancPluginGetConfiguration(OrthancPluginContext* context) | |
2862 | { | |
2863 | char* result; | |
2864 | ||
2865 | _OrthancPluginRetrieveDynamicString params; | |
2866 | params.result = &result; | |
2867 | params.argument = NULL; | |
2868 | ||
2869 | if (context->InvokeService(context, _OrthancPluginService_GetConfiguration, ¶ms) != OrthancPluginErrorCode_Success) | |
2870 | { | |
2871 | /* Error */ | |
2872 | return NULL; | |
2873 | } | |
2874 | else | |
2875 | { | |
2876 | return result; | |
2877 | } | |
2878 | } | |
2879 | ||
2880 | ||
2881 | ||
2882 | typedef struct | |
2883 | { | |
2884 | OrthancPluginRestOutput* output; | |
2885 | const char* subType; | |
2886 | const char* contentType; | |
2887 | } _OrthancPluginStartMultipartAnswer; | |
2888 | ||
2889 | /** | |
2890 | * @brief Start an HTTP multipart answer. | |
2891 | * | |
2892 | * Initiates a HTTP multipart answer, as the result of a REST request. | |
2893 | * | |
2894 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2895 | * @param output The HTTP connection to the client application. | |
2896 | * @param subType The sub-type of the multipart answer ("mixed" or "related"). | |
2897 | * @param contentType The MIME type of the items in the multipart answer. | |
2898 | * @return 0 if success, or the error code if failure. | |
2899 | * @see OrthancPluginSendMultipartItem(), OrthancPluginSendMultipartItem2() | |
2900 | * @ingroup REST | |
2901 | **/ | |
2902 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer( | |
2903 | OrthancPluginContext* context, | |
2904 | OrthancPluginRestOutput* output, | |
2905 | const char* subType, | |
2906 | const char* contentType) | |
2907 | { | |
2908 | _OrthancPluginStartMultipartAnswer params; | |
2909 | params.output = output; | |
2910 | params.subType = subType; | |
2911 | params.contentType = contentType; | |
2912 | return context->InvokeService(context, _OrthancPluginService_StartMultipartAnswer, ¶ms); | |
2913 | } | |
2914 | ||
2915 | ||
2916 | /** | |
2917 | * @brief Send an item as a part of some HTTP multipart answer. | |
2918 | * | |
2919 | * This function sends an item as a part of some HTTP multipart | |
2920 | * answer that was initiated by OrthancPluginStartMultipartAnswer(). | |
2921 | * | |
2922 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2923 | * @param output The HTTP connection to the client application. | |
2924 | * @param answer Pointer to the memory buffer containing the item. | |
2925 | * @param answerSize Number of bytes of the item. | |
2926 | * @return 0 if success, or the error code if failure (this notably happens | |
2927 | * if the connection is closed by the client). | |
2928 | * @see OrthancPluginSendMultipartItem2() | |
2929 | * @ingroup REST | |
2930 | **/ | |
2931 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem( | |
2932 | OrthancPluginContext* context, | |
2933 | OrthancPluginRestOutput* output, | |
2934 | const char* answer, | |
2935 | uint32_t answerSize) | |
2936 | { | |
2937 | _OrthancPluginAnswerBuffer params; | |
2938 | params.output = output; | |
2939 | params.answer = answer; | |
2940 | params.answerSize = answerSize; | |
2941 | params.mimeType = NULL; | |
2942 | return context->InvokeService(context, _OrthancPluginService_SendMultipartItem, ¶ms); | |
2943 | } | |
2944 | ||
2945 | ||
2946 | ||
2947 | typedef struct | |
2948 | { | |
2949 | OrthancPluginMemoryBuffer* target; | |
2950 | const void* source; | |
2951 | uint32_t size; | |
2952 | OrthancPluginCompressionType compression; | |
2953 | uint8_t uncompress; | |
2954 | } _OrthancPluginBufferCompression; | |
2955 | ||
2956 | ||
2957 | /** | |
2958 | * @brief Compress or decompress a buffer. | |
2959 | * | |
2960 | * This function compresses or decompresses a buffer, using the | |
2961 | * version of the zlib library that is used by the Orthanc core. | |
2962 | * | |
2963 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
2964 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
2965 | * @param source The source buffer. | |
2966 | * @param size The size in bytes of the source buffer. | |
2967 | * @param compression The compression algorithm. | |
2968 | * @param uncompress If set to "0", the buffer must be compressed. | |
2969 | * If set to "1", the buffer must be uncompressed. | |
2970 | * @return 0 if success, or the error code if failure. | |
2971 | * @ingroup Images | |
2972 | **/ | |
2973 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginBufferCompression( | |
2974 | OrthancPluginContext* context, | |
2975 | OrthancPluginMemoryBuffer* target, | |
2976 | const void* source, | |
2977 | uint32_t size, | |
2978 | OrthancPluginCompressionType compression, | |
2979 | uint8_t uncompress) | |
2980 | { | |
2981 | _OrthancPluginBufferCompression params; | |
2982 | params.target = target; | |
2983 | params.source = source; | |
2984 | params.size = size; | |
2985 | params.compression = compression; | |
2986 | params.uncompress = uncompress; | |
2987 | ||
2988 | return context->InvokeService(context, _OrthancPluginService_BufferCompression, ¶ms); | |
2989 | } | |
2990 | ||
2991 | ||
2992 | ||
2993 | typedef struct | |
2994 | { | |
2995 | OrthancPluginMemoryBuffer* target; | |
2996 | const char* path; | |
2997 | } _OrthancPluginReadFile; | |
2998 | ||
2999 | /** | |
3000 | * @brief Read a file. | |
3001 | * | |
3002 | * Read the content of a file on the filesystem, and returns it into | |
3003 | * a newly allocated memory buffer. | |
3004 | * | |
3005 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3006 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3007 | * @param path The path of the file to be read. | |
3008 | * @return 0 if success, or the error code if failure. | |
3009 | **/ | |
3010 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReadFile( | |
3011 | OrthancPluginContext* context, | |
3012 | OrthancPluginMemoryBuffer* target, | |
3013 | const char* path) | |
3014 | { | |
3015 | _OrthancPluginReadFile params; | |
3016 | params.target = target; | |
3017 | params.path = path; | |
3018 | return context->InvokeService(context, _OrthancPluginService_ReadFile, ¶ms); | |
3019 | } | |
3020 | ||
3021 | ||
3022 | ||
3023 | typedef struct | |
3024 | { | |
3025 | const char* path; | |
3026 | const void* data; | |
3027 | uint32_t size; | |
3028 | } _OrthancPluginWriteFile; | |
3029 | ||
3030 | /** | |
3031 | * @brief Write a file. | |
3032 | * | |
3033 | * Write the content of a memory buffer to the filesystem. | |
3034 | * | |
3035 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3036 | * @param path The path of the file to be written. | |
3037 | * @param data The content of the memory buffer. | |
3038 | * @param size The size of the memory buffer. | |
3039 | * @return 0 if success, or the error code if failure. | |
3040 | **/ | |
3041 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWriteFile( | |
3042 | OrthancPluginContext* context, | |
3043 | const char* path, | |
3044 | const void* data, | |
3045 | uint32_t size) | |
3046 | { | |
3047 | _OrthancPluginWriteFile params; | |
3048 | params.path = path; | |
3049 | params.data = data; | |
3050 | params.size = size; | |
3051 | return context->InvokeService(context, _OrthancPluginService_WriteFile, ¶ms); | |
3052 | } | |
3053 | ||
3054 | ||
3055 | ||
3056 | typedef struct | |
3057 | { | |
3058 | const char** target; | |
3059 | OrthancPluginErrorCode error; | |
3060 | } _OrthancPluginGetErrorDescription; | |
3061 | ||
3062 | /** | |
3063 | * @brief Get the description of a given error code. | |
3064 | * | |
3065 | * This function returns the description of a given error code. | |
3066 | * | |
3067 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3068 | * @param error The error code of interest. | |
3069 | * @return The error description. This is a statically-allocated | |
3070 | * string, do not free it. | |
3071 | **/ | |
3072 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetErrorDescription( | |
3073 | OrthancPluginContext* context, | |
3074 | OrthancPluginErrorCode error) | |
3075 | { | |
3076 | const char* result = NULL; | |
3077 | ||
3078 | _OrthancPluginGetErrorDescription params; | |
3079 | params.target = &result; | |
3080 | params.error = error; | |
3081 | ||
3082 | if (context->InvokeService(context, _OrthancPluginService_GetErrorDescription, ¶ms) != OrthancPluginErrorCode_Success || | |
3083 | result == NULL) | |
3084 | { | |
3085 | return "Unknown error code"; | |
3086 | } | |
3087 | else | |
3088 | { | |
3089 | return result; | |
3090 | } | |
3091 | } | |
3092 | ||
3093 | ||
3094 | ||
3095 | typedef struct | |
3096 | { | |
3097 | OrthancPluginRestOutput* output; | |
3098 | uint16_t status; | |
3099 | const char* body; | |
3100 | uint32_t bodySize; | |
3101 | } _OrthancPluginSendHttpStatus; | |
3102 | ||
3103 | /** | |
3104 | * @brief Send a HTTP status, with a custom body. | |
3105 | * | |
3106 | * This function answers to a HTTP request by sending a HTTP status | |
3107 | * code (such as "400 - Bad Request"), together with a body | |
3108 | * describing the error. The body will only be returned if the | |
3109 | * configuration option "HttpDescribeErrors" of Orthanc is set to "true". | |
3110 | * | |
3111 | * Note that: | |
3112 | * - Successful requests (status 200) must use ::OrthancPluginAnswerBuffer(). | |
3113 | * - Redirections (status 301) must use ::OrthancPluginRedirect(). | |
3114 | * - Unauthorized access (status 401) must use ::OrthancPluginSendUnauthorized(). | |
3115 | * - Methods not allowed (status 405) must use ::OrthancPluginSendMethodNotAllowed(). | |
3116 | * | |
3117 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3118 | * @param output The HTTP connection to the client application. | |
3119 | * @param status The HTTP status code to be sent. | |
3120 | * @param body The body of the answer. | |
3121 | * @param bodySize The size of the body. | |
3122 | * @see OrthancPluginSendHttpStatusCode() | |
3123 | * @ingroup REST | |
3124 | **/ | |
3125 | ORTHANC_PLUGIN_INLINE void OrthancPluginSendHttpStatus( | |
3126 | OrthancPluginContext* context, | |
3127 | OrthancPluginRestOutput* output, | |
3128 | uint16_t status, | |
3129 | const char* body, | |
3130 | uint32_t bodySize) | |
3131 | { | |
3132 | _OrthancPluginSendHttpStatus params; | |
3133 | params.output = output; | |
3134 | params.status = status; | |
3135 | params.body = body; | |
3136 | params.bodySize = bodySize; | |
3137 | context->InvokeService(context, _OrthancPluginService_SendHttpStatus, ¶ms); | |
3138 | } | |
3139 | ||
3140 | ||
3141 | ||
3142 | typedef struct | |
3143 | { | |
3144 | const OrthancPluginImage* image; | |
3145 | uint32_t* resultUint32; | |
3146 | OrthancPluginPixelFormat* resultPixelFormat; | |
3147 | void** resultBuffer; | |
3148 | } _OrthancPluginGetImageInfo; | |
3149 | ||
3150 | ||
3151 | /** | |
3152 | * @brief Return the pixel format of an image. | |
3153 | * | |
3154 | * This function returns the type of memory layout for the pixels of the given image. | |
3155 | * | |
3156 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3157 | * @param image The image of interest. | |
3158 | * @return The pixel format. | |
3159 | * @ingroup Images | |
3160 | **/ | |
3161 | ORTHANC_PLUGIN_INLINE OrthancPluginPixelFormat OrthancPluginGetImagePixelFormat( | |
3162 | OrthancPluginContext* context, | |
3163 | const OrthancPluginImage* image) | |
3164 | { | |
3165 | OrthancPluginPixelFormat target; | |
3166 | ||
3167 | _OrthancPluginGetImageInfo params; | |
3168 | memset(¶ms, 0, sizeof(params)); | |
3169 | params.image = image; | |
3170 | params.resultPixelFormat = ⌖ | |
3171 | ||
3172 | if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, ¶ms) != OrthancPluginErrorCode_Success) | |
3173 | { | |
3174 | return OrthancPluginPixelFormat_Unknown; | |
3175 | } | |
3176 | else | |
3177 | { | |
3178 | return (OrthancPluginPixelFormat) target; | |
3179 | } | |
3180 | } | |
3181 | ||
3182 | ||
3183 | ||
3184 | /** | |
3185 | * @brief Return the width of an image. | |
3186 | * | |
3187 | * This function returns the width of the given image. | |
3188 | * | |
3189 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3190 | * @param image The image of interest. | |
3191 | * @return The width. | |
3192 | * @ingroup Images | |
3193 | **/ | |
3194 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageWidth( | |
3195 | OrthancPluginContext* context, | |
3196 | const OrthancPluginImage* image) | |
3197 | { | |
3198 | uint32_t width; | |
3199 | ||
3200 | _OrthancPluginGetImageInfo params; | |
3201 | memset(¶ms, 0, sizeof(params)); | |
3202 | params.image = image; | |
3203 | params.resultUint32 = &width; | |
3204 | ||
3205 | if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, ¶ms) != OrthancPluginErrorCode_Success) | |
3206 | { | |
3207 | return 0; | |
3208 | } | |
3209 | else | |
3210 | { | |
3211 | return width; | |
3212 | } | |
3213 | } | |
3214 | ||
3215 | ||
3216 | ||
3217 | /** | |
3218 | * @brief Return the height of an image. | |
3219 | * | |
3220 | * This function returns the height of the given image. | |
3221 | * | |
3222 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3223 | * @param image The image of interest. | |
3224 | * @return The height. | |
3225 | * @ingroup Images | |
3226 | **/ | |
3227 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImageHeight( | |
3228 | OrthancPluginContext* context, | |
3229 | const OrthancPluginImage* image) | |
3230 | { | |
3231 | uint32_t height; | |
3232 | ||
3233 | _OrthancPluginGetImageInfo params; | |
3234 | memset(¶ms, 0, sizeof(params)); | |
3235 | params.image = image; | |
3236 | params.resultUint32 = &height; | |
3237 | ||
3238 | if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, ¶ms) != OrthancPluginErrorCode_Success) | |
3239 | { | |
3240 | return 0; | |
3241 | } | |
3242 | else | |
3243 | { | |
3244 | return height; | |
3245 | } | |
3246 | } | |
3247 | ||
3248 | ||
3249 | ||
3250 | /** | |
3251 | * @brief Return the pitch of an image. | |
3252 | * | |
3253 | * This function returns the pitch of the given image. The pitch is | |
3254 | * defined as the number of bytes between 2 successive lines of the | |
3255 | * image in the memory buffer. | |
3256 | * | |
3257 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3258 | * @param image The image of interest. | |
3259 | * @return The pitch. | |
3260 | * @ingroup Images | |
3261 | **/ | |
3262 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetImagePitch( | |
3263 | OrthancPluginContext* context, | |
3264 | const OrthancPluginImage* image) | |
3265 | { | |
3266 | uint32_t pitch; | |
3267 | ||
3268 | _OrthancPluginGetImageInfo params; | |
3269 | memset(¶ms, 0, sizeof(params)); | |
3270 | params.image = image; | |
3271 | params.resultUint32 = &pitch; | |
3272 | ||
3273 | if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, ¶ms) != OrthancPluginErrorCode_Success) | |
3274 | { | |
3275 | return 0; | |
3276 | } | |
3277 | else | |
3278 | { | |
3279 | return pitch; | |
3280 | } | |
3281 | } | |
3282 | ||
3283 | ||
3284 | ||
3285 | /** | |
3286 | * @brief Return a pointer to the content of an image. | |
3287 | * | |
3288 | * This function returns a pointer to the memory buffer that | |
3289 | * contains the pixels of the image. | |
3290 | * | |
3291 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3292 | * @param image The image of interest. | |
3293 | * @return The pointer. | |
3294 | * @ingroup Images | |
3295 | **/ | |
3296 | ORTHANC_PLUGIN_INLINE void* OrthancPluginGetImageBuffer( | |
3297 | OrthancPluginContext* context, | |
3298 | const OrthancPluginImage* image) | |
3299 | { | |
3300 | void* target = NULL; | |
3301 | ||
3302 | _OrthancPluginGetImageInfo params; | |
3303 | memset(¶ms, 0, sizeof(params)); | |
3304 | params.resultBuffer = ⌖ | |
3305 | params.image = image; | |
3306 | ||
3307 | if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, ¶ms) != OrthancPluginErrorCode_Success) | |
3308 | { | |
3309 | return NULL; | |
3310 | } | |
3311 | else | |
3312 | { | |
3313 | return target; | |
3314 | } | |
3315 | } | |
3316 | ||
3317 | ||
3318 | typedef struct | |
3319 | { | |
3320 | OrthancPluginImage** target; | |
3321 | const void* data; | |
3322 | uint32_t size; | |
3323 | OrthancPluginImageFormat format; | |
3324 | } _OrthancPluginUncompressImage; | |
3325 | ||
3326 | ||
3327 | /** | |
3328 | * @brief Decode a compressed image. | |
3329 | * | |
3330 | * This function decodes a compressed image from a memory buffer. | |
3331 | * | |
3332 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3333 | * @param data Pointer to a memory buffer containing the compressed image. | |
3334 | * @param size Size of the memory buffer containing the compressed image. | |
3335 | * @param format The file format of the compressed image. | |
3336 | * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). | |
3337 | * @ingroup Images | |
3338 | **/ | |
3339 | ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginUncompressImage( | |
3340 | OrthancPluginContext* context, | |
3341 | const void* data, | |
3342 | uint32_t size, | |
3343 | OrthancPluginImageFormat format) | |
3344 | { | |
3345 | OrthancPluginImage* target = NULL; | |
3346 | ||
3347 | _OrthancPluginUncompressImage params; | |
3348 | memset(¶ms, 0, sizeof(params)); | |
3349 | params.target = ⌖ | |
3350 | params.data = data; | |
3351 | params.size = size; | |
3352 | params.format = format; | |
3353 | ||
3354 | if (context->InvokeService(context, _OrthancPluginService_UncompressImage, ¶ms) != OrthancPluginErrorCode_Success) | |
3355 | { | |
3356 | return NULL; | |
3357 | } | |
3358 | else | |
3359 | { | |
3360 | return target; | |
3361 | } | |
3362 | } | |
3363 | ||
3364 | ||
3365 | ||
3366 | ||
3367 | typedef struct | |
3368 | { | |
3369 | OrthancPluginImage* image; | |
3370 | } _OrthancPluginFreeImage; | |
3371 | ||
3372 | /** | |
3373 | * @brief Free an image. | |
3374 | * | |
3375 | * This function frees an image that was decoded with OrthancPluginUncompressImage(). | |
3376 | * | |
3377 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3378 | * @param image The image. | |
3379 | * @ingroup Images | |
3380 | **/ | |
3381 | ORTHANC_PLUGIN_INLINE void OrthancPluginFreeImage( | |
3382 | OrthancPluginContext* context, | |
3383 | OrthancPluginImage* image) | |
3384 | { | |
3385 | _OrthancPluginFreeImage params; | |
3386 | params.image = image; | |
3387 | ||
3388 | context->InvokeService(context, _OrthancPluginService_FreeImage, ¶ms); | |
3389 | } | |
3390 | ||
3391 | ||
3392 | ||
3393 | ||
3394 | typedef struct | |
3395 | { | |
3396 | OrthancPluginMemoryBuffer* target; | |
3397 | OrthancPluginImageFormat imageFormat; | |
3398 | OrthancPluginPixelFormat pixelFormat; | |
3399 | uint32_t width; | |
3400 | uint32_t height; | |
3401 | uint32_t pitch; | |
3402 | const void* buffer; | |
3403 | uint8_t quality; | |
3404 | } _OrthancPluginCompressImage; | |
3405 | ||
3406 | ||
3407 | /** | |
3408 | * @brief Encode a PNG image. | |
3409 | * | |
3410 | * This function compresses the given memory buffer containing an | |
3411 | * image using the PNG specification, and stores the result of the | |
3412 | * compression into a newly allocated memory buffer. | |
3413 | * | |
3414 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3415 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3416 | * @param format The memory layout of the uncompressed image. | |
3417 | * @param width The width of the image. | |
3418 | * @param height The height of the image. | |
3419 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3420 | * between 2 successive lines of the image in the memory buffer). | |
3421 | * @param buffer The memory buffer containing the uncompressed image. | |
3422 | * @return 0 if success, or the error code if failure. | |
3423 | * @see OrthancPluginCompressAndAnswerPngImage() | |
3424 | * @ingroup Images | |
3425 | **/ | |
3426 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressPngImage( | |
3427 | OrthancPluginContext* context, | |
3428 | OrthancPluginMemoryBuffer* target, | |
3429 | OrthancPluginPixelFormat format, | |
3430 | uint32_t width, | |
3431 | uint32_t height, | |
3432 | uint32_t pitch, | |
3433 | const void* buffer) | |
3434 | { | |
3435 | _OrthancPluginCompressImage params; | |
3436 | memset(¶ms, 0, sizeof(params)); | |
3437 | params.target = target; | |
3438 | params.imageFormat = OrthancPluginImageFormat_Png; | |
3439 | params.pixelFormat = format; | |
3440 | params.width = width; | |
3441 | params.height = height; | |
3442 | params.pitch = pitch; | |
3443 | params.buffer = buffer; | |
3444 | params.quality = 0; /* Unused for PNG */ | |
3445 | ||
3446 | return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); | |
3447 | } | |
3448 | ||
3449 | ||
3450 | /** | |
3451 | * @brief Encode a JPEG image. | |
3452 | * | |
3453 | * This function compresses the given memory buffer containing an | |
3454 | * image using the JPEG specification, and stores the result of the | |
3455 | * compression into a newly allocated memory buffer. | |
3456 | * | |
3457 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3458 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3459 | * @param format The memory layout of the uncompressed image. | |
3460 | * @param width The width of the image. | |
3461 | * @param height The height of the image. | |
3462 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3463 | * between 2 successive lines of the image in the memory buffer). | |
3464 | * @param buffer The memory buffer containing the uncompressed image. | |
3465 | * @param quality The quality of the JPEG encoding, between 1 (worst | |
3466 | * quality, best compression) and 100 (best quality, worst | |
3467 | * compression). | |
3468 | * @return 0 if success, or the error code if failure. | |
3469 | * @ingroup Images | |
3470 | **/ | |
3471 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCompressJpegImage( | |
3472 | OrthancPluginContext* context, | |
3473 | OrthancPluginMemoryBuffer* target, | |
3474 | OrthancPluginPixelFormat format, | |
3475 | uint32_t width, | |
3476 | uint32_t height, | |
3477 | uint32_t pitch, | |
3478 | const void* buffer, | |
3479 | uint8_t quality) | |
3480 | { | |
3481 | _OrthancPluginCompressImage params; | |
3482 | memset(¶ms, 0, sizeof(params)); | |
3483 | params.target = target; | |
3484 | params.imageFormat = OrthancPluginImageFormat_Jpeg; | |
3485 | params.pixelFormat = format; | |
3486 | params.width = width; | |
3487 | params.height = height; | |
3488 | params.pitch = pitch; | |
3489 | params.buffer = buffer; | |
3490 | params.quality = quality; | |
3491 | ||
3492 | return context->InvokeService(context, _OrthancPluginService_CompressImage, ¶ms); | |
3493 | } | |
3494 | ||
3495 | ||
3496 | ||
3497 | /** | |
3498 | * @brief Answer to a REST request with a JPEG image. | |
3499 | * | |
3500 | * This function answers to a REST request with a JPEG image. The | |
3501 | * parameters of this function describe a memory buffer that | |
3502 | * contains an uncompressed image. The image will be automatically compressed | |
3503 | * as a JPEG image by the core system of Orthanc. | |
3504 | * | |
3505 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3506 | * @param output The HTTP connection to the client application. | |
3507 | * @param format The memory layout of the uncompressed image. | |
3508 | * @param width The width of the image. | |
3509 | * @param height The height of the image. | |
3510 | * @param pitch The pitch of the image (i.e. the number of bytes | |
3511 | * between 2 successive lines of the image in the memory buffer). | |
3512 | * @param buffer The memory buffer containing the uncompressed image. | |
3513 | * @param quality The quality of the JPEG encoding, between 1 (worst | |
3514 | * quality, best compression) and 100 (best quality, worst | |
3515 | * compression). | |
3516 | * @ingroup REST | |
3517 | **/ | |
3518 | ORTHANC_PLUGIN_INLINE void OrthancPluginCompressAndAnswerJpegImage( | |
3519 | OrthancPluginContext* context, | |
3520 | OrthancPluginRestOutput* output, | |
3521 | OrthancPluginPixelFormat format, | |
3522 | uint32_t width, | |
3523 | uint32_t height, | |
3524 | uint32_t pitch, | |
3525 | const void* buffer, | |
3526 | uint8_t quality) | |
3527 | { | |
3528 | _OrthancPluginCompressAndAnswerImage params; | |
3529 | params.output = output; | |
3530 | params.imageFormat = OrthancPluginImageFormat_Jpeg; | |
3531 | params.pixelFormat = format; | |
3532 | params.width = width; | |
3533 | params.height = height; | |
3534 | params.pitch = pitch; | |
3535 | params.buffer = buffer; | |
3536 | params.quality = quality; | |
3537 | context->InvokeService(context, _OrthancPluginService_CompressAndAnswerImage, ¶ms); | |
3538 | } | |
3539 | ||
3540 | ||
3541 | ||
3542 | ||
3543 | typedef struct | |
3544 | { | |
3545 | OrthancPluginMemoryBuffer* target; | |
3546 | OrthancPluginHttpMethod method; | |
3547 | const char* url; | |
3548 | const char* username; | |
3549 | const char* password; | |
3550 | const char* body; | |
3551 | uint32_t bodySize; | |
3552 | } _OrthancPluginCallHttpClient; | |
3553 | ||
3554 | ||
3555 | /** | |
3556 | * @brief Issue a HTTP GET call. | |
3557 | * | |
3558 | * Make a HTTP GET call to the given URL. The result to the query is | |
3559 | * stored into a newly allocated memory buffer. Favor | |
3560 | * OrthancPluginRestApiGet() if calling the built-in REST API of the | |
3561 | * Orthanc instance that hosts this plugin. | |
3562 | * | |
3563 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3564 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3565 | * @param url The URL of interest. | |
3566 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3567 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3568 | * @return 0 if success, or the error code if failure. | |
3569 | **/ | |
3570 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpGet( | |
3571 | OrthancPluginContext* context, | |
3572 | OrthancPluginMemoryBuffer* target, | |
3573 | const char* url, | |
3574 | const char* username, | |
3575 | const char* password) | |
3576 | { | |
3577 | _OrthancPluginCallHttpClient params; | |
3578 | memset(¶ms, 0, sizeof(params)); | |
3579 | ||
3580 | params.target = target; | |
3581 | params.method = OrthancPluginHttpMethod_Get; | |
3582 | params.url = url; | |
3583 | params.username = username; | |
3584 | params.password = password; | |
3585 | ||
3586 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3587 | } | |
3588 | ||
3589 | ||
3590 | /** | |
3591 | * @brief Issue a HTTP POST call. | |
3592 | * | |
3593 | * Make a HTTP POST call to the given URL. The result to the query | |
3594 | * is stored into a newly allocated memory buffer. Favor | |
3595 | * OrthancPluginRestApiPost() if calling the built-in REST API of | |
3596 | * the Orthanc instance that hosts this plugin. | |
3597 | * | |
3598 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3599 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3600 | * @param url The URL of interest. | |
3601 | * @param body The content of the body of the request. | |
3602 | * @param bodySize The size of the body of the request. | |
3603 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3604 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3605 | * @return 0 if success, or the error code if failure. | |
3606 | **/ | |
3607 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPost( | |
3608 | OrthancPluginContext* context, | |
3609 | OrthancPluginMemoryBuffer* target, | |
3610 | const char* url, | |
3611 | const char* body, | |
3612 | uint32_t bodySize, | |
3613 | const char* username, | |
3614 | const char* password) | |
3615 | { | |
3616 | _OrthancPluginCallHttpClient params; | |
3617 | memset(¶ms, 0, sizeof(params)); | |
3618 | ||
3619 | params.target = target; | |
3620 | params.method = OrthancPluginHttpMethod_Post; | |
3621 | params.url = url; | |
3622 | params.body = body; | |
3623 | params.bodySize = bodySize; | |
3624 | params.username = username; | |
3625 | params.password = password; | |
3626 | ||
3627 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3628 | } | |
3629 | ||
3630 | ||
3631 | /** | |
3632 | * @brief Issue a HTTP PUT call. | |
3633 | * | |
3634 | * Make a HTTP PUT call to the given URL. The result to the query is | |
3635 | * stored into a newly allocated memory buffer. Favor | |
3636 | * OrthancPluginRestApiPut() if calling the built-in REST API of the | |
3637 | * Orthanc instance that hosts this plugin. | |
3638 | * | |
3639 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3640 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3641 | * @param url The URL of interest. | |
3642 | * @param body The content of the body of the request. | |
3643 | * @param bodySize The size of the body of the request. | |
3644 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3645 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3646 | * @return 0 if success, or the error code if failure. | |
3647 | **/ | |
3648 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpPut( | |
3649 | OrthancPluginContext* context, | |
3650 | OrthancPluginMemoryBuffer* target, | |
3651 | const char* url, | |
3652 | const char* body, | |
3653 | uint32_t bodySize, | |
3654 | const char* username, | |
3655 | const char* password) | |
3656 | { | |
3657 | _OrthancPluginCallHttpClient params; | |
3658 | memset(¶ms, 0, sizeof(params)); | |
3659 | ||
3660 | params.target = target; | |
3661 | params.method = OrthancPluginHttpMethod_Put; | |
3662 | params.url = url; | |
3663 | params.body = body; | |
3664 | params.bodySize = bodySize; | |
3665 | params.username = username; | |
3666 | params.password = password; | |
3667 | ||
3668 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3669 | } | |
3670 | ||
3671 | ||
3672 | /** | |
3673 | * @brief Issue a HTTP DELETE call. | |
3674 | * | |
3675 | * Make a HTTP DELETE call to the given URL. Favor | |
3676 | * OrthancPluginRestApiDelete() if calling the built-in REST API of | |
3677 | * the Orthanc instance that hosts this plugin. | |
3678 | * | |
3679 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3680 | * @param url The URL of interest. | |
3681 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
3682 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
3683 | * @return 0 if success, or the error code if failure. | |
3684 | **/ | |
3685 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpDelete( | |
3686 | OrthancPluginContext* context, | |
3687 | const char* url, | |
3688 | const char* username, | |
3689 | const char* password) | |
3690 | { | |
3691 | _OrthancPluginCallHttpClient params; | |
3692 | memset(¶ms, 0, sizeof(params)); | |
3693 | ||
3694 | params.method = OrthancPluginHttpMethod_Delete; | |
3695 | params.url = url; | |
3696 | params.username = username; | |
3697 | params.password = password; | |
3698 | ||
3699 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient, ¶ms); | |
3700 | } | |
3701 | ||
3702 | ||
3703 | ||
3704 | typedef struct | |
3705 | { | |
3706 | OrthancPluginImage** target; | |
3707 | const OrthancPluginImage* source; | |
3708 | OrthancPluginPixelFormat targetFormat; | |
3709 | } _OrthancPluginConvertPixelFormat; | |
3710 | ||
3711 | ||
3712 | /** | |
3713 | * @brief Change the pixel format of an image. | |
3714 | * | |
3715 | * This function creates a new image, changing the memory layout of the pixels. | |
3716 | * | |
3717 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3718 | * @param source The source image. | |
3719 | * @param targetFormat The target pixel format. | |
3720 | * @return The resulting image. It must be freed with OrthancPluginFreeImage(). | |
3721 | * @ingroup Images | |
3722 | **/ | |
3723 | ORTHANC_PLUGIN_INLINE OrthancPluginImage *OrthancPluginConvertPixelFormat( | |
3724 | OrthancPluginContext* context, | |
3725 | const OrthancPluginImage* source, | |
3726 | OrthancPluginPixelFormat targetFormat) | |
3727 | { | |
3728 | OrthancPluginImage* target = NULL; | |
3729 | ||
3730 | _OrthancPluginConvertPixelFormat params; | |
3731 | params.target = ⌖ | |
3732 | params.source = source; | |
3733 | params.targetFormat = targetFormat; | |
3734 | ||
3735 | if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, ¶ms) != OrthancPluginErrorCode_Success) | |
3736 | { | |
3737 | return NULL; | |
3738 | } | |
3739 | else | |
3740 | { | |
3741 | return target; | |
3742 | } | |
3743 | } | |
3744 | ||
3745 | ||
3746 | ||
3747 | /** | |
3748 | * @brief Return the number of available fonts. | |
3749 | * | |
3750 | * This function returns the number of fonts that are built in the | |
3751 | * Orthanc core. These fonts can be used to draw texts on images | |
3752 | * through OrthancPluginDrawText(). | |
3753 | * | |
3754 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3755 | * @return The number of fonts. | |
3756 | * @ingroup Images | |
3757 | **/ | |
3758 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontsCount( | |
3759 | OrthancPluginContext* context) | |
3760 | { | |
3761 | uint32_t count = 0; | |
3762 | ||
3763 | _OrthancPluginReturnSingleValue params; | |
3764 | memset(¶ms, 0, sizeof(params)); | |
3765 | params.resultUint32 = &count; | |
3766 | ||
3767 | if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, ¶ms) != OrthancPluginErrorCode_Success) | |
3768 | { | |
3769 | /* Error */ | |
3770 | return 0; | |
3771 | } | |
3772 | else | |
3773 | { | |
3774 | return count; | |
3775 | } | |
3776 | } | |
3777 | ||
3778 | ||
3779 | ||
3780 | ||
3781 | typedef struct | |
3782 | { | |
3783 | uint32_t fontIndex; /* in */ | |
3784 | const char** name; /* out */ | |
3785 | uint32_t* size; /* out */ | |
3786 | } _OrthancPluginGetFontInfo; | |
3787 | ||
3788 | /** | |
3789 | * @brief Return the name of a font. | |
3790 | * | |
3791 | * This function returns the name of a font that is built in the Orthanc core. | |
3792 | * | |
3793 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3794 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3795 | * @return The font name. This is a statically-allocated string, do not free it. | |
3796 | * @ingroup Images | |
3797 | **/ | |
3798 | ORTHANC_PLUGIN_INLINE const char* OrthancPluginGetFontName( | |
3799 | OrthancPluginContext* context, | |
3800 | uint32_t fontIndex) | |
3801 | { | |
3802 | const char* result = NULL; | |
3803 | ||
3804 | _OrthancPluginGetFontInfo params; | |
3805 | memset(¶ms, 0, sizeof(params)); | |
3806 | params.name = &result; | |
3807 | params.fontIndex = fontIndex; | |
3808 | ||
3809 | if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) | |
3810 | { | |
3811 | return NULL; | |
3812 | } | |
3813 | else | |
3814 | { | |
3815 | return result; | |
3816 | } | |
3817 | } | |
3818 | ||
3819 | ||
3820 | /** | |
3821 | * @brief Return the size of a font. | |
3822 | * | |
3823 | * This function returns the size of a font that is built in the Orthanc core. | |
3824 | * | |
3825 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3826 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3827 | * @return The font size. | |
3828 | * @ingroup Images | |
3829 | **/ | |
3830 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFontSize( | |
3831 | OrthancPluginContext* context, | |
3832 | uint32_t fontIndex) | |
3833 | { | |
3834 | uint32_t result; | |
3835 | ||
3836 | _OrthancPluginGetFontInfo params; | |
3837 | memset(¶ms, 0, sizeof(params)); | |
3838 | params.size = &result; | |
3839 | params.fontIndex = fontIndex; | |
3840 | ||
3841 | if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, ¶ms) != OrthancPluginErrorCode_Success) | |
3842 | { | |
3843 | return 0; | |
3844 | } | |
3845 | else | |
3846 | { | |
3847 | return result; | |
3848 | } | |
3849 | } | |
3850 | ||
3851 | ||
3852 | ||
3853 | typedef struct | |
3854 | { | |
3855 | OrthancPluginImage* image; | |
3856 | uint32_t fontIndex; | |
3857 | const char* utf8Text; | |
3858 | int32_t x; | |
3859 | int32_t y; | |
3860 | uint8_t r; | |
3861 | uint8_t g; | |
3862 | uint8_t b; | |
3863 | } _OrthancPluginDrawText; | |
3864 | ||
3865 | ||
3866 | /** | |
3867 | * @brief Draw text on an image. | |
3868 | * | |
3869 | * This function draws some text on some image. | |
3870 | * | |
3871 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3872 | * @param image The image upon which to draw the text. | |
3873 | * @param fontIndex The index of the font. This value must be less than OrthancPluginGetFontsCount(). | |
3874 | * @param utf8Text The text to be drawn, encoded as an UTF-8 zero-terminated string. | |
3875 | * @param x The X position of the text over the image. | |
3876 | * @param y The Y position of the text over the image. | |
3877 | * @param r The value of the red color channel of the text. | |
3878 | * @param g The value of the green color channel of the text. | |
3879 | * @param b The value of the blue color channel of the text. | |
3880 | * @return 0 if success, other value if error. | |
3881 | * @ingroup Images | |
3882 | **/ | |
3883 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginDrawText( | |
3884 | OrthancPluginContext* context, | |
3885 | OrthancPluginImage* image, | |
3886 | uint32_t fontIndex, | |
3887 | const char* utf8Text, | |
3888 | int32_t x, | |
3889 | int32_t y, | |
3890 | uint8_t r, | |
3891 | uint8_t g, | |
3892 | uint8_t b) | |
3893 | { | |
3894 | _OrthancPluginDrawText params; | |
3895 | memset(¶ms, 0, sizeof(params)); | |
3896 | params.image = image; | |
3897 | params.fontIndex = fontIndex; | |
3898 | params.utf8Text = utf8Text; | |
3899 | params.x = x; | |
3900 | params.y = y; | |
3901 | params.r = r; | |
3902 | params.g = g; | |
3903 | params.b = b; | |
3904 | ||
3905 | return context->InvokeService(context, _OrthancPluginService_DrawText, ¶ms); | |
3906 | } | |
3907 | ||
3908 | ||
3909 | ||
3910 | typedef struct | |
3911 | { | |
3912 | OrthancPluginStorageArea* storageArea; | |
3913 | const char* uuid; | |
3914 | const void* content; | |
3915 | uint64_t size; | |
3916 | OrthancPluginContentType type; | |
3917 | } _OrthancPluginStorageAreaCreate; | |
3918 | ||
3919 | ||
3920 | /** | |
3921 | * @brief Create a file inside the storage area. | |
3922 | * | |
3923 | * This function creates a new file inside the storage area that is | |
3924 | * currently used by Orthanc. | |
3925 | * | |
3926 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3927 | * @param storageArea The storage area. | |
3928 | * @param uuid The identifier of the file to be created. | |
3929 | * @param content The content to store in the newly created file. | |
3930 | * @param size The size of the content. | |
3931 | * @param type The type of the file content. | |
3932 | * @return 0 if success, other value if error. | |
3933 | * @ingroup Callbacks | |
3934 | **/ | |
3935 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaCreate( | |
3936 | OrthancPluginContext* context, | |
3937 | OrthancPluginStorageArea* storageArea, | |
3938 | const char* uuid, | |
3939 | const void* content, | |
3940 | uint64_t size, | |
3941 | OrthancPluginContentType type) | |
3942 | { | |
3943 | _OrthancPluginStorageAreaCreate params; | |
3944 | params.storageArea = storageArea; | |
3945 | params.uuid = uuid; | |
3946 | params.content = content; | |
3947 | params.size = size; | |
3948 | params.type = type; | |
3949 | ||
3950 | return context->InvokeService(context, _OrthancPluginService_StorageAreaCreate, ¶ms); | |
3951 | } | |
3952 | ||
3953 | ||
3954 | typedef struct | |
3955 | { | |
3956 | OrthancPluginMemoryBuffer* target; | |
3957 | OrthancPluginStorageArea* storageArea; | |
3958 | const char* uuid; | |
3959 | OrthancPluginContentType type; | |
3960 | } _OrthancPluginStorageAreaRead; | |
3961 | ||
3962 | ||
3963 | /** | |
3964 | * @brief Read a file from the storage area. | |
3965 | * | |
3966 | * This function reads the content of a given file from the storage | |
3967 | * area that is currently used by Orthanc. | |
3968 | * | |
3969 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
3970 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
3971 | * @param storageArea The storage area. | |
3972 | * @param uuid The identifier of the file to be read. | |
3973 | * @param type The type of the file content. | |
3974 | * @return 0 if success, other value if error. | |
3975 | * @ingroup Callbacks | |
3976 | **/ | |
3977 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRead( | |
3978 | OrthancPluginContext* context, | |
3979 | OrthancPluginMemoryBuffer* target, | |
3980 | OrthancPluginStorageArea* storageArea, | |
3981 | const char* uuid, | |
3982 | OrthancPluginContentType type) | |
3983 | { | |
3984 | _OrthancPluginStorageAreaRead params; | |
3985 | params.target = target; | |
3986 | params.storageArea = storageArea; | |
3987 | params.uuid = uuid; | |
3988 | params.type = type; | |
3989 | ||
3990 | return context->InvokeService(context, _OrthancPluginService_StorageAreaRead, ¶ms); | |
3991 | } | |
3992 | ||
3993 | ||
3994 | typedef struct | |
3995 | { | |
3996 | OrthancPluginStorageArea* storageArea; | |
3997 | const char* uuid; | |
3998 | OrthancPluginContentType type; | |
3999 | } _OrthancPluginStorageAreaRemove; | |
4000 | ||
4001 | /** | |
4002 | * @brief Remove a file from the storage area. | |
4003 | * | |
4004 | * This function removes a given file from the storage area that is | |
4005 | * currently used by Orthanc. | |
4006 | * | |
4007 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4008 | * @param storageArea The storage area. | |
4009 | * @param uuid The identifier of the file to be removed. | |
4010 | * @param type The type of the file content. | |
4011 | * @return 0 if success, other value if error. | |
4012 | * @ingroup Callbacks | |
4013 | **/ | |
4014 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStorageAreaRemove( | |
4015 | OrthancPluginContext* context, | |
4016 | OrthancPluginStorageArea* storageArea, | |
4017 | const char* uuid, | |
4018 | OrthancPluginContentType type) | |
4019 | { | |
4020 | _OrthancPluginStorageAreaRemove params; | |
4021 | params.storageArea = storageArea; | |
4022 | params.uuid = uuid; | |
4023 | params.type = type; | |
4024 | ||
4025 | return context->InvokeService(context, _OrthancPluginService_StorageAreaRemove, ¶ms); | |
4026 | } | |
4027 | ||
4028 | ||
4029 | ||
4030 | typedef struct | |
4031 | { | |
4032 | OrthancPluginErrorCode* target; | |
4033 | int32_t code; | |
4034 | uint16_t httpStatus; | |
4035 | const char* message; | |
4036 | } _OrthancPluginRegisterErrorCode; | |
4037 | ||
4038 | /** | |
4039 | * @brief Declare a custom error code for this plugin. | |
4040 | * | |
4041 | * This function declares a custom error code that can be generated | |
4042 | * by this plugin. This declaration is used to enrich the body of | |
4043 | * the HTTP answer in the case of an error, and to set the proper | |
4044 | * HTTP status code. | |
4045 | * | |
4046 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4047 | * @param code The error code that is internal to this plugin. | |
4048 | * @param httpStatus The HTTP status corresponding to this error. | |
4049 | * @param message The description of the error. | |
4050 | * @return The error code that has been assigned inside the Orthanc core. | |
4051 | * @ingroup Toolbox | |
4052 | **/ | |
4053 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterErrorCode( | |
4054 | OrthancPluginContext* context, | |
4055 | int32_t code, | |
4056 | uint16_t httpStatus, | |
4057 | const char* message) | |
4058 | { | |
4059 | OrthancPluginErrorCode target; | |
4060 | ||
4061 | _OrthancPluginRegisterErrorCode params; | |
4062 | params.target = ⌖ | |
4063 | params.code = code; | |
4064 | params.httpStatus = httpStatus; | |
4065 | params.message = message; | |
4066 | ||
4067 | if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, ¶ms) == OrthancPluginErrorCode_Success) | |
4068 | { | |
4069 | return target; | |
4070 | } | |
4071 | else | |
4072 | { | |
4073 | /* There was an error while assigned the error. Use a generic code. */ | |
4074 | return OrthancPluginErrorCode_Plugin; | |
4075 | } | |
4076 | } | |
4077 | ||
4078 | ||
4079 | ||
4080 | typedef struct | |
4081 | { | |
4082 | uint16_t group; | |
4083 | uint16_t element; | |
4084 | OrthancPluginValueRepresentation vr; | |
4085 | const char* name; | |
4086 | uint32_t minMultiplicity; | |
4087 | uint32_t maxMultiplicity; | |
4088 | } _OrthancPluginRegisterDictionaryTag; | |
4089 | ||
4090 | /** | |
4091 | * @brief Register a new tag into the DICOM dictionary. | |
4092 | * | |
4093 | * This function declares a new tag in the dictionary of DICOM tags | |
4094 | * that are known to Orthanc. This function should be used in the | |
4095 | * OrthancPluginInitialize() callback. | |
4096 | * | |
4097 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4098 | * @param group The group of the tag. | |
4099 | * @param element The element of the tag. | |
4100 | * @param vr The value representation of the tag. | |
4101 | * @param name The nickname of the tag. | |
4102 | * @param minMultiplicity The minimum multiplicity of the tag (must be above 0). | |
4103 | * @param maxMultiplicity The maximum multiplicity of the tag. A value of 0 means | |
4104 | * an arbitrary multiplicity ("<tt>n</tt>"). | |
4105 | * @return 0 if success, other value if error. | |
4106 | * @ingroup Toolbox | |
4107 | **/ | |
4108 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDictionaryTag( | |
4109 | OrthancPluginContext* context, | |
4110 | uint16_t group, | |
4111 | uint16_t element, | |
4112 | OrthancPluginValueRepresentation vr, | |
4113 | const char* name, | |
4114 | uint32_t minMultiplicity, | |
4115 | uint32_t maxMultiplicity) | |
4116 | { | |
4117 | _OrthancPluginRegisterDictionaryTag params; | |
4118 | params.group = group; | |
4119 | params.element = element; | |
4120 | params.vr = vr; | |
4121 | params.name = name; | |
4122 | params.minMultiplicity = minMultiplicity; | |
4123 | params.maxMultiplicity = maxMultiplicity; | |
4124 | ||
4125 | return context->InvokeService(context, _OrthancPluginService_RegisterDictionaryTag, ¶ms); | |
4126 | } | |
4127 | ||
4128 | ||
4129 | ||
4130 | ||
4131 | typedef struct | |
4132 | { | |
4133 | OrthancPluginStorageArea* storageArea; | |
4134 | OrthancPluginResourceType level; | |
4135 | } _OrthancPluginReconstructMainDicomTags; | |
4136 | ||
4137 | /** | |
4138 | * @brief Reconstruct the main DICOM tags. | |
4139 | * | |
4140 | * This function requests the Orthanc core to reconstruct the main | |
4141 | * DICOM tags of all the resources of the given type. This function | |
4142 | * can only be used as a part of the upgrade of a custom database | |
4143 | * back-end | |
4144 | * (cf. OrthancPlugins::IDatabaseBackend::UpgradeDatabase). A | |
4145 | * database transaction will be automatically setup. | |
4146 | * | |
4147 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4148 | * @param storageArea The storage area. | |
4149 | * @param level The type of the resources of interest. | |
4150 | * @return 0 if success, other value if error. | |
4151 | * @ingroup Callbacks | |
4152 | **/ | |
4153 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReconstructMainDicomTags( | |
4154 | OrthancPluginContext* context, | |
4155 | OrthancPluginStorageArea* storageArea, | |
4156 | OrthancPluginResourceType level) | |
4157 | { | |
4158 | _OrthancPluginReconstructMainDicomTags params; | |
4159 | params.level = level; | |
4160 | params.storageArea = storageArea; | |
4161 | ||
4162 | return context->InvokeService(context, _OrthancPluginService_ReconstructMainDicomTags, ¶ms); | |
4163 | } | |
4164 | ||
4165 | ||
4166 | typedef struct | |
4167 | { | |
4168 | char** result; | |
4169 | const char* instanceId; | |
4170 | const void* buffer; | |
4171 | uint32_t size; | |
4172 | OrthancPluginDicomToJsonFormat format; | |
4173 | OrthancPluginDicomToJsonFlags flags; | |
4174 | uint32_t maxStringLength; | |
4175 | } _OrthancPluginDicomToJson; | |
4176 | ||
4177 | ||
4178 | /** | |
4179 | * @brief Format a DICOM memory buffer as a JSON string. | |
4180 | * | |
4181 | * This function takes as input a memory buffer containing a DICOM | |
4182 | * file, and outputs a JSON string representing the tags of this | |
4183 | * DICOM file. | |
4184 | * | |
4185 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4186 | * @param buffer The memory buffer containing the DICOM file. | |
4187 | * @param size The size of the memory buffer. | |
4188 | * @param format The output format. | |
4189 | * @param flags Flags governing the output. | |
4190 | * @param maxStringLength The maximum length of a field. Too long fields will | |
4191 | * be output as "null". The 0 value means no maximum length. | |
4192 | * @return The NULL value if the case of an error, or the JSON | |
4193 | * string. This string must be freed by OrthancPluginFreeString(). | |
4194 | * @ingroup Toolbox | |
4195 | * @see OrthancPluginDicomInstanceToJson | |
4196 | **/ | |
4197 | ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomBufferToJson( | |
4198 | OrthancPluginContext* context, | |
4199 | const void* buffer, | |
4200 | uint32_t size, | |
4201 | OrthancPluginDicomToJsonFormat format, | |
4202 | OrthancPluginDicomToJsonFlags flags, | |
4203 | uint32_t maxStringLength) | |
4204 | { | |
4205 | char* result; | |
4206 | ||
4207 | _OrthancPluginDicomToJson params; | |
4208 | memset(¶ms, 0, sizeof(params)); | |
4209 | params.result = &result; | |
4210 | params.buffer = buffer; | |
4211 | params.size = size; | |
4212 | params.format = format; | |
4213 | params.flags = flags; | |
4214 | params.maxStringLength = maxStringLength; | |
4215 | ||
4216 | if (context->InvokeService(context, _OrthancPluginService_DicomBufferToJson, ¶ms) != OrthancPluginErrorCode_Success) | |
4217 | { | |
4218 | /* Error */ | |
4219 | return NULL; | |
4220 | } | |
4221 | else | |
4222 | { | |
4223 | return result; | |
4224 | } | |
4225 | } | |
4226 | ||
4227 | ||
4228 | /** | |
4229 | * @brief Format a DICOM instance as a JSON string. | |
4230 | * | |
4231 | * This function formats a DICOM instance that is stored in Orthanc, | |
4232 | * and outputs a JSON string representing the tags of this DICOM | |
4233 | * instance. | |
4234 | * | |
4235 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4236 | * @param instanceId The Orthanc identifier of the instance. | |
4237 | * @param format The output format. | |
4238 | * @param flags Flags governing the output. | |
4239 | * @param maxStringLength The maximum length of a field. Too long fields will | |
4240 | * be output as "null". The 0 value means no maximum length. | |
4241 | * @return The NULL value if the case of an error, or the JSON | |
4242 | * string. This string must be freed by OrthancPluginFreeString(). | |
4243 | * @ingroup Toolbox | |
4244 | * @see OrthancPluginDicomInstanceToJson | |
4245 | **/ | |
4246 | ORTHANC_PLUGIN_INLINE char* OrthancPluginDicomInstanceToJson( | |
4247 | OrthancPluginContext* context, | |
4248 | const char* instanceId, | |
4249 | OrthancPluginDicomToJsonFormat format, | |
4250 | OrthancPluginDicomToJsonFlags flags, | |
4251 | uint32_t maxStringLength) | |
4252 | { | |
4253 | char* result; | |
4254 | ||
4255 | _OrthancPluginDicomToJson params; | |
4256 | memset(¶ms, 0, sizeof(params)); | |
4257 | params.result = &result; | |
4258 | params.instanceId = instanceId; | |
4259 | params.format = format; | |
4260 | params.flags = flags; | |
4261 | params.maxStringLength = maxStringLength; | |
4262 | ||
4263 | if (context->InvokeService(context, _OrthancPluginService_DicomInstanceToJson, ¶ms) != OrthancPluginErrorCode_Success) | |
4264 | { | |
4265 | /* Error */ | |
4266 | return NULL; | |
4267 | } | |
4268 | else | |
4269 | { | |
4270 | return result; | |
4271 | } | |
4272 | } | |
4273 | ||
4274 | ||
4275 | typedef struct | |
4276 | { | |
4277 | OrthancPluginMemoryBuffer* target; | |
4278 | const char* uri; | |
4279 | uint32_t headersCount; | |
4280 | const char* const* headersKeys; | |
4281 | const char* const* headersValues; | |
4282 | int32_t afterPlugins; | |
4283 | } _OrthancPluginRestApiGet2; | |
4284 | ||
4285 | /** | |
4286 | * @brief Make a GET call to the Orthanc REST API, with custom HTTP headers. | |
4287 | * | |
4288 | * Make a GET call to the Orthanc REST API with extended | |
4289 | * parameters. The result to the query is stored into a newly | |
4290 | * allocated memory buffer. | |
4291 | * | |
4292 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4293 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4294 | * @param uri The URI in the built-in Orthanc API. | |
4295 | * @param headersCount The number of HTTP headers. | |
4296 | * @param headersKeys Array containing the keys of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4297 | * @param headersValues Array containing the values of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4298 | * @param afterPlugins If 0, the built-in API of Orthanc is used. | |
4299 | * If 1, the API is tainted by the plugins. | |
4300 | * @return 0 if success, or the error code if failure. | |
4301 | * @see OrthancPluginRestApiGet, OrthancPluginRestApiGetAfterPlugins | |
4302 | * @ingroup Orthanc | |
4303 | **/ | |
4304 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRestApiGet2( | |
4305 | OrthancPluginContext* context, | |
4306 | OrthancPluginMemoryBuffer* target, | |
4307 | const char* uri, | |
4308 | uint32_t headersCount, | |
4309 | const char* const* headersKeys, | |
4310 | const char* const* headersValues, | |
4311 | int32_t afterPlugins) | |
4312 | { | |
4313 | _OrthancPluginRestApiGet2 params; | |
4314 | params.target = target; | |
4315 | params.uri = uri; | |
4316 | params.headersCount = headersCount; | |
4317 | params.headersKeys = headersKeys; | |
4318 | params.headersValues = headersValues; | |
4319 | params.afterPlugins = afterPlugins; | |
4320 | ||
4321 | return context->InvokeService(context, _OrthancPluginService_RestApiGet2, ¶ms); | |
4322 | } | |
4323 | ||
4324 | ||
4325 | ||
4326 | typedef struct | |
4327 | { | |
4328 | OrthancPluginWorklistCallback callback; | |
4329 | } _OrthancPluginWorklistCallback; | |
4330 | ||
4331 | /** | |
4332 | * @brief Register a callback to handle modality worklists requests. | |
4333 | * | |
4334 | * This function registers a callback to handle C-Find SCP requests | |
4335 | * on modality worklists. | |
4336 | * | |
4337 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4338 | * @param callback The callback. | |
4339 | * @return 0 if success, other value if error. | |
4340 | * @ingroup DicomCallbacks | |
4341 | **/ | |
4342 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterWorklistCallback( | |
4343 | OrthancPluginContext* context, | |
4344 | OrthancPluginWorklistCallback callback) | |
4345 | { | |
4346 | _OrthancPluginWorklistCallback params; | |
4347 | params.callback = callback; | |
4348 | ||
4349 | return context->InvokeService(context, _OrthancPluginService_RegisterWorklistCallback, ¶ms); | |
4350 | } | |
4351 | ||
4352 | ||
4353 | ||
4354 | typedef struct | |
4355 | { | |
4356 | OrthancPluginWorklistAnswers* answers; | |
4357 | const OrthancPluginWorklistQuery* query; | |
4358 | const void* dicom; | |
4359 | uint32_t size; | |
4360 | } _OrthancPluginWorklistAnswersOperation; | |
4361 | ||
4362 | /** | |
4363 | * @brief Add one answer to some modality worklist request. | |
4364 | * | |
4365 | * This function adds one worklist (encoded as a DICOM file) to the | |
4366 | * set of answers corresponding to some C-Find SCP request against | |
4367 | * modality worklists. | |
4368 | * | |
4369 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4370 | * @param answers The set of answers. | |
4371 | * @param query The worklist query, as received by the callback. | |
4372 | * @param dicom The worklist to answer, encoded as a DICOM file. | |
4373 | * @param size The size of the DICOM file. | |
4374 | * @return 0 if success, other value if error. | |
4375 | * @ingroup DicomCallbacks | |
4376 | * @see OrthancPluginCreateDicom() | |
4377 | **/ | |
4378 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistAddAnswer( | |
4379 | OrthancPluginContext* context, | |
4380 | OrthancPluginWorklistAnswers* answers, | |
4381 | const OrthancPluginWorklistQuery* query, | |
4382 | const void* dicom, | |
4383 | uint32_t size) | |
4384 | { | |
4385 | _OrthancPluginWorklistAnswersOperation params; | |
4386 | params.answers = answers; | |
4387 | params.query = query; | |
4388 | params.dicom = dicom; | |
4389 | params.size = size; | |
4390 | ||
4391 | return context->InvokeService(context, _OrthancPluginService_WorklistAddAnswer, ¶ms); | |
4392 | } | |
4393 | ||
4394 | ||
4395 | /** | |
4396 | * @brief Mark the set of worklist answers as incomplete. | |
4397 | * | |
4398 | * This function marks as incomplete the set of answers | |
4399 | * corresponding to some C-Find SCP request against modality | |
4400 | * worklists. This must be used if canceling the handling of a | |
4401 | * request when too many answers are to be returned. | |
4402 | * | |
4403 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4404 | * @param answers The set of answers. | |
4405 | * @return 0 if success, other value if error. | |
4406 | * @ingroup DicomCallbacks | |
4407 | **/ | |
4408 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistMarkIncomplete( | |
4409 | OrthancPluginContext* context, | |
4410 | OrthancPluginWorklistAnswers* answers) | |
4411 | { | |
4412 | _OrthancPluginWorklistAnswersOperation params; | |
4413 | params.answers = answers; | |
4414 | params.query = NULL; | |
4415 | params.dicom = NULL; | |
4416 | params.size = 0; | |
4417 | ||
4418 | return context->InvokeService(context, _OrthancPluginService_WorklistMarkIncomplete, ¶ms); | |
4419 | } | |
4420 | ||
4421 | ||
4422 | typedef struct | |
4423 | { | |
4424 | const OrthancPluginWorklistQuery* query; | |
4425 | const void* dicom; | |
4426 | uint32_t size; | |
4427 | int32_t* isMatch; | |
4428 | OrthancPluginMemoryBuffer* target; | |
4429 | } _OrthancPluginWorklistQueryOperation; | |
4430 | ||
4431 | /** | |
4432 | * @brief Test whether a worklist matches the query. | |
4433 | * | |
4434 | * This function checks whether one worklist (encoded as a DICOM | |
4435 | * file) matches the C-Find SCP query against modality | |
4436 | * worklists. This function must be called before adding the | |
4437 | * worklist as an answer through OrthancPluginWorklistAddAnswer(). | |
4438 | * | |
4439 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4440 | * @param query The worklist query, as received by the callback. | |
4441 | * @param dicom The worklist to answer, encoded as a DICOM file. | |
4442 | * @param size The size of the DICOM file. | |
4443 | * @return 1 if the worklist matches the query, 0 otherwise. | |
4444 | * @ingroup DicomCallbacks | |
4445 | **/ | |
4446 | ORTHANC_PLUGIN_INLINE int32_t OrthancPluginWorklistIsMatch( | |
4447 | OrthancPluginContext* context, | |
4448 | const OrthancPluginWorklistQuery* query, | |
4449 | const void* dicom, | |
4450 | uint32_t size) | |
4451 | { | |
4452 | int32_t isMatch = 0; | |
4453 | ||
4454 | _OrthancPluginWorklistQueryOperation params; | |
4455 | params.query = query; | |
4456 | params.dicom = dicom; | |
4457 | params.size = size; | |
4458 | params.isMatch = &isMatch; | |
4459 | params.target = NULL; | |
4460 | ||
4461 | if (context->InvokeService(context, _OrthancPluginService_WorklistIsMatch, ¶ms) == OrthancPluginErrorCode_Success) | |
4462 | { | |
4463 | return isMatch; | |
4464 | } | |
4465 | else | |
4466 | { | |
4467 | /* Error: Assume non-match */ | |
4468 | return 0; | |
4469 | } | |
4470 | } | |
4471 | ||
4472 | ||
4473 | /** | |
4474 | * @brief Retrieve the worklist query as a DICOM file. | |
4475 | * | |
4476 | * This function retrieves the DICOM file that underlies a C-Find | |
4477 | * SCP query against modality worklists. | |
4478 | * | |
4479 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4480 | * @param target Memory buffer where to store the DICOM file. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4481 | * @param query The worklist query, as received by the callback. | |
4482 | * @return 0 if success, other value if error. | |
4483 | * @ingroup DicomCallbacks | |
4484 | **/ | |
4485 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWorklistGetDicomQuery( | |
4486 | OrthancPluginContext* context, | |
4487 | OrthancPluginMemoryBuffer* target, | |
4488 | const OrthancPluginWorklistQuery* query) | |
4489 | { | |
4490 | _OrthancPluginWorklistQueryOperation params; | |
4491 | params.query = query; | |
4492 | params.dicom = NULL; | |
4493 | params.size = 0; | |
4494 | params.isMatch = NULL; | |
4495 | params.target = target; | |
4496 | ||
4497 | return context->InvokeService(context, _OrthancPluginService_WorklistGetDicomQuery, ¶ms); | |
4498 | } | |
4499 | ||
4500 | ||
4501 | /** | |
4502 | * @brief Get the origin of a DICOM file. | |
4503 | * | |
4504 | * This function returns the origin of a DICOM instance that has been received by Orthanc. | |
4505 | * | |
4506 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4507 | * @param instance The instance of interest. | |
4508 | * @return The origin of the instance. | |
4509 | * @ingroup Callbacks | |
4510 | **/ | |
4511 | ORTHANC_PLUGIN_INLINE OrthancPluginInstanceOrigin OrthancPluginGetInstanceOrigin( | |
4512 | OrthancPluginContext* context, | |
4513 | OrthancPluginDicomInstance* instance) | |
4514 | { | |
4515 | OrthancPluginInstanceOrigin origin; | |
4516 | ||
4517 | _OrthancPluginAccessDicomInstance params; | |
4518 | memset(¶ms, 0, sizeof(params)); | |
4519 | params.resultOrigin = &origin; | |
4520 | params.instance = instance; | |
4521 | ||
4522 | if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, ¶ms) != OrthancPluginErrorCode_Success) | |
4523 | { | |
4524 | /* Error */ | |
4525 | return OrthancPluginInstanceOrigin_Unknown; | |
4526 | } | |
4527 | else | |
4528 | { | |
4529 | return origin; | |
4530 | } | |
4531 | } | |
4532 | ||
4533 | ||
4534 | typedef struct | |
4535 | { | |
4536 | OrthancPluginMemoryBuffer* target; | |
4537 | const char* json; | |
4538 | const OrthancPluginImage* pixelData; | |
4539 | OrthancPluginCreateDicomFlags flags; | |
4540 | } _OrthancPluginCreateDicom; | |
4541 | ||
4542 | /** | |
4543 | * @brief Create a DICOM instance from a JSON string and an image. | |
4544 | * | |
4545 | * This function takes as input a string containing a JSON file | |
4546 | * describing the content of a DICOM instance. As an output, it | |
4547 | * writes the corresponding DICOM instance to a newly allocated | |
4548 | * memory buffer. Additionally, an image to be encoded within the | |
4549 | * DICOM instance can also be provided. | |
4550 | * | |
4551 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4552 | * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4553 | * @param json The input JSON file. | |
4554 | * @param pixelData The image. Can be NULL, if the pixel data is encoded inside the JSON with the data URI scheme. | |
4555 | * @param flags Flags governing the output. | |
4556 | * @return 0 if success, other value if error. | |
4557 | * @ingroup Toolbox | |
4558 | * @see OrthancPluginDicomBufferToJson | |
4559 | **/ | |
4560 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginCreateDicom( | |
4561 | OrthancPluginContext* context, | |
4562 | OrthancPluginMemoryBuffer* target, | |
4563 | const char* json, | |
4564 | const OrthancPluginImage* pixelData, | |
4565 | OrthancPluginCreateDicomFlags flags) | |
4566 | { | |
4567 | _OrthancPluginCreateDicom params; | |
4568 | params.target = target; | |
4569 | params.json = json; | |
4570 | params.pixelData = pixelData; | |
4571 | params.flags = flags; | |
4572 | ||
4573 | return context->InvokeService(context, _OrthancPluginService_CreateDicom, ¶ms); | |
4574 | } | |
4575 | ||
4576 | ||
4577 | typedef struct | |
4578 | { | |
4579 | OrthancPluginDecodeImageCallback callback; | |
4580 | } _OrthancPluginDecodeImageCallback; | |
4581 | ||
4582 | /** | |
4583 | * @brief Register a callback to handle the decoding of DICOM images. | |
4584 | * | |
4585 | * This function registers a custom callback to the decoding of | |
4586 | * DICOM images, replacing the built-in decoder of Orthanc. | |
4587 | * | |
4588 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4589 | * @param callback The callback. | |
4590 | * @return 0 if success, other value if error. | |
4591 | * @ingroup Callbacks | |
4592 | **/ | |
4593 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterDecodeImageCallback( | |
4594 | OrthancPluginContext* context, | |
4595 | OrthancPluginDecodeImageCallback callback) | |
4596 | { | |
4597 | _OrthancPluginDecodeImageCallback params; | |
4598 | params.callback = callback; | |
4599 | ||
4600 | return context->InvokeService(context, _OrthancPluginService_RegisterDecodeImageCallback, ¶ms); | |
4601 | } | |
4602 | ||
4603 | ||
4604 | ||
4605 | typedef struct | |
4606 | { | |
4607 | OrthancPluginImage** target; | |
4608 | OrthancPluginPixelFormat format; | |
4609 | uint32_t width; | |
4610 | uint32_t height; | |
4611 | uint32_t pitch; | |
4612 | void* buffer; | |
4613 | const void* constBuffer; | |
4614 | uint32_t bufferSize; | |
4615 | uint32_t frameIndex; | |
4616 | } _OrthancPluginCreateImage; | |
4617 | ||
4618 | ||
4619 | /** | |
4620 | * @brief Create an image. | |
4621 | * | |
4622 | * This function creates an image of given size and format. | |
4623 | * | |
4624 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4625 | * @param format The format of the pixels. | |
4626 | * @param width The width of the image. | |
4627 | * @param height The height of the image. | |
4628 | * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). | |
4629 | * @ingroup Images | |
4630 | **/ | |
4631 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImage( | |
4632 | OrthancPluginContext* context, | |
4633 | OrthancPluginPixelFormat format, | |
4634 | uint32_t width, | |
4635 | uint32_t height) | |
4636 | { | |
4637 | OrthancPluginImage* target = NULL; | |
4638 | ||
4639 | _OrthancPluginCreateImage params; | |
4640 | memset(¶ms, 0, sizeof(params)); | |
4641 | params.target = ⌖ | |
4642 | params.format = format; | |
4643 | params.width = width; | |
4644 | params.height = height; | |
4645 | ||
4646 | if (context->InvokeService(context, _OrthancPluginService_CreateImage, ¶ms) != OrthancPluginErrorCode_Success) | |
4647 | { | |
4648 | return NULL; | |
4649 | } | |
4650 | else | |
4651 | { | |
4652 | return target; | |
4653 | } | |
4654 | } | |
4655 | ||
4656 | ||
4657 | /** | |
4658 | * @brief Create an image pointing to a memory buffer. | |
4659 | * | |
4660 | * This function creates an image whose content points to a memory | |
4661 | * buffer managed by the plugin. Note that the buffer is directly | |
4662 | * accessed, no memory is allocated and no data is copied. | |
4663 | * | |
4664 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4665 | * @param format The format of the pixels. | |
4666 | * @param width The width of the image. | |
4667 | * @param height The height of the image. | |
4668 | * @param pitch The pitch of the image (i.e. the number of bytes | |
4669 | * between 2 successive lines of the image in the memory buffer). | |
4670 | * @param buffer The memory buffer. | |
4671 | * @return The newly allocated image. It must be freed with OrthancPluginFreeImage(). | |
4672 | * @ingroup Images | |
4673 | **/ | |
4674 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginCreateImageAccessor( | |
4675 | OrthancPluginContext* context, | |
4676 | OrthancPluginPixelFormat format, | |
4677 | uint32_t width, | |
4678 | uint32_t height, | |
4679 | uint32_t pitch, | |
4680 | void* buffer) | |
4681 | { | |
4682 | OrthancPluginImage* target = NULL; | |
4683 | ||
4684 | _OrthancPluginCreateImage params; | |
4685 | memset(¶ms, 0, sizeof(params)); | |
4686 | params.target = ⌖ | |
4687 | params.format = format; | |
4688 | params.width = width; | |
4689 | params.height = height; | |
4690 | params.pitch = pitch; | |
4691 | params.buffer = buffer; | |
4692 | ||
4693 | if (context->InvokeService(context, _OrthancPluginService_CreateImageAccessor, ¶ms) != OrthancPluginErrorCode_Success) | |
4694 | { | |
4695 | return NULL; | |
4696 | } | |
4697 | else | |
4698 | { | |
4699 | return target; | |
4700 | } | |
4701 | } | |
4702 | ||
4703 | ||
4704 | ||
4705 | /** | |
4706 | * @brief Decode one frame from a DICOM instance. | |
4707 | * | |
4708 | * This function decodes one frame of a DICOM image that is stored | |
4709 | * in a memory buffer. This function will give the same result as | |
4710 | * OrthancPluginUncompressImage() for single-frame DICOM images. | |
4711 | * | |
4712 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4713 | * @param buffer Pointer to a memory buffer containing the DICOM image. | |
4714 | * @param bufferSize Size of the memory buffer containing the DICOM image. | |
4715 | * @param frameIndex The index of the frame of interest in a multi-frame image. | |
4716 | * @return The uncompressed image. It must be freed with OrthancPluginFreeImage(). | |
4717 | * @ingroup Images | |
4718 | **/ | |
4719 | ORTHANC_PLUGIN_INLINE OrthancPluginImage* OrthancPluginDecodeDicomImage( | |
4720 | OrthancPluginContext* context, | |
4721 | const void* buffer, | |
4722 | uint32_t bufferSize, | |
4723 | uint32_t frameIndex) | |
4724 | { | |
4725 | OrthancPluginImage* target = NULL; | |
4726 | ||
4727 | _OrthancPluginCreateImage params; | |
4728 | memset(¶ms, 0, sizeof(params)); | |
4729 | params.target = ⌖ | |
4730 | params.constBuffer = buffer; | |
4731 | params.bufferSize = bufferSize; | |
4732 | params.frameIndex = frameIndex; | |
4733 | ||
4734 | if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, ¶ms) != OrthancPluginErrorCode_Success) | |
4735 | { | |
4736 | return NULL; | |
4737 | } | |
4738 | else | |
4739 | { | |
4740 | return target; | |
4741 | } | |
4742 | } | |
4743 | ||
4744 | ||
4745 | ||
4746 | typedef struct | |
4747 | { | |
4748 | char** result; | |
4749 | const void* buffer; | |
4750 | uint32_t size; | |
4751 | } _OrthancPluginComputeHash; | |
4752 | ||
4753 | /** | |
4754 | * @brief Compute an MD5 hash. | |
4755 | * | |
4756 | * This functions computes the MD5 cryptographic hash of the given memory buffer. | |
4757 | * | |
4758 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4759 | * @param buffer The source memory buffer. | |
4760 | * @param size The size in bytes of the source buffer. | |
4761 | * @return The NULL value in case of error, or a string containing the cryptographic hash. | |
4762 | * This string must be freed by OrthancPluginFreeString(). | |
4763 | * @ingroup Toolbox | |
4764 | **/ | |
4765 | ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeMd5( | |
4766 | OrthancPluginContext* context, | |
4767 | const void* buffer, | |
4768 | uint32_t size) | |
4769 | { | |
4770 | char* result; | |
4771 | ||
4772 | _OrthancPluginComputeHash params; | |
4773 | params.result = &result; | |
4774 | params.buffer = buffer; | |
4775 | params.size = size; | |
4776 | ||
4777 | if (context->InvokeService(context, _OrthancPluginService_ComputeMd5, ¶ms) != OrthancPluginErrorCode_Success) | |
4778 | { | |
4779 | /* Error */ | |
4780 | return NULL; | |
4781 | } | |
4782 | else | |
4783 | { | |
4784 | return result; | |
4785 | } | |
4786 | } | |
4787 | ||
4788 | ||
4789 | /** | |
4790 | * @brief Compute a SHA-1 hash. | |
4791 | * | |
4792 | * This functions computes the SHA-1 cryptographic hash of the given memory buffer. | |
4793 | * | |
4794 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4795 | * @param buffer The source memory buffer. | |
4796 | * @param size The size in bytes of the source buffer. | |
4797 | * @return The NULL value in case of error, or a string containing the cryptographic hash. | |
4798 | * This string must be freed by OrthancPluginFreeString(). | |
4799 | * @ingroup Toolbox | |
4800 | **/ | |
4801 | ORTHANC_PLUGIN_INLINE char* OrthancPluginComputeSha1( | |
4802 | OrthancPluginContext* context, | |
4803 | const void* buffer, | |
4804 | uint32_t size) | |
4805 | { | |
4806 | char* result; | |
4807 | ||
4808 | _OrthancPluginComputeHash params; | |
4809 | params.result = &result; | |
4810 | params.buffer = buffer; | |
4811 | params.size = size; | |
4812 | ||
4813 | if (context->InvokeService(context, _OrthancPluginService_ComputeSha1, ¶ms) != OrthancPluginErrorCode_Success) | |
4814 | { | |
4815 | /* Error */ | |
4816 | return NULL; | |
4817 | } | |
4818 | else | |
4819 | { | |
4820 | return result; | |
4821 | } | |
4822 | } | |
4823 | ||
4824 | ||
4825 | ||
4826 | typedef struct | |
4827 | { | |
4828 | OrthancPluginDictionaryEntry* target; | |
4829 | const char* name; | |
4830 | } _OrthancPluginLookupDictionary; | |
4831 | ||
4832 | /** | |
4833 | * @brief Get information about the given DICOM tag. | |
4834 | * | |
4835 | * This functions makes a lookup in the dictionary of DICOM tags | |
4836 | * that are known to Orthanc, and returns information about this | |
4837 | * tag. The tag can be specified using its human-readable name | |
4838 | * (e.g. "PatientName") or a set of two hexadecimal numbers | |
4839 | * (e.g. "0010-0020"). | |
4840 | * | |
4841 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4842 | * @param target Where to store the information about the tag. | |
4843 | * @param name The name of the DICOM tag. | |
4844 | * @return 0 if success, other value if error. | |
4845 | * @ingroup Toolbox | |
4846 | **/ | |
4847 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginLookupDictionary( | |
4848 | OrthancPluginContext* context, | |
4849 | OrthancPluginDictionaryEntry* target, | |
4850 | const char* name) | |
4851 | { | |
4852 | _OrthancPluginLookupDictionary params; | |
4853 | params.target = target; | |
4854 | params.name = name; | |
4855 | return context->InvokeService(context, _OrthancPluginService_LookupDictionary, ¶ms); | |
4856 | } | |
4857 | ||
4858 | ||
4859 | ||
4860 | typedef struct | |
4861 | { | |
4862 | OrthancPluginRestOutput* output; | |
4863 | const char* answer; | |
4864 | uint32_t answerSize; | |
4865 | uint32_t headersCount; | |
4866 | const char* const* headersKeys; | |
4867 | const char* const* headersValues; | |
4868 | } _OrthancPluginSendMultipartItem2; | |
4869 | ||
4870 | /** | |
4871 | * @brief Send an item as a part of some HTTP multipart answer, with custom headers. | |
4872 | * | |
4873 | * This function sends an item as a part of some HTTP multipart | |
4874 | * answer that was initiated by OrthancPluginStartMultipartAnswer(). In addition to | |
4875 | * OrthancPluginSendMultipartItem(), this function will set HTTP header associated | |
4876 | * with the item. | |
4877 | * | |
4878 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4879 | * @param output The HTTP connection to the client application. | |
4880 | * @param answer Pointer to the memory buffer containing the item. | |
4881 | * @param answerSize Number of bytes of the item. | |
4882 | * @param headersCount The number of HTTP headers. | |
4883 | * @param headersKeys Array containing the keys of the HTTP headers. | |
4884 | * @param headersValues Array containing the values of the HTTP headers. | |
4885 | * @return 0 if success, or the error code if failure (this notably happens | |
4886 | * if the connection is closed by the client). | |
4887 | * @see OrthancPluginSendMultipartItem() | |
4888 | * @ingroup REST | |
4889 | **/ | |
4890 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem2( | |
4891 | OrthancPluginContext* context, | |
4892 | OrthancPluginRestOutput* output, | |
4893 | const char* answer, | |
4894 | uint32_t answerSize, | |
4895 | uint32_t headersCount, | |
4896 | const char* const* headersKeys, | |
4897 | const char* const* headersValues) | |
4898 | { | |
4899 | _OrthancPluginSendMultipartItem2 params; | |
4900 | params.output = output; | |
4901 | params.answer = answer; | |
4902 | params.answerSize = answerSize; | |
4903 | params.headersCount = headersCount; | |
4904 | params.headersKeys = headersKeys; | |
4905 | params.headersValues = headersValues; | |
4906 | ||
4907 | return context->InvokeService(context, _OrthancPluginService_SendMultipartItem2, ¶ms); | |
4908 | } | |
4909 | ||
4910 | ||
4911 | typedef struct | |
4912 | { | |
4913 | OrthancPluginIncomingHttpRequestFilter callback; | |
4914 | } _OrthancPluginIncomingHttpRequestFilter; | |
4915 | ||
4916 | /** | |
4917 | * @brief Register a callback to filter incoming HTTP requests. | |
4918 | * | |
4919 | * This function registers a custom callback to filter incoming HTTP/REST | |
4920 | * requests received by the HTTP server of Orthanc. | |
4921 | * | |
4922 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4923 | * @param callback The callback. | |
4924 | * @return 0 if success, other value if error. | |
4925 | * @ingroup Callbacks | |
4926 | **/ | |
4927 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingHttpRequestFilter( | |
4928 | OrthancPluginContext* context, | |
4929 | OrthancPluginIncomingHttpRequestFilter callback) | |
4930 | { | |
4931 | _OrthancPluginIncomingHttpRequestFilter params; | |
4932 | params.callback = callback; | |
4933 | ||
4934 | return context->InvokeService(context, _OrthancPluginService_RegisterIncomingHttpRequestFilter, ¶ms); | |
4935 | } | |
4936 | ||
4937 | ||
4938 | ||
4939 | typedef struct | |
4940 | { | |
4941 | OrthancPluginMemoryBuffer* answerBody; | |
4942 | OrthancPluginMemoryBuffer* answerHeaders; | |
4943 | uint16_t* httpStatus; | |
4944 | OrthancPluginHttpMethod method; | |
4945 | const char* url; | |
4946 | uint32_t headersCount; | |
4947 | const char* const* headersKeys; | |
4948 | const char* const* headersValues; | |
4949 | const char* body; | |
4950 | uint32_t bodySize; | |
4951 | const char* username; | |
4952 | const char* password; | |
4953 | uint32_t timeout; | |
4954 | const char* certificateFile; | |
4955 | const char* certificateKeyFile; | |
4956 | const char* certificateKeyPassword; | |
4957 | uint8_t pkcs11; | |
4958 | } _OrthancPluginCallHttpClient2; | |
4959 | ||
4960 | ||
4961 | ||
4962 | /** | |
4963 | * @brief Issue a HTTP call with full flexibility. | |
4964 | * | |
4965 | * Make a HTTP call to the given URL. The result to the query is | |
4966 | * stored into a newly allocated memory buffer. The HTTP request | |
4967 | * will be done accordingly to the global configuration of Orthanc | |
4968 | * (in particular, the options "HttpProxy", "HttpTimeout", | |
4969 | * "HttpsVerifyPeers", "HttpsCACertificates", and "Pkcs11" will be | |
4970 | * taken into account). | |
4971 | * | |
4972 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
4973 | * @param answerBody The target memory buffer (out argument). | |
4974 | * It must be freed with OrthancPluginFreeMemoryBuffer(). | |
4975 | * @param answerHeaders The target memory buffer for the HTTP headers in the answers (out argument). | |
4976 | * The answer headers are formatted as a JSON object (associative array). | |
4977 | * The buffer must be freed with OrthancPluginFreeMemoryBuffer(). | |
4978 | * This argument can be set to NULL if the plugin has no interest in the HTTP headers. | |
4979 | * @param httpStatus The HTTP status after the execution of the request (out argument). | |
4980 | * @param method HTTP method to be used. | |
4981 | * @param url The URL of interest. | |
4982 | * @param headersCount The number of HTTP headers. | |
4983 | * @param headersKeys Array containing the keys of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4984 | * @param headersValues Array containing the values of the HTTP headers (can be <tt>NULL</tt> if no header). | |
4985 | * @param username The username (can be <tt>NULL</tt> if no password protection). | |
4986 | * @param password The password (can be <tt>NULL</tt> if no password protection). | |
4987 | * @param body The body of the POST request. | |
4988 | * @param bodySize The size of the body. | |
4989 | * @param timeout Timeout in seconds (0 for default timeout). | |
4990 | * @param certificateFile Path to the client certificate for HTTPS, in PEM format | |
4991 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4992 | * @param certificateKeyFile Path to the key of the client certificate for HTTPS, in PEM format | |
4993 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4994 | * @param certificateKeyPassword Password to unlock the key of the client certificate | |
4995 | * (can be <tt>NULL</tt> if no client certificate or if not using HTTPS). | |
4996 | * @param pkcs11 Enable PKCS#11 client authentication for hardware security modules and smart cards. | |
4997 | * @return 0 if success, or the error code if failure. | |
4998 | **/ | |
4999 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginHttpClient( | |
5000 | OrthancPluginContext* context, | |
5001 | OrthancPluginMemoryBuffer* answerBody, | |
5002 | OrthancPluginMemoryBuffer* answerHeaders, | |
5003 | uint16_t* httpStatus, | |
5004 | OrthancPluginHttpMethod method, | |
5005 | const char* url, | |
5006 | uint32_t headersCount, | |
5007 | const char* const* headersKeys, | |
5008 | const char* const* headersValues, | |
5009 | const char* body, | |
5010 | uint32_t bodySize, | |
5011 | const char* username, | |
5012 | const char* password, | |
5013 | uint32_t timeout, | |
5014 | const char* certificateFile, | |
5015 | const char* certificateKeyFile, | |
5016 | const char* certificateKeyPassword, | |
5017 | uint8_t pkcs11) | |
5018 | { | |
5019 | _OrthancPluginCallHttpClient2 params; | |
5020 | memset(¶ms, 0, sizeof(params)); | |
5021 | ||
5022 | params.answerBody = answerBody; | |
5023 | params.answerHeaders = answerHeaders; | |
5024 | params.httpStatus = httpStatus; | |
5025 | params.method = method; | |
5026 | params.url = url; | |
5027 | params.headersCount = headersCount; | |
5028 | params.headersKeys = headersKeys; | |
5029 | params.headersValues = headersValues; | |
5030 | params.body = body; | |
5031 | params.bodySize = bodySize; | |
5032 | params.username = username; | |
5033 | params.password = password; | |
5034 | params.timeout = timeout; | |
5035 | params.certificateFile = certificateFile; | |
5036 | params.certificateKeyFile = certificateKeyFile; | |
5037 | params.certificateKeyPassword = certificateKeyPassword; | |
5038 | params.pkcs11 = pkcs11; | |
5039 | ||
5040 | return context->InvokeService(context, _OrthancPluginService_CallHttpClient2, ¶ms); | |
5041 | } | |
5042 | ||
5043 | ||
5044 | /** | |
5045 | * @brief Generate an UUID. | |
5046 | * | |
5047 | * Generate a random GUID/UUID (globally unique identifier). | |
5048 | * | |
5049 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5050 | * @return NULL in the case of an error, or a newly allocated string | |
5051 | * containing the UUID. This string must be freed by OrthancPluginFreeString(). | |
5052 | * @ingroup Toolbox | |
5053 | **/ | |
5054 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGenerateUuid( | |
5055 | OrthancPluginContext* context) | |
5056 | { | |
5057 | char* result; | |
5058 | ||
5059 | _OrthancPluginRetrieveDynamicString params; | |
5060 | params.result = &result; | |
5061 | params.argument = NULL; | |
5062 | ||
5063 | if (context->InvokeService(context, _OrthancPluginService_GenerateUuid, ¶ms) != OrthancPluginErrorCode_Success) | |
5064 | { | |
5065 | /* Error */ | |
5066 | return NULL; | |
5067 | } | |
5068 | else | |
5069 | { | |
5070 | return result; | |
5071 | } | |
5072 | } | |
5073 | ||
5074 | ||
5075 | ||
5076 | ||
5077 | typedef struct | |
5078 | { | |
5079 | OrthancPluginFindCallback callback; | |
5080 | } _OrthancPluginFindCallback; | |
5081 | ||
5082 | /** | |
5083 | * @brief Register a callback to handle C-Find requests. | |
5084 | * | |
5085 | * This function registers a callback to handle C-Find SCP requests | |
5086 | * that are not related to modality worklists. | |
5087 | * | |
5088 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5089 | * @param callback The callback. | |
5090 | * @return 0 if success, other value if error. | |
5091 | * @ingroup DicomCallbacks | |
5092 | **/ | |
5093 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterFindCallback( | |
5094 | OrthancPluginContext* context, | |
5095 | OrthancPluginFindCallback callback) | |
5096 | { | |
5097 | _OrthancPluginFindCallback params; | |
5098 | params.callback = callback; | |
5099 | ||
5100 | return context->InvokeService(context, _OrthancPluginService_RegisterFindCallback, ¶ms); | |
5101 | } | |
5102 | ||
5103 | ||
5104 | typedef struct | |
5105 | { | |
5106 | OrthancPluginFindAnswers *answers; | |
5107 | const OrthancPluginFindQuery *query; | |
5108 | const void *dicom; | |
5109 | uint32_t size; | |
5110 | uint32_t index; | |
5111 | uint32_t *resultUint32; | |
5112 | uint16_t *resultGroup; | |
5113 | uint16_t *resultElement; | |
5114 | char **resultString; | |
5115 | } _OrthancPluginFindOperation; | |
5116 | ||
5117 | /** | |
5118 | * @brief Add one answer to some C-Find request. | |
5119 | * | |
5120 | * This function adds one answer (encoded as a DICOM file) to the | |
5121 | * set of answers corresponding to some C-Find SCP request that is | |
5122 | * not related to modality worklists. | |
5123 | * | |
5124 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5125 | * @param answers The set of answers. | |
5126 | * @param dicom The answer to be added, encoded as a DICOM file. | |
5127 | * @param size The size of the DICOM file. | |
5128 | * @return 0 if success, other value if error. | |
5129 | * @ingroup DicomCallbacks | |
5130 | * @see OrthancPluginCreateDicom() | |
5131 | **/ | |
5132 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginFindAddAnswer( | |
5133 | OrthancPluginContext* context, | |
5134 | OrthancPluginFindAnswers* answers, | |
5135 | const void* dicom, | |
5136 | uint32_t size) | |
5137 | { | |
5138 | _OrthancPluginFindOperation params; | |
5139 | memset(¶ms, 0, sizeof(params)); | |
5140 | params.answers = answers; | |
5141 | params.dicom = dicom; | |
5142 | params.size = size; | |
5143 | ||
5144 | return context->InvokeService(context, _OrthancPluginService_FindAddAnswer, ¶ms); | |
5145 | } | |
5146 | ||
5147 | ||
5148 | /** | |
5149 | * @brief Mark the set of C-Find answers as incomplete. | |
5150 | * | |
5151 | * This function marks as incomplete the set of answers | |
5152 | * corresponding to some C-Find SCP request that is not related to | |
5153 | * modality worklists. This must be used if canceling the handling | |
5154 | * of a request when too many answers are to be returned. | |
5155 | * | |
5156 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5157 | * @param answers The set of answers. | |
5158 | * @return 0 if success, other value if error. | |
5159 | * @ingroup DicomCallbacks | |
5160 | **/ | |
5161 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginFindMarkIncomplete( | |
5162 | OrthancPluginContext* context, | |
5163 | OrthancPluginFindAnswers* answers) | |
5164 | { | |
5165 | _OrthancPluginFindOperation params; | |
5166 | memset(¶ms, 0, sizeof(params)); | |
5167 | params.answers = answers; | |
5168 | ||
5169 | return context->InvokeService(context, _OrthancPluginService_FindMarkIncomplete, ¶ms); | |
5170 | } | |
5171 | ||
5172 | ||
5173 | ||
5174 | /** | |
5175 | * @brief Get the number of tags in a C-Find query. | |
5176 | * | |
5177 | * This function returns the number of tags that are contained in | |
5178 | * the given C-Find query. | |
5179 | * | |
5180 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5181 | * @param query The C-Find query. | |
5182 | * @return The number of tags. | |
5183 | * @ingroup DicomCallbacks | |
5184 | **/ | |
5185 | ORTHANC_PLUGIN_INLINE uint32_t OrthancPluginGetFindQuerySize( | |
5186 | OrthancPluginContext* context, | |
5187 | const OrthancPluginFindQuery* query) | |
5188 | { | |
5189 | uint32_t count = 0; | |
5190 | ||
5191 | _OrthancPluginFindOperation params; | |
5192 | memset(¶ms, 0, sizeof(params)); | |
5193 | params.query = query; | |
5194 | params.resultUint32 = &count; | |
5195 | ||
5196 | if (context->InvokeService(context, _OrthancPluginService_GetFindQuerySize, ¶ms) != OrthancPluginErrorCode_Success) | |
5197 | { | |
5198 | /* Error */ | |
5199 | return 0; | |
5200 | } | |
5201 | else | |
5202 | { | |
5203 | return count; | |
5204 | } | |
5205 | } | |
5206 | ||
5207 | ||
5208 | /** | |
5209 | * @brief Get one tag in a C-Find query. | |
5210 | * | |
5211 | * This function returns the group and the element of one DICOM tag | |
5212 | * in the given C-Find query. | |
5213 | * | |
5214 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5215 | * @param group The group of the tag (output). | |
5216 | * @param element The element of the tag (output). | |
5217 | * @param query The C-Find query. | |
5218 | * @param index The index of the tag of interest. | |
5219 | * @return 0 if success, other value if error. | |
5220 | * @ingroup DicomCallbacks | |
5221 | **/ | |
5222 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginGetFindQueryTag( | |
5223 | OrthancPluginContext* context, | |
5224 | uint16_t* group, | |
5225 | uint16_t* element, | |
5226 | const OrthancPluginFindQuery* query, | |
5227 | uint32_t index) | |
5228 | { | |
5229 | _OrthancPluginFindOperation params; | |
5230 | memset(¶ms, 0, sizeof(params)); | |
5231 | params.query = query; | |
5232 | params.index = index; | |
5233 | params.resultGroup = group; | |
5234 | params.resultElement = element; | |
5235 | ||
5236 | return context->InvokeService(context, _OrthancPluginService_GetFindQueryTag, ¶ms); | |
5237 | } | |
5238 | ||
5239 | ||
5240 | /** | |
5241 | * @brief Get the symbolic name of one tag in a C-Find query. | |
5242 | * | |
5243 | * This function returns the symbolic name of one DICOM tag in the | |
5244 | * given C-Find query. | |
5245 | * | |
5246 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5247 | * @param query The C-Find query. | |
5248 | * @param index The index of the tag of interest. | |
5249 | * @return The NULL value in case of error, or a string containing the name of the tag. | |
5250 | * @return 0 if success, other value if error. | |
5251 | * @ingroup DicomCallbacks | |
5252 | **/ | |
5253 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetFindQueryTagName( | |
5254 | OrthancPluginContext* context, | |
5255 | const OrthancPluginFindQuery* query, | |
5256 | uint32_t index) | |
5257 | { | |
5258 | char* result; | |
5259 | ||
5260 | _OrthancPluginFindOperation params; | |
5261 | memset(¶ms, 0, sizeof(params)); | |
5262 | params.query = query; | |
5263 | params.index = index; | |
5264 | params.resultString = &result; | |
5265 | ||
5266 | if (context->InvokeService(context, _OrthancPluginService_GetFindQueryTagName, ¶ms) != OrthancPluginErrorCode_Success) | |
5267 | { | |
5268 | /* Error */ | |
5269 | return NULL; | |
5270 | } | |
5271 | else | |
5272 | { | |
5273 | return result; | |
5274 | } | |
5275 | } | |
5276 | ||
5277 | ||
5278 | /** | |
5279 | * @brief Get the value associated with one tag in a C-Find query. | |
5280 | * | |
5281 | * This function returns the value associated with one tag in the | |
5282 | * given C-Find query. | |
5283 | * | |
5284 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5285 | * @param query The C-Find query. | |
5286 | * @param index The index of the tag of interest. | |
5287 | * @return The NULL value in case of error, or a string containing the value of the tag. | |
5288 | * @return 0 if success, other value if error. | |
5289 | * @ingroup DicomCallbacks | |
5290 | **/ | |
5291 | ORTHANC_PLUGIN_INLINE char* OrthancPluginGetFindQueryValue( | |
5292 | OrthancPluginContext* context, | |
5293 | const OrthancPluginFindQuery* query, | |
5294 | uint32_t index) | |
5295 | { | |
5296 | char* result; | |
5297 | ||
5298 | _OrthancPluginFindOperation params; | |
5299 | memset(¶ms, 0, sizeof(params)); | |
5300 | params.query = query; | |
5301 | params.index = index; | |
5302 | params.resultString = &result; | |
5303 | ||
5304 | if (context->InvokeService(context, _OrthancPluginService_GetFindQueryValue, ¶ms) != OrthancPluginErrorCode_Success) | |
5305 | { | |
5306 | /* Error */ | |
5307 | return NULL; | |
5308 | } | |
5309 | else | |
5310 | { | |
5311 | return result; | |
5312 | } | |
5313 | } | |
5314 | ||
5315 | ||
5316 | ||
5317 | ||
5318 | typedef struct | |
5319 | { | |
5320 | OrthancPluginMoveCallback callback; | |
5321 | OrthancPluginGetMoveSize getMoveSize; | |
5322 | OrthancPluginApplyMove applyMove; | |
5323 | OrthancPluginFreeMove freeMove; | |
5324 | } _OrthancPluginMoveCallback; | |
5325 | ||
5326 | /** | |
5327 | * @brief Register a callback to handle C-Move requests. | |
5328 | * | |
5329 | * This function registers a callback to handle C-Move SCP requests. | |
5330 | * | |
5331 | * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). | |
5332 | * @param callback The main callback. | |
5333 | * @param getMoveSize Callback to read the number of C-Move suboperations. | |
5334 | * @param applyMove Callback to apply one C-Move suboperations. | |
5335 | * @param freeMove Callback to free the C-Move driver. | |
5336 | * @return 0 if success, other value if error. | |
5337 | * @ingroup DicomCallbacks | |
5338 | **/ | |
5339 | ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterMoveCallback( | |
5340 | OrthancPluginContext* context, | |
5341 | OrthancPluginMoveCallback callback, | |
5342 | OrthancPluginGetMoveSize getMoveSize, | |
5343 | OrthancPluginApplyMove applyMove, | |
5344 | OrthancPluginFreeMove freeMove) | |
5345 | { | |
5346 | _OrthancPluginMoveCallback params; | |
5347 | params.callback = callback; | |
5348 | params.getMoveSize = getMoveSize; | |
5349 | params.applyMove = applyMove; | |
5350 | params.freeMove = freeMove; | |
5351 | ||
5352 | return context->InvokeService(context, _OrthancPluginService_RegisterMoveCallback, ¶ms); | |
5353 | } | |
5354 | ||
5355 | ||
5356 | ||
5357 | ||
5358 | #ifdef __cplusplus | |
5359 | } | |
5360 | #endif | |
5361 | ||
5362 | ||
5363 | /** @} */ | |
5364 |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |
2 | 2 | # Orthanc - A Lightweight, RESTful DICOM Store |
3 | 3 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
4 | 4 | # Department, University Hospital of Liege, Belgium |
5 | # Copyright (C) 2017 Osimis, Belgium | |
5 | # Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 | 6 | # |
7 | 7 | # This program is free software: you can redistribute it and/or |
8 | 8 | # modify it under the terms of the GNU Affero General Public License |
2 | 2 | # Orthanc - A Lightweight, RESTful DICOM Store |
3 | 3 | # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
4 | 4 | # Department, University Hospital of Liege, Belgium |
5 | # Copyright (C) 2017 Osimis, Belgium | |
5 | # Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 | 6 | # |
7 | 7 | # This program is free software: you can redistribute it and/or |
8 | 8 | # modify it under the terms of the GNU Affero General Public License |
8 | 8 | import os |
9 | 9 | import stat |
10 | 10 | import urllib2 |
11 | import uuid | |
12 | 11 | |
13 | TARGET = os.path.join(os.path.dirname(__file__), '..', 'Orthanc') | |
12 | TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc') | |
14 | 13 | PLUGIN_SDK_VERSION = '1.1.0' |
15 | 14 | REPOSITORY = 'https://bitbucket.org/sjodogne/orthanc/raw' |
16 | 15 | |
17 | 16 | FILES = [ |
18 | 'Core/ChunkedBuffer.cpp', | |
19 | 'Core/ChunkedBuffer.h', | |
20 | 'Core/Enumerations.cpp', | |
21 | 'Core/Enumerations.h', | |
22 | 'Core/Logging.h', | |
23 | 'Core/OrthancException.h', | |
24 | 'Core/PrecompiledHeaders.h', | |
25 | 'Core/Toolbox.cpp', | |
26 | 'Core/Toolbox.h', | |
27 | 'Core/SystemToolbox.h', | |
28 | 'Core/SystemToolbox.cpp', | |
29 | 'Core/WebServiceParameters.cpp', | |
30 | 'Core/WebServiceParameters.h', | |
31 | 'Plugins/Samples/Common/ExportedSymbols.list', | |
32 | 'Plugins/Samples/Common/OrthancPluginException.h', | |
33 | 'Plugins/Samples/Common/OrthancPluginCppWrapper.h', | |
34 | 'Plugins/Samples/Common/OrthancPluginCppWrapper.cpp', | |
35 | 'Plugins/Samples/Common/VersionScript.map', | |
36 | 'Resources/CMake/BoostConfiguration.cmake', | |
37 | 'Resources/CMake/Compiler.cmake', | |
38 | 'Resources/CMake/DownloadPackage.cmake', | |
39 | 'Resources/CMake/GoogleTestConfiguration.cmake', | |
40 | 'Resources/CMake/JsonCppConfiguration.cmake', | |
41 | 'Resources/CMake/PugixmlConfiguration.cmake', | |
42 | 'Resources/CMake/ZlibConfiguration.cmake', | |
43 | 'Resources/MinGW-W64-Toolchain32.cmake', | |
44 | 'Resources/MinGW-W64-Toolchain64.cmake', | |
45 | 'Resources/MinGWToolchain.cmake', | |
46 | 'Resources/ThirdParty/VisualStudio/stdint.h', | |
47 | 'Resources/WindowsResources.py', | |
48 | 'Resources/WindowsResources.rc', | |
17 | 'DownloadOrthancFramework.cmake', | |
18 | 'LinuxStandardBaseToolchain.cmake', | |
19 | 'MinGW-W64-Toolchain32.cmake', | |
20 | 'MinGW-W64-Toolchain64.cmake', | |
21 | 'MinGWToolchain.cmake', | |
49 | 22 | ] |
50 | 23 | |
51 | 24 | SDK = [ |
52 | 25 | 'orthanc/OrthancCPlugin.h', |
53 | ] | |
54 | ||
55 | EXE = [ | |
56 | 'Resources/WindowsResources.py', | |
57 | 26 | ] |
58 | ||
59 | ||
60 | 27 | |
61 | 28 | |
62 | 29 | def Download(x): |
70 | 37 | except: |
71 | 38 | pass |
72 | 39 | |
73 | url = '%s/%s/%s?force=%s' % (REPOSITORY, branch, source, uuid.uuid4()) | |
40 | url = '%s/%s/%s' % (REPOSITORY, branch, source) | |
74 | 41 | |
75 | 42 | with open(target, 'w') as f: |
76 | try: | |
77 | f.write(urllib2.urlopen(url).read()) | |
78 | except: | |
79 | print('Cannot download %s' % url) | |
80 | raise | |
43 | f.write(urllib2.urlopen(url).read()) | |
81 | 44 | |
82 | 45 | |
83 | 46 | commands = [] |
84 | 47 | |
85 | 48 | for f in FILES: |
86 | commands.append([ 'default', f, f ]) | |
49 | commands.append([ 'default', | |
50 | os.path.join('Resources', f), | |
51 | f ]) | |
87 | 52 | |
88 | 53 | for f in SDK: |
89 | if PLUGIN_SDK_VERSION == 'mainline': | |
90 | branch = 'default' | |
91 | else: | |
92 | branch = 'Orthanc-%s' % PLUGIN_SDK_VERSION | |
93 | ||
94 | commands.append([ branch, | |
95 | 'Plugins/Include/%s' % f, | |
96 | 'Sdk-%s/%s' % (PLUGIN_SDK_VERSION, f) ]) | |
54 | commands.append([ | |
55 | 'Orthanc-%s' % PLUGIN_SDK_VERSION, | |
56 | 'Plugins/Include/%s' % f, | |
57 | 'Sdk-%s/%s' % (PLUGIN_SDK_VERSION, f) | |
58 | ]) | |
97 | 59 | |
98 | 60 | |
99 | 61 | pool = multiprocessing.Pool(10) # simultaneous downloads |
100 | 62 | pool.map(Download, commands) |
101 | ||
102 | ||
103 | for exe in EXE: | |
104 | path = os.path.join(TARGET, exe) | |
105 | st = os.stat(path) | |
106 | os.chmod(path, st.st_mode | stat.S_IEXEC) |
81 | 81 | |
82 | 82 | |
83 | 83 | |
84 | =========================================== | |
85 | 6.5.8 WADO-RS / RetrieveRenderedTransaction | |
86 | =========================================== | |
87 | ||
88 | Not supported yet. | |
89 | ||
90 | ||
91 | ||
84 | 92 | =========== |
85 | 93 | 6.6 STOW-RS |
86 | 94 | =========== |
1 | 1 | * Orthanc - A Lightweight, RESTful DICOM Store |
2 | 2 | * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
3 | 3 | * Department, University Hospital of Liege, Belgium |
4 | * Copyright (C) 2017 Osimis, Belgium | |
4 | * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
5 | 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or |
7 | 7 | * modify it under the terms of the GNU Affero General Public License |