# HG changeset patch # User Sebastien Jodogne # Date 1547467992 -3600 # Node ID a323b75e5b08f4570c84d6a4ff53375b42eb5d37 # Parent 0fa7181ac4e5fdcafba72ea07f8dfa0d3abe7c5b# Parent 8f2bda0719f4b9242e69df916c360c55e4b8c778 Fix issue #125 (Mongoose: /instances/{id} returns 500 on invalid HTTP Method) diff -r 0fa7181ac4e5 -r a323b75e5b08 Core/DicomNetworking/DicomUserConnection.cpp --- a/Core/DicomNetworking/DicomUserConnection.cpp Sat Jan 12 11:08:53 2019 +0100 +++ b/Core/DicomNetworking/DicomUserConnection.cpp Mon Jan 14 13:13:12 2019 +0100 @@ -82,6 +82,10 @@ #include "../PrecompiledHeaders.h" #include "DicomUserConnection.h" +#if !defined(DCMTK_VERSION_NUMBER) +# error The macro DCMTK_VERSION_NUMBER must be defined +#endif + #include "../DicomFormat/DicomArray.h" #include "../Logging.h" #include "../OrthancException.h" @@ -330,7 +334,12 @@ // Figure out which SOP class and SOP instance is encapsulated in the file DIC_UI sopClass; DIC_UI sopInstance; + +#if DCMTK_VERSION_NUMBER >= 364 + if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sizeof(sopClass), sopInstance, sizeof(sopInstance))) +#else if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) +#endif { throw OrthancException(ErrorCode_NoSopClassOrInstance); } @@ -572,7 +581,15 @@ T_DIMSE_C_FindRSP response; DcmDataset* statusDetail = NULL; + +#if DCMTK_VERSION_NUMBER >= 364 + int responseCount; +#endif + OFCondition cond = DIMSE_findUser(association, presID, &request, dataset, +#if DCMTK_VERSION_NUMBER >= 364 + responseCount, +#endif FindCallback, &payload, /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ dimseTimeout, diff -r 0fa7181ac4e5 -r a323b75e5b08 Core/DicomNetworking/Internals/CommandDispatcher.cpp --- a/Core/DicomNetworking/Internals/CommandDispatcher.cpp Sat Jan 12 11:08:53 2019 +0100 +++ b/Core/DicomNetworking/Internals/CommandDispatcher.cpp Mon Jan 14 13:13:12 2019 +0100 @@ -83,6 +83,10 @@ #include "../../PrecompiledHeaders.h" #include "CommandDispatcher.h" +#if !defined(DCMTK_VERSION_NUMBER) +# error The macro DCMTK_VERSION_NUMBER must be defined +#endif + #include "FindScp.h" #include "StoreScp.h" #include "MoveScp.h" @@ -364,7 +368,11 @@ UID_RETIRED_UltrasoundImageStorage, UID_RETIRED_UltrasoundMultiframeImageStorage, UID_RETIRED_VLImageStorage, +#if DCMTK_VERSION_NUMBER >= 364 + UID_RETIRED_VLMultiframeImageStorage, +#else UID_RETIRED_VLMultiFrameImageStorage, +#endif UID_RETIRED_XRayAngiographicBiPlaneImageStorage, // draft UID_DRAFT_SRAudioStorage, @@ -469,8 +477,16 @@ DIC_AE calledAet_C; DIC_AE remoteIp_C; DIC_AE calledIP_C; - if (ASC_getAPTitles(assoc->params, remoteAet_C, calledAet_C, NULL).bad() || - ASC_getPresentationAddresses(assoc->params, remoteIp_C, calledIP_C).bad()) + + if ( +#if DCMTK_VERSION_NUMBER >= 364 + ASC_getAPTitles(assoc->params, remoteAet_C, sizeof(remoteAet_C), calledAet_C, sizeof(calledAet_C), NULL, 0).bad() || + ASC_getPresentationAddresses(assoc->params, remoteIp_C, sizeof(remoteIp_C), calledIP_C, sizeof(calledIP_C)).bad() +#else + ASC_getAPTitles(assoc->params, remoteAet_C, calledAet_C, NULL).bad() || + ASC_getPresentationAddresses(assoc->params, remoteIp_C, calledIP_C).bad() +#endif + ) { T_ASC_RejectParameters rej = { @@ -606,7 +622,12 @@ ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); /* acknowledge or reject this association */ +#if DCMTK_VERSION_NUMBER >= 364 + cond = ASC_getApplicationContextName(assoc->params, buf, sizeof(buf)); +#else cond = ASC_getApplicationContextName(assoc->params, buf); +#endif + if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) { /* reject: the application context name is not supported */ diff -r 0fa7181ac4e5 -r a323b75e5b08 Core/DicomNetworking/Internals/StoreScp.cpp --- a/Core/DicomNetworking/Internals/StoreScp.cpp Sat Jan 12 11:08:53 2019 +0100 +++ b/Core/DicomNetworking/Internals/StoreScp.cpp Mon Jan 14 13:13:12 2019 +0100 @@ -83,6 +83,10 @@ #include "../../PrecompiledHeaders.h" #include "StoreScp.h" +#if !defined(DCMTK_VERSION_NUMBER) +# error The macro DCMTK_VERSION_NUMBER must be defined +#endif + #include "../../DicomParsing/FromDcmtkBridge.h" #include "../../DicomParsing/ToDcmtkBridge.h" #include "../../OrthancException.h" @@ -188,10 +192,16 @@ if (rsp->DimseStatus == STATUS_Success) { // which SOP class and SOP instance ? + +#if DCMTK_VERSION_NUMBER >= 364 + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sizeof(sopClass), + sopInstance, sizeof(sopInstance), /*opt_correctUIDPadding*/ OFFalse)) +#else if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, /*opt_correctUIDPadding*/ OFFalse)) +#endif { - //LOG4CPP_ERROR(Internals::GetLogger(), "bad DICOM file: " << fileName); - rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + //LOG4CPP_ERROR(Internals::GetLogger(), "bad DICOM file: " << fileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; } else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) { diff -r 0fa7181ac4e5 -r a323b75e5b08 Core/DicomParsing/FromDcmtkBridge.cpp --- a/Core/DicomParsing/FromDcmtkBridge.cpp Sat Jan 12 11:08:53 2019 +0100 +++ b/Core/DicomParsing/FromDcmtkBridge.cpp Mon Jan 14 13:13:12 2019 +0100 @@ -41,6 +41,10 @@ # error The macro ORTHANC_SANDBOXED must be defined #endif +#if !defined(DCMTK_VERSION_NUMBER) +# error The macro DCMTK_VERSION_NUMBER must be defined +#endif + #include "FromDcmtkBridge.h" #include "ToDcmtkBridge.h" #include "../Logging.h" @@ -165,7 +169,11 @@ ~DictionaryLocker() { +#if DCMTK_VERSION_NUMBER >= 364 + dcmDataDict.wrunlock(); +#else dcmDataDict.unlock(); +#endif } DcmDataDictionary& operator*() diff -r 0fa7181ac4e5 -r a323b75e5b08 NEWS --- a/NEWS Sat Jan 12 11:08:53 2019 +0100 +++ b/NEWS Mon Jan 14 13:13:12 2019 +0100 @@ -15,9 +15,11 @@ ----------- * Don't consider tags whose group is below 0x0008 in C-FIND SCP +* Compatibility with DCMTK 3.6.4 * Fix issue #21 (DICOM files missing after uploading with Firefox) * Fix issue #118 (Wording in Configuration.json regarding SynchronousCMove) * Fix issue #124 (GET /studies/ID/media fails for certain dicom file) +* Fix issue #125 (Mongoose: /instances/{id} returns 500 on invalid HTTP Method) * Fixed Orthanc Explorer on IE and Firefox: Explorer always show "too many results" and it's therefore impossible to browse the content. * Upgraded dependencies for static and Windows builds: diff -r 0fa7181ac4e5 -r a323b75e5b08 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Sat Jan 12 11:08:53 2019 +0100 +++ b/Plugins/Engine/OrthancPlugins.cpp Mon Jan 14 13:13:12 2019 +0100 @@ -38,6 +38,10 @@ #error The plugin support is disabled #endif +#if !defined(DCMTK_VERSION_NUMBER) +# error The macro DCMTK_VERSION_NUMBER must be defined +#endif + #include "../../Core/ChunkedBuffer.h" #include "../../Core/DicomFormat/DicomArray.h" @@ -2416,7 +2420,11 @@ ~DictionaryReadLocker() { +#if DCMTK_VERSION_NUMBER >= 364 + dcmDataDict.rdunlock(); +#else dcmDataDict.unlock(); +#endif } const DcmDataDictionary* operator->() diff -r 0fa7181ac4e5 -r a323b75e5b08 Resources/Patches/mongoose-3.8-patch.diff --- a/Resources/Patches/mongoose-3.8-patch.diff Sat Jan 12 11:08:53 2019 +0100 +++ b/Resources/Patches/mongoose-3.8-patch.diff Mon Jan 14 13:13:12 2019 +0100 @@ -1,5 +1,5 @@ ---- mongoose.c.orig 2014-09-01 11:25:18.223466994 +0200 -+++ mongoose.c 2014-09-01 11:30:21.807479338 +0200 +--- mongoose.c.orig 2019-01-14 13:06:27.147098524 +0100 ++++ mongoose.c 2019-01-14 12:44:35.331361929 +0100 @@ -50,6 +50,14 @@ #define PATH_MAX FILENAME_MAX #endif // __SYMBIAN32__ @@ -27,3 +27,80 @@ #endif // _MSC_VER #define ERRNO GetLastError() +@@ -2997,19 +3006,19 @@ + } + } + +-static int is_valid_http_method(const char *method) { +- return !strcmp(method, "GET") || !strcmp(method, "POST") || ++static int is_valid_http_method(const char *method, int *isValidHttpMethod) { ++ *isValidHttpMethod = !strcmp(method, "GET") || !strcmp(method, "POST") || + !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") || + !strcmp(method, "PUT") || !strcmp(method, "DELETE") || + !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND") +- || !strcmp(method, "MKCOL") +- ; ++ || !strcmp(method, "MKCOL"); ++ return *isValidHttpMethod; + } + + // Parse HTTP request, fill in mg_request_info structure. + // This function modifies the buffer by NUL-terminating + // HTTP request components, header names and header values. +-static int parse_http_message(char *buf, int len, struct mg_request_info *ri) { ++static int parse_http_message(char *buf, int len, struct mg_request_info *ri, int *isValidHttpMethod) { + int is_request, request_length = get_request_len(buf, len); + if (request_length > 0) { + // Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port +@@ -3025,7 +3034,7 @@ + ri->request_method = skip(&buf, " "); + ri->uri = skip(&buf, " "); + ri->http_version = skip(&buf, "\r\n"); +- if (((is_request = is_valid_http_method(ri->request_method)) && ++ if (((is_request = is_valid_http_method(ri->request_method, isValidHttpMethod)) && + memcmp(ri->http_version, "HTTP/", 5) != 0) || + (!is_request && memcmp(ri->request_method, "HTTP/", 5)) != 0) { + request_length = -1; +@@ -4930,7 +4939,7 @@ + return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0'); + } + +-static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len) { ++static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *isValidHttpMethod) { + const char *cl; + + ebuf[0] = '\0'; +@@ -4944,7 +4953,7 @@ + } else if (conn->request_len <= 0) { + snprintf(ebuf, ebuf_len, "%s", "Client closed connection"); + } else if (parse_http_message(conn->buf, conn->buf_size, +- &conn->request_info) <= 0) { ++ &conn->request_info, isValidHttpMethod) <= 0) { + snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf); + } else { + // Request is valid +@@ -4973,7 +4982,8 @@ + } else if (mg_vprintf(conn, fmt, ap) <= 0) { + snprintf(ebuf, ebuf_len, "%s", "Error sending request"); + } else { +- getreq(conn, ebuf, ebuf_len); ++ int isValidHttpMethod = 1; /* unused in this case */ ++ getreq(conn, ebuf, ebuf_len, &isValidHttpMethod); + } + if (ebuf[0] != '\0' && conn != NULL) { + mg_close_connection(conn); +@@ -4995,8 +5005,13 @@ + // to crule42. + conn->data_len = 0; + do { +- if (!getreq(conn, ebuf, sizeof(ebuf))) { ++ int isValidHttpMethod = 1; ++ if (!getreq(conn, ebuf, sizeof(ebuf), &isValidHttpMethod)) { ++ if (isValidHttpMethod) { + send_http_error(conn, 500, "Server Error", "%s", ebuf); ++ } else { ++ send_http_error(conn, 400, "Bad Request", "%s", ebuf); ++ } + conn->must_close = 1; + } else if (!is_valid_uri(conn->request_info.uri)) { + snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri);