changeset 3361:ea07b29c6d0e emscripten-logging

Merge fro default
author Benjamin Golinvaux <bgo@osimis.io>
date Tue, 07 May 2019 13:10:48 +0200
parents 815b81142ff7 (current diff) 7569d3dc1c20 (diff)
children 0b88d89e71d5
files Core/Logging.cpp
diffstat 10 files changed, 283 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/FileBuffer.cpp	Tue May 07 13:10:48 2019 +0200
@@ -0,0 +1,122 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "PrecompiledHeaders.h"
+#include "FileBuffer.h"
+
+#include "TemporaryFile.h"
+#include "OrthancException.h"
+
+#include <boost/filesystem/fstream.hpp>
+
+
+namespace Orthanc
+{
+  class FileBuffer::PImpl
+  {
+  private:
+    TemporaryFile                file_;
+    boost::filesystem::ofstream  stream_;
+    bool                         isWriting_;
+
+  public:
+    PImpl() :
+      isWriting_(true)
+    {
+      stream_.open(file_.GetPath(), std::ofstream::out | std::ofstream::binary);
+      if (!stream_.good())
+      {
+        throw OrthancException(ErrorCode_CannotWriteFile);
+      }
+    }
+
+    ~PImpl()
+    {
+      if (isWriting_)
+      {
+        stream_.close();
+      }
+    }
+
+    void Append(const char* buffer,
+                size_t size)
+    {
+      if (!isWriting_)
+      {
+        throw OrthancException(ErrorCode_BadSequenceOfCalls);
+      }
+
+      if (size > 0)
+      {
+        stream_.write(buffer, size);
+        if (!stream_.good())
+        {
+          stream_.close();
+          throw OrthancException(ErrorCode_FileStorageCannotWrite);
+        }
+      }
+    }
+
+    void Read(std::string& target)
+    {
+      if (isWriting_)
+      {
+        stream_.close();
+        isWriting_ = false;
+      }
+
+      file_.Read(target);
+    }
+  };
+
+    
+  FileBuffer::FileBuffer() :
+    pimpl_(new PImpl)
+  {
+  }
+
+
+  void FileBuffer::Append(const char* buffer,
+                          size_t size)
+  {
+    assert(pimpl_.get() != NULL);
+    pimpl_->Append(buffer, size);
+  }
+
+
+  void FileBuffer::Read(std::string& target)
+  {
+    assert(pimpl_.get() != NULL);
+    pimpl_->Read(target);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/FileBuffer.h	Tue May 07 13:10:48 2019 +0200
@@ -0,0 +1,64 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#if !defined(ORTHANC_SANDBOXED)
+#  error The macro ORTHANC_SANDBOXED must be defined
+#endif
+
+#if ORTHANC_SANDBOXED == 1
+#  error The namespace SystemToolbox cannot be used in sandboxed environments
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+
+namespace Orthanc
+{
+  class FileBuffer : public boost::noncopyable
+  {
+  private:
+    class PImpl;
+    boost::shared_ptr<PImpl> pimpl_;
+
+  public:
+    FileBuffer();
+
+    void Append(const char* buffer,
+                size_t size);
+
+    void Read(std::string& target);
+  };
+}
--- a/Core/HttpClient.cpp	Tue May 07 11:23:11 2019 +0200
+++ b/Core/HttpClient.cpp	Tue May 07 13:10:48 2019 +0200
@@ -358,7 +358,7 @@
 
     url_ = "";
     method_ = HttpMethod_Get;
-    lastStatus_ = HttpStatus_200_Ok;
+    lastStatus_ = HttpStatus_None;
     SetVerbose(GlobalParameters::GetInstance().IsDefaultVerbose());
     timeout_ = GlobalParameters::GetInstance().GetDefaultTimeout();
     GlobalParameters::GetInstance().GetDefaultProxy(proxy_);
--- a/Core/HttpServer/HttpServer.cpp	Tue May 07 11:23:11 2019 +0200
+++ b/Core/HttpServer/HttpServer.cpp	Tue May 07 13:10:48 2019 +0200
@@ -36,9 +36,11 @@
 #include "../PrecompiledHeaders.h"
 #include "HttpServer.h"
 
+#include "../ChunkedBuffer.h"
+#include "../FileBuffer.h"
 #include "../Logging.h"
-#include "../ChunkedBuffer.h"
 #include "../OrthancException.h"
+#include "../TemporaryFile.h"
 #include "HttpToolbox.h"
 
 #if ORTHANC_ENABLE_MONGOOSE == 1
@@ -308,41 +310,69 @@
     IHttpHandler::Arguments::const_iterator cs = headers.find("content-length");
     if (cs == headers.end())
     {
-      return PostDataStatus_NoLength;
-    }
-
-    int length;      
-    try
-    {
-      length = boost::lexical_cast<int>(cs->second);
-    }
-    catch (boost::bad_lexical_cast&)
-    {
-      return PostDataStatus_NoLength;
-    }
+      // Store all the individual chunks within a temporary file, then
+      // read it back into the memory buffer "postData"
+      FileBuffer buffer;
 
-    if (length < 0)
-    {
-      length = 0;
-    }
-
-    postData.resize(length);
-
-    size_t pos = 0;
-    while (length > 0)
-    {
-      int r = mg_read(connection, &postData[pos], length);
-      if (r <= 0)
+      std::string tmp(1024 * 1024, 0);
+      
+      for (;;)
       {
-        return PostDataStatus_Failure;
+        int r = mg_read(connection, &tmp[0], tmp.size());
+        if (r < 0)
+        {
+          return PostDataStatus_Failure;
+        }
+        else if (r == 0)
+        {
+          break;
+        }
+        else
+        {
+          buffer.Append(tmp.c_str(), r);
+        }
       }
 
-      assert(r <= length);
-      length -= r;
-      pos += r;
+      buffer.Read(postData);
+
+      return PostDataStatus_Success;
     }
+    else
+    {
+      // "Content-Length" is available
+      int length;      
+      try
+      {
+        length = boost::lexical_cast<int>(cs->second);
+      }
+      catch (boost::bad_lexical_cast&)
+      {
+        return PostDataStatus_NoLength;
+      }
 
-    return PostDataStatus_Success;
+      if (length < 0)
+      {
+        length = 0;
+      }
+
+      postData.resize(length);
+
+      size_t pos = 0;
+      while (length > 0)
+      {
+        int r = mg_read(connection, &postData[pos], length);
+        if (r <= 0)
+        {
+          return PostDataStatus_Failure;
+        }
+
+        assert(r <= length);
+        length -= r;
+        pos += r;
+      }
+
+      return PostDataStatus_Success;
+    }
   }
 
 
--- a/Core/Logging.cpp	Tue May 07 11:23:11 2019 +0200
+++ b/Core/Logging.cpp	Tue May 07 13:10:48 2019 +0200
@@ -274,6 +274,10 @@
       }
     }
 
+    void Initialize()
+    {
+    }
+
     void EnableInfoLevel(bool enabled)
     {
       globalVerbose_ = enabled;
--- a/NEWS	Tue May 07 11:23:11 2019 +0200
+++ b/NEWS	Tue May 07 13:10:48 2019 +0200
@@ -5,6 +5,7 @@
 Maintenance
 -----------
 
+* Orthanc now accepts "-H 'Transfer-Encoding: chunked'" option from curl
 * Size of the Orthanc static binaries are reduced by compressing ICU data
 * Anonymization: Preserve hierarchical relationships in (0008,1115) [] (0020,000e)
 * Fix issue #136 (C-FIND request fails when found DICOM file does not have certain tags)
--- a/Plugins/Samples/GdcmDecoder/GdcmImageDecoder.cpp	Tue May 07 11:23:11 2019 +0200
+++ b/Plugins/Samples/GdcmDecoder/GdcmImageDecoder.cpp	Tue May 07 13:10:48 2019 +0200
@@ -371,7 +371,10 @@
     if (decoded.empty())
     {
       decoded.resize(pimpl_->GetImage().GetBufferLength());
-      pimpl_->GetImage().GetBuffer(&decoded[0]);
+      if (!pimpl_->GetImage().GetBuffer(&decoded[0]))
+      {
+        throw std::runtime_error("Image not properly decoded to a memory buffer");
+      }
     }
 
     const void* sourceBuffer = &decoded[0];
--- a/Resources/CMake/OrthancFrameworkConfiguration.cmake	Tue May 07 11:23:11 2019 +0200
+++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake	Tue May 07 13:10:48 2019 +0200
@@ -541,6 +541,7 @@
 
   list(APPEND ORTHANC_CORE_SOURCES_INTERNAL
     ${ORTHANC_ROOT}/Core/Cache/SharedArchive.cpp
+    ${ORTHANC_ROOT}/Core/FileBuffer.cpp
     ${ORTHANC_ROOT}/Core/FileStorage/FilesystemStorage.cpp
     ${ORTHANC_ROOT}/Core/MetricsRegistry.cpp
     ${ORTHANC_ROOT}/Core/MultiThreading/RunnableWorkersPool.cpp
--- a/Resources/EmbedResources.py	Tue May 07 11:23:11 2019 +0200
+++ b/Resources/EmbedResources.py	Tue May 07 13:10:48 2019 +0200
@@ -231,6 +231,12 @@
 
     # http://stackoverflow.com/a/1035360
     pos = 0
+    buffer = []  # instead of appending a few bytes at a time to the cpp file, 
+                 # we first append each chunk to a list, join it and write it 
+                 # to the file.  We've measured that it was 2-3 times faster in python3.
+                 # Note that speed is important since if generation is too slow,
+                 # cmake might try to compile the EmbeddedResources.cpp file while it is
+                 # still being generated !
     for b in content:
         if PYTHON_MAJOR_VERSION == 2:
             c = ord(b[0])
@@ -238,17 +244,18 @@
             c = b
 
         if pos > 0:
-            cpp.write(', ')
+            buffer.append(",")
 
         if (pos % 16) == 0:
-            cpp.write('\n    ')
+            buffer.append("\n")
 
         if c < 0:
             raise Exception("Internal error")
 
-        cpp.write("0x%02x" % c)
+        buffer.append("0x%02x" % c)
         pos += 1
 
+    cpp.write("".join(buffer))
     # Zero-size array are disallowed, so we put one single void character in it.
     if pos == 0:
         cpp.write('  0')
--- a/UnitTestsSources/UnitTestsMain.cpp	Tue May 07 11:23:11 2019 +0200
+++ b/UnitTestsSources/UnitTestsMain.cpp	Tue May 07 13:10:48 2019 +0200
@@ -39,6 +39,7 @@
 #include <ctype.h>
 
 #include "../Core/DicomFormat/DicomTag.h"
+#include "../Core/FileBuffer.h"
 #include "../Core/HttpServer/HttpToolbox.h"
 #include "../Core/Logging.h"
 #include "../Core/MetricsRegistry.h"
@@ -679,6 +680,21 @@
 }
 
 
+TEST(Toolbox, FileBuffer)
+{
+  FileBuffer f;
+  f.Append("a", 1);
+  f.Append("", 0);
+  f.Append("bc", 2);
+
+  std::string s;
+  f.Read(s);
+  ASSERT_EQ("abc", s);
+
+  ASSERT_THROW(f.Append("d", 1), OrthancException);  // File is closed
+}
+
+
 TEST(Toolbox, Wildcard)
 {
   ASSERT_EQ("abcd", Toolbox::WildcardToRegularExpression("abcd"));