# HG changeset patch # User Sebastien Jodogne # Date 1439300262 -7200 # Node ID f938f7779bcb7ac86439adca742b3efd5a55d78d # Parent 3606278d305e3af92546d24035446c8ff920ca57 fixes diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/BufferHttpSender.h --- 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(); diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/FilesystemHttpSender.cpp --- 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 @@ -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_; + } } } diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/FilesystemHttpSender.h --- 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 @@ -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 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(); }; } diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/HttpFileSender.cpp --- 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; } } diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/HttpFileSender.h --- 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(); diff -r 3606278d305e -r f938f7779bcb Core/HttpServer/HttpOutput.cpp --- 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(); } diff -r 3606278d305e -r f938f7779bcb OrthancServer/OrthancRestApi/OrthancRestArchive.cpp --- 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); diff -r 3606278d305e -r f938f7779bcb OrthancServer/ServerContext.cpp --- 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 sender(accessor_.ConstructHttpFileSender(attachment.GetUuid(), attachment.GetContentType())); sender->SetContentType(GetMimeType(content)); - sender->SetFilename(instancePublicId + ".dcm"); + sender->SetContentFilename(instancePublicId + ".dcm"); output.AnswerStream(*sender); }