# HG changeset patch # User Sebastien Jodogne # Date 1398178041 -7200 # Node ID 45b16f67259c4483cb2d22132da6a7045db51462 # Parent 63f707278fc86b0a67a92a77c7e9de682d8b17b0# Parent b2a62f22fbe85c713956e0fedbc46f0ca91daec9 integration mainline -> lua-scripting diff -r 63f707278fc8 -r 45b16f67259c AUTHORS --- a/AUTHORS Fri May 03 12:23:02 2013 +0200 +++ b/AUTHORS Tue Apr 22 16:47:21 2014 +0200 @@ -11,6 +11,19 @@ Overall design and main developper. +Client library +-------------- + +The client library of Orthanc is automatically wrapped from the C++ +code using the LAAW software. LAAW is the Lightweight, Automated API +Wrapper from the Jomago team, that comes from the following authors: + +* Sebastien Jodogne +* Alain Mazy +* Benjamin Golinvaux + +LAAW should be soon released as a separate open-source project. + Contributors ------------ diff -r 63f707278fc8 -r 45b16f67259c CMakeLists.txt --- a/CMakeLists.txt Fri May 03 12:23:02 2013 +0200 +++ b/CMakeLists.txt Tue Apr 22 16:47:21 2014 +0200 @@ -3,34 +3,39 @@ project(Orthanc) # Version of the build, should always be "mainline" except in release branches -add_definitions( - -DORTHANC_VERSION="mainline" - ) +set(ORTHANC_VERSION "mainline") + + +##################################################################### +## CMake parameters tunable at the command line +##################################################################### # Parameters of the build -SET(STATIC_BUILD ON CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") -SET(STANDALONE_BUILD OFF CACHE BOOL "Standalone build (all the resources are embedded, necessary for releases)") +SET(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") +SET(STANDALONE_BUILD ON CACHE BOOL "Standalone build (all the resources are embedded, necessary for releases)") SET(ENABLE_SSL ON CACHE BOOL "Include support for SSL") -SET(BUILD_UNIT_TESTS ON CACHE BOOL "Build the unit tests") +SET(BUILD_CLIENT_LIBRARY ON CACHE BOOL "Build the client library") +SET(DCMTK_DICTIONARY_DIR "" CACHE PATH "Directory containing the DCMTK dictionaries \"dicom.dic\" and \"private.dic\" (only when using system version of DCMTK)") +SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages") +SET(UNIT_TESTS_WITH_HTTP_CONNEXIONS ON CACHE BOOL "Allow unit tests to make HTTP requests") -# Advanced parameters (for Debian packaging) -SET(USE_DYNAMIC_JSONCPP OFF CACHE BOOL "Use the dynamic version of JsonCpp (only for Debian sid)") -SET(USE_DYNAMIC_GOOGLE_LOG ON CACHE BOOL "Use the dynamic version of Google Log") -SET(USE_DYNAMIC_GOOGLE_TEST ON CACHE BOOL "Use the dynamic version of Google Test (not for Debian sid)") -SET(USE_DYNAMIC_SQLITE ON CACHE BOOL "Use the dynamic version of SQLite") -SET(USE_DYNAMIC_MONGOOSE OFF CACHE BOOL "Use the dynamic version of Mongoose") -SET(USE_DYNAMIC_LUA OFF CACHE BOOL "Use the dynamic version of Lua") -SET(DEBIAN_FORCE_HARDENING OFF CACHE BOOL "Force the injection of Debian hardening flags (unrecommended)") -SET(DEBIAN_USE_GTEST_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (only for Debian sid)") -SET(ONLY_CORE_LIBRARY OFF CACHE BOOL "Only build the core library") +# Advanced parameters to fine-tune linking against system libraries +SET(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp") +SET(USE_SYSTEM_GOOGLE_LOG ON CACHE BOOL "Use the system version of Google Log") +SET(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test") +SET(USE_SYSTEM_SQLITE ON CACHE BOOL "Use the system version of SQLite") +SET(USE_SYSTEM_MONGOOSE ON CACHE BOOL "Use the system version of Mongoose") +SET(USE_SYSTEM_LUA ON CACHE BOOL "Use the system version of Lua") +SET(USE_SYSTEM_DCMTK ON CACHE BOOL "Use the system version of DCMTK") +SET(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost") +SET(USE_SYSTEM_LIBPNG ON CACHE BOOL "Use the system version of LibPng") +SET(USE_SYSTEM_CURL ON CACHE BOOL "Use the system version of LibCurl") +SET(USE_SYSTEM_OPENSSL ON CACHE BOOL "Use the system version of OpenSSL") +SET(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of ZLib") -mark_as_advanced(USE_DYNAMIC_JSONCPP) -mark_as_advanced(USE_DYNAMIC_GOOGLE_LOG) -mark_as_advanced(USE_DYNAMIC_GOOGLE_TEST) -mark_as_advanced(USE_DYNAMIC_SQLITE) -mark_as_advanced(DEBIAN_FORCE_HARDENING) -mark_as_advanced(DEBIAN_USE_STATIC_GOOGLE_TEST) -mark_as_advanced(ONLY_CORE_LIBRARY) +# Distribution-specific settings +SET(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") +mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE) # Some basic inclusions include(CheckIncludeFiles) @@ -40,8 +45,17 @@ include(${CMAKE_SOURCE_DIR}/Resources/CMake/DownloadPackage.cmake) include(${CMAKE_SOURCE_DIR}/Resources/CMake/Compiler.cmake) +set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}) + + + + +##################################################################### +## Inclusion of third-party dependencies +##################################################################### + # Configuration of the standalone builds -if (${CMAKE_CROSSCOMPILING}) +if (CMAKE_CROSSCOMPILING) # Cross-compilation implies the standalone build SET(STANDALONE_BUILD ON) endif() @@ -50,10 +64,19 @@ SET(THIRD_PARTY_SOURCES ${CMAKE_SOURCE_DIR}/Resources/md5/md5.c ${CMAKE_SOURCE_DIR}/Resources/base64/base64.cpp - ${CMAKE_SOURCE_DIR}/Resources/sha1/sha1.cpp ) include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleLogConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/BoostConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/DcmtkConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/MongooseConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/ZlibConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/SQLiteConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/JsonCppConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibPngConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/LuaConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibCurlConfiguration.cmake) + if (${ENABLE_SSL}) add_definitions(-DORTHANC_SSL_ENABLED=1) @@ -62,24 +85,16 @@ add_definitions(-DORTHANC_SSL_ENABLED=0) endif() -include(${CMAKE_SOURCE_DIR}/Resources/CMake/BoostConfiguration.cmake) -if(NOT ONLY_CORE_LIBRARY) - include(${CMAKE_SOURCE_DIR}/Resources/CMake/DcmtkConfiguration.cmake) -endif() -include(${CMAKE_SOURCE_DIR}/Resources/CMake/MongooseConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/ZlibConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/SQLiteConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/JsonCppConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibCurlConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibPngConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/Resources/CMake/LuaConfiguration.cmake) - +##################################################################### +## Autogeneration of files +##################################################################### # Prepare the embedded files set(EMBEDDED_FILES PREPARE_DATABASE ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/PrepareDatabase.sql + UPGRADE_DATABASE_3_TO_4 ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/Upgrade3To4.sql CONFIGURATION_SAMPLE ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Configuration.json LUA_TOOLBOX ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Toolbox.lua ) @@ -104,11 +119,24 @@ -# The main instructions to build the Orthanc binaries +##################################################################### +## Build the core of Orthanc +##################################################################### + +add_definitions( + -DORTHANC_VERSION="${ORTHANC_VERSION}" + ) + +list(LENGTH OPENSSL_SOURCES OPENSSL_SOURCES_LENGTH) +if (${OPENSSL_SOURCES_LENGTH} GREATER 0) + add_library(OpenSSL STATIC ${OPENSSL_SOURCES}) +endif() + add_library(CoreLibrary STATIC ${AUTOGENERATED_SOURCES} ${THIRD_PARTY_SOURCES} + ${CURL_SOURCES} Core/Cache/MemoryCache.cpp Core/ChunkedBuffer.cpp @@ -122,10 +150,12 @@ Core/DicomFormat/DicomTag.cpp Core/DicomFormat/DicomIntegerPixelAccessor.cpp Core/DicomFormat/DicomInstanceHasher.cpp + Core/Enumerations.cpp Core/FileStorage/FileStorage.cpp Core/FileStorage/StorageAccessor.cpp Core/FileStorage/CompressedFileStorageAccessor.cpp Core/FileStorage/FileStorageAccessor.cpp + Core/HttpClient.cpp Core/HttpServer/EmbeddedResourceHttpHandler.cpp Core/HttpServer/FilesystemHttpHandler.cpp Core/HttpServer/HttpHandler.cpp @@ -136,8 +166,14 @@ Core/RestApi/RestApiPath.cpp Core/RestApi/RestApiOutput.cpp Core/RestApi/RestApi.cpp + Core/MultiThreading/ArrayFilledByThreads.cpp Core/MultiThreading/BagOfRunnablesBySteps.cpp - Core/PngWriter.cpp + Core/MultiThreading/Mutex.cpp + Core/MultiThreading/ReaderWriterLock.cpp + Core/MultiThreading/SharedMessageQueue.cpp + Core/MultiThreading/ThreadedCommandProcessor.cpp + Core/FileFormats/PngReader.cpp + Core/FileFormats/PngWriter.cpp Core/SQLite/Connection.cpp Core/SQLite/FunctionContext.cpp Core/SQLite/Statement.cpp @@ -149,84 +185,263 @@ Core/Lua/LuaContext.cpp Core/Lua/LuaFunctionCall.cpp - OrthancCppClient/HttpClient.cpp - OrthancCppClient/HttpException.cpp + OrthancCppClient/OrthancConnection.cpp + OrthancCppClient/Study.cpp + OrthancCppClient/Series.cpp + OrthancCppClient/Instance.cpp + OrthancCppClient/Patient.cpp ) +##################################################################### +## Build the Orthanc server +##################################################################### + +add_library(ServerLibrary + STATIC + ${DCMTK_SOURCES} + OrthancServer/DicomProtocol/DicomFindAnswers.cpp + OrthancServer/DicomProtocol/DicomServer.cpp + OrthancServer/DicomProtocol/DicomUserConnection.cpp + OrthancServer/FromDcmtkBridge.cpp + OrthancServer/Internals/CommandDispatcher.cpp + OrthancServer/Internals/FindScp.cpp + OrthancServer/Internals/MoveScp.cpp + OrthancServer/Internals/StoreScp.cpp + OrthancServer/OrthancInitialization.cpp + OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp + OrthancServer/OrthancRestApi/OrthancRestApi.cpp + OrthancServer/OrthancRestApi/OrthancRestArchive.cpp + OrthancServer/OrthancRestApi/OrthancRestChanges.cpp + OrthancServer/OrthancRestApi/OrthancRestModalities.cpp + OrthancServer/OrthancRestApi/OrthancRestResources.cpp + OrthancServer/OrthancRestApi/OrthancRestSystem.cpp + OrthancServer/ServerIndex.cpp + OrthancServer/ToDcmtkBridge.cpp + OrthancServer/DatabaseWrapper.cpp + OrthancServer/ServerContext.cpp + OrthancServer/ServerEnumerations.cpp + OrthancServer/ServerToolbox.cpp + OrthancServer/OrthancFindRequestHandler.cpp + OrthancServer/OrthancMoveRequestHandler.cpp + ) + +# Ensure autogenerated code is built before building ServerLibrary +add_dependencies(ServerLibrary CoreLibrary) + +add_executable(Orthanc + OrthancServer/main.cpp + ) + +target_link_libraries(Orthanc ServerLibrary CoreLibrary) + +if (${OPENSSL_SOURCES_LENGTH} GREATER 0) + target_link_libraries(Orthanc OpenSSL) +endif() + +install( + TARGETS Orthanc + RUNTIME DESTINATION sbin + ) + + + +##################################################################### +## Build the unit tests +##################################################################### + +if (UNIT_TESTS_WITH_HTTP_CONNEXIONS) + add_definitions(-DUNIT_TESTS_WITH_HTTP_CONNEXIONS=1) +else() + add_definitions(-DUNIT_TESTS_WITH_HTTP_CONNEXIONS=0) +endif() + +add_definitions(-DORTHANC_BUILD_UNIT_TESTS=1) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleTestConfiguration.cmake) +add_executable(UnitTests + ${GTEST_SOURCES} + UnitTestsSources/DicomMap.cpp + UnitTestsSources/FileStorage.cpp + UnitTestsSources/MemoryCache.cpp + UnitTestsSources/Png.cpp + UnitTestsSources/RestApi.cpp + UnitTestsSources/SQLite.cpp + UnitTestsSources/SQLiteChromium.cpp + UnitTestsSources/ServerIndexTests.cpp + UnitTestsSources/Versions.cpp + UnitTestsSources/Zip.cpp + UnitTestsSources/Lua.cpp + UnitTestsSources/MultiThreading.cpp + UnitTestsSources/UnitTestsMain.cpp + ) +target_link_libraries(UnitTests ServerLibrary CoreLibrary) + +if (${OPENSSL_SOURCES_LENGTH} GREATER 0) + target_link_libraries(UnitTests OpenSSL) +endif() + + -if(NOT ONLY_CORE_LIBRARY) - add_library(ServerLibrary - STATIC - ${DCMTK_SOURCES} - OrthancServer/DicomProtocol/DicomFindAnswers.cpp - OrthancServer/DicomProtocol/DicomServer.cpp - OrthancServer/DicomProtocol/DicomUserConnection.cpp - OrthancServer/FromDcmtkBridge.cpp - OrthancServer/Internals/CommandDispatcher.cpp - OrthancServer/Internals/FindScp.cpp - OrthancServer/Internals/MoveScp.cpp - OrthancServer/Internals/StoreScp.cpp - OrthancServer/OrthancInitialization.cpp - OrthancServer/OrthancRestApi.cpp - OrthancServer/ServerIndex.cpp - OrthancServer/ToDcmtkBridge.cpp - OrthancServer/DatabaseWrapper.cpp - OrthancServer/ServerContext.cpp - OrthancServer/ServerEnumerations.cpp - OrthancServer/ServerToolbox.cpp +##################################################################### +## Create the standalone DLL containing the Orthanc Client API +##################################################################### + +if (BUILD_CLIENT_LIBRARY) + include_directories(${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/Laaw) + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + if (CMAKE_CROSSCOMPILING) + # Remove the default "lib" prefix from "libOrthancClient.dll" if cross-compiling + set(CMAKE_SHARED_LIBRARY_PREFIX "") + + if (${CMAKE_SIZEOF_VOID_P} EQUAL 4) + set(ORTHANC_CPP_CLIENT_AUX ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.def) + elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(ORTHANC_CPP_CLIENT_AUX ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.def) + else() + message(FATAL_ERROR "Support your platform here") + endif() + else() + # Nothing to do if using Visual Studio + endif() + + if (${CMAKE_SIZEOF_VOID_P} EQUAL 4) + set(CMAKE_SHARED_LIBRARY_SUFFIX "_Windows32.dll") + list(APPEND ORTHANC_CPP_CLIENT_AUX ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.rc) + elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 8) + set(CMAKE_SHARED_LIBRARY_SUFFIX "_Windows64.dll") + list(APPEND ORTHANC_CPP_CLIENT_AUX ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.rc) + else() + message(FATAL_ERROR "Support your platform here") + endif() + + else() + set(ORTHANC_CPP_CLIENT_AUX ${OPENSSL_SOURCES}) + endif() + + add_library(OrthancClient SHARED + ${ORTHANC_ROOT}/Core/OrthancException.cpp + ${ORTHANC_ROOT}/Core/Enumerations.cpp + ${ORTHANC_ROOT}/Core/Toolbox.cpp + ${ORTHANC_ROOT}/Core/HttpClient.cpp + ${ORTHANC_ROOT}/Core/MultiThreading/ArrayFilledByThreads.cpp + ${ORTHANC_ROOT}/Core/MultiThreading/ThreadedCommandProcessor.cpp + ${ORTHANC_ROOT}/Core/MultiThreading/SharedMessageQueue.cpp + ${ORTHANC_ROOT}/Core/FileFormats/PngReader.cpp + ${ORTHANC_ROOT}/OrthancCppClient/OrthancConnection.cpp + ${ORTHANC_ROOT}/OrthancCppClient/Series.cpp + ${ORTHANC_ROOT}/OrthancCppClient/Study.cpp + ${ORTHANC_ROOT}/OrthancCppClient/Instance.cpp + ${ORTHANC_ROOT}/OrthancCppClient/Patient.cpp + ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/SharedLibrary.cpp + ${ORTHANC_ROOT}/Resources/md5/md5.c + ${ORTHANC_ROOT}/Resources/base64/base64.cpp + ${ORTHANC_CPP_CLIENT_AUX} + ${THIRD_PARTY_SOURCES} + ${CURL_SOURCES} ) - # Ensure autogenerated code is built before building ServerLibrary - add_dependencies(ServerLibrary CoreLibrary) + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set_target_properties(OrthancClient + PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--as-needed -Wl,--version-script=${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/Laaw/VersionScript.map" + ) + target_link_libraries(OrthancClient pthread) + + elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + target_link_libraries(OrthancClient OpenSSL ws2_32) + + if (CMAKE_CROSSCOMPILING) + set_target_properties(OrthancClient + PROPERTIES LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++" + ) + endif() - add_executable(Orthanc - OrthancServer/main.cpp - ) + else() + message(FATAL_ERROR "Support your platform here") + endif() + - target_link_libraries(Orthanc ServerLibrary CoreLibrary) + # Set the version of the "Orthanc Client" shared library + file(STRINGS + ${CMAKE_SOURCE_DIR}/OrthancCppClient/SharedLibrary/Product.json + ORTHANC_CLIENT_VERSION_TMP + REGEX "^[ \t]*\"Version\"[ \t]*") + + string(REGEX REPLACE "^.*\"([0-9]+)\\.([0-9]+)\\.([0-9]+)\"" "\\1.\\2" + ORTHANC_CLIENT_VERSION ${ORTHANC_CLIENT_VERSION_TMP}) + + message("Setting the version of the library to ${ORTHANC_CLIENT_VERSION}") + + set_target_properties(OrthancClient PROPERTIES + VERSION ${ORTHANC_CLIENT_VERSION} + SOVERSION ${ORTHANC_CLIENT_VERSION}) + install( - TARGETS Orthanc - RUNTIME DESTINATION bin + TARGETS OrthancClient + RUNTIME DESTINATION lib # Destination for Windows + LIBRARY DESTINATION lib # Destination for Linux ) - # Build the unit tests if required - if (BUILD_UNIT_TESTS) - add_definitions(-DORTHANC_BUILD_UNIT_TESTS=1) - include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleTestConfiguration.cmake) - add_executable(UnitTests - ${GTEST_SOURCES} - UnitTests/FileStorage.cpp - UnitTests/MemoryCache.cpp - UnitTests/PngWriter.cpp - UnitTests/RestApi.cpp - UnitTests/SQLite.cpp - UnitTests/SQLiteChromium.cpp - UnitTests/ServerIndex.cpp - UnitTests/Versions.cpp - UnitTests/Zip.cpp - UnitTests/Lua.cpp - UnitTests/main.cpp - ) - target_link_libraries(UnitTests ServerLibrary CoreLibrary) - endif() + install( + FILES ${ORTHANC_ROOT}/OrthancCppClient/SharedLibrary/AUTOGENERATED/OrthancCppClient.h + DESTINATION include/orthanc + ) endif() -# Generate the Doxygen documentation if Doxygen is present + + +##################################################################### +## Generate the documentation if Doxygen is present +##################################################################### + find_package(Doxygen) if (DOXYGEN_FOUND) configure_file( ${CMAKE_SOURCE_DIR}/Resources/Orthanc.doxygen ${CMAKE_CURRENT_BINARY_DIR}/Orthanc.doxygen @ONLY) + add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Orthanc.doxygen WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating API documentation with Doxygen" VERBATIM + COMMENT "Generating internal documentation with Doxygen" VERBATIM ) + + if (BUILD_CLIENT_LIBRARY) + configure_file( + ${CMAKE_SOURCE_DIR}/Resources/OrthancClient.doxygen + ${CMAKE_CURRENT_BINARY_DIR}/OrthancClient.doxygen + @ONLY) + + add_custom_command(TARGET OrthancClient + POST_BUILD + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/OrthancClient.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating client documentation with Doxygen" VERBATIM + ) + + install( + DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/OrthancClientDocumentation/doc/ + DESTINATION share/doc/orthanc/OrthancClient + ) + endif() + else() message("Doxygen not found. The documentation will not be built.") endif() + +##################################################################### +## Prepare the "uninstall" target +## http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F +##################################################################### + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Resources/CMake/Uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff -r 63f707278fc8 -r 45b16f67259c Core/Cache/CacheIndex.h --- a/Core/Cache/CacheIndex.h Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * In addition, as a special exception, the copyright holders of this - * program give permission to link the code of its release with the - * OpenSSL project's "OpenSSL" library (or with modified versions of it - * that use the same license as the "OpenSSL" library), and distribute - * the linked executables. You must obey the GNU General Public License - * in all respects for all of the code used other than "OpenSSL". If you - * modify file(s) with this exception, you may extend this exception to - * your version of the file(s), but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source files - * in the program, then also delete it here. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - **/ - - -#pragma once - -#include -#include -#include -#include - -#include "../OrthancException.h" -#include "../Toolbox.h" - -namespace Orthanc -{ - /** - * This class implements the index of a cache with least recently - * used (LRU) recycling policy. All the items of the cache index - * can be associated with a payload. - * Reference: http://stackoverflow.com/a/2504317 - **/ - template - class CacheIndex : public boost::noncopyable - { - private: - typedef std::list< std::pair > Queue; - typedef std::map Index; - - Index index_; - Queue queue_; - - /** - * Internal method for debug builds to check whether the internal - * data structures are not corrupted. - **/ - void CheckInvariants() const; - - public: - /** - * Add a new element to the cache index, and make it the most - * recent element. - * \param id The ID of the element. - * \param payload The payload of the element. - **/ - void Add(T id, Payload payload = Payload()); - - /** - * When accessing an element of the cache, this method tags the - * element as the most recently used. - * \param id The most recently accessed item. - **/ - void TagAsMostRecent(T id); - - /** - * Remove an element from the cache index. - * \param id The item to remove. - **/ - Payload Invalidate(T id); - - /** - * Get the oldest element in the cache and remove it. - * \return The oldest item. - **/ - T RemoveOldest() - { - Payload p; - return RemoveOldest(p); - } - - /** - * Get the oldest element in the cache, remove it and return the - * associated payload. - * \param payload Where to store the associated payload. - * \return The oldest item. - **/ - T RemoveOldest(Payload& payload); - - /** - * Check whether an element is contained in the cache. - * \param id The item. - * \return \c true iff the item is indexed by the cache. - **/ - bool Contains(T id) const - { - return index_.find(id) != index_.end(); - } - - bool Contains(T id, Payload& payload) const - { - typename Index::const_iterator it = index_.find(id); - if (it == index_.end()) - { - return false; - } - else - { - payload = it->second->second; - return true; - } - } - - /** - * Return the number of elements in the cache. - * \return The number of elements. - **/ - size_t GetSize() const - { - assert(index_.size() == queue_.size()); - return queue_.size(); - } - - /** - * Check whether the cache index is empty. - * \return \c true iff the cache is empty. - **/ - bool IsEmpty() const - { - return index_.empty(); - } - }; - - - - - /****************************************************************** - ** Implementation of the template - ******************************************************************/ - - template - void CacheIndex::CheckInvariants() const - { -#ifndef NDEBUG - assert(index_.size() == queue_.size()); - - for (typename Index::const_iterator - it = index_.begin(); it != index_.end(); it++) - { - assert(it->second != queue_.end()); - assert(it->second->first == it->first); - } -#endif - } - - - template - void CacheIndex::Add(T id, Payload payload) - { - if (Contains(id)) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - queue_.push_front(std::make_pair(id, payload)); - index_[id] = queue_.begin(); - - CheckInvariants(); - } - - - template - void CacheIndex::TagAsMostRecent(T id) - { - if (!Contains(id)) - { - throw OrthancException(ErrorCode_InexistentItem); - } - - typename Index::iterator it = index_.find(id); - assert(it != index_.end()); - - std::pair item = *(it->second); - - queue_.erase(it->second); - queue_.push_front(item); - index_[id] = queue_.begin(); - - CheckInvariants(); - } - - - template - Payload CacheIndex::Invalidate(T id) - { - if (!Contains(id)) - { - throw OrthancException(ErrorCode_InexistentItem); - } - - typename Index::iterator it = index_.find(id); - assert(it != index_.end()); - - Payload payload = it->second->second; - queue_.erase(it->second); - index_.erase(it); - - CheckInvariants(); - return payload; - } - - - template - T CacheIndex::RemoveOldest(Payload& payload) - { - if (IsEmpty()) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls); - } - - std::pair item = queue_.back(); - T oldest = item.first; - payload = item.second; - - queue_.pop_back(); - assert(index_.find(oldest) != index_.end()); - index_.erase(oldest); - - CheckInvariants(); - - return oldest; - } -} diff -r 63f707278fc8 -r 45b16f67259c Core/Cache/ICachePageProvider.h --- a/Core/Cache/ICachePageProvider.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Cache/ICachePageProvider.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Cache/LeastRecentlyUsedIndex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Cache/LeastRecentlyUsedIndex.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,346 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include +#include +#include +#include + +#include "../OrthancException.h" +#include "../Toolbox.h" + +namespace Orthanc +{ + /** + * This class implements the index of a cache with least recently + * used (LRU) recycling policy. All the items of the cache index + * can be associated with a payload. + * Reference: http://stackoverflow.com/a/2504317 + **/ + template + class LeastRecentlyUsedIndex : public boost::noncopyable + { + private: + typedef std::list< std::pair > Queue; + typedef std::map Index; + + Index index_; + Queue queue_; + + /** + * Internal method for debug builds to check whether the internal + * data structures are not corrupted. + **/ + void CheckInvariants() const; + + public: + /** + * Add a new element to the cache index, and make it the most + * recent element. + * \param id The ID of the element. + * \param payload The payload of the element. + **/ + void Add(T id, Payload payload = Payload()); + + void AddOrMakeMostRecent(T id, Payload payload = Payload()); + + /** + * When accessing an element of the cache, this method tags the + * element as the most recently used. + * \param id The most recently accessed item. + **/ + void MakeMostRecent(T id); + + void MakeMostRecent(T id, Payload updatedPayload); + + /** + * Remove an element from the cache index. + * \param id The item to remove. + **/ + Payload Invalidate(T id); + + /** + * Get the oldest element in the cache and remove it. + * \return The oldest item. + **/ + T RemoveOldest(); + + /** + * Get the oldest element in the cache, remove it and return the + * associated payload. + * \param payload Where to store the associated payload. + * \return The oldest item. + **/ + T RemoveOldest(Payload& payload); + + /** + * Check whether an element is contained in the cache. + * \param id The item. + * \return \c true iff the item is indexed by the cache. + **/ + bool Contains(T id) const + { + return index_.find(id) != index_.end(); + } + + bool Contains(T id, Payload& payload) const + { + typename Index::const_iterator it = index_.find(id); + if (it == index_.end()) + { + return false; + } + else + { + payload = it->second->second; + return true; + } + } + + /** + * Return the number of elements in the cache. + * \return The number of elements. + **/ + size_t GetSize() const + { + assert(index_.size() == queue_.size()); + return queue_.size(); + } + + /** + * Check whether the cache index is empty. + * \return \c true iff the cache is empty. + **/ + bool IsEmpty() const + { + return index_.empty(); + } + + const T& GetOldest() const; + + const Payload& GetOldestPayload() const; + }; + + + + + /****************************************************************** + ** Implementation of the template + ******************************************************************/ + + template + void LeastRecentlyUsedIndex::CheckInvariants() const + { +#ifndef NDEBUG + assert(index_.size() == queue_.size()); + + for (typename Index::const_iterator + it = index_.begin(); it != index_.end(); it++) + { + assert(it->second != queue_.end()); + assert(it->second->first == it->first); + } +#endif + } + + + template + void LeastRecentlyUsedIndex::Add(T id, Payload payload) + { + if (Contains(id)) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + queue_.push_front(std::make_pair(id, payload)); + index_[id] = queue_.begin(); + + CheckInvariants(); + } + + + template + void LeastRecentlyUsedIndex::MakeMostRecent(T id) + { + if (!Contains(id)) + { + throw OrthancException(ErrorCode_InexistentItem); + } + + typename Index::iterator it = index_.find(id); + assert(it != index_.end()); + + std::pair item = *(it->second); + + queue_.erase(it->second); + queue_.push_front(item); + index_[id] = queue_.begin(); + + CheckInvariants(); + } + + + template + void LeastRecentlyUsedIndex::AddOrMakeMostRecent(T id, Payload payload) + { + typename Index::iterator it = index_.find(id); + + if (it != index_.end()) + { + // Already existing. Make it most recent. + std::pair item = *(it->second); + item.second = payload; + queue_.erase(it->second); + queue_.push_front(item); + } + else + { + // New item + queue_.push_front(std::make_pair(id, payload)); + } + + index_[id] = queue_.begin(); + + CheckInvariants(); + } + + + template + void LeastRecentlyUsedIndex::MakeMostRecent(T id, Payload updatedPayload) + { + if (!Contains(id)) + { + throw OrthancException(ErrorCode_InexistentItem); + } + + typename Index::iterator it = index_.find(id); + assert(it != index_.end()); + + std::pair item = *(it->second); + item.second = updatedPayload; + + queue_.erase(it->second); + queue_.push_front(item); + index_[id] = queue_.begin(); + + CheckInvariants(); + } + + + template + Payload LeastRecentlyUsedIndex::Invalidate(T id) + { + if (!Contains(id)) + { + throw OrthancException(ErrorCode_InexistentItem); + } + + typename Index::iterator it = index_.find(id); + assert(it != index_.end()); + + Payload payload = it->second->second; + queue_.erase(it->second); + index_.erase(it); + + CheckInvariants(); + return payload; + } + + + template + T LeastRecentlyUsedIndex::RemoveOldest(Payload& payload) + { + if (IsEmpty()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + std::pair item = queue_.back(); + T oldest = item.first; + payload = item.second; + + queue_.pop_back(); + assert(index_.find(oldest) != index_.end()); + index_.erase(oldest); + + CheckInvariants(); + + return oldest; + } + + + template + T LeastRecentlyUsedIndex::RemoveOldest() + { + if (IsEmpty()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + std::pair item = queue_.back(); + T oldest = item.first; + + queue_.pop_back(); + assert(index_.find(oldest) != index_.end()); + index_.erase(oldest); + + CheckInvariants(); + + return oldest; + } + + + template + const T& LeastRecentlyUsedIndex::GetOldest() const + { + if (IsEmpty()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + return queue_.back().first; + } + + + template + const Payload& LeastRecentlyUsedIndex::GetOldestPayload() const + { + if (IsEmpty()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + return queue_.back().second; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/Cache/MemoryCache.cpp --- a/Core/Cache/MemoryCache.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Cache/MemoryCache.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -46,7 +46,7 @@ { VLOG(1) << "Reusing a cache page"; assert(p != NULL); - index_.TagAsMostRecent(id); + index_.MakeMostRecent(id); return *p; } diff -r 63f707278fc8 -r 45b16f67259c Core/Cache/MemoryCache.h --- a/Core/Cache/MemoryCache.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Cache/MemoryCache.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -33,7 +33,7 @@ #pragma once #include -#include "CacheIndex.h" +#include "LeastRecentlyUsedIndex.h" #include "ICachePageProvider.h" namespace Orthanc @@ -52,7 +52,7 @@ ICachePageProvider& provider_; size_t cacheSize_; - CacheIndex index_; + LeastRecentlyUsedIndex index_; Page& Load(const std::string& id); diff -r 63f707278fc8 -r 45b16f67259c Core/ChunkedBuffer.cpp --- a/Core/ChunkedBuffer.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/ChunkedBuffer.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -43,7 +43,7 @@ numBytes_ = 0; for (Chunks::iterator it = chunks_.begin(); - it != chunks_.end(); it++) + it != chunks_.end(); ++it) { delete *it; } @@ -70,7 +70,7 @@ size_t pos = 0; for (Chunks::iterator it = chunks_.begin(); - it != chunks_.end(); it++) + it != chunks_.end(); ++it) { assert(*it != NULL); diff -r 63f707278fc8 -r 45b16f67259c Core/ChunkedBuffer.h --- a/Core/ChunkedBuffer.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/ChunkedBuffer.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/BufferCompressor.cpp --- a/Core/Compression/BufferCompressor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/BufferCompressor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/BufferCompressor.h --- a/Core/Compression/BufferCompressor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/BufferCompressor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/HierarchicalZipWriter.cpp --- a/Core/Compression/HierarchicalZipWriter.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/HierarchicalZipWriter.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -81,12 +81,12 @@ std::string result; Stack::const_iterator it = stack_.begin(); - it++; // Skip the root node (to avoid absolute paths) + ++it; // Skip the root node (to avoid absolute paths) while (it != stack_.end()) { result += (*it)->name_ + "/"; - it++; + ++it; } return result; @@ -118,7 +118,7 @@ HierarchicalZipWriter::Index::~Index() { - for (Stack::iterator it = stack_.begin(); it != stack_.end(); it++) + for (Stack::iterator it = stack_.begin(); it != stack_.end(); ++it) { delete *it; } diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/HierarchicalZipWriter.h --- a/Core/Compression/HierarchicalZipWriter.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/HierarchicalZipWriter.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -94,6 +94,16 @@ ~HierarchicalZipWriter(); + void SetZip64(bool isZip64) + { + writer_.SetZip64(isZip64); + } + + bool IsZip64() const + { + return writer_.IsZip64(); + } + void SetCompressionLevel(uint8_t level) { writer_.SetCompressionLevel(level); diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/ZipWriter.cpp --- a/Core/Compression/ZipWriter.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/ZipWriter.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -29,11 +29,15 @@ * along with this program. If not, see . **/ +#ifndef NOMINMAX +#define NOMINMAX +#endif #include "ZipWriter.h" #include "../../Resources/minizip/zip.h" #include +#include #include "../OrthancException.h" @@ -76,6 +80,7 @@ { compressionLevel_ = 6; hasFileInZip_ = false; + isZip64_ = false; pimpl_->file_ = NULL; } @@ -113,7 +118,16 @@ } hasFileInZip_ = false; - pimpl_->file_ = zipOpen64(path_.c_str(), APPEND_STATUS_CREATE); + + if (isZip64_) + { + pimpl_->file_ = zipOpen64(path_.c_str(), APPEND_STATUS_CREATE); + } + else + { + pimpl_->file_ = zipOpen(path_.c_str(), APPEND_STATUS_CREATE); + } + if (!pimpl_->file_) { throw OrthancException(ErrorCode_CannotWriteFile); @@ -126,6 +140,12 @@ path_ = path; } + void ZipWriter::SetZip64(bool isZip64) + { + Close(); + isZip64_ = isZip64; + } + void ZipWriter::SetCompressionLevel(uint8_t level) { if (level >= 10) @@ -133,6 +153,7 @@ throw OrthancException("ZIP compression level must be between 0 (no compression) and 9 (highest compression"); } + Close(); compressionLevel_ = level; } @@ -143,13 +164,30 @@ zip_fileinfo zfi; PrepareFileInfo(zfi); - if (zipOpenNewFileInZip64(pimpl_->file_, path, - &zfi, - NULL, 0, - NULL, 0, - "", // Comment - Z_DEFLATED, - compressionLevel_, 1) != 0) + int result; + + if (isZip64_) + { + result = zipOpenNewFileInZip64(pimpl_->file_, path, + &zfi, + NULL, 0, + NULL, 0, + "", // Comment + Z_DEFLATED, + compressionLevel_, 1); + } + else + { + result = zipOpenNewFileInZip(pimpl_->file_, path, + &zfi, + NULL, 0, + NULL, 0, + "", // Comment + Z_DEFLATED, + compressionLevel_); + } + + if (result != 0) { throw OrthancException(ErrorCode_CannotWriteFile); } diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/ZipWriter.h --- a/Core/Compression/ZipWriter.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/ZipWriter.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -48,6 +48,7 @@ struct PImpl; boost::shared_ptr pimpl_; + bool isZip64_; bool hasFileInZip_; uint8_t compressionLevel_; std::string path_; @@ -57,6 +58,13 @@ ~ZipWriter(); + void SetZip64(bool isZip64); + + bool IsZip64() const + { + return isZip64_; + } + void SetCompressionLevel(uint8_t level); uint8_t GetCompressionLevel() const diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/ZlibCompressor.cpp --- a/Core/Compression/ZlibCompressor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/ZlibCompressor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Compression/ZlibCompressor.h --- a/Core/Compression/ZlibCompressor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Compression/ZlibCompressor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomArray.cpp --- a/Core/DicomFormat/DicomArray.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomArray.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -41,7 +41,7 @@ elements_.reserve(map.map_.size()); for (DicomMap::Map::const_iterator it = - map.map_.begin(); it != map.map_.end(); it++) + map.map_.begin(); it != map.map_.end(); ++it) { elements_.push_back(new DicomElement(it->first, *it->second)); } diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomArray.h --- a/Core/DicomFormat/DicomArray.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomArray.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomElement.h --- a/Core/DicomFormat/DicomElement.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomElement.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomInstanceHasher.cpp --- a/Core/DicomFormat/DicomInstanceHasher.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomInstanceHasher.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomInstanceHasher.h --- a/Core/DicomFormat/DicomInstanceHasher.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomInstanceHasher.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomIntegerPixelAccessor.cpp --- a/Core/DicomFormat/DicomIntegerPixelAccessor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomIntegerPixelAccessor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -30,12 +30,12 @@ **/ -#include "DicomIntegerPixelAccessor.h" - #ifndef NOMINMAX #define NOMINMAX #endif +#include "DicomIntegerPixelAccessor.h" + #include "../OrthancException.h" #include #include @@ -140,11 +140,13 @@ if (pixelRepresentation) { + // Pixels are signed mask_ = (1 << (bitsStored - 1)) - 1; signMask_ = (1 << (bitsStored - 1)); } else { + // Pixels are unsigned mask_ = (1 << bitsStored) - 1; signMask_ = 0; } @@ -231,25 +233,28 @@ pixel += channel * frameOffset_ / samplesPerPixel_ + x * bytesPerPixel_; } - int32_t v; + uint32_t v; v = pixel[0]; if (bytesPerPixel_ >= 2) - v = v + (static_cast(pixel[1]) << 8); + v = v + (static_cast(pixel[1]) << 8); if (bytesPerPixel_ >= 3) - v = v + (static_cast(pixel[2]) << 16); + v = v + (static_cast(pixel[2]) << 16); if (bytesPerPixel_ >= 4) - v = v + (static_cast(pixel[3]) << 24); + v = v + (static_cast(pixel[3]) << 24); - v = (v >> shift_) & mask_; + v = v >> shift_; if (v & signMask_) { - // Signed value: Not implemented yet - //throw OrthancException(ErrorCode_NotImplemented); - v = 0; + // Signed value + // http://en.wikipedia.org/wiki/Two%27s_complement#Subtraction_from_2N + return -static_cast(mask_) + static_cast(v & mask_) - 1; } - - return v; + else + { + // Unsigned value + return static_cast(v & mask_); + } } diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomIntegerPixelAccessor.h --- a/Core/DicomFormat/DicomIntegerPixelAccessor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomIntegerPixelAccessor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomMap.cpp --- a/Core/DicomFormat/DicomMap.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomMap.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -76,9 +76,11 @@ DicomTag(0x0018, 0x0024), // SequenceName DicomTag(0x0018, 0x1030), // ProtocolName DicomTag(0x0020, 0x0011), // SeriesNumber - //DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, + DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, DICOM_TAG_IMAGES_IN_ACQUISITION, + DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, DICOM_TAG_NUMBER_OF_SLICES, + DICOM_TAG_NUMBER_OF_TIME_SLICES, DICOM_TAG_SERIES_INSTANCE_UID }; @@ -90,6 +92,7 @@ DICOM_TAG_IMAGE_INDEX, DICOM_TAG_INSTANCE_NUMBER, DICOM_TAG_NUMBER_OF_FRAMES, + DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, DICOM_TAG_SOP_INSTANCE_UID }; @@ -125,7 +128,7 @@ void DicomMap::Clear() { - for (Map::iterator it = map_.begin(); it != map_.end(); it++) + for (Map::iterator it = map_.begin(); it != map_.end(); ++it) { delete it->second; } @@ -177,7 +180,7 @@ { std::auto_ptr result(new DicomMap); - for (Map::const_iterator it = map_.begin(); it != map_.end(); it++) + for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) { result->map_.insert(std::make_pair(it->first, it->second->Clone())); } @@ -196,7 +199,7 @@ } else { - throw OrthancException("Inexistent tag"); + throw OrthancException(ErrorCode_InexistentTag); } } @@ -277,4 +280,110 @@ SetValue(tag, source.GetValue(tag)); } } + + + bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) + { + DicomTag *tags = NULL; + size_t size; + + switch (level) + { + case ResourceType_Patient: + tags = patientTags; + size = sizeof(patientTags) / sizeof(DicomTag); + break; + + case ResourceType_Study: + tags = studyTags; + size = sizeof(studyTags) / sizeof(DicomTag); + break; + + case ResourceType_Series: + tags = seriesTags; + size = sizeof(seriesTags) / sizeof(DicomTag); + break; + + case ResourceType_Instance: + tags = instanceTags; + size = sizeof(instanceTags) / sizeof(DicomTag); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + for (size_t i = 0; i < size; i++) + { + if (tags[i] == tag) + { + return true; + } + } + + return false; + } + + bool DicomMap::IsMainDicomTag(const DicomTag& tag) + { + return (IsMainDicomTag(tag, ResourceType_Patient) || + IsMainDicomTag(tag, ResourceType_Study) || + IsMainDicomTag(tag, ResourceType_Series) || + IsMainDicomTag(tag, ResourceType_Instance)); + } + + + void DicomMap::GetMainDicomTagsInternal(std::set& result, ResourceType level) + { + DicomTag *tags = NULL; + size_t size; + + switch (level) + { + case ResourceType_Patient: + tags = patientTags; + size = sizeof(patientTags) / sizeof(DicomTag); + break; + + case ResourceType_Study: + tags = studyTags; + size = sizeof(studyTags) / sizeof(DicomTag); + break; + + case ResourceType_Series: + tags = seriesTags; + size = sizeof(seriesTags) / sizeof(DicomTag); + break; + + case ResourceType_Instance: + tags = instanceTags; + size = sizeof(instanceTags) / sizeof(DicomTag); + break; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + for (size_t i = 0; i < size; i++) + { + result.insert(tags[i]); + } + } + + + void DicomMap::GetMainDicomTags(std::set& result, ResourceType level) + { + result.clear(); + GetMainDicomTagsInternal(result, level); + } + + + void DicomMap::GetMainDicomTags(std::set& result) + { + result.clear(); + GetMainDicomTagsInternal(result, ResourceType_Patient); + GetMainDicomTagsInternal(result, ResourceType_Study); + GetMainDicomTagsInternal(result, ResourceType_Series); + GetMainDicomTagsInternal(result, ResourceType_Instance); + } } diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomMap.h --- a/Core/DicomFormat/DicomMap.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomMap.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -35,7 +35,9 @@ #include "DicomTag.h" #include "DicomValue.h" #include "DicomString.h" +#include "../Enumerations.h" +#include #include #include @@ -63,6 +65,8 @@ void ExtractTags(DicomMap& source, const DicomTag* tags, size_t count) const; + + static void GetMainDicomTagsInternal(std::set& result, ResourceType level); public: DicomMap() @@ -148,5 +152,13 @@ void CopyTagIfExists(const DicomMap& source, const DicomTag& tag); + + static bool IsMainDicomTag(const DicomTag& tag, ResourceType level); + + static bool IsMainDicomTag(const DicomTag& tag); + + static void GetMainDicomTags(std::set& result, ResourceType level); + + static void GetMainDicomTags(std::set& result); }; } diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomNullValue.h --- a/Core/DicomFormat/DicomNullValue.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomNullValue.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomString.h --- a/Core/DicomFormat/DicomString.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomString.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomTag.cpp --- a/Core/DicomFormat/DicomTag.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomTag.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomTag.h --- a/Core/DicomFormat/DicomTag.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomTag.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -95,6 +95,7 @@ static const DicomTag DICOM_TAG_INSTANCE_NUMBER(0x0020, 0x0013); static const DicomTag DICOM_TAG_NUMBER_OF_SLICES(0x0054, 0x0081); + static const DicomTag DICOM_TAG_NUMBER_OF_TIME_SLICES(0x0054, 0x0101); static const DicomTag DICOM_TAG_NUMBER_OF_FRAMES(0x0028, 0x0008); static const DicomTag DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES(0x0018, 0x1090); static const DicomTag DICOM_TAG_IMAGES_IN_ACQUISITION(0x0020, 0x1002); @@ -105,4 +106,13 @@ static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016); static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID(0x0002, 0x0002); static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID(0x0002, 0x0003); + + // DICOM tags used for fMRI (thanks to Will Ryder) + static const DicomTag DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS(0x0020, 0x0105); + static const DicomTag DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER(0x0020, 0x0100); + + // Tags for C-FIND and C-MOVE + static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005); + static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052); + static const DicomTag DICOM_TAG_MODALITIES_IN_STUDY(0x0008, 0x0061); } diff -r 63f707278fc8 -r 45b16f67259c Core/DicomFormat/DicomValue.h --- a/Core/DicomFormat/DicomValue.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/DicomFormat/DicomValue.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/EnumerationDictionary.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/EnumerationDictionary.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,122 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "OrthancException.h" + +#include +#include +#include + +namespace Orthanc +{ + namespace Toolbox + { + template + class EnumerationDictionary + { + private: + typedef std::map EnumerationToString; + typedef std::map StringToEnumeration; + + EnumerationToString enumerationToString_; + StringToEnumeration stringToEnumeration_; + + public: + void Add(Enumeration value, const std::string& str) + { + // Check if these values are free + if (enumerationToString_.find(value) != enumerationToString_.end() || + stringToEnumeration_.find(str) != stringToEnumeration_.end()) + { + throw OrthancException(ErrorCode_BadRequest); + } + + // Prevent the registration of a number + try + { + boost::lexical_cast(str); + throw OrthancException(ErrorCode_BadRequest); + } + catch (boost::bad_lexical_cast) + { + // OK, the string is not a number + } + + enumerationToString_[value] = str; + stringToEnumeration_[str] = value; + stringToEnumeration_[boost::lexical_cast(static_cast(value))] = value; + } + + Enumeration Translate(const std::string& str) const + { + try + { + int value = boost::lexical_cast(str); + return static_cast(value); + } + catch (boost::bad_lexical_cast) + { + } + + typename StringToEnumeration::const_iterator + found = stringToEnumeration_.find(str); + + if (found == stringToEnumeration_.end()) + { + throw OrthancException(ErrorCode_InexistentItem); + } + else + { + return found->second; + } + } + + std::string Translate(Enumeration e) const + { + typename EnumerationToString::const_iterator + found = enumerationToString_.find(e); + + if (found == enumerationToString_.end()) + { + // No name for this item + return boost::lexical_cast(static_cast(e)); + } + else + { + return found->second; + } + } + }; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/Enumerations.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Enumerations.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,277 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Enumerations.h" + +#include "OrthancException.h" +#include "Toolbox.h" + +namespace Orthanc +{ + const char* EnumerationToString(HttpMethod method) + { + switch (method) + { + case HttpMethod_Get: + return "GET"; + + case HttpMethod_Post: + return "POST"; + + case HttpMethod_Delete: + return "DELETE"; + + case HttpMethod_Put: + return "PUT"; + + default: + return "?"; + } + } + + + const char* EnumerationToString(HttpStatus status) + { + switch (status) + { + case HttpStatus_100_Continue: + return "Continue"; + + case HttpStatus_101_SwitchingProtocols: + return "Switching Protocols"; + + case HttpStatus_102_Processing: + return "Processing"; + + case HttpStatus_200_Ok: + return "OK"; + + case HttpStatus_201_Created: + return "Created"; + + case HttpStatus_202_Accepted: + return "Accepted"; + + case HttpStatus_203_NonAuthoritativeInformation: + return "Non-Authoritative Information"; + + case HttpStatus_204_NoContent: + return "No Content"; + + case HttpStatus_205_ResetContent: + return "Reset Content"; + + case HttpStatus_206_PartialContent: + return "Partial Content"; + + case HttpStatus_207_MultiStatus: + return "Multi-Status"; + + case HttpStatus_208_AlreadyReported: + return "Already Reported"; + + case HttpStatus_226_IMUsed: + return "IM Used"; + + case HttpStatus_300_MultipleChoices: + return "Multiple Choices"; + + case HttpStatus_301_MovedPermanently: + return "Moved Permanently"; + + case HttpStatus_302_Found: + return "Found"; + + case HttpStatus_303_SeeOther: + return "See Other"; + + case HttpStatus_304_NotModified: + return "Not Modified"; + + case HttpStatus_305_UseProxy: + return "Use Proxy"; + + case HttpStatus_307_TemporaryRedirect: + return "Temporary Redirect"; + + case HttpStatus_400_BadRequest: + return "Bad Request"; + + case HttpStatus_401_Unauthorized: + return "Unauthorized"; + + case HttpStatus_402_PaymentRequired: + return "Payment Required"; + + case HttpStatus_403_Forbidden: + return "Forbidden"; + + case HttpStatus_404_NotFound: + return "Not Found"; + + case HttpStatus_405_MethodNotAllowed: + return "Method Not Allowed"; + + case HttpStatus_406_NotAcceptable: + return "Not Acceptable"; + + case HttpStatus_407_ProxyAuthenticationRequired: + return "Proxy Authentication Required"; + + case HttpStatus_408_RequestTimeout: + return "Request Timeout"; + + case HttpStatus_409_Conflict: + return "Conflict"; + + case HttpStatus_410_Gone: + return "Gone"; + + case HttpStatus_411_LengthRequired: + return "Length Required"; + + case HttpStatus_412_PreconditionFailed: + return "Precondition Failed"; + + case HttpStatus_413_RequestEntityTooLarge: + return "Request Entity Too Large"; + + case HttpStatus_414_RequestUriTooLong: + return "Request-URI Too Long"; + + case HttpStatus_415_UnsupportedMediaType: + return "Unsupported Media Type"; + + case HttpStatus_416_RequestedRangeNotSatisfiable: + return "Requested Range Not Satisfiable"; + + case HttpStatus_417_ExpectationFailed: + return "Expectation Failed"; + + case HttpStatus_422_UnprocessableEntity: + return "Unprocessable Entity"; + + case HttpStatus_423_Locked: + return "Locked"; + + case HttpStatus_424_FailedDependency: + return "Failed Dependency"; + + case HttpStatus_426_UpgradeRequired: + return "Upgrade Required"; + + case HttpStatus_500_InternalServerError: + return "Internal Server Error"; + + case HttpStatus_501_NotImplemented: + return "Not Implemented"; + + case HttpStatus_502_BadGateway: + return "Bad Gateway"; + + case HttpStatus_503_ServiceUnavailable: + return "Service Unavailable"; + + case HttpStatus_504_GatewayTimeout: + return "Gateway Timeout"; + + case HttpStatus_505_HttpVersionNotSupported: + return "HTTP Version Not Supported"; + + case HttpStatus_506_VariantAlsoNegotiates: + return "Variant Also Negotiates"; + + case HttpStatus_507_InsufficientStorage: + return "Insufficient Storage"; + + case HttpStatus_509_BandwidthLimitExceeded: + return "Bandwidth Limit Exceeded"; + + case HttpStatus_510_NotExtended: + return "Not Extended"; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + const char* EnumerationToString(ResourceType type) + { + switch (type) + { + case ResourceType_Patient: + return "Patient"; + + case ResourceType_Study: + return "Study"; + + case ResourceType_Series: + return "Series"; + + case ResourceType_Instance: + return "Instance"; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + ResourceType StringToResourceType(const char* type) + { + std::string s(type); + Toolbox::ToUpperCase(s); + + if (s == "PATIENT" || s == "PATIENTS") + { + return ResourceType_Patient; + } + else if (s == "STUDY" || s == "STUDIES") + { + return ResourceType_Study; + } + else if (s == "SERIES") + { + return ResourceType_Series; + } + else if (s == "INSTANCE" || s == "IMAGE" || + s == "INSTANCES" || s == "IMAGES") + { + return ResourceType_Instance; + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/Enumerations.h --- a/Core/Enumerations.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Enumerations.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -32,10 +32,17 @@ #pragma once -#include "../OrthancCppClient/HttpEnumerations.h" +#include namespace Orthanc { + enum Endianness + { + Endianness_Unknown, + Endianness_Big, + Endianness_Little + }; + enum ErrorCode { // Generic error codes @@ -49,6 +56,7 @@ ErrorCode_BadSequenceOfCalls, ErrorCode_InexistentItem, ErrorCode_BadRequest, + ErrorCode_NetworkProtocol, // Specific error codes ErrorCode_UriSyntax, @@ -58,14 +66,149 @@ ErrorCode_Timeout, ErrorCode_UnknownResource, ErrorCode_IncompatibleDatabaseVersion, - ErrorCode_FullStorage + ErrorCode_FullStorage, + ErrorCode_CorruptedFile, + ErrorCode_InexistentTag + }; + + /** + * {summary}{The memory layout of the pixels (resp. voxels) of a 2D (resp. 3D) image.} + **/ + enum LAAW_API PixelFormat + { + /** + * {summary}{Color image in RGB24 format.} + * {description}{This format describes a color image. The pixels are stored in 3 + * consecutive bytes. The memory layout is RGB. + **/ + PixelFormat_RGB24, + + /** + * {summary}{Graylevel 8bpp image.} + * {description}{The image is graylevel. Each pixel is unsigned and stored in one byte.} + **/ + PixelFormat_Grayscale8, + + /** + * {summary}{Graylevel, unsigned 16bpp image.} + * {description}{The image is graylevel. Each pixel is unsigned and stored in two bytes.} + **/ + PixelFormat_Grayscale16, + + /** + * {summary}{Graylevel, signed 16bpp image.} + * {description}{The image is graylevel. Each pixel is signed and stored in two bytes.} + **/ + PixelFormat_SignedGrayscale16 + }; + + + /** + * {summary}{The extraction mode specifies the way the values of the pixels are scaled when downloading a 2D image.} + **/ + enum LAAW_API ImageExtractionMode + { + /** + * {summary}{Rescaled to 8bpp.} + * {description}{The minimum value of the image is set to 0, and its maximum value is set to 255.} + **/ + ImageExtractionMode_Preview, + + /** + * {summary}{Truncation to the [0, 255] range.} + **/ + ImageExtractionMode_UInt8, + + /** + * {summary}{Truncation to the [0, 65535] range.} + **/ + ImageExtractionMode_UInt16, + + /** + * {summary}{Truncation to the [-32768, 32767] range.} + **/ + ImageExtractionMode_Int16 }; - enum PixelFormat + + /** + * Most common, non-joke and non-experimental HTTP status codes + * http://en.wikipedia.org/wiki/List_of_HTTP_status_codes + **/ + enum HttpStatus { - PixelFormat_RGB24, - PixelFormat_Grayscale8, - PixelFormat_Grayscale16 + HttpStatus_None = -1, + + // 1xx Informational + HttpStatus_100_Continue = 100, + HttpStatus_101_SwitchingProtocols = 101, + HttpStatus_102_Processing = 102, + + // 2xx Success + HttpStatus_200_Ok = 200, + HttpStatus_201_Created = 201, + HttpStatus_202_Accepted = 202, + HttpStatus_203_NonAuthoritativeInformation = 203, + HttpStatus_204_NoContent = 204, + HttpStatus_205_ResetContent = 205, + HttpStatus_206_PartialContent = 206, + HttpStatus_207_MultiStatus = 207, + HttpStatus_208_AlreadyReported = 208, + HttpStatus_226_IMUsed = 226, + + // 3xx Redirection + HttpStatus_300_MultipleChoices = 300, + HttpStatus_301_MovedPermanently = 301, + HttpStatus_302_Found = 302, + HttpStatus_303_SeeOther = 303, + HttpStatus_304_NotModified = 304, + HttpStatus_305_UseProxy = 305, + HttpStatus_307_TemporaryRedirect = 307, + + // 4xx Client Error + HttpStatus_400_BadRequest = 400, + HttpStatus_401_Unauthorized = 401, + HttpStatus_402_PaymentRequired = 402, + HttpStatus_403_Forbidden = 403, + HttpStatus_404_NotFound = 404, + HttpStatus_405_MethodNotAllowed = 405, + HttpStatus_406_NotAcceptable = 406, + HttpStatus_407_ProxyAuthenticationRequired = 407, + HttpStatus_408_RequestTimeout = 408, + HttpStatus_409_Conflict = 409, + HttpStatus_410_Gone = 410, + HttpStatus_411_LengthRequired = 411, + HttpStatus_412_PreconditionFailed = 412, + HttpStatus_413_RequestEntityTooLarge = 413, + HttpStatus_414_RequestUriTooLong = 414, + HttpStatus_415_UnsupportedMediaType = 415, + HttpStatus_416_RequestedRangeNotSatisfiable = 416, + HttpStatus_417_ExpectationFailed = 417, + HttpStatus_422_UnprocessableEntity = 422, + HttpStatus_423_Locked = 423, + HttpStatus_424_FailedDependency = 424, + HttpStatus_426_UpgradeRequired = 426, + + // 5xx Server Error + HttpStatus_500_InternalServerError = 500, + HttpStatus_501_NotImplemented = 501, + HttpStatus_502_BadGateway = 502, + HttpStatus_503_ServiceUnavailable = 503, + HttpStatus_504_GatewayTimeout = 504, + HttpStatus_505_HttpVersionNotSupported = 505, + HttpStatus_506_VariantAlsoNegotiates = 506, + HttpStatus_507_InsufficientStorage = 507, + HttpStatus_509_BandwidthLimitExceeded = 509, + HttpStatus_510_NotExtended = 510 + }; + + + enum HttpMethod + { + HttpMethod_Get = 0, + HttpMethod_Post = 1, + HttpMethod_Delete = 2, + HttpMethod_Put = 3 }; @@ -84,6 +227,27 @@ enum FileContentType { FileContentType_Dicom = 1, - FileContentType_Json = 2 + FileContentType_DicomAsJson = 2, + + // Make sure that the value "65535" can be stored into this enumeration + FileContentType_StartUser = 1024, + FileContentType_EndUser = 65535 }; + + enum ResourceType + { + ResourceType_Patient = 1, + ResourceType_Study = 2, + ResourceType_Series = 3, + ResourceType_Instance = 4 + }; + + + const char* EnumerationToString(HttpMethod method); + + const char* EnumerationToString(HttpStatus status); + + const char* EnumerationToString(ResourceType type); + + ResourceType StringToResourceType(const char* type); } diff -r 63f707278fc8 -r 45b16f67259c Core/FileFormats/PngReader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileFormats/PngReader.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,305 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "PngReader.h" + +#include "../OrthancException.h" +#include "../Toolbox.h" + +#include +#include // For memcpy() + +namespace Orthanc +{ + namespace + { + struct FileRabi + { + FILE* fp_; + + FileRabi(const char* filename) + { + fp_ = fopen(filename, "rb"); + if (!fp_) + { + throw OrthancException(ErrorCode_InexistentFile); + } + } + + ~FileRabi() + { + if (fp_) + fclose(fp_); + } + }; + } + + + struct PngReader::PngRabi + { + png_structp png_; + png_infop info_; + png_infop endInfo_; + + void Destruct() + { + if (png_) + { + png_destroy_read_struct(&png_, &info_, &endInfo_); + + png_ = NULL; + info_ = NULL; + endInfo_ = NULL; + } + } + + PngRabi() + { + png_ = NULL; + info_ = NULL; + endInfo_ = NULL; + + png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + info_ = png_create_info_struct(png_); + if (!info_) + { + png_destroy_read_struct(&png_, NULL, NULL); + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + endInfo_ = png_create_info_struct(png_); + if (!info_) + { + png_destroy_read_struct(&png_, &info_, NULL); + throw OrthancException(ErrorCode_NotEnoughMemory); + } + } + + ~PngRabi() + { + Destruct(); + } + + static void MemoryCallback(png_structp png_ptr, + png_bytep data, + png_size_t size); + }; + + + void PngReader::CheckHeader(const void* header) + { + int is_png = !png_sig_cmp((png_bytep) header, 0, 8); + if (!is_png) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + + PngReader::PngReader() + { + width_ = 0; + height_ = 0; + pitch_ = 0; + format_ = PixelFormat_Grayscale8; + } + + void PngReader::Read(PngRabi& rabi) + { + png_set_sig_bytes(rabi.png_, 8); + + png_read_info(rabi.png_, rabi.info_); + + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + int compression_type, filter_method; + // get size and bit-depth of the PNG-image + png_get_IHDR(rabi.png_, rabi.info_, + &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + width_ = width; + height_ = height; + + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8) + { + format_ = PixelFormat_Grayscale8; + pitch_ = width_; + } + else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16) + { + format_ = PixelFormat_Grayscale16; + pitch_ = 2 * width_; + + if (Toolbox::DetectEndianness() == Endianness_Little) + { + png_set_swap(rabi.png_); + } + } + else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8) + { + format_ = PixelFormat_Grayscale8; + pitch_ = 3 * width_; + } + else + { + throw OrthancException(ErrorCode_NotImplemented); + } + + buffer_.resize(height_ * pitch_); + + if (height_ == 0 || width_ == 0) + { + // Empty image, we are done + return; + } + + png_read_update_info(rabi.png_, rabi.info_); + + std::vector rows(height_); + for (size_t i = 0; i < height_; i++) + { + rows[i] = &buffer_[0] + i * pitch_; + } + + png_read_image(rabi.png_, &rows[0]); + } + + void PngReader::ReadFromFile(const char* filename) + { + FileRabi f(filename); + + char header[8]; + if (fread(header, 1, 8, f.fp_) != 8) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + + CheckHeader(header); + + PngRabi rabi; + + if (setjmp(png_jmpbuf(rabi.png_))) + { + rabi.Destruct(); + throw OrthancException(ErrorCode_BadFileFormat); + } + + png_init_io(rabi.png_, f.fp_); + + Read(rabi); + } + + + + namespace + { + struct MemoryBuffer + { + const uint8_t* buffer_; + size_t size_; + size_t pos_; + bool ok_; + }; + } + + + void PngReader::PngRabi::MemoryCallback(png_structp png_ptr, + png_bytep outBytes, + png_size_t byteCountToRead) + { + MemoryBuffer* from = reinterpret_cast(png_get_io_ptr(png_ptr)); + + if (!from->ok_) + { + return; + } + + if (from->pos_ + byteCountToRead > from->size_) + { + from->ok_ = false; + return; + } + + memcpy(outBytes, from->buffer_ + from->pos_, byteCountToRead); + + from->pos_ += byteCountToRead; + } + + + void PngReader::ReadFromMemory(const void* buffer, + size_t size) + { + if (size < 8) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + + CheckHeader(buffer); + + PngRabi rabi; + + if (setjmp(png_jmpbuf(rabi.png_))) + { + rabi.Destruct(); + throw OrthancException(ErrorCode_BadFileFormat); + } + + MemoryBuffer tmp; + tmp.buffer_ = reinterpret_cast(buffer) + 8; // We skip the header + tmp.size_ = size - 8; + tmp.pos_ = 0; + tmp.ok_ = true; + + png_set_read_fn(rabi.png_, &tmp, PngRabi::MemoryCallback); + + Read(rabi); + + if (!tmp.ok_) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + + void PngReader::ReadFromMemory(const std::string& buffer) + { + if (buffer.size() != 0) + ReadFromMemory(&buffer[0], buffer.size()); + else + ReadFromMemory(NULL, 0); + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/FileFormats/PngReader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileFormats/PngReader.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,109 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Enumerations.h" + +#include +#include +#include + +namespace Orthanc +{ + class PngReader + { + private: + struct PngRabi; + + PixelFormat format_; + unsigned int width_; + unsigned int height_; + unsigned int pitch_; + std::vector buffer_; + + void CheckHeader(const void* header); + + void Read(PngRabi& rabi); + + public: + PngReader(); + + PixelFormat GetFormat() const + { + return format_; + } + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + unsigned int GetPitch() const + { + return pitch_; + } + + const void* GetBuffer() const + { + if (buffer_.size() > 0) + return &buffer_[0]; + else + return NULL; + } + + const void* GetBuffer(unsigned int y) const + { + if (buffer_.size() > 0) + return &buffer_[y * pitch_]; + else + return NULL; + } + + void ReadFromFile(const char* filename); + + void ReadFromFile(const std::string& filename) + { + ReadFromFile(filename.c_str()); + } + + void ReadFromMemory(const void* buffer, + size_t size); + + void ReadFromMemory(const std::string& buffer); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/FileFormats/PngWriter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileFormats/PngWriter.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,263 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "PngWriter.h" + +#include +#include +#include +#include "../OrthancException.h" +#include "../ChunkedBuffer.h" +#include "../Toolbox.h" + + +// http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-4 +// http://zarb.org/~gc/html/libpng.html +/* + void write_row_callback(png_ptr, png_uint_32 row, int pass) + { + }*/ + + + + +/* bool isError_; + +// http://www.libpng.org/pub/png/book/chapter14.html#png.ch14.div.2 + +static void ErrorHandler(png_structp png, png_const_charp message) +{ +printf("** [%s]\n", message); + +PngWriter* that = (PngWriter*) png_get_error_ptr(png); +that->isError_ = true; +printf("** %d\n", (int)that); + +//((PngWriter*) payload)->isError_ = true; +} + +static void WarningHandler(png_structp png, png_const_charp message) +{ + printf("++ %d\n", (int)message); +}*/ + + +namespace Orthanc +{ + struct PngWriter::PImpl + { + png_structp png_; + png_infop info_; + + // Filled by Prepare() + std::vector rows_; + int bitDepth_; + int colorType_; + }; + + + + PngWriter::PngWriter() : pimpl_(new PImpl) + { + pimpl_->png_ = NULL; + pimpl_->info_ = NULL; + + pimpl_->png_ = png_create_write_struct + (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //this, ErrorHandler, WarningHandler); + if (!pimpl_->png_) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + pimpl_->info_ = png_create_info_struct(pimpl_->png_); + if (!pimpl_->info_) + { + png_destroy_write_struct(&pimpl_->png_, NULL); + throw OrthancException(ErrorCode_NotEnoughMemory); + } + } + + PngWriter::~PngWriter() + { + if (pimpl_->info_) + { + png_destroy_info_struct(pimpl_->png_, &pimpl_->info_); + } + + if (pimpl_->png_) + { + png_destroy_write_struct(&pimpl_->png_, NULL); + } + } + + + + void PngWriter::Prepare(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + pimpl_->rows_.resize(height); + for (unsigned int y = 0; y < height; y++) + { + pimpl_->rows_[y] = const_cast(reinterpret_cast(buffer)) + y * pitch; + } + + switch (format) + { + case PixelFormat_RGB24: + pimpl_->bitDepth_ = 8; + pimpl_->colorType_ = PNG_COLOR_TYPE_RGB; + break; + + case PixelFormat_Grayscale8: + pimpl_->bitDepth_ = 8; + pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; + break; + + case PixelFormat_Grayscale16: + case PixelFormat_SignedGrayscale16: + pimpl_->bitDepth_ = 16; + pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; + break; + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } + + + void PngWriter::Compress(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format) + { + png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height, + pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(pimpl_->png_, pimpl_->info_); + + if (height > 0) + { + switch (format) + { + case PixelFormat_Grayscale16: + case PixelFormat_SignedGrayscale16: + { + int transforms = 0; + if (Toolbox::DetectEndianness() == Endianness_Little) + { + transforms = PNG_TRANSFORM_SWAP_ENDIAN; + } + + png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]); + png_write_png(pimpl_->png_, pimpl_->info_, transforms, NULL); + + break; + } + + default: + png_write_image(pimpl_->png_, &pimpl_->rows_[0]); + } + } + + png_write_end(pimpl_->png_, NULL); + } + + + void PngWriter::WriteToFile(const char* filename, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + Prepare(width, height, pitch, format, buffer); + + FILE* fp = fopen(filename, "wb"); + if (!fp) + { + throw OrthancException(ErrorCode_CannotWriteFile); + } + + png_init_io(pimpl_->png_, fp); + + if (setjmp(png_jmpbuf(pimpl_->png_))) + { + // Error during writing PNG + throw OrthancException(ErrorCode_CannotWriteFile); + } + + Compress(width, height, pitch, format); + + fclose(fp); + } + + + + + static void MemoryCallback(png_structp png_ptr, + png_bytep data, + png_size_t size) + { + ChunkedBuffer* buffer = reinterpret_cast(png_get_io_ptr(png_ptr)); + buffer->AddChunk(reinterpret_cast(data), size); + } + + + + void PngWriter::WriteToMemory(std::string& png, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + ChunkedBuffer chunks; + + Prepare(width, height, pitch, format, buffer); + + if (setjmp(png_jmpbuf(pimpl_->png_))) + { + // Error during writing PNG + throw OrthancException(ErrorCode_InternalError); + } + + png_set_write_fn(pimpl_->png_, &chunks, MemoryCallback, NULL); + + Compress(width, height, pitch, format); + + chunks.Flatten(png); + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/FileFormats/PngWriter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileFormats/PngWriter.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,78 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Enumerations.h" + +#include +#include + +namespace Orthanc +{ + class PngWriter + { + private: + struct PImpl; + boost::shared_ptr pimpl_; + + void Compress(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format); + + void Prepare(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + + public: + PngWriter(); + + ~PngWriter(); + + void WriteToFile(const char* filename, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + + void WriteToMemory(std::string& png, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/CompressedFileStorageAccessor.cpp --- a/Core/FileStorage/CompressedFileStorageAccessor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/CompressedFileStorageAccessor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -42,21 +42,36 @@ size_t size, FileContentType type) { + std::string md5; + + if (storeMD5_) + { + Toolbox::ComputeMD5(md5, data, size); + } + switch (compressionType_) { case CompressionType_None: { std::string uuid = storage_.Create(data, size); - return FileInfo(uuid, type, size); + return FileInfo(uuid, type, size, md5); } case CompressionType_Zlib: { std::string compressed; zlib_.Compress(compressed, data, size); + + std::string compressedMD5; + + if (storeMD5_) + { + Toolbox::ComputeMD5(compressedMD5, compressed); + } + std::string uuid = storage_.Create(compressed); - return FileInfo(uuid, type, size, - CompressionType_Zlib, compressed.size()); + return FileInfo(uuid, type, size, md5, + CompressionType_Zlib, compressed.size(), compressedMD5); } default: diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/CompressedFileStorageAccessor.h --- a/Core/FileStorage/CompressedFileStorageAccessor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/CompressedFileStorageAccessor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/FileInfo.h --- a/Core/FileStorage/FileInfo.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/FileInfo.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -43,9 +43,13 @@ private: std::string uuid_; FileContentType contentType_; + uint64_t uncompressedSize_; + std::string uncompressedMD5_; + CompressionType compressionType_; uint64_t compressedSize_; + std::string compressedMD5_; public: FileInfo() @@ -57,12 +61,15 @@ **/ FileInfo(const std::string& uuid, FileContentType contentType, - uint64_t size) : + uint64_t size, + const std::string& md5) : uuid_(uuid), contentType_(contentType), uncompressedSize_(size), + uncompressedMD5_(md5), compressionType_(CompressionType_None), - compressedSize_(size) + compressedSize_(size), + compressedMD5_(md5) { } @@ -72,13 +79,17 @@ FileInfo(const std::string& uuid, FileContentType contentType, uint64_t uncompressedSize, + const std::string& uncompressedMD5, CompressionType compressionType, - uint64_t compressedSize) : + uint64_t compressedSize, + const std::string& compressedMD5) : uuid_(uuid), contentType_(contentType), uncompressedSize_(uncompressedSize), + uncompressedMD5_(uncompressedMD5), compressionType_(compressionType), - compressedSize_(compressedSize) + compressedSize_(compressedSize), + compressedMD5_(compressedMD5) { } @@ -106,5 +117,15 @@ { return compressedSize_; } + + const std::string& GetCompressedMD5() const + { + return compressedMD5_; + } + + const std::string& GetUncompressedMD5() const + { + return uncompressedMD5_; + } }; } diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/FileStorage.cpp --- a/Core/FileStorage/FileStorage.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/FileStorage.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -267,7 +267,7 @@ List result; ListAllFiles(result); - for (List::const_iterator it = result.begin(); it != result.end(); it++) + for (List::const_iterator it = result.begin(); it != result.end(); ++it) { Remove(*it); } diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/FileStorage.h --- a/Core/FileStorage/FileStorage.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/FileStorage.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/FileStorageAccessor.cpp --- a/Core/FileStorage/FileStorageAccessor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/FileStorageAccessor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -38,6 +38,13 @@ size_t size, FileContentType type) { - return FileInfo(storage_.Create(data, size), type, size); + std::string md5; + + if (storeMD5_) + { + Toolbox::ComputeMD5(md5, data, size); + } + + return FileInfo(storage_.Create(data, size), type, size, md5); } } diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/FileStorageAccessor.h --- a/Core/FileStorage/FileStorageAccessor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/FileStorageAccessor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/StorageAccessor.cpp --- a/Core/FileStorage/StorageAccessor.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/StorageAccessor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/FileStorage/StorageAccessor.h --- a/Core/FileStorage/StorageAccessor.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/FileStorage/StorageAccessor.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -45,15 +45,32 @@ class StorageAccessor : boost::noncopyable { protected: + bool storeMD5_; + virtual FileInfo WriteInternal(const void* data, size_t size, FileContentType type) = 0; public: + StorageAccessor() + { + storeMD5_ = true; + } + virtual ~StorageAccessor() { } + void SetStoreMD5(bool storeMD5) + { + storeMD5_ = storeMD5; + } + + bool IsStoreMD5() const + { + return storeMD5_; + } + FileInfo Write(const void* data, size_t size, FileContentType type) diff -r 63f707278fc8 -r 45b16f67259c Core/HttpClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpClient.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,257 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "HttpClient.h" + +#include "../Core/Toolbox.h" +#include "../Core/OrthancException.h" + +#include +#include + + +namespace Orthanc +{ + struct HttpClient::PImpl + { + CURL* curl_; + struct curl_slist *postHeaders_; + }; + + + static CURLcode CheckCode(CURLcode code) + { + if (code != CURLE_OK) + { + throw OrthancException("libCURL error: " + std::string(curl_easy_strerror(code))); + } + + return code; + } + + + static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *payload) + { + std::string& target = *(static_cast(payload)); + + size_t length = size * nmemb; + if (length == 0) + return 0; + + size_t pos = target.size(); + + target.resize(pos + length); + memcpy(&target.at(pos), buffer, length); + + return length; + } + + + void HttpClient::Setup() + { + pimpl_->postHeaders_ = NULL; + if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + pimpl_->curl_ = curl_easy_init(); + if (!pimpl_->curl_) + { + curl_slist_free_all(pimpl_->postHeaders_); + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1)); + +#if ORTHANC_SSL_ENABLED == 1 + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); +#endif + + // This fixes the "longjmp causes uninitialized stack frame" crash + // that happens on modern Linux versions. + // http://stackoverflow.com/questions/9191668/error-longjmp-causes-uninitialized-stack-frame + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOSIGNAL, 1)); + + url_ = ""; + method_ = HttpMethod_Get; + lastStatus_ = HttpStatus_200_Ok; + isVerbose_ = false; + } + + + HttpClient::HttpClient() : pimpl_(new PImpl) + { + Setup(); + } + + + HttpClient::HttpClient(const HttpClient& other) : pimpl_(new PImpl) + { + Setup(); + + if (other.IsVerbose()) + { + SetVerbose(true); + } + + if (other.credentials_.size() != 0) + { + credentials_ = other.credentials_; + } + } + + + HttpClient::~HttpClient() + { + curl_easy_cleanup(pimpl_->curl_); + curl_slist_free_all(pimpl_->postHeaders_); + } + + + void HttpClient::SetVerbose(bool isVerbose) + { + isVerbose_ = isVerbose; + + if (isVerbose_) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1)); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0)); + } + } + + + bool HttpClient::Apply(std::string& answer) + { + answer.clear(); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, NULL)); + + if (credentials_.size() != 0) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_USERPWD, credentials_.c_str())); + } + + switch (method_) + { + case HttpMethod_Get: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L)); + break; + + case HttpMethod_Post: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->postHeaders_)); + + if (postData_.size() > 0) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, postData_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, postData_.size())); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0)); + } + + break; + + case HttpMethod_Delete: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE")); + break; + + case HttpMethod_Put: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L)); + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + + // Do the actual request + CheckCode(curl_easy_perform(pimpl_->curl_)); + + long status; + CheckCode(curl_easy_getinfo(pimpl_->curl_, CURLINFO_RESPONSE_CODE, &status)); + + if (status == 0) + { + // This corresponds to a call to an inexistent host + lastStatus_ = HttpStatus_500_InternalServerError; + } + else + { + lastStatus_ = static_cast(status); + } + + return (status >= 200 && status < 300); + } + + + bool HttpClient::Apply(Json::Value& answer) + { + std::string s; + if (Apply(s)) + { + Json::Reader reader; + return reader.parse(s, answer); + } + else + { + return false; + } + } + + + void HttpClient::SetCredentials(const char* username, + const char* password) + { + credentials_ = std::string(username) + ":" + std::string(password); + } + + + void HttpClient::GlobalInitialize() + { + CheckCode(curl_global_init(CURL_GLOBAL_DEFAULT)); + } + + void HttpClient::GlobalFinalize() + { + curl_global_cleanup(); + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/HttpClient.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpClient.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,125 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Core/Enumerations.h" + +#include +#include +#include + +namespace Orthanc +{ + class HttpClient + { + private: + struct PImpl; + boost::shared_ptr pimpl_; + + std::string url_; + std::string credentials_; + HttpMethod method_; + HttpStatus lastStatus_; + std::string postData_; + bool isVerbose_; + + void Setup(); + + void operator= (const HttpClient&); // Forbidden + + public: + HttpClient(const HttpClient& base); + + HttpClient(); + + ~HttpClient(); + + void SetUrl(const char* url) + { + url_ = std::string(url); + } + + void SetUrl(const std::string& url) + { + url_ = url; + } + + const std::string& GetUrl() const + { + return url_; + } + + void SetMethod(HttpMethod method) + { + method_ = method; + } + + HttpMethod GetMethod() const + { + return method_; + } + + std::string& AccessPostData() + { + return postData_; + } + + const std::string& AccessPostData() const + { + return postData_; + } + + void SetVerbose(bool isVerbose); + + bool IsVerbose() const + { + return isVerbose_; + } + + bool Apply(std::string& answer); + + bool Apply(Json::Value& answer); + + HttpStatus GetLastStatus() const + { + return lastStatus_; + } + + void SetCredentials(const char* username, + const char* password); + + static void GlobalInitialize(); + + static void GlobalFinalize(); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/BufferHttpSender.h --- a/Core/HttpServer/BufferHttpSender.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/BufferHttpSender.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/EmbeddedResourceHttpHandler.cpp --- a/Core/HttpServer/EmbeddedResourceHttpHandler.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/EmbeddedResourceHttpHandler.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -58,13 +58,13 @@ void EmbeddedResourceHttpHandler::Handle( HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& arguments, const std::string&) { - if (method != Orthanc_HttpMethod_Get) + if (method != HttpMethod_Get) { output.SendMethodNotAllowedError("GET"); return; @@ -79,10 +79,10 @@ size_t size = EmbeddedResources::GetDirectoryResourceSize(resourceId_, resourcePath.c_str()); output.AnswerBufferWithContentType(buffer, size, contentType); } - catch (OrthancException& e) + catch (OrthancException&) { LOG(WARNING) << "Unable to find HTTP resource: " << resourcePath; - output.SendHeader(Orthanc_HttpStatus_404_NotFound); + output.SendHeader(HttpStatus_404_NotFound); } } } diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/EmbeddedResourceHttpHandler.h --- a/Core/HttpServer/EmbeddedResourceHttpHandler.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/EmbeddedResourceHttpHandler.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -54,7 +54,7 @@ virtual void Handle( HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& arguments, diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/FilesystemHttpHandler.cpp --- a/Core/HttpServer/FilesystemHttpHandler.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/FilesystemHttpHandler.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -127,13 +127,13 @@ void FilesystemHttpHandler::Handle( HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& arguments, const std::string&) { - if (method != Orthanc_HttpMethod_Get) + if (method != HttpMethod_Get) { output.SendMethodNotAllowedError("GET"); return; @@ -161,7 +161,7 @@ } else { - output.SendHeader(Orthanc_HttpStatus_404_NotFound); + output.SendHeader(HttpStatus_404_NotFound); } } } diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/FilesystemHttpHandler.h --- a/Core/HttpServer/FilesystemHttpHandler.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/FilesystemHttpHandler.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -56,7 +56,7 @@ virtual void Handle( HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& arguments, diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/FilesystemHttpSender.cpp --- a/Core/HttpServer/FilesystemHttpSender.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/FilesystemHttpSender.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/FilesystemHttpSender.h --- a/Core/HttpServer/FilesystemHttpSender.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/FilesystemHttpSender.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpFileSender.cpp --- a/Core/HttpServer/HttpFileSender.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpFileSender.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -47,7 +47,7 @@ if (!SendData(output)) { - output.SendHeader(Orthanc_HttpStatus_500_InternalServerError); + output.SendHeader(HttpStatus_500_InternalServerError); } } } diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpFileSender.h --- a/Core/HttpServer/HttpFileSender.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpFileSender.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpHandler.cpp --- a/Core/HttpServer/HttpHandler.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpHandler.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpHandler.h --- a/Core/HttpServer/HttpHandler.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpHandler.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -36,7 +36,6 @@ #include #include #include "../Toolbox.h" -#include "../../OrthancCppClient/HttpEnumerations.h" namespace Orthanc { @@ -54,7 +53,7 @@ virtual bool IsServedUri(const UriComponents& uri) = 0; virtual void Handle(HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& getArguments, diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpOutput.cpp --- a/Core/HttpServer/HttpOutput.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpOutput.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -38,7 +38,6 @@ #include #include "../OrthancException.h" #include "../Toolbox.h" -#include "../../OrthancCppClient/HttpException.h" namespace Orthanc { @@ -90,7 +89,7 @@ std::string s = "HTTP/1.1 200 OK\r\n"; for (Header::const_iterator - it = header.begin(); it != header.end(); it++) + it = header.begin(); it != header.end(); ++it) { s += it->first + ": " + it->second + "\r\n"; } @@ -104,17 +103,17 @@ void HttpOutput::SendMethodNotAllowedError(const std::string& allowed) { std::string s = - "HTTP/1.1 405 " + std::string(HttpException::GetDescription(Orthanc_HttpStatus_405_MethodNotAllowed)) + + "HTTP/1.1 405 " + std::string(EnumerationToString(HttpStatus_405_MethodNotAllowed)) + "\r\nAllow: " + allowed + "\r\n\r\n"; Send(&s[0], s.size()); } - void HttpOutput::SendHeader(Orthanc_HttpStatus status) + void HttpOutput::SendHeader(HttpStatus status) { - if (status == Orthanc_HttpStatus_200_Ok || - status == Orthanc_HttpStatus_405_MethodNotAllowed) + if (status == HttpStatus_200_Ok || + status == HttpStatus_405_MethodNotAllowed) { throw OrthancException("Please use the dedicated methods to this HTTP status code in HttpOutput"); } @@ -123,11 +122,11 @@ } - void HttpOutput::SendHeaderInternal(Orthanc_HttpStatus status) + void HttpOutput::SendHeaderInternal(HttpStatus status) { std::string s = "HTTP/1.1 " + boost::lexical_cast(status) + - " " + std::string(HttpException::GetDescription(status)) + + " " + std::string(EnumerationToString(status)) + "\r\n\r\n"; Send(&s[0], s.size()); } @@ -145,7 +144,7 @@ const HttpHandler::Arguments& cookies) { for (HttpHandler::Arguments::const_iterator it = cookies.begin(); - it != cookies.end(); it++) + it != cookies.end(); ++it) { header.push_back(std::make_pair("Set-Cookie", it->first + "=" + it->second)); } @@ -190,7 +189,7 @@ void HttpOutput::Redirect(const std::string& path) { std::string s = - "HTTP/1.1 301 " + std::string(HttpException::GetDescription(Orthanc_HttpStatus_301_MovedPermanently)) + + "HTTP/1.1 301 " + std::string(EnumerationToString(HttpStatus_301_MovedPermanently)) + "\r\nLocation: " + path + "\r\n\r\n"; Send(&s[0], s.size()); diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/HttpOutput.h --- a/Core/HttpServer/HttpOutput.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/HttpOutput.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -45,7 +45,7 @@ private: typedef std::list< std::pair > Header; - void SendHeaderInternal(Orthanc_HttpStatus status); + void SendHeaderInternal(HttpStatus status); void PrepareOkHeader(Header& header, const char* contentType, @@ -74,7 +74,7 @@ void SendMethodNotAllowedError(const std::string& allowed); - void SendHeader(Orthanc_HttpStatus status); + void SendHeader(HttpStatus status); void Redirect(const std::string& path); diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/MongooseServer.cpp --- a/Core/HttpServer/MongooseServer.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/MongooseServer.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -49,6 +49,9 @@ #include "HttpOutput.h" #include "mongoose.h" +#if ORTHANC_SSL_ENABLED == 1 +#include +#endif #define ORTHANC_REALM "Orthanc Secure Area" @@ -129,7 +132,7 @@ void Clear() { for (Content::iterator it = content_.begin(); - it != content_.end(); it++) + it != content_.end(); ++it) { delete *it; } @@ -138,7 +141,7 @@ Content::iterator Find(const std::string& filename) { for (Content::iterator it = content_.begin(); - it != content_.end(); it++) + it != content_.end(); ++it) { if ((*it)->GetFilename() == filename) { @@ -254,7 +257,7 @@ HttpHandler* MongooseServer::FindHandler(const UriComponents& forUri) const { for (Handlers::const_iterator it = - handlers_.begin(); it != handlers_.end(); it++) + handlers_.begin(); it != handlers_.end(); ++it) { if ((*it)->IsServedUri(forUri)) { @@ -268,9 +271,9 @@ - static PostDataStatus ReadPostData(std::string& postData, - struct mg_connection *connection, - const HttpHandler::Arguments& headers) + static PostDataStatus ReadBody(std::string& postData, + struct mg_connection *connection, + const HttpHandler::Arguments& headers) { HttpHandler::Arguments::const_iterator cs = headers.find("content-length"); if (cs == headers.end()) @@ -303,6 +306,7 @@ { return PostDataStatus_Failure; } + assert(r <= length); length -= r; pos += r; @@ -322,7 +326,7 @@ std::string boundary = "--" + contentType.substr(multipartLength); std::string postData; - PostDataStatus status = ReadPostData(postData, connection, headers); + PostDataStatus status = ReadBody(postData, connection, headers); if (status != PostDataStatus_Success) { @@ -485,6 +489,83 @@ } + static bool ExtractMethod(HttpMethod& method, + const struct mg_request_info *request, + const HttpHandler::Arguments& headers, + const HttpHandler::Arguments& argumentsGET) + { + std::string overriden; + + // Check whether some PUT/DELETE faking is done + + // 1. Faking with Google's approach + HttpHandler::Arguments::const_iterator methodOverride = + headers.find("x-http-method-override"); + + if (methodOverride != headers.end()) + { + overriden = methodOverride->second; + } + else if (!strcmp(request->request_method, "GET")) + { + // 2. Faking with Ruby on Rail's approach + // GET /my/resource?_method=delete <=> DELETE /my/resource + methodOverride = argumentsGET.find("_method"); + if (methodOverride != argumentsGET.end()) + { + overriden = methodOverride->second; + } + } + + if (overriden.size() > 0) + { + // A faking has been done within this request + Toolbox::ToUpperCase(overriden); + + LOG(INFO) << "HTTP method faking has been detected for " << overriden; + + if (overriden == "PUT") + { + method = HttpMethod_Put; + return true; + } + else if (overriden == "DELETE") + { + method = HttpMethod_Delete; + return true; + } + else + { + return false; + } + } + + // No PUT/DELETE faking was present + if (!strcmp(request->request_method, "GET")) + { + method = HttpMethod_Get; + } + else if (!strcmp(request->request_method, "POST")) + { + method = HttpMethod_Post; + } + else if (!strcmp(request->request_method, "DELETE")) + { + method = HttpMethod_Delete; + } + else if (!strcmp(request->request_method, "PUT")) + { + method = HttpMethod_Put; + } + else + { + return false; + } + + return true; + } + + static void* Callback(enum mg_event event, struct mg_connection *connection, @@ -492,33 +573,10 @@ { if (event == MG_NEW_REQUEST) { - MongooseServer* that = (MongooseServer*) (request->user_data); + MongooseServer* that = reinterpret_cast(request->user_data); MongooseOutput output(connection); - // Compute the method - Orthanc_HttpMethod method; - if (!strcmp(request->request_method, "GET")) - { - method = Orthanc_HttpMethod_Get; - } - else if (!strcmp(request->request_method, "POST")) - { - method = Orthanc_HttpMethod_Post; - } - else if (!strcmp(request->request_method, "DELETE")) - { - method = Orthanc_HttpMethod_Delete; - } - else if (!strcmp(request->request_method, "PUT")) - { - method = Orthanc_HttpMethod_Put; - } - else - { - output.SendHeader(Orthanc_HttpStatus_405_MethodNotAllowed); - return (void*) ""; - } - + // Check remote calls if (!that->IsRemoteAccessAllowed() && request->remote_ip != LOCALHOST) { @@ -526,8 +584,9 @@ return (void*) ""; } - HttpHandler::Arguments arguments, headers; + // Extract the HTTP headers + HttpHandler::Arguments headers; for (int i = 0; i < request->num_headers; i++) { std::string name = request->http_headers[i].name; @@ -535,6 +594,24 @@ headers.insert(std::make_pair(name, request->http_headers[i].value)); } + + // Extract the GET arguments + HttpHandler::Arguments argumentsGET; + if (!strcmp(request->request_method, "GET")) + { + HttpHandler::ParseGetQuery(argumentsGET, request->query_string); + } + + + // Compute the HTTP method, taking method faking into consideration + HttpMethod method; + if (!ExtractMethod(method, request, headers, argumentsGET)) + { + output.SendHeader(HttpStatus_400_BadRequest); + return (void*) ""; + } + + // Authenticate this connection if (that->IsAuthenticationEnabled() && !Authorize(*that, headers, output)) @@ -564,83 +641,93 @@ } - std::string postData; - - if (method == Orthanc_HttpMethod_Get) + // Extract the body of the request for PUT and POST + std::string body; + if (method == HttpMethod_Post || + method == HttpMethod_Put) { - HttpHandler::ParseGetQuery(arguments, request->query_string); - } - else if (method == Orthanc_HttpMethod_Post || - method == Orthanc_HttpMethod_Put) - { + PostDataStatus status; + HttpHandler::Arguments::const_iterator ct = headers.find("content-type"); if (ct == headers.end()) { - output.SendHeader(Orthanc_HttpStatus_400_BadRequest); - return (void*) ""; - } - - PostDataStatus status; - - std::string contentType = ct->second; - if (contentType.size() >= multipartLength && - !memcmp(contentType.c_str(), multipart, multipartLength)) - { - status = ParseMultipartPost(postData, connection, headers, contentType, that->GetChunkStore()); + // No content-type specified. Assume no multi-part content occurs at this point. + status = ReadBody(body, connection, headers); } else { - status = ReadPostData(postData, connection, headers); + std::string contentType = ct->second; + if (contentType.size() >= multipartLength && + !memcmp(contentType.c_str(), multipart, multipartLength)) + { + status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore()); + } + else + { + status = ReadBody(body, connection, headers); + } } switch (status) { - case PostDataStatus_NoLength: - output.SendHeader(Orthanc_HttpStatus_411_LengthRequired); - return (void*) ""; + case PostDataStatus_NoLength: + output.SendHeader(HttpStatus_411_LengthRequired); + return (void*) ""; - case PostDataStatus_Failure: - output.SendHeader(Orthanc_HttpStatus_400_BadRequest); - return (void*) ""; + case PostDataStatus_Failure: + output.SendHeader(HttpStatus_400_BadRequest); + return (void*) ""; - case PostDataStatus_Pending: - output.AnswerBufferWithContentType(NULL, 0, ""); - return (void*) ""; + case PostDataStatus_Pending: + output.AnswerBufferWithContentType(NULL, 0, ""); + return (void*) ""; - default: - break; + default: + break; } } + + // Call the proper handler for this URI UriComponents uri; - Toolbox::SplitUriComponents(uri, request->uri); + try + { + Toolbox::SplitUriComponents(uri, request->uri); + } + catch (OrthancException) + { + output.SendHeader(HttpStatus_400_BadRequest); + return (void*) ""; + } + HttpHandler* handler = that->FindHandler(uri); if (handler) { try { - handler->Handle(output, method, uri, headers, arguments, postData); + LOG(INFO) << EnumerationToString(method) << " " << Toolbox::FlattenUri(uri); + handler->Handle(output, method, uri, headers, argumentsGET, body); } catch (OrthancException& e) { LOG(ERROR) << "MongooseServer Exception [" << e.What() << "]"; - output.SendHeader(Orthanc_HttpStatus_500_InternalServerError); + output.SendHeader(HttpStatus_500_InternalServerError); } catch (boost::bad_lexical_cast&) { LOG(ERROR) << "MongooseServer Exception: Bad lexical cast"; - output.SendHeader(Orthanc_HttpStatus_400_BadRequest); + output.SendHeader(HttpStatus_400_BadRequest); } catch (std::runtime_error&) { LOG(ERROR) << "MongooseServer Exception: Presumably a bad JSON request"; - output.SendHeader(Orthanc_HttpStatus_400_BadRequest); + output.SendHeader(HttpStatus_400_BadRequest); } } else { - output.SendHeader(Orthanc_HttpStatus_404_NotFound); + output.SendHeader(HttpStatus_404_NotFound); } // Mark as processed @@ -666,6 +753,17 @@ authentication_ = false; ssl_ = false; port_ = 8000; + filter_ = NULL; + +#if ORTHANC_SSL_ENABLED == 1 + // Check for the Heartbleed exploit + // https://en.wikipedia.org/wiki/OpenSSL#Heartbleed_bug + if (OPENSSL_VERSION_NUMBER < 0x1000107fL /* openssl-1.0.1g */ && + OPENSSL_VERSION_NUMBER >= 0x1000100fL /* openssl-1.0.1 */) + { + LOG(WARNING) << "This version of OpenSSL is vulnerable to the Heartbleed exploit"; + } +#endif } @@ -731,7 +829,7 @@ Stop(); for (Handlers::iterator it = - handlers_.begin(); it != handlers_.end(); it++) + handlers_.begin(); it != handlers_.end(); ++it) { delete *it; } diff -r 63f707278fc8 -r 45b16f67259c Core/HttpServer/MongooseServer.h --- a/Core/HttpServer/MongooseServer.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/HttpServer/MongooseServer.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -51,7 +51,7 @@ { } - virtual bool IsAllowed(Orthanc_HttpMethod method, + virtual bool IsAllowed(HttpMethod method, const char* uri, const char* ip, const char* username) const = 0; diff -r 63f707278fc8 -r 45b16f67259c Core/ICommand.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/ICommand.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,48 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "IDynamicObject.h" + +namespace Orthanc +{ + /** + * This class is the base class for the "Command" design pattern. + * http://en.wikipedia.org/wiki/Command_pattern + **/ + class ICommand : public IDynamicObject + { + public: + virtual bool Execute() = 0; + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/IDynamicObject.h --- a/Core/IDynamicObject.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/IDynamicObject.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Lua/LuaContext.cpp --- a/Core/Lua/LuaContext.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Lua/LuaContext.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -42,11 +42,18 @@ namespace Orthanc { - int LuaContext::PrintToLog(lua_State *L) + int LuaContext::PrintToLog(lua_State *state) { + // Get the pointer to the "LuaContext" underlying object + lua_getglobal(state, "_LuaContext"); + assert(lua_type(state, -1) == LUA_TLIGHTUSERDATA); + LuaContext* that = const_cast(reinterpret_cast(lua_topointer(state, -1))); + assert(that != NULL); + lua_pop(state, 1); + // http://medek.wordpress.com/2009/02/03/wrapping-lua-errors-and-print-function/ - int nArgs = lua_gettop(L); - lua_getglobal(L, "tostring"); + int nArgs = lua_gettop(state); + lua_getglobal(state, "tostring"); // Make sure you start at 1 *NOT* 0 for arrays in Lua. std::string result; @@ -54,10 +61,10 @@ for (int i = 1; i <= nArgs; i++) { const char *s; - lua_pushvalue(L, -1); - lua_pushvalue(L, i); - lua_call(L, 1, 1); - s = lua_tostring(L, -1); + lua_pushvalue(state, -1); + lua_pushvalue(state, i); + lua_call(state, 1, 1); + s = lua_tostring(state, -1); if (result.size() > 0) result.append(", "); @@ -67,10 +74,12 @@ else result.append(s); - lua_pop(L, 1); + lua_pop(state, 1); } LOG(INFO) << "Lua says: " << result; + that->log_.append(result); + that->log_.append("\n"); return 0; } @@ -86,6 +95,9 @@ luaL_openlibs(lua_); lua_register(lua_, "print", PrintToLog); + + lua_pushlightuserdata(lua_, this); + lua_setglobal(lua_, "_LuaContext"); } @@ -95,12 +107,12 @@ } - void LuaContext::Execute(const std::string& command) + void LuaContext::Execute(std::string* output, + const std::string& command) { boost::mutex::scoped_lock lock(mutex_); - lua_settop(lua_, 0); - + log_.clear(); int error = (luaL_loadbuffer(lua_, command.c_str(), command.size(), "line") || lua_pcall(lua_, 0, 0, 0)); @@ -112,6 +124,11 @@ lua_pop(lua_, 1); /* pop error message from the stack */ throw LuaException(description); } + + if (output != NULL) + { + *output = log_; + } } diff -r 63f707278fc8 -r 45b16f67259c Core/Lua/LuaContext.h --- a/Core/Lua/LuaContext.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Lua/LuaContext.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -53,15 +53,28 @@ lua_State *lua_; boost::mutex mutex_; + std::string log_; static int PrintToLog(lua_State *L); + void Execute(std::string* output, + const std::string& command); + public: LuaContext(); ~LuaContext(); - void Execute(const std::string& command); + void Execute(const std::string& command) + { + Execute(NULL, command); + } + + void Execute(std::string& output, + const std::string& command) + { + Execute(&output, command); + } void Execute(EmbeddedResources::FileResourceId resource); diff -r 63f707278fc8 -r 45b16f67259c Core/Lua/LuaException.h --- a/Core/Lua/LuaException.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Lua/LuaException.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/Lua/LuaFunctionCall.cpp --- a/Core/Lua/LuaFunctionCall.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Lua/LuaFunctionCall.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -130,7 +130,7 @@ Json::Value::Members members = value.getMemberNames(); for (Json::Value::Members::const_iterator - it = members.begin(); it != members.end(); it++) + it = members.begin(); it != members.end(); ++it) { // Push the index of the cell lua_pushstring(context_.lua_, it->c_str()); diff -r 63f707278fc8 -r 45b16f67259c Core/Lua/LuaFunctionCall.h --- a/Core/Lua/LuaFunctionCall.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Lua/LuaFunctionCall.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ArrayFilledByThreads.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ArrayFilledByThreads.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,121 @@ +#include "ArrayFilledByThreads.h" + +#include "../MultiThreading/ThreadedCommandProcessor.h" +#include "../OrthancException.h" + +namespace Orthanc +{ + class ArrayFilledByThreads::Command : public ICommand + { + private: + ArrayFilledByThreads& that_; + size_t index_; + + public: + Command(ArrayFilledByThreads& that, + size_t index) : + that_(that), + index_(index) + { + } + + virtual bool Execute() + { + std::auto_ptr obj(that_.filler_.GetFillerItem(index_)); + if (obj.get() == NULL) + { + return false; + } + else + { + boost::mutex::scoped_lock lock(that_.mutex_); + that_.array_[index_] = obj.release(); + return true; + } + } + }; + + void ArrayFilledByThreads::Clear() + { + for (size_t i = 0; i < array_.size(); i++) + { + if (array_[i]) + delete array_[i]; + } + + array_.clear(); + filled_ = false; + } + + void ArrayFilledByThreads::Update() + { + if (!filled_) + { + array_.resize(filler_.GetFillerSize()); + + Orthanc::ThreadedCommandProcessor processor(threadCount_); + for (size_t i = 0; i < array_.size(); i++) + { + processor.Post(new Command(*this, i)); + } + + processor.Join(); + filled_ = true; + } + } + + + ArrayFilledByThreads::ArrayFilledByThreads(IFiller& filler) : filler_(filler) + { + filled_ = false; + threadCount_ = 4; + } + + + ArrayFilledByThreads::~ArrayFilledByThreads() + { + Clear(); + } + + + void ArrayFilledByThreads::Reload() + { + Clear(); + Update(); + } + + + void ArrayFilledByThreads::Invalidate() + { + Clear(); + } + + + void ArrayFilledByThreads::SetThreadCount(unsigned int t) + { + if (t < 1) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + threadCount_ = t; + } + + + size_t ArrayFilledByThreads::GetSize() + { + Update(); + return array_.size(); + } + + + IDynamicObject& ArrayFilledByThreads::GetItem(size_t index) + { + if (index >= GetSize()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + return *array_[index]; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ArrayFilledByThreads.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ArrayFilledByThreads.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include "../IDynamicObject.h" + +namespace Orthanc +{ + class ArrayFilledByThreads + { + public: + class IFiller + { + public: + virtual size_t GetFillerSize() = 0; + + virtual IDynamicObject* GetFillerItem(size_t index) = 0; + }; + + private: + IFiller& filler_; + boost::mutex mutex_; + std::vector array_; + bool filled_; + unsigned int threadCount_; + + class Command; + + void Clear(); + + void Update(); + + public: + ArrayFilledByThreads(IFiller& filler); + + ~ArrayFilledByThreads(); + + void Reload(); + + void Invalidate(); + + void SetThreadCount(unsigned int t); + + unsigned int GetThreadCount() const + { + return threadCount_; + } + + size_t GetSize(); + + IDynamicObject& GetItem(size_t index); + }; +} + diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/BagOfRunnablesBySteps.cpp --- a/Core/MultiThreading/BagOfRunnablesBySteps.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/MultiThreading/BagOfRunnablesBySteps.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -102,7 +102,11 @@ assert(t.get() != NULL); assert(bag->pimpl_->activeThreads_.find(r.get()) == bag->pimpl_->activeThreads_.end()); - t->join(); + if (t->joinable()) + { + t->join(); + } + bag->pimpl_->oneThreadIsJoined_.notify_one(); } @@ -128,7 +132,11 @@ // Stop the finish listener pimpl_->stopFinishListener_ = true; pimpl_->oneThreadIsStopped_.notify_one(); // Awakens the listener - pimpl_->finishListener_->join(); + + if (pimpl_->finishListener_->joinable()) + { + pimpl_->finishListener_->join(); + } } diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/BagOfRunnablesBySteps.h --- a/Core/MultiThreading/BagOfRunnablesBySteps.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/MultiThreading/BagOfRunnablesBySteps.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ILockable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ILockable.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,50 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include + +namespace Orthanc +{ + class ILockable : public boost::noncopyable + { + public: + virtual ~ILockable() + { + } + + virtual void Lock() = 0; + + virtual void Unlock() = 0; + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/IRunnableBySteps.h --- a/Core/MultiThreading/IRunnableBySteps.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/MultiThreading/IRunnableBySteps.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/Locker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/Locker.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,55 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "ILockable.h" + +namespace Orthanc +{ + class Locker + { + private: + ILockable& lockable_; + + public: + Locker(ILockable& lockable) : lockable_(lockable) + { + lockable_.Lock(); + } + + virtual ~Locker() + { + lockable_.Unlock(); + } + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/Mutex.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/Mutex.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,120 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Mutex.h" + +#include "../OrthancException.h" + +#if defined(_WIN32) +#include +#elif defined(__linux) +#include +#else +#error Support your platform here +#endif + +namespace Orthanc +{ +#if defined (_WIN32) + + struct Mutex::PImpl + { + CRITICAL_SECTION criticalSection_; + }; + + Mutex::Mutex() + { + pimpl_ = new PImpl; + ::InitializeCriticalSection(&pimpl_->criticalSection_); + } + + Mutex::~Mutex() + { + ::DeleteCriticalSection(&pimpl_->criticalSection_); + delete pimpl_; + } + + void Mutex::Lock() + { + ::EnterCriticalSection(&pimpl_->criticalSection_); + } + + void Mutex::Unlock() + { + ::LeaveCriticalSection(&pimpl_->criticalSection_); + } + + +#elif defined(__linux) + + struct Mutex::PImpl + { + pthread_mutex_t mutex_; + }; + + Mutex::Mutex() + { + pimpl_ = new PImpl; + + if (pthread_mutex_init(&pimpl_->mutex_, NULL) != 0) + { + delete pimpl_; + throw OrthancException(ErrorCode_InternalError); + } + } + + Mutex::~Mutex() + { + pthread_mutex_destroy(&pimpl_->mutex_); + delete pimpl_; + } + + void Mutex::Lock() + { + if (pthread_mutex_lock(&pimpl_->mutex_) != 0) + { + throw OrthancException(ErrorCode_InternalError); + } + } + + void Mutex::Unlock() + { + if (pthread_mutex_unlock(&pimpl_->mutex_) != 0) + { + throw OrthancException(ErrorCode_InternalError); + } + } + +#else +#error Support your plateform here +#endif +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/Mutex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/Mutex.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,55 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "ILockable.h" + +namespace Orthanc +{ + class Mutex : public ILockable + { + private: + struct PImpl; + + PImpl *pimpl_; + + public: + Mutex(); + + ~Mutex(); + + virtual void Lock(); + + virtual void Unlock(); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ReaderWriterLock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ReaderWriterLock.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,122 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "ReaderWriterLock.h" + +#include + +namespace Orthanc +{ + namespace + { + // Anonymous namespace to avoid clashes between compilation + // modules. + + class ReaderLockable : public ILockable + { + private: + boost::shared_mutex& lock_; + + public: + ReaderLockable(boost::shared_mutex& lock) : lock_(lock) + { + } + + virtual void Lock() + { + lock_.lock_shared(); + } + + virtual void Unlock() + { + lock_.unlock_shared(); + } + }; + + + class WriterLockable : public ILockable + { + private: + boost::shared_mutex& lock_; + + public: + WriterLockable(boost::shared_mutex& lock) : lock_(lock) + { + } + + virtual void Lock() + { + lock_.lock(); + } + + virtual void Unlock() + { + lock_.unlock(); + } + }; + } + + struct ReaderWriterLock::PImpl + { + boost::shared_mutex lock_; + ReaderLockable reader_; + WriterLockable writer_; + + PImpl() : reader_(lock_), writer_(lock_) + { + } + }; + + + ReaderWriterLock::ReaderWriterLock() + { + pimpl_ = new PImpl; + } + + + ReaderWriterLock::~ReaderWriterLock() + { + delete pimpl_; + } + + + ILockable& ReaderWriterLock::ForReader() + { + return pimpl_->reader_; + } + + + ILockable& ReaderWriterLock::ForWriter() + { + return pimpl_->writer_; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ReaderWriterLock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ReaderWriterLock.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,55 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "ILockable.h" + +namespace Orthanc +{ + class ReaderWriterLock + { + private: + struct PImpl; + + PImpl *pimpl_; + + public: + ReaderWriterLock(); + + virtual ~ReaderWriterLock(); + + ILockable& ForReader(); + + ILockable& ForWriter(); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/SharedMessageQueue.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/SharedMessageQueue.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,126 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "SharedMessageQueue.h" + +namespace Orthanc +{ + SharedMessageQueue::SharedMessageQueue(unsigned int maxSize) + { + maxSize_ = maxSize; + } + + + SharedMessageQueue::~SharedMessageQueue() + { + for (Queue::iterator it = queue_.begin(); it != queue_.end(); ++it) + { + delete *it; + } + } + + + void SharedMessageQueue::Enqueue(IDynamicObject* message) + { + boost::mutex::scoped_lock lock(mutex_); + + if (maxSize_ != 0 && queue_.size() > maxSize_) + { + // Too many elements in the queue: First remove the oldest + delete queue_.front(); + queue_.pop_front(); + } + + queue_.push_back(message); + elementAvailable_.notify_one(); + } + + + IDynamicObject* SharedMessageQueue::Dequeue(int32_t millisecondsTimeout) + { + boost::mutex::scoped_lock lock(mutex_); + + // Wait for a message to arrive in the FIFO queue + while (queue_.empty()) + { + if (millisecondsTimeout == 0) + { + elementAvailable_.wait(lock); + } + else + { + bool success = elementAvailable_.timed_wait + (lock, boost::posix_time::milliseconds(millisecondsTimeout)); + if (!success) + { + return NULL; + } + } + } + + std::auto_ptr message(queue_.front()); + queue_.pop_front(); + + if (queue_.empty()) + { + emptied_.notify_all(); + } + + return message.release(); + } + + + + bool SharedMessageQueue::WaitEmpty(int32_t millisecondsTimeout) + { + boost::mutex::scoped_lock lock(mutex_); + + // Wait for the queue to become empty + while (!queue_.empty()) + { + if (millisecondsTimeout == 0) + { + emptied_.wait(lock); + } + else + { + if (!emptied_.timed_wait + (lock, boost::posix_time::milliseconds(millisecondsTimeout))) + { + return false; + } + } + } + + return true; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/SharedMessageQueue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/SharedMessageQueue.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,67 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../IDynamicObject.h" + +#include +#include +#include + +namespace Orthanc +{ + class SharedMessageQueue + { + private: + typedef std::list Queue; + + unsigned int maxSize_; + Queue queue_; + boost::mutex mutex_; + boost::condition_variable elementAvailable_; + boost::condition_variable emptied_; + + public: + SharedMessageQueue(unsigned int maxSize = 0); + + ~SharedMessageQueue(); + + // This transfers the ownership of the message + void Enqueue(IDynamicObject* message); + + // The caller is responsible to delete the dequeud message! + IDynamicObject* Dequeue(int32_t millisecondsTimeout); + + bool WaitEmpty(int32_t millisecondsTimeout); + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ThreadedCommandProcessor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ThreadedCommandProcessor.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,210 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "ThreadedCommandProcessor.h" + +#include "../OrthancException.h" + +namespace Orthanc +{ + static const int32_t TIMEOUT = 10; + + + void ThreadedCommandProcessor::Processor(ThreadedCommandProcessor* that) + { + while (!that->done_) + { + std::auto_ptr command(that->queue_.Dequeue(TIMEOUT)); + + if (command.get() != NULL) + { + bool success = false; + + try + { + if (that->success_) + { + // No command has failed so far + + if (that->cancel_) + { + // The commands have been canceled. Skip the execution + // of this command, yet mark it as succeeded. + success = true; + } + else + { + success = dynamic_cast(*command).Execute(); + } + } + else + { + // A command has already failed. Skip the execution of this command. + } + } + catch (OrthancException) + { + } + + { + boost::mutex::scoped_lock lock(that->mutex_); + assert(that->remainingCommands_ > 0); + that->remainingCommands_--; + + if (!success) + { + if (!that->cancel_ && that->listener_ && that->success_) + { + // This is the first command that fails + that->listener_->SignalFailure(); + } + + that->success_ = false; + } + else + { + if (!that->cancel_ && that->listener_) + { + if (that->remainingCommands_ == 0) + { + that->listener_->SignalSuccess(that->totalCommands_); + } + else + { + that->listener_->SignalProgress(that->totalCommands_ - that->remainingCommands_, + that->totalCommands_); + } + } + } + + that->processedCommand_.notify_all(); + } + } + } + } + + + ThreadedCommandProcessor::ThreadedCommandProcessor(unsigned int numThreads) + { + if (numThreads < 1) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + listener_ = NULL; + success_ = true; + done_ = false; + cancel_ = false; + threads_.resize(numThreads); + remainingCommands_ = 0; + totalCommands_ = 0; + + for (unsigned int i = 0; i < numThreads; i++) + { + threads_[i] = new boost::thread(Processor, this); + } + } + + + ThreadedCommandProcessor::~ThreadedCommandProcessor() + { + done_ = true; + + for (unsigned int i = 0; i < threads_.size(); i++) + { + boost::thread* t = threads_[i]; + + if (t != NULL) + { + if (t->joinable()) + { + t->join(); + } + + delete t; + } + } + } + + + void ThreadedCommandProcessor::Post(ICommand* command) + { + if (command == NULL) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + boost::mutex::scoped_lock lock(mutex_); + queue_.Enqueue(command); + remainingCommands_++; + totalCommands_++; + } + + + bool ThreadedCommandProcessor::Join() + { + boost::mutex::scoped_lock lock(mutex_); + + while (!remainingCommands_ == 0) + { + processedCommand_.wait(lock); + } + + if (cancel_ && listener_) + { + listener_->SignalCancel(); + } + + // Reset the sequence counters for subsequent commands + bool hasSucceeded = success_; + success_ = true; + totalCommands_ = 0; + cancel_ = false; + + return hasSucceeded; + } + + + void ThreadedCommandProcessor::Cancel() + { + boost::mutex::scoped_lock lock(mutex_); + + cancel_ = true; + } + + + void ThreadedCommandProcessor::SetListener(IListener& listener) + { + boost::mutex::scoped_lock lock(mutex_); + listener_ = &listener; + } +} diff -r 63f707278fc8 -r 45b16f67259c Core/MultiThreading/ThreadedCommandProcessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/ThreadedCommandProcessor.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,94 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../ICommand.h" + +#include "SharedMessageQueue.h" + +namespace Orthanc +{ + class ThreadedCommandProcessor + { + public: + class IListener + { + public: + virtual ~IListener() + { + } + + virtual void SignalProgress(unsigned int current, + unsigned int total) = 0; + + virtual void SignalSuccess(unsigned int total) = 0; + + virtual void SignalFailure() = 0; + + virtual void SignalCancel() = 0; + }; + + private: + SharedMessageQueue queue_; + bool done_; + bool cancel_; + std::vector threads_; + IListener* listener_; + + boost::mutex mutex_; + bool success_; + unsigned int remainingCommands_, totalCommands_; + boost::condition_variable processedCommand_; + + static void Processor(ThreadedCommandProcessor* that); + + public: + ThreadedCommandProcessor(unsigned int numThreads); + + ~ThreadedCommandProcessor(); + + // This takes the ownership of the command + void Post(ICommand* command); + + bool Join(); + + void Cancel(); + + void SetListener(IListener& listener); + + IListener& GetListener() const + { + return *listener_; + } + }; +} diff -r 63f707278fc8 -r 45b16f67259c Core/OrthancException.cpp --- a/Core/OrthancException.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/OrthancException.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -102,6 +102,15 @@ case ErrorCode_BadRequest: return "Bad request"; + case ErrorCode_NetworkProtocol: + return "Error in the network protocol"; + + case ErrorCode_CorruptedFile: + return "Corrupted file (inconsistent MD5 hash)"; + + case ErrorCode_InexistentTag: + return "Inexistent tag"; + case ErrorCode_Custom: default: return "???"; diff -r 63f707278fc8 -r 45b16f67259c Core/OrthancException.h --- a/Core/OrthancException.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/OrthancException.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -46,21 +46,20 @@ public: static const char* GetDescription(ErrorCode error); - OrthancException(const char* custom) + OrthancException(const char* custom) : + error_(ErrorCode_Custom), + custom_(custom) { - error_ = ErrorCode_Custom; - custom_ = custom; } - OrthancException(const std::string& custom) + OrthancException(const std::string& custom) : + error_(ErrorCode_Custom), + custom_(custom) { - error_ = ErrorCode_Custom; - custom_ = custom; } - OrthancException(ErrorCode error) + OrthancException(ErrorCode error) : error_(error) { - error_ = error; } ErrorCode GetErrorCode() const diff -r 63f707278fc8 -r 45b16f67259c Core/PngWriter.cpp --- a/Core/PngWriter.cpp Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * In addition, as a special exception, the copyright holders of this - * program give permission to link the code of its release with the - * OpenSSL project's "OpenSSL" library (or with modified versions of it - * that use the same license as the "OpenSSL" library), and distribute - * the linked executables. You must obey the GNU General Public License - * in all respects for all of the code used other than "OpenSSL". If you - * modify file(s) with this exception, you may extend this exception to - * your version of the file(s), but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source files - * in the program, then also delete it here. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - **/ - - -#include "PngWriter.h" - -#include -#include -#include -#include "OrthancException.h" -#include "ChunkedBuffer.h" - - -// http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-4 -// http://zarb.org/~gc/html/libpng.html -/* - void write_row_callback(png_ptr, png_uint_32 row, int pass) - { - }*/ - - - - -/* bool isError_; - -// http://www.libpng.org/pub/png/book/chapter14.html#png.ch14.div.2 - -static void ErrorHandler(png_structp png, png_const_charp message) -{ -printf("** [%s]\n", message); - -PngWriter* that = (PngWriter*) png_get_error_ptr(png); -that->isError_ = true; -printf("** %d\n", (int)that); - -//((PngWriter*) payload)->isError_ = true; -} - -static void WarningHandler(png_structp png, png_const_charp message) -{ - printf("++ %d\n", (int)message); -}*/ - - -namespace Orthanc -{ - struct PngWriter::PImpl - { - png_structp png_; - png_infop info_; - - // Filled by Prepare() - std::vector rows_; - int bitDepth_; - int colorType_; - }; - - - - PngWriter::PngWriter() : pimpl_(new PImpl) - { - pimpl_->png_ = NULL; - pimpl_->info_ = NULL; - - pimpl_->png_ = png_create_write_struct - (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //this, ErrorHandler, WarningHandler); - if (!pimpl_->png_) - { - throw OrthancException(ErrorCode_NotEnoughMemory); - } - - pimpl_->info_ = png_create_info_struct(pimpl_->png_); - if (!pimpl_->info_) - { - png_destroy_write_struct(&pimpl_->png_, NULL); - throw OrthancException(ErrorCode_NotEnoughMemory); - } - } - - PngWriter::~PngWriter() - { - if (pimpl_->info_) - { - png_destroy_info_struct(pimpl_->png_, &pimpl_->info_); - } - - if (pimpl_->png_) - { - png_destroy_write_struct(&pimpl_->png_, NULL); - } - } - - - - void PngWriter::Prepare(unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer) - { - pimpl_->rows_.resize(height); - for (unsigned int y = 0; y < height; y++) - { - pimpl_->rows_[y] = const_cast(reinterpret_cast(buffer)) + y * pitch; - } - - switch (format) - { - case PixelFormat_RGB24: - pimpl_->bitDepth_ = 8; - pimpl_->colorType_ = PNG_COLOR_TYPE_RGB; - break; - - case PixelFormat_Grayscale8: - pimpl_->bitDepth_ = 8; - pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; - break; - - case PixelFormat_Grayscale16: - pimpl_->bitDepth_ = 16; - pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; - break; - - default: - throw OrthancException(ErrorCode_NotImplemented); - } - } - - - void PngWriter::Compress(unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format) - { - png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height, - pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - png_write_info(pimpl_->png_, pimpl_->info_); - - if (height > 0) - { - switch (format) - { - case PixelFormat_Grayscale16: - // Must swap the endianness!! - png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]); - png_write_png(pimpl_->png_, pimpl_->info_, PNG_TRANSFORM_SWAP_ENDIAN, NULL); - break; - - default: - png_write_image(pimpl_->png_, &pimpl_->rows_[0]); - } - } - - png_write_end(pimpl_->png_, NULL); - } - - - void PngWriter::WriteToFile(const char* filename, - unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer) - { - Prepare(width, height, pitch, format, buffer); - - FILE* fp = fopen(filename, "wb"); - if (!fp) - { - throw OrthancException(ErrorCode_CannotWriteFile); - } - - png_init_io(pimpl_->png_, fp); - - if (setjmp(png_jmpbuf(pimpl_->png_))) - { - // Error during writing PNG - throw OrthancException(ErrorCode_CannotWriteFile); - } - - Compress(width, height, pitch, format); - - fclose(fp); - } - - - - - static void MemoryCallback(png_structp png_ptr, - png_bytep data, - png_size_t size) - { - ChunkedBuffer* buffer = (ChunkedBuffer*) png_get_io_ptr(png_ptr); - buffer->AddChunk(reinterpret_cast(data), size); - } - - - - void PngWriter::WriteToMemory(std::string& png, - unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer) - { - ChunkedBuffer chunks; - - Prepare(width, height, pitch, format, buffer); - - if (setjmp(png_jmpbuf(pimpl_->png_))) - { - // Error during writing PNG - throw OrthancException(ErrorCode_InternalError); - } - - png_set_write_fn(pimpl_->png_, &chunks, MemoryCallback, NULL); - - Compress(width, height, pitch, format); - - chunks.Flatten(png); - } -} diff -r 63f707278fc8 -r 45b16f67259c Core/PngWriter.h --- a/Core/PngWriter.h Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * In addition, as a special exception, the copyright holders of this - * program give permission to link the code of its release with the - * OpenSSL project's "OpenSSL" library (or with modified versions of it - * that use the same license as the "OpenSSL" library), and distribute - * the linked executables. You must obey the GNU General Public License - * in all respects for all of the code used other than "OpenSSL". If you - * modify file(s) with this exception, you may extend this exception to - * your version of the file(s), but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source files - * in the program, then also delete it here. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - **/ - - -#pragma once - -#include "Enumerations.h" - -#include -#include - -namespace Orthanc -{ - class PngWriter - { - private: - struct PImpl; - boost::shared_ptr pimpl_; - - void Compress(unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format); - - void Prepare(unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer); - - public: - PngWriter(); - - ~PngWriter(); - - void WriteToFile(const char* filename, - unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer); - - void WriteToMemory(std::string& png, - unsigned int width, - unsigned int height, - unsigned int pitch, - PixelFormat format, - const void* buffer); - }; -} diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApi.cpp --- a/Core/RestApi/RestApi.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApi.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -51,7 +51,7 @@ result.clear(); for (HttpHandler::Arguments::const_iterator - it = getArguments_->begin(); it != getArguments_->end(); it++) + it = getArguments_.begin(); it != getArguments_.end(); ++it) { result[it->first] = it->second; } @@ -63,7 +63,7 @@ bool RestApi::IsGetAccepted(const UriComponents& uri) { for (GetHandlers::const_iterator it = getHandlers_.begin(); - it != getHandlers_.end(); it++) + it != getHandlers_.end(); ++it) { if (it->first->Match(uri)) { @@ -77,7 +77,7 @@ bool RestApi::IsPutAccepted(const UriComponents& uri) { for (PutHandlers::const_iterator it = putHandlers_.begin(); - it != putHandlers_.end(); it++) + it != putHandlers_.end(); ++it) { if (it->first->Match(uri)) { @@ -91,7 +91,7 @@ bool RestApi::IsPostAccepted(const UriComponents& uri) { for (PostHandlers::const_iterator it = postHandlers_.begin(); - it != postHandlers_.end(); it++) + it != postHandlers_.end(); ++it) { if (it->first->Match(uri)) { @@ -105,7 +105,7 @@ bool RestApi::IsDeleteAccepted(const UriComponents& uri) { for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); - it != deleteHandlers_.end(); it++) + it != deleteHandlers_.end(); ++it) { if (it->first->Match(uri)) { @@ -147,25 +147,25 @@ RestApi::~RestApi() { for (GetHandlers::iterator it = getHandlers_.begin(); - it != getHandlers_.end(); it++) + it != getHandlers_.end(); ++it) { delete it->first; } for (PutHandlers::iterator it = putHandlers_.begin(); - it != putHandlers_.end(); it++) + it != putHandlers_.end(); ++it) { delete it->first; } for (PostHandlers::iterator it = postHandlers_.begin(); - it != postHandlers_.end(); it++) + it != postHandlers_.end(); ++it) { delete it->first; } for (DeleteHandlers::iterator it = deleteHandlers_.begin(); - it != deleteHandlers_.end(); it++) + it != deleteHandlers_.end(); ++it) { delete it->first; } @@ -180,7 +180,7 @@ } void RestApi::Handle(HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& getArguments, @@ -191,88 +191,58 @@ RestApiPath::Components components; UriComponents trailing; - if (method == Orthanc_HttpMethod_Get) + if (method == HttpMethod_Get) { for (GetHandlers::const_iterator it = getHandlers_.begin(); - it != getHandlers_.end(); it++) + it != getHandlers_.end(); ++it) { if (it->first->Match(components, trailing, uri)) { - LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri); + //LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri); ok = true; - GetCall call; - call.output_ = &restOutput; - call.context_ = this; - call.httpHeaders_ = &headers; - call.uriComponents_ = &components; - call.trailing_ = &trailing; - call.fullUri_ = &uri; - - call.getArguments_ = &getArguments; + GetCall call(restOutput, *this, headers, components, trailing, uri, getArguments); it->second(call); } } } - else if (method == Orthanc_HttpMethod_Put) + else if (method == HttpMethod_Put) { for (PutHandlers::const_iterator it = putHandlers_.begin(); - it != putHandlers_.end(); it++) + it != putHandlers_.end(); ++it) { if (it->first->Match(components, trailing, uri)) { - LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri); + //LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri); ok = true; - PutCall call; - call.output_ = &restOutput; - call.context_ = this; - call.httpHeaders_ = &headers; - call.uriComponents_ = &components; - call.trailing_ = &trailing; - call.fullUri_ = &uri; - - call.data_ = &postData; + PutCall call(restOutput, *this, headers, components, trailing, uri, postData); it->second(call); } } } - else if (method == Orthanc_HttpMethod_Post) + else if (method == HttpMethod_Post) { for (PostHandlers::const_iterator it = postHandlers_.begin(); - it != postHandlers_.end(); it++) + it != postHandlers_.end(); ++it) { if (it->first->Match(components, trailing, uri)) { - LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri); + //LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri); ok = true; - PostCall call; - call.output_ = &restOutput; - call.context_ = this; - call.httpHeaders_ = &headers; - call.uriComponents_ = &components; - call.trailing_ = &trailing; - call.fullUri_ = &uri; - - call.data_ = &postData; + PostCall call(restOutput, *this, headers, components, trailing, uri, postData); it->second(call); } } } - else if (method == Orthanc_HttpMethod_Delete) + else if (method == HttpMethod_Delete) { for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); - it != deleteHandlers_.end(); it++) + it != deleteHandlers_.end(); ++it) { if (it->first->Match(components, trailing, uri)) { - LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri); + //LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri); ok = true; - DeleteCall call; - call.output_ = &restOutput; - call.context_ = this; - call.httpHeaders_ = &headers; - call.uriComponents_ = &components; - call.trailing_ = &trailing; - call.fullUri_ = &uri; + DeleteCall call(restOutput, *this, headers, components, trailing, uri); it->second(call); } } @@ -280,7 +250,8 @@ if (!ok) { - LOG(INFO) << "REST method " << method << " not allowed on: " << Toolbox::FlattenUri(uri); + LOG(INFO) << "REST method " << EnumerationToString(method) + << " not allowed on: " << Toolbox::FlattenUri(uri); output.SendMethodNotAllowedError(GetAcceptedMethods(uri)); } } diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApi.h --- a/Core/RestApi/RestApi.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApi.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -48,12 +48,27 @@ friend class RestApi; private: - RestApiOutput* output_; - RestApi* context_; - const HttpHandler::Arguments* httpHeaders_; - const RestApiPath::Components* uriComponents_; - const UriComponents* trailing_; - const UriComponents* fullUri_; + RestApiOutput& output_; + RestApi& context_; + const HttpHandler::Arguments& httpHeaders_; + const RestApiPath::Components& uriComponents_; + const UriComponents& trailing_; + const UriComponents& fullUri_; + + Call(RestApiOutput& output, + RestApi& context, + const HttpHandler::Arguments& httpHeaders, + const RestApiPath::Components& uriComponents, + const UriComponents& trailing, + const UriComponents& fullUri) : + output_(output), + context_(context), + httpHeaders_(httpHeaders), + uriComponents_(uriComponents), + trailing_(trailing), + fullUri_(fullUri) + { + } protected: static bool ParseJsonRequestInternal(Json::Value& result, @@ -62,44 +77,44 @@ public: RestApiOutput& GetOutput() { - return *output_; + return output_; } RestApi& GetContext() { - return *context_; + return context_; } const UriComponents& GetFullUri() const { - return *fullUri_; + return fullUri_; } const UriComponents& GetTrailingUri() const { - return *trailing_; + return trailing_; } std::string GetUriComponent(const std::string& name, const std::string& defaultValue) const { - return HttpHandler::GetArgument(*uriComponents_, name, defaultValue); + return HttpHandler::GetArgument(uriComponents_, name, defaultValue); } std::string GetHttpHeader(const std::string& name, const std::string& defaultValue) const { - return HttpHandler::GetArgument(*httpHeaders_, name, defaultValue); + return HttpHandler::GetArgument(httpHeaders_, name, defaultValue); } const HttpHandler::Arguments& GetHttpHeaders() const { - return *httpHeaders_; + return httpHeaders_; } void ParseCookies(HttpHandler::Arguments& result) const { - HttpHandler::ParseCookies(result, *httpHeaders_); + HttpHandler::ParseCookies(result, httpHeaders_); } virtual bool ParseJsonRequest(Json::Value& result) const = 0; @@ -111,34 +126,59 @@ friend class RestApi; private: - const HttpHandler::Arguments* getArguments_; + const HttpHandler::Arguments& getArguments_; public: + GetCall(RestApiOutput& output, + RestApi& context, + const HttpHandler::Arguments& httpHeaders, + const RestApiPath::Components& uriComponents, + const UriComponents& trailing, + const UriComponents& fullUri, + const HttpHandler::Arguments& getArguments) : + Call(output, context, httpHeaders, uriComponents, trailing, fullUri), + getArguments_(getArguments) + { + } + std::string GetArgument(const std::string& name, const std::string& defaultValue) const { - return HttpHandler::GetArgument(*getArguments_, name, defaultValue); + return HttpHandler::GetArgument(getArguments_, name, defaultValue); } bool HasArgument(const std::string& name) const { - return getArguments_->find(name) != getArguments_->end(); + return getArguments_.find(name) != getArguments_.end(); } virtual bool ParseJsonRequest(Json::Value& result) const; }; + class PutCall : public Call { friend class RestApi; private: - const std::string* data_; + const std::string& data_; public: + PutCall(RestApiOutput& output, + RestApi& context, + const HttpHandler::Arguments& httpHeaders, + const RestApiPath::Components& uriComponents, + const UriComponents& trailing, + const UriComponents& fullUri, + const std::string& data) : + Call(output, context, httpHeaders, uriComponents, trailing, fullUri), + data_(data) + { + } + const std::string& GetPutBody() const { - return *data_; + return data_; } virtual bool ParseJsonRequest(Json::Value& result) const @@ -152,12 +192,24 @@ friend class RestApi; private: - const std::string* data_; + const std::string& data_; public: + PostCall(RestApiOutput& output, + RestApi& context, + const HttpHandler::Arguments& httpHeaders, + const RestApiPath::Components& uriComponents, + const UriComponents& trailing, + const UriComponents& fullUri, + const std::string& data) : + Call(output, context, httpHeaders, uriComponents, trailing, fullUri), + data_(data) + { + } + const std::string& GetPostBody() const { - return *data_; + return data_; } virtual bool ParseJsonRequest(Json::Value& result) const @@ -169,6 +221,16 @@ class DeleteCall : public Call { public: + DeleteCall(RestApiOutput& output, + RestApi& context, + const HttpHandler::Arguments& httpHeaders, + const RestApiPath::Components& uriComponents, + const UriComponents& trailing, + const UriComponents& fullUri) : + Call(output, context, httpHeaders, uriComponents, trailing, fullUri) + { + } + virtual bool ParseJsonRequest(Json::Value& result) const { result.clear(); @@ -212,7 +274,7 @@ virtual bool IsServedUri(const UriComponents& uri); virtual void Handle(HttpOutput& output, - Orthanc_HttpMethod method, + HttpMethod method, const UriComponents& uri, const Arguments& headers, const Arguments& getArguments, diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApiOutput.cpp --- a/Core/RestApi/RestApiOutput.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApiOutput.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -48,7 +48,7 @@ { if (!alreadySent_) { - output_.SendHeader(Orthanc_HttpStatus_400_BadRequest); + output_.SendHeader(HttpStatus_400_BadRequest); } } @@ -100,10 +100,10 @@ alreadySent_ = true; } - void RestApiOutput::SignalError(Orthanc_HttpStatus status) + void RestApiOutput::SignalError(HttpStatus status) { - if (status != Orthanc_HttpStatus_403_Forbidden && - status != Orthanc_HttpStatus_415_UnsupportedMediaType) + if (status != HttpStatus_403_Forbidden && + status != HttpStatus_415_UnsupportedMediaType) { throw OrthancException("This HTTP status is not allowed in a REST API"); } diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApiOutput.h --- a/Core/RestApi/RestApiOutput.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApiOutput.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -74,7 +74,7 @@ size_t length, const std::string& contentType); - void SignalError(Orthanc_HttpStatus status); + void SignalError(HttpStatus status); void Redirect(const std::string& path); diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApiPath.cpp --- a/Core/RestApi/RestApiPath.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApiPath.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/RestApi/RestApiPath.h --- a/Core/RestApi/RestApiPath.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/RestApi/RestApiPath.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Connection.cpp --- a/Core/SQLite/Connection.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Connection.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -111,7 +111,7 @@ { for (CachedStatements::iterator it = cachedStatements_.begin(); - it != cachedStatements_.end(); it++) + it != cachedStatements_.end(); ++it) { delete it->second; } @@ -331,7 +331,7 @@ void* payload = sqlite3_user_data(rawContext); assert(payload != NULL); - IScalarFunction& func = *(IScalarFunction*) payload; + IScalarFunction& func = *reinterpret_cast(payload); func.Compute(context); } @@ -339,7 +339,7 @@ static void ScalarFunctionDestroyer(void* payload) { assert(payload != NULL); - delete (IScalarFunction*) payload; + delete reinterpret_cast(payload); } diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Connection.h --- a/Core/SQLite/Connection.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Connection.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/FunctionContext.cpp --- a/Core/SQLite/FunctionContext.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/FunctionContext.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Redistribution and use in source and binary forms, with or without @@ -89,6 +89,12 @@ CheckIndex(index); return std::string(reinterpret_cast(sqlite3_value_text(argv_[index]))); } + + bool FunctionContext::IsNullValue(unsigned int index) const + { + CheckIndex(index); + return sqlite3_value_type(argv_[index]) == SQLITE_NULL; + } void FunctionContext::SetNullResult() { diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/FunctionContext.h --- a/Core/SQLite/FunctionContext.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/FunctionContext.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Redistribution and use in source and binary forms, with or without @@ -74,6 +74,8 @@ double GetDoubleValue(unsigned int index) const; std::string GetStringValue(unsigned int index) const; + + bool IsNullValue(unsigned int index) const; void SetNullResult(); diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/IScalarFunction.h --- a/Core/SQLite/IScalarFunction.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/IScalarFunction.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Redistribution and use in source and binary forms, with or without diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Statement.cpp --- a/Core/SQLite/Statement.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Statement.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -295,7 +295,7 @@ return true; }*/ - bool Statement::ColumnBlobAsVector(int col, std::vector* val) const + /*bool Statement::ColumnBlobAsVector(int col, std::vector* val) const { val->clear(); @@ -306,14 +306,14 @@ memcpy(&(*val)[0], data, len); } return true; - } + }*/ - bool Statement::ColumnBlobAsVector( + /*bool Statement::ColumnBlobAsVector( int col, std::vector* val) const { return ColumnBlobAsVector(col, reinterpret_cast< std::vector* >(val)); - } + }*/ } } diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Statement.h --- a/Core/SQLite/Statement.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Statement.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -89,10 +89,6 @@ return reference_.GetWrappedObject(); } - // Resets the statement to its initial condition. This includes any current - // result row, and also the bound variables if the |clear_bound_vars| is true. - void Reset(bool clear_bound_vars = true); - public: Statement(Connection& database, const std::string& sql); @@ -166,9 +162,12 @@ const void* ColumnBlob(int col) const; bool ColumnBlobAsString(int col, std::string* blob); //bool ColumnBlobAsString16(int col, string16* val) const; - bool ColumnBlobAsVector(int col, std::vector* val) const; - bool ColumnBlobAsVector(int col, std::vector* val) const; + //bool ColumnBlobAsVector(int col, std::vector* val) const; + //bool ColumnBlobAsVector(int col, std::vector* val) const; + // Resets the statement to its initial condition. This includes any current + // result row, and also the bound variables if the |clear_bound_vars| is true. + void Reset(bool clear_bound_vars = true); }; } } diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/StatementId.cpp --- a/Core/SQLite/StatementId.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/StatementId.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/StatementId.h --- a/Core/SQLite/StatementId.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/StatementId.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/StatementReference.cpp --- a/Core/SQLite/StatementReference.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/StatementReference.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -39,6 +39,7 @@ #include "../OrthancException.h" #include +#include #include "sqlite3.h" namespace Orthanc @@ -103,8 +104,11 @@ { if (refCount_ != 0) { - // There remain references to this object - throw OrthancException(ErrorCode_InternalError); + // There remain references to this object. We cannot throw + // an exception because: + // http://www.parashift.com/c++-faq/dtors-shouldnt-throw.html + + LOG(ERROR) << "Bad value of the reference counter"; } else if (statement_ != NULL) { @@ -115,7 +119,11 @@ { if (root_->refCount_ == 0) { - throw OrthancException(ErrorCode_InternalError); + // There remain references to this object. We cannot throw + // an exception because: + // http://www.parashift.com/c++-faq/dtors-shouldnt-throw.html + + LOG(ERROR) << "Bad value of the reference counter"; } else { diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/StatementReference.h --- a/Core/SQLite/StatementReference.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/StatementReference.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Transaction.cpp --- a/Core/SQLite/Transaction.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Transaction.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/SQLite/Transaction.h --- a/Core/SQLite/Transaction.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/SQLite/Transaction.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * Copyright (c) 2012 The Chromium Authors. All rights reserved. diff -r 63f707278fc8 -r 45b16f67259c Core/Toolbox.cpp --- a/Core/Toolbox.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Toolbox.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -34,12 +34,15 @@ #include "OrthancException.h" +#include #include #include #include #include +#include #include #include +#include #if defined(_WIN32) #include @@ -64,7 +67,19 @@ #include "../Resources/md5/md5.h" #include "../Resources/base64/base64.h" -#include "../Resources/sha1/sha1.h" + + +#ifdef _MSC_VER +// Patch for the missing "_strtoll" symbol when compiling with Visual Studio +extern "C" +{ +int64_t _strtoi64(const char *nptr, char **endptr, int base); +int64_t strtoll(const char *nptr, char **endptr, int base) +{ + return _strtoi64(nptr, endptr, base); +} +} +#endif #if BOOST_HAS_LOCALE == 0 @@ -131,9 +146,9 @@ #if defined(_WIN32) static BOOL WINAPI ConsoleControlHandler(DWORD dwCtrlType) { - // http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx - finish = true; - return true; + // http://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx + finish = true; + return true; } #else static void SignalHandler(int) @@ -142,17 +157,6 @@ } #endif - void Toolbox::Sleep(uint32_t seconds) - { -#if defined(_WIN32) - ::Sleep(static_cast(seconds) * static_cast(1000)); -#elif defined(__linux) - usleep(static_cast(seconds) * static_cast(1000000)); -#else -#error Support your platform here -#endif - } - void Toolbox::USleep(uint64_t microSeconds) { #if defined(_WIN32) @@ -168,10 +172,11 @@ void Toolbox::ServerBarrier() { #if defined(_WIN32) - SetConsoleCtrlHandler(ConsoleControlHandler, true); + SetConsoleCtrlHandler(ConsoleControlHandler, true); #else signal(SIGINT, SignalHandler); signal(SIGQUIT, SignalHandler); + signal(SIGTERM, SignalHandler); #endif finish = false; @@ -181,10 +186,11 @@ } #if defined(_WIN32) - SetConsoleCtrlHandler(ConsoleControlHandler, false); + SetConsoleCtrlHandler(ConsoleControlHandler, false); #else signal(SIGINT, NULL); signal(SIGQUIT, NULL); + signal(SIGTERM, NULL); #endif } @@ -202,15 +208,29 @@ } + void Toolbox::ToUpperCase(std::string& result, + const std::string& source) + { + result = source; + ToUpperCase(result); + } + + void Toolbox::ToLowerCase(std::string& result, + const std::string& source) + { + result = source; + ToLowerCase(result); + } + void Toolbox::ReadFile(std::string& content, const std::string& path) { boost::filesystem::ifstream f; - f.open(path, std::ifstream::in | std::ios::binary); + f.open(path, std::ifstream::in | std::ifstream::binary); if (!f.good()) { - throw OrthancException("Unable to open a file"); + throw OrthancException(ErrorCode_InexistentFile); } // http://www.cplusplus.com/reference/iostream/istream/tellg/ @@ -228,6 +248,26 @@ } + void Toolbox::WriteFile(const std::string& content, + const std::string& path) + { + boost::filesystem::ofstream f; + f.open(path, std::ofstream::binary); + if (!f.good()) + { + throw OrthancException(ErrorCode_CannotWriteFile); + } + + if (content.size() != 0) + { + f.write(content.c_str(), content.size()); + } + + f.close(); + } + + + void Toolbox::RemoveFile(const std::string& path) { if (boost::filesystem::exists(path)) @@ -414,13 +454,29 @@ void Toolbox::ComputeMD5(std::string& result, const std::string& data) { + if (data.size() > 0) + { + ComputeMD5(result, &data[0], data.size()); + } + else + { + ComputeMD5(result, NULL, 0); + } + } + + + void Toolbox::ComputeMD5(std::string& result, + const void* data, + size_t length) + { md5_state_s state; md5_init(&state); - if (data.size() > 0) + if (length > 0) { - md5_append(&state, reinterpret_cast(&data[0]), - static_cast(data.size())); + md5_append(&state, + reinterpret_cast(data), + static_cast(length)); } md5_byte_t actualHash[16]; @@ -538,31 +594,27 @@ void Toolbox::ComputeSHA1(std::string& result, const std::string& data) { - SHA1 sha1; + boost::uuids::detail::sha1 sha1; + if (data.size() > 0) { - sha1.Input(&data[0], data.size()); + sha1.process_bytes(&data[0], data.size()); } - unsigned digest[5]; + unsigned int digest[5]; // Sanity check for the memory layout: A SHA-1 digest is 160 bits wide - assert(sizeof(unsigned) == 4 && sizeof(digest) == (160 / 8)); + assert(sizeof(unsigned int) == 4 && sizeof(digest) == (160 / 8)); - if (sha1.Result(digest)) - { - result.resize(8 * 5 + 4); - sprintf(&result[0], "%08x-%08x-%08x-%08x-%08x", - digest[0], - digest[1], - digest[2], - digest[3], - digest[4]); - } - else - { - throw OrthancException(ErrorCode_InternalError); - } + sha1.get_digest(digest); + + result.resize(8 * 5 + 4); + sprintf(&result[0], "%08x-%08x-%08x-%08x-%08x", + digest[0], + digest[1], + digest[2], + digest[3], + digest[4]); } bool Toolbox::IsSHA1(const std::string& str) @@ -671,4 +723,85 @@ s.resize(target); } + + + Endianness Toolbox::DetectEndianness() + { + // http://sourceforge.net/p/predef/wiki/Endianness/ + + uint8_t buffer[4]; + + buffer[0] = 0x00; + buffer[1] = 0x01; + buffer[2] = 0x02; + buffer[3] = 0x03; + + switch (*((uint32_t *)buffer)) + { + case 0x00010203: + return Endianness_Big; + + case 0x03020100: + return Endianness_Little; + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } + + + std::string Toolbox::WildcardToRegularExpression(const std::string& source) + { + // TODO - Speed up this with a regular expression + + std::string result = source; + + // Escape all special characters + boost::replace_all(result, "\\", "\\\\"); + boost::replace_all(result, "^", "\\^"); + boost::replace_all(result, ".", "\\."); + boost::replace_all(result, "$", "\\$"); + boost::replace_all(result, "|", "\\|"); + boost::replace_all(result, "(", "\\("); + boost::replace_all(result, ")", "\\)"); + boost::replace_all(result, "[", "\\["); + boost::replace_all(result, "]", "\\]"); + boost::replace_all(result, "+", "\\+"); + boost::replace_all(result, "/", "\\/"); + boost::replace_all(result, "{", "\\{"); + boost::replace_all(result, "}", "\\}"); + + // Convert wildcards '*' and '?' to their regex equivalents + boost::replace_all(result, "?", "."); + boost::replace_all(result, "*", ".*"); + + return result; + } + + + + void Toolbox::TokenizeString(std::vector& result, + const std::string& value, + char separator) + { + result.clear(); + + std::string currentItem; + + for (size_t i = 0; i < value.size(); i++) + { + if (value[i] == separator) + { + result.push_back(currentItem); + currentItem.clear(); + } + else + { + currentItem.push_back(value[i]); + } + } + + result.push_back(currentItem); + } } + diff -r 63f707278fc8 -r 45b16f67259c Core/Toolbox.h --- a/Core/Toolbox.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Toolbox.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -32,6 +32,8 @@ #pragma once +#include "Enumerations.h" + #include #include #include @@ -48,14 +50,21 @@ { void ServerBarrier(); - void ToUpperCase(std::string& s); + void ToUpperCase(std::string& s); // Inplace version + + void ToLowerCase(std::string& s); // Inplace version - void ToLowerCase(std::string& s); + void ToUpperCase(std::string& result, + const std::string& source); + + void ToLowerCase(std::string& result, + const std::string& source); void ReadFile(std::string& content, const std::string& path); - void Sleep(uint32_t seconds); + void WriteFile(const std::string& content, + const std::string& path); void USleep(uint64_t microSeconds); @@ -77,6 +86,10 @@ void ComputeMD5(std::string& result, const std::string& data); + void ComputeMD5(std::string& result, + const void* data, + size_t length); + void ComputeSHA1(std::string& result, const std::string& data); @@ -101,5 +114,13 @@ // In-place percent-decoding for URL void UrlDecode(std::string& s); + + Endianness DetectEndianness(); + + std::string WildcardToRegularExpression(const std::string& s); + + void TokenizeString(std::vector& result, + const std::string& source, + char separator); } } diff -r 63f707278fc8 -r 45b16f67259c Core/Uuid.cpp --- a/Core/Uuid.cpp Fri May 03 12:23:02 2013 +0200 +++ b/Core/Uuid.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or @@ -141,15 +141,15 @@ } - TemporaryFile::TemporaryFile() + TemporaryFile::TemporaryFile() : + path_(CreateTemporaryPath(NULL)) { - path_ = CreateTemporaryPath(NULL); } - TemporaryFile::TemporaryFile(const char* extension) + TemporaryFile::TemporaryFile(const char* extension) : + path_(CreateTemporaryPath(extension)) { - path_ = CreateTemporaryPath(extension); } diff -r 63f707278fc8 -r 45b16f67259c Core/Uuid.h --- a/Core/Uuid.h Fri May 03 12:23:02 2013 +0200 +++ b/Core/Uuid.h Tue Apr 22 16:47:21 2014 +0200 @@ -1,6 +1,6 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, * Belgium * * This program is free software: you can redistribute it and/or diff -r 63f707278fc8 -r 45b16f67259c INSTALL --- a/INSTALL Fri May 03 12:23:02 2013 +0200 +++ b/INSTALL Tue Apr 22 16:47:21 2014 +0200 @@ -43,29 +43,7 @@ Native Linux Compilation ------------------------ -To build binaries with debug information: - -# cd ~/OrthancBuild -# cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug ~/Orthanc -# make -# make doc - - -To build a release version: - -# cd ~/OrthancBuild -# cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release ~/Orthanc -# make -# make doc - - -Under Linux, you have the possibility to dynamically link Orthanc -against the shared libraries of your system, provided their version is -recent enough. This greatly speeds up the compilation: - -# cd ~/OrthancBuild -# cmake -DSTATIC_BUILD=OFF -DCMAKE_BUILD_TYPE=Debug ~/Orthanc -# make +See the file "LinuxCompilation.txt". @@ -104,23 +82,3 @@ # cd [...]\OrthancBuild # cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug [...]\Orthanc # mingw32-make - - - -Using ccache ------------- - -Under Linux, you have the opportunity to use "ccache" to dramatically -decrease the compilation time when rebuilding Orthanc. This is -especially useful for developers. Under Debian/Ubuntu, you would use: - -# CC="ccache gcc" CXX="ccache g++" cmake "-DDCMTK_LIBRARIES=wrap;oflog" \ - -DSTATIC_BUILD=OFF -DCMAKE_BUILD_TYPE=Debug ~/Orthanc - - - -Troubleshooting ---------------- - -The build instructions for specific Linux distributions are available at the following place: -https://code.google.com/p/orthanc/wiki/FAQ#I_use_the_Linux_distribution_XXX,_how_can_I_build_Orthanc? diff -r 63f707278fc8 -r 45b16f67259c LinuxCompilation.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LinuxCompilation.txt Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,205 @@ +This file is a complement to "INSTALL", which contains instructions +that are specific to Linux. + + +Static linking for Linux +======================== + +The most simple way of building Orthanc under Linux consists in +statically linking against all the third-party dependencies. In this +case, the system-wide libraries will not be used. The build tool +(CMake) will download the sources of all the required packages and +automatically compile them. This process should work on all the Linux +distributions. + + +To build binaries with debug information: + +# cd ~/OrthancBuild +# cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug ~/Orthanc +# make +# make doc + + +To build a release version: + +# cd ~/OrthancBuild +# cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release ~/Orthanc +# make +# make doc + + +Note: When the "STATIC_BUILD" option is set to "ON", the build tool +will not ask you the permission to download packages from the +Internet. + + +Use system-wide libraries under Linux +===================================== + +Under Linux, by default, Orthanc links against the shared libraries of +your system (the "STATIC_BUILD" option is set to "OFF"). This greatly +speeds up the compilation. This is also required when building +packages for Linux distributions. Because using system libraries is +the default behavior, you just have to use: + +# cd ~/OrthancBuild +# cmake -DCMAKE_BUILD_TYPE=Debug ~/Orthanc +# make + + +However, on some Linux distributions, it is still required to download +and static link against some third-party dependencies, e.g. when the +system-wide library is not shipped or is outdated. Because of +difference in the packaging of the various Linux distribution, it is +also sometimes required to fine-tune some options. + +You will find below build instructions for specific Linux +distributions. Distributions tagged by "SUPPORTED" are tested by +Sébastien Jodogne. Distributions tagged by "CONTRIBUTED" come from +Orthanc users. + + +SUPPORTED - Debian Squeeze (6.x) +-------------------------------- + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgoogle-glog-dev libpng-dev libgtest-dev \ + libsqlite3-dev libssl-dev zlib1g-dev + +# cmake -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_BOOST=OFF \ + -DUSE_SYSTEM_DCMTK=OFF \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_SYSTEM_JSONCPP=OFF \ + ~/Orthanc + + +SUPPORTED - Debian Wheezy (7.x) +------------------------------- + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgtest-dev libpng-dev libsqlite3-dev \ + libssl-dev zlib1g-dev libdcmtk2-dev \ + libboost-all-dev libwrap0-dev libjsoncpp-dev + +# cmake -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_GOOGLE_LOG=OFF \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + ~/Orthanc + + +SUPPORTED - Debian Jessie/Sid +----------------------------- + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgoogle-glog-dev libgtest-dev libpng-dev \ + libsqlite3-dev libssl-dev zlib1g-dev libdcmtk2-dev \ + libboost-all-dev libwrap0-dev libjsoncpp-dev + +# cmake -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + ~/Orthanc + +Note: Have also a look at the official package: +http://anonscm.debian.org/viewvc/debian-med/trunk/packages/orthanc/trunk/debian/ + + +SUPPORTED - Ubuntu 12.04 LTS +---------------------------- + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgtest-dev libpng-dev libsqlite3-dev libssl-dev \ + zlib1g-dev libdcmtk2-dev libboost-all-dev libwrap0-dev + +# cmake "-DDCMTK_LIBRARIES=wrap;oflog" \ + -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_SYSTEM_JSONCPP=OFF \ + -DUSE_SYSTEM_GOOGLE_LOG=OFF \ + -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + ~/Orthanc + + +SUPPORTED - Ubuntu 12.10 +------------------------ + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgoogle-glog-dev libgtest-dev libpng-dev \ + libsqlite3-dev libssl-dev zlib1g-dev \ + libdcmtk2-dev libboost-all-dev libwrap0-dev + +# cmake "-DDCMTK_LIBRARIES=wrap;oflog" \ + -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_SYSTEM_JSONCPP=OFF \ + -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + ~/Orthanc + + +SUPPORTED - Ubuntu 13.10 +------------------------ + +# sudo apt-get install build-essential unzip cmake mercurial \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgoogle-glog-dev libgtest-dev libpng-dev \ + libsqlite3-dev libssl-dev zlib1g-dev \ + libdcmtk2-dev libboost-all-dev libwrap0-dev libjsoncpp-dev + +# cmake "-DDCMTK_LIBRARIES=wrap;oflog" \ + -DALLOW_DOWNLOADS=ON \ + -DUSE_SYSTEM_MONGOOSE=OFF \ + -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON \ + ~/Orthanc + + + +SUPPORTED - Fedora 18/19/20 +--------------------------- + +# sudo yum install make automake gcc gcc-c++ python cmake \ + boost-devel curl-devel dcmtk-devel glog-devel \ + gtest-devel libpng-devel libsqlite3x-devel libuuid-devel \ + mongoose-devel openssl-devel jsoncpp-devel lua-devel + +# cmake ~/Orthanc + +Note: Have also a look at the official package: +http://pkgs.fedoraproject.org/cgit/orthanc.git/tree/?h=f18 + + + + + +Other Linux distributions? +-------------------------- + +Please send us your build instructions (by a mail to +s.jodogne@gmail.com)! + +You can find build instructions for Orthanc up to 0.7.0 on the +following Wiki page: +https://code.google.com/p/orthanc/wiki/LinuxCompilationUpTo070 + +These instructions will not work as such beyond Orthanc 0.7.0, but +they might give indications. + + + + +Using ccache +============ + +Under Linux, you also have the opportunity to use "ccache" to +dramatically decrease the compilation time when rebuilding +Orthanc. This is especially useful for developers. To this end, you +would use: + +# CC="ccache gcc" CXX="ccache g++" cmake ~/Orthanc [Other Options] diff -r 63f707278fc8 -r 45b16f67259c NEWS --- a/NEWS Fri May 03 12:23:02 2013 +0200 +++ b/NEWS Tue Apr 22 16:47:21 2014 +0200 @@ -2,11 +2,137 @@ =============================== -* Store-SCU for patients and studies in Orthanc Explorer. + +Version 0.7.4 (2014/04/16) +========================== + +* Switch to openssl-1.0.1g in static builds (cf. Heartbleed exploit) +* Switch to boost 1.55.0 in static builds (to solve compiling errors) +* Better logging about nonexistent tags +* Dcm4Chee manufacturer +* Automatic discovering of the path to the DICOM dictionaries +* In the "DicomModalities" config, the port number can be a string + + +Version 0.7.3 (2014/02/14) +========================== + +Major changes +------------- + +* Fixes in the implementation of the C-FIND handler for Query/Retrieve +* Custom attachment of files to patients, studies, series or instances +* Access to lowlevel info about the attached files through the REST API +* Recover pixel data for more transfer syntaxes (notably JPEG) + +Minor changes +------------- + +* AET comparison is now case-insensitive by default +* Possibility to disable the HTTP server or the DICOM server +* Automatic computation of MD5 hashes for the stored DICOM files +* Maintenance tool to recover DICOM files compressed by Orthanc +* The newline characters in the configuration file are fixed for Linux +* Capture of the SIGTERM signal in Linux + + +Version 0.7.2 (2013/11/08) +========================== + +* Support of Query/Retrieve from medInria +* Accept more transfer syntaxes for C-Store SCP and SCU (notably JPEG) +* Create the meta-header when receiving files through C-Store SCP +* Fixes and improvements thanks to the static analyzer cppcheck + + +Version 0.7.1 (2013/10/30) +========================== + +* Use ZIP64 only when required to improve compatibility (cf. issue #7) +* Refactoring of the CMake options +* Fix for big-endian architectures (RedHat bug #985748) +* Use filenames with 8 characters in ZIP files for maximum compatibility +* Possibility to build Orthanc inplace (in the source directory) + + +Version 0.7.0 (2013/10/25) +========================== + +Major changes +------------- + +* DICOM Query/Retrieve is supported + +Minor changes +------------- + +* Possibility to keep the PatientID during an anonymization +* Check whether "unzip", "tar" and/or "7-zip" are installed from CMake + + +Version 0.6.2 (2013/10/04) +========================== + +* Build of the C++ client as a shared library +* Improvements and documentation of the C++ client API +* Fix of Debian bug #724947 (licensing issue with the SHA-1 library) +* Switch to Boost 1.54.0 (cf. issue #9) +* "make uninstall" is now possible + + +Version 0.6.1 (2013/09/16) +========================== + +* Detection of stable patients/studies/series +* C-Find SCU at the instance level +* Link from modified to original resource in Orthanc Explorer +* Fix of issue #8 +* Anonymization of the medical alerts tag (0010,2000) + + +Version 0.6.0 (2013/07/16) +========================== + +Major changes +------------- + +* Introduction of the C++ client +* Send DICOM resources to other Orthanc instances through HTTP +* Access to signed images (instances/.../image-int16) + (Closes: Debian #716958) + +Minor changes +------------- + +* Export of DICOM files to the host filesystem (instances/.../export) +* Statistics about patients, studies, series and instances +* Link from anonymized to original resource in Orthanc Explorer +* Fixes for Red Hat and Debian packaging +* Fixes for history in Orthanc Explorer +* Fixes for boost::thread, as reported by Cyril Paulus +* Fix licensing (Closes: Debian #712038) + +Metadata +-------- + +* Access to the metadata through the REST API (.../metadata) +* Support of user-defined metadata +* "LastUpdate" metadata for patients, studies and series +* "/tools/now" to be used in combination with "LastUpdate" +* Improved support of series with temporal positions + + +Version 0.5.2 (2013/05/07) +========================== + * "Bulk" Store-SCU (send several DICOM instances with the same - DICOM connexion). -* Filtering of incoming DICOM instances (through Lua scripting). -* Filtering of incoming HTTP requests (through Lua scripting). + DICOM connexion) +* Store-SCU for patients and studies in Orthanc Explorer +* Filtering of incoming DICOM instances (through Lua scripting) +* Filtering of incoming HTTP requests (through Lua scripting) +* Clearing of "/exports" and "/changes" +* Check MD5 of third party downloads +* Faking of the HTTP methods PUT and DELETE Version 0.5.1 (2013/04/17) diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/CMakeLists.txt --- a/OrthancCppClient/CMakeLists.txt Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -# Mini-project to check whether "OrthancCppClient" can compile in a -# standalone fashion - -cmake_minimum_required(VERSION 2.8) - -project(OrthancCppClientTest) - -SET(STATIC_BUILD OFF) - -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DownloadPackage.cmake) -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/JsonCppConfiguration.cmake) -include(${CMAKE_SOURCE_DIR}/../Resources/CMake/LibCurlConfiguration.cmake) - -if (${CMAKE_COMPILER_IS_GNUCXX}) - set(CMAKE_C_FLAGS "-Wall -pedantic -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile - set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wno-long-long -Wno-variadic-macros") - set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") -elseif (${MSVC}) - add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) -endif() - -add_library(OrthancCppClient - SHARED - - ${THIRD_PARTY_SOURCES} - HttpException.cpp - HttpClient.cpp - ) - -add_executable(Test - main.cpp - ) - -target_link_libraries(Test OrthancCppClient) diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/HttpClient.cpp --- a/OrthancCppClient/HttpClient.cpp Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpClient.h" - -#include -#include - - -namespace Orthanc -{ - struct HttpClient::PImpl - { - CURL* curl_; - struct curl_slist *postHeaders_; - }; - - - static CURLcode CheckCode(CURLcode code) - { - if (code != CURLE_OK) - { - printf("ICI: %s\n", curl_easy_strerror(code)); - throw HttpException("CURL: " + std::string(curl_easy_strerror(code))); - } - - return code; - } - - - static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *payload) - { - std::string& target = *(static_cast(payload)); - - size_t length = size * nmemb; - if (length == 0) - return 0; - - size_t pos = target.size(); - - target.resize(pos + length); - memcpy(&target.at(pos), buffer, length); - - return length; - } - - - HttpClient::HttpClient() : pimpl_(new PImpl) - { - pimpl_->postHeaders_ = NULL; - if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL) - { - throw HttpException("HttpClient: Not enough memory"); - } - - pimpl_->curl_ = curl_easy_init(); - if (!pimpl_->curl_) - { - curl_slist_free_all(pimpl_->postHeaders_); - throw HttpException("HttpClient: Not enough memory"); - } - - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1)); - -#if ORTHANC_SSL_ENABLED == 1 - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); -#endif - - url_ = ""; - method_ = Orthanc_HttpMethod_Get; - lastStatus_ = Orthanc_HttpStatus_200_Ok; - isVerbose_ = false; - } - - - HttpClient::~HttpClient() - { - curl_easy_cleanup(pimpl_->curl_); - curl_slist_free_all(pimpl_->postHeaders_); - } - - - void HttpClient::SetVerbose(bool isVerbose) - { - isVerbose_ = isVerbose; - - if (isVerbose_) - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1)); - } - else - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0)); - } - } - - - bool HttpClient::Apply(std::string& answer) - { - answer.clear(); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, NULL)); - - switch (method_) - { - case Orthanc_HttpMethod_Get: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L)); - break; - - case Orthanc_HttpMethod_Post: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->postHeaders_)); - - if (postData_.size() > 0) - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, postData_.c_str())); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, postData_.size())); - } - else - { - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0)); - } - - break; - - case Orthanc_HttpMethod_Delete: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L)); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE")); - break; - - case Orthanc_HttpMethod_Put: - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L)); - break; - - default: - throw HttpException("HttpClient: Internal error"); - } - - // Do the actual request - CheckCode(curl_easy_perform(pimpl_->curl_)); - - long status; - CheckCode(curl_easy_getinfo(pimpl_->curl_, CURLINFO_RESPONSE_CODE, &status)); - - if (status == 0) - { - // This corresponds to a call to an inexistent host - lastStatus_ = Orthanc_HttpStatus_500_InternalServerError; - } - else - { - lastStatus_ = static_cast(status); - } - - return (status >= 200 && status < 300); - } - - - bool HttpClient::Apply(Json::Value& answer) - { - std::string s; - if (Apply(s)) - { - Json::Reader reader; - return reader.parse(s, answer); - } - else - { - return false; - } - } - - - void HttpClient::SetPassword(const char* username, - const char* password) - { - std::string s = std::string(username) + ":" + std::string(password); - CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_USERPWD, s.c_str())); - } -} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/HttpClient.h --- a/OrthancCppClient/HttpClient.h Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - -#include "HttpEnumerations.h" -#include "HttpException.h" - -#include -#include -#include - -namespace Orthanc -{ - class HttpClient - { - private: - struct PImpl; - boost::shared_ptr pimpl_; - - std::string url_; - Orthanc_HttpMethod method_; - Orthanc_HttpStatus lastStatus_; - std::string postData_; - bool isVerbose_; - - public: - HttpClient(); - - ~HttpClient(); - - void SetUrl(const char* url) - { - url_ = std::string(url); - } - - void SetUrl(const std::string& url) - { - url_ = url; - } - - const std::string& GetUrl() const - { - return url_; - } - - void SetMethod(Orthanc_HttpMethod method) - { - method_ = method; - } - - Orthanc_HttpMethod GetMethod() const - { - return method_; - } - - std::string& AccessPostData() - { - return postData_; - } - - const std::string& AccessPostData() const - { - return postData_; - } - - void SetVerbose(bool isVerbose); - - bool IsVerbose() const - { - return isVerbose_; - } - - bool Apply(std::string& answer); - - bool Apply(Json::Value& answer); - - Orthanc_HttpStatus GetLastStatus() const - { - return lastStatus_; - } - - const char* GetLastStatusText() const - { - return HttpException::GetDescription(lastStatus_); - } - - void SetPassword(const char* username, - const char* password); - }; -} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/HttpEnumerations.h --- a/OrthancCppClient/HttpEnumerations.h Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - - -/** - * This file contains the enumerations for the access to the Orthanc - * REST API in C and C++. Namespaces are not used, in order to enable - * the access in C. - **/ - -// Most common, non-joke and non-experimental HTTP status codes -// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes -enum Orthanc_HttpStatus -{ - Orthanc_HttpStatus_None = -1, - - // 1xx Informational - Orthanc_HttpStatus_100_Continue = 100, - Orthanc_HttpStatus_101_SwitchingProtocols = 101, - Orthanc_HttpStatus_102_Processing = 102, - - // 2xx Success - Orthanc_HttpStatus_200_Ok = 200, - Orthanc_HttpStatus_201_Created = 201, - Orthanc_HttpStatus_202_Accepted = 202, - Orthanc_HttpStatus_203_NonAuthoritativeInformation = 203, - Orthanc_HttpStatus_204_NoContent = 204, - Orthanc_HttpStatus_205_ResetContent = 205, - Orthanc_HttpStatus_206_PartialContent = 206, - Orthanc_HttpStatus_207_MultiStatus = 207, - Orthanc_HttpStatus_208_AlreadyReported = 208, - Orthanc_HttpStatus_226_IMUsed = 226, - - // 3xx Redirection - Orthanc_HttpStatus_300_MultipleChoices = 300, - Orthanc_HttpStatus_301_MovedPermanently = 301, - Orthanc_HttpStatus_302_Found = 302, - Orthanc_HttpStatus_303_SeeOther = 303, - Orthanc_HttpStatus_304_NotModified = 304, - Orthanc_HttpStatus_305_UseProxy = 305, - Orthanc_HttpStatus_307_TemporaryRedirect = 307, - - // 4xx Client Error - Orthanc_HttpStatus_400_BadRequest = 400, - Orthanc_HttpStatus_401_Unauthorized = 401, - Orthanc_HttpStatus_402_PaymentRequired = 402, - Orthanc_HttpStatus_403_Forbidden = 403, - Orthanc_HttpStatus_404_NotFound = 404, - Orthanc_HttpStatus_405_MethodNotAllowed = 405, - Orthanc_HttpStatus_406_NotAcceptable = 406, - Orthanc_HttpStatus_407_ProxyAuthenticationRequired = 407, - Orthanc_HttpStatus_408_RequestTimeout = 408, - Orthanc_HttpStatus_409_Conflict = 409, - Orthanc_HttpStatus_410_Gone = 410, - Orthanc_HttpStatus_411_LengthRequired = 411, - Orthanc_HttpStatus_412_PreconditionFailed = 412, - Orthanc_HttpStatus_413_RequestEntityTooLarge = 413, - Orthanc_HttpStatus_414_RequestUriTooLong = 414, - Orthanc_HttpStatus_415_UnsupportedMediaType = 415, - Orthanc_HttpStatus_416_RequestedRangeNotSatisfiable = 416, - Orthanc_HttpStatus_417_ExpectationFailed = 417, - Orthanc_HttpStatus_422_UnprocessableEntity = 422, - Orthanc_HttpStatus_423_Locked = 423, - Orthanc_HttpStatus_424_FailedDependency = 424, - Orthanc_HttpStatus_426_UpgradeRequired = 426, - - // 5xx Server Error - Orthanc_HttpStatus_500_InternalServerError = 500, - Orthanc_HttpStatus_501_NotImplemented = 501, - Orthanc_HttpStatus_502_BadGateway = 502, - Orthanc_HttpStatus_503_ServiceUnavailable = 503, - Orthanc_HttpStatus_504_GatewayTimeout = 504, - Orthanc_HttpStatus_505_HttpVersionNotSupported = 505, - Orthanc_HttpStatus_506_VariantAlsoNegotiates = 506, - Orthanc_HttpStatus_507_InsufficientStorage = 507, - Orthanc_HttpStatus_509_BandwidthLimitExceeded = 509, - Orthanc_HttpStatus_510_NotExtended = 510 -}; - - -enum Orthanc_HttpMethod -{ - Orthanc_HttpMethod_Get = 0, - Orthanc_HttpMethod_Post = 1, - Orthanc_HttpMethod_Delete = 2, - Orthanc_HttpMethod_Put = 3 -}; diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/HttpException.cpp --- a/OrthancCppClient/HttpException.cpp Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpException.h" - -namespace Orthanc -{ - const char* HttpException::What() const - { - if (status_ == Orthanc_HttpStatus_None) - { - return custom_.c_str(); - } - else - { - return GetDescription(status_); - } - } - - const char* HttpException::GetDescription(Orthanc_HttpStatus status) - { - switch (status) - { - case Orthanc_HttpStatus_100_Continue: - return "Continue"; - - case Orthanc_HttpStatus_101_SwitchingProtocols: - return "Switching Protocols"; - - case Orthanc_HttpStatus_102_Processing: - return "Processing"; - - case Orthanc_HttpStatus_200_Ok: - return "OK"; - - case Orthanc_HttpStatus_201_Created: - return "Created"; - - case Orthanc_HttpStatus_202_Accepted: - return "Accepted"; - - case Orthanc_HttpStatus_203_NonAuthoritativeInformation: - return "Non-Authoritative Information"; - - case Orthanc_HttpStatus_204_NoContent: - return "No Content"; - - case Orthanc_HttpStatus_205_ResetContent: - return "Reset Content"; - - case Orthanc_HttpStatus_206_PartialContent: - return "Partial Content"; - - case Orthanc_HttpStatus_207_MultiStatus: - return "Multi-Status"; - - case Orthanc_HttpStatus_208_AlreadyReported: - return "Already Reported"; - - case Orthanc_HttpStatus_226_IMUsed: - return "IM Used"; - - case Orthanc_HttpStatus_300_MultipleChoices: - return "Multiple Choices"; - - case Orthanc_HttpStatus_301_MovedPermanently: - return "Moved Permanently"; - - case Orthanc_HttpStatus_302_Found: - return "Found"; - - case Orthanc_HttpStatus_303_SeeOther: - return "See Other"; - - case Orthanc_HttpStatus_304_NotModified: - return "Not Modified"; - - case Orthanc_HttpStatus_305_UseProxy: - return "Use Proxy"; - - case Orthanc_HttpStatus_307_TemporaryRedirect: - return "Temporary Redirect"; - - case Orthanc_HttpStatus_400_BadRequest: - return "Bad Request"; - - case Orthanc_HttpStatus_401_Unauthorized: - return "Unauthorized"; - - case Orthanc_HttpStatus_402_PaymentRequired: - return "Payment Required"; - - case Orthanc_HttpStatus_403_Forbidden: - return "Forbidden"; - - case Orthanc_HttpStatus_404_NotFound: - return "Not Found"; - - case Orthanc_HttpStatus_405_MethodNotAllowed: - return "Method Not Allowed"; - - case Orthanc_HttpStatus_406_NotAcceptable: - return "Not Acceptable"; - - case Orthanc_HttpStatus_407_ProxyAuthenticationRequired: - return "Proxy Authentication Required"; - - case Orthanc_HttpStatus_408_RequestTimeout: - return "Request Timeout"; - - case Orthanc_HttpStatus_409_Conflict: - return "Conflict"; - - case Orthanc_HttpStatus_410_Gone: - return "Gone"; - - case Orthanc_HttpStatus_411_LengthRequired: - return "Length Required"; - - case Orthanc_HttpStatus_412_PreconditionFailed: - return "Precondition Failed"; - - case Orthanc_HttpStatus_413_RequestEntityTooLarge: - return "Request Entity Too Large"; - - case Orthanc_HttpStatus_414_RequestUriTooLong: - return "Request-URI Too Long"; - - case Orthanc_HttpStatus_415_UnsupportedMediaType: - return "Unsupported Media Type"; - - case Orthanc_HttpStatus_416_RequestedRangeNotSatisfiable: - return "Requested Range Not Satisfiable"; - - case Orthanc_HttpStatus_417_ExpectationFailed: - return "Expectation Failed"; - - case Orthanc_HttpStatus_422_UnprocessableEntity: - return "Unprocessable Entity"; - - case Orthanc_HttpStatus_423_Locked: - return "Locked"; - - case Orthanc_HttpStatus_424_FailedDependency: - return "Failed Dependency"; - - case Orthanc_HttpStatus_426_UpgradeRequired: - return "Upgrade Required"; - - case Orthanc_HttpStatus_500_InternalServerError: - return "Internal Server Error"; - - case Orthanc_HttpStatus_501_NotImplemented: - return "Not Implemented"; - - case Orthanc_HttpStatus_502_BadGateway: - return "Bad Gateway"; - - case Orthanc_HttpStatus_503_ServiceUnavailable: - return "Service Unavailable"; - - case Orthanc_HttpStatus_504_GatewayTimeout: - return "Gateway Timeout"; - - case Orthanc_HttpStatus_505_HttpVersionNotSupported: - return "HTTP Version Not Supported"; - - case Orthanc_HttpStatus_506_VariantAlsoNegotiates: - return "Variant Also Negotiates"; - - case Orthanc_HttpStatus_507_InsufficientStorage: - return "Insufficient Storage"; - - case Orthanc_HttpStatus_509_BandwidthLimitExceeded: - return "Bandwidth Limit Exceeded"; - - case Orthanc_HttpStatus_510_NotExtended: - return "Not Extended"; - - default: - throw HttpException("Unknown HTTP status"); - } - } -} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/HttpException.h --- a/OrthancCppClient/HttpException.h Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#pragma once - -#include "HttpEnumerations.h" - -#include - -namespace Orthanc -{ - class HttpException - { - private: - Orthanc_HttpStatus status_; - std::string custom_; - - public: - static const char* GetDescription(Orthanc_HttpStatus status); - - HttpException(const std::string& custom) - { - status_ = Orthanc_HttpStatus_None; - custom_ = custom; - } - - HttpException(Orthanc_HttpStatus status) - { - status_ = status; - } - - Orthanc_HttpStatus GetHttpStatus() const - { - return status_; - } - - const char* What() const; - }; -} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Instance.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Instance.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,285 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Instance.h" + +#include "OrthancConnection.h" + +#include + +namespace OrthancClient +{ + void Instance::DownloadImage() + { + if (reader_.get() == NULL) + { + const char* suffix; + switch (mode_) + { + case Orthanc::ImageExtractionMode_Preview: + suffix = "preview"; + break; + + case Orthanc::ImageExtractionMode_UInt8: + suffix = "image-uint8"; + break; + + case Orthanc::ImageExtractionMode_UInt16: + suffix = "image-uint16"; + break; + + case Orthanc::ImageExtractionMode_Int16: + suffix = "image-int16"; + break; + + default: + throw OrthancClientException(Orthanc::ErrorCode_NotImplemented); + } + + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/instances/" + id_ + "/" + suffix); + std::string png; + + if (!client.Apply(png)) + { + throw OrthancClientException(Orthanc::ErrorCode_NotImplemented); + } + + reader_.reset(new Orthanc::PngReader); + reader_->ReadFromMemory(png); + } + } + + void Instance::DownloadDicom() + { + if (dicom_.get() == NULL) + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/instances/" + id_ + "/file"); + + dicom_.reset(new std::string); + + if (!client.Apply(*dicom_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + } + + Instance::Instance(const OrthancConnection& connection, + const char* id) : + connection_(connection), + id_(id), + mode_(Orthanc::ImageExtractionMode_Int16) + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/instances/" + id_ + "/simplified-tags"); + Json::Value v; + if (!client.Apply(tags_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + const char* Instance::GetTagAsString(const char* tag) const + { + if (tags_.isMember(tag)) + { + return tags_[tag].asCString(); + } + else + { + throw OrthancClientException(Orthanc::ErrorCode_InexistentItem); + } + } + + float Instance::GetTagAsFloat(const char* tag) const + { + std::string value = GetTagAsString(tag); + + try + { + return boost::lexical_cast(value); + } + catch (boost::bad_lexical_cast) + { + throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat); + } + } + + int Instance::GetTagAsInt(const char* tag) const + { + std::string value = GetTagAsString(tag); + + try + { + return boost::lexical_cast(value); + } + catch (boost::bad_lexical_cast) + { + throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat); + } + } + + unsigned int Instance::GetWidth() + { + DownloadImage(); + return reader_->GetWidth(); + } + + unsigned int Instance::GetHeight() + { + DownloadImage(); + return reader_->GetHeight(); + } + + unsigned int Instance::GetPitch() + { + DownloadImage(); + return reader_->GetPitch(); + } + + Orthanc::PixelFormat Instance::GetPixelFormat() + { + DownloadImage(); + return reader_->GetFormat(); + } + + const void* Instance::GetBuffer() + { + DownloadImage(); + return reader_->GetBuffer(); + } + + const void* Instance::GetBuffer(unsigned int y) + { + DownloadImage(); + return reader_->GetBuffer(y); + } + + void Instance::DiscardImage() + { + reader_.reset(); + } + + void Instance::DiscardDicom() + { + dicom_.reset(); + } + + + void Instance::SetImageExtractionMode(Orthanc::ImageExtractionMode mode) + { + if (mode_ == mode) + { + return; + } + + DiscardImage(); + mode_ = mode; + } + + + void Instance::SplitVectorOfFloats(std::vector& target, + const char* tag) + { + const std::string value = GetTagAsString(tag); + + target.clear(); + + try + { + std::string tmp; + for (size_t i = 0; i < value.size(); i++) + { + if (value[i] == '\\') + { + target.push_back(boost::lexical_cast(tmp)); + tmp.clear(); + } + else + { + tmp.push_back(value[i]); + } + } + + target.push_back(boost::lexical_cast(tmp)); + } + catch (boost::bad_lexical_cast) + { + // Unable to parse the Image Orientation Patient. + throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat); + } + } + + + const uint64_t Instance::GetDicomSize() + { + DownloadDicom(); + assert(dicom_.get() != NULL); + return dicom_->size(); + } + + const void* Instance::GetDicom() + { + DownloadDicom(); + assert(dicom_.get() != NULL); + + if (dicom_->size() == 0) + { + return NULL; + } + else + { + return &((*dicom_) [0]); + } + } + + + void Instance::LoadTagContent(const char* path) + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/instances/" + id_ + "/content/" + path); + + if (!client.Apply(content_)) + { + throw OrthancClientException(Orthanc::ErrorCode_UnknownResource); + } + } + + + const char* Instance::GetLoadedTagContent() const + { + return content_.c_str(); + } +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Instance.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Instance.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,202 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include +#include + +#include "OrthancClientException.h" +#include "../Core/IDynamicObject.h" +#include "../Core/FileFormats/PngReader.h" + +namespace OrthancClient +{ + class OrthancConnection; + + /** + * {summary}{Connection to an instance stored in %Orthanc.} + * {description}{This class encapsulates a connection to an image instance + * from a remote instance of %Orthanc.} + **/ + class LAAW_API Instance : public Orthanc::IDynamicObject + { + private: + const OrthancConnection& connection_; + std::string id_; + Json::Value tags_; + std::auto_ptr reader_; + Orthanc::ImageExtractionMode mode_; + std::auto_ptr dicom_; + std::string content_; + + void DownloadImage(); + + void DownloadDicom(); + + public: + /** + * {summary}{Create a connection to some image instance.} + * {param}{connection The remote instance of %Orthanc.} + * {param}{id The %Orthanc identifier of the image instance.} + **/ + Instance(const OrthancConnection& connection, + const char* id); + + + /** + * {summary}{Get the %Orthanc identifier of this identifier.} + * {returns}{The identifier.} + **/ + const char* GetId() const + { + return id_.c_str(); + } + + + /** + * {summary}{Set the extraction mode for the 2D image corresponding to this instance.} + * {param}{mode The extraction mode.} + **/ + void SetImageExtractionMode(Orthanc::ImageExtractionMode mode); + + /** + * {summary}{Get the extraction mode for the 2D image corresponding to this instance.} + * {returns}{The extraction mode.} + **/ + Orthanc::ImageExtractionMode GetImageExtractionMode() const + { + return mode_; + } + + + /** + * {summary}{Get the string value of some DICOM tag of this instance.} + * {param}{tag The name of the tag of interest.} + * {returns}{The value of the tag.} + **/ + const char* GetTagAsString(const char* tag) const; + + /** + * {summary}{Get the floating point value that is stored in some DICOM tag of this instance.} + * {param}{tag The name of the tag of interest.} + * {returns}{The value of the tag.} + **/ + float GetTagAsFloat(const char* tag) const; + + /** + * {summary}{Get the integer value that is stored in some DICOM tag of this instance.} + * {param}{tag The name of the tag of interest.} + * {returns}{The value of the tag.} + **/ + int32_t GetTagAsInt(const char* tag) const; + + + /** + * {summary}{Get the width of the 2D image.} + * {description}{Get the width of the 2D image that is encoded by this DICOM instance.} + * {returns}{The width.} + **/ + uint32_t GetWidth(); + + /** + * {summary}{Get the height of the 2D image.} + * {description}{Get the height of the 2D image that is encoded by this DICOM instance.} + * {returns}{The height.} + **/ + uint32_t GetHeight(); + + /** + * {summary}{Get the number of bytes between two lines of the image (pitch).} + * {description}{Get the number of bytes between two lines of the image in the memory buffer returned by GetBuffer(). This value depends on the extraction mode for the image.} + * {returns}{The pitch.} + **/ + uint32_t GetPitch(); + + /** + * {summary}{Get the format of the pixels of the 2D image.} + * {description}{Return the memory layout that is used for the 2D image that is encoded by this DICOM instance. This value depends on the extraction mode for the image.} + * {returns}{The pixel format.} + **/ + Orthanc::PixelFormat GetPixelFormat(); + + /** + * {summary}{Access the memory buffer in which the raw pixels of the 2D image are stored.} + * {returns}{A pointer to the memory buffer.} + **/ + const void* GetBuffer(); + + /** + * {summary}{Access the memory buffer in which the raw pixels of some line of the 2D image are stored.} + * {param}{y The line of interest.} + * {returns}{A pointer to the memory buffer.} + **/ + const void* GetBuffer(uint32_t y); + + /** + * {summary}{Get the size of the DICOM file corresponding to this instance.} + * {returns}{The file size.} + **/ + const uint64_t GetDicomSize(); + + /** + * {summary}{Get a pointer to the content of the DICOM file corresponding to this instance.} + * {returns}{The DICOM file.} + **/ + const void* GetDicom(); + + /** + * {summary}{Discard the downloaded 2D image, so as to make room in memory.} + **/ + void DiscardImage(); + + /** + * {summary}{Discard the downloaded DICOM file, so as to make room in memory.} + **/ + void DiscardDicom(); + + LAAW_API_INTERNAL void SplitVectorOfFloats(std::vector& target, + const char* tag); + + /** + * {summary}{Load a raw tag from the DICOM file.} + * {param}{path The path to the tag of interest (e.g. "0020-000d").} + **/ + void LoadTagContent(const char* path); + + /** + * {summary}{Return the value of the raw tag that was loaded by LoadContent.} + * {returns}{The tag value.} + **/ + const char* GetLoadedTagContent() const; + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/OrthancClientException.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/OrthancClientException.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,58 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Core/OrthancException.h" +#include + +namespace OrthancClient +{ + class OrthancClientException : public ::Laaw::LaawException + { + public: + OrthancClientException(Orthanc::ErrorCode code) : + LaawException(Orthanc::OrthancException::GetDescription(code)) + { + } + + OrthancClientException(const char* message) : + LaawException(message) + { + } + + OrthancClientException(const std::string& message) : + LaawException(message) + { + } + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/OrthancConnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/OrthancConnection.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,114 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "OrthancConnection.h" + +#include "../Core/Toolbox.h" + +namespace OrthancClient +{ + void OrthancConnection::ReadPatients() + { + client_.SetMethod(Orthanc::HttpMethod_Get); + client_.SetUrl(orthancUrl_ + "/patients"); + + Json::Value v; + if (!client_.Apply(content_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + Orthanc::IDynamicObject* OrthancConnection::GetFillerItem(size_t index) + { + Json::Value::ArrayIndex tmp = static_cast(index); + std::string id = content_[tmp].asString(); + return new Patient(*this, id.c_str()); + } + + Patient& OrthancConnection::GetPatient(unsigned int index) + { + return dynamic_cast(patients_.GetItem(index)); + } + + OrthancConnection::OrthancConnection(const char* orthancUrl) : + orthancUrl_(orthancUrl), patients_(*this) + { + ReadPatients(); + } + + OrthancConnection::OrthancConnection(const char* orthancUrl, + const char* username, + const char* password) : + orthancUrl_(orthancUrl), patients_(*this) + { + client_.SetCredentials(username, password); + ReadPatients(); + } + + + void OrthancConnection::Store(const void* dicom, uint64_t size) + { + if (size == 0) + { + return; + } + + client_.SetMethod(Orthanc::HttpMethod_Post); + client_.SetUrl(orthancUrl_ + "/instances"); + + // Copy the DICOM file in the POST body. TODO - Avoid memory copy + client_.AccessPostData().resize(static_cast(size)); + memcpy(&client_.AccessPostData()[0], dicom, static_cast(size)); + + Json::Value v; + if (!client_.Apply(v)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + + Reload(); + } + + + void OrthancConnection::StoreFile(const char* filename) + { + std::string content; + Orthanc::Toolbox::ReadFile(content, filename); + + if (content.size() != 0) + { + Store(&content[0], content.size()); + } + } + +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/OrthancConnection.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/OrthancConnection.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,180 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Core/HttpClient.h" + +#include "Patient.h" + +namespace OrthancClient +{ + /** + * {summary}{Connection to an instance of %Orthanc.} + * {description}{This class encapsulates a connection to a remote instance + * of %Orthanc through its REST API.} + **/ + class LAAW_API OrthancConnection : + public boost::noncopyable, + private Orthanc::ArrayFilledByThreads::IFiller + { + private: + Orthanc::HttpClient client_; + std::string orthancUrl_; + Orthanc::ArrayFilledByThreads patients_; + Json::Value content_; + + void ReadPatients(); + + virtual size_t GetFillerSize() + { + return content_.size(); + } + + virtual Orthanc::IDynamicObject* GetFillerItem(size_t index); + + public: + /** + * {summary}{Create a connection to an instance of %Orthanc.} + * {param}{orthancUrl URL to which the REST API of %Orthanc is listening.} + **/ + OrthancConnection(const char* orthancUrl); + + /** + * {summary}{Create a connection to an instance of %Orthanc, with authentication.} + * {param}{orthancUrl URL to which the REST API of %Orthanc is listening.} + * {param}{username The username.} + * {param}{password The password.} + **/ + OrthancConnection(const char* orthancUrl, + const char* username, + const char* password); + + virtual ~OrthancConnection() + { + } + + /** + * {summary}{Returns the number of threads for this connection.} + * {description}{Returns the number of simultaneous connections + * that are used when downloading information from this instance + * of %Orthanc.} + * {returns}{The number of threads.} + **/ + uint32_t GetThreadCount() const + { + return patients_.GetThreadCount(); + } + + /** + * {summary}{Sets the number of threads for this connection.} + * {description}{Sets the number of simultaneous connections + * that are used when downloading information from this instance + * of %Orthanc.} + * {param}{threadCount The number of threads.} + **/ + void SetThreadCount(uint32_t threadCount) + { + patients_.SetThreadCount(threadCount); + } + + /** + * {summary}{Reload the list of the patients.} + * {description}{This method will reload the list of the patients from the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated.} + **/ + void Reload() + { + ReadPatients(); + patients_.Invalidate(); + } + + LAAW_API_INTERNAL const Orthanc::HttpClient& GetHttpClient() const + { + return client_; + } + + /** + * {summary}{Returns the URL of this instance of %Orthanc.} + * {description}{Returns the URL of the remote %Orthanc instance to which this object is connected.} + * {returns}{The URL.} + **/ + const char* GetOrthancUrl() const + { + return orthancUrl_.c_str(); + } + + /** + * {summary}{Returns the number of patients.} + * {description}{Returns the number of patients that are stored in the remote instance of %Orthanc.} + * {returns}{The number of patients.} + **/ + uint32_t GetPatientCount() + { + return patients_.GetSize(); + } + + /** + * {summary}{Get some patient.} + * {description}{This method will return an object that contains information about some patient. The patients are indexed by a number between 0 (inclusive) and the result of GetPatientCount() (exclusive).} + * {param}{index The index of the patient of interest.} + * {returns}{The patient.} + **/ + Patient& GetPatient(uint32_t index); + + /** + * {summary}{Delete some patient.} + * {description}{Delete some patient from the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated.} + * {param}{index The index of the patient of interest.} + * {returns}{The patient.} + **/ + void DeletePatient(uint32_t index) + { + GetPatient(index).Delete(); + Reload(); + } + + /** + * {summary}{Send a DICOM file.} + * {description}{This method will store a DICOM file in the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated.} + * {param}{filename Path to the DICOM file} + **/ + void StoreFile(const char* filename); + + /** + * {summary}{Send a DICOM file that is contained inside a memory buffer.} + * {description}{This method will store a DICOM file in the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated.} + * {param}{dicom The memory buffer containing the DICOM file.} + * {param}{size The size of the DICOM file.} + **/ + void Store(const void* dicom, uint64_t size); + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Patient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Patient.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,92 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Patient.h" + +#include "OrthancConnection.h" + +namespace OrthancClient +{ + void Patient::ReadPatient() + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/patients/" + id_); + + Json::Value v; + if (!client.Apply(patient_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + Orthanc::IDynamicObject* Patient::GetFillerItem(size_t index) + { + Json::Value::ArrayIndex tmp = static_cast(index); + std::string id = patient_["Studies"][tmp].asString(); + return new Study(connection_, id.c_str()); + } + + Patient::Patient(const OrthancConnection& connection, + const char* id) : + connection_(connection), + id_(id), + studies_(*this) + { + studies_.SetThreadCount(connection.GetThreadCount()); + ReadPatient(); + } + + const char* Patient::GetMainDicomTag(const char* tag, const char* defaultValue) const + { + if (patient_["MainDicomTags"].isMember(tag)) + { + return patient_["MainDicomTags"][tag].asCString(); + } + else + { + return defaultValue; + } + } + + void Patient::Delete() + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetMethod(Orthanc::HttpMethod_Delete); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/patients/" + id_); + + std::string s; + if (!client.Apply(s)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Patient.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Patient.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,121 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "Study.h" + +namespace OrthancClient +{ + /** + * {summary}{Connection to a patient stored in %Orthanc.} + * {description}{This class encapsulates a connection to a patient + * from a remote instance of %Orthanc.} + **/ + class LAAW_API Patient : + public Orthanc::IDynamicObject, + private Orthanc::ArrayFilledByThreads::IFiller + { + private: + const OrthancConnection& connection_; + std::string id_; + Json::Value patient_; + Orthanc::ArrayFilledByThreads studies_; + + void ReadPatient(); + + virtual size_t GetFillerSize() + { + return patient_["Studies"].size(); + } + + virtual Orthanc::IDynamicObject* GetFillerItem(size_t index); + + public: + /** + * {summary}{Create a connection to some patient.} + * {param}{connection The remote instance of %Orthanc.} + * {param}{id The %Orthanc identifier of the patient.} + **/ + Patient(const OrthancConnection& connection, + const char* id); + + /** + * {summary}{Reload the studies of this patient.} + * {description}{This method will reload the list of the studies of this patient. Pay attention to the fact that the studies that have been previously returned by GetStudy() will be invalidated.} + **/ + void Reload() + { + studies_.Reload(); + } + + /** + * {summary}{Return the number of studies for this patient.} + * {returns}{The number of studies.} + **/ + uint32_t GetStudyCount() + { + return studies_.GetSize(); + } + + /** + * {summary}{Get some study of this patient.} + * {description}{This method will return an object that contains information about some study. The studies are indexed by a number between 0 (inclusive) and the result of GetStudyCount() (exclusive).} + * {param}{index The index of the study of interest.} + * {returns}{The study.} + **/ + Study& GetStudy(uint32_t index) + { + return dynamic_cast(studies_.GetItem(index)); + } + + /** + * {summary}{Get the %Orthanc identifier of this patient.} + * {returns}{The identifier.} + **/ + const char* GetId() const + { + return id_.c_str(); + } + + /** + * {summary}{Get the value of one of the main DICOM tags for this patient.} + * {param}{tag The name of the tag of interest ("PatientName", "PatientID", "PatientSex" or "PatientBirthDate").} + * {param}{defaultValue The default value to be returned if this tag does not exist.} + * {returns}{The value of the tag.} + **/ + const char* GetMainDicomTag(const char* tag, + const char* defaultValue) const; + + LAAW_API_INTERNAL void Delete(); + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Series.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Series.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,514 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Series.h" + +#include "OrthancConnection.h" + +#include +#include + +namespace OrthancClient +{ + namespace + { + class SliceLocator + { + private: + float normal_[3]; + + public: + SliceLocator(Instance& someSlice) + { + /** + * Compute the slice normal from Image Orientation Patient. + * http://nipy.sourceforge.net/nibabel/dicom/dicom_orientation.html#dicom-z-from-slice + * http://www.itk.org/pipermail/insight-users/2003-September/004762.html + **/ + + std::vector cosines; + someSlice.SplitVectorOfFloats(cosines, "ImageOrientationPatient"); + + if (cosines.size() != 6) + { + throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat); + } + + normal_[0] = cosines[1] * cosines[5] - cosines[2] * cosines[4]; + normal_[1] = cosines[2] * cosines[3] - cosines[0] * cosines[5]; + normal_[2] = cosines[0] * cosines[4] - cosines[1] * cosines[3]; + } + + + /** + * Compute the distance of some slice along the slice normal. + **/ + float ComputeSliceLocation(Instance& instance) const + { + std::vector ipp; + instance.SplitVectorOfFloats(ipp, "ImagePositionPatient"); + if (ipp.size() != 3) + { + throw OrthancClientException(Orthanc::ErrorCode_BadFileFormat); + } + + float dist = 0; + + for (int i = 0; i < 3; i++) + { + dist += normal_[i] * ipp[i]; + } + + return dist; + } + }; + + class ImageDownloadCommand : public Orthanc::ICommand + { + private: + Orthanc::PixelFormat format_; + Orthanc::ImageExtractionMode mode_; + Instance& instance_; + void* target_; + size_t lineStride_; + + public: + ImageDownloadCommand(Instance& instance, + Orthanc::PixelFormat format, + Orthanc::ImageExtractionMode mode, + void* target, + size_t lineStride) : + format_(format), + mode_(mode), + instance_(instance), + target_(target), + lineStride_(lineStride) + { + instance_.SetImageExtractionMode(mode); + } + + virtual bool Execute() + { + using namespace Orthanc; + + unsigned int width = instance_.GetHeight(); + + for (unsigned int y = 0; y < instance_.GetHeight(); y++) + { + uint8_t* p = reinterpret_cast(target_) + y * lineStride_; + + if (instance_.GetPixelFormat() == format_) + { + memcpy(p, instance_.GetBuffer(y), 2 * instance_.GetWidth()); + } + else if (instance_.GetPixelFormat() == PixelFormat_Grayscale8 && + format_ == PixelFormat_RGB24) + { + const uint8_t* s = reinterpret_cast(instance_.GetBuffer(y)); + for (unsigned int x = 0; x < width; x++, s++, p += 3) + { + p[0] = *s; + p[1] = *s; + p[2] = *s; + } + } + else + { + throw OrthancClientException(ErrorCode_NotImplemented); + } + } + + // Do not keep the image in memory, as we are loading 3D images + instance_.DiscardImage(); + + return true; + } + }; + + + class ProgressToFloatListener : public Orthanc::ThreadedCommandProcessor::IListener + { + private: + float* target_; + + public: + ProgressToFloatListener(float* target) : target_(target) + { + } + + virtual void SignalProgress(unsigned int current, + unsigned int total) + { + if (total == 0) + { + *target_ = 0; + } + else + { + *target_ = static_cast(current) / static_cast(total); + } + } + + virtual void SignalSuccess(unsigned int total) + { + *target_ = 1; + } + + virtual void SignalFailure() + { + *target_ = 0; + } + + virtual void SignalCancel() + { + *target_ = 0; + } + }; + + } + + + void Series::Check3DImage() + { + if (!Is3DImage()) + { + throw OrthancClientException(Orthanc::ErrorCode_NotImplemented); + } + } + + bool Series::Is3DImageInternal() + { + try + { + if (GetInstanceCount() == 0) + { + return true; + } + + Instance& i1 = GetInstance(0); + + for (unsigned int i = 0; i < GetInstanceCount(); i++) + { + Instance& i2 = GetInstance(i); + + if (std::string(i1.GetTagAsString("Columns")) != std::string(i2.GetTagAsString("Columns")) || + std::string(i1.GetTagAsString("Rows")) != std::string(i2.GetTagAsString("Rows")) || + std::string(i1.GetTagAsString("ImageOrientationPatient")) != std::string(i2.GetTagAsString("ImageOrientationPatient")) || + std::string(i1.GetTagAsString("SliceThickness")) != std::string(i2.GetTagAsString("SliceThickness")) || + std::string(i1.GetTagAsString("PixelSpacing")) != std::string(i2.GetTagAsString("PixelSpacing"))) + { + return false; + } + } + + SliceLocator locator(GetInstance(0)); + std::set l; + for (unsigned int i = 0; i < GetInstanceCount(); i++) + { + l.insert(locator.ComputeSliceLocation(GetInstance(i))); + } + + return l.size() == GetInstanceCount(); + } + catch (OrthancClientException) + { + return false; + } + } + + void Series::ReadSeries() + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/series/" + id_); + Json::Value v; + if (!client.Apply(series_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + Orthanc::IDynamicObject* Series::GetFillerItem(size_t index) + { + Json::Value::ArrayIndex tmp = static_cast(index); + std::string id = series_["Instances"][tmp].asString(); + return new Instance(connection_, id.c_str()); + } + + Series::Series(const OrthancConnection& connection, + const char* id) : + connection_(connection), + id_(id), + instances_(*this) + { + ReadSeries(); + status_ = Status3DImage_NotTested; + url_ = std::string(connection_.GetOrthancUrl()) + "/series/" + id_; + + isVoxelSizeRead_ = false; + voxelSizeX_ = 0; + voxelSizeY_ = 0; + voxelSizeZ_ = 0; + + instances_.SetThreadCount(connection.GetThreadCount()); + } + + + bool Series::Is3DImage() + { + if (status_ == Status3DImage_NotTested) + { + status_ = Is3DImageInternal() ? Status3DImage_True : Status3DImage_False; + } + + return status_ == Status3DImage_True; + } + + unsigned int Series::GetInstanceCount() + { + return instances_.GetSize(); + } + + Instance& Series::GetInstance(unsigned int index) + { + return dynamic_cast(instances_.GetItem(index)); + } + + unsigned int Series::GetWidth() + { + Check3DImage(); + + if (GetInstanceCount() == 0) + return 0; + else + return GetInstance(0).GetTagAsInt("Columns"); + } + + unsigned int Series::GetHeight() + { + Check3DImage(); + + if (GetInstanceCount() == 0) + return 0; + else + return GetInstance(0).GetTagAsInt("Rows"); + } + + void Series::LoadVoxelSize() + { + if (isVoxelSizeRead_) + { + return; + } + + Check3DImage(); + + if (GetInstanceCount() == 0) + { + // Empty image, use some default value + voxelSizeX_ = 1; + voxelSizeY_ = 1; + voxelSizeZ_ = 1; + } + else + { + try + { + std::string s = GetInstance(0).GetTagAsString("PixelSpacing"); + size_t pos = s.find('\\'); + assert(pos != std::string::npos); + std::string sy = s.substr(0, pos); + std::string sx = s.substr(pos + 1); + + voxelSizeX_ = boost::lexical_cast(sx); + voxelSizeY_ = boost::lexical_cast(sy); + voxelSizeZ_ = GetInstance(0).GetTagAsFloat("SliceThickness"); + } + catch (boost::bad_lexical_cast) + { + throw OrthancClientException(Orthanc::ErrorCode_NotImplemented); + } + } + + isVoxelSizeRead_ = true; + } + + + const char* Series::GetMainDicomTag(const char* tag, const char* defaultValue) const + { + if (series_["MainDicomTags"].isMember(tag)) + { + return series_["MainDicomTags"][tag].asCString(); + } + else + { + return defaultValue; + } + } + + + + void Series::Load3DImageInternal(void* target, + Orthanc::PixelFormat format, + size_t lineStride, + size_t stackStride, + Orthanc::ThreadedCommandProcessor::IListener* listener) + { + using namespace Orthanc; + + // Choose the extraction mode, depending on the format of the + // target image. + + uint8_t bytesPerPixel; + ImageExtractionMode mode; + + switch (format) + { + case PixelFormat_RGB24: + bytesPerPixel = 3; + mode = ImageExtractionMode_Preview; + break; + + case PixelFormat_Grayscale8: + bytesPerPixel = 1; + mode = ImageExtractionMode_UInt8; // Preview ??? + break; + + case PixelFormat_Grayscale16: + bytesPerPixel = 2; + mode = ImageExtractionMode_UInt16; + break; + + case PixelFormat_SignedGrayscale16: + bytesPerPixel = 2; + mode = ImageExtractionMode_UInt16; + format = PixelFormat_Grayscale16; + break; + + default: + throw OrthancClientException(ErrorCode_NotImplemented); + } + + + // Check that the target image is properly sized + unsigned int sx = GetWidth(); + unsigned int sy = GetHeight(); + + if (lineStride < sx * bytesPerPixel || + stackStride < sx * sy * bytesPerPixel) + { + throw OrthancClientException(ErrorCode_BadRequest); + } + + if (sx == 0 || sy == 0 || GetInstanceCount() == 0) + { + // Empty image, nothing to do + if (listener) + listener->SignalSuccess(0); + return; + } + + + /** + * Order the stacks according to their distance along the slice + * normal (using the "Image Position Patient" tag). This works + * even if the "SliceLocation" tag is absent. + **/ + SliceLocator locator(GetInstance(0)); + + typedef std::map Instances; + Instances instances; + for (unsigned int i = 0; i < GetInstanceCount(); i++) + { + float dist = locator.ComputeSliceLocation(GetInstance(i)); + instances[dist] = &GetInstance(i); + } + + if (instances.size() != GetInstanceCount()) + { + // Several instances have the same Z coordinate + throw OrthancClientException(ErrorCode_NotImplemented); + } + + + // Submit the download of each stack as a set of commands + ThreadedCommandProcessor processor(connection_.GetThreadCount()); + + if (listener != NULL) + { + processor.SetListener(*listener); + } + + uint8_t* stackTarget = reinterpret_cast(target); + for (Instances::iterator it = instances.begin(); it != instances.end(); ++it) + { + processor.Post(new ImageDownloadCommand(*it->second, format, mode, stackTarget, lineStride)); + stackTarget += stackStride; + } + + + // Wait for all the stacks to be downloaded + if (!processor.Join()) + { + throw OrthancClientException(ErrorCode_NetworkProtocol); + } + } + + float Series::GetVoxelSizeX() + { + LoadVoxelSize(); + return voxelSizeX_; + } + + float Series::GetVoxelSizeY() + { + LoadVoxelSize(); + return voxelSizeY_; + } + + float Series::GetVoxelSizeZ() + { + LoadVoxelSize(); + return voxelSizeZ_; + } + + void Series::Load3DImage(void* target, + Orthanc::PixelFormat format, + int64_t lineStride, + int64_t stackStride, + float* progress) + { + ProgressToFloatListener listener(progress); + Load3DImageInternal(target, format, static_cast(lineStride), + static_cast(stackStride), &listener); + } +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Series.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Series.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,234 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "Instance.h" + +#include "../Core/MultiThreading/ArrayFilledByThreads.h" +#include "../Core/MultiThreading/ThreadedCommandProcessor.h" + +namespace OrthancClient +{ + /** + * {summary}{Connection to a series stored in %Orthanc.} + * {description}{This class encapsulates a connection to a series + * from a remote instance of %Orthanc.} + **/ + class LAAW_API Series : + public Orthanc::IDynamicObject, + private Orthanc::ArrayFilledByThreads::IFiller + { + private: + enum Status3DImage + { + Status3DImage_NotTested, + Status3DImage_True, + Status3DImage_False + }; + + const OrthancConnection& connection_; + std::string id_, url_; + Json::Value series_; + Orthanc::ArrayFilledByThreads instances_; + Status3DImage status_; + + bool isVoxelSizeRead_; + float voxelSizeX_; + float voxelSizeY_; + float voxelSizeZ_; + + void Check3DImage(); + + bool Is3DImageInternal(); + + void ReadSeries(); + + virtual size_t GetFillerSize() + { + return series_["Instances"].size(); + } + + virtual Orthanc::IDynamicObject* GetFillerItem(size_t index); + + void Load3DImageInternal(void* target, + Orthanc::PixelFormat format, + size_t lineStride, + size_t stackStride, + Orthanc::ThreadedCommandProcessor::IListener* listener); + + void LoadVoxelSize(); + + public: + /** + * {summary}{Create a connection to some series.} + * {param}{connection The remote instance of %Orthanc.} + * {param}{id The %Orthanc identifier of the series.} + **/ + Series(const OrthancConnection& connection, + const char* id); + + /** + * {summary}{Reload the instances of this series.} + * {description}{This method will reload the list of the instances of this series. Pay attention to the fact that the instances that have been previously returned by GetInstance() will be invalidated.} + **/ + void Reload() + { + instances_.Reload(); + } + + /** + * {summary}{Return the number of instances for this series.} + * {returns}{The number of instances.} + **/ + uint32_t GetInstanceCount(); + + /** + * {summary}{Get some instance of this series.} + * {description}{This method will return an object that contains information about some instance. The instances are indexed by a number between 0 (inclusive) and the result of GetInstanceCount() (exclusive).} + * {param}{index The index of the instance of interest.} + * {returns}{The instance.} + **/ + Instance& GetInstance(uint32_t index); + + /** + * {summary}{Get the %Orthanc identifier of this series.} + * {returns}{The identifier.} + **/ + const char* GetId() const + { + return id_.c_str(); + } + + /** + * {summary}{Returns the URL to this series.} + * {returns}{The URL.} + **/ + const char* GetUrl() const + { + return url_.c_str(); + } + + + /** + * {summary}{Get the value of one of the main DICOM tags for this series.} + * {param}{tag The name of the tag of interest ("Modality", "Manufacturer", "SeriesDate", "SeriesDescription", "SeriesInstanceUID"...).} + * {param}{defaultValue The default value to be returned if this tag does not exist.} + * {returns}{The value of the tag.} + **/ + const char* GetMainDicomTag(const char* tag, + const char* defaultValue) const; + + /** + * {summary}{Test whether this series encodes a 3D image that can be downloaded from %Orthanc.} + * {returns}{"true" if and only if this is a 3D image.} + **/ + bool Is3DImage(); + + /** + * {summary}{Get the width of the 3D image.} + * {description}{Get the width of the 3D image (i.e. along the X-axis). This call is only valid if this series corresponds to a 3D image.} + * {returns}{The width.} + **/ + uint32_t GetWidth(); + + /** + * {summary}{Get the height of the 3D image.} + * {description}{Get the height of the 3D image (i.e. along the Y-axis). This call is only valid if this series corresponds to a 3D image.} + * {returns}{The height.} + **/ + uint32_t GetHeight(); + + /** + * {summary}{Get the physical size of a voxel along the X-axis.} + * {description}{Get the physical size of a voxel along the X-axis. This call is only valid if this series corresponds to a 3D image.} + * {returns}{The voxel size.} + **/ + float GetVoxelSizeX(); + + /** + * {summary}{Get the physical size of a voxel along the Y-axis.} + * {description}{Get the physical size of a voxel along the Y-axis. This call is only valid if this series corresponds to a 3D image.} + * {returns}{The voxel size.} + **/ + float GetVoxelSizeY(); + + /** + * {summary}{Get the physical size of a voxel along the Z-axis.} + * {description}{Get the physical size of a voxel along the Z-axis. This call is only valid if this series corresponds to a 3D image.} + * {returns}{The voxel size.} + **/ + float GetVoxelSizeZ(); + + LAAW_API_INTERNAL void Load3DImage(void* target, + Orthanc::PixelFormat format, + int64_t lineStride, + int64_t stackStride, + Orthanc::ThreadedCommandProcessor::IListener& listener) + { + Load3DImageInternal(target, format, static_cast(lineStride), + static_cast(stackStride), &listener); + } + + /** + * {summary}{Load the 3D image into a memory buffer.} + * {description}{Load the 3D image into a memory buffer. This call is only valid if this series corresponds to a 3D image. The "target" buffer must be wide enough to store all the voxels of the image.} + * {param}{target The target memory buffer.} + * {param}{format The memory layout of the voxels.} + * {param}{lineStride The number of bytes between two lines in the target memory buffer.} + * {param}{stackStride The number of bytes between two 2D slices in the target memory buffer.} + **/ + void Load3DImage(void* target, + Orthanc::PixelFormat format, + int64_t lineStride, + int64_t stackStride) + { + Load3DImageInternal(target, format, static_cast(lineStride), + static_cast(stackStride), NULL); + } + + /** + * {summary}{Load the 3D image into a memory buffer.} + * {description}{Load the 3D image into a memory buffer. This call is only valid if this series corresponds to a 3D image. The "target" buffer must be wide enough to store all the voxels of the image. This method will also update a progress indicator to monitor the loading of the image.} + * {param}{target The target memory buffer.} + * {param}{format The memory layout of the voxels.} + * {param}{lineStride The number of bytes between two lines in the target memory buffer.} + * {param}{stackStride The number of bytes between two 2D slices in the target memory buffer.} + * {param}{progress A pointer to a floating-point number that is continuously updated by the download threads to reflect the percentage of completion (between 0 and 1). This value can be read from a separate thread.} + **/ + void Load3DImage(void* target, + Orthanc::PixelFormat format, + int64_t lineStride, + int64_t stackStride, + float* progress); + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/ExternC.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,1502 @@ +/** + * Laaw - Lightweight, Automated API Wrapper + * Copyright (C) 2010-2013 Jomago - Alain Mazy, Benjamin Golinvaux, + * Sebastien Jodogne + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include +#include // For strcpy() and strlen() +#include // For free() + +static char* LAAW_EXTERNC_CopyString(const char* str) +{ + char* copy = reinterpret_cast(malloc(strlen(str) + 1)); + strcpy(copy, str); + return copy; +} + +extern "C" +{ + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_1f1acb322ea4d0aad65172824607673c(void** newObject, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::OrthancConnection(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_f3fd272e4636f6a531aabb72ee01cd5b(void** newObject, const char* arg0, const char* arg1, const char* arg2) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::OrthancConnection(reinterpret_cast< const char* >(arg0), reinterpret_cast< const char* >(arg1), reinterpret_cast< const char* >(arg2)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_12d3de0a96e9efb11136a9811bb9ed38(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + delete static_cast(thisObject); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7(const void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +*result = this_->GetThreadCount(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e(void* thisObject, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +this_->SetThreadCount(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +this_->Reload(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_e840242bf58d17d3c1d722da09ce88e0(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +*result = this_->GetOrthancUrl(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_c9af31433001b5dfc012a552dc6d0050(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +*result = this_->GetPatientCount(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_3fba4d6b818180a44cd1cae6046334dc(void* thisObject, void** result, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +*result = &this_->GetPatient(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_aeb20dc75b9246188db857317e5e0ce7(void* thisObject, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +this_->DeletePatient(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_62689803d9871e4d9c51a648640b320b(void* thisObject, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +this_->StoreFile(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_2fb64c9e5a67eccd413b0e913469a421(void* thisObject, const void* arg0, uint64_t arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::OrthancConnection* this_ = static_cast(thisObject); +this_->Store(reinterpret_cast< const void* >(arg0), arg1); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_6cf0d7268667f9b0aa4511bacf184919(void** newObject, void* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::Patient(*reinterpret_cast< ::OrthancClient::OrthancConnection* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_7d81cd502ee27e859735d0ea7112b5a1(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + delete static_cast(thisObject); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_f756172daf04516eec3a566adabb4335(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Patient* this_ = static_cast(thisObject); +this_->Reload(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_ddb68763ec902a97d579666a73a20118(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Patient* this_ = static_cast(thisObject); +*result = this_->GetStudyCount(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_fba3c68b4be7558dbc65f7ce1ab57d63(void* thisObject, void** result, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Patient* this_ = static_cast(thisObject); +*result = &this_->GetStudy(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_b4ca99d958f843493e58d1ef967340e1(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Patient* this_ = static_cast(thisObject); +*result = this_->GetId(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_78d5cc76d282437b6f93ec3b82c35701(const void* thisObject, const char** result, const char* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Patient* this_ = static_cast(thisObject); +*result = this_->GetMainDicomTag(reinterpret_cast< const char* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342(void** newObject, void* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::Series(*reinterpret_cast< ::OrthancClient::OrthancConnection* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + delete static_cast(thisObject); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_48a2a1a9d68c047e22bfba23014643d2(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +this_->Reload(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_852bf8296ca21c5fde5ec565cc10721d(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetInstanceCount(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_efd04574e0779faa83df1f2d8f9888db(void* thisObject, void** result, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = &this_->GetInstance(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_736247ff5e8036dac38163da6f666ed5(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetId(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_d82d2598a7a73f4b6fcc0c09c25b08ca(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetUrl(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_88134b978f9acb2aecdadf54aeab3c64(const void* thisObject, const char** result, const char* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetMainDicomTag(reinterpret_cast< const char* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_152cb1b704c053d24b0dab7461ba6ea3(void* thisObject, int32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->Is3DImage(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_eee03f337ec81d9f1783cd41e5238757(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetWidth(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_006f08237bd7611636fc721baebfb4c5(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetHeight(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0(void* thisObject, float* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetVoxelSizeX(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab(void* thisObject, float* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetVoxelSizeY(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d(void* thisObject, float* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +*result = this_->GetVoxelSizeZ(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5(void* thisObject, void* arg0, int32_t arg1, int64_t arg2, int64_t arg3) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +this_->Load3DImage(reinterpret_cast< void* >(arg0), static_cast< ::Orthanc::PixelFormat >(arg1), arg2, arg3); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c(void* thisObject, void* arg0, int32_t arg1, int64_t arg2, int64_t arg3, float* arg4) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Series* this_ = static_cast(thisObject); +this_->Load3DImage(reinterpret_cast< void* >(arg0), static_cast< ::Orthanc::PixelFormat >(arg1), arg2, arg3, reinterpret_cast< float* >(arg4)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678(void** newObject, void* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::Study(*reinterpret_cast< ::OrthancClient::OrthancConnection* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + delete static_cast(thisObject); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Study* this_ = static_cast(thisObject); +this_->Reload(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Study* this_ = static_cast(thisObject); +*result = this_->GetSeriesCount(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05(void* thisObject, void** result, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Study* this_ = static_cast(thisObject); +*result = &this_->GetSeries(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Study* this_ = static_cast(thisObject); +*result = this_->GetId(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654(const void* thisObject, const char** result, const char* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Study* this_ = static_cast(thisObject); +*result = this_->GetMainDicomTag(reinterpret_cast< const char* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d(void** newObject, void* arg0, const char* arg1) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + *newObject = new OrthancClient::Instance(*reinterpret_cast< ::OrthancClient::OrthancConnection* >(arg0), reinterpret_cast< const char* >(arg1)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + delete static_cast(thisObject); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetId(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146(void* thisObject, int32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +this_->SetImageExtractionMode(static_cast< ::Orthanc::ImageExtractionMode >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda(const void* thisObject, int32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetImageExtractionMode(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484(const void* thisObject, const char** result, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetTagAsString(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb(const void* thisObject, float* result, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetTagAsFloat(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_1729a067d902771517388eedd7346b23(const void* thisObject, int32_t* result, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetTagAsInt(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetWidth(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetHeight(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8(void* thisObject, uint32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetPitch(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c(void* thisObject, int32_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetPixelFormat(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b(void* thisObject, const void** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetBuffer(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef(void* thisObject, const void** result, uint32_t arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetBuffer(arg0); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91(void* thisObject, uint64_t* result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetDicomSize(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e(void* thisObject, const void** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetDicom(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +this_->DiscardImage(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c(void* thisObject) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +this_->DiscardDicom(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd(void* thisObject, const char* arg0) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + OrthancClient::Instance* this_ = static_cast(thisObject); +this_->LoadTagContent(reinterpret_cast< const char* >(arg0)); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + LAAW_EXPORT_DLL_API char* LAAW_CALL_CONVENTION LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb(const void* thisObject, const char** result) + { + try + { + #ifdef LAAW_EXTERNC_START_FUNCTION + LAAW_EXTERNC_START_FUNCTION; + #endif + + const OrthancClient::Instance* this_ = static_cast(thisObject); +*result = this_->GetLoadedTagContent(); + + return NULL; + } + catch (::Laaw::LaawException& e) + { + return LAAW_EXTERNC_CopyString(e.What()); + } + catch (...) + { + return LAAW_EXTERNC_CopyString("..."); + } + } + + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetDescription() + { + return "Native client to the REST API of Orthanc"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetCompany() + { + return "CHU of Liege"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetProduct() + { + return "OrthancClient"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetCopyright() + { + return "(c) 2012-2014, Sebastien Jodogne, CHU of Liege"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetVersion() + { + return "0.7"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetFileVersion() + { + return "0.7.0.4"; + } + + LAAW_EXPORT_DLL_API const char* LAAW_CALL_CONVENTION LAAW_EXTERNC_GetFullVersion() + { + return "0.7.4"; + } + + LAAW_EXPORT_DLL_API void LAAW_CALL_CONVENTION LAAW_EXTERNC_FreeString(char* str) + { + if (str != NULL) + free(str); + } +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/OrthancCppClient.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/OrthancCppClient.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,1784 @@ +/** + * Laaw - Lightweight, Automated API Wrapper + * Copyright (C) 2010-2013 Jomago - Alain Mazy, Benjamin Golinvaux, + * Sebastien Jodogne + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +/** + * @file + **/ + +#pragma once + +#include +#include +#include +#include + +#if defined(_WIN32) + +/******************************************************************** + ** This is the Windows-specific section + ********************************************************************/ + +#include + +/* cf. http://sourceforge.net/p/predef/wiki/Architectures/ */ +#ifdef _M_X64 +/* 64 bits target */ +#define LAAW_ORTHANC_CLIENT_CALL_CONV __fastcall +#define LAAW_ORTHANC_CLIENT_CALL_DECORATION(Name, StdCallSuffix) Name +#define LAAW_ORTHANC_CLIENT_DEFAULT_PATH "OrthancClient_Windows64.dll" +#else +/* 32 bits target */ +#define LAAW_ORTHANC_CLIENT_CALL_CONV __stdcall +#define LAAW_ORTHANC_CLIENT_CALL_DECORATION(Name, StdCallSuffix) "_" Name "@" StdCallSuffix +#define LAAW_ORTHANC_CLIENT_DEFAULT_PATH "OrthancClient_Windows32.dll" +#endif + +#define LAAW_ORTHANC_CLIENT_HANDLE_TYPE HINSTANCE +#define LAAW_ORTHANC_CLIENT_HANDLE_NULL 0 +#define LAAW_ORTHANC_CLIENT_FUNCTION_TYPE FARPROC +#define LAAW_ORTHANC_CLIENT_LOADER(path) LoadLibraryA(path) +#define LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle, name, decoration) GetProcAddress(handle, LAAW_ORTHANC_CLIENT_CALL_DECORATION(name, decoration)) +#define LAAW_ORTHANC_CLIENT_CLOSER(handle) FreeLibrary(handle) + + +/******************************************************************** + ** This is the Linux-specific section + ********************************************************************/ + +#elif defined (__linux) + +#include +#include + +/* cf. http://sourceforge.net/p/predef/wiki/Architectures/ */ +#ifdef __amd64__ +#define LAAW_ORTHANC_CLIENT_DEFAULT_PATH "libOrthancClient.so.0.7" +#else +#define LAAW_ORTHANC_CLIENT_DEFAULT_PATH "libOrthancClient.so.0.7" +#endif + +#define LAAW_ORTHANC_CLIENT_CALL_CONV +#define LAAW_ORTHANC_CLIENT_HANDLE_TYPE void* +#define LAAW_ORTHANC_CLIENT_HANDLE_NULL NULL +#define LAAW_ORTHANC_CLIENT_FUNCTION_TYPE intptr_t +#define LAAW_ORTHANC_CLIENT_LOADER(path) dlopen(path, RTLD_LAZY) +#define LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle, name, decoration) (LAAW_ORTHANC_CLIENT_FUNCTION_TYPE) dlsym(handle, name) +#define LAAW_ORTHANC_CLIENT_CLOSER(handle) dlclose(handle) + + +#else +#error Please support your platform here +#endif + + +/******************************************************************** + ** Definition of the integer types + ********************************************************************/ + +#ifndef LAAW_INT8 // Only define the integer types once + +#if defined(__GNUC__) + +// Under GCC (including MinGW), the stdint.h standard header is used. + +#include + +#define LAAW_INT8 int8_t +#define LAAW_UINT8 uint8_t +#define LAAW_INT16 int16_t +#define LAAW_UINT16 uint16_t +#define LAAW_INT32 int32_t +#define LAAW_UINT32 uint32_t +#define LAAW_INT64 int64_t +#define LAAW_UINT64 uint64_t + +#elif defined(_MSC_VER) + +// Under Visual Studio, it is required to define the various integer +// types by hand. + +#if (_MSC_VER < 1300) +typedef signed char LAAW_INT8; +typedef signed short LAAW_INT16; +typedef signed int LAAW_INT32; +typedef unsigned char LAAW_UINT8; +typedef unsigned short LAAW_UINT16; +typedef unsigned int LAAW_UINT32; +#else +typedef signed __int8 LAAW_INT8; +typedef signed __int16 LAAW_INT16; +typedef signed __int32 LAAW_INT32; +typedef unsigned __int8 LAAW_UINT8; +typedef unsigned __int16 LAAW_UINT16; +typedef unsigned __int32 LAAW_UINT32; +#endif + +typedef signed __int64 LAAW_INT64; +typedef unsigned __int64 LAAW_UINT64; + +#else +#error "Please support your compiler here" +#endif + +#endif + + + + + +/******************************************************************** + ** This is a shared section between Windows and Linux + ********************************************************************/ + +namespace OrthancClient { +/** + * @brief Exception class that is thrown by the functions of this shared library. + **/ +class OrthancClientException : public std::exception + { + private: + std::string message_; + + public: + /** + * @brief Constructs an exception. + * @param message The error message. + **/ + OrthancClientException(std::string message) : message_(message) + { + } + + ~OrthancClientException() throw() + { + } + + /** + * @brief Get the error message associated with this exception. + * @returns The error message. + **/ + const std::string& What() const throw() + { + return message_; + } +}; +} + + +namespace OrthancClient { namespace Internals { +/** + * This internal class implements a Singleton design pattern that will + * store a reference to the shared library handle, together with a + * pointer to each function in the shared library. + **/ +class Library + { + private: + LAAW_ORTHANC_CLIENT_HANDLE_TYPE handle_; + LAAW_ORTHANC_CLIENT_FUNCTION_TYPE functionsIndex_[62 + 1]; + + + + void Load(const char* sharedLibraryPath) + { + + if (handle_ != LAAW_ORTHANC_CLIENT_HANDLE_NULL) + { + // Do nothing if the library is already loaded + return; + } + + /* Setup the path to the default shared library if not provided */ + if (sharedLibraryPath == NULL) + { + sharedLibraryPath = LAAW_ORTHANC_CLIENT_DEFAULT_PATH; + } + + /* Load the shared library */ + handle_ = LAAW_ORTHANC_CLIENT_LOADER(sharedLibraryPath); + + + if (handle_ == LAAW_ORTHANC_CLIENT_HANDLE_NULL) + { + throw ::OrthancClient::OrthancClientException("Error loading shared library"); + } + + LoadFunctions(); + } + + inline void LoadFunctions(); + + void FreeString(char* str) + { + typedef void (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (char*); + Function function = (Function) GetFunction(62); + function(str); + } + + Library() + { + handle_ = LAAW_ORTHANC_CLIENT_HANDLE_NULL; + } + + ~Library() + { + Finalize(); + } + + public: + LAAW_ORTHANC_CLIENT_FUNCTION_TYPE GetFunction(unsigned int index) + { + /** + * If the library has not been manually initialized by a call to + * ::OrthancClient::Initialize(), it is loaded from + * the default location (lazy initialization). + **/ + if (handle_ == NULL) + { + Load(NULL); + } + + return functionsIndex_[index]; + } + + void ThrowExceptionIfNeeded(char* message) + { + if (message != NULL) + { + std::string tmp(message); + FreeString(message); + throw ::OrthancClient::OrthancClientException(tmp); + } + } + + static inline Library& GetInstance() + { + /** + * This function defines a "static variable" inside a "static + * inline method" of a class. This ensures that a single + * instance of this variable will be used across all the + * compilation modules of the software. + * http://stackoverflow.com/a/1389403/881731 + **/ + + static Library singleton; + return singleton; + } + + static void Initialize(const char* sharedLibraryPath) + { + GetInstance().Load(sharedLibraryPath); + } + + void Finalize() + { + if (handle_ != LAAW_ORTHANC_CLIENT_HANDLE_NULL) + { + LAAW_ORTHANC_CLIENT_CLOSER(handle_); + handle_ = LAAW_ORTHANC_CLIENT_HANDLE_NULL; + } + } +}; +}} + + +/*! + * \addtogroup Global Global definitions. + * @{ + * @} + */ + + +namespace OrthancClient { +/*! + * \addtogroup Initialization Initialization of the shared library. + * @{ + */ + +/** + * @brief Manually initialize the shared library, using the default library name. + * + * Call this method before using the library to ensure correct + * behaviour in multi-threaded applications. This method is also + * useful to control the time at which the shared library is + * loaded (e.g. for real-time applications). + **/ +inline void Initialize() +{ + ::OrthancClient::Internals::Library::Initialize(NULL); +} + +/** + * @brief Manually initialize the shared library. + * + * Call this method before using the library to ensure correct + * behaviour in multi-threaded applications. This method is also + * useful to control the time at which the shared library is + * loaded (e.g. for real-time applications). + * + * @param sharedLibraryPath The path to the shared library that + * contains the module. + **/ +inline void Initialize(const std::string& sharedLibraryPath) +{ + ::OrthancClient::Internals::Library::Initialize(sharedLibraryPath.c_str()); +} + +/** + * @brief Manually finalize the shared library. + * + * Calling explicitly this function is not mandatory. It is useful to + * force the release of the resources acquired by the shared library, + * or to manually control the order in which the global variables get + * deleted. + **/ +inline void Finalize() +{ + ::OrthancClient::Internals::Library::GetInstance().Finalize(); +} + + +/** + * @} + */ +} + + +namespace OrthancClient { namespace Internals { +inline void Library::LoadFunctions() +{ + typedef const char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (); + Function getVersion = (Function) LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_GetVersion", "0"); + if (getVersion == NULL) + { + throw ::OrthancClient::OrthancClientException("Unable to get the library version"); + } + + /** + * It is assumed that the API does not change when the revision + * number (MAJOR.MINOR.REVISION) changes. + **/ + if (strcmp(getVersion(), "0.7")) + { + throw ::OrthancClient::OrthancClientException("Mismatch between the C++ header and the library version"); + } + + functionsIndex_[62] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_FreeString", "4"); + functionsIndex_[3] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7", "8"); + functionsIndex_[4] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e", "8"); + functionsIndex_[5] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f", "4"); + functionsIndex_[6] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e840242bf58d17d3c1d722da09ce88e0", "8"); + functionsIndex_[7] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c9af31433001b5dfc012a552dc6d0050", "8"); + functionsIndex_[8] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_3fba4d6b818180a44cd1cae6046334dc", "12"); + functionsIndex_[9] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_aeb20dc75b9246188db857317e5e0ce7", "8"); + functionsIndex_[10] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_62689803d9871e4d9c51a648640b320b", "8"); + functionsIndex_[11] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2fb64c9e5a67eccd413b0e913469a421", "16"); + functionsIndex_[0] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1f1acb322ea4d0aad65172824607673c", "8"); + functionsIndex_[1] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_f3fd272e4636f6a531aabb72ee01cd5b", "16"); + functionsIndex_[2] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_12d3de0a96e9efb11136a9811bb9ed38", "4"); + functionsIndex_[14] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_f756172daf04516eec3a566adabb4335", "4"); + functionsIndex_[15] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_ddb68763ec902a97d579666a73a20118", "8"); + functionsIndex_[16] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_fba3c68b4be7558dbc65f7ce1ab57d63", "12"); + functionsIndex_[17] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b4ca99d958f843493e58d1ef967340e1", "8"); + functionsIndex_[18] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_78d5cc76d282437b6f93ec3b82c35701", "16"); + functionsIndex_[12] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6cf0d7268667f9b0aa4511bacf184919", "12"); + functionsIndex_[13] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_7d81cd502ee27e859735d0ea7112b5a1", "4"); + functionsIndex_[21] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_48a2a1a9d68c047e22bfba23014643d2", "4"); + functionsIndex_[22] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_852bf8296ca21c5fde5ec565cc10721d", "8"); + functionsIndex_[23] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_efd04574e0779faa83df1f2d8f9888db", "12"); + functionsIndex_[24] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_736247ff5e8036dac38163da6f666ed5", "8"); + functionsIndex_[25] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_d82d2598a7a73f4b6fcc0c09c25b08ca", "8"); + functionsIndex_[26] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_88134b978f9acb2aecdadf54aeab3c64", "16"); + functionsIndex_[27] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_152cb1b704c053d24b0dab7461ba6ea3", "8"); + functionsIndex_[28] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_eee03f337ec81d9f1783cd41e5238757", "8"); + functionsIndex_[29] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_006f08237bd7611636fc721baebfb4c5", "8"); + functionsIndex_[30] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0", "8"); + functionsIndex_[31] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab", "8"); + functionsIndex_[32] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d", "8"); + functionsIndex_[33] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5", "28"); + functionsIndex_[34] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c", "32"); + functionsIndex_[19] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342", "12"); + functionsIndex_[20] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0", "4"); + functionsIndex_[37] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7", "4"); + functionsIndex_[38] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321", "8"); + functionsIndex_[39] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05", "12"); + functionsIndex_[40] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7", "8"); + functionsIndex_[41] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654", "16"); + functionsIndex_[35] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678", "12"); + functionsIndex_[36] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376", "4"); + functionsIndex_[44] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb", "8"); + functionsIndex_[45] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146", "8"); + functionsIndex_[46] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda", "8"); + functionsIndex_[47] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484", "12"); + functionsIndex_[48] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb", "12"); + functionsIndex_[49] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1729a067d902771517388eedd7346b23", "12"); + functionsIndex_[50] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745", "8"); + functionsIndex_[51] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0", "8"); + functionsIndex_[52] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8", "8"); + functionsIndex_[53] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c", "8"); + functionsIndex_[54] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b", "8"); + functionsIndex_[55] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef", "12"); + functionsIndex_[56] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91", "8"); + functionsIndex_[57] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e", "8"); + functionsIndex_[58] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a", "4"); + functionsIndex_[59] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c", "4"); + functionsIndex_[60] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd", "8"); + functionsIndex_[61] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb", "8"); + functionsIndex_[42] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d", "12"); + functionsIndex_[43] = LAAW_ORTHANC_CLIENT_GET_FUNCTION(handle_, "LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207", "4"); + + /* Check whether the functions were properly loaded */ + for (unsigned int i = 0; i <= 62; i++) + { + if (functionsIndex_[i] == (LAAW_ORTHANC_CLIENT_FUNCTION_TYPE) NULL) + { + throw ::OrthancClient::OrthancClientException("Unable to load the functions of the shared library"); + } + } +} +}} +namespace OrthancClient +{ + class OrthancConnection; +} + +namespace OrthancClient +{ + class Patient; +} + +namespace OrthancClient +{ + class Series; +} + +namespace OrthancClient +{ + class Study; +} + +namespace OrthancClient +{ + class Instance; +} + +namespace Orthanc +{ + /** + * @brief The memory layout of the pixels (resp. voxels) of a 2D (resp. 3D) image. + * + * The memory layout of the pixels (resp. voxels) of a 2D (resp. 3D) image. + * + * @ingroup Global + **/ + enum PixelFormat + { + /** + * @brief Graylevel, signed 16bpp image. + * + * The image is graylevel. Each pixel is signed and stored in two bytes. + * + **/ + PixelFormat_SignedGrayscale16 = 3, + /** + * @brief Color image in RGB24 format. + * + * Color image in RGB24 format. + * + **/ + PixelFormat_RGB24 = 0, + /** + * @brief Graylevel 8bpp image. + * + * The image is graylevel. Each pixel is unsigned and stored in one byte. + * + **/ + PixelFormat_Grayscale8 = 1, + /** + * @brief Graylevel, unsigned 16bpp image. + * + * The image is graylevel. Each pixel is unsigned and stored in two bytes. + * + **/ + PixelFormat_Grayscale16 = 2 + }; +} + +namespace Orthanc +{ + /** + * @brief The extraction mode specifies the way the values of the pixels are scaled when downloading a 2D image. + * + * The extraction mode specifies the way the values of the pixels are scaled when downloading a 2D image. + * + * @ingroup Global + **/ + enum ImageExtractionMode + { + /** + * @brief Truncation to the [-32768, 32767] range. + * + * Truncation to the [-32768, 32767] range. + * + **/ + ImageExtractionMode_Int16 = 3, + /** + * @brief Rescaled to 8bpp. + * + * The minimum value of the image is set to 0, and its maximum value is set to 255. + * + **/ + ImageExtractionMode_Preview = 0, + /** + * @brief Truncation to the [0, 255] range. + * + * Truncation to the [0, 255] range. + * + **/ + ImageExtractionMode_UInt8 = 1, + /** + * @brief Truncation to the [0, 65535] range. + * + * Truncation to the [0, 65535] range. + * + **/ + ImageExtractionMode_UInt16 = 2 + }; +} + +namespace OrthancClient +{ + /** + * @brief Connection to an instance of %Orthanc. + * + * This class encapsulates a connection to a remote instance of %Orthanc through its REST API. + * + **/ + class OrthancConnection + { + friend class ::OrthancClient::Patient; + friend class ::OrthancClient::Series; + friend class ::OrthancClient::Study; + friend class ::OrthancClient::Instance; + private: + bool isReference_; + OrthancConnection& operator= (const OrthancConnection&); // Assignment is forbidden + void* pimpl_; + OrthancConnection(void* pimpl) : isReference_(true), pimpl_(pimpl) {} + public: + /** + * @brief Construct a new reference to this object. + * + * Construct a new reference to this object. Pay attention to the fact that when the referenced object is deleted, the content of this object will be invalid. + * + * @param other The original object. + **/ + OrthancConnection(const OrthancConnection& other) : isReference_(true), pimpl_(other.pimpl_) { } + inline OrthancConnection(const ::std::string& orthancUrl); + inline OrthancConnection(const ::std::string& orthancUrl, const ::std::string& username, const ::std::string& password); + inline ~OrthancConnection(); + inline LAAW_UINT32 GetThreadCount() const; + inline void SetThreadCount(LAAW_UINT32 threadCount); + inline void Reload(); + inline ::std::string GetOrthancUrl() const; + inline LAAW_UINT32 GetPatientCount(); + inline ::OrthancClient::Patient GetPatient(LAAW_UINT32 index); + inline void DeletePatient(LAAW_UINT32 index); + inline void StoreFile(const ::std::string& filename); + inline void Store(const void* dicom, LAAW_UINT64 size); + }; +} + +namespace OrthancClient +{ + /** + * @brief Connection to a patient stored in %Orthanc. + * + * This class encapsulates a connection to a patient from a remote instance of %Orthanc. + * + **/ + class Patient + { + friend class ::OrthancClient::OrthancConnection; + friend class ::OrthancClient::Series; + friend class ::OrthancClient::Study; + friend class ::OrthancClient::Instance; + private: + bool isReference_; + Patient& operator= (const Patient&); // Assignment is forbidden + void* pimpl_; + Patient(void* pimpl) : isReference_(true), pimpl_(pimpl) {} + public: + /** + * @brief Construct a new reference to this object. + * + * Construct a new reference to this object. Pay attention to the fact that when the referenced object is deleted, the content of this object will be invalid. + * + * @param other The original object. + **/ + Patient(const Patient& other) : isReference_(true), pimpl_(other.pimpl_) { } + inline Patient(::OrthancClient::OrthancConnection& connection, const ::std::string& id); + inline ~Patient(); + inline void Reload(); + inline LAAW_UINT32 GetStudyCount(); + inline ::OrthancClient::Study GetStudy(LAAW_UINT32 index); + inline ::std::string GetId() const; + inline ::std::string GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const; + }; +} + +namespace OrthancClient +{ + /** + * @brief Connection to a series stored in %Orthanc. + * + * This class encapsulates a connection to a series from a remote instance of %Orthanc. + * + **/ + class Series + { + friend class ::OrthancClient::OrthancConnection; + friend class ::OrthancClient::Patient; + friend class ::OrthancClient::Study; + friend class ::OrthancClient::Instance; + private: + bool isReference_; + Series& operator= (const Series&); // Assignment is forbidden + void* pimpl_; + Series(void* pimpl) : isReference_(true), pimpl_(pimpl) {} + public: + /** + * @brief Construct a new reference to this object. + * + * Construct a new reference to this object. Pay attention to the fact that when the referenced object is deleted, the content of this object will be invalid. + * + * @param other The original object. + **/ + Series(const Series& other) : isReference_(true), pimpl_(other.pimpl_) { } + inline Series(::OrthancClient::OrthancConnection& connection, const ::std::string& id); + inline ~Series(); + inline void Reload(); + inline LAAW_UINT32 GetInstanceCount(); + inline ::OrthancClient::Instance GetInstance(LAAW_UINT32 index); + inline ::std::string GetId() const; + inline ::std::string GetUrl() const; + inline ::std::string GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const; + inline bool Is3DImage(); + inline LAAW_UINT32 GetWidth(); + inline LAAW_UINT32 GetHeight(); + inline float GetVoxelSizeX(); + inline float GetVoxelSizeY(); + inline float GetVoxelSizeZ(); + inline void Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride); + inline void Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride, float progress[]); + }; +} + +namespace OrthancClient +{ + /** + * @brief Connection to a study stored in %Orthanc. + * + * This class encapsulates a connection to a study from a remote instance of %Orthanc. + * + **/ + class Study + { + friend class ::OrthancClient::OrthancConnection; + friend class ::OrthancClient::Patient; + friend class ::OrthancClient::Series; + friend class ::OrthancClient::Instance; + private: + bool isReference_; + Study& operator= (const Study&); // Assignment is forbidden + void* pimpl_; + Study(void* pimpl) : isReference_(true), pimpl_(pimpl) {} + public: + /** + * @brief Construct a new reference to this object. + * + * Construct a new reference to this object. Pay attention to the fact that when the referenced object is deleted, the content of this object will be invalid. + * + * @param other The original object. + **/ + Study(const Study& other) : isReference_(true), pimpl_(other.pimpl_) { } + inline Study(::OrthancClient::OrthancConnection& connection, const ::std::string& id); + inline ~Study(); + inline void Reload(); + inline LAAW_UINT32 GetSeriesCount(); + inline ::OrthancClient::Series GetSeries(LAAW_UINT32 index); + inline ::std::string GetId() const; + inline ::std::string GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const; + }; +} + +namespace OrthancClient +{ + /** + * @brief Connection to an instance stored in %Orthanc. + * + * This class encapsulates a connection to an image instance from a remote instance of %Orthanc. + * + **/ + class Instance + { + friend class ::OrthancClient::OrthancConnection; + friend class ::OrthancClient::Patient; + friend class ::OrthancClient::Series; + friend class ::OrthancClient::Study; + private: + bool isReference_; + Instance& operator= (const Instance&); // Assignment is forbidden + void* pimpl_; + Instance(void* pimpl) : isReference_(true), pimpl_(pimpl) {} + public: + /** + * @brief Construct a new reference to this object. + * + * Construct a new reference to this object. Pay attention to the fact that when the referenced object is deleted, the content of this object will be invalid. + * + * @param other The original object. + **/ + Instance(const Instance& other) : isReference_(true), pimpl_(other.pimpl_) { } + inline Instance(::OrthancClient::OrthancConnection& connection, const ::std::string& id); + inline ~Instance(); + inline ::std::string GetId() const; + inline void SetImageExtractionMode(::Orthanc::ImageExtractionMode mode); + inline ::Orthanc::ImageExtractionMode GetImageExtractionMode() const; + inline ::std::string GetTagAsString(const ::std::string& tag) const; + inline float GetTagAsFloat(const ::std::string& tag) const; + inline LAAW_INT32 GetTagAsInt(const ::std::string& tag) const; + inline LAAW_UINT32 GetWidth(); + inline LAAW_UINT32 GetHeight(); + inline LAAW_UINT32 GetPitch(); + inline ::Orthanc::PixelFormat GetPixelFormat(); + inline const void* GetBuffer(); + inline const void* GetBuffer(LAAW_UINT32 y); + inline LAAW_UINT64 GetDicomSize(); + inline const void* GetDicom(); + inline void DiscardImage(); + inline void DiscardDicom(); + inline void LoadTagContent(const ::std::string& path); + inline ::std::string GetLoadedTagContent() const; + }; +} + +namespace OrthancClient +{ + /** + * @brief Create a connection to an instance of %Orthanc. + * + * Create a connection to an instance of %Orthanc. + * + * @param orthancUrl URL to which the REST API of %Orthanc is listening. + **/ + inline OrthancConnection::OrthancConnection(const ::std::string& orthancUrl) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(0); + char* error = function(&pimpl_, orthancUrl.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Create a connection to an instance of %Orthanc, with authentication. + * + * Create a connection to an instance of %Orthanc, with authentication. + * + * @param orthancUrl URL to which the REST API of %Orthanc is listening. + * @param username The username. + * @param password The password. + **/ + inline OrthancConnection::OrthancConnection(const ::std::string& orthancUrl, const ::std::string& username, const ::std::string& password) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, const char*, const char*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(1); + char* error = function(&pimpl_, orthancUrl.c_str(), username.c_str(), password.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Destructs the object. + * + * Destructs the object. + * + **/ + inline OrthancConnection::~OrthancConnection() + { + if (isReference_) return; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(2); + char* error = function(pimpl_); + error = error; // Remove warning about unused variable + } + /** + * @brief Returns the number of threads for this connection. + * + * Returns the number of simultaneous connections that are used when downloading information from this instance of %Orthanc. + * + * @return The number of threads. + **/ + inline LAAW_UINT32 OrthancConnection::GetThreadCount() const + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(3); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Sets the number of threads for this connection. + * + * Sets the number of simultaneous connections that are used when downloading information from this instance of %Orthanc. + * + * @param threadCount The number of threads. + **/ + inline void OrthancConnection::SetThreadCount(LAAW_UINT32 threadCount) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(4); + char* error = function(pimpl_, threadCount); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Reload the list of the patients. + * + * This method will reload the list of the patients from the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated. + * + **/ + inline void OrthancConnection::Reload() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(5); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Returns the URL of this instance of %Orthanc. + * + * Returns the URL of the remote %Orthanc instance to which this object is connected. + * + * @return The URL. + **/ + inline ::std::string OrthancConnection::GetOrthancUrl() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(6); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Returns the number of patients. + * + * Returns the number of patients that are stored in the remote instance of %Orthanc. + * + * @return The number of patients. + **/ + inline LAAW_UINT32 OrthancConnection::GetPatientCount() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(7); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get some patient. + * + * This method will return an object that contains information about some patient. The patients are indexed by a number between 0 (inclusive) and the result of GetPatientCount() (exclusive). + * + * @param index The index of the patient of interest. + * @return The patient. + **/ + inline ::OrthancClient::Patient OrthancConnection::GetPatient(LAAW_UINT32 index) + { + void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void**, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(8); + char* error = function(pimpl_, &result_, index); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return ::OrthancClient::Patient(result_); + } + /** + * @brief Delete some patient. + * + * Delete some patient from the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated. + * + * @param index The index of the patient of interest. + * @return The patient. + **/ + inline void OrthancConnection::DeletePatient(LAAW_UINT32 index) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(9); + char* error = function(pimpl_, index); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Send a DICOM file. + * + * This method will store a DICOM file in the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated. + * + * @param filename Path to the DICOM file + **/ + inline void OrthancConnection::StoreFile(const ::std::string& filename) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(10); + char* error = function(pimpl_, filename.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Send a DICOM file that is contained inside a memory buffer. + * + * This method will store a DICOM file in the remote instance of %Orthanc. Pay attention to the fact that the patients that have been previously returned by GetPatient() will be invalidated. + * + * @param dicom The memory buffer containing the DICOM file. + * @param size The size of the DICOM file. + **/ + inline void OrthancConnection::Store(const void* dicom, LAAW_UINT64 size) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void*, LAAW_UINT64); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(11); + char* error = function(pimpl_, dicom, size); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } +} + +namespace OrthancClient +{ + /** + * @brief Create a connection to some patient. + * + * Create a connection to some patient. + * + * @param connection The remote instance of %Orthanc. + * @param id The %Orthanc identifier of the patient. + **/ + inline Patient::Patient(::OrthancClient::OrthancConnection& connection, const ::std::string& id) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(12); + char* error = function(&pimpl_, connection.pimpl_, id.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Destructs the object. + * + * Destructs the object. + * + **/ + inline Patient::~Patient() + { + if (isReference_) return; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(13); + char* error = function(pimpl_); + error = error; // Remove warning about unused variable + } + /** + * @brief Reload the studies of this patient. + * + * This method will reload the list of the studies of this patient. Pay attention to the fact that the studies that have been previously returned by GetStudy() will be invalidated. + * + **/ + inline void Patient::Reload() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(14); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Return the number of studies for this patient. + * + * Return the number of studies for this patient. + * + * @return The number of studies. + **/ + inline LAAW_UINT32 Patient::GetStudyCount() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(15); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get some study of this patient. + * + * This method will return an object that contains information about some study. The studies are indexed by a number between 0 (inclusive) and the result of GetStudyCount() (exclusive). + * + * @param index The index of the study of interest. + * @return The study. + **/ + inline ::OrthancClient::Study Patient::GetStudy(LAAW_UINT32 index) + { + void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void**, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(16); + char* error = function(pimpl_, &result_, index); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return ::OrthancClient::Study(result_); + } + /** + * @brief Get the %Orthanc identifier of this patient. + * + * Get the %Orthanc identifier of this patient. + * + * @return The identifier. + **/ + inline ::std::string Patient::GetId() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(17); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Get the value of one of the main DICOM tags for this patient. + * + * Get the value of one of the main DICOM tags for this patient. + * + * @param tag The name of the tag of interest ("PatientName", "PatientID", "PatientSex" or "PatientBirthDate"). + * @param defaultValue The default value to be returned if this tag does not exist. + * @return The value of the tag. + **/ + inline ::std::string Patient::GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(18); + char* error = function(pimpl_, &result_, tag.c_str(), defaultValue.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } +} + +namespace OrthancClient +{ + /** + * @brief Create a connection to some series. + * + * Create a connection to some series. + * + * @param connection The remote instance of %Orthanc. + * @param id The %Orthanc identifier of the series. + **/ + inline Series::Series(::OrthancClient::OrthancConnection& connection, const ::std::string& id) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(19); + char* error = function(&pimpl_, connection.pimpl_, id.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Destructs the object. + * + * Destructs the object. + * + **/ + inline Series::~Series() + { + if (isReference_) return; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(20); + char* error = function(pimpl_); + error = error; // Remove warning about unused variable + } + /** + * @brief Reload the instances of this series. + * + * This method will reload the list of the instances of this series. Pay attention to the fact that the instances that have been previously returned by GetInstance() will be invalidated. + * + **/ + inline void Series::Reload() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(21); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Return the number of instances for this series. + * + * Return the number of instances for this series. + * + * @return The number of instances. + **/ + inline LAAW_UINT32 Series::GetInstanceCount() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(22); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get some instance of this series. + * + * This method will return an object that contains information about some instance. The instances are indexed by a number between 0 (inclusive) and the result of GetInstanceCount() (exclusive). + * + * @param index The index of the instance of interest. + * @return The instance. + **/ + inline ::OrthancClient::Instance Series::GetInstance(LAAW_UINT32 index) + { + void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void**, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(23); + char* error = function(pimpl_, &result_, index); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return ::OrthancClient::Instance(result_); + } + /** + * @brief Get the %Orthanc identifier of this series. + * + * Get the %Orthanc identifier of this series. + * + * @return The identifier. + **/ + inline ::std::string Series::GetId() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(24); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Returns the URL to this series. + * + * Returns the URL to this series. + * + * @return The URL. + **/ + inline ::std::string Series::GetUrl() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(25); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Get the value of one of the main DICOM tags for this series. + * + * Get the value of one of the main DICOM tags for this series. + * + * @param tag The name of the tag of interest ("Modality", "Manufacturer", "SeriesDate", "SeriesDescription", "SeriesInstanceUID"...). + * @param defaultValue The default value to be returned if this tag does not exist. + * @return The value of the tag. + **/ + inline ::std::string Series::GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(26); + char* error = function(pimpl_, &result_, tag.c_str(), defaultValue.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Test whether this series encodes a 3D image that can be downloaded from %Orthanc. + * + * Test whether this series encodes a 3D image that can be downloaded from %Orthanc. + * + * @return "true" if and only if this is a 3D image. + **/ + inline bool Series::Is3DImage() + { + LAAW_INT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_INT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(27); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_ != 0; + } + /** + * @brief Get the width of the 3D image. + * + * Get the width of the 3D image (i.e. along the X-axis). This call is only valid if this series corresponds to a 3D image. + * + * @return The width. + **/ + inline LAAW_UINT32 Series::GetWidth() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(28); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the height of the 3D image. + * + * Get the height of the 3D image (i.e. along the Y-axis). This call is only valid if this series corresponds to a 3D image. + * + * @return The height. + **/ + inline LAAW_UINT32 Series::GetHeight() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(29); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the physical size of a voxel along the X-axis. + * + * Get the physical size of a voxel along the X-axis. This call is only valid if this series corresponds to a 3D image. + * + * @return The voxel size. + **/ + inline float Series::GetVoxelSizeX() + { + float result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, float*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(30); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the physical size of a voxel along the Y-axis. + * + * Get the physical size of a voxel along the Y-axis. This call is only valid if this series corresponds to a 3D image. + * + * @return The voxel size. + **/ + inline float Series::GetVoxelSizeY() + { + float result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, float*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(31); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the physical size of a voxel along the Z-axis. + * + * Get the physical size of a voxel along the Z-axis. This call is only valid if this series corresponds to a 3D image. + * + * @return The voxel size. + **/ + inline float Series::GetVoxelSizeZ() + { + float result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, float*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(32); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Load the 3D image into a memory buffer. + * + * Load the 3D image into a memory buffer. This call is only valid if this series corresponds to a 3D image. The "target" buffer must be wide enough to store all the voxels of the image. + * + * @param target The target memory buffer. + * @param format The memory layout of the voxels. + * @param lineStride The number of bytes between two lines in the target memory buffer. + * @param stackStride The number of bytes between two 2D slices in the target memory buffer. + **/ + inline void Series::Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void*, LAAW_INT32, LAAW_INT64, LAAW_INT64); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(33); + char* error = function(pimpl_, target, format, lineStride, stackStride); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Load the 3D image into a memory buffer. + * + * Load the 3D image into a memory buffer. This call is only valid if this series corresponds to a 3D image. The "target" buffer must be wide enough to store all the voxels of the image. This method will also update a progress indicator to monitor the loading of the image. + * + * @param target The target memory buffer. + * @param format The memory layout of the voxels. + * @param lineStride The number of bytes between two lines in the target memory buffer. + * @param stackStride The number of bytes between two 2D slices in the target memory buffer. + * @param progress A pointer to a floating-point number that is continuously updated by the download threads to reflect the percentage of completion (between 0 and 1). This value can be read from a separate thread. + **/ + inline void Series::Load3DImage(void* target, ::Orthanc::PixelFormat format, LAAW_INT64 lineStride, LAAW_INT64 stackStride, float progress[]) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void*, LAAW_INT32, LAAW_INT64, LAAW_INT64, float*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(34); + char* error = function(pimpl_, target, format, lineStride, stackStride, progress); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } +} + +namespace OrthancClient +{ + /** + * @brief Create a connection to some study. + * + * Create a connection to some study. + * + * @param connection The remote instance of %Orthanc. + * @param id The %Orthanc identifier of the study. + **/ + inline Study::Study(::OrthancClient::OrthancConnection& connection, const ::std::string& id) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(35); + char* error = function(&pimpl_, connection.pimpl_, id.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Destructs the object. + * + * Destructs the object. + * + **/ + inline Study::~Study() + { + if (isReference_) return; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(36); + char* error = function(pimpl_); + error = error; // Remove warning about unused variable + } + /** + * @brief Reload the series of this study. + * + * This method will reload the list of the series of this study. Pay attention to the fact that the series that have been previously returned by GetSeries() will be invalidated. + * + **/ + inline void Study::Reload() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(37); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Return the number of series for this study. + * + * Return the number of series for this study. + * + * @return The number of series. + **/ + inline LAAW_UINT32 Study::GetSeriesCount() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(38); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get some series of this study. + * + * This method will return an object that contains information about some series. The series are indexed by a number between 0 (inclusive) and the result of GetSeriesCount() (exclusive). + * + * @param index The index of the series of interest. + * @return The series. + **/ + inline ::OrthancClient::Series Study::GetSeries(LAAW_UINT32 index) + { + void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, void**, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(39); + char* error = function(pimpl_, &result_, index); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return ::OrthancClient::Series(result_); + } + /** + * @brief Get the %Orthanc identifier of this study. + * + * Get the %Orthanc identifier of this study. + * + * @return The identifier. + **/ + inline ::std::string Study::GetId() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(40); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Get the value of one of the main DICOM tags for this study. + * + * Get the value of one of the main DICOM tags for this study. + * + * @param tag The name of the tag of interest ("StudyDate", "StudyDescription", "StudyInstanceUID" or "StudyTime"). + * @param defaultValue The default value to be returned if this tag does not exist. + * @return The value of the tag. + **/ + inline ::std::string Study::GetMainDicomTag(const ::std::string& tag, const ::std::string& defaultValue) const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(41); + char* error = function(pimpl_, &result_, tag.c_str(), defaultValue.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } +} + +namespace OrthancClient +{ + /** + * @brief Create a connection to some image instance. + * + * Create a connection to some image instance. + * + * @param connection The remote instance of %Orthanc. + * @param id The %Orthanc identifier of the image instance. + **/ + inline Instance::Instance(::OrthancClient::OrthancConnection& connection, const ::std::string& id) + { + isReference_ = false; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void**, void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(42); + char* error = function(&pimpl_, connection.pimpl_, id.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Destructs the object. + * + * Destructs the object. + * + **/ + inline Instance::~Instance() + { + if (isReference_) return; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(43); + char* error = function(pimpl_); + error = error; // Remove warning about unused variable + } + /** + * @brief Get the %Orthanc identifier of this identifier. + * + * Get the %Orthanc identifier of this identifier. + * + * @return The identifier. + **/ + inline ::std::string Instance::GetId() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(44); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Set the extraction mode for the 2D image corresponding to this instance. + * + * Set the extraction mode for the 2D image corresponding to this instance. + * + * @param mode The extraction mode. + **/ + inline void Instance::SetImageExtractionMode(::Orthanc::ImageExtractionMode mode) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_INT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(45); + char* error = function(pimpl_, mode); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Get the extraction mode for the 2D image corresponding to this instance. + * + * Get the extraction mode for the 2D image corresponding to this instance. + * + * @return The extraction mode. + **/ + inline ::Orthanc::ImageExtractionMode Instance::GetImageExtractionMode() const + { + LAAW_INT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, LAAW_INT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(46); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return static_cast< ::Orthanc::ImageExtractionMode >(result_); + } + /** + * @brief Get the string value of some DICOM tag of this instance. + * + * Get the string value of some DICOM tag of this instance. + * + * @param tag The name of the tag of interest. + * @return The value of the tag. + **/ + inline ::std::string Instance::GetTagAsString(const ::std::string& tag) const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(47); + char* error = function(pimpl_, &result_, tag.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } + /** + * @brief Get the floating point value that is stored in some DICOM tag of this instance. + * + * Get the floating point value that is stored in some DICOM tag of this instance. + * + * @param tag The name of the tag of interest. + * @return The value of the tag. + **/ + inline float Instance::GetTagAsFloat(const ::std::string& tag) const + { + float result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, float*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(48); + char* error = function(pimpl_, &result_, tag.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the integer value that is stored in some DICOM tag of this instance. + * + * Get the integer value that is stored in some DICOM tag of this instance. + * + * @param tag The name of the tag of interest. + * @return The value of the tag. + **/ + inline LAAW_INT32 Instance::GetTagAsInt(const ::std::string& tag) const + { + LAAW_INT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, LAAW_INT32*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(49); + char* error = function(pimpl_, &result_, tag.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the width of the 2D image. + * + * Get the width of the 2D image that is encoded by this DICOM instance. + * + * @return The width. + **/ + inline LAAW_UINT32 Instance::GetWidth() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(50); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the height of the 2D image. + * + * Get the height of the 2D image that is encoded by this DICOM instance. + * + * @return The height. + **/ + inline LAAW_UINT32 Instance::GetHeight() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(51); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the number of bytes between two lines of the image (pitch). + * + * Get the number of bytes between two lines of the image in the memory buffer returned by GetBuffer(). This value depends on the extraction mode for the image. + * + * @return The pitch. + **/ + inline LAAW_UINT32 Instance::GetPitch() + { + LAAW_UINT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(52); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get the format of the pixels of the 2D image. + * + * Return the memory layout that is used for the 2D image that is encoded by this DICOM instance. This value depends on the extraction mode for the image. + * + * @return The pixel format. + **/ + inline ::Orthanc::PixelFormat Instance::GetPixelFormat() + { + LAAW_INT32 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_INT32*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(53); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return static_cast< ::Orthanc::PixelFormat >(result_); + } + /** + * @brief Access the memory buffer in which the raw pixels of the 2D image are stored. + * + * Access the memory buffer in which the raw pixels of the 2D image are stored. + * + * @return A pointer to the memory buffer. + **/ + inline const void* Instance::GetBuffer() + { + const void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(54); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return reinterpret_cast< const void* >(result_); + } + /** + * @brief Access the memory buffer in which the raw pixels of some line of the 2D image are stored. + * + * Access the memory buffer in which the raw pixels of some line of the 2D image are stored. + * + * @param y The line of interest. + * @return A pointer to the memory buffer. + **/ + inline const void* Instance::GetBuffer(LAAW_UINT32 y) + { + const void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**, LAAW_UINT32); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(55); + char* error = function(pimpl_, &result_, y); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return reinterpret_cast< const void* >(result_); + } + /** + * @brief Get the size of the DICOM file corresponding to this instance. + * + * Get the size of the DICOM file corresponding to this instance. + * + * @return The file size. + **/ + inline LAAW_UINT64 Instance::GetDicomSize() + { + LAAW_UINT64 result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, LAAW_UINT64*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(56); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return result_; + } + /** + * @brief Get a pointer to the content of the DICOM file corresponding to this instance. + * + * Get a pointer to the content of the DICOM file corresponding to this instance. + * + * @return The DICOM file. + **/ + inline const void* Instance::GetDicom() + { + const void* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const void**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(57); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return reinterpret_cast< const void* >(result_); + } + /** + * @brief Discard the downloaded 2D image, so as to make room in memory. + * + * Discard the downloaded 2D image, so as to make room in memory. + * + **/ + inline void Instance::DiscardImage() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(58); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Discard the downloaded DICOM file, so as to make room in memory. + * + * Discard the downloaded DICOM file, so as to make room in memory. + * + **/ + inline void Instance::DiscardDicom() + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(59); + char* error = function(pimpl_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Load a raw tag from the DICOM file. + * + * Load a raw tag from the DICOM file. + * + * @param path The path to the tag of interest (e.g. "0020-000d"). + **/ + inline void Instance::LoadTagContent(const ::std::string& path) + { + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (void*, const char*); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(60); + char* error = function(pimpl_, path.c_str()); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + } + /** + * @brief Return the value of the raw tag that was loaded by LoadContent. + * + * Return the value of the raw tag that was loaded by LoadContent. + * + * @return The tag value. + **/ + inline ::std::string Instance::GetLoadedTagContent() const + { + const char* result_; + typedef char* (LAAW_ORTHANC_CLIENT_CALL_CONV* Function) (const void*, const char**); + Function function = (Function) ::OrthancClient::Internals::Library::GetInstance().GetFunction(61); + char* error = function(pimpl_, &result_); + ::OrthancClient::Internals::Library::GetInstance().ThrowExceptionIfNeeded(error); + return std::string(result_); + } +} + diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.def Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,72 @@ +LIBRARY some.dll +EXPORTS + _LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7@8 = LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7@8 + _LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e@8 = LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e@8 + _LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f@4 = LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f@4 + _LAAW_EXTERNC_e840242bf58d17d3c1d722da09ce88e0@8 = LAAW_EXTERNC_e840242bf58d17d3c1d722da09ce88e0@8 + _LAAW_EXTERNC_c9af31433001b5dfc012a552dc6d0050@8 = LAAW_EXTERNC_c9af31433001b5dfc012a552dc6d0050@8 + _LAAW_EXTERNC_3fba4d6b818180a44cd1cae6046334dc@12 = LAAW_EXTERNC_3fba4d6b818180a44cd1cae6046334dc@12 + _LAAW_EXTERNC_aeb20dc75b9246188db857317e5e0ce7@8 = LAAW_EXTERNC_aeb20dc75b9246188db857317e5e0ce7@8 + _LAAW_EXTERNC_62689803d9871e4d9c51a648640b320b@8 = LAAW_EXTERNC_62689803d9871e4d9c51a648640b320b@8 + _LAAW_EXTERNC_2fb64c9e5a67eccd413b0e913469a421@16 = LAAW_EXTERNC_2fb64c9e5a67eccd413b0e913469a421@16 + _LAAW_EXTERNC_1f1acb322ea4d0aad65172824607673c@8 = LAAW_EXTERNC_1f1acb322ea4d0aad65172824607673c@8 + _LAAW_EXTERNC_f3fd272e4636f6a531aabb72ee01cd5b@16 = LAAW_EXTERNC_f3fd272e4636f6a531aabb72ee01cd5b@16 + _LAAW_EXTERNC_12d3de0a96e9efb11136a9811bb9ed38@4 = LAAW_EXTERNC_12d3de0a96e9efb11136a9811bb9ed38@4 + _LAAW_EXTERNC_f756172daf04516eec3a566adabb4335@4 = LAAW_EXTERNC_f756172daf04516eec3a566adabb4335@4 + _LAAW_EXTERNC_ddb68763ec902a97d579666a73a20118@8 = LAAW_EXTERNC_ddb68763ec902a97d579666a73a20118@8 + _LAAW_EXTERNC_fba3c68b4be7558dbc65f7ce1ab57d63@12 = LAAW_EXTERNC_fba3c68b4be7558dbc65f7ce1ab57d63@12 + _LAAW_EXTERNC_b4ca99d958f843493e58d1ef967340e1@8 = LAAW_EXTERNC_b4ca99d958f843493e58d1ef967340e1@8 + _LAAW_EXTERNC_78d5cc76d282437b6f93ec3b82c35701@16 = LAAW_EXTERNC_78d5cc76d282437b6f93ec3b82c35701@16 + _LAAW_EXTERNC_6cf0d7268667f9b0aa4511bacf184919@12 = LAAW_EXTERNC_6cf0d7268667f9b0aa4511bacf184919@12 + _LAAW_EXTERNC_7d81cd502ee27e859735d0ea7112b5a1@4 = LAAW_EXTERNC_7d81cd502ee27e859735d0ea7112b5a1@4 + _LAAW_EXTERNC_48a2a1a9d68c047e22bfba23014643d2@4 = LAAW_EXTERNC_48a2a1a9d68c047e22bfba23014643d2@4 + _LAAW_EXTERNC_852bf8296ca21c5fde5ec565cc10721d@8 = LAAW_EXTERNC_852bf8296ca21c5fde5ec565cc10721d@8 + _LAAW_EXTERNC_efd04574e0779faa83df1f2d8f9888db@12 = LAAW_EXTERNC_efd04574e0779faa83df1f2d8f9888db@12 + _LAAW_EXTERNC_736247ff5e8036dac38163da6f666ed5@8 = LAAW_EXTERNC_736247ff5e8036dac38163da6f666ed5@8 + _LAAW_EXTERNC_d82d2598a7a73f4b6fcc0c09c25b08ca@8 = LAAW_EXTERNC_d82d2598a7a73f4b6fcc0c09c25b08ca@8 + _LAAW_EXTERNC_88134b978f9acb2aecdadf54aeab3c64@16 = LAAW_EXTERNC_88134b978f9acb2aecdadf54aeab3c64@16 + _LAAW_EXTERNC_152cb1b704c053d24b0dab7461ba6ea3@8 = LAAW_EXTERNC_152cb1b704c053d24b0dab7461ba6ea3@8 + _LAAW_EXTERNC_eee03f337ec81d9f1783cd41e5238757@8 = LAAW_EXTERNC_eee03f337ec81d9f1783cd41e5238757@8 + _LAAW_EXTERNC_006f08237bd7611636fc721baebfb4c5@8 = LAAW_EXTERNC_006f08237bd7611636fc721baebfb4c5@8 + _LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0@8 = LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0@8 + _LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab@8 = LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab@8 + _LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d@8 = LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d@8 + _LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5@28 = LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5@28 + _LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c@32 = LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c@32 + _LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342@12 = LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342@12 + _LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0@4 = LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0@4 + _LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7@4 = LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7@4 + _LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321@8 = LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321@8 + _LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05@12 = LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05@12 + _LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7@8 = LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7@8 + _LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654@16 = LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654@16 + _LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678@12 = LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678@12 + _LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376@4 = LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376@4 + _LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb@8 = LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb@8 + _LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146@8 = LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146@8 + _LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda@8 = LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda@8 + _LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484@12 = LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484@12 + _LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb@12 = LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb@12 + _LAAW_EXTERNC_1729a067d902771517388eedd7346b23@12 = LAAW_EXTERNC_1729a067d902771517388eedd7346b23@12 + _LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745@8 = LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745@8 + _LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0@8 = LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0@8 + _LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8@8 = LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8@8 + _LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c@8 = LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c@8 + _LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b@8 = LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b@8 + _LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef@12 = LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef@12 + _LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91@8 = LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91@8 + _LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e@8 = LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e@8 + _LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a@4 = LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a@4 + _LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c@4 = LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c@4 + _LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd@8 = LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd@8 + _LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb@8 = LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb@8 + _LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d@12 = LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d@12 + _LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207@4 = LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207@4 + _LAAW_EXTERNC_GetDescription@0 = LAAW_EXTERNC_GetDescription@0 + _LAAW_EXTERNC_GetCompany@0 = LAAW_EXTERNC_GetCompany@0 + _LAAW_EXTERNC_GetProduct@0 = LAAW_EXTERNC_GetProduct@0 + _LAAW_EXTERNC_GetCopyright@0 = LAAW_EXTERNC_GetCopyright@0 + _LAAW_EXTERNC_GetVersion@0 = LAAW_EXTERNC_GetVersion@0 + _LAAW_EXTERNC_GetFileVersion@0 = LAAW_EXTERNC_GetFileVersion@0 + _LAAW_EXTERNC_GetFullVersion@0 = LAAW_EXTERNC_GetFullVersion@0 + _LAAW_EXTERNC_FreeString@4 = LAAW_EXTERNC_FreeString@4 diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows32.rc Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,30 @@ +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,7,0,4 + PRODUCTVERSION 0,7,0,0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "Comments", "Release 0.7.4" + VALUE "CompanyName", "CHU of Liege" + VALUE "FileDescription", "Native client to the REST API of Orthanc" + VALUE "FileVersion", "0.7.0.4" + VALUE "InternalName", "OrthancClient" + VALUE "LegalCopyright", "(c) 2012-2014, Sebastien Jodogne, CHU of Liege" + VALUE "LegalTrademarks", "Licensing information is available on https://code.google.com/p/orthanc/" + VALUE "OriginalFilename", "OrthancClient_Windows32.dll" + VALUE "ProductName", "OrthancClient" + VALUE "ProductVersion", "0.7" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 // U.S. English + END + END diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.def Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,72 @@ +LIBRARY some.dll +EXPORTS + LAAW_EXTERNC_557aee7b61817292a0f31269d3c35db7 + LAAW_EXTERNC_0b8dff0ce67f10954a49b059e348837e + LAAW_EXTERNC_e05097c153f676e5a5ee54dcfc78256f + LAAW_EXTERNC_e840242bf58d17d3c1d722da09ce88e0 + LAAW_EXTERNC_c9af31433001b5dfc012a552dc6d0050 + LAAW_EXTERNC_3fba4d6b818180a44cd1cae6046334dc + LAAW_EXTERNC_aeb20dc75b9246188db857317e5e0ce7 + LAAW_EXTERNC_62689803d9871e4d9c51a648640b320b + LAAW_EXTERNC_2fb64c9e5a67eccd413b0e913469a421 + LAAW_EXTERNC_1f1acb322ea4d0aad65172824607673c + LAAW_EXTERNC_f3fd272e4636f6a531aabb72ee01cd5b + LAAW_EXTERNC_12d3de0a96e9efb11136a9811bb9ed38 + LAAW_EXTERNC_f756172daf04516eec3a566adabb4335 + LAAW_EXTERNC_ddb68763ec902a97d579666a73a20118 + LAAW_EXTERNC_fba3c68b4be7558dbc65f7ce1ab57d63 + LAAW_EXTERNC_b4ca99d958f843493e58d1ef967340e1 + LAAW_EXTERNC_78d5cc76d282437b6f93ec3b82c35701 + LAAW_EXTERNC_6cf0d7268667f9b0aa4511bacf184919 + LAAW_EXTERNC_7d81cd502ee27e859735d0ea7112b5a1 + LAAW_EXTERNC_48a2a1a9d68c047e22bfba23014643d2 + LAAW_EXTERNC_852bf8296ca21c5fde5ec565cc10721d + LAAW_EXTERNC_efd04574e0779faa83df1f2d8f9888db + LAAW_EXTERNC_736247ff5e8036dac38163da6f666ed5 + LAAW_EXTERNC_d82d2598a7a73f4b6fcc0c09c25b08ca + LAAW_EXTERNC_88134b978f9acb2aecdadf54aeab3c64 + LAAW_EXTERNC_152cb1b704c053d24b0dab7461ba6ea3 + LAAW_EXTERNC_eee03f337ec81d9f1783cd41e5238757 + LAAW_EXTERNC_006f08237bd7611636fc721baebfb4c5 + LAAW_EXTERNC_b794f5cd3dad7d7b575dd1fd902afdd0 + LAAW_EXTERNC_8ee2e50dd9df8f66a3c1766090dd03ab + LAAW_EXTERNC_046aed35bbe4751691f4c34cc249a61d + LAAW_EXTERNC_4dcc7a0fd025efba251ac6e9b701c2c5 + LAAW_EXTERNC_b2601a161c24ad0a1d3586246f87452c + LAAW_EXTERNC_193599b9e345384fcdfcd47c29c55342 + LAAW_EXTERNC_7c97f17063a357d38c5fab1136ad12a0 + LAAW_EXTERNC_e65b20b7e0170b67544cd6664a4639b7 + LAAW_EXTERNC_470e981b0e41f17231ba0ae6f3033321 + LAAW_EXTERNC_04cefd138b6ea15ad909858f2a0a8f05 + LAAW_EXTERNC_aee5b1f6f0c082f2c3b0986f9f6a18c7 + LAAW_EXTERNC_93965682bace75491413e1f0b8d5a654 + LAAW_EXTERNC_b01c6003238eb46c8db5dc823d7ca678 + LAAW_EXTERNC_0147007fb99bad8cd95a139ec8795376 + LAAW_EXTERNC_236ee8b403bc99535a8a4695c0cd45cb + LAAW_EXTERNC_2a437b7aba6bb01e81113835be8f0146 + LAAW_EXTERNC_2bcbcb850934ae0bb4c6f0cc940e6cda + LAAW_EXTERNC_8d415c3a78a48e7e61d9fd24e7c79484 + LAAW_EXTERNC_70d2f8398bbc63b5f792b69b4ad5fecb + LAAW_EXTERNC_1729a067d902771517388eedd7346b23 + LAAW_EXTERNC_72e2aeee66cd3abd8ab7e987321c3745 + LAAW_EXTERNC_1ea3df5a1ac1a1a687fe7325adddb6f0 + LAAW_EXTERNC_99b4f370e4f532d8b763e2cb49db92f8 + LAAW_EXTERNC_c41c742b68617f1c0590577a0a5ebc0c + LAAW_EXTERNC_142dd2feba0fc1d262bbd0baeb441a8b + LAAW_EXTERNC_5f5c9f81a4dff8daa6c359f1d0488fef + LAAW_EXTERNC_9ca979fffd08fa256306d4e68d8b0e91 + LAAW_EXTERNC_6f2d77a26edc91c28d89408dbc3c271e + LAAW_EXTERNC_c0f494b80d4ff8b232df7a75baa0700a + LAAW_EXTERNC_d604f44bd5195e082e745e9cbc164f4c + LAAW_EXTERNC_1710299d1c5f3b1f2b7cf3962deebbfd + LAAW_EXTERNC_bb55aaf772ddceaadee36f4e54136bcb + LAAW_EXTERNC_6c5ad02f91b583e29cebd0bd319ce21d + LAAW_EXTERNC_4068241c44a9c1367fe0e57be523f207 + LAAW_EXTERNC_GetDescription + LAAW_EXTERNC_GetCompany + LAAW_EXTERNC_GetProduct + LAAW_EXTERNC_GetCopyright + LAAW_EXTERNC_GetVersion + LAAW_EXTERNC_GetFileVersion + LAAW_EXTERNC_GetFullVersion + LAAW_EXTERNC_FreeString diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/AUTOGENERATED/Windows64.rc Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,30 @@ +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,7,0,4 + PRODUCTVERSION 0,7,0,0 + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "Comments", "Release 0.7.4" + VALUE "CompanyName", "CHU of Liege" + VALUE "FileDescription", "Native client to the REST API of Orthanc" + VALUE "FileVersion", "0.7.0.4" + VALUE "InternalName", "OrthancClient" + VALUE "LegalCopyright", "(c) 2012-2014, Sebastien Jodogne, CHU of Liege" + VALUE "LegalTrademarks", "Licensing information is available on https://code.google.com/p/orthanc/" + VALUE "OriginalFilename", "OrthancClient_Windows64.dll" + VALUE "ProductName", "OrthancClient" + VALUE "ProductVersion", "0.7" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 // U.S. English + END + END diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/ConfigurationCpp.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/ConfigurationCpp.json Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,5 @@ +{ + "InternalsNamespace" : [ "OrthancClient", "Internals" ], + "PublicNamespace" : [ "OrthancClient" ], + "ExceptionClassName" : "OrthancClientException" +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/Generate.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/Generate.sh Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +mkdir -p AUTOGENERATED +LAAW_ROOT=~/Subversion/Jomago/Src/Labo/Laaw + +${LAAW_ROOT}/Parser/Build/LaawParser.exe AUTOGENERATED/CodeModelRaw.json ../OrthancConnection.h -I`pwd`/../../s/jsoncpp-src-0.6.0-rc2/include -fms-extensions +python ${LAAW_ROOT}/Generators/CodeModelPostProcessing.py AUTOGENERATED/CodeModel.json AUTOGENERATED/CodeModelRaw.json Product.json +python ${LAAW_ROOT}/Generators/GenerateWrapperCpp.py AUTOGENERATED/OrthancCppClient.h AUTOGENERATED/CodeModel.json Product.json ConfigurationCpp.json +python ${LAAW_ROOT}/Generators/GenerateExternC.py AUTOGENERATED/ExternC.cpp AUTOGENERATED/CodeModel.json Product.json +python ${LAAW_ROOT}/Generators/GenerateWindows32Def.py AUTOGENERATED/Windows32.def AUTOGENERATED/CodeModel.json +python ${LAAW_ROOT}/Generators/GenerateWindows64Def.py AUTOGENERATED/Windows64.def AUTOGENERATED/CodeModel.json +python ${LAAW_ROOT}/Generators/ApplyProductSubstitutions.py AUTOGENERATED/Windows32.rc ${LAAW_ROOT}/Resources/DllResources.rc.mustache Product.json PLATFORM_SUFFIX "_Windows32" +python ${LAAW_ROOT}/Generators/ApplyProductSubstitutions.py AUTOGENERATED/Windows64.rc ${LAAW_ROOT}/Resources/DllResources.rc.mustache Product.json PLATFORM_SUFFIX "_Windows64" diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/Laaw/VersionScript.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/Laaw/VersionScript.map Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,9 @@ +# This is a version-script + +{ +global: + LAAW_EXTERNC_*; + +local: + *; +}; diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/Laaw/laaw/laaw-exports.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/Laaw/laaw/laaw-exports.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,85 @@ +/** + * Laaw - Lightweight, Automated API Wrapper + * Copyright (C) 2010-2013 Jomago - Alain Mazy, Benjamin Golinvaux, + * Sebastien Jodogne + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +/******************************************************************** + ** Windows target + ********************************************************************/ + +#if defined _WIN32 + +#include + +#if defined(__GNUC__) +// This is Mingw +#define LAAW_EXPORT_DLL_API // The exports are handled by the .DEF file +#else +// This is MSVC +#define LAAW_EXPORT_DLL_API __declspec(dllexport) +#endif + +#ifdef _M_X64 +// 64 bits target +#define LAAW_CALL_CONVENTION +#else +// 32 bits target +#define LAAW_CALL_CONVENTION __stdcall // Use the StdCall in Windows32 (for VB6) +#endif + + +/******************************************************************** + ** Linux target + ********************************************************************/ + +#elif defined(__linux) + +// Try the gcc visibility support +// http://gcc.gnu.org/wiki/Visibility +#if ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define LAAW_EXPORT_DLL_API __attribute__ ((visibility("default"))) +#define LAAW_CALL_CONVENTION +#else +#error No support for visibility in your version of GCC +#endif + + +/******************************************************************** + ** Max OS X target + ********************************************************************/ + +#else + +#define LAAW_EXPORT_DLL_API __attribute__ ((visibility("default"))) +#define LAAW_CALL_CONVENTION + +#endif diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/Laaw/laaw/laaw.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/Laaw/laaw/laaw.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,89 @@ +/** + * Laaw - Lightweight, Automated API Wrapper + * Copyright (C) 2010-2013 Jomago - Alain Mazy, Benjamin Golinvaux, + * Sebastien Jodogne + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "laaw-exports.h" +#include +#include + +#if (LAAW_PARSING == 1) + +#define LAAW_API __attribute__((deprecated(""))) +#define LAAW_API_INTERNAL __attribute__((deprecated(""))) +#define LAAW_API_OVERLOAD(name) __attribute__((deprecated(""))) +#define LAAW_API_PROPERTY __attribute__((deprecated(""))) +#define LAAW_API_STATIC_CLASS __attribute__((deprecated(""))) +#define LAAW_API_CUSTOM(name, value) __attribute__((deprecated(""))) + +#else + +#define LAAW_API +#define LAAW_API_INTERNAL +#define LAAW_API_OVERLOAD(name) +#define LAAW_API_PROPERTY +#define LAAW_API_STATIC_CLASS +#define LAAW_API_CUSTOM(name, value) + +#endif + + +namespace Laaw +{ + /** + * This is the base class from which all the public exceptions in + * the SDK should derive. + **/ + class LaawException + { + private: + std::string what_; + + public: + LaawException() + { + } + + LaawException(const std::string& what) : what_(what) + { + } + + LaawException(const char* what) : what_(what) + { + } + + virtual const char* What() const + { + return what_.c_str(); + } + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/Product.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/Product.json Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,8 @@ +{ + "Product" : "OrthancClient", + "Description" : "Native client to the REST API of Orthanc", + "Company" : "CHU of Liege", + "Copyright" : "(c) 2012-2014, Sebastien Jodogne, CHU of Liege", + "Legal" : "Licensing information is available on https://code.google.com/p/orthanc/", + "Version" : "0.7.4" +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/SharedLibrary/SharedLibrary.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/SharedLibrary/SharedLibrary.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,56 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + + +#include "../../Core/HttpClient.h" +#include "../OrthancConnection.h" + + +class SharedLibrarySingleton +{ +public: + SharedLibrarySingleton() + { + Orthanc::HttpClient::GlobalInitialize(); + } + + ~SharedLibrarySingleton() + { + Orthanc::HttpClient::GlobalFinalize(); + } +}; + + +static SharedLibrarySingleton singleton_; + + +#include "AUTOGENERATED/ExternC.cpp" diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Study.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Study.cpp Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,79 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "Study.h" + +#include "OrthancConnection.h" + +namespace OrthancClient +{ + void Study::ReadStudy() + { + Orthanc::HttpClient client(connection_.GetHttpClient()); + client.SetUrl(std::string(connection_.GetOrthancUrl()) + "/studies/" + id_); + + Json::Value v; + if (!client.Apply(study_)) + { + throw OrthancClientException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + Orthanc::IDynamicObject* Study::GetFillerItem(size_t index) + { + Json::Value::ArrayIndex tmp = static_cast(index); + std::string id = study_["Series"][tmp].asString(); + return new Series(connection_, id.c_str()); + } + + Study::Study(const OrthancConnection& connection, + const char* id) : + connection_(connection), + id_(id), + series_(*this) + { + series_.SetThreadCount(connection.GetThreadCount()); + ReadStudy(); + } + + const char* Study::GetMainDicomTag(const char* tag, const char* defaultValue) const + { + if (study_["MainDicomTags"].isMember(tag)) + { + return study_["MainDicomTags"][tag].asCString(); + } + else + { + return defaultValue; + } + } +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/Study.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancCppClient/Study.h Tue Apr 22 16:47:21 2014 +0200 @@ -0,0 +1,119 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "Series.h" + +namespace OrthancClient +{ + /** + * {summary}{Connection to a study stored in %Orthanc.} + * {description}{This class encapsulates a connection to a study + * from a remote instance of %Orthanc.} + **/ + class LAAW_API Study : + public Orthanc::IDynamicObject, + private Orthanc::ArrayFilledByThreads::IFiller + { + private: + const OrthancConnection& connection_; + std::string id_; + Json::Value study_; + Orthanc::ArrayFilledByThreads series_; + + void ReadStudy(); + + virtual size_t GetFillerSize() + { + return study_["Series"].size(); + } + + virtual Orthanc::IDynamicObject* GetFillerItem(size_t index); + + public: + /** + * {summary}{Create a connection to some study.} + * {param}{connection The remote instance of %Orthanc.} + * {param}{id The %Orthanc identifier of the study.} + **/ + Study(const OrthancConnection& connection, + const char* id); + + /** + * {summary}{Reload the series of this study.} + * {description}{This method will reload the list of the series of this study. Pay attention to the fact that the series that have been previously returned by GetSeries() will be invalidated.} + **/ + void Reload() + { + series_.Reload(); + } + + /** + * {summary}{Return the number of series for this study.} + * {returns}{The number of series.} + **/ + uint32_t GetSeriesCount() + { + return series_.GetSize(); + } + + /** + * {summary}{Get some series of this study.} + * {description}{This method will return an object that contains information about some series. The series are indexed by a number between 0 (inclusive) and the result of GetSeriesCount() (exclusive).} + * {param}{index The index of the series of interest.} + * {returns}{The series.} + **/ + Series& GetSeries(uint32_t index) + { + return dynamic_cast(series_.GetItem(index)); + } + + /** + * {summary}{Get the %Orthanc identifier of this study.} + * {returns}{The identifier.} + **/ + const char* GetId() const + { + return id_.c_str(); + } + + /** + * {summary}{Get the value of one of the main DICOM tags for this study.} + * {param}{tag The name of the tag of interest ("StudyDate", "StudyDescription", "StudyInstanceUID" or "StudyTime").} + * {param}{defaultValue The default value to be returned if this tag does not exist.} + * {returns}{The value of the tag.} + **/ + const char* GetMainDicomTag(const char* tag, + const char* defaultValue) const; + }; +} diff -r 63f707278fc8 -r 45b16f67259c OrthancCppClient/main.cpp --- a/OrthancCppClient/main.cpp Fri May 03 12:23:02 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/** - * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege, - * Belgium - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - **/ - - -#include "HttpClient.h" - -#include - -int main() -{ - // Prepare a simple call to a Web service - Orthanc::HttpClient c; - c.SetUrl("http://nominatim.openstreetmap.org/search?format=json&q=chu+liege+belgium"); - - // Do the request and store the result in a JSON structure - Json::Value result; - c.Apply(result); - - // Display the JSON answer - std::cout << result << std::endl; - - return 0; -} diff -r 63f707278fc8 -r 45b16f67259c OrthancExplorer/explorer.html --- a/OrthancExplorer/explorer.html Fri May 03 12:23:02 2013 +0200 +++ b/OrthancExplorer/explorer.html Tue Apr 22 16:47:21 2014 +0200 @@ -88,12 +88,24 @@ - - Delete this patient - Store in another DICOM modality - Download ZIP - Anonymize

+ + +
@@ -156,15 +180,27 @@ -