changeset 1522:f938f7779bcb

fixes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 11 Aug 2015 15:37:42 +0200
parents 3606278d305e
children c388502a066d
files Core/HttpServer/BufferHttpSender.h Core/HttpServer/FilesystemHttpSender.cpp Core/HttpServer/FilesystemHttpSender.h Core/HttpServer/HttpFileSender.cpp Core/HttpServer/HttpFileSender.h Core/HttpServer/HttpOutput.cpp OrthancServer/OrthancRestApi/OrthancRestArchive.cpp OrthancServer/ServerContext.cpp
diffstat 8 files changed, 169 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/BufferHttpSender.h	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/BufferHttpSender.h	Tue Aug 11 15:37:42 2015 +0200
@@ -61,6 +61,13 @@
      * Implementation of the IHttpStreamAnswer interface.
      **/
 
+    virtual HttpCompression GetHttpCompression(bool /*gzipAllowed*/, 
+                                               bool /*deflateAllowed*/)
+    {
+      // No compression is supported
+      return HttpCompression_None;
+    }
+
     virtual uint64_t GetContentLength()
     {
       return buffer_.size();
--- a/Core/HttpServer/FilesystemHttpSender.cpp	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/FilesystemHttpSender.cpp	Tue Aug 11 15:37:42 2015 +0200
@@ -33,6 +33,8 @@
 #include "FilesystemHttpSender.h"
 
 #include "../Toolbox.h"
+#include "../OrthancException.h"
+#include "../Compression/ZlibCompressor.h"
 
 #include <stdio.h>
 
@@ -41,45 +43,131 @@
 
 namespace Orthanc
 {
-  void FilesystemHttpSender::Open()
+  void FilesystemHttpSender::Initialize(const boost::filesystem::path& path)
   {
-    SetFilename(path_.filename().string());
-    file_.open(path_.string().c_str(), std::ifstream::binary);
+    sourceCompression_ = CompressionType_None;
+    targetCompression_ = HttpCompression_None;
+
+    SetContentFilename(path.filename().string());
+    file_.open(path.string().c_str(), std::ifstream::binary);
+
+    if (!file_.is_open())
+    {
+      throw OrthancException(ErrorCode_InexistentFile);
+    }
 
     file_.seekg(0, file_.end);
     size_ = file_.tellg();
     file_.seekg(0, file_.beg);
-
-    chunk_.resize(CHUNK_SIZE);
-    chunkSize_ = 0;
-  }
-
-  FilesystemHttpSender::FilesystemHttpSender(const char* path)
-  {
-    path_ = std::string(path);
-    Open();
   }
 
-  FilesystemHttpSender::FilesystemHttpSender(const boost::filesystem::path& path)
+
+  HttpCompression FilesystemHttpSender::GetHttpCompression(bool gzipAllowed, 
+                                                           bool deflateAllowed)
   {
-    path_ = path;
-    Open();
-  }
+    switch (sourceCompression_)
+    {
+      case CompressionType_None:
+      {
+        return HttpCompression_None;
+      }
+
+      case CompressionType_ZlibWithSize:
+      {
+        if (size_ == 0)
+        {
+          return HttpCompression_None;
+        }
+
+        if (size_ < sizeof(uint64_t))
+        {
+          throw OrthancException(ErrorCode_CorruptedFile);
+        }
 
-  FilesystemHttpSender::FilesystemHttpSender(const FilesystemStorage& storage,
-                                             const std::string& uuid)
-  {
-    path_ = storage.GetPath(uuid).string();
-    Open();
+        if (deflateAllowed)
+        {
+          file_.seekg(sizeof(uint64_t), file_.end);
+          return HttpCompression_Deflate;
+        }
+        else
+        {
+          uncompressed_.reset(new BufferHttpSender);
+
+          // TODO Stream-based uncompression
+          assert(size_ != 0);
+          std::string compressed;
+          compressed.resize(size_);
+
+          file_.read(&compressed[0], size_);
+          if ((file_.flags() & std::istream::failbit) ||
+              !(file_.flags() & std::istream::eofbit))
+          {
+            throw OrthancException(ErrorCode_CorruptedFile);
+          }
+          
+          ZlibCompressor compressor;
+          IBufferCompressor::Uncompress(uncompressed_->GetBuffer(), compressor, compressed);
+          return HttpCompression_None;
+        }
+
+        break;
+      }
+
+      default:
+        throw OrthancException(ErrorCode_NotImplemented);
+    }
   }
 
 
   bool FilesystemHttpSender::ReadNextChunk()
   {
-    file_.read(&chunk_[0], chunk_.size());
+    if (uncompressed_.get() != NULL)
+    {
+      return uncompressed_->ReadNextChunk();
+    }
+    else
+    {
+      if (chunk_.size() == 0)
+      {
+        chunk_.resize(CHUNK_SIZE);
+      }
+
+      file_.read(&chunk_[0], chunk_.size());
+
+      if (file_.flags() & std::istream::failbit)
+      {
+        throw OrthancException(ErrorCode_CorruptedFile);
+      }
+
+      chunkSize_ = file_.gcount();
+
+      return chunkSize_ > 0;
+    }
+  }
 
-    chunkSize_ = file_.gcount();
 
-    return chunkSize_ > 0;
+  const char* FilesystemHttpSender::GetChunkContent()
+  {
+    if (uncompressed_.get() != NULL)
+    {
+      return uncompressed_->GetChunkContent();
+    }
+    else
+    {
+      return chunk_.c_str();
+    }
+  }
+
+  
+  size_t FilesystemHttpSender::GetChunkSize()
+  {
+    if (uncompressed_.get() != NULL)
+    {
+      return uncompressed_->GetChunkSize();
+    }
+    else
+    {
+      return chunkSize_;
+    }
   }
 }
--- a/Core/HttpServer/FilesystemHttpSender.h	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/FilesystemHttpSender.h	Tue Aug 11 15:37:42 2015 +0200
@@ -32,6 +32,7 @@
 #pragma once
 
 #include "HttpFileSender.h"
+#include "BufferHttpSender.h"
 #include "../FileStorage/FilesystemStorage.h"
 
 #include <fstream>
@@ -41,27 +42,47 @@
   class FilesystemHttpSender : public HttpFileSender
   {
   private:
-    boost::filesystem::path path_;
-    std::ifstream           file_;
-    uint64_t                size_;
-    std::string             chunk_;
-    size_t                  chunkSize_;
+    std::ifstream    file_;
+    uint64_t         size_;
+    std::string      chunk_;
+    size_t           chunkSize_;
+    CompressionType  sourceCompression_;
+    HttpCompression  targetCompression_;
 
-    void Open();
+    std::auto_ptr<BufferHttpSender>  uncompressed_;
+
+    void Initialize(const boost::filesystem::path& path);
 
   public:
-    FilesystemHttpSender(const char* path);
+    FilesystemHttpSender(const std::string& path)
+    {
+      Initialize(path);
+    }
 
-    FilesystemHttpSender(const boost::filesystem::path& path);
+    FilesystemHttpSender(const boost::filesystem::path& path)
+    {
+      Initialize(path);
+    }
 
     FilesystemHttpSender(const FilesystemStorage& storage,
-                         const std::string& uuid);
+                         const std::string& uuid)
+    {
+      Initialize(storage.GetPath(uuid));
+    }
+
+    void SetSourceCompression(CompressionType compression)
+    {
+      sourceCompression_ = compression;
+    }
 
 
     /**
      * Implementation of the IHttpStreamAnswer interface.
      **/
 
+    virtual HttpCompression GetHttpCompression(bool /*gzipAllowed*/, 
+                                               bool /*deflateAllowed*/);
+
     virtual uint64_t GetContentLength()
     {
       return size_;
@@ -69,14 +90,8 @@
 
     virtual bool ReadNextChunk();
 
-    virtual const char* GetChunkContent()
-    {
-      return chunk_.c_str();
-    }
+    virtual const char* GetChunkContent();
 
-    virtual size_t GetChunkSize()
-    {
-      return chunkSize_;
-    }
+    virtual size_t GetChunkSize();
   };
 }
--- a/Core/HttpServer/HttpFileSender.cpp	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/HttpFileSender.cpp	Tue Aug 11 15:37:42 2015 +0200
@@ -40,7 +40,7 @@
 
 namespace Orthanc
 {
-  void HttpFileSender::SetFilename(const std::string& filename)
+  void HttpFileSender::SetContentFilename(const std::string& filename)
   {
     filename_ = filename;
 
@@ -53,9 +53,14 @@
 
   bool HttpFileSender::HasContentFilename(std::string& filename)
   {
-    if (!filename_.empty())
+    if (filename_.empty())
+    {
+      return false;
+    }
+    else
     {
       filename = filename_;
+      return true;
     }
   }
     
--- a/Core/HttpServer/HttpFileSender.h	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/HttpFileSender.h	Tue Aug 11 15:37:42 2015 +0200
@@ -53,25 +53,18 @@
       return contentType_;
     }
 
-    void SetFilename(const std::string& filename);
+    void SetContentFilename(const std::string& filename);
 
-    const std::string& GetFilename() const
+    const std::string& GetContentFilename() const
     {
       return filename_;
     }
 
 
     /**
-     * Implementation of the IHttpStreamAnswer interface. No
-     * compression is supported.
+     * Implementation of the IHttpStreamAnswer interface.
      **/
 
-    virtual HttpCompression GetHttpCompression(bool /*gzipAllowed*/, 
-                                               bool /*deflateAllowed*/)
-    {
-      return HttpCompression_None;
-    }
-
     virtual bool HasContentFilename(std::string& filename);
     
     virtual std::string GetContentType();
--- a/Core/HttpServer/HttpOutput.cpp	Tue Aug 11 13:37:24 2015 +0200
+++ b/Core/HttpServer/HttpOutput.cpp	Tue Aug 11 15:37:42 2015 +0200
@@ -220,8 +220,9 @@
     switch (state_)
     {
       case State_WritingHeader:
-        LOG(ERROR) << "Closing the HTTP body, but the header has not been sent yet";
-        throw OrthancException(ErrorCode_BadSequenceOfCalls);
+        SetContentLength(0);
+        SendBody(NULL, 0);
+        break;
 
       case State_WritingBody:
         if (!hasContentLength_ ||
@@ -390,8 +391,6 @@
 
   void HttpOutput::AnswerEmpty()
   {
-    stateMachine_.SetContentLength(0);
-    stateMachine_.SendBody(NULL, 0);
     stateMachine_.CloseBody();
   }
 
--- a/OrthancServer/OrthancRestApi/OrthancRestArchive.cpp	Tue Aug 11 13:37:24 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestArchive.cpp	Tue Aug 11 15:37:42 2015 +0200
@@ -296,9 +296,9 @@
     }
 
     // Prepare the sending of the ZIP file
-    FilesystemHttpSender sender(tmp.GetPath().c_str());
+    FilesystemHttpSender sender(tmp.GetPath());
     sender.SetContentType("application/zip");
-    sender.SetFilename(id + ".zip");
+    sender.SetContentFilename(id + ".zip");
 
     // Send the ZIP
     call.GetOutput().AnswerStream(sender);
@@ -357,9 +357,9 @@
     }
 
     // Prepare the sending of the ZIP file
-    FilesystemHttpSender sender(tmp.GetPath().c_str());
+    FilesystemHttpSender sender(tmp.GetPath());
     sender.SetContentType("application/zip");
-    sender.SetFilename(id + ".zip");
+    sender.SetContentFilename(id + ".zip");
 
     // Send the ZIP
     call.GetOutput().AnswerStream(sender);
--- a/OrthancServer/ServerContext.cpp	Tue Aug 11 13:37:24 2015 +0200
+++ b/OrthancServer/ServerContext.cpp	Tue Aug 11 15:37:42 2015 +0200
@@ -317,7 +317,7 @@
 
     std::auto_ptr<HttpFileSender> sender(accessor_.ConstructHttpFileSender(attachment.GetUuid(), attachment.GetContentType()));
     sender->SetContentType(GetMimeType(content));
-    sender->SetFilename(instancePublicId + ".dcm");
+    sender->SetContentFilename(instancePublicId + ".dcm");
     output.AnswerStream(*sender);
   }