comparison Plugins/Samples/WebSkeleton/Framework/Plugin.cpp @ 1181:17302d83abfd

Sample plugin framework to serve static resources
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 Sep 2014 14:13:20 +0200
parents
children 6e7e5ed91c2d
comparison
equal deleted inserted replaced
1180:dea1c786e1c6 1181:17302d83abfd
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege,
4 * Belgium
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use, copy,
10 * modify, merge, publish, distribute, sublicense, and/or sell copies
11 * of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 **/
26
27
28 #include "../Configuration.h"
29
30 #include <OrthancCPlugin.h>
31 #include <string>
32 #include <stdexcept>
33 #include <algorithm>
34 #include <sys/stat.h>
35
36 #if ORTHANC_PLUGIN_STANDALONE == 1
37 // This is an auto-generated file for standalone builds
38 #include <EmbeddedResources.h>
39 #endif
40
41 static OrthancPluginContext* context = NULL;
42
43
44 static const char* GetMimeType(const std::string& path)
45 {
46 size_t dot = path.find_last_of('.');
47
48 std::string extension = (dot == std::string::npos) ? "" : path.substr(dot);
49 std::transform(extension.begin(), extension.end(), extension.begin(), tolower);
50
51 if (extension == ".html")
52 {
53 return "text/html";
54 }
55 else if (extension == ".css")
56 {
57 return "text/css";
58 }
59 else if (extension == ".js")
60 {
61 return "application/javascript";
62 }
63 else if (extension == ".gif")
64 {
65 return "image/gif";
66 }
67 else if (extension == ".json")
68 {
69 return "application/json";
70 }
71 else if (extension == ".xml")
72 {
73 return "application/xml";
74 }
75 else if (extension == ".png")
76 {
77 return "image/png";
78 }
79 else if (extension == ".jpg" || extension == ".jpeg")
80 {
81 return "image/jpeg";
82 }
83 else
84 {
85 std::string s = "Unknown MIME type for extension: " + extension;
86 OrthancPluginLogWarning(context, s.c_str());
87 return "application/octet-stream";
88 }
89 }
90
91
92 static bool ReadFile(std::string& content,
93 const std::string& path)
94 {
95 struct stat s;
96 if (stat(path.c_str(), &s) != 0 ||
97 !(s.st_mode & S_IFREG))
98 {
99 // Either the path does not exist, or it is not a regular file
100 return false;
101 }
102
103 FILE* fp = fopen(path.c_str(), "rb");
104 if (fp == NULL)
105 {
106 return false;
107 }
108
109 long size;
110
111 if (fseek(fp, 0, SEEK_END) == -1 ||
112 (size = ftell(fp)) < 0)
113 {
114 fclose(fp);
115 return false;
116 }
117
118 content.resize(size);
119
120 if (fseek(fp, 0, SEEK_SET) == -1)
121 {
122 fclose(fp);
123 return false;
124 }
125
126 bool ok = true;
127
128 if (size > 0 &&
129 fread(&content[0], size, 1, fp) != 1)
130 {
131 ok = false;
132 }
133
134 fclose(fp);
135
136 return ok;
137 }
138
139
140 #if ORTHANC_PLUGIN_STANDALONE == 1
141 static int32_t ServeStaticResource(OrthancPluginRestOutput* output,
142 const char* url,
143 const OrthancPluginHttpRequest* request)
144 {
145 if (request->method != OrthancPluginHttpMethod_Get)
146 {
147 OrthancPluginSendMethodNotAllowed(context, output, "GET");
148 return 0;
149 }
150
151 std::string path = "/" + std::string(request->groups[0]);
152 const char* mime = GetMimeType(path);
153
154 try
155 {
156 std::string s;
157 Orthanc::EmbeddedResources::GetDirectoryResource
158 (s, Orthanc::EmbeddedResources::STATIC_RESOURCES, path.c_str());
159
160 const char* resource = s.size() ? s.c_str() : NULL;
161 OrthancPluginAnswerBuffer(context, output, resource, s.size(), mime);
162
163 return 0;
164 }
165 catch (std::runtime_error&)
166 {
167 std::string s = "Unknown static resource in plugin: " + std::string(request->groups[0]);
168 OrthancPluginLogError(context, s.c_str());
169 OrthancPluginSendHttpStatusCode(context, output, 404);
170 return 0;
171 }
172 }
173 #endif
174
175
176 #if ORTHANC_PLUGIN_STANDALONE == 0
177 static int32_t ServeFolder(OrthancPluginRestOutput* output,
178 const char* url,
179 const OrthancPluginHttpRequest* request)
180 {
181 if (request->method != OrthancPluginHttpMethod_Get)
182 {
183 OrthancPluginSendMethodNotAllowed(context, output, "GET");
184 return 0;
185 }
186
187 std::string path = ORTHANC_PLUGIN_RESOURCES_ROOT "/" + std::string(request->groups[0]);
188 const char* mime = GetMimeType(path);
189
190 std::string s;
191 if (ReadFile(s, path))
192 {
193 const char* resource = s.size() ? s.c_str() : NULL;
194 OrthancPluginAnswerBuffer(context, output, resource, s.size(), mime);
195
196 return 0;
197 }
198 else
199 {
200 std::string s = "Unknown static resource in plugin: " + std::string(request->groups[0]);
201 OrthancPluginLogError(context, s.c_str());
202 OrthancPluginSendHttpStatusCode(context, output, 404);
203 return 0;
204 }
205 }
206 #endif
207
208
209 static int32_t RedirectRoot(OrthancPluginRestOutput* output,
210 const char* url,
211 const OrthancPluginHttpRequest* request)
212 {
213 if (request->method != OrthancPluginHttpMethod_Get)
214 {
215 OrthancPluginSendMethodNotAllowed(context, output, "GET");
216 }
217 else
218 {
219 OrthancPluginRedirect(context, output, ORTHANC_PLUGIN_WEB_ROOT "index.html");
220 }
221
222 return 0;
223 }
224
225
226 extern "C"
227 {
228 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
229 {
230 context = c;
231
232 /* Check the version of the Orthanc core */
233 if (OrthancPluginCheckVersion(c) == 0)
234 {
235 char info[256];
236 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin",
237 c->orthancVersion,
238 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
239 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
240 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
241 OrthancPluginLogError(context, info);
242 return -1;
243 }
244
245 /* Register the callbacks */
246
247 #if ORTHANC_PLUGIN_STANDALONE == 1
248 OrthancPluginLogInfo(context, "Serving static resources (standalone build)");
249 OrthancPluginRegisterRestCallback(context, ORTHANC_PLUGIN_WEB_ROOT "(.*)", ServeStaticResource);
250 #else
251 OrthancPluginLogInfo(context, "Serving resources from folder: " ORTHANC_PLUGIN_RESOURCES_ROOT);
252 OrthancPluginRegisterRestCallback(context, ORTHANC_PLUGIN_WEB_ROOT "(.*)", ServeFolder);
253 #endif
254
255 OrthancPluginRegisterRestCallback(context, "/", RedirectRoot);
256
257 return 0;
258 }
259
260
261 ORTHANC_PLUGINS_API void OrthancPluginFinalize()
262 {
263 }
264
265
266 ORTHANC_PLUGINS_API const char* OrthancPluginGetName()
267 {
268 return ORTHANC_PLUGIN_NAME;
269 }
270
271
272 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion()
273 {
274 return ORTHANC_PLUGIN_VERSION;
275 }
276 }