Mercurial > hg > orthanc-wsi
changeset 136:0a1443204818
sync
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 10 Apr 2018 07:24:24 +0200 |
parents | c5c54d5c52e5 |
children | 90b392cb1aba |
files | Resources/Orthanc/Core/DicomFormat/DicomTag.h Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.cpp Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.cpp Resources/Orthanc/Core/SystemToolbox.cpp Resources/Orthanc/Core/SystemToolbox.h Resources/Orthanc/Core/TemporaryFile.cpp Resources/Orthanc/Core/Toolbox.cpp Resources/Orthanc/Core/Toolbox.h Resources/Orthanc/NEWS Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake Resources/Orthanc/Resources/CMake/Compiler.cmake Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake |
diffstat | 13 files changed, 301 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/Resources/Orthanc/Core/DicomFormat/DicomTag.h Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/DicomFormat/DicomTag.h Tue Apr 10 07:24:24 2018 +0200 @@ -123,8 +123,6 @@ static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID(0x0002, 0x0002); static const DicomTag DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID(0x0002, 0x0003); static const DicomTag DICOM_TAG_DEIDENTIFICATION_METHOD(0x0012, 0x0063); - static const DicomTag DICOM_TAG_REFERENCED_SOP_INSTANCE_UID(0x0008, 0x1155); - static const DicomTag DICOM_TAG_FRAME_OF_REFERENCE_UID(0x0020, 0x0052); // DICOM tags used for fMRI (thanks to Will Ryder) static const DicomTag DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS(0x0020, 0x0105); @@ -195,4 +193,14 @@ static const DicomTag DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES(0x0020, 0x1208); static const DicomTag DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES(0x0020, 0x1209); static const DicomTag DICOM_TAG_SOP_CLASSES_IN_STUDY(0x0008, 0x0062); + + // Tags to preserve relationships during anonymization + static const DicomTag DICOM_TAG_REFERENCED_IMAGE_SEQUENCE(0x0008, 0x1140); + static const DicomTag DICOM_TAG_REFERENCED_SOP_INSTANCE_UID(0x0008, 0x1155); + static const DicomTag DICOM_TAG_SOURCE_IMAGE_SEQUENCE(0x0008, 0x2112); + static const DicomTag DICOM_TAG_FRAME_OF_REFERENCE_UID(0x0020, 0x0052); + static const DicomTag DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_UID(0x3006, 0x0024); + static const DicomTag DICOM_TAG_RELATED_FRAME_OF_REFERENCE_UID(0x3006, 0x00c2); + static const DicomTag DICOM_TAG_CURRENT_REQUESTED_PROCEDURE_EVIDENCE_SEQUENCE(0x0040, 0xa375); + static const DicomTag DICOM_TAG_REFERENCED_SERIES_SEQUENCE(0x0008, 0x1115); }
--- a/Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.cpp Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/DicomParsing/FromDcmtkBridge.cpp Tue Apr 10 07:24:24 2018 +0200 @@ -37,14 +37,20 @@ #define NOMINMAX #endif +#if !defined(ORTHANC_SANDBOXED) +# error The macro ORTHANC_SANDBOXED must be defined +#endif + #include "FromDcmtkBridge.h" #include "ToDcmtkBridge.h" #include "../Logging.h" -#include "../SystemToolbox.h" #include "../Toolbox.h" -#include "../TemporaryFile.h" #include "../OrthancException.h" +#if ORTHANC_SANDBOXED == 0 +# include "../TemporaryFile.h" +#endif + #include <list> #include <limits> @@ -127,6 +133,7 @@ std::string content; EmbeddedResources::GetFileResource(content, resource); +#if ORTHANC_SANDBOXED == 0 TemporaryFile tmp; tmp.Write(content); @@ -136,6 +143,14 @@ << "your TEMP directory does not contain special characters."; throw OrthancException(ErrorCode_InternalError); } +#else + if (!dictionary.loadFromMemory(content)) + { + LOG(ERROR) << "Cannot read embedded dictionary. Under Windows, make sure that " + << "your TEMP directory does not contain special characters."; + throw OrthancException(ErrorCode_InternalError); + } +#endif } #else @@ -1151,7 +1166,7 @@ // The "PatientID" field is of type LO (Long String), 64 // Bytes Maximum. An UUID is of length 36, thus it can be used // as a random PatientID. - return SystemToolbox::GenerateUuid(); + return Toolbox::GenerateUuid(); case ResourceType_Instance: return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); @@ -2167,7 +2182,7 @@ case ITagVisitor::Action_Replace: { std::string s = Toolbox::ConvertFromUtf8(newValue, encoding); - if (element.putString(s.c_str(), s.size()) != EC_Normal) + if (element.putString(s.c_str()) != EC_Normal) { LOG(ERROR) << "Cannot replace value of tag: " << tag.Format(); throw OrthancException(ErrorCode_InternalError);
--- a/Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.cpp Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/DicomParsing/ToDcmtkBridge.cpp Tue Apr 10 07:24:24 2018 +0200 @@ -35,7 +35,6 @@ #include "ToDcmtkBridge.h" #include <memory> -#include <dcmtk/dcmnet/diutil.h> #include "../OrthancException.h"
--- a/Resources/Orthanc/Core/SystemToolbox.cpp Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/SystemToolbox.cpp Tue Apr 10 07:24:24 2018 +0200 @@ -62,19 +62,6 @@ #endif -// Inclusions for UUID -// http://stackoverflow.com/a/1626302 - -extern "C" -{ -#if defined(_WIN32) -# include <rpc.h> -#else -# include <uuid/uuid.h> -#endif -} - - #include "Logging.h" #include "OrthancException.h" #include "Toolbox.h" @@ -539,28 +526,6 @@ } - std::string SystemToolbox::GenerateUuid() - { -#ifdef WIN32 - UUID uuid; - UuidCreate ( &uuid ); - - unsigned char * str; - UuidToStringA ( &uuid, &str ); - - std::string s( ( char* ) str ); - - RpcStringFreeA ( &str ); -#else - uuid_t uuid; - uuid_generate_random ( uuid ); - char s[37]; - uuid_unparse ( uuid, s ); -#endif - return s; - } - - static boost::posix_time::ptime GetNow(bool utc) { if (utc)
--- a/Resources/Orthanc/Core/SystemToolbox.h Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/SystemToolbox.h Tue Apr 10 07:24:24 2018 +0200 @@ -93,8 +93,6 @@ FILE* OpenFile(const std::string& path, FileMode mode); - std::string GenerateUuid(); - std::string GetNowIsoString(bool utc); void GetNowDicom(std::string& date,
--- a/Resources/Orthanc/Core/TemporaryFile.cpp Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/TemporaryFile.cpp Tue Apr 10 07:24:24 2018 +0200 @@ -52,7 +52,7 @@ #endif // We use UUID to create unique path to temporary files - std::string filename = "Orthanc-" + Orthanc::SystemToolbox::GenerateUuid(); + std::string filename = "Orthanc-" + Orthanc::Toolbox::GenerateUuid(); if (extension != NULL) {
--- a/Resources/Orthanc/Core/Toolbox.cpp Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/Toolbox.cpp Tue Apr 10 07:24:24 2018 +0200 @@ -87,8 +87,94 @@ #endif +// Inclusions for UUID +// http://stackoverflow.com/a/1626302 + +extern "C" +{ +#if defined(_WIN32) +# include <rpc.h> +#else +# include <uuid/uuid.h> +#endif +} + + + namespace Orthanc { + void Toolbox::LinesIterator::FindEndOfLine() + { + lineEnd_ = lineStart_; + + while (lineEnd_ < content_.size() && + content_[lineEnd_] != '\n' && + content_[lineEnd_] != '\r') + { + lineEnd_ += 1; + } + } + + + Toolbox::LinesIterator::LinesIterator(const std::string& content) : + content_(content), + lineStart_(0) + { + FindEndOfLine(); + } + + + bool Toolbox::LinesIterator::GetLine(std::string& target) const + { + assert(lineStart_ <= content_.size() && + lineEnd_ <= content_.size() && + lineStart_ <= lineEnd_); + + if (lineStart_ == content_.size()) + { + return false; + } + else + { + target = content_.substr(lineStart_, lineEnd_ - lineStart_); + return true; + } + } + + + void Toolbox::LinesIterator::Next() + { + lineStart_ = lineEnd_; + + if (lineStart_ != content_.size()) + { + assert(content_[lineStart_] == '\r' || + content_[lineStart_] == '\n'); + + char second; + + if (content_[lineStart_] == '\r') + { + second = '\n'; + } + else + { + second = '\r'; + } + + lineStart_ += 1; + + if (lineStart_ < content_.size() && + content_[lineStart_] == second) + { + lineStart_ += 1; + } + + FindEndOfLine(); + } + } + + void Toolbox::ToUpperCase(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), toupper); @@ -1376,4 +1462,65 @@ return boost::locale::conv::utf_to_utf<char>(w); } #endif + + + std::string Toolbox::GenerateUuid() + { +#ifdef WIN32 + UUID uuid; + UuidCreate ( &uuid ); + + unsigned char * str; + UuidToStringA ( &uuid, &str ); + + std::string s( ( char* ) str ); + + RpcStringFreeA ( &str ); +#else + uuid_t uuid; + uuid_generate_random ( uuid ); + char s[37]; + uuid_unparse ( uuid, s ); +#endif + return s; + } } + + + +OrthancLinesIterator* OrthancLinesIterator_Create(const std::string& content) +{ + return reinterpret_cast<OrthancLinesIterator*>(new Orthanc::Toolbox::LinesIterator(content)); +} + + +bool OrthancLinesIterator_GetLine(std::string& target, + const OrthancLinesIterator* iterator) +{ + if (iterator != NULL) + { + return reinterpret_cast<const Orthanc::Toolbox::LinesIterator*>(iterator)->GetLine(target); + } + else + { + return false; + } +} + + +void OrthancLinesIterator_Next(OrthancLinesIterator* iterator) +{ + if (iterator != NULL) + { + reinterpret_cast<Orthanc::Toolbox::LinesIterator*>(iterator)->Next(); + } +} + + +void OrthancLinesIterator_Free(OrthancLinesIterator* iterator) +{ + if (iterator != NULL) + { + delete reinterpret_cast<const Orthanc::Toolbox::LinesIterator*>(iterator); + } +}
--- a/Resources/Orthanc/Core/Toolbox.h Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Core/Toolbox.h Tue Apr 10 07:24:24 2018 +0200 @@ -79,6 +79,24 @@ namespace Toolbox { + class LinesIterator + { + private: + const std::string& content_; + size_t lineStart_; + size_t lineEnd_; + + void FindEndOfLine(); + + public: + LinesIterator(const std::string& content); + + bool GetLine(std::string& target) const; + + void Next(); + }; + + void ToUpperCase(std::string& s); // Inplace version void ToLowerCase(std::string& s); // Inplace version @@ -214,5 +232,28 @@ std::string ToUpperCaseWithAccents(const std::string& source); #endif + + std::string GenerateUuid(); } } + + + + +/** + * The plain C, opaque data structure "OrthancLinesIterator" is a thin + * wrapper around Orthanc::Toolbox::LinesIterator, and is only used by + * "../Resources/WebAssembly/dcdict.cc", in order to avoid code + * duplication + **/ + +struct OrthancLinesIterator; + +OrthancLinesIterator* OrthancLinesIterator_Create(const std::string& content); + +bool OrthancLinesIterator_GetLine(std::string& target, + const OrthancLinesIterator* iterator); + +void OrthancLinesIterator_Next(OrthancLinesIterator* iterator); + +void OrthancLinesIterator_Free(OrthancLinesIterator* iterator);
--- a/Resources/Orthanc/NEWS Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/NEWS Tue Apr 10 07:24:24 2018 +0200 @@ -11,6 +11,7 @@ * Added "?expand" GET argument to "/peers" and "/modalities" routes * New URI: "/tools/create-media-extended" to generate a DICOMDIR archive from several resources, including additional type-3 tags +* Preservation of UID relationships while anonymizing Lua --- @@ -28,13 +29,15 @@ * Orthanc now uses UTC (universal time) instead of local time in its database * Fix to allow creating DICOM instances with empty Specific Character Set (0008,0005) -* Upgrade to curl 7.57.0 for static and Windows builds * Support of Linux Standard Base * Static linking against libuuid (from e2fsprogs) * Fix static build on CentOS 6 -* Upgrade to JsonCpp 1.8.4 for static builds * Possibility of using JsonCpp 0.10.6 if the compiler does not support C++11 with the "-DUSE_LEGACY_JSONCPP=ON" CMake option +* Upgraded dependencies for static and Windows builds: + - curl 7.57.0 + - jsoncpp 1.8.4 + - zlib 1.2.11 Version 1.3.1 (2017-11-29)
--- a/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Resources/CMake/BoostConfiguration.cmake Tue Apr 10 07:24:24 2018 +0200 @@ -145,6 +145,7 @@ ) elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + # No support for threads in WebAssembly else() message(FATAL_ERROR "Support your platform here") @@ -254,7 +255,8 @@ CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "PNaCl" OR CMAKE_SYSTEM_NAME STREQUAL "NaCl32" OR - CMAKE_SYSTEM_NAME STREQUAL "NaCl64") + CMAKE_SYSTEM_NAME STREQUAL "NaCl64" OR + CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # For WebAssembly or asm.js list(APPEND BOOST_SOURCES ${BOOST_SOURCES_DIR}/libs/locale/src/posix/codecvt.cpp ${BOOST_SOURCES_DIR}/libs/locale/src/posix/collate.cpp
--- a/Resources/Orthanc/Resources/CMake/Compiler.cmake Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Resources/CMake/Compiler.cmake Tue Apr 10 07:24:24 2018 +0200 @@ -174,6 +174,12 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") message("Building using Emscripten (for WebAssembly or asm.js targets)") + # The BINARYEN_TRAP_MODE specifies what to do when divisions per + # zero (and similar conditions like integer overflows) are + # encountered: The "clamp" mode avoids throwing errors, as they + # cannot be properly catched by "try {} catch (...)" constructions. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]' -s BINARYEN_TRAP_MODE='\"clamp\"'") + else() message(FATAL_ERROR "Support your platform here") endif()
--- a/Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Resources/CMake/DcmtkConfiguration.cmake Tue Apr 10 07:24:24 2018 +0200 @@ -100,14 +100,26 @@ message("The patches for DCMTK have already been applied") endif() + IF (CMAKE_CROSSCOMPILING) if (CMAKE_COMPILER_IS_GNUCXX AND - ${CMAKE_SYSTEM_NAME} STREQUAL "Windows") # MinGW + CMAKE_SYSTEM_NAME STREQUAL "Windows") # MinGW SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.") + + elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # WebAssembly or asm.js + + # Check out "../WebAssembly/ArithmeticTests/" to regenerate the + # "arith.h" file + configure_file( + ${ORTHANC_ROOT}/Resources/WebAssembly/arith.h + ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/arith.h + COPYONLY) + else() message(FATAL_ERROR "Support your platform here") endif() ENDIF() + if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase") SET(DCMTK_ENABLE_CHARSET_CONVERSION "iconv" CACHE STRING "") @@ -129,6 +141,35 @@ include(${DCMTK_SOURCES_DIR}/CMake/CheckFunctionWithHeaderExists.cmake) include(${DCMTK_SOURCES_DIR}/CMake/GenerateDCMTKConfigure.cmake) + + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # WebAssembly or + # asm.js The macros below are not properly discovered by DCMTK + # when using WebAssembly. Check out "../WebAssembly/arith.h" for + # how we produced these values. This step MUST be after + # "GenerateDCMTKConfigure" and before the generation of + # "osconfig.h". + UNSET(SIZEOF_VOID_P CACHE) + UNSET(SIZEOF_CHAR CACHE) + UNSET(SIZEOF_DOUBLE CACHE) + UNSET(SIZEOF_FLOAT CACHE) + UNSET(SIZEOF_INT CACHE) + UNSET(SIZEOF_LONG CACHE) + UNSET(SIZEOF_SHORT CACHE) + UNSET(SIZEOF_VOID_P CACHE) + UNSET(C_CHAR_UNSIGNED CACHE) + + SET(SIZEOF_VOID_P 4 CACHE INTERNAL "") + SET(SIZEOF_CHAR 1 CACHE INTERNAL "") + SET(SIZEOF_DOUBLE 8 CACHE INTERNAL "") + SET(SIZEOF_FLOAT 4 CACHE INTERNAL "") + SET(SIZEOF_INT 4 CACHE INTERNAL "") + SET(SIZEOF_LONG 4 CACHE INTERNAL "") + SET(SIZEOF_SHORT 2 CACHE INTERNAL "") + SET(SIZEOF_VOID_P 4 CACHE INTERNAL "") + SET(C_CHAR_UNSIGNED 0 CACHE INTERNAL "") + endif() + + set(DCMTK_PACKAGE_VERSION_SUFFIX "") set(DCMTK_PACKAGE_VERSION_NUMBER ${DCMTK_VERSION_NUMBER}) @@ -151,7 +192,9 @@ endif() # This step must be after the generation of "osconfig.h" - INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES() + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES() + endif() endif() AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmdata/libsrc DCMTK_SOURCES) @@ -218,7 +261,8 @@ ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR - ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") + ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" OR + ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") list(REMOVE_ITEM DCMTK_SOURCES ${DCMTK_SOURCES_DIR}/oflog/libsrc/clfsap.cc ${DCMTK_SOURCES_DIR}/oflog/libsrc/windebap.cc @@ -248,18 +292,26 @@ endif() endif() + + if (NOT USE_DCMTK_360 AND + ORTHANC_SANDBOXED) + configure_file( + ${ORTHANC_ROOT}/Resources/WebAssembly/dcdict.h + ${DCMTK_SOURCES_DIR}/dcmdata/include/dcmtk/dcmdata/dcdict.h + COPYONLY) + + configure_file( + ${ORTHANC_ROOT}/Resources/WebAssembly/dcdict.cc + ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdict.cc + COPYONLY) + endif() + + list(REMOVE_ITEM DCMTK_SOURCES ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdictbi.cc ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdeftag.cc ) - if (USE_DCMTK_360) - # Removing this file is required with DCMTK 3.6.0 - list(REMOVE_ITEM DCMTK_SOURCES - ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdictbi.cc - ) - endif() - #set_source_files_properties(${DCMTK_SOURCES} # PROPERTIES COMPILE_DEFINITIONS # "PACKAGE_VERSION=\"${DCMTK_PACKAGE_VERSION}\";PACKAGE_VERSION_NUMBER=\"${DCMTK_VERSION_NUMBER}\"") @@ -361,6 +413,10 @@ /usr/share/libdcmtk14 /usr/share/libdcmtk15 /usr/share/libdcmtk16 + /usr/share/libdcmtk17 + /usr/share/libdcmtk18 + /usr/share/libdcmtk19 + /usr/share/libdcmtk20 /usr/local/share/dcmtk )
--- a/Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake Mon Mar 26 11:04:50 2018 +0200 +++ b/Resources/Orthanc/Resources/CMake/ZlibConfiguration.cmake Tue Apr 10 07:24:24 2018 +0200 @@ -1,7 +1,7 @@ if (STATIC_BUILD OR NOT USE_SYSTEM_ZLIB) - SET(ZLIB_SOURCES_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.7) - SET(ZLIB_URL "http://www.orthanc-server.com/downloads/third-party/zlib-1.2.7.tar.gz") - SET(ZLIB_MD5 "60df6a37c56e7c1366cca812414f7b85") + SET(ZLIB_SOURCES_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.11) + SET(ZLIB_URL "http://www.orthanc-server.com/downloads/third-party/zlib-1.2.11.tar.gz") + SET(ZLIB_MD5 "1c9f62f0778697a09d36121ead88e08e") DownloadPackage(${ZLIB_MD5} ${ZLIB_URL} "${ZLIB_SOURCES_DIR}")