# HG changeset patch # User Sebastien Jodogne # Date 1440600586 -7200 # Node ID b5bc87a7212d9d6dd6becfe37081abdcdc6748bc # Parent d7e569640d09b275f0384f3aa816f03866de0fa5 OrthancPluginReadFile, OrthancPluginWriteFile diff -r d7e569640d09 -r b5bc87a7212d Core/Toolbox.cpp --- a/Core/Toolbox.cpp Wed Aug 26 12:12:25 2015 +0200 +++ b/Core/Toolbox.cpp Wed Aug 26 16:49:46 2015 +0200 @@ -230,7 +230,8 @@ } - void Toolbox::WriteFile(const std::string& content, + void Toolbox::WriteFile(const void* content, + size_t size, const std::string& path) { boost::filesystem::ofstream f; @@ -240,15 +241,22 @@ throw OrthancException(ErrorCode_CannotWriteFile); } - if (content.size() != 0) + if (size != 0) { - f.write(content.c_str(), content.size()); + f.write(reinterpret_cast(content), size); } f.close(); } + void Toolbox::WriteFile(const std::string& content, + const std::string& path) + { + WriteFile(content.size() > 0 ? content.c_str() : NULL, + content.size(), path); + } + void Toolbox::RemoveFile(const std::string& path) { diff -r d7e569640d09 -r b5bc87a7212d Core/Toolbox.h --- a/Core/Toolbox.h Wed Aug 26 12:12:25 2015 +0200 +++ b/Core/Toolbox.h Wed Aug 26 16:49:46 2015 +0200 @@ -69,6 +69,10 @@ void WriteFile(const std::string& content, const std::string& path); + void WriteFile(const void* content, + size_t size, + const std::string& path); + void USleep(uint64_t microSeconds); void RemoveFile(const std::string& path); diff -r d7e569640d09 -r b5bc87a7212d NEWS --- a/NEWS Wed Aug 26 12:12:25 2015 +0200 +++ b/NEWS Wed Aug 26 16:49:46 2015 +0200 @@ -19,7 +19,9 @@ Plugins ------- -* New function OrthancPluginBufferCompression() to (un)compress memory buffers +* New function "OrthancPluginBufferCompression()" to (un)compress memory buffers +* New function "OrthancPluginReadFile()" to read files from the filesystem +* New function "OrthancPluginWriteFile()" to write files to the filesystem * Plugins have access to explicit error codes Maintenance diff -r d7e569640d09 -r b5bc87a7212d Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Wed Aug 26 12:12:25 2015 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Wed Aug 26 16:49:46 2015 +0200 @@ -935,6 +935,8 @@ bool OrthancPlugins::InvokeService(_OrthancPluginService service, const void* parameters) { + VLOG(1) << "Calling plugin service: " << service; + boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); switch (service) @@ -1198,6 +1200,26 @@ return true; } + case _OrthancPluginService_ReadFile: + { + const _OrthancPluginReadFile& p = + *reinterpret_cast(parameters); + + std::string content; + Toolbox::ReadFile(content, p.path); + CopyToMemoryBuffer(*p.target, content.size() > 0 ? content.c_str() : NULL, content.size()); + + return true; + } + + case _OrthancPluginService_WriteFile: + { + const _OrthancPluginWriteFile& p = + *reinterpret_cast(parameters); + Toolbox::WriteFile(p.data, p.size, p.path); + return true; + } + default: // This service is unknown by the Orthanc plugin engine return false; diff -r d7e569640d09 -r b5bc87a7212d Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Wed Aug 26 12:12:25 2015 +0200 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Wed Aug 26 16:49:46 2015 +0200 @@ -352,6 +352,8 @@ _OrthancPluginService_GetExpectedDatabaseVersion = 12, _OrthancPluginService_GetConfiguration = 13, _OrthancPluginService_BufferCompression = 14, + _OrthancPluginService_ReadFile = 15, + _OrthancPluginService_WriteFile = 16, /* Registration of callbacks */ _OrthancPluginService_RegisterRestCallback = 1000, @@ -2387,6 +2389,69 @@ } + + typedef struct + { + OrthancPluginMemoryBuffer* target; + const char* path; + } _OrthancPluginReadFile; + + /** + * @brief Read a file. + * + * Read the content of a file on the filesystem, and returns it into + * a newly allocated memory buffer. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). + * @param target The target memory buffer. + * @param path The path of the file to be read. + * @return 0 if success, or the error code if failure. + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginReadFile( + OrthancPluginContext* context, + OrthancPluginMemoryBuffer* target, + const char* path) + { + _OrthancPluginReadFile params; + params.target = target; + params.path = path; + return context->InvokeService(context, _OrthancPluginService_ReadFile, ¶ms); + } + + + + typedef struct + { + const char* path; + const void* data; + uint32_t size; + } _OrthancPluginWriteFile; + + /** + * @brief Write a file. + * + * Write the content of a memory buffer to the filesystem. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). + * @param path The path of the file to be written. + * @param data The content of the memory buffer. + * @param size The size of the memory buffer. + * @return 0 if success, or the error code if failure. + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginWriteFile( + OrthancPluginContext* context, + const char* path, + const void* data, + uint32_t size) + { + _OrthancPluginWriteFile params; + params.path = path; + params.data = data; + params.size = size; + return context->InvokeService(context, _OrthancPluginService_WriteFile, ¶ms); + } + + #ifdef __cplusplus } #endif diff -r d7e569640d09 -r b5bc87a7212d Plugins/Samples/ServeFolders/Plugin.cpp --- a/Plugins/Samples/ServeFolders/Plugin.cpp Wed Aug 26 12:12:25 2015 +0200 +++ b/Plugins/Samples/ServeFolders/Plugin.cpp Wed Aug 26 16:49:46 2015 +0200 @@ -89,52 +89,20 @@ } - -static bool ReadFile(std::string& content, +static bool ReadFile(std::string& target, const std::string& path) { - struct stat s; - if (stat(path.c_str(), &s) != 0 || - !(s.st_mode & S_IFREG)) - { - // Either the path does not exist, or it is not a regular file - return false; - } - - FILE* fp = fopen(path.c_str(), "rb"); - if (fp == NULL) + OrthancPluginMemoryBuffer buffer; + if (OrthancPluginReadFile(context_, &buffer, path.c_str())) { return false; } - - long size; - - if (fseek(fp, 0, SEEK_END) == -1 || - (size = ftell(fp)) < 0) - { - fclose(fp); - return false; - } - - content.resize(size); - - if (fseek(fp, 0, SEEK_SET) == -1) + else { - fclose(fp); - return false; + target.assign(reinterpret_cast(buffer.data), buffer.size); + OrthancPluginFreeMemoryBuffer(context_, &buffer); + return true; } - - bool ok = true; - - if (size > 0 && - fread(&content[0], size, 1, fp) != 1) - { - ok = false; - } - - fclose(fp); - - return ok; } @@ -210,9 +178,9 @@ } -static int32_t IndexCallback(OrthancPluginRestOutput* output, - const char* url, - const OrthancPluginHttpRequest* request) +static int32_t ListServedFolders(OrthancPluginRestOutput* output, + const char* url, + const OrthancPluginHttpRequest* request) { if (request->method != OrthancPluginHttpMethod_Get) { @@ -296,23 +264,35 @@ for (Json::Value::Members::const_iterator it = members.begin(); it != members.end(); ++it) { - const std::string& baseUri = *it; - const std::string path = configuration["ServeFolders"][*it].asString(); - const std::string regex = "(" + baseUri + ")/(.*)"; + std::string baseUri = *it; + + // Remove the heading and trailing slashes if any + while (!baseUri.empty() && + *baseUri.begin() == '/') + { + baseUri = baseUri.substr(1); + } - if (baseUri.empty() || - *baseUri.rbegin() == '/') + while (!baseUri.empty() && + *baseUri.rbegin() == '/') { - std::string message = "The URI of a folder to be server cannot be empty or end with a '/': " + *it; - OrthancPluginLogWarning(context_, message.c_str()); + baseUri.resize(baseUri.size() - 1); + } + + if (baseUri.empty()) + { + OrthancPluginLogError(context_, "The URI of a folder to be served cannot be empty"); return -1; } + const std::string path = configuration["ServeFolders"][*it].asString(); + const std::string regex = "/(" + baseUri + ")/(.*)"; + OrthancPluginRegisterRestCallback(context, regex.c_str(), FolderCallback); folders_[baseUri] = path; } - OrthancPluginRegisterRestCallback(context, INDEX_URI, IndexCallback); + OrthancPluginRegisterRestCallback(context, INDEX_URI, ListServedFolders); OrthancPluginSetRootUri(context, INDEX_URI); return 0;