14
14
* along with this program; if not, write to the Free Software
15
15
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
* $Id: webdav.pike,v 1.1.1.1 2005/02/23 14:47:21 cvs Exp $
20
constant cvs_version="$Id: webdav.pike,v 1.1.1.1 2005/02/23 14:47:21 cvs Exp $";
23
* - PUT method does not return correct response (at least on IE)
24
* - IE asks for overwritting existing file even if file is not present
17
* $Id: webdav.pike,v 1.3 2006/05/17 20:41:49 exodusd Exp $
20
constant cvs_version="$Id: webdav.pike,v 1.3 2006/05/17 20:41:49 exodusd Exp $";
59
void lock(mixed ctx, string fname, mapping lock_data) {
61
ctx->set_attribute(OBJ_LOCK, lock_data);
63
null_ressources[fname] = lock_data | ([ "isnull": 1, ]) ;
65
mapping is_locked(mixed ctx, string fname) {
66
if ( !objectp(ctx) ) {
67
return null_ressources[fname];
69
return ctx->query_attribute(OBJ_LOCK);
55
string url_name(string fname) {
56
return replace_uml(fname);
59
static string generate_token(object ctx) {
63
id = ctx->get_object_id();
65
string token = sprintf("%08x", random(time()));
66
string ttoken = sprintf("%08x", time()) + sprintf("%08x", random(time())) + sprintf("%08x", random(time()));
68
return "opaquelocktoken:" + token + "-" +
69
ttoken[0..3] + "-" + ttoken[4..7] + "-" + ttoken[8..11] + "-" +
73
string lock(mixed ctx, string fname, mapping lock_data) {
76
if ( !lock_data->token ) {
77
token = generate_token(ctx);
78
lock_data->token = token;
81
token = lock_data->token;
84
mapping ldata = ctx->query_attribute(OBJ_LOCK) || ([ ]);
85
ldata[token] = lock_data;
86
ctx->set_attribute(OBJ_LOCK, ldata);
89
mapping ldata = null_ressources[fname];
90
ldata[token] = lock_data;
91
null_ressources[fname] = ldata | ([ "isnull": 1, ]) ;
93
return lock_data->token;
95
void unlock(mixed ctx, string fname, void|string token)
97
if ( !stringp(token) )
98
ctx->set_attribute(OBJ_LOCK, 0);
100
mapping ldata = ctx->query_attribute(OBJ_LOCK);
101
if ( mappingp(ldata) ) {
102
m_delete(ldata, token);
103
ctx->set_attribute(OBJ_LOCK, ldata);
107
mapping get_locks(mixed ctx, string fname) {
109
return null_ressources[fname];
110
return ctx->query_attribute(OBJ_LOCK) || ([ ]);
112
mapping is_locked(mixed ctx, string fname, void|string gottoken) {
115
ldata = null_ressources[fname] || ([ ]);
117
ldata = ctx->query_attribute(OBJ_LOCK) || ([ ]);
118
DAV_WERR("is_locked(%O, %s)", ctx, fname);
120
foreach(indices(ldata), string token) {
121
mapping lockdata = ldata[token];
122
if ( mappingp(lockdata) ) {
124
if ( stringp(lockdata["timeout"]) ) {
125
sscanf(lockdata["timeout"], "Second-%d", timeout);
127
if ( lockdata->locktime > 0 && (time() - lockdata->locktime) < timeout )
129
DAV_WERR("active lock found...");
130
if ( !stringp(gottoken) || lockdata->token == gottoken )
135
if ( objectp(ctx) ) {
136
object env = ctx->get_environment();
137
ldata = is_locked(env, "", gottoken);
138
if ( mappingp(ldata) )
141
if ( !stringp(gottoken) ) {
143
ctx->set_attribute(OBJ_LOCK, 0);
145
null_ressources[fname] = 0;
149
string get_user_href() {
150
return _Server->get_server_name() + "/~" + this_user()->get_user_name();
153
string get_etag(mixed ctx) {
154
return ctx->get_etag();
73
157
object get_object_id() { return _dav->get_object_id(); }
74
158
object this() { return _dav->get_user_object(); }
77
161
static object __webdavHandler;
163
int check_lock(object obj, mapping vars, void|string fname)
165
if ( !objectp(obj) && !stringp(fname) )
167
if ( !stringp(fname) )
169
string token = get_opaquelocktoken(__request->request_headers->if);
170
if ( stringp(token) ) {
171
if ( mappingp(__webdavHandler->is_locked(obj, fname, token)) )
174
mapping res = __webdavHandler->is_locked(obj, fname);
175
DAV_WERR("Checking lock (current token=%O) locked=%O", token, res);
79
179
mapping handle_OPTIONS(object obj, mapping variables)
81
181
mapping result = ::handle_OPTIONS(obj, variables);
82
182
result->extra_heads += ([
83
183
"MS-Author-Via": "DAV",
95
194
mapping handle_LOCK(object obj, mapping variables)
97
return lock(__request->not_query, __request->request_headers,
99
__webdavHandler, obj);
196
if ( this_user() == USER("guest") )
197
return response_noaccess(obj, variables);
198
obj = _fp->path_to_object(__request->not_query, 1);
102
mapping handle_UNLOCK(object obj, mapping variables)
104
return unlock(__request->not_query, __request->request_headers,
200
return lock(__request->not_query, __request->request_headers,
105
201
__request->body_raw,
106
202
__webdavHandler, obj);
205
mapping handle_UNLOCK(object obj, mapping variables)
207
if ( this_user() == USER("guest") )
208
return response_noaccess(obj, variables);
209
obj = _fp->path_to_object(__request->not_query, 1);
211
return unlock(__request->not_query, __request->request_headers,
213
__webdavHandler, obj);
110
217
static bool move_and_rename(object obj, string name)
219
string fname, dname, sname;
221
sname = _Server->get_server_name();
222
sscanf(name, "%*s://" + _Server->get_server_name() + "%s", name);
114
224
if ( name[-1] == '/' )
115
225
name = dirname(name);
149
259
__request->misc["new-uri"] = __request->misc->destination;
150
260
DAV_WERR("Handling move:misc=\n"+sprintf("%O\n", __request->misc));
152
object dest = _fp->path_to_object(__request->misc["new-uri"]);
262
destination = __request->misc["new-uri"];
263
if ( catch(destination = url_to_string(destination)) )
264
FATAL("Failed to convert destination %s", destination);
266
object dest = _fp->path_to_object(destination);
153
267
if ( objectp(dest) ) {
154
268
if ( __request->misc->overwrite == "F" ) {
155
269
DAV_WERR("overwritting failed !");
156
270
return low_answer(412, "Pre-Condition Failed");
273
if ( !check_lock(dest, variables) )
274
return low_answer(423, "Locked");
163
if ( !move_and_rename(obj, __request->misc["new-uri"]) )
279
if ( !move_and_rename(obj, destination) )
164
280
return low_answer(409, "conflict");
165
281
return low_answer(res, "moved");
219
338
// dirname and fname
220
339
if ( !move_and_rename(duplicate, __request->misc->destination) )
221
340
return low_answer(409, "conflict");
341
duplicate->set_attribute(OBJ_LOCK, 0);
222
342
return low_answer(res, "copied");
225
return low_answer(404, "not found");
345
FATAL("Resource could not be found !");
346
return low_answer(404, "not found");
229
350
mapping|void handle_PROPPATCH(object obj, mapping variables)
352
obj = _fp->path_to_object(__request->not_query, 1);
354
if ( !check_lock(obj, variables) )
355
return low_answer(423, "Locked");
231
357
return proppatch(__request->not_query, __request->request_headers,
232
358
__request->body_raw, __webdavHandler, obj);
361
mapping handle_DELETE(object obj, mapping vars)
364
if ( !check_lock(obj, vars) )
365
return low_answer(423, "Locked");
366
return ::handle_DELETE(obj, vars);
369
mapping handle_PUT(object obj, mapping vars)
371
string fname = __request->not_query;
373
obj = _fp->path_to_object(__request->not_query, 1);
376
if ( !check_lock(obj, vars, fname) )
377
return low_answer(423, "Locked");
379
mapping result = ::handle_PUT(obj, vars);
381
mapping locks = __webdavHandler->get_locks(0, fname);
382
if ( mappingp(locks) && sizeof(locks) > 0 ) {
383
// locked null resources
384
object fp = vars->fp;
386
fp = get_module("filepath:tree");
387
obj = fp->path_to_object(fname);
388
if ( objectp(obj) ) {
389
if ( !mappingp(obj->query_attribute(OBJ_LOCK)) )
390
obj->set_attribute(OBJ_LOCK, locks);
395
FATAL("While setting lock for previous null resource: %O", err);
235
400
mapping|void handle_PROPFIND(object obj, mapping variables)
237
werror("handle_PROPFIND("+(objectp(obj) ? obj->describe() : "none")+")\n");
239
return low_answer(404, "not found");
240
return propfind(__request->not_query, __request->request_headers,
241
__request->body_raw, __webdavHandler, obj);
402
isWebDAV = 1; // heuristics ;-)
404
obj = _fp->path_to_object(__request->not_query, 1);
407
return low_answer(404, "not found");
409
return propfind(__request->not_query, __request->request_headers,
410
__request->body_raw, __webdavHandler, obj);
244
413
mixed get_property(object obj, Property property)
246
417
if ( !objectp(property) )
247
418
error("No property found, null-pointer !");
248
419
DAV_WERR("Get property %s, val=%O, ns=%O", property->get_name(),obj->query_attribute(property->get_name()), property->describe_namespace());
249
420
string pname = property->get_ns_name();
251
423
switch( property->get_name() ) {
252
424
case "displayname":