Roxen.git
/
server
/
base_server
/
module.pike
version
»
Context lines:
10
20
40
80
file
none
3
Roxen.git/server/base_server/module.pike:1:
// This file is part of Roxen WebServer. // Copyright © 1996 - 2001, Roxen IS.
-
// $Id: module.pike,v 1.
200
2004/05/12
16
:
12
:
24
mast Exp $
+
// $Id: module.pike,v 1.
201
2004/05/12
19
:
56
:
46
mast Exp $
#include <module_constants.h> #include <module.h> #include <request_trace.h> constant __pragma_save_parent__ = 1; inherit "basic_defvar"; mapping(string:array(int)) error_log=([]);
Roxen.git/server/base_server/module.pike:269:
//! for the given path. This is used for recursive operations that can //! yield different results for different encountered files or //! directories. //! //! The status is stored in the @[MultiStatus] object returned by //! @[id->get_multi_status]. The server will use it to make a 207 //! Multi-Status response iff the module returns an empty mapping as //! response. //! //! @param path
-
//! Path below the filesystem location to which the status applies.
+
//! Path
(
below the filesystem location
)
to which the status applies.
//! //! @param status_code //! The HTTP status code. //! //! @param message //! If given, it's a message to include in the response. The //! message may contain line feeds ('\n') and ISO-8859-1 //! characters in the ranges 32..126 and 128..255. Line feeds are //! converted to spaces if the response format doesn't allow them. //!
Roxen.git/server/base_server/module.pike:518:
int any_failed; foreach(results, mapping(string:mixed) answer) { if (any_failed = (answer && (answer->error >= 300))) { break; } } if (any_failed) { // Unroll and fail any succeeded items. int i; mapping(string:mixed) answer =
-
Roxen.http_status (Protocols.HTTP.DAV_FAILED_DEP
, "Failed dependency."
);
+
Roxen.http_status (Protocols.HTTP.DAV_FAILED_DEP);
for(i = 0; i < sizeof(results); i++) { if (!results[i] || results[i]->error < 300) { result->add_property("", instructions[i]->property_name, answer); } else { result->add_property("", instructions[i]->property_name, results[i]); } } properties->unroll();
Roxen.git/server/base_server/module.pike:890:
//! there is no other lock already that conflicts with this one, i.e. //! that @code{check_locks(path,lock->recursive,id)@} would return //! @expr{LOCK_NONE@} if @expr{lock->lockscope@} is //! @expr{"DAV:exclusive"@}, or @expr{< LOCK_OWN_BELOW@} if //! @expr{lock->lockscope@} is @expr{"DAV:shared"@}. //! //! This function is only provided as a helper to call from //! @[lock_file] if the default lock implementation is to be used. //! //! @param path
-
//! Normalized path below the filesystem location that the lock
+
//! Normalized path
(
below the filesystem location
)
that the lock
//! applies to. //! //! @param lock //! The lock to register. //! //! @note //! The default implementation only handles the @expr{"DAV:write"@} //! lock type. It uses @[resource_id] to map paths to unique resources //! and @[authenticated_user_id] to tell users apart. static void register_lock(string path, DAVLock lock, RequestID id)
Roxen.git/server/base_server/module.pike:948:
//! obtaining an exclusive lock. A resource that doesn't exist can be //! locked, provided the directory it would be in exists (relaxed in //! RFC 2518Bis (working draft)). //! //! It's up to @[find_file] et al to actually check that the necessary //! locks are held. It can preferably use @[write_access] for that, //! which has a default implementation for checking //! @expr{"DAV:write"@} locks. //! //! @param path
-
//! Normalized path below the filesystem location that the lock
+
//! Normalized path
(
below the filesystem location
)
that the lock
//! applies to. //! //! @param lock //! The lock to register. //! //! @returns //! Returns @expr{0@} if the lock is successfully installed or if //! locking isn't used. Returns a status mapping if an error //! occurred. mapping(string:mixed) lock_file(string path, DAVLock lock, RequestID id) { return 0; } //! Remove @[lock] that currently is locking the resource at @[path]. //! //! @param path
-
//! Normalized path below the filesystem location that the lock
+
//! Normalized path
(
below the filesystem location
)
that the lock
//! applies to. //! //! @param lock //! The lock to unregister. (It must not be changed or destructed.) //! //! @returns //! Returns a status mapping on any error, zero otherwise. mapping(string:mixed) unlock_file (string path, DAVLock lock, RequestID id)
Roxen.git/server/base_server/module.pike:1005:
ASSERT_IF_DEBUG (lock /*%O*/ == removed_lock /*%O*/, lock, removed_lock); TRACE_LEAVE("Ok."); return 0; } //! Checks that the conditions specified by the WebDAV @expr{"If"@} //! header are fulfilled on the given path (RFC 2518 9.4). This means //! that locks are checked as necessary using @[check_locks]. //! //! @param path
-
//! Path below the filesystem location that the lock applies to.
+
//! Path
(
below the filesystem location
)
that the lock applies to.
//! //! @param recursive //! If @expr{1@} also check write access recursively under @[path]. //! //! @returns //! Returns @expr{0@} (zero) on success, a status mapping on //! failure, or @expr{1@} if @[recursive] is set and write access is //! allowed on this level but maybe not somewhere below. The caller //! should in the last case do the operation on this level if //! possible and then handle each member in the directory
Roxen.git/server/base_server/module.pike:1148:
{ return check_if_header (relative_path, recursive, id); } mapping(string:mixed)|int(-1..0)|Stdio.File find_file(string path, RequestID id); //! Delete the file specified by @[path]. //! //! It's unspecified if it works recursively or not, but if it does
-
//! then it has to check DAV locks
through @[write_access]
-
//!
recursively.
+
//! then it has to check DAV locks recursively.
//! //! @returns //! Returns a 204 status on success, 0 if the file doesn't exist, or //! an appropriate status mapping for any other error. //! //! @note //! The default implementation falls back to @[find_file()]. mapping(string:mixed) delete_file(string path, RequestID id) { // Fall back to find_file(). RequestID tmp_id = id->clone_me(); tmp_id->not_query = query_location() + path; tmp_id->method = "DELETE"; // FIXME: Logging? return find_file(path, tmp_id) ||
-
Roxen.http_status(tmp_id->misc->error_code
|| 404
);
+
tmp_id->misc->error_code &&
Roxen.http_status
(tmp_id->misc->error_code);
} //! Delete @[path] recursively.
-
+
//!
+
//! The default implementation handles the recursion and calls
+
//! @[delete_file] for each file and empty directory.
+
//!
//! @returns
-
//! Returns @expr{0@} (zero) on file not found.
-
//!
Returns
@[Roxen.http_status(204)] on success.
-
//!
Returns other result mappings on failure.
+
//! Returns @expr{0@} (zero) on file not found.
Returns
+
//! @[Roxen.http_status(204)] on success.
Returns other result
+
//! mappings on failure.
That includes an empty mapping in case some
+
//! subparts couldn't be deleted, to signify a 207 Multi-Status
+
//! response using the info in @[id->get_multi_status()].
mapping(string:mixed) recurse_delete_files(string path, RequestID id, void|MultiStatus.Prefixed stat) { SIMPLE_TRACE_ENTER (this, "Deleting %O recursively", path); if (!stat) id->get_multi_status()->prefix (id->url_base() + query_location()[1..]); Stat st = stat_file(path, id); if (!st) {
Roxen.git/server/base_server/module.pike:1200:
if (st->isdir) { // RFC 2518 8.6.2 // The DELETE operation on a collection MUST act as if a // "Depth: infinity" header was used on it. int fail; if (!has_suffix(path, "/")) path += "/"; foreach(find_dir(path, id) || ({}), string fname) { fname = path + fname; if (Stat sub_stat = stat_file (fname, id)) {
-
SIMPLE_TRACE_ENTER (this, "Deleting %O
recursively
", fname);
+
SIMPLE_TRACE_ENTER (this, "Deleting %O", fname);
if (mapping(string:mixed) sub_res = recurse(fname, sub_stat)) { // RFC 2518 8.6.2
-
// 424 (Failed Dependancy) errors SHOULD NOT be in the
-
// 207 (Multi-Status).
-
//
+
// Additionally 204 (No Content) errors SHOULD NOT be returned // in the 207 (Multi-Status). The reason for this prohibition // is that 204 (No Content) is the default success code.
-
if (sub_res
->error
!= 204
&& sub_res->error !=
424
) {
+
if (
sizeof (
sub_res
)
&& sub_res->error !=
204
) {
stat->add_status(fname, sub_res->error, sub_res->rettext); } if (sub_res->error >= 300) fail = 1; } } } if (fail) { SIMPLE_TRACE_LEAVE ("Partial failure");
-
return
Roxen.http_status
(
424
);
+
return (
[]
);
} } SIMPLE_TRACE_LEAVE (""); return delete_file (path, id); }; return recurse(path, st) || Roxen.http_status(204); }
Roxen.git/server/base_server/module.pike:1348:
if (res && res->error >= 300) return res; return copy_properties(source, destination, behavior, id) || res; } mapping(string:mixed) copy_file(string source, string destination, PropertyBehavior behavior, Overwrite overwrite, RequestID id) { SIMPLE_TRACE_ENTER(this, "copy_file(%O, %O, %O, %O, %O)\n", source, destination, behavior, overwrite, id);
-
TRACE_LEAVE("Not implemented
yet
.");
+
TRACE_LEAVE("Not implemented.");
return Roxen.http_status (Protocols.HTTP.HTTP_NOT_IMPL); } mapping(string:mixed) recurse_copy_files(string source, string destination, int depth, mapping(string:PropertyBehavior) behavior, Overwrite overwrite, RequestID id) { SIMPLE_TRACE_ENTER(this, "recurse_copy_files(%O, %O, %O, %O, %O)\n", source, destination, depth, behavior, id); string src_tmp = has_suffix(source, "/")?source:(source+"/");
Roxen.git/server/base_server/module.pike:1385:
if (!st) { TRACE_LEAVE("Source not found."); return 0; /* FIXME: 404? */ } // FIXME: Check destination? if (st->isdir) { mapping(string:mixed) res = copy_collection(source, destination, behavior[loc+source] || behavior[0], overwrite, result, id);
-
if (res &&
(
res->error
!= 204) && (res-
>
error !
=
201)) {
-
if (res->error >=
300) {
+
if (res && res->error >= 300) {
// RFC 2518 8.8.3 and 8.8.8 (error minimization). TRACE_LEAVE("Copy of collection failed."); return res; }
-
result->add_status(destination, res->error, res->rettext);
-
}
+
if (depth <= 0) { TRACE_LEAVE("Non-recursive copy of collection done."); return res; } depth--; foreach(find_dir(source, id), string filename) { string subsrc = combine_path_unix(source, filename); string subdst = combine_path_unix(destination, filename); SIMPLE_TRACE_ENTER(this, "Recursive copy from %O to %O, depth %O\n", subsrc, subdst, depth); mapping(string:mixed) sub_res = recurse(subsrc, subdst, depth); if (sub_res && (sub_res->error != 204) && (sub_res->error != 201)) {
-
result->add_status(
combine_path_unix(destination
,
filename),
-
sub_res->error, sub_res->rettext);
+
result->add_status(
subdst
, sub_res->error, sub_res->rettext);
} } TRACE_LEAVE(""); return res; } else { TRACE_LEAVE(""); return copy_file(source, destination, behavior[query_location()+source] || behavior[0], overwrite, id); } };
-
return
recurse (source, destination, depth);
+
int
start_ms_size = id->multi_status_size();
+
mapping(string:mixed) res =
recurse (source, destination, depth);
+
if (res && res->error != 204 && res->error != 201)
+
return res;
+
else if (id->multi_status_size() != start_ms_size)
+
return ([]);
+
else
+
return res;
} string real_file(string f, RequestID id){} void add_api_function( string name, function f, void|array(string) types) { _api_functions[name] = ({ f, types }); } mapping api_functions()