Codebase list orthanc-dicomweb / 8a12324
New upstream version 0.5+dfsg jodogne-guest 6 years ago
73 changed file(s) with 6157 addition(s) and 13753 deletion(s). Raw diff Collapse all Expand all
00 repo: d5f45924411123cfd02d035fd50b8e37536eadef
1 node: f58f8d749b95d85a792e786a0256d0cc2278cc4d
2 branch: OrthancDicomWeb-0.4
1 node: b5f71018159133105d5cc1eb60d852a385bab998
2 branch: OrthancDicomWeb-0.5
33 latesttag: null
4 latesttagdistance: 179
5 changessincelatesttag: 189
4 latesttagdistance: 210
5 changessincelatesttag: 221
1313 4000 Liege
1414 Belgium
1515
16 * Osimis <info@osimis.io>
16 * Osimis S.A. <info@osimis.io>
1717 Rue des Chasseurs Ardennais 3
1818 4031 Liege
1919 Belgium
00 # Orthanc - A Lightweight, RESTful DICOM Store
11 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
22 # Department, University Hospital of Liege, Belgium
3 # Copyright (C) 2017 Osimis, Belgium
3 # Copyright (C) 2017-2018 Osimis S.A., Belgium
44 #
55 # This program is free software: you can redistribute it and/or
66 # modify it under the terms of the GNU Affero General Public License
2020
2121 project(OrthancDicomWeb)
2222
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()
2432
2533
2634 # Parameters of the build
2735 set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
2836 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\"")
2940
3041 # Advanced parameters to fine-tune linking against system libraries
31 set(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost")
3242 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")
3743 set(USE_SYSTEM_ORTHANC_SDK ON CACHE BOOL "Use the system version of the Orthanc plugin SDK")
3844
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)
4245
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)
5246
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
5861
5962 include(${CMAKE_SOURCE_DIR}/Resources/CMake/GdcmConfiguration.cmake)
6063
6164
6265 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)
6467 else ()
6568 CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCPlugin.h HAVE_ORTHANC_H)
6669 if (NOT HAVE_ORTHANC_H)
99102 endif()
100103
101104
105 include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h"
106
102107 add_definitions(
103 -DORTHANC_ENABLE_MD5=0
104 -DORTHANC_ENABLE_BASE64=0
105 -DORTHANC_ENABLE_LOGGING=0
106 -DORTHANC_SANDBOXED=0
107108 -DHAS_ORTHANC_EXCEPTION=1
108109 )
109110
110 include_directories(${ORTHANC_ROOT}/Core) # To access "OrthancException.h"
111
112111 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
125112 Plugin/Configuration.cpp
126113 Plugin/Dicom.cpp
127114 Plugin/DicomResults.cpp
115
116 ${ORTHANC_ROOT}/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
117 ${ORTHANC_CORE_SOURCES}
128118 )
129119
130120 add_library(OrthancDicomWeb SHARED ${CORE_SOURCES}
158148
159149 add_executable(UnitTests
160150 ${CORE_SOURCES}
161 ${GTEST_SOURCES}
151 ${GOOGLE_TEST_SOURCES}
162152 ${CMAKE_SOURCE_DIR}/Plugin/DicomWebServers.cpp
163153 UnitTestsSources/UnitTestsMain.cpp
164154 )
165155
166 target_link_libraries(UnitTests ${GDCM_LIBRARIES})
156 target_link_libraries(UnitTests
157 ${GDCM_LIBRARIES}
158 ${GOOGLE_TEST_LIBRARIES}
159 )
167160
168161 if (STATIC_BUILD OR NOT USE_SYSTEM_GDCM)
169162 add_dependencies(OrthancDicomWeb GDCM)
00 Pending changes in the mainline
11 ===============================
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
216
317
418 Version 0.4 (2017-07-19)
+0
-103
Orthanc/Core/ChunkedBuffer.cpp less more
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
-72
Orthanc/Core/ChunkedBuffer.h less more
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
-1479
Orthanc/Core/Enumerations.cpp less more
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
-547
Orthanc/Core/Enumerations.h less more
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
-178
Orthanc/Core/Logging.h less more
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
-77
Orthanc/Core/OrthancException.h less more
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
-61
Orthanc/Core/PrecompiledHeaders.h less more
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
-552
Orthanc/Core/SystemToolbox.cpp less more
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
-105
Orthanc/Core/SystemToolbox.h less more
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
-1254
Orthanc/Core/Toolbox.cpp less more
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
-210
Orthanc/Core/Toolbox.h less more
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
-273
Orthanc/Core/WebServiceParameters.cpp less more
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
-131
Orthanc/Core/WebServiceParameters.h less more
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
-7
Orthanc/Plugins/Samples/Common/ExportedSymbols.list less more
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
-1222
Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp less more
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
-524
Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h less more
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
-101
Orthanc/Plugins/Samples/Common/OrthancPluginException.h less more
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
-12
Orthanc/Plugins/Samples/Common/VersionScript.map less more
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
-238
Orthanc/Resources/CMake/BoostConfiguration.cmake less more
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
-188
Orthanc/Resources/CMake/Compiler.cmake less more
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
-172
Orthanc/Resources/CMake/DownloadPackage.cmake less more
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
-58
Orthanc/Resources/CMake/GoogleTestConfiguration.cmake less more
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
-60
Orthanc/Resources/CMake/JsonCppConfiguration.cmake less more
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
-33
Orthanc/Resources/CMake/PugixmlConfiguration.cmake less more
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
-36
Orthanc/Resources/CMake/ZlibConfiguration.cmake less more
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
-17
Orthanc/Resources/MinGW-W64-Toolchain32.cmake less more
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
-17
Orthanc/Resources/MinGW-W64-Toolchain64.cmake less more
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
-17
Orthanc/Resources/MinGWToolchain.cmake less more
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
-259
Orthanc/Resources/ThirdParty/VisualStudio/stdint.h less more
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
-90
Orthanc/Resources/WindowsResources.py less more
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
-30
Orthanc/Resources/WindowsResources.rc less more
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
-5365
Orthanc/Sdk-1.1.0/orthanc/OrthancCPlugin.h less more
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params) != 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, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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(&params, 0, sizeof(params));
2186 params.resultString = &result;
2187 params.instance = instance;
2188
2189 if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, &params) != 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(&params, 0, sizeof(params));
2219 params.resultInt64 = &size;
2220 params.instance = instance;
2221
2222 if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, &params) != 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(&params, 0, sizeof(params));
2252 params.resultString = &result;
2253 params.instance = instance;
2254
2255 if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, &params) != 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(&params, 0, sizeof(params));
2288 params.resultStringToFree = &result;
2289 params.instance = instance;
2290
2291 if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, &params) != 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(&params, 0, sizeof(params));
2326 params.resultStringToFree = &result;
2327 params.instance = instance;
2328
2329 if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, &params) != 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(&params, 0, sizeof(params));
2366 params.resultInt64 = &result;
2367 params.instance = instance;
2368 params.key = metadata;
2369
2370 if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, &params) != 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(&params, 0, sizeof(params));
2404 params.resultString = &result;
2405 params.instance = instance;
2406 params.key = metadata;
2407
2408 if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, &params) != 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, &params);
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, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
2768 params.resultUint32 = &count;
2769
2770 if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, &params) != 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, &params) != 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(&params, 0, sizeof(params));
2835 params.resultUint32 = &count;
2836
2837 if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
3169 params.image = image;
3170 params.resultPixelFormat = &target;
3171
3172 if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, &params) != 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(&params, 0, sizeof(params));
3202 params.image = image;
3203 params.resultUint32 = &width;
3204
3205 if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, &params) != 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(&params, 0, sizeof(params));
3235 params.image = image;
3236 params.resultUint32 = &height;
3237
3238 if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, &params) != 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(&params, 0, sizeof(params));
3270 params.image = image;
3271 params.resultUint32 = &pitch;
3272
3273 if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, &params) != 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(&params, 0, sizeof(params));
3304 params.resultBuffer = &target;
3305 params.image = image;
3306
3307 if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, &params) != 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(&params, 0, sizeof(params));
3349 params.target = &target;
3350 params.data = data;
3351 params.size = size;
3352 params.format = format;
3353
3354 if (context->InvokeService(context, _OrthancPluginService_UncompressImage, &params) != 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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 = &target;
3732 params.source = source;
3733 params.targetFormat = targetFormat;
3734
3735 if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, &params) != 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(&params, 0, sizeof(params));
3765 params.resultUint32 = &count;
3766
3767 if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, &params) != 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(&params, 0, sizeof(params));
3806 params.name = &result;
3807 params.fontIndex = fontIndex;
3808
3809 if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != 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(&params, 0, sizeof(params));
3838 params.size = &result;
3839 params.fontIndex = fontIndex;
3840
3841 if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != 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(&params, 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, &params);
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, &params);
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, &params);
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, &params);
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 = &target;
4063 params.code = code;
4064 params.httpStatus = httpStatus;
4065 params.message = message;
4066
4067 if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, &params) == 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, &params);
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, &params);
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(&params, 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, &params) != 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(&params, 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params) == 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, &params);
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(&params, 0, sizeof(params));
4519 params.resultOrigin = &origin;
4520 params.instance = instance;
4521
4522 if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, &params) != 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, &params);
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, &params);
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(&params, 0, sizeof(params));
4641 params.target = &target;
4642 params.format = format;
4643 params.width = width;
4644 params.height = height;
4645
4646 if (context->InvokeService(context, _OrthancPluginService_CreateImage, &params) != 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(&params, 0, sizeof(params));
4686 params.target = &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, &params) != 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(&params, 0, sizeof(params));
4729 params.target = &target;
4730 params.constBuffer = buffer;
4731 params.bufferSize = bufferSize;
4732 params.frameIndex = frameIndex;
4733
4734 if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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(&params, 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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
5140 params.answers = answers;
5141 params.dicom = dicom;
5142 params.size = size;
5143
5144 return context->InvokeService(context, _OrthancPluginService_FindAddAnswer, &params);
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(&params, 0, sizeof(params));
5167 params.answers = answers;
5168
5169 return context->InvokeService(context, _OrthancPluginService_FindMarkIncomplete, &params);
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(&params, 0, sizeof(params));
5193 params.query = query;
5194 params.resultUint32 = &count;
5195
5196 if (context->InvokeService(context, _OrthancPluginService_GetFindQuerySize, &params) != 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(&params, 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, &params);
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(&params, 0, sizeof(params));
5262 params.query = query;
5263 params.index = index;
5264 params.resultString = &result;
5265
5266 if (context->InvokeService(context, _OrthancPluginService_GetFindQueryTagName, &params) != 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(&params, 0, sizeof(params));
5300 params.query = query;
5301 params.index = index;
5302 params.resultString = &result;
5303
5304 if (context->InvokeService(context, _OrthancPluginService_GetFindQueryValue, &params) != 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, &params);
5353 }
5354
5355
5356
5357
5358 #ifdef __cplusplus
5359 }
5360 #endif
5361
5362
5363 /** @} */
5364
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2727
2828 #include "Plugin.h"
2929 #include "DicomWebServers.h"
30 #include "../Orthanc/Core/Toolbox.h"
30
31 #include <Core/Toolbox.h>
3132
3233 namespace OrthancPlugins
3334 {
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2020
2121 #pragma once
2222
23 #include "../Orthanc/Core/Enumerations.h"
23 #include <Core/Enumerations.h>
2424
2525 #include <orthanc/OrthancCPlugin.h>
2626 #include <json/value.h>
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2323 #include "Plugin.h"
2424 #include "ChunkedBuffer.h"
2525
26 #include "../Orthanc/Core/Toolbox.h"
26 #include <Core/Toolbox.h>
2727
2828 #include <gdcmDictEntry.h>
2929 #include <gdcmStringFilter.h>
116116 }
117117
118118
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
119146 static bool ConvertDicomStringToUtf8(std::string& result,
120147 const gdcm::Dict& dictionary,
121 const gdcm::File* file,
122148 const gdcm::DataElement& element,
123149 const Orthanc::Encoding sourceEncoding)
124150 {
128154 return false;
129155 }
130156
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);
147190 return true;
148191 }
149192 }
258301
259302 const gdcm::DataElement& element = GetDataSet().GetDataElement(tag);
260303
261 if (!ConvertDicomStringToUtf8(result, dictionary, &GetFile(), element, GetEncoding()))
304 if (!ConvertDicomStringToUtf8(result, dictionary, element, GetEncoding()))
262305 {
263306 return false;
264307 }
407450
408451 static void DicomToXmlInternal(pugi::xml_node& target,
409452 const gdcm::Dict& dictionary,
410 const gdcm::File* file,
411453 const gdcm::DataSet& dicom,
412454 const Orthanc::Encoding sourceEncoding,
413455 const std::string& bulkUri)
458500 childUri = bulkUri + std::string(path) + "/" + number + "/";
459501 }
460502
461 DicomToXmlInternal(item, dictionary, file, seq->GetItem(i).GetNestedDataSet(), sourceEncoding, childUri);
503 DicomToXmlInternal(item, dictionary, seq->GetItem(i).GetNestedDataSet(), sourceEncoding, childUri);
462504 }
463505 }
464506 }
479521 value.append_attribute("number").set_value("1");
480522
481523 std::string tmp;
482 if (ConvertDicomStringToUtf8(tmp, dictionary, file, *it, sourceEncoding))
524 if (ConvertDicomStringToUtf8(tmp, dictionary, *it, sourceEncoding))
483525 {
484526 value.append_child(pugi::node_pcdata).set_value(tmp.c_str());
485527 }
494536
495537 static void DicomToXml(pugi::xml_document& target,
496538 const gdcm::Dict& dictionary,
497 const gdcm::File* file,
498539 const gdcm::DataSet& dicom,
499540 const std::string& bulkUriRoot)
500541 {
504545 root.append_attribute("xmlns:xsi").set_value("http://www.w3.org/2001/XMLSchema-instance");
505546
506547 Orthanc::Encoding encoding = DetectEncoding(dicom);
507 DicomToXmlInternal(root, dictionary, file, dicom, encoding, bulkUriRoot);
548 DicomToXmlInternal(root, dictionary, dicom, encoding, bulkUriRoot);
508549
509550 pugi::xml_node decl = target.prepend_child(pugi::node_declaration);
510551 decl.append_attribute("version").set_value("1.0");
514555
515556 static void DicomToJsonInternal(Json::Value& target,
516557 const gdcm::Dict& dictionary,
517 const gdcm::File* file,
518558 const gdcm::DataSet& dicom,
519559 const std::string& bulkUri,
520560 Orthanc::Encoding sourceEncoding)
563603 childUri = bulkUri + std::string(path) + "/" + number + "/";
564604 }
565605
566 DicomToJsonInternal(child, dictionary, file, seq->GetItem(i).GetNestedDataSet(), childUri, sourceEncoding);
606 DicomToJsonInternal(child, dictionary, seq->GetItem(i).GetNestedDataSet(), childUri, sourceEncoding);
567607 node["Value"].append(child);
568608 }
569609 }
585625 node["Value"] = Json::arrayValue;
586626
587627 std::string value;
588 if (ConvertDicomStringToUtf8(value, dictionary, file, *it, sourceEncoding))
628 if (ConvertDicomStringToUtf8(value, dictionary, *it, sourceEncoding))
589629 {
590630 node["Value"].append(value.c_str());
591631 }
607647
608648 static void DicomToJson(Json::Value& target,
609649 const gdcm::Dict& dictionary,
610 const gdcm::File* file,
611650 const gdcm::DataSet& dicom,
612651 const std::string& bulkUriRoot)
613652 {
614653 Orthanc::Encoding encoding = DetectEncoding(dicom);
615 DicomToJsonInternal(target, dictionary, file, dicom, bulkUriRoot, encoding);
654 DicomToJsonInternal(target, dictionary, dicom, bulkUriRoot, encoding);
616655 }
617656
618657
619658 void GenerateSingleDicomAnswer(std::string& result,
620659 const std::string& wadoBase,
621660 const gdcm::Dict& dictionary,
622 const gdcm::File* file, // Can be NULL
623661 const gdcm::DataSet& dicom,
624662 bool isXml,
625663 bool isBulkAccessible)
633671 if (isXml)
634672 {
635673 pugi::xml_document doc;
636 DicomToXml(doc, dictionary, file, dicom, bulkUriRoot);
674 DicomToXml(doc, dictionary, dicom, bulkUriRoot);
637675
638676 ChunkedBufferWriter writer;
639677 doc.save(writer, " ", pugi::format_default, pugi::encoding_utf8);
643681 else
644682 {
645683 Json::Value v;
646 DicomToJson(v, dictionary, file, dicom, bulkUriRoot);
684 DicomToJson(v, dictionary, dicom, bulkUriRoot);
647685
648686 Json::FastWriter writer;
649687 result = writer.write(v);
660698 bool isBulkAccessible)
661699 {
662700 std::string answer;
663 GenerateSingleDicomAnswer(answer, wadoBase, dictionary, NULL, dicom, isXml, isBulkAccessible);
701 GenerateSingleDicomAnswer(answer, wadoBase, dictionary, dicom, isXml, isBulkAccessible);
664702 OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(),
665 isXml ? "application/dicom+xml" : "application/json");
703 isXml ? "application/dicom+xml" : "application/dicom+json");
666704 }
667705
668706
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2222
2323 #include "Configuration.h"
2424
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>
2828
2929 #include <gdcmReader.h>
3030 #include <gdcmDataSet.h>
6262 void Setup(const std::string& dicom);
6363
6464 public:
65 ParsedDicomFile(const OrthancPlugins::MultipartItem& item);
65 explicit ParsedDicomFile(const OrthancPlugins::MultipartItem& item);
6666
67 ParsedDicomFile(const OrthancPlugins::MemoryBuffer& item);
67 explicit ParsedDicomFile(const OrthancPlugins::MemoryBuffer& item);
6868
69 ParsedDicomFile(const std::string& dicom)
69 explicit ParsedDicomFile(const std::string& dicom)
7070 {
7171 Setup(dicom);
7272 }
111111 void GenerateSingleDicomAnswer(std::string& result,
112112 const std::string& wadoBase,
113113 const gdcm::Dict& dictionary,
114 const gdcm::File* file, // Can be NULL
115114 const gdcm::DataSet& dicom,
116115 bool isXml,
117116 bool isBulkAccessible);
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2121 #include "DicomResults.h"
2222
2323 #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>
2627
2728 #include <boost/lexical_cast.hpp>
2829 #include <boost/noncopyable.hpp>
7879 }
7980
8081
81 void DicomResults::AddInternal(const gdcm::File* file,
82 const gdcm::DataSet& dicom)
82 void DicomResults::AddInternal(const gdcm::DataSet& dicom)
8383 {
8484 std::string item;
8585
8686 if (isXml_)
8787 {
88 GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, file, dicom, true, isBulkAccessible_);
88 GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, dicom, true, isBulkAccessible_);
8989 }
9090 else
9191 {
92 GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, file, dicom, false, isBulkAccessible_);
92 GenerateSingleDicomAnswer(item, wadoBase_, dictionary_, dicom, false, isBulkAccessible_);
9393 }
9494
9595 AddInternal(item);
419419
420420 std::string answer;
421421 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");
423423 }
424424 }
425425 }
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
4444
4545 void AddInternal(const std::string& item);
4646
47 void AddInternal(const gdcm::File* file,
48 const gdcm::DataSet& dicom);
47 void AddInternal(const gdcm::DataSet& dicom);
4948
5049 public:
5150 DicomResults(OrthancPluginContext* context,
5756
5857 void Add(const gdcm::File& file)
5958 {
60 AddInternal(&file, file.GetDataSet());
59 AddInternal(file.GetDataSet());
6160 }
6261
63 void Add(const gdcm::File& file,
64 const gdcm::DataSet& subset)
62 void Add(const gdcm::DataSet& subset)
6563 {
66 AddInternal(&file, subset);
64 AddInternal(subset);
6765 }
6866
6967 void AddFromOrthanc(const Json::Value& dicom,
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2828 #include <set>
2929 #include <boost/lexical_cast.hpp>
3030
31 #include "../Orthanc/Core/ChunkedBuffer.h"
32 #include "../Orthanc/Core/Toolbox.h"
31 #include <Core/ChunkedBuffer.h>
32 #include <Core/Toolbox.h>
3333
3434
3535 static void AddInstance(std::list<std::string>& target,
284284
285285 std::map<std::string, std::string> queryArguments;
286286 std::map<std::string, std::string> httpHeaders;
287 httpHeaders["Accept"] = "application/json";
287 httpHeaders["Accept"] = "application/dicom+json";
288288 httpHeaders["Expect"] = "";
289289 httpHeaders["Content-Type"] = mime;
290290
297297 Orthanc::ChunkedBuffer chunks;
298298 size_t countInstances = 0;
299299
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)
301301 {
302302 OrthancPlugins::MemoryBuffer dicom(context);
303303 if (dicom.RestApiGet("/instances/" + *it + "/file", false))
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2121 #include "DicomWebServers.h"
2222
2323 #include "Configuration.h"
24 #include "../Orthanc/Core/Toolbox.h"
24
25 #include <Core/Toolbox.h>
2526
2627 namespace OrthancPlugins
2728 {
142143 assert(!url.empty() && url[url.size() - 1] == '/');
143144
144145 // Remove the leading "/" in the URI if need be
145 std::string tmp;
146146 if (!uri.empty() &&
147147 uri[0] == '/')
148148 {
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
1919
2020 #pragma once
2121
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>
2424
2525 #include <list>
2626 #include <string>
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2828 #include "Configuration.h"
2929 #include "DicomWebServers.h"
3030
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>
3333
3434 #include <gdcmDictEntry.h>
3535 #include <gdcmDict.h>
8686 }
8787 }
8888
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
8999
90100 void ListServers(OrthancPluginRestOutput* output,
91101 const char* url,
102112 std::list<std::string> servers;
103113 OrthancPlugins::DicomWebServers::GetInstance().ListServers(servers);
104114
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 }
116147
117148 void ListServerOperations(OrthancPluginRestOutput* output,
118149 const char* /*url*/,
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2020
2121 #pragma once
2222
23 #include "../Orthanc/Plugins/Samples/Common/OrthancPluginCppWrapper.h"
23 #include <Plugins/Samples/Common/OrthancPluginCppWrapper.h>
2424
2525 #include <gdcmDict.h>
2626
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2525 #include "Dicom.h"
2626 #include "DicomResults.h"
2727 #include "Configuration.h"
28 #include "../Orthanc/Core/Toolbox.h"
28
29 #include <Core/Toolbox.h>
2930
3031 #include <gdcmTag.h>
3132 #include <list>
156157
157158
158159 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)
164165 {
165166 std::string args;
166167
196197 }
197198 else if (key == "includefield")
198199 {
199 if (key == "all")
200 if (value == "all")
200201 {
201202 includeAllFields_ = true;
202203 }
269270 }
270271
271272 result["Expand"] = false;
272 result["CaseSensitive"] = true;
273 result["CaseSensitive"] = OrthancPlugins::Configuration::GetBooleanValue("QidoCaseSensitive", true);
273274 result["Query"] = Json::objectValue;
274275 result["Limit"] = limit_;
275276 result["Since"] = offset_;
276277
277278 if (offset_ != 0 &&
278279 !OrthancPlugins::CheckMinimalOrthancVersion(
279 OrthancPlugins::Configuration::GetContext(), 1, 2, 1))
280 OrthancPlugins::Configuration::GetContext(), 1, 3, 0))
280281 {
281282 OrthancPlugins::Configuration::LogError(
282283 "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");
284285 }
285286
286287 for (Filters::const_iterator it = filters_.begin();
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2323
2424 #include "Configuration.h"
2525 #include "Dicom.h"
26 #include "../Orthanc/Core/Toolbox.h"
26
27 #include <Core/Toolbox.h>
2728
2829 #include <stdexcept>
2930
6061
6162 if (!OrthancPlugins::LookupHttpHeader(accept, request, "accept"))
6263 {
63 return true; // By default, return XML Native DICOM Model
64 return false; // By default, return DICOM+JSON
6465 }
6566
6667 Orthanc::Toolbox::ToLowerCase(accept);
67 if (accept == "application/json")
68 if (accept == "application/dicom+json" ||
69 accept == "application/json" ||
70 accept == "*/*")
6871 {
6972 return false;
7073 }
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 }
8186 }
8287
8388
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2323 #include "Configuration.h"
2424 #include "Dicom.h"
2525 #include "DicomResults.h"
26 #include "../Orthanc/Core/Toolbox.h"
26
27 #include <Core/Toolbox.h>
2728
2829 #include <memory>
2930
7475 static bool AcceptMetadata(const OrthancPluginHttpRequest* request,
7576 bool& isXml)
7677 {
77 isXml = true;
78 isXml = false; // By default, return application/dicom+json
7879
7980 std::string accept;
80
8181 if (!OrthancPlugins::LookupHttpHeader(accept, request, "accept"))
8282 {
83 // By default, return "multipart/related; type=application/dicom+xml;"
8483 return true;
8584 }
8685
8887 std::map<std::string, std::string> attributes;
8988 OrthancPlugins::ParseContentType(application, attributes, accept);
9089
91 if (application == "application/json")
92 {
93 isXml = false;
90 if (application == "application/json" ||
91 application == "application/dicom+json" ||
92 application == "*/*")
93 {
9494 return true;
9595 }
9696
97 if (application != "multipart/related" &&
98 application != "*/*")
97 if (application != "multipart/related")
9998 {
10099 OrthancPlugins::Configuration::LogError("This WADO-RS plugin cannot generate the following content type: " + accept);
101100 return false;
105104 {
106105 std::string s = attributes["type"];
107106 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 + ")");
112115 return false;
113116 }
117 }
118 else
119 {
120 OrthancPlugins::Configuration::LogError("Missing \"type\" in multipart/related accept type (" + accept + ")");
121 return false;
114122 }
115123
116124 if (attributes.find("transfer-syntax") != attributes.end())
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
2020
2121 #include "WadoRs.h"
2222
23 #include "../Orthanc/Core/Toolbox.h"
2423 #include "Dicom.h"
2524 #include "Plugin.h"
25
26 #include <Core/Toolbox.h>
2627
2728 #include <memory>
2829 #include <list>
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
22
33 # mkdir Build
44 # cd Build
5 # cmake .. -DCMAKE_BUILD_TYPE=Debug -DALLOW_DOWNLOADS=ON -DSTATIC_BUILD=ON
5 # cmake .. -DCMAKE_BUILD_TYPE=Debug -DSTATIC_BUILD=ON
66 # make
77
88
1111
1212 # mkdir Build
1313 # 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
1515 # make
1616
1717
2424 -DALLOW_DOWNLOADS=ON \
2525 -DUSE_SYSTEM_JSONCPP=OFF \
2626 -DUSE_SYSTEM_PUGIXML=OFF \
27 -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON
27 -DUSE_GOOGLE_TEST_DEBIAN_SOURCE_PACKAGE=ON
2828 # make
2929
3030
00 # Orthanc - A Lightweight, RESTful DICOM Store
11 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
22 # Department, University Hospital of Liege, Belgium
3 # Copyright (C) 2017 Osimis, Belgium
3 # Copyright (C) 2017-2018 Osimis S.A., Belgium
44 #
55 # This program is free software: you can redistribute it and/or
66 # modify it under the terms of the GNU Affero General Public License
1717
1818
1919 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
2220 if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
2321 ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
2422 ${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
2525 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")
2630 endif()
2731
2832 set(Flags
3943 )
4044
4145 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)
4373 endif()
4474
4575 include(ExternalProject)
4676 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"
4979 TIMEOUT 60
5080 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 (*)
5282 INSTALL_COMMAND "" # Skip the install step
5383 )
5484
6090 list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix)
6191 endif()
6292
63 set(GDCM_LIBRARIES
93 set(GDCM_LIBRARIES
94 # WARNING: The order of the libraries below *is* important!
6495 ${Prefix}gdcmMSFF${Suffix}
6596 ${Prefix}gdcmcharls${Suffix}
6697 ${Prefix}gdcmDICT${Suffix}
69100 ${Prefix}gdcmjpeg8${Suffix}
70101 ${Prefix}gdcmjpeg12${Suffix}
71102 ${Prefix}gdcmjpeg16${Suffix}
72 ${Prefix}gdcmMEXD${Suffix}
73 ${Prefix}gdcmopenjpeg${Suffix}
103 ${Prefix}gdcmopenjp2${Suffix}
74104 ${Prefix}gdcmzlib${Suffix}
75 ${Prefix}socketxx${Suffix}
76105 ${Prefix}gdcmCommon${Suffix}
77106 ${Prefix}gdcmexpat${Suffix}
78107
108 #${Prefix}socketxx${Suffix}
109 #${Prefix}gdcmMEXD${Suffix} # DICOM Networking, unneeded by Orthanc plugins
79110 #${Prefix}gdcmgetopt${Suffix}
80111 )
81112
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params) != 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, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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(&params, 0, sizeof(params));
2186 params.resultString = &result;
2187 params.instance = instance;
2188
2189 if (context->InvokeService(context, _OrthancPluginService_GetInstanceRemoteAet, &params) != 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(&params, 0, sizeof(params));
2219 params.resultInt64 = &size;
2220 params.instance = instance;
2221
2222 if (context->InvokeService(context, _OrthancPluginService_GetInstanceSize, &params) != 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(&params, 0, sizeof(params));
2252 params.resultString = &result;
2253 params.instance = instance;
2254
2255 if (context->InvokeService(context, _OrthancPluginService_GetInstanceData, &params) != 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(&params, 0, sizeof(params));
2288 params.resultStringToFree = &result;
2289 params.instance = instance;
2290
2291 if (context->InvokeService(context, _OrthancPluginService_GetInstanceJson, &params) != 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(&params, 0, sizeof(params));
2326 params.resultStringToFree = &result;
2327 params.instance = instance;
2328
2329 if (context->InvokeService(context, _OrthancPluginService_GetInstanceSimplifiedJson, &params) != 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(&params, 0, sizeof(params));
2366 params.resultInt64 = &result;
2367 params.instance = instance;
2368 params.key = metadata;
2369
2370 if (context->InvokeService(context, _OrthancPluginService_HasInstanceMetadata, &params) != 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(&params, 0, sizeof(params));
2404 params.resultString = &result;
2405 params.instance = instance;
2406 params.key = metadata;
2407
2408 if (context->InvokeService(context, _OrthancPluginService_GetInstanceMetadata, &params) != 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, &params);
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, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
2768 params.resultUint32 = &count;
2769
2770 if (context->InvokeService(context, _OrthancPluginService_GetCommandLineArgumentsCount, &params) != 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, &params) != 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(&params, 0, sizeof(params));
2835 params.resultUint32 = &count;
2836
2837 if (context->InvokeService(context, _OrthancPluginService_GetExpectedDatabaseVersion, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
3169 params.image = image;
3170 params.resultPixelFormat = &target;
3171
3172 if (context->InvokeService(context, _OrthancPluginService_GetImagePixelFormat, &params) != 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(&params, 0, sizeof(params));
3202 params.image = image;
3203 params.resultUint32 = &width;
3204
3205 if (context->InvokeService(context, _OrthancPluginService_GetImageWidth, &params) != 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(&params, 0, sizeof(params));
3235 params.image = image;
3236 params.resultUint32 = &height;
3237
3238 if (context->InvokeService(context, _OrthancPluginService_GetImageHeight, &params) != 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(&params, 0, sizeof(params));
3270 params.image = image;
3271 params.resultUint32 = &pitch;
3272
3273 if (context->InvokeService(context, _OrthancPluginService_GetImagePitch, &params) != 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(&params, 0, sizeof(params));
3304 params.resultBuffer = &target;
3305 params.image = image;
3306
3307 if (context->InvokeService(context, _OrthancPluginService_GetImageBuffer, &params) != 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(&params, 0, sizeof(params));
3349 params.target = &target;
3350 params.data = data;
3351 params.size = size;
3352 params.format = format;
3353
3354 if (context->InvokeService(context, _OrthancPluginService_UncompressImage, &params) != 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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(&params, 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, &params);
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 = &target;
3732 params.source = source;
3733 params.targetFormat = targetFormat;
3734
3735 if (context->InvokeService(context, _OrthancPluginService_ConvertPixelFormat, &params) != 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(&params, 0, sizeof(params));
3765 params.resultUint32 = &count;
3766
3767 if (context->InvokeService(context, _OrthancPluginService_GetFontsCount, &params) != 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(&params, 0, sizeof(params));
3806 params.name = &result;
3807 params.fontIndex = fontIndex;
3808
3809 if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != 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(&params, 0, sizeof(params));
3838 params.size = &result;
3839 params.fontIndex = fontIndex;
3840
3841 if (context->InvokeService(context, _OrthancPluginService_GetFontInfo, &params) != 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(&params, 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, &params);
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, &params);
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, &params);
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, &params);
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 = &target;
4063 params.code = code;
4064 params.httpStatus = httpStatus;
4065 params.message = message;
4066
4067 if (context->InvokeService(context, _OrthancPluginService_RegisterErrorCode, &params) == 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, &params);
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, &params);
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(&params, 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, &params) != 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(&params, 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, &params) != 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, &params);
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, &params);
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, &params);
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, &params);
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, &params) == 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, &params);
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(&params, 0, sizeof(params));
4519 params.resultOrigin = &origin;
4520 params.instance = instance;
4521
4522 if (context->InvokeService(context, _OrthancPluginService_GetInstanceOrigin, &params) != 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, &params);
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, &params);
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(&params, 0, sizeof(params));
4641 params.target = &target;
4642 params.format = format;
4643 params.width = width;
4644 params.height = height;
4645
4646 if (context->InvokeService(context, _OrthancPluginService_CreateImage, &params) != 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(&params, 0, sizeof(params));
4686 params.target = &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, &params) != 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(&params, 0, sizeof(params));
4729 params.target = &target;
4730 params.constBuffer = buffer;
4731 params.bufferSize = bufferSize;
4732 params.frameIndex = frameIndex;
4733
4734 if (context->InvokeService(context, _OrthancPluginService_DecodeDicomImage, &params) != 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, &params) != 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, &params) != 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, &params);
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, &params);
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, &params);
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(&params, 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, &params);
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, &params) != 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, &params);
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(&params, 0, sizeof(params));
5140 params.answers = answers;
5141 params.dicom = dicom;
5142 params.size = size;
5143
5144 return context->InvokeService(context, _OrthancPluginService_FindAddAnswer, &params);
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(&params, 0, sizeof(params));
5167 params.answers = answers;
5168
5169 return context->InvokeService(context, _OrthancPluginService_FindMarkIncomplete, &params);
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(&params, 0, sizeof(params));
5193 params.query = query;
5194 params.resultUint32 = &count;
5195
5196 if (context->InvokeService(context, _OrthancPluginService_GetFindQuerySize, &params) != 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(&params, 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, &params);
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(&params, 0, sizeof(params));
5262 params.query = query;
5263 params.index = index;
5264 params.resultString = &result;
5265
5266 if (context->InvokeService(context, _OrthancPluginService_GetFindQueryTagName, &params) != 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(&params, 0, sizeof(params));
5300 params.query = query;
5301 params.index = index;
5302 params.resultString = &result;
5303
5304 if (context->InvokeService(context, _OrthancPluginService_GetFindQueryValue, &params) != 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, &params);
5353 }
5354
5355
5356
5357
5358 #ifdef __cplusplus
5359 }
5360 #endif
5361
5362
5363 /** @} */
5364
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License
22 # Orthanc - A Lightweight, RESTful DICOM Store
33 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
44 # Department, University Hospital of Liege, Belgium
5 # Copyright (C) 2017 Osimis, Belgium
5 # Copyright (C) 2017-2018 Osimis S.A., Belgium
66 #
77 # This program is free software: you can redistribute it and/or
88 # modify it under the terms of the GNU Affero General Public License
22 # Orthanc - A Lightweight, RESTful DICOM Store
33 # Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
44 # Department, University Hospital of Liege, Belgium
5 # Copyright (C) 2017 Osimis, Belgium
5 # Copyright (C) 2017-2018 Osimis S.A., Belgium
66 #
77 # This program is free software: you can redistribute it and/or
88 # modify it under the terms of the GNU Affero General Public License
88 import os
99 import stat
1010 import urllib2
11 import uuid
1211
13 TARGET = os.path.join(os.path.dirname(__file__), '..', 'Orthanc')
12 TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc')
1413 PLUGIN_SDK_VERSION = '1.1.0'
1514 REPOSITORY = 'https://bitbucket.org/sjodogne/orthanc/raw'
1615
1716 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',
4922 ]
5023
5124 SDK = [
5225 'orthanc/OrthancCPlugin.h',
53 ]
54
55 EXE = [
56 'Resources/WindowsResources.py',
5726 ]
58
59
6027
6128
6229 def Download(x):
7037 except:
7138 pass
7239
73 url = '%s/%s/%s?force=%s' % (REPOSITORY, branch, source, uuid.uuid4())
40 url = '%s/%s/%s' % (REPOSITORY, branch, source)
7441
7542 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())
8144
8245
8346 commands = []
8447
8548 for f in FILES:
86 commands.append([ 'default', f, f ])
49 commands.append([ 'default',
50 os.path.join('Resources', f),
51 f ])
8752
8853 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 ])
9759
9860
9961 pool = multiprocessing.Pool(10) # simultaneous downloads
10062 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)
8181
8282
8383
84 ===========================================
85 6.5.8 WADO-RS / RetrieveRenderedTransaction
86 ===========================================
87
88 Not supported yet.
89
90
91
8492 ===========
8593 6.6 STOW-RS
8694 ===========
11 * Orthanc - A Lightweight, RESTful DICOM Store
22 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
33 * Department, University Hospital of Liege, Belgium
4 * Copyright (C) 2017 Osimis, Belgium
4 * Copyright (C) 2017-2018 Osimis S.A., Belgium
55 *
66 * This program is free software: you can redistribute it and/or
77 * modify it under the terms of the GNU Affero General Public License