예제 #1
0
  void HttpClient::Setup()
  {
    pimpl_->postHeaders_ = NULL;
    if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL)
    {
      throw OrthancException(ErrorCode_NotEnoughMemory);
    }

    pimpl_->curl_ = curl_easy_init();
    if (!pimpl_->curl_)
    {
      curl_slist_free_all(pimpl_->postHeaders_);
      throw OrthancException(ErrorCode_NotEnoughMemory);
    }

    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback));
    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0));
    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1));

#if ORTHANC_SSL_ENABLED == 1
    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 0)); 
#endif

    // This fixes the "longjmp causes uninitialized stack frame" crash
    // that happens on modern Linux versions.
    // http://stackoverflow.com/questions/9191668/error-longjmp-causes-uninitialized-stack-frame
    CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOSIGNAL, 1));

    url_ = "";
    method_ = HttpMethod_Get;
    lastStatus_ = HttpStatus_200_Ok;
    isVerbose_ = false;
    timeout_ = 0;
  }
예제 #2
0
    PngRabi()
    {
      png_ = NULL;
      info_ = NULL;
      endInfo_ = NULL;

      png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      if (!png_)
      {
        throw OrthancException(ErrorCode_NotEnoughMemory);
      }

      info_ = png_create_info_struct(png_);
      if (!info_)
      {
        png_destroy_read_struct(&png_, NULL, NULL);
        throw OrthancException(ErrorCode_NotEnoughMemory);
      }

      endInfo_ = png_create_info_struct(png_);
      if (!info_)
      {
        png_destroy_read_struct(&png_, &info_, NULL);
        throw OrthancException(ErrorCode_NotEnoughMemory);
      }
    }
예제 #3
0
  SharedLibrary::SharedLibrary(const std::string& path) : 
    path_(path), 
    handle_(NULL)
  {
#if defined(_WIN32)
    handle_ = ::LoadLibraryA(path_.c_str());
    if (handle_ == NULL)
    {
      LOG(ERROR) << "LoadLibrary(" << path_ << ") failed: Error " << ::GetLastError();
      throw OrthancException(ErrorCode_SharedLibrary);
    }

#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
    handle_ = ::dlopen(path_.c_str(), RTLD_NOW);
    if (handle_ == NULL) 
    {
      std::string explanation;
      const char *tmp = ::dlerror();
      if (tmp)
      {
        explanation = ": Error " + std::string(tmp);
      }

      LOG(ERROR) << "dlopen(" << path_ << ") failed" << explanation;
      throw OrthancException(ErrorCode_SharedLibrary);
    }

#else
#error Support your platform here
#endif   
  }
예제 #4
0
  void HttpOutput::StateMachine::CloseBody()
  {
    switch (state_)
    {
      case State_WritingHeader:
        SetContentLength(0);
        SendBody(NULL, 0);
        break;

      case State_WritingBody:
        if (!hasContentLength_ ||
            contentPosition_ == contentLength_)
        {
          state_ = State_Done;
        }
        else
        {
          LOG(ERROR) << "The body size has not reached what was declared with SetContentSize()";
          throw OrthancException(ErrorCode_BadSequenceOfCalls);
        }

        break;

      case State_WritingMultipart:
        LOG(ERROR) << "Cannot invoke CloseBody() with multipart outputs";
        throw OrthancException(ErrorCode_BadSequenceOfCalls);

      case State_Done:
        return;  // Ignore

      default:
        throw OrthancException(ErrorCode_InternalError);
    }      
  }
예제 #5
0
 StatementReference::~StatementReference()
 {
   if (IsRoot())
   {
     if (refCount_ != 0)
     {
       // There remain references to this object
       throw OrthancException(ErrorCode_InternalError);
     }
     else if (statement_ != NULL)
     {
       sqlite3_finalize(statement_);
     }
   }
   else
   {
     if (root_->refCount_ == 0)
     {
       throw OrthancException(ErrorCode_InternalError);
     }
     else
     {
       root_->refCount_--;
     }
   }
 }
예제 #6
0
  void PngReader::ReadFromMemory(const void* buffer,
                                 size_t size)
  {
    if (size < 8)
    {
      throw OrthancException(ErrorCode_BadFileFormat);
    }

    CheckHeader(buffer);

    PngRabi rabi;

    if (setjmp(png_jmpbuf(rabi.png_)))
    {
      rabi.Destruct();
      throw OrthancException(ErrorCode_BadFileFormat);
    }

    MemoryBuffer tmp;
    tmp.buffer_ = reinterpret_cast<const uint8_t*>(buffer) + 8;  // We skip the header
    tmp.size_ = size - 8;
    tmp.pos_ = 0;
    tmp.ok_ = true;

    png_set_read_fn(rabi.png_, &tmp, PngRabi::MemoryCallback);

    Read(rabi);

    if (!tmp.ok_)
    {
      throw OrthancException(ErrorCode_BadFileFormat);
    }
  }
예제 #7
0
  void PngWriter::WriteToFile(const char* filename,
                              unsigned int width,
                              unsigned int height,
                              unsigned int pitch,
                              PixelFormat format,
                              const void* buffer)
  {
    Prepare(width, height, pitch, format, buffer);

    FILE* fp = fopen(filename, "wb");
    if (!fp)
    {
      throw OrthancException(ErrorCode_CannotWriteFile);
    }    

    png_init_io(pimpl_->png_, fp);

    if (setjmp(png_jmpbuf(pimpl_->png_)))
    {
      // Error during writing PNG
      throw OrthancException(ErrorCode_CannotWriteFile);      
    }

    Compress(width, height, pitch, format);

    fclose(fp);
  }
예제 #8
0
  void DicomServer::SetApplicationEntityTitle(const std::string& aet)
  {
    if (aet.size() == 0)
    {
      throw OrthancException(ErrorCode_BadApplicationEntityTitle);
    }

    if (aet.size() > 16)
    {
      throw OrthancException(ErrorCode_BadApplicationEntityTitle);
    }

    for (size_t i = 0; i < aet.size(); i++)
    {
      if (!(aet[i] == '-' ||
            aet[i] == '_' ||
            isdigit(aet[i]) ||
            (aet[i] >= 'A' && aet[i] <= 'Z')))
      {
        LOG(WARNING) << "For best interoperability, only upper case, alphanumeric characters should be present in AET: \"" << aet << "\"";
        break;
      }
    }

    Stop();
    aet_ = aet;
  }
예제 #9
0
  void PngWriter::WriteToFileInternal(const std::string& filename,
                                      unsigned int width,
                                      unsigned int height,
                                      unsigned int pitch,
                                      PixelFormat format,
                                      const void* buffer)
  {
    Prepare(width, height, pitch, format, buffer);

    FILE* fp = Toolbox::OpenFile(filename, FileMode_WriteBinary);
    if (!fp)
    {
      throw OrthancException(ErrorCode_CannotWriteFile);
    }    

    png_init_io(pimpl_->png_, fp);

    if (setjmp(png_jmpbuf(pimpl_->png_)))
    {
      // Error during writing PNG
      throw OrthancException(ErrorCode_CannotWriteFile);      
    }

    Compress(width, height, pitch, format);

    fclose(fp);
  }
예제 #10
0
  void ZipWriter::Open()
  {
    if (IsOpen())
    {
      return;
    }

    if (path_.size() == 0)
    {
      throw OrthancException("Please call SetOutputPath() before creating the file");
    }

    hasFileInZip_ = false;

    if (isZip64_)
    {
      pimpl_->file_ = zipOpen64(path_.c_str(), APPEND_STATUS_CREATE);
    }
    else
    {
      pimpl_->file_ = zipOpen(path_.c_str(), APPEND_STATUS_CREATE);
    }

    if (!pimpl_->file_)
    {
      throw OrthancException(ErrorCode_CannotWriteFile);
    }
  }
  static void ParseListOfTags(DicomModification& target,
                              const Json::Value& query,
                              TagOperation operation)
  {
    if (!query.isArray())
    {
      throw OrthancException(ErrorCode_BadRequest);
    }

    for (Json::Value::ArrayIndex i = 0; i < query.size(); i++)
    {
      std::string name = query[i].asString();

      DicomTag tag = FromDcmtkBridge::ParseTag(name);

      switch (operation)
      {
        case TagOperation_Keep:
          target.Keep(tag);
          VLOG(1) << "Keep: " << name << " " << tag << std::endl;
          break;

        case TagOperation_Remove:
          target.Remove(tag);
          VLOG(1) << "Remove: " << name << " " << tag << std::endl;
          break;

        default:
          throw OrthancException(ErrorCode_InternalError);
      }
    }
  }
예제 #12
0
  void ZlibCompressor::Compress(std::string& compressed,
                                const void* uncompressed,
                                size_t uncompressedSize)
  {
    if (uncompressedSize == 0)
    {
      compressed.clear();
      return;
    }

    uLongf compressedSize = compressBound(uncompressedSize) + 1024 /* security margin */;
    if (compressedSize == 0)
    {
      compressedSize = 1;
    }

    uint8_t* target;
    if (HasPrefixWithUncompressedSize())
    {
      compressed.resize(compressedSize + sizeof(uint64_t));
      target = reinterpret_cast<uint8_t*>(&compressed[0]) + sizeof(uint64_t);
    }
    else
    {
      compressed.resize(compressedSize);
      target = reinterpret_cast<uint8_t*>(&compressed[0]);
    }

    int error = compress2(target,
                          &compressedSize,
                          const_cast<Bytef *>(static_cast<const Bytef *>(uncompressed)), 
                          uncompressedSize,
                          GetCompressionLevel());

    if (error != Z_OK)
    {
      compressed.clear();

      switch (error)
      {
      case Z_MEM_ERROR:
        throw OrthancException(ErrorCode_NotEnoughMemory);

      default:
        throw OrthancException(ErrorCode_InternalError);
      }  
    }

    // The compression was successful
    if (HasPrefixWithUncompressedSize())
    {
      uint64_t s = static_cast<uint64_t>(uncompressedSize);
      memcpy(&compressed[0], &s, sizeof(uint64_t));
      compressed.resize(compressedSize + sizeof(uint64_t));
    }
    else
    {
      compressed.resize(compressedSize);
    }
  }
예제 #13
0
  void DicomInstanceToStore::ComputeMissingInformation()
  {
    if (buffer_.HasContent() &&
        summary_.HasContent() &&
        json_.HasContent())
    {
      // Fine, everything is available
      return; 
    }
    
    if (!buffer_.HasContent())
    {
      if (!parsed_.HasContent())
      {
        throw OrthancException(ErrorCode_NotImplemented);
      }
      else
      {
        // Serialize the parsed DICOM file
        buffer_.Allocate();
        if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer_.GetContent(), GetDataset(parsed_.GetContent())))
        {
          LOG(ERROR) << "Unable to serialize a DICOM file to a memory buffer";
          throw OrthancException(ErrorCode_InternalError);
        }
      }
    }

    if (summary_.HasContent() &&
        json_.HasContent())
    {
      return;
    }

    // At this point, we know that the DICOM file is available as a
    // memory buffer, but that its summary or its JSON version is
    // missing

    if (!parsed_.HasContent())
    {
      parsed_.TakeOwnership(new ParsedDicomFile(buffer_.GetConstContent()));
    }

    // At this point, we have parsed the DICOM file
    
    if (!summary_.HasContent())
    {
      summary_.Allocate();
      FromDcmtkBridge::Convert(summary_.GetContent(), GetDataset(parsed_.GetContent()));
    }
    
    if (!json_.HasContent())
    {
      json_.Allocate();
      FromDcmtkBridge::ToJson(json_.GetContent(), GetDataset(parsed_.GetContent()));
    }
  }
예제 #14
0
    static ENGINE* LoadEngine()
    {
      // This function creates an engine for PKCS#11 and inspired by
      // the "ENGINE_load_dynamic" function from OpenSSL, in file
      // "crypto/engine/eng_dyn.c"

      ENGINE* engine = ENGINE_new();
      if (!engine)
      {
        LOG(ERROR) << "Cannot create an OpenSSL engine for PKCS#11";
        throw OrthancException(ErrorCode_InternalError);
      }

      // Create a PKCS#11 context using libp11
      context_ = pkcs11_new();
      if (!context_)
      {
        LOG(ERROR) << "Cannot create a libp11 context for PKCS#11";
        ENGINE_free(engine);
        throw OrthancException(ErrorCode_InternalError);
      }

      if (!ENGINE_set_id(engine, PKCS11_ENGINE_ID) ||
          !ENGINE_set_name(engine, PKCS11_ENGINE_NAME) ||
          !ENGINE_set_cmd_defns(engine, PKCS11_ENGINE_COMMANDS) ||

          // Register the callback functions
          !ENGINE_set_init_function(engine, EngineInitialize) ||
          !ENGINE_set_finish_function(engine, EngineFinalize) ||
          !ENGINE_set_destroy_function(engine, EngineDestroy) ||
          !ENGINE_set_ctrl_function(engine, EngineControl) ||
          !ENGINE_set_load_pubkey_function(engine, EngineLoadPublicKey) ||
          !ENGINE_set_load_privkey_function(engine, EngineLoadPrivateKey) ||

          !ENGINE_set_RSA(engine, PKCS11_get_rsa_method()) ||
          !ENGINE_set_ECDSA(engine, PKCS11_get_ecdsa_method()) ||
          !ENGINE_set_ECDH(engine, PKCS11_get_ecdh_method()) ||

#if OPENSSL_VERSION_NUMBER  >= 0x10100002L
          !ENGINE_set_EC(engine, PKCS11_get_ec_key_method()) ||
#endif

          // Make OpenSSL know about our PKCS#11 engine
          !ENGINE_add(engine))
      {
        LOG(ERROR) << "Cannot initialize the OpenSSL engine for PKCS#11";
        pkcs11_finish(context_);
        ENGINE_free(engine);
        throw OrthancException(ErrorCode_InternalError);
      }

      // If the "ENGINE_add" worked, it gets a structural
      // reference. We release our just-created reference.
      ENGINE_free(engine);

      return ENGINE_by_id(PKCS11_ENGINE_ID);
    }
예제 #15
0
파일: Toolbox.cpp 프로젝트: gbanana/orthanc
  void Toolbox::SplitUriComponents(UriComponents& components,
                                   const std::string& uri)
  {
    static const char URI_SEPARATOR = '/';

    components.clear();

    if (uri.size() == 0 ||
        uri[0] != URI_SEPARATOR)
    {
      throw OrthancException(ErrorCode_UriSyntax);
    }

    // Count the number of slashes in the URI to make an assumption
    // about the number of components in the URI
    unsigned int estimatedSize = 0;
    for (unsigned int i = 0; i < uri.size(); i++)
    {
      if (uri[i] == URI_SEPARATOR)
        estimatedSize++;
    }

    components.reserve(estimatedSize - 1);

    unsigned int start = 1;
    unsigned int end = 1;
    while (end < uri.size())
    {
      // This is the loop invariant
      assert(uri[start - 1] == '/' && (end >= start));

      if (uri[end] == '/')
      {
        components.push_back(std::string(&uri[start], end - start));
        end++;
        start = end;
      }
      else
      {
        end++;
      }
    }

    if (start < uri.size())
    {
      components.push_back(std::string(&uri[start], end - start));
    }

    for (size_t i = 0; i < components.size(); i++)
    {
      if (components[i].size() == 0)
      {
        // Empty component, as in: "/coucou//e"
        throw OrthancException(ErrorCode_UriSyntax);
      }
    }
  }
예제 #16
0
파일: Toolbox.cpp 프로젝트: gbanana/orthanc
  void Toolbox::ExecuteSystemCommand(const std::string& command,
                                     const std::vector<std::string>& arguments)
  {
    // Convert the arguments as a C array
    std::vector<char*>  args(arguments.size() + 2);

    args.front() = const_cast<char*>(command.c_str());

    for (size_t i = 0; i < arguments.size(); i++)
    {
      args[i + 1] = const_cast<char*>(arguments[i].c_str());
    }

    args.back() = NULL;

    int status;

#if defined(_WIN32)
    // http://msdn.microsoft.com/en-us/library/275khfab.aspx
    status = static_cast<int>(_spawnvp(_P_OVERLAY, command.c_str(), &args[0]));

#else
    int pid = fork();

    if (pid == -1)
    {
      // Error in fork()
#if HAVE_GOOGLE_LOG == 1
      LOG(ERROR) << "Cannot fork a child process";
#endif

      throw OrthancException(ErrorCode_SystemCommand);
    }
    else if (pid == 0)
    {
      // Execute the system command in the child process
      execvp(command.c_str(), &args[0]);

      // We should never get here
      _exit(1);
    }
    else
    {
      // Wait for the system command to exit
      waitpid(pid, &status, 0);
    }
#endif

    if (status != 0)
    {
#if HAVE_GOOGLE_LOG == 1
      LOG(ERROR) << "System command failed with status code " << status;
#endif

      throw OrthancException(ErrorCode_SystemCommand);
    }
  }
예제 #17
0
  std::string FileStorage::CreateFileWithoutCompression(const void* content, size_t size)
  {
    std::string uuid;
    boost::filesystem::path path;
    
    for (;;)
    {
      uuid = Toolbox::GenerateUuid();
      path = GetPath(uuid);

      if (!boost::filesystem::exists(path))
      {
        // OK, this is indeed a new file
        break;
      }

      // Extremely improbable case: This Uuid has already been created
      // in the past. Try again.
    }

    if (boost::filesystem::exists(path.parent_path()))
    {
      if (!boost::filesystem::is_directory(path.parent_path()))
      {
        throw OrthancException("The subdirectory to be created is already occupied by a regular file");        
      }
    }
    else
    {
      if (!boost::filesystem::create_directories(path.parent_path()))
      {
        throw OrthancException("Unable to create a subdirectory in the file storage");        
      }
    }

    boost::filesystem::ofstream f;
    f.open(path, std::ofstream::out | std::ios::binary);
    if (!f.good())
    {
      throw OrthancException("Unable to create a new file in the file storage");
    }

    if (size != 0)
    {
      f.write(static_cast<const char*>(content), size);
      if (!f.good())
      {
        f.close();
        throw OrthancException("Unable to write to the new file in the file storage");
      }
    }

    f.close();

    return uuid;
  } 
예제 #18
0
  void ZlibCompressor::Uncompress(std::string& uncompressed,
                                  const void* compressed,
                                  size_t compressedSize)
  {
    if (compressedSize == 0)
    {
      uncompressed.clear();
      return;
    }

    if (!HasPrefixWithUncompressedSize())
    {
      LOG(ERROR) << "Cannot guess the uncompressed size of a zlib-encoded buffer";
      throw OrthancException(ErrorCode_InternalError);
    }

    uint64_t uncompressedSize = ReadUncompressedSizePrefix(compressed, compressedSize);
    
    try
    {
      uncompressed.resize(static_cast<size_t>(uncompressedSize));
    }
    catch (...)
    {
      throw OrthancException(ErrorCode_NotEnoughMemory);
    }

    uLongf tmp = static_cast<uLongf>(uncompressedSize);
    int error = uncompress
      (reinterpret_cast<uint8_t*>(&uncompressed[0]), 
       &tmp,
       reinterpret_cast<const uint8_t*>(compressed) + sizeof(uint64_t),
       compressedSize - sizeof(uint64_t));

    if (error != Z_OK)
    {
      uncompressed.clear();

      switch (error)
      {
      case Z_DATA_ERROR:
        throw OrthancException(ErrorCode_CorruptedFile);

      case Z_MEM_ERROR:
        throw OrthancException(ErrorCode_NotEnoughMemory);

      default:
        throw OrthancException(ErrorCode_InternalError);
      }  
    }
  }
예제 #19
0
  void ZlibCompressor::Uncompress(std::string& uncompressed,
                                  const void* compressed,
                                  size_t compressedSize)
  {
    if (compressedSize == 0)
    {
      uncompressed.clear();
      return;
    }

    if (compressedSize < sizeof(size_t))
    {
      throw OrthancException("Zlib: The compressed buffer is ill-formed");
    }

    size_t uncompressedLength;
    memcpy(&uncompressedLength, compressed, sizeof(size_t));
    
    try
    {
      uncompressed.resize(uncompressedLength);
    }
    catch (...)
    {
      throw OrthancException("Zlib: Corrupted compressed buffer");
    }

    uLongf tmp = uncompressedLength;
    int error = uncompress
      (reinterpret_cast<uint8_t*>(&uncompressed[0]), 
       &tmp,
       reinterpret_cast<const uint8_t*>(compressed) + sizeof(size_t),
       compressedSize - sizeof(size_t));

    if (error != Z_OK)
    {
      uncompressed.clear();

      switch (error)
      {
      case Z_DATA_ERROR:
        throw OrthancException("Zlib: Corrupted or incomplete compressed buffer");

      case Z_MEM_ERROR:
        throw OrthancException(ErrorCode_NotEnoughMemory);

      default:
        throw OrthancException(ErrorCode_InternalError);
      }  
    }
  }
예제 #20
0
void FilesystemStorage::Create(const std::string& uuid,
                               const void* content,
                               size_t size,
                               FileContentType /*type*/)
{
    boost::filesystem::path path;

    path = GetPath(uuid);

    if (boost::filesystem::exists(path))
    {
        // Extremely unlikely case: This Uuid has already been created
        // in the past.
        throw OrthancException(ErrorCode_InternalError);
    }

    if (boost::filesystem::exists(path.parent_path()))
    {
        if (!boost::filesystem::is_directory(path.parent_path()))
        {
            throw OrthancException("The subdirectory to be created is already occupied by a regular file");
        }
    }
    else
    {
        if (!boost::filesystem::create_directories(path.parent_path()))
        {
            throw OrthancException("Unable to create a subdirectory in the file storage");
        }
    }

    boost::filesystem::ofstream f;
    f.open(path, std::ofstream::out | std::ios::binary);
    if (!f.good())
    {
        throw OrthancException("Unable to create a new file in the file storage");
    }

    if (size != 0)
    {
        f.write(static_cast<const char*>(content), size);
        if (!f.good())
        {
            f.close();
            throw OrthancException("Unable to write to the new file in the file storage");
        }
    }

    f.close();
}
예제 #21
0
  void HttpOutput::StateMachine::StartMultipart(const std::string& subType,
                                                const std::string& contentType)
  {
    if (subType != "mixed" &&
        subType != "related")
    {
      throw OrthancException(ErrorCode_ParameterOutOfRange);
    }

    if (keepAlive_)
    {
      LOG(ERROR) << "Multipart answers are not implemented together with keep-alive connections";
      throw OrthancException(ErrorCode_NotImplemented);
    }

    if (state_ != State_WritingHeader)
    {
      throw OrthancException(ErrorCode_BadSequenceOfCalls);
    }

    if (status_ != HttpStatus_200_Ok)
    {
      SendBody(NULL, 0);
      return;
    }

    stream_.OnHttpStatusReceived(status_);

    std::string header = "HTTP/1.1 200 OK\r\n";

    // Possibly add the cookies
    for (std::list<std::string>::const_iterator
           it = headers_.begin(); it != headers_.end(); ++it)
    {
      if (!Toolbox::StartsWith(*it, "Set-Cookie: "))
      {
        LOG(ERROR) << "The only headers that can be set in multipart answers are Set-Cookie (here: " << *it << " is set)";
        throw OrthancException(ErrorCode_BadSequenceOfCalls);
      }

      header += *it;
    }

    multipartBoundary_ = Toolbox::GenerateUuid();
    multipartContentType_ = contentType;
    header += "Content-Type: multipart/" + subType + "; type=" + contentType + "; boundary=" + multipartBoundary_ + "\r\n\r\n";

    stream_.Send(true, header.c_str(), header.size());
    state_ = State_WritingMultipart;
  }
예제 #22
0
  void FilesystemStorage::Create(const std::string& uuid,
                                 const void* content, 
                                 size_t size,
                                 FileContentType /*type*/)
  {
    boost::filesystem::path path;
    
    path = GetPath(uuid);

    if (boost::filesystem::exists(path))
    {
      // Extremely unlikely case: This Uuid has already been created
      // in the past.
      throw OrthancException(ErrorCode_InternalError);
    }

    if (boost::filesystem::exists(path.parent_path()))
    {
      if (!boost::filesystem::is_directory(path.parent_path()))
      {
        throw OrthancException(ErrorCode_DirectoryOverFile);
      }
    }
    else
    {
      if (!boost::filesystem::create_directories(path.parent_path()))
      {
        throw OrthancException(ErrorCode_FileStorageCannotWrite);
      }
    }

    boost::filesystem::ofstream f;
    f.open(path, std::ofstream::out | std::ios::binary);
    if (!f.good())
    {
      throw OrthancException(ErrorCode_FileStorageCannotWrite);
    }

    if (size != 0)
    {
      f.write(static_cast<const char*>(content), size);
      if (!f.good())
      {
        f.close();
        throw OrthancException(ErrorCode_FileStorageCannotWrite);
      }
    }

    f.close();
  }
예제 #23
0
파일: Mutex.cpp 프로젝트: freemed/orthanc
 void Mutex::Unlock()
 {
   if (pthread_mutex_unlock(&pimpl_->mutex_) != 0)
   {
     throw OrthancException(ErrorCode_InternalError);    
   }
 }
예제 #24
0
  void RestApiOutput::AnswerJson(const Json::Value& value)
  {
    CheckStatus();

    if (convertJsonToXml_)
    {
#if ORTHANC_PUGIXML_ENABLED == 1
      std::string s;
      Toolbox::JsonToXml(s, value);
      output_.SetContentType("application/xml");
      output_.Answer(s);
#else
      LOG(ERROR) << "Orthanc was compiled without XML support";
      throw OrthancException(ErrorCode_InternalError);
#endif
    }
    else
    {
      Json::StyledWriter writer;
      output_.SetContentType("application/json");
      output_.Answer(writer.write(value));
    }

    alreadySent_ = true;
  }
예제 #25
0
    void FillInstance(DcmDirectoryRecord& record,
                      DcmItem& dicom,
                      DcmMetaInfo& metaInfo,
                      const char* path)
    {
      // cf. "DicomDirInterface::buildImageRecord()"

      /* copy attribute values from dataset to image record */
      copyElementType1(dicom, DCM_InstanceNumber, record);
      //copyElementType1C(dicom, DCM_ImageType, record);
      copyElementType1C(dicom, DCM_ReferencedImageSequence, record);

      OFString tmp;

      DcmElement* item = record.remove(DCM_ReferencedImageSequence);
      if (item != NULL)
      {
        delete item;
      }

      if (record.putAndInsertString(DCM_ReferencedFileID, path).bad() ||
          dicom.findAndGetOFStringArray(DCM_SOPClassUID, tmp).bad() ||
          record.putAndInsertString(DCM_ReferencedSOPClassUIDInFile, tmp.c_str()).bad() ||
          dicom.findAndGetOFStringArray(DCM_SOPInstanceUID, tmp).bad() ||
          record.putAndInsertString(DCM_ReferencedSOPInstanceUIDInFile, tmp.c_str()).bad() ||
          metaInfo.findAndGetOFStringArray(DCM_TransferSyntaxUID, tmp).bad() ||
          record.putAndInsertString(DCM_ReferencedTransferSyntaxUIDInFile, tmp.c_str()).bad())
      {
        throw OrthancException(ErrorCode_BadFileFormat);
      }
    }
  float HttpContentNegociation::GetQuality(const Tokens& parameters)
  {
    for (size_t i = 1; i < parameters.size(); i++)
    {
      std::string key, value;
      if (SplitPair(key, value, parameters[i], '=') &&
          key == "q")
      {
        float quality;
        bool ok = false;

        try
        {
          quality = boost::lexical_cast<float>(value);
          ok = (quality >= 0.0f && quality <= 1.0f);
        }
        catch (boost::bad_lexical_cast&)
        {
        }

        if (ok)
        {
          return quality;
        }
        else
        {
          LOG(ERROR) << "Quality parameter out of range in a HTTP request (must be between 0 and 1): " << value;
          throw OrthancException(ErrorCode_BadRequest);
        }
      }
    }

    return 1.0f;  // Default quality
  }
예제 #27
0
  void HttpOutput::Answer(const void* buffer, 
                          size_t length)
  {
    if (length == 0)
    {
      AnswerEmpty();
      return;
    }

    HttpCompression compression = GetPreferredCompression(length);

    if (compression == HttpCompression_None)
    {
      stateMachine_.SetContentLength(length);
      stateMachine_.SendBody(buffer, length);
      return;
    }

    std::string compressed, encoding;

    switch (compression)
    {
      case HttpCompression_Deflate:
      {
        encoding = "deflate";
        ZlibCompressor compressor;
        // Do not prefix the buffer with its uncompressed size, to be compatible with "deflate"
        compressor.SetPrefixWithUncompressedSize(false);  
        compressor.Compress(compressed, buffer, length);
        break;
      }

      case HttpCompression_Gzip:
      {
        encoding = "gzip";
        GzipCompressor compressor;
        compressor.Compress(compressed, buffer, length);
        break;
      }

      default:
        throw OrthancException(ErrorCode_InternalError);
    }

    LOG(TRACE) << "Compressing a HTTP answer using " << encoding;

    // The body is empty, do not use HTTP compression
    if (compressed.size() == 0)
    {
      AnswerEmpty();
    }
    else
    {
      stateMachine_.AddHeader("Content-Encoding", encoding);
      stateMachine_.SetContentLength(compressed.size());
      stateMachine_.SendBody(compressed.c_str(), compressed.size());
    }

    stateMachine_.CloseBody();
  }
예제 #28
0
  void ServerJob::CheckOrdering()
  {
    std::map<ServerCommandInstance*, unsigned int> index;

    unsigned int count = 0;
    for (std::list<ServerCommandInstance*>::const_iterator
           it = filters_.begin(); it != filters_.end(); ++it)
    {
      index[*it] = count++;
    }

    for (std::list<ServerCommandInstance*>::const_iterator
           it = filters_.begin(); it != filters_.end(); ++it)
    {
      const std::list<ServerCommandInstance*>& nextCommands = (*it)->GetNextCommands();

      for (std::list<ServerCommandInstance*>::const_iterator
             next = nextCommands.begin(); next != nextCommands.end(); ++next)
      {
        if (index.find(*next) == index.end() ||
            index[*next] <= index[*it])
        {
          // You must reorder your calls to "ServerJob::AddCommand"
          throw OrthancException(ErrorCode_BadJobOrdering);
        }
      }
    }
  }
예제 #29
0
    void LoadIdentifiers(const DicomTag*& tags,
                         size_t& size,
                         ResourceType level)
    {
      switch (level)
      {
        case ResourceType_Patient:
          tags = patientIdentifiers;
          size = sizeof(patientIdentifiers) / sizeof(DicomTag);
          break;

        case ResourceType_Study:
          tags = studyIdentifiers;
          size = sizeof(studyIdentifiers) / sizeof(DicomTag);
          break;

        case ResourceType_Series:
          tags = seriesIdentifiers;
          size = sizeof(seriesIdentifiers) / sizeof(DicomTag);
          break;

        case ResourceType_Instance:
          tags = instanceIdentifiers;
          size = sizeof(instanceIdentifiers) / sizeof(DicomTag);
          break;

        default:
          throw OrthancException(ErrorCode_ParameterOutOfRange);
      }
    }
예제 #30
0
  void ExportedResource::Format(Json::Value& item) const
  {
    item = Json::objectValue;
    item["Seq"] = static_cast<int>(seq_);
    item["ResourceType"] = EnumerationToString(resourceType_);
    item["ID"] = publicId_;
    item["Path"] = GetBasePath(resourceType_, publicId_);
    item["RemoteModality"] = modality_;
    item["Date"] = date_;

    // WARNING: Do not add "break" below and do not reorder the case items!
    switch (resourceType_)
    {
      case ResourceType_Instance:
        item["SOPInstanceUID"] = sopInstanceUid_;

      case ResourceType_Series:
        item["SeriesInstanceUID"] = seriesInstanceUid_;

      case ResourceType_Study:
        item["StudyInstanceUID"] = studyInstanceUid_;

      case ResourceType_Patient:
        item["PatientID"] = patientId_;
        break;

      default:
        throw OrthancException(ErrorCode_InternalError);
    }
  }