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