diff Plugins/Samples/ServeFolders/Plugin.cpp @ 1589:334d3a92ed83

improvements to the ServeFolders plugin
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 26 Aug 2015 17:43:00 +0200
parents b5bc87a7212d
children 415dfd1d1c61
line wrap: on
line diff
--- a/Plugins/Samples/ServeFolders/Plugin.cpp	Wed Aug 26 16:49:46 2015 +0200
+++ b/Plugins/Samples/ServeFolders/Plugin.cpp	Wed Aug 26 17:43:00 2015 +0200
@@ -22,11 +22,8 @@
 
 #include <json/reader.h>
 #include <json/value.h>
-#include <string.h>
-#include <stdio.h>
-#include <fstream>
-#include <algorithm>
-#include <sys/stat.h>
+#include <boost/filesystem.hpp>
+
 
 static OrthancPluginContext* context_ = NULL;
 static std::map<std::string, std::string> folders_;
@@ -136,6 +133,80 @@
 }
 
 
+
+static bool LookupFolder(std::string& folder,
+                         OrthancPluginRestOutput* output,
+                         const OrthancPluginHttpRequest* request)
+{
+  const std::string uri = request->groups[0];
+
+  std::map<std::string, std::string>::const_iterator found = folders_.find(uri);
+  if (found == folders_.end())
+  {
+    std::string s = "Unknown URI in plugin server-folders: " + uri;
+    OrthancPluginLogError(context_, s.c_str());
+    OrthancPluginSendHttpStatusCode(context_, output, 404);
+    return false;
+  }
+  else
+  {
+    folder = found->second;
+    return true;
+  }
+}
+
+
+static int32_t IndexCallback(OrthancPluginRestOutput* output,
+                             const char* url,
+                             const OrthancPluginHttpRequest* request)
+{
+  namespace fs = boost::filesystem;
+
+  if (request->method != OrthancPluginHttpMethod_Get)
+  {
+    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
+    return 0;
+  }
+
+  std::string folder;
+  if (LookupFolder(folder, output, request))
+  {
+    std::string baseUri = "/" + std::string(request->groups[0]);
+
+    if (fs::is_regular_file(fs::path(folder) / "index.html"))
+    {
+      std::string s = baseUri + "/index.html";
+      OrthancPluginRedirect(context_, output, s.c_str());
+    }
+    else
+    {
+      std::string s;
+      s += "<html>\n";
+      s += "  <body>\n";
+      s += "    <ul>\n";
+
+      fs::directory_iterator end;
+      for (fs::directory_iterator it(folder) ; it != end; ++it)
+      {
+        if (fs::is_regular_file(it->status()))
+        {
+          std::string f = it->path().filename().string();
+          s += "      <li><a href=\"" + baseUri + "/" + f + "\">" + f + "</a></li>";
+        }
+      }
+
+      s += "    </ul>\n";
+      s += "  </body>\n";
+      s += "</html>\n";
+
+      OrthancPluginAnswerBuffer(context_, output, s.c_str(), s.size(), "text/html");
+    }
+  }
+
+  return 0;
+}
+
+
 static int32_t FolderCallback(OrthancPluginRestOutput* output,
                               const char* url,
                               const OrthancPluginHttpRequest* request)
@@ -146,32 +217,27 @@
     return 0;
   }
 
-  const std::string uri = request->groups[0];
-  const std::string item = request->groups[1];
+  std::string folder;
 
-  std::map<std::string, std::string>::const_iterator found = folders_.find(uri);
-  if (found == folders_.end())
+  if (LookupFolder(folder, output, request))
   {
-    std::string s = "Unknown URI in plugin server-folders: " + uri;
-    OrthancPluginLogError(context_, s.c_str());
-    OrthancPluginSendHttpStatusCode(context_, output, 404);
-    return 0;
-  }
+    const std::string item = request->groups[1];
+
+    std::string path = folder + "/" + item;
+    const char* mime = GetMimeType(path);
 
-  std::string path = found->second + "/" + item;
-  const char* mime = GetMimeType(path);
-
-  std::string s;
-  if (ReadFile(s, path))
-  {
-    const char* resource = s.size() ? s.c_str() : NULL;
-    OrthancPluginAnswerBuffer(context_, output, resource, s.size(), mime);
-  }
-  else
-  {
-    std::string s = "Inexistent file in served folder: " + path;
-    OrthancPluginLogError(context_, s.c_str());
-    OrthancPluginSendHttpStatusCode(context_, output, 404);
+    std::string s;
+    if (ReadFile(s, path))
+    {
+      const char* resource = s.size() ? s.c_str() : NULL;
+      OrthancPluginAnswerBuffer(context_, output, resource, s.size(), mime);
+    }
+    else
+    {
+      std::string s = "Inexistent file in served folder: " + path;
+      OrthancPluginLogError(context_, s.c_str());
+      OrthancPluginSendHttpStatusCode(context_, output, 404);
+    }
   }
 
   return 0;
@@ -200,7 +266,7 @@
     for (std::map<std::string, std::string>::const_iterator
            it = folders_.begin(); it != folders_.end(); ++it)
     {
-      s += "<li><a href=\"" + it->first + "/index.html\">" + it->first + "</li>\n";
+      s += "<li><a href=\"/" + it->first + "\">" + it->first + "</li>\n";
     }
     
     s += "</ul>\n";
@@ -214,7 +280,6 @@
 }
 
 
-
 extern "C"
 {
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
@@ -266,7 +331,7 @@
     {
       std::string baseUri = *it;
 
-      // Remove the heading and trailing slashes if any
+      // Remove the heading and trailing slashes in the root URI, if any
       while (!baseUri.empty() &&
              *baseUri.begin() == '/')
       {
@@ -285,11 +350,28 @@
         return -1;
       }
 
-      const std::string path = configuration["ServeFolders"][*it].asString();
-      const std::string regex = "/(" + baseUri + ")/(.*)";
+      // Check whether the source folder exists and is indeed a directory
+      const std::string folder = configuration["ServeFolders"][*it].asString();
+      if (!boost::filesystem::is_directory(folder))
+      {
+        std::string msg = "Trying and serve an inexistent folder: " + folder;
+        OrthancPluginLogError(context_, msg.c_str());
+        return -1;
+      }
+
+      folders_[baseUri] = folder;
 
-      OrthancPluginRegisterRestCallback(context, regex.c_str(), FolderCallback);
-      folders_[baseUri] = path;
+      // Register the callback to serve the index of the folder
+      {
+        const std::string regex = "/(" + baseUri + ")";
+        OrthancPluginRegisterRestCallback(context, regex.c_str(), IndexCallback);
+      }
+
+      // Register the callback to serve the folder
+      {
+        const std::string regex = "/(" + baseUri + ")/(.*)";
+        OrthancPluginRegisterRestCallback(context, regex.c_str(), FolderCallback);
+      }
     }
 
     OrthancPluginRegisterRestCallback(context, INDEX_URI, ListServedFolders);