changeset 3120:a323b75e5b08 db-changes

Fix issue #125 (Mongoose: /instances/{id} returns 500 on invalid HTTP Method)
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 14 Jan 2019 13:13:12 +0100
parents 0fa7181ac4e5 (current diff) 8f2bda0719f4 (diff)
children f86ebf971a72
files NEWS Plugins/Engine/OrthancPlugins.cpp
diffstat 7 files changed, 149 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- 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 */
--- 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)
             {
--- 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*()
--- 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:
--- 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->()
--- 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);