comparison OrthancFramework/Sources/HttpServer/IWebDavBucket.cpp @ 4228:c8c0bbaaace3

write access to webdav
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 Oct 2020 12:45:11 +0200
parents 7bd5eab3ba25
children b313a0001893
comparison
equal deleted inserted replaced
4227:7fff7e683d65 4228:c8c0bbaaace3
21 21
22 22
23 #include "../PrecompiledHeaders.h" 23 #include "../PrecompiledHeaders.h"
24 #include "IWebDavBucket.h" 24 #include "IWebDavBucket.h"
25 25
26 #include "HttpOutput.h"
26 #include "../OrthancException.h" 27 #include "../OrthancException.h"
27 #include "../Toolbox.h" 28 #include "../Toolbox.h"
28 29
29 30
30 static boost::posix_time::ptime GetNow() 31 static boost::posix_time::ptime GetNow()
88 hasModificationTime_ = true; 89 hasModificationTime_ = true;
89 } 90 }
90 91
91 92
92 void IWebDavBucket::Resource::Format(pugi::xml_node& node, 93 void IWebDavBucket::Resource::Format(pugi::xml_node& node,
93 const std::string& parentPath) const 94 const std::string& parentPath) const
94 { 95 {
95 node.set_name("D:response"); 96 node.set_name("D:response");
96 97
97 std::string s = AddTrailingSlash(parentPath) + GetName(); 98 std::string s = AddTrailingSlash(parentPath) + GetName();
98 node.append_child("D:href").append_child(pugi::node_pcdata).set_value(s.c_str()); 99 node.append_child("D:href").append_child(pugi::node_pcdata).set_value(s.c_str());
99 100
100 pugi::xml_node propstat = node.append_child("D:propstat"); 101 pugi::xml_node propstat = node.append_child("D:propstat");
101 propstat.append_child("D:status").append_child(pugi::node_pcdata). 102
102 set_value("HTTP/1.1 200 OK"); 103 static const HttpStatus status = HttpStatus_200_Ok;
104 s = ("HTTP/1.1 " + boost::lexical_cast<std::string>(status) + " " +
105 std::string(EnumerationToString(status)));
106 propstat.append_child("D:status").append_child(pugi::node_pcdata).set_value(s.c_str());
103 107
104 pugi::xml_node prop = propstat.append_child("D:prop"); 108 pugi::xml_node prop = propstat.append_child("D:prop");
105 109
106 // IMPORTANT: The "Z" suffix is mandatory on Windows >= 7 110 // IMPORTANT: The "Z" suffix is mandatory on Windows >= 7
107 s = boost::posix_time::to_iso_extended_string(GetCreationTime()) + "Z"; 111 s = boost::posix_time::to_iso_extended_string(GetCreationTime()) + "Z";
108 prop.append_child("D:creationdate").append_child(pugi::node_pcdata).set_value(s.c_str()); 112 prop.append_child("D:creationdate").append_child(pugi::node_pcdata).set_value(s.c_str());
109 113
110 s = boost::posix_time::to_iso_extended_string(GetModificationTime()) + "Z"; 114 s = boost::posix_time::to_iso_extended_string(GetModificationTime()) + "Z";
111 prop.append_child("D:getlastmodified").append_child(pugi::node_pcdata).set_value(s.c_str()); 115 prop.append_child("D:getlastmodified").append_child(pugi::node_pcdata).set_value(s.c_str());
112 116
117 #if 0
118 // Maybe used by davfs2
119 prop.append_child("D:quota-available-bytes");
120 prop.append_child("D:quota-used-bytes");
121 #endif
122
113 #if 0 123 #if 0
114 prop.append_child("D:lockdiscovery"); 124 prop.append_child("D:lockdiscovery");
115 pugi::xml_node lock = prop.append_child("D:supportedlock"); 125 pugi::xml_node lock = prop.append_child("D:supportedlock");
116 126
117 pugi::xml_node lockentry = lock.append_child("D:lockentry"); 127 pugi::xml_node lockentry = lock.append_child("D:lockentry");
215 decl.append_attribute("version").set_value("1.0"); 225 decl.append_attribute("version").set_value("1.0");
216 decl.append_attribute("encoding").set_value("UTF-8"); 226 decl.append_attribute("encoding").set_value("UTF-8");
217 227
218 Toolbox::XmlToString(target, doc); 228 Toolbox::XmlToString(target, doc);
219 } 229 }
230
231
232 void IWebDavBucket::AnswerFakedProppatch(HttpOutput& output,
233 const std::string& uri)
234 {
235 /**
236 * This is a fake implementation. The goal is to make happy the
237 * WebDAV clients that set properties (such as Windows >= 7).
238 **/
239
240 pugi::xml_document doc;
241
242 pugi::xml_node root = doc.append_child("D:multistatus");
243 root.append_attribute("xmlns:D").set_value("DAV:");
244
245 pugi::xml_node response = root.append_child("D:response");
246 response.append_child("D:href").append_child(pugi::node_pcdata).set_value(uri.c_str());
247
248 response.append_child("D:propstat");
249
250 pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
251 decl.append_attribute("version").set_value("1.0");
252 decl.append_attribute("encoding").set_value("UTF-8");
253
254 std::string s;
255 Toolbox::XmlToString(s, doc);
256
257 output.AddHeader("Content-Type", "application/xml");
258 output.SendStatus(HttpStatus_207_MultiStatus, s);
259 }
260
261
262 void IWebDavBucket::AnswerFakedLock(HttpOutput& output,
263 const std::string& uri)
264 {
265 /**
266 * This is a fake implementation. No lock is actually
267 * created. The goal is to make happy the WebDAV clients
268 * that use locking (such as Windows >= 7).
269 **/
270
271 pugi::xml_document doc;
272
273 pugi::xml_node root = doc.append_child("D:prop");
274 root.append_attribute("xmlns:D").set_value("DAV:");
275
276 pugi::xml_node activelock = root.append_child("D:lockdiscovery").append_child("D:activelock");
277 activelock.append_child("D:locktype").append_child("D:write");
278 activelock.append_child("D:lockscope").append_child("D:exclusive");
279 activelock.append_child("D:depth").append_child(pugi::node_pcdata).set_value("0");
280 activelock.append_child("D:timeout").append_child(pugi::node_pcdata).set_value("Second-3599");
281
282 activelock.append_child("D:lockroot").append_child("D:href")
283 .append_child(pugi::node_pcdata).set_value(uri.c_str());
284 activelock.append_child("D:owner");
285
286 std::string token = Toolbox::GenerateUuid();
287 boost::erase_all(token, "-");
288 token = "opaquelocktoken:0x" + token;
289
290 activelock.append_child("D:locktoken").append_child("D:href").
291 append_child(pugi::node_pcdata).set_value(token.c_str());
292
293 pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
294 decl.append_attribute("version").set_value("1.0");
295 decl.append_attribute("encoding").set_value("UTF-8");
296
297 std::string s;
298 Toolbox::XmlToString(s, doc);
299
300 output.AddHeader("Lock-Token", token); // Necessary for davfs2
301 output.AddHeader("Content-Type", "application/xml");
302 output.SendStatus(HttpStatus_201_Created, s);
303 }
304
305
306 void IWebDavBucket::AnswerFakedUnlock(HttpOutput& output)
307 {
308 output.SendStatus(HttpStatus_204_NoContent);
309 }
220 } 310 }