Mercurial > hg > orthanc
annotate OrthancServer/Sources/OrthancWebDav.cpp @ 4399:80fd140b12ba
New command-line option: "--openapi" to write the OpenAPI documentation of the REST API to a file
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 23 Dec 2020 12:21:03 +0100 |
parents | 3ea753570c6d |
children | d9473bd5ed43 |
rev | line source |
---|---|
4240 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #include "OrthancWebDav.h" | |
35 | |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
36 #include "../../OrthancFramework/Sources/Compression/ZipReader.h" |
4240 | 37 #include "../../OrthancFramework/Sources/DicomFormat/DicomArray.h" |
38 #include "../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h" | |
39 #include "../../OrthancFramework/Sources/HttpServer/WebDavStorage.h" | |
4304 | 40 #include "../../OrthancFramework/Sources/Logging.h" |
4240 | 41 #include "Search/DatabaseLookup.h" |
42 #include "ServerContext.h" | |
43 | |
44 #include <boost/regex.hpp> | |
45 #include <boost/algorithm/string/predicate.hpp> | |
46 | |
47 | |
48 static const char* const BY_PATIENTS = "by-patients"; | |
49 static const char* const BY_STUDIES = "by-studies"; | |
4241 | 50 static const char* const BY_DATES = "by-dates"; |
4240 | 51 static const char* const BY_UIDS = "by-uids"; |
52 static const char* const UPLOADS = "uploads"; | |
53 static const char* const MAIN_DICOM_TAGS = "MainDicomTags"; | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
54 static const char* const STUDY_INFO = "study.json"; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
55 static const char* const SERIES_INFO = "series.json"; |
4240 | 56 |
57 | |
58 namespace Orthanc | |
59 { | |
60 static boost::posix_time::ptime GetNow() | |
61 { | |
62 return boost::posix_time::second_clock::universal_time(); | |
63 } | |
64 | |
65 | |
66 static void LookupTime(boost::posix_time::ptime& target, | |
67 ServerContext& context, | |
68 const std::string& publicId, | |
69 MetadataType metadata) | |
70 { | |
71 std::string value; | |
72 if (context.GetIndex().LookupMetadata(value, publicId, metadata)) | |
73 { | |
74 try | |
75 { | |
76 target = boost::posix_time::from_iso_string(value); | |
77 return; | |
78 } | |
79 catch (std::exception& e) | |
80 { | |
81 } | |
82 } | |
83 | |
84 target = GetNow(); | |
85 } | |
86 | |
87 | |
88 class OrthancWebDav::DicomIdentifiersVisitor : public ServerContext::ILookupVisitor | |
89 { | |
90 private: | |
91 ServerContext& context_; | |
92 bool isComplete_; | |
93 Collection& target_; | |
94 ResourceType level_; | |
95 | |
96 public: | |
97 DicomIdentifiersVisitor(ServerContext& context, | |
98 Collection& target, | |
99 ResourceType level) : | |
100 context_(context), | |
101 isComplete_(false), | |
102 target_(target), | |
103 level_(level) | |
104 { | |
105 } | |
106 | |
107 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
108 { | |
109 return false; // (*) | |
110 } | |
111 | |
112 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
113 { | |
114 isComplete_ = true; // TODO | |
115 } | |
116 | |
117 virtual void Visit(const std::string& publicId, | |
118 const std::string& instanceId /* unused */, | |
119 const DicomMap& mainDicomTags, | |
120 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
121 { | |
122 DicomTag tag(0, 0); | |
123 MetadataType timeMetadata; | |
124 | |
125 switch (level_) | |
126 { | |
127 case ResourceType_Study: | |
128 tag = DICOM_TAG_STUDY_INSTANCE_UID; | |
129 timeMetadata = MetadataType_LastUpdate; | |
130 break; | |
131 | |
132 case ResourceType_Series: | |
133 tag = DICOM_TAG_SERIES_INSTANCE_UID; | |
134 timeMetadata = MetadataType_LastUpdate; | |
135 break; | |
136 | |
137 case ResourceType_Instance: | |
138 tag = DICOM_TAG_SOP_INSTANCE_UID; | |
139 timeMetadata = MetadataType_Instance_ReceptionDate; | |
140 break; | |
141 | |
142 default: | |
143 throw OrthancException(ErrorCode_InternalError); | |
144 } | |
145 | |
146 std::string s; | |
147 if (mainDicomTags.LookupStringValue(s, tag, false) && | |
148 !s.empty()) | |
149 { | |
150 std::unique_ptr<Resource> resource; | |
151 | |
152 if (level_ == ResourceType_Instance) | |
153 { | |
154 FileInfo info; | |
155 if (context_.GetIndex().LookupAttachment(info, publicId, FileContentType_Dicom)) | |
156 { | |
157 std::unique_ptr<File> f(new File(s + ".dcm")); | |
158 f->SetMimeType(MimeType_Dicom); | |
159 f->SetContentLength(info.GetUncompressedSize()); | |
160 resource.reset(f.release()); | |
161 } | |
162 } | |
163 else | |
164 { | |
165 resource.reset(new Folder(s)); | |
166 } | |
167 | |
168 if (resource.get() != NULL) | |
169 { | |
170 boost::posix_time::ptime t; | |
171 LookupTime(t, context_, publicId, timeMetadata); | |
172 resource->SetCreationTime(t); | |
173 target_.AddResource(resource.release()); | |
174 } | |
175 } | |
176 } | |
177 }; | |
178 | |
179 | |
180 class OrthancWebDav::DicomFileVisitor : public ServerContext::ILookupVisitor | |
181 { | |
182 private: | |
183 ServerContext& context_; | |
184 bool success_; | |
185 std::string& target_; | |
186 boost::posix_time::ptime& time_; | |
187 | |
188 public: | |
189 DicomFileVisitor(ServerContext& context, | |
190 std::string& target, | |
191 boost::posix_time::ptime& time) : | |
192 context_(context), | |
193 success_(false), | |
194 target_(target), | |
195 time_(time) | |
196 { | |
197 } | |
198 | |
199 bool IsSuccess() const | |
200 { | |
201 return success_; | |
202 } | |
203 | |
204 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
205 { | |
206 return false; // (*) | |
207 } | |
208 | |
209 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
210 { | |
211 } | |
212 | |
213 virtual void Visit(const std::string& publicId, | |
214 const std::string& instanceId /* unused */, | |
215 const DicomMap& mainDicomTags, | |
216 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
217 { | |
218 if (success_) | |
219 { | |
220 success_ = false; // Two matches => Error | |
221 } | |
222 else | |
223 { | |
224 LookupTime(time_, context_, publicId, MetadataType_Instance_ReceptionDate); | |
225 context_.ReadDicom(target_, publicId); | |
226 success_ = true; | |
227 } | |
228 } | |
229 }; | |
230 | |
231 | |
232 class OrthancWebDav::OrthancJsonVisitor : public ServerContext::ILookupVisitor | |
233 { | |
234 private: | |
235 ServerContext& context_; | |
236 bool success_; | |
237 std::string& target_; | |
238 ResourceType level_; | |
239 | |
240 public: | |
241 OrthancJsonVisitor(ServerContext& context, | |
242 std::string& target, | |
243 ResourceType level) : | |
244 context_(context), | |
245 success_(false), | |
246 target_(target), | |
247 level_(level) | |
248 { | |
249 } | |
250 | |
251 bool IsSuccess() const | |
252 { | |
253 return success_; | |
254 } | |
255 | |
256 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
257 { | |
258 return false; // (*) | |
259 } | |
260 | |
261 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
262 { | |
263 } | |
264 | |
265 virtual void Visit(const std::string& publicId, | |
266 const std::string& instanceId /* unused */, | |
267 const DicomMap& mainDicomTags, | |
268 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
269 { | |
270 Json::Value info; | |
271 if (context_.GetIndex().LookupResource(info, publicId, level_)) | |
272 { | |
273 if (success_) | |
274 { | |
275 success_ = false; // Two matches => Error | |
276 } | |
277 else | |
278 { | |
279 target_ = info.toStyledString(); | |
280 | |
281 // Replace UNIX newlines with DOS newlines | |
282 boost::replace_all(target_, "\n", "\r\n"); | |
283 | |
284 success_ = true; | |
285 } | |
286 } | |
287 } | |
288 }; | |
289 | |
290 | |
291 class OrthancWebDav::ResourcesIndex : public boost::noncopyable | |
292 { | |
293 public: | |
294 typedef std::map<std::string, std::string> Map; | |
295 | |
296 private: | |
297 ServerContext& context_; | |
298 ResourceType level_; | |
299 std::string template_; | |
300 Map pathToResource_; | |
301 Map resourceToPath_; | |
302 | |
303 void CheckInvariants() | |
304 { | |
305 #ifndef NDEBUG | |
306 assert(pathToResource_.size() == resourceToPath_.size()); | |
307 | |
308 for (Map::const_iterator it = pathToResource_.begin(); it != pathToResource_.end(); ++it) | |
309 { | |
310 assert(resourceToPath_[it->second] == it->first); | |
311 } | |
312 | |
313 for (Map::const_iterator it = resourceToPath_.begin(); it != resourceToPath_.end(); ++it) | |
314 { | |
315 assert(pathToResource_[it->second] == it->first); | |
316 } | |
317 #endif | |
318 } | |
319 | |
320 void AddTags(DicomMap& target, | |
321 const std::string& resourceId, | |
322 ResourceType tagsFromLevel) | |
323 { | |
324 DicomMap tags; | |
325 if (context_.GetIndex().GetMainDicomTags(tags, resourceId, level_, tagsFromLevel)) | |
326 { | |
327 target.Merge(tags); | |
328 } | |
329 } | |
330 | |
331 void Register(const std::string& resourceId) | |
332 { | |
333 // Don't register twice the same resource | |
334 if (resourceToPath_.find(resourceId) == resourceToPath_.end()) | |
335 { | |
336 std::string name = template_; | |
337 | |
338 DicomMap tags; | |
339 | |
340 AddTags(tags, resourceId, level_); | |
341 | |
342 if (level_ == ResourceType_Study) | |
343 { | |
344 AddTags(tags, resourceId, ResourceType_Patient); | |
345 } | |
346 | |
347 DicomArray arr(tags); | |
348 for (size_t i = 0; i < arr.GetSize(); i++) | |
349 { | |
350 const DicomElement& element = arr.GetElement(i); | |
351 if (!element.GetValue().IsNull() && | |
352 !element.GetValue().IsBinary()) | |
353 { | |
354 const std::string tag = FromDcmtkBridge::GetTagName(element.GetTag(), ""); | |
355 boost::replace_all(name, "{{" + tag + "}}", element.GetValue().GetContent()); | |
356 } | |
357 } | |
358 | |
359 // Blank the tags that were not matched | |
360 static const boost::regex REGEX_BLANK_TAGS("{{.*?}}"); // non-greedy match | |
361 name = boost::regex_replace(name, REGEX_BLANK_TAGS, ""); | |
362 | |
363 // UTF-8 characters cannot be used on Windows XP | |
364 name = Toolbox::ConvertToAscii(name); | |
365 boost::replace_all(name, "/", ""); | |
366 boost::replace_all(name, "\\", ""); | |
367 | |
368 // Trim sequences of spaces as one single space | |
369 static const boost::regex REGEX_TRIM_SPACES("{{.*?}}"); | |
370 name = boost::regex_replace(name, REGEX_TRIM_SPACES, " "); | |
371 name = Toolbox::StripSpaces(name); | |
372 | |
373 size_t count = 0; | |
374 for (;;) | |
375 { | |
376 std::string path = name; | |
377 if (count > 0) | |
378 { | |
379 path += " (" + boost::lexical_cast<std::string>(count) + ")"; | |
380 } | |
381 | |
382 if (pathToResource_.find(path) == pathToResource_.end()) | |
383 { | |
384 pathToResource_[path] = resourceId; | |
385 resourceToPath_[resourceId] = path; | |
386 return; | |
387 } | |
388 | |
389 count++; | |
390 } | |
391 | |
392 throw OrthancException(ErrorCode_InternalError); | |
393 } | |
394 } | |
395 | |
396 public: | |
397 ResourcesIndex(ServerContext& context, | |
398 ResourceType level, | |
399 const std::string& templateString) : | |
400 context_(context), | |
401 level_(level), | |
402 template_(templateString) | |
403 { | |
404 } | |
405 | |
406 ResourceType GetLevel() const | |
407 { | |
408 return level_; | |
409 } | |
410 | |
411 void Refresh(std::set<std::string>& removedPaths /* out */, | |
412 const std::set<std::string>& resources) | |
413 { | |
414 CheckInvariants(); | |
415 | |
416 // Detect the resources that have been removed since last refresh | |
417 removedPaths.clear(); | |
418 std::set<std::string> removedResources; | |
419 | |
420 for (Map::iterator it = resourceToPath_.begin(); it != resourceToPath_.end(); ++it) | |
421 { | |
422 if (resources.find(it->first) == resources.end()) | |
423 { | |
424 const std::string& path = it->second; | |
425 | |
426 assert(pathToResource_.find(path) != pathToResource_.end()); | |
427 pathToResource_.erase(path); | |
428 removedPaths.insert(path); | |
429 | |
430 removedResources.insert(it->first); // Delay the removal to avoid disturbing the iterator | |
431 } | |
432 } | |
433 | |
434 // Remove the missing resources | |
435 for (std::set<std::string>::const_iterator it = removedResources.begin(); it != removedResources.end(); ++it) | |
436 { | |
437 assert(resourceToPath_.find(*it) != resourceToPath_.end()); | |
438 resourceToPath_.erase(*it); | |
439 } | |
440 | |
441 CheckInvariants(); | |
442 | |
443 for (std::set<std::string>::const_iterator it = resources.begin(); it != resources.end(); ++it) | |
444 { | |
445 Register(*it); | |
446 } | |
447 | |
448 CheckInvariants(); | |
449 } | |
450 | |
451 const Map& GetPathToResource() const | |
452 { | |
453 return pathToResource_; | |
454 } | |
455 }; | |
456 | |
457 | |
458 class OrthancWebDav::InstancesOfSeries : public INode | |
459 { | |
460 private: | |
461 ServerContext& context_; | |
462 std::string parentSeries_; | |
463 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
464 static bool LookupInstanceId(std::string& instanceId, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
465 const UriComponents& path) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
466 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
467 if (path.size() == 1 && |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
468 boost::ends_with(path[0], ".dcm")) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
469 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
470 instanceId = path[0].substr(0, path[0].size() - 4); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
471 return true; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
472 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
473 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
474 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
475 return false; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
476 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
477 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
478 |
4240 | 479 public: |
480 InstancesOfSeries(ServerContext& context, | |
481 const std::string& parentSeries) : | |
482 context_(context), | |
483 parentSeries_(parentSeries) | |
484 { | |
485 } | |
486 | |
487 virtual bool ListCollection(IWebDavBucket::Collection& target, | |
488 const UriComponents& path) ORTHANC_OVERRIDE | |
489 { | |
490 if (path.empty()) | |
491 { | |
492 std::list<std::string> resources; | |
493 try | |
494 { | |
495 context_.GetIndex().GetChildren(resources, parentSeries_); | |
496 } | |
497 catch (OrthancException&) | |
498 { | |
499 // Unknown (or deleted) parent series | |
500 return false; | |
501 } | |
502 | |
503 for (std::list<std::string>::const_iterator | |
504 it = resources.begin(); it != resources.end(); ++it) | |
505 { | |
506 boost::posix_time::ptime time; | |
507 LookupTime(time, context_, *it, MetadataType_Instance_ReceptionDate); | |
508 | |
509 FileInfo info; | |
510 if (context_.GetIndex().LookupAttachment(info, *it, FileContentType_Dicom)) | |
511 { | |
512 std::unique_ptr<File> resource(new File(*it + ".dcm")); | |
513 resource->SetMimeType(MimeType_Dicom); | |
514 resource->SetContentLength(info.GetUncompressedSize()); | |
515 resource->SetCreationTime(time); | |
516 target.AddResource(resource.release()); | |
517 } | |
518 } | |
519 | |
520 return true; | |
521 } | |
522 else | |
523 { | |
524 return false; | |
525 } | |
526 } | |
527 | |
528 virtual bool GetFileContent(MimeType& mime, | |
529 std::string& content, | |
530 boost::posix_time::ptime& time, | |
531 const UriComponents& path) ORTHANC_OVERRIDE | |
532 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
533 std::string instanceId; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
534 if (LookupInstanceId(instanceId, path)) |
4240 | 535 { |
536 try | |
537 { | |
538 mime = MimeType_Dicom; | |
539 context_.ReadDicom(content, instanceId); | |
540 LookupTime(time, context_, instanceId, MetadataType_Instance_ReceptionDate); | |
541 return true; | |
542 } | |
543 catch (OrthancException&) | |
544 { | |
545 // File was removed | |
546 return false; | |
547 } | |
548 } | |
549 else | |
550 { | |
551 return false; | |
552 } | |
553 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
554 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
555 virtual bool DeleteItem(const UriComponents& path) ORTHANC_OVERRIDE |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
556 { |
4252 | 557 if (path.empty()) |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
558 { |
4252 | 559 // Delete all |
560 std::list<std::string> resources; | |
561 try | |
562 { | |
563 context_.GetIndex().GetChildren(resources, parentSeries_); | |
564 } | |
565 catch (OrthancException&) | |
566 { | |
567 // Unknown (or deleted) parent series | |
568 return true; | |
569 } | |
570 | |
571 for (std::list<std::string>::const_iterator it = resources.begin(); | |
572 it != resources.end(); ++it) | |
573 { | |
574 Json::Value info; | |
575 context_.DeleteResource(info, *it, ResourceType_Instance); | |
576 } | |
577 | |
578 return true; | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
579 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
580 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
581 { |
4252 | 582 std::string instanceId; |
583 if (LookupInstanceId(instanceId, path)) | |
584 { | |
585 Json::Value info; | |
586 return context_.DeleteResource(info, instanceId, ResourceType_Instance); | |
587 } | |
588 else | |
589 { | |
590 return false; | |
591 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
592 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
593 } |
4240 | 594 }; |
595 | |
596 | |
597 | |
598 /** | |
599 * The "InternalNode" class corresponds to a non-leaf node in the | |
600 * WebDAV tree, that only contains subfolders (no file). | |
601 * | |
602 * TODO: Implement a LRU index to dynamically remove the oldest | |
603 * children on high RAM usage. | |
604 **/ | |
605 class OrthancWebDav::InternalNode : public INode | |
606 { | |
607 private: | |
608 typedef std::map<std::string, INode*> Children; | |
609 | |
610 Children children_; | |
611 | |
612 INode* GetChild(const std::string& path) // Don't delete the result pointer! | |
613 { | |
614 Children::const_iterator child = children_.find(path); | |
615 if (child == children_.end()) | |
616 { | |
4253 | 617 INode* node = CreateSubfolder(path); |
4240 | 618 |
4253 | 619 if (node == NULL) |
4240 | 620 { |
621 return NULL; | |
622 } | |
623 else | |
624 { | |
4253 | 625 children_[path] = node; |
626 return node; | |
4240 | 627 } |
628 } | |
629 else | |
630 { | |
631 assert(child->second != NULL); | |
632 return child->second; | |
633 } | |
634 } | |
635 | |
636 protected: | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
637 void InvalidateSubfolder(const std::string& path) |
4240 | 638 { |
639 Children::iterator child = children_.find(path); | |
640 if (child != children_.end()) | |
641 { | |
642 assert(child->second != NULL); | |
643 delete child->second; | |
644 children_.erase(child); | |
645 } | |
646 } | |
647 | |
648 virtual void Refresh() = 0; | |
649 | |
650 virtual bool ListSubfolders(IWebDavBucket::Collection& target) = 0; | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
651 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
652 virtual INode* CreateSubfolder(const std::string& path) = 0; |
4240 | 653 |
654 public: | |
655 virtual ~InternalNode() | |
656 { | |
657 for (Children::iterator it = children_.begin(); it != children_.end(); ++it) | |
658 { | |
659 assert(it->second != NULL); | |
660 delete it->second; | |
661 } | |
662 } | |
663 | |
664 virtual bool ListCollection(IWebDavBucket::Collection& target, | |
665 const UriComponents& path) | |
666 ORTHANC_OVERRIDE ORTHANC_FINAL | |
667 { | |
668 Refresh(); | |
669 | |
670 if (path.empty()) | |
671 { | |
672 return ListSubfolders(target); | |
673 } | |
674 else | |
675 { | |
676 // Recursivity | |
677 INode* child = GetChild(path[0]); | |
678 if (child == NULL) | |
679 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
680 // Must be "true" to allow DELETE on folders that are |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
681 // automatically removed through recursive deletion |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
682 return true; |
4240 | 683 } |
684 else | |
685 { | |
686 UriComponents subpath(path.begin() + 1, path.end()); | |
687 return child->ListCollection(target, subpath); | |
688 } | |
689 } | |
690 } | |
691 | |
692 virtual bool GetFileContent(MimeType& mime, | |
693 std::string& content, | |
694 boost::posix_time::ptime& time, | |
695 const UriComponents& path) | |
696 ORTHANC_OVERRIDE ORTHANC_FINAL | |
697 { | |
698 if (path.empty()) | |
699 { | |
700 return false; // An internal node doesn't correspond to a file | |
701 } | |
702 else | |
703 { | |
704 // Recursivity | |
705 Refresh(); | |
706 | |
707 INode* child = GetChild(path[0]); | |
708 if (child == NULL) | |
709 { | |
710 return false; | |
711 } | |
712 else | |
713 { | |
714 UriComponents subpath(path.begin() + 1, path.end()); | |
715 return child->GetFileContent(mime, content, time, subpath); | |
716 } | |
717 } | |
718 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
719 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
720 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
721 virtual bool DeleteItem(const UriComponents& path) ORTHANC_OVERRIDE ORTHANC_FINAL |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
722 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
723 Refresh(); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
724 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
725 if (path.empty()) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
726 { |
4252 | 727 IWebDavBucket::Collection collection; |
728 if (ListSubfolders(collection)) | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
729 { |
4252 | 730 std::set<std::string> content; |
731 collection.ListDisplayNames(content); | |
732 | |
733 for (std::set<std::string>::const_iterator | |
734 it = content.begin(); it != content.end(); ++it) | |
735 { | |
736 INode* node = GetChild(*it); | |
737 if (node) | |
738 { | |
739 node->DeleteItem(path); | |
740 } | |
741 } | |
742 | |
743 return true; | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
744 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
745 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
746 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
747 return false; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
748 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
749 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
750 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
751 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
752 INode* child = GetChild(path[0]); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
753 if (child == NULL) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
754 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
755 return true; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
756 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
757 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
758 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
759 // Recursivity |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
760 UriComponents subpath(path.begin() + 1, path.end()); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
761 return child->DeleteItem(subpath); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
762 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
763 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
764 } |
4240 | 765 }; |
766 | |
767 | |
768 class OrthancWebDav::ListOfResources : public InternalNode | |
769 { | |
770 private: | |
771 ServerContext& context_; | |
772 const Templates& templates_; | |
773 std::unique_ptr<ResourcesIndex> index_; | |
774 MetadataType timeMetadata_; | |
775 | |
776 protected: | |
777 virtual void Refresh() ORTHANC_OVERRIDE ORTHANC_FINAL | |
778 { | |
779 std::list<std::string> resources; | |
780 GetCurrentResources(resources); | |
781 | |
782 std::set<std::string> removedPaths; | |
783 index_->Refresh(removedPaths, std::set<std::string>(resources.begin(), resources.end())); | |
784 | |
785 // Remove the children whose associated resource doesn't exist anymore | |
786 for (std::set<std::string>::const_iterator | |
787 it = removedPaths.begin(); it != removedPaths.end(); ++it) | |
788 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
789 InvalidateSubfolder(*it); |
4240 | 790 } |
791 } | |
792 | |
793 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE ORTHANC_FINAL | |
794 { | |
795 if (index_->GetLevel() == ResourceType_Instance) | |
796 { | |
797 // Not a collection, no subfolders | |
798 return false; | |
799 } | |
800 else | |
801 { | |
802 const ResourcesIndex::Map& paths = index_->GetPathToResource(); | |
803 | |
804 for (ResourcesIndex::Map::const_iterator it = paths.begin(); it != paths.end(); ++it) | |
805 { | |
806 boost::posix_time::ptime time; | |
807 LookupTime(time, context_, it->second, timeMetadata_); | |
808 | |
809 std::unique_ptr<IWebDavBucket::Resource> resource(new IWebDavBucket::Folder(it->first)); | |
810 resource->SetCreationTime(time); | |
811 target.AddResource(resource.release()); | |
812 } | |
813 | |
814 return true; | |
815 } | |
816 } | |
817 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
818 virtual INode* CreateSubfolder(const std::string& path) ORTHANC_OVERRIDE ORTHANC_FINAL |
4240 | 819 { |
820 ResourcesIndex::Map::const_iterator resource = index_->GetPathToResource().find(path); | |
821 if (resource == index_->GetPathToResource().end()) | |
822 { | |
823 return NULL; | |
824 } | |
825 else | |
826 { | |
827 return CreateResourceNode(resource->second); | |
828 } | |
829 } | |
830 | |
831 ServerContext& GetContext() const | |
832 { | |
833 return context_; | |
834 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
835 |
4240 | 836 virtual void GetCurrentResources(std::list<std::string>& resources) = 0; |
837 | |
838 virtual INode* CreateResourceNode(const std::string& resource) = 0; | |
839 | |
840 public: | |
841 ListOfResources(ServerContext& context, | |
842 ResourceType level, | |
843 const Templates& templates) : | |
844 context_(context), | |
845 templates_(templates) | |
846 { | |
847 Templates::const_iterator t = templates.find(level); | |
848 if (t == templates.end()) | |
849 { | |
850 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
851 } | |
852 | |
853 index_.reset(new ResourcesIndex(context, level, t->second)); | |
854 | |
855 if (level == ResourceType_Instance) | |
856 { | |
857 timeMetadata_ = MetadataType_Instance_ReceptionDate; | |
858 } | |
859 else | |
860 { | |
861 timeMetadata_ = MetadataType_LastUpdate; | |
862 } | |
863 } | |
864 | |
865 ResourceType GetLevel() const | |
866 { | |
867 return index_->GetLevel(); | |
868 } | |
869 | |
870 const Templates& GetTemplates() const | |
871 { | |
872 return templates_; | |
873 } | |
874 }; | |
875 | |
876 | |
877 | |
878 class OrthancWebDav::SingleDicomResource : public ListOfResources | |
879 { | |
880 private: | |
881 std::string parentId_; | |
882 | |
883 protected: | |
884 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE | |
885 { | |
886 try | |
887 { | |
888 GetContext().GetIndex().GetChildren(resources, parentId_); | |
889 } | |
890 catch (OrthancException&) | |
891 { | |
892 // Unknown parent resource | |
893 resources.clear(); | |
894 } | |
895 } | |
896 | |
897 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE | |
898 { | |
899 if (GetLevel() == ResourceType_Instance) | |
900 { | |
901 return NULL; | |
902 } | |
903 else if (GetLevel() == ResourceType_Series) | |
904 { | |
905 return new InstancesOfSeries(GetContext(), resource); | |
906 } | |
907 else | |
908 { | |
909 ResourceType l = GetChildResourceType(GetLevel()); | |
910 return new SingleDicomResource(GetContext(), l, resource, GetTemplates()); | |
911 } | |
912 } | |
913 | |
914 public: | |
915 SingleDicomResource(ServerContext& context, | |
916 ResourceType level, | |
917 const std::string& parentId, | |
918 const Templates& templates) : | |
919 ListOfResources(context, level, templates), | |
920 parentId_(parentId) | |
921 { | |
922 } | |
923 }; | |
924 | |
925 | |
926 class OrthancWebDav::RootNode : public ListOfResources | |
927 { | |
928 protected: | |
929 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE | |
930 { | |
931 GetContext().GetIndex().GetAllUuids(resources, GetLevel()); | |
932 } | |
933 | |
934 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE | |
935 { | |
936 if (GetLevel() == ResourceType_Series) | |
937 { | |
938 return new InstancesOfSeries(GetContext(), resource); | |
939 } | |
940 else | |
941 { | |
942 ResourceType l = GetChildResourceType(GetLevel()); | |
943 return new SingleDicomResource(GetContext(), l, resource, GetTemplates()); | |
944 } | |
945 } | |
946 | |
947 public: | |
948 RootNode(ServerContext& context, | |
949 ResourceType level, | |
950 const Templates& templates) : | |
951 ListOfResources(context, level, templates) | |
952 { | |
953 } | |
954 }; | |
955 | |
956 | |
957 class OrthancWebDav::ListOfStudiesByDate : public ListOfResources | |
958 { | |
959 private: | |
960 std::string year_; | |
961 std::string month_; | |
962 | |
963 class Visitor : public ServerContext::ILookupVisitor | |
964 { | |
965 private: | |
966 std::list<std::string>& resources_; | |
967 | |
968 public: | |
4253 | 969 explicit Visitor(std::list<std::string>& resources) : |
4240 | 970 resources_(resources) |
971 { | |
972 } | |
973 | |
974 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
975 { | |
976 return false; // (*) | |
977 } | |
978 | |
979 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
980 { | |
981 } | |
982 | |
983 virtual void Visit(const std::string& publicId, | |
984 const std::string& instanceId /* unused */, | |
985 const DicomMap& mainDicomTags, | |
986 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
987 { | |
988 resources_.push_back(publicId); | |
989 } | |
990 }; | |
991 | |
992 protected: | |
993 virtual void GetCurrentResources(std::list<std::string>& resources) ORTHANC_OVERRIDE | |
994 { | |
995 DatabaseLookup query; | |
996 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + month_ + "01-" + year_ + month_ + "31", | |
997 true /* case sensitive */, true /* mandatory tag */); | |
998 | |
999 Visitor visitor(resources); | |
1000 GetContext().Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | |
1001 } | |
1002 | |
1003 virtual INode* CreateResourceNode(const std::string& resource) ORTHANC_OVERRIDE | |
1004 { | |
1005 return new SingleDicomResource(GetContext(), ResourceType_Series, resource, GetTemplates()); | |
1006 } | |
1007 | |
1008 public: | |
1009 ListOfStudiesByDate(ServerContext& context, | |
1010 const std::string& year, | |
1011 const std::string& month, | |
1012 const Templates& templates) : | |
1013 ListOfResources(context, ResourceType_Study, templates), | |
1014 year_(year), | |
1015 month_(month) | |
1016 { | |
1017 if (year.size() != 4 || | |
1018 month.size() != 2) | |
1019 { | |
1020 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1021 } | |
1022 } | |
1023 }; | |
1024 | |
1025 | |
1026 class OrthancWebDav::ListOfStudiesByMonth : public InternalNode | |
1027 { | |
1028 private: | |
1029 ServerContext& context_; | |
1030 std::string year_; | |
1031 const Templates& templates_; | |
1032 | |
1033 class Visitor : public ServerContext::ILookupVisitor | |
1034 { | |
1035 private: | |
1036 std::set<std::string> months_; | |
1037 | |
1038 public: | |
1039 const std::set<std::string>& GetMonths() const | |
1040 { | |
1041 return months_; | |
1042 } | |
1043 | |
1044 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE | |
1045 { | |
1046 return false; // (*) | |
1047 } | |
1048 | |
1049 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
1050 { | |
1051 } | |
1052 | |
1053 virtual void Visit(const std::string& publicId, | |
1054 const std::string& instanceId /* unused */, | |
1055 const DicomMap& mainDicomTags, | |
1056 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE | |
1057 { | |
1058 std::string s; | |
1059 if (mainDicomTags.LookupStringValue(s, DICOM_TAG_STUDY_DATE, false) && | |
1060 s.size() == 8) | |
1061 { | |
1062 months_.insert(s.substr(4, 2)); // Get the month from "YYYYMMDD" | |
1063 } | |
1064 } | |
1065 }; | |
1066 | |
1067 protected: | |
1068 virtual void Refresh() ORTHANC_OVERRIDE | |
1069 { | |
1070 } | |
1071 | |
1072 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE | |
1073 { | |
1074 DatabaseLookup query; | |
1075 query.AddRestConstraint(DICOM_TAG_STUDY_DATE, year_ + "0101-" + year_ + "1231", | |
1076 true /* case sensitive */, true /* mandatory tag */); | |
1077 | |
1078 Visitor visitor; | |
1079 context_.Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | |
1080 | |
1081 for (std::set<std::string>::const_iterator it = visitor.GetMonths().begin(); | |
1082 it != visitor.GetMonths().end(); ++it) | |
1083 { | |
1084 target.AddResource(new IWebDavBucket::Folder(year_ + "-" + *it)); | |
1085 } | |
1086 | |
1087 return true; | |
1088 } | |
1089 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1090 virtual INode* CreateSubfolder(const std::string& path) ORTHANC_OVERRIDE |
4240 | 1091 { |
1092 if (path.size() != 7) // Format: "YYYY-MM" | |
1093 { | |
1094 throw OrthancException(ErrorCode_InternalError); | |
1095 } | |
1096 else | |
1097 { | |
1098 const std::string year = path.substr(0, 4); | |
1099 const std::string month = path.substr(5, 2); | |
1100 return new ListOfStudiesByDate(context_, year, month, templates_); | |
1101 } | |
1102 } | |
1103 | |
1104 public: | |
1105 ListOfStudiesByMonth(ServerContext& context, | |
1106 const std::string& year, | |
1107 const Templates& templates) : | |
1108 context_(context), | |
1109 year_(year), | |
1110 templates_(templates) | |
1111 { | |
1112 if (year_.size() != 4) | |
1113 { | |
1114 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1115 } | |
1116 } | |
1117 }; | |
1118 | |
1119 | |
1120 class OrthancWebDav::ListOfStudiesByYear : public InternalNode | |
1121 { | |
1122 private: | |
1123 ServerContext& context_; | |
1124 const Templates& templates_; | |
1125 | |
1126 protected: | |
1127 virtual void Refresh() ORTHANC_OVERRIDE | |
1128 { | |
1129 } | |
1130 | |
1131 virtual bool ListSubfolders(IWebDavBucket::Collection& target) ORTHANC_OVERRIDE | |
1132 { | |
1133 std::list<std::string> resources; | |
1134 context_.GetIndex().GetAllUuids(resources, ResourceType_Study); | |
1135 | |
1136 std::set<std::string> years; | |
1137 | |
1138 for (std::list<std::string>::const_iterator it = resources.begin(); it != resources.end(); ++it) | |
1139 { | |
1140 DicomMap tags; | |
1141 std::string studyDate; | |
1142 if (context_.GetIndex().GetMainDicomTags(tags, *it, ResourceType_Study, ResourceType_Study) && | |
1143 tags.LookupStringValue(studyDate, DICOM_TAG_STUDY_DATE, false) && | |
1144 studyDate.size() == 8) | |
1145 { | |
1146 years.insert(studyDate.substr(0, 4)); // Get the year from "YYYYMMDD" | |
1147 } | |
1148 } | |
1149 | |
1150 for (std::set<std::string>::const_iterator it = years.begin(); it != years.end(); ++it) | |
1151 { | |
1152 target.AddResource(new IWebDavBucket::Folder(*it)); | |
1153 } | |
1154 | |
1155 return true; | |
1156 } | |
1157 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1158 virtual INode* CreateSubfolder(const std::string& path) ORTHANC_OVERRIDE |
4240 | 1159 { |
1160 return new ListOfStudiesByMonth(context_, path, templates_); | |
1161 } | |
1162 | |
1163 public: | |
1164 ListOfStudiesByYear(ServerContext& context, | |
1165 const Templates& templates) : | |
1166 context_(context), | |
1167 templates_(templates) | |
1168 { | |
1169 } | |
1170 }; | |
1171 | |
1172 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1173 class OrthancWebDav::DicomDeleteVisitor : public ServerContext::ILookupVisitor |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1174 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1175 private: |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1176 ServerContext& context_; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1177 ResourceType level_; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1178 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1179 public: |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1180 DicomDeleteVisitor(ServerContext& context, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1181 ResourceType level) : |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1182 context_(context), |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1183 level_(level) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1184 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1185 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1186 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1187 virtual bool IsDicomAsJsonNeeded() const ORTHANC_OVERRIDE |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1188 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1189 return false; // (*) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1190 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1191 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1192 virtual void MarkAsComplete() ORTHANC_OVERRIDE |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1193 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1194 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1195 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1196 virtual void Visit(const std::string& publicId, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1197 const std::string& instanceId /* unused */, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1198 const DicomMap& mainDicomTags /* unused */, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1199 const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1200 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1201 Json::Value info; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1202 context_.DeleteResource(info, publicId, level_); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1203 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1204 }; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1205 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1206 |
4240 | 1207 void OrthancWebDav::AddVirtualFile(Collection& collection, |
1208 const UriComponents& path, | |
1209 const std::string& filename) | |
1210 { | |
1211 MimeType mime; | |
1212 std::string content; | |
4246 | 1213 boost::posix_time::ptime modification; // Unused, let the date be set to "GetNow()" |
4240 | 1214 |
1215 UriComponents p = path; | |
1216 p.push_back(filename); | |
1217 | |
1218 if (GetFileContent(mime, content, modification, p)) | |
1219 { | |
1220 std::unique_ptr<File> f(new File(filename)); | |
1221 f->SetMimeType(mime); | |
1222 f->SetContentLength(content.size()); | |
1223 collection.AddResource(f.release()); | |
1224 } | |
1225 } | |
1226 | |
1227 | |
1228 void OrthancWebDav::UploadWorker(OrthancWebDav* that) | |
1229 { | |
1230 assert(that != NULL); | |
1231 | |
1232 boost::posix_time::ptime lastModification = GetNow(); | |
1233 | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1234 while (that->uploadRunning_) |
4240 | 1235 { |
1236 std::unique_ptr<IDynamicObject> obj(that->uploadQueue_.Dequeue(100)); | |
1237 if (obj.get() != NULL) | |
1238 { | |
1239 that->Upload(reinterpret_cast<const SingleValueObject<std::string>&>(*obj).GetValue()); | |
1240 lastModification = GetNow(); | |
1241 } | |
4245
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1242 else if (GetNow() - lastModification > boost::posix_time::seconds(30)) |
4240 | 1243 { |
4245
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1244 /** |
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1245 * After every 30 seconds of inactivity, remove the empty |
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1246 * folders. This delay is needed to avoid removing |
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1247 * just-created folders before the remote WebDAV has time to |
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1248 * write files into it. |
c70df925151e
RequestOrigin_WebDav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4244
diff
changeset
|
1249 **/ |
4268
0ae2ca210077
new macro TLOG() to replace VLOG() for trace logs with a category
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4264
diff
changeset
|
1250 LOG(TRACE) << "Cleaning up the empty WebDAV upload folders"; |
4240 | 1251 that->uploads_.RemoveEmptyFolders(); |
1252 lastModification = GetNow(); | |
1253 } | |
1254 } | |
1255 } | |
1256 | |
1257 | |
1258 void OrthancWebDav::Upload(const std::string& path) | |
1259 { | |
1260 UriComponents uri; | |
1261 Toolbox::SplitUriComponents(uri, path); | |
1262 | |
1263 LOG(INFO) << "Upload from WebDAV: " << path; | |
1264 | |
1265 MimeType mime; | |
1266 std::string content; | |
1267 boost::posix_time::ptime time; | |
1268 if (uploads_.GetFileContent(mime, content, time, uri)) | |
1269 { | |
4244
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1270 bool success = false; |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1271 |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1272 if (ZipReader::IsZipMemoryBuffer(content)) |
4240 | 1273 { |
4374
79ef2b6d8e76
there will be a 1.8.2 release before 1.9.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4358
diff
changeset
|
1274 // New in Orthanc 1.8.2 |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1275 std::unique_ptr<ZipReader> reader(ZipReader::CreateFromMemory(content)); |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1276 |
4386 | 1277 std::string filename, uncompressedFile; |
1278 while (reader->ReadNextFile(filename, uncompressedFile)) | |
4244
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1279 { |
4386 | 1280 if (!uncompressedFile.empty()) |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1281 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1282 LOG(INFO) << "Uploading DICOM file extracted from a ZIP archive in WebDAV: " << filename; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1283 |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1284 DicomInstanceToStore instance; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1285 instance.SetOrigin(DicomInstanceOrigin::FromWebDav()); |
4386 | 1286 instance.SetBuffer(uncompressedFile.c_str(), uncompressedFile.size()); |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1287 |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1288 std::string publicId; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1289 |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1290 try |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1291 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1292 context_.Store(publicId, instance, StoreInstanceMode_Default); |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1293 } |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1294 catch (OrthancException& e) |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1295 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1296 if (e.GetErrorCode() == ErrorCode_BadFileFormat) |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1297 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1298 LOG(ERROR) << "Cannot import non-DICOM file from ZIP archive: " << filename; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1299 } |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1300 } |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1301 } |
4244
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1302 } |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1303 |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1304 success = true; |
4240 | 1305 } |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1306 else |
4240 | 1307 { |
4358
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1308 DicomInstanceToStore instance; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1309 instance.SetOrigin(DicomInstanceOrigin::FromWebDav()); |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1310 instance.SetBuffer(content.c_str(), content.size()); |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1311 |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1312 try |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1313 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1314 std::string publicId; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1315 StoreStatus status = context_.Store(publicId, instance, StoreInstanceMode_Default); |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1316 if (status == StoreStatus_Success || |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1317 status == StoreStatus_AlreadyStored) |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1318 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1319 LOG(INFO) << "Successfully imported DICOM instance from WebDAV: " |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1320 << path << " (Orthanc ID: " << publicId << ")"; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1321 success = true; |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1322 } |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1323 } |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1324 catch (OrthancException& e) |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1325 { |
d6929f052ec4
ZIP archives containing DICOM files can be uploaded using WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4304
diff
changeset
|
1326 } |
4244
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1327 } |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1328 |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1329 uploads_.DeleteItem(uri); |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1330 |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1331 if (!success) |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1332 { |
416c35da7d25
robustness against non-dicom files
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4243
diff
changeset
|
1333 LOG(WARNING) << "Cannot import DICOM instance from WebWAV (maybe not a DICOM file): " << path; |
4240 | 1334 } |
1335 } | |
1336 } | |
1337 | |
1338 | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1339 OrthancWebDav::INode& OrthancWebDav::GetRootNode(const std::string& rootPath) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1340 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1341 if (rootPath == BY_PATIENTS) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1342 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1343 return *patients_; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1344 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1345 else if (rootPath == BY_STUDIES) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1346 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1347 return *studies_; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1348 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1349 else if (rootPath == BY_DATES) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1350 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1351 return *dates_; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1352 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1353 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1354 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1355 throw OrthancException(ErrorCode_InternalError); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1356 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1357 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1358 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1359 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1360 OrthancWebDav::OrthancWebDav(ServerContext& context, |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1361 bool allowDicomDelete, |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1362 bool allowUpload) : |
4240 | 1363 context_(context), |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1364 allowDicomDelete_(allowDicomDelete), |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1365 allowUpload_(allowUpload), |
4240 | 1366 uploads_(false /* store uploads as temporary files */), |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1367 uploadRunning_(false) |
4240 | 1368 { |
1369 patientsTemplates_[ResourceType_Patient] = "{{PatientID}} - {{PatientName}}"; | |
1370 patientsTemplates_[ResourceType_Study] = "{{StudyDate}} - {{StudyDescription}}"; | |
1371 patientsTemplates_[ResourceType_Series] = "{{Modality}} - {{SeriesDescription}}"; | |
1372 | |
1373 studiesTemplates_[ResourceType_Study] = "{{PatientID}} - {{PatientName}} - {{StudyDescription}}"; | |
1374 studiesTemplates_[ResourceType_Series] = patientsTemplates_[ResourceType_Series]; | |
1375 | |
1376 patients_.reset(new RootNode(context, ResourceType_Patient, patientsTemplates_)); | |
1377 studies_.reset(new RootNode(context, ResourceType_Study, studiesTemplates_)); | |
1378 dates_.reset(new ListOfStudiesByYear(context, studiesTemplates_)); | |
1379 } | |
1380 | |
1381 | |
1382 bool OrthancWebDav::IsExistingFolder(const UriComponents& path) | |
1383 { | |
1384 if (path.empty()) | |
1385 { | |
1386 return true; | |
1387 } | |
1388 else if (path[0] == BY_UIDS) | |
1389 { | |
1390 return (path.size() <= 3 && | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1391 (path.size() != 3 || path[2] != STUDY_INFO)); |
4240 | 1392 } |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1393 else if (path[0] == BY_PATIENTS || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1394 path[0] == BY_STUDIES || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1395 path[0] == BY_DATES) |
4240 | 1396 { |
4252 | 1397 IWebDavBucket::Collection collection; |
1398 return GetRootNode(path[0]).ListCollection(collection, UriComponents(path.begin() + 1, path.end())); | |
4240 | 1399 } |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1400 else if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1401 path[0] == UPLOADS) |
4240 | 1402 { |
1403 return uploads_.IsExistingFolder(UriComponents(path.begin() + 1, path.end())); | |
1404 } | |
1405 else | |
1406 { | |
1407 return false; | |
1408 } | |
1409 } | |
1410 | |
1411 | |
1412 bool OrthancWebDav::ListCollection(Collection& collection, | |
1413 const UriComponents& path) | |
1414 { | |
1415 if (path.empty()) | |
1416 { | |
4241 | 1417 collection.AddResource(new Folder(BY_DATES)); |
4240 | 1418 collection.AddResource(new Folder(BY_PATIENTS)); |
1419 collection.AddResource(new Folder(BY_STUDIES)); | |
1420 collection.AddResource(new Folder(BY_UIDS)); | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1421 |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1422 if (allowUpload_) |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1423 { |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1424 collection.AddResource(new Folder(UPLOADS)); |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1425 } |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1426 |
4240 | 1427 return true; |
1428 } | |
1429 else if (path[0] == BY_UIDS) | |
1430 { | |
1431 DatabaseLookup query; | |
1432 ResourceType level; | |
1433 size_t limit = 0; // By default, no limits | |
1434 | |
1435 if (path.size() == 1) | |
1436 { | |
1437 level = ResourceType_Study; | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1438 limit = 0; // TODO - Should we limit here? |
4240 | 1439 } |
1440 else if (path.size() == 2) | |
1441 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1442 AddVirtualFile(collection, path, STUDY_INFO); |
4240 | 1443 |
1444 level = ResourceType_Series; | |
1445 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
1446 true /* case sensitive */, true /* mandatory tag */); | |
1447 } | |
1448 else if (path.size() == 3) | |
1449 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1450 AddVirtualFile(collection, path, SERIES_INFO); |
4240 | 1451 |
1452 level = ResourceType_Instance; | |
1453 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
1454 true /* case sensitive */, true /* mandatory tag */); | |
1455 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | |
1456 true /* case sensitive */, true /* mandatory tag */); | |
1457 } | |
1458 else | |
1459 { | |
1460 return false; | |
1461 } | |
1462 | |
1463 DicomIdentifiersVisitor visitor(context_, collection, level); | |
1464 context_.Apply(visitor, query, level, 0 /* since */, limit); | |
1465 | |
1466 return true; | |
1467 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1468 else if (path[0] == BY_PATIENTS || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1469 path[0] == BY_STUDIES || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1470 path[0] == BY_DATES) |
4240 | 1471 { |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1472 return GetRootNode(path[0]).ListCollection(collection, UriComponents(path.begin() + 1, path.end())); |
4240 | 1473 } |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1474 else if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1475 path[0] == UPLOADS) |
4240 | 1476 { |
1477 return uploads_.ListCollection(collection, UriComponents(path.begin() + 1, path.end())); | |
1478 } | |
1479 else | |
1480 { | |
1481 return false; | |
1482 } | |
1483 } | |
1484 | |
1485 | |
1486 bool OrthancWebDav::GetFileContent(MimeType& mime, | |
1487 std::string& content, | |
1488 boost::posix_time::ptime& modificationTime, | |
1489 const UriComponents& path) | |
1490 { | |
1491 if (path.empty()) | |
1492 { | |
1493 return false; | |
1494 } | |
1495 else if (path[0] == BY_UIDS) | |
1496 { | |
1497 if (path.size() == 3 && | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1498 path[2] == STUDY_INFO) |
4240 | 1499 { |
1500 DatabaseLookup query; | |
1501 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
1502 true /* case sensitive */, true /* mandatory tag */); | |
1503 | |
1504 OrthancJsonVisitor visitor(context_, content, ResourceType_Study); | |
1505 context_.Apply(visitor, query, ResourceType_Study, 0 /* since */, 0 /* no limit */); | |
1506 | |
1507 mime = MimeType_Json; | |
1508 return visitor.IsSuccess(); | |
1509 } | |
1510 else if (path.size() == 4 && | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1511 path[3] == SERIES_INFO) |
4240 | 1512 { |
1513 DatabaseLookup query; | |
1514 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
1515 true /* case sensitive */, true /* mandatory tag */); | |
1516 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | |
1517 true /* case sensitive */, true /* mandatory tag */); | |
1518 | |
1519 OrthancJsonVisitor visitor(context_, content, ResourceType_Series); | |
1520 context_.Apply(visitor, query, ResourceType_Series, 0 /* since */, 0 /* no limit */); | |
1521 | |
1522 mime = MimeType_Json; | |
1523 return visitor.IsSuccess(); | |
1524 } | |
1525 else if (path.size() == 4 && | |
1526 boost::ends_with(path[3], ".dcm")) | |
1527 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1528 const std::string sopInstanceUid = path[3].substr(0, path[3].size() - 4); |
4240 | 1529 |
1530 DatabaseLookup query; | |
1531 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], | |
1532 true /* case sensitive */, true /* mandatory tag */); | |
1533 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], | |
1534 true /* case sensitive */, true /* mandatory tag */); | |
1535 query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, | |
1536 true /* case sensitive */, true /* mandatory tag */); | |
1537 | |
1538 DicomFileVisitor visitor(context_, content, modificationTime); | |
1539 context_.Apply(visitor, query, ResourceType_Instance, 0 /* since */, 0 /* no limit */); | |
1540 | |
1541 mime = MimeType_Dicom; | |
1542 return visitor.IsSuccess(); | |
1543 } | |
1544 else | |
1545 { | |
1546 return false; | |
1547 } | |
1548 } | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1549 else if (path[0] == BY_PATIENTS || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1550 path[0] == BY_STUDIES || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1551 path[0] == BY_DATES) |
4240 | 1552 { |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1553 return GetRootNode(path[0]).GetFileContent(mime, content, modificationTime, UriComponents(path.begin() + 1, path.end())); |
4241 | 1554 } |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1555 else if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1556 path[0] == UPLOADS) |
4240 | 1557 { |
1558 return uploads_.GetFileContent(mime, content, modificationTime, UriComponents(path.begin() + 1, path.end())); | |
1559 } | |
1560 else | |
1561 { | |
1562 return false; | |
1563 } | |
1564 } | |
1565 | |
1566 | |
1567 bool OrthancWebDav::StoreFile(const std::string& content, | |
1568 const UriComponents& path) | |
1569 { | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1570 if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1571 path.size() >= 1 && |
4240 | 1572 path[0] == UPLOADS) |
1573 { | |
1574 UriComponents subpath(UriComponents(path.begin() + 1, path.end())); | |
1575 | |
1576 if (uploads_.StoreFile(content, subpath)) | |
1577 { | |
1578 if (!content.empty()) | |
1579 { | |
1580 uploadQueue_.Enqueue(new SingleValueObject<std::string>(Toolbox::FlattenUri(subpath))); | |
1581 } | |
1582 return true; | |
1583 } | |
1584 else | |
1585 { | |
1586 return false; | |
1587 } | |
1588 } | |
1589 else | |
1590 { | |
1591 return false; | |
1592 } | |
1593 } | |
1594 | |
1595 | |
1596 bool OrthancWebDav::CreateFolder(const UriComponents& path) | |
1597 { | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1598 if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1599 path.size() >= 1 && |
4240 | 1600 path[0] == UPLOADS) |
1601 { | |
1602 return uploads_.CreateFolder(UriComponents(path.begin() + 1, path.end())); | |
1603 } | |
1604 else | |
1605 { | |
1606 return false; | |
1607 } | |
1608 } | |
1609 | |
1610 | |
1611 bool OrthancWebDav::DeleteItem(const std::vector<std::string>& path) | |
1612 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1613 if (path.empty()) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1614 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1615 return false; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1616 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1617 else if (path[0] == BY_UIDS && |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1618 path.size() >= 2 && |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1619 path.size() <= 4) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1620 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1621 if (allowDicomDelete_) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1622 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1623 ResourceType level; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1624 DatabaseLookup query; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1625 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1626 query.AddRestConstraint(DICOM_TAG_STUDY_INSTANCE_UID, path[1], |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1627 true /* case sensitive */, true /* mandatory tag */); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1628 level = ResourceType_Study; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1629 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1630 if (path.size() >= 3) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1631 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1632 if (path[2] == STUDY_INFO) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1633 { |
4252 | 1634 return true; // Allow deletion of virtual files (to avoid blocking recursive DELETE) |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1635 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1636 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1637 query.AddRestConstraint(DICOM_TAG_SERIES_INSTANCE_UID, path[2], |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1638 true /* case sensitive */, true /* mandatory tag */); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1639 level = ResourceType_Series; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1640 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1641 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1642 if (path.size() == 4) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1643 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1644 if (path[3] == SERIES_INFO) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1645 { |
4252 | 1646 return true; // Allow deletion of virtual files (to avoid blocking recursive DELETE) |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1647 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1648 else if (boost::ends_with(path[3], ".dcm")) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1649 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1650 const std::string sopInstanceUid = path[3].substr(0, path[3].size() - 4); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1651 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1652 query.AddRestConstraint(DICOM_TAG_SOP_INSTANCE_UID, sopInstanceUid, |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1653 true /* case sensitive */, true /* mandatory tag */); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1654 level = ResourceType_Instance; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1655 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1656 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1657 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1658 return false; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1659 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1660 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1661 |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1662 DicomDeleteVisitor visitor(context_, level); |
4252 | 1663 context_.Apply(visitor, query, level, 0 /* since */, 0 /* no limit */); |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1664 return true; |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1665 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1666 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1667 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1668 return false; // read-only |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1669 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1670 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1671 else if (path[0] == BY_PATIENTS || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1672 path[0] == BY_STUDIES || |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1673 path[0] == BY_DATES) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1674 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1675 if (allowDicomDelete_) |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1676 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1677 return GetRootNode(path[0]).DeleteItem(UriComponents(path.begin() + 1, path.end())); |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1678 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1679 else |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1680 { |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1681 return false; // read-only |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1682 } |
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1683 } |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1684 else if (allowUpload_ && |
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1685 path[0] == UPLOADS) |
4240 | 1686 { |
1687 return uploads_.DeleteItem(UriComponents(path.begin() + 1, path.end())); | |
1688 } | |
1689 else | |
1690 { | |
4242
5cfa6ba75dfc
deleting resources from Orthanc WebDAV
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4241
diff
changeset
|
1691 return false; |
4240 | 1692 } |
1693 } | |
1694 | |
1695 | |
1696 void OrthancWebDav::Start() | |
1697 { | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1698 if (uploadRunning_) |
4240 | 1699 { |
1700 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
1701 } | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1702 else if (allowUpload_) |
4240 | 1703 { |
1704 LOG(INFO) << "Starting the WebDAV upload thread"; | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1705 uploadRunning_ = true; |
4240 | 1706 uploadThread_ = boost::thread(UploadWorker, this); |
1707 } | |
1708 } | |
1709 | |
1710 | |
1711 void OrthancWebDav::Stop() | |
1712 { | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1713 if (uploadRunning_) |
4240 | 1714 { |
1715 LOG(INFO) << "Stopping the WebDAV upload thread"; | |
4243
64f57c9d5f79
configuration options for webdav
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4242
diff
changeset
|
1716 uploadRunning_ = false; |
4240 | 1717 if (uploadThread_.joinable()) |
1718 { | |
1719 uploadThread_.join(); | |
1720 } | |
1721 } | |
1722 } | |
1723 } |