Roxen.git / server / base_server / module.pike

version» Context lines:

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.194 2004/05/10 19:11:50 grubba Exp $ + // $Id: module.pike,v 1.195 2004/05/10 19:25:05 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:381:      //! Return the set of properties for @[path].   //!   //! @returns   //! Returns @tt{0@} (zero) if @[path] does not exist.   //!   //! Returns an error mapping if there's some other error accessing   //! the properties.   //!   //! Otherwise returns a @[PropertySet] object. - PropertySet|mapping(string:mixed) query_properties(string path, RequestID id) + PropertySet|mapping(string:mixed) query_property_set(string path, RequestID id)   {    SIMPLE_TRACE_ENTER (this, "Querying properties on %O", path);    Stat st = stat_file(path, id);       if (!st) {    SIMPLE_TRACE_LEAVE ("No such file or dir");    return 0;    }       PropertySet res = DefaultPropertySet(path, query_location()+path, id, st);
Roxen.git/server/base_server/module.pike:405:      //! Returns the value of the specified property, or an error code   //! mapping.   //!   //! @note   //! Returning a string is shorthand for returning an array   //! with a single text node.   string|array(Parser.XML.Tree.SimpleNode)|mapping(string:mixed)    query_property(string path, string prop_name, RequestID id)   { -  mapping(string:mixed)|PropertySet properties = query_properties(path, id); +  mapping(string:mixed)|PropertySet properties = query_property_set(path, id);    if (!properties) {    return Roxen.http_status(Protocols.HTTP.HTTP_NOT_FOUND,    "No such file or directory.");    }    if (mappingp (properties))    return properties;    return properties->query_property(prop_name) ||    Roxen.http_status(Protocols.HTTP.HTTP_NOT_FOUND, "No such property.");   }   
Roxen.git/server/base_server/module.pike:429:    int depth, MultiStatus.Prefixed result,    RequestID id,    multiset(string)|void filt)   {    SIMPLE_TRACE_ENTER (this, "%s for %O, depth %d",    mode == "DAV:propname" ? "Listing property names" :    mode == "DAV:allprop" ? "Retrieving all properties" :    mode == "DAV:prop" ? "Retrieving specific properties" :    "Finding properties with mode " + mode,    path, depth); -  mapping(string:mixed)|PropertySet properties = query_properties(path, id); +  mapping(string:mixed)|PropertySet properties = query_property_set(path, id);       if (!properties) {    SIMPLE_TRACE_LEAVE ("No such file or dir");    return;    }       {    mapping(string:mixed) ret = mappingp (properties) ?    properties : properties->find_properties(mode, result, filt);   
Roxen.git/server/base_server/module.pike:468:       SIMPLE_TRACE_LEAVE ("");    return;   }      mapping(string:mixed) patch_properties(string path,    array(PatchPropertyCommand) instructions,    MultiStatus.Prefixed result, RequestID id)   {    SIMPLE_TRACE_ENTER (this, "Patching properties for %O", path); -  mapping(string:mixed)|PropertySet properties = query_properties(path, id); +  mapping(string:mixed)|PropertySet properties = query_property_set(path, id);       if (!properties) {    SIMPLE_TRACE_LEAVE ("No such file or dir");    return 0;    }    if (mappingp (properties)) { -  SIMPLE_TRACE_LEAVE ("Got error %d from query_properties: %O", +  SIMPLE_TRACE_LEAVE ("Got error %d from query_property_set: %O",    properties->error, properties->rettext);    return properties;    }       mapping(string:mixed) errcode;       if (errcode = write_access(path, 0, id)) {    SIMPLE_TRACE_LEAVE("Patching denied by write_access().");    return errcode;    }
Roxen.git/server/base_server/module.pike:546:      //! Convenience variant of @[patch_properties()] that sets a single   //! property.   //!   //! @returns   //! Returns a mapping on any error, zero otherwise.   mapping(string:mixed) set_property (string path, string prop_name,    string|array(Parser.XML.Tree.SimpleNode) value,    RequestID id)   { -  mapping(string:mixed)|PropertySet properties = query_properties(path, id); +  mapping(string:mixed)|PropertySet properties = query_property_set(path, id);    if (!properties) return Roxen.http_status(Protocols.HTTP.HTTP_NOT_FOUND,    "File not found.");    if (mappingp (properties)) return properties;       mapping(string:mixed) result = properties->start();    if (result) return result;       result = properties->set_property(prop_name, value);    if (result && result->error >= 300) {    properties->unroll();
Roxen.git/server/base_server/module.pike:572:   }      //! Convenience variant of @[patch_properties()] that removes a single   //! property.   //!   //! @returns   //! Returns a mapping on any error, zero otherwise.   mapping(string:mixed) remove_property (string path, string prop_name,    RequestID id)   { -  mapping(string:mixed)|PropertySet properties = query_properties(path, id); +  mapping(string:mixed)|PropertySet properties = query_property_set(path, id);    if (!properties) return Roxen.http_status(Protocols.HTTP.HTTP_NOT_FOUND,    "File not found.");    if (mappingp (properties)) return properties;       mapping(string:mixed) result = properties->start();    if (result) return result;       result = properties->remove_property(prop_name);    if (result && result->error >= 300) {    properties->unroll();
Roxen.git/server/base_server/module.pike:1163:   mapping(string:mixed) recurse_delete_files(string path,    MultiStatus.Prefixed stat,    RequestID id)   {    Stat st = stat_file(path, id);    if (!st) return 0;    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. -  mapping fail; +  mapping(string:mixed) fail;    if (!has_suffix(path, "/")) path += "/";    foreach(find_dir(path, id) || ({}), string fname) {    mapping sub_res = recurse_delete_files(path+fname, stat, id);    // 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 && sub_res->error != 204 && sub_res->error != 424) {    stat->add_status(path+fname, sub_res->error, sub_res->rettext);    if (sub_res->error >= 300) fail = Roxen.http_status(424);    }    }    if (fail) return Roxen.http_status(424);    }    return delete_file(path, id) || Roxen.http_status(204);   }    - mapping make_collection(string path, RequestID id) + mapping(string:mixed) make_collection(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 = "MKCOL";    // FIXME: Logging?    return find_file(path, tmp_id);   }      //! State of the Overwrite header.
Roxen.git/server/base_server/module.pike:1208:    DO_OVERWRITE = 1, //! The Overwrite header is "T".   };      //! State of the DAV:PropertyBehavior for this source.   static enum PropertyBehavior {    PROPERTY_OMIT = -1, //! DAV:omit (Omit if it can't be copied).    PROPERTY_COPY = 0, //! Copy if it can't be kept alive (default).    PROPERTY_ALIVE = 1, //! DAV:keepalive (Live properties must be kept alive).   }    - mapping copy_properties(string source, string destination, + mapping(string:mixed) copy_properties(string source, string destination,    PropertyBehavior behavior, RequestID id)   {    SIMPLE_TRACE_ENTER(this, "copy_properties(%O, %O, %O, %O)",    source, destination, behavior, id); -  PropertySet source_properties = query_properties(source, id); -  PropertySet destination_properties = query_properties(destination, id); +  PropertySet source_properties = query_property_set(source, id); +  PropertySet destination_properties = query_property_set(destination, id);       multiset(string) property_set = source_properties->query_all_properties(); -  mapping res; +  mapping(string:mixed) res;    foreach(property_set; string property_name;) {    SIMPLE_TRACE_ENTER(this, "Copying the property %O.", property_name);    string|array(Parser.XML.Tree.SimpleNode)|mapping(string:mixed) source_val =    source_properties->query_property(property_name);    if (mappingp(source_val)) {    TRACE_LEAVE("Reading of property failed. Skipped.");    continue;    }    string|array(Parser.XML.Tree.SimpleNode)|mapping(string:mixed) dest_val =    destination_properties->query_property(property_name);    if (dest_val == source_val) {    TRACE_LEAVE("Destination already has the correct value.");    continue;    } -  mapping res = +  mapping(string:mixed) subres =    destination_properties->set_property(property_name, source_val);    if (behavior == PROPERTY_OMIT) {    TRACE_LEAVE("Omit verify.");    continue;    } -  if ((behavior == PROPERTY_ALIVE) && (res->error < 300)) { +  if ((behavior == PROPERTY_ALIVE) && (subres->error < 300)) {    // FIXME: Check that if the property was live in source,    // it is still live in destination.    // This is likely already so, since we're in the same module.    } -  if ((res->error < 300) || -  (res->error == Protocols.HTTP.HTTP_CONFLICT)) { +  if ((subres->error < 300) || +  (subres->error == Protocols.HTTP.HTTP_CONFLICT)) {    // Ok, or read-only property.    TRACE_LEAVE("Copy ok or read-only property.");    continue;    } -  if (!res) { +  if (!subres) {    // Copy failed, but attempt to copy the rest.    res = Roxen.http_status(Protocols.HTTP.HTTP_PRECOND_FAILED);    }    TRACE_LEAVE("Copy failed.");    }    TRACE_LEAVE(res?"Failed.":"Ok.");    return res;   }    - mapping copy_collection(string source, string destination, + //! Used by the default @[recurse_copy_files] to copy a collection + //! (aka directory). + mapping(string:mixed) copy_collection(string source, string destination,    PropertyBehavior behavior, Overwrite overwrite,    MultiStatus.Prefixed result, RequestID id)   {    SIMPLE_TRACE_ENTER(this, "copy_collection(%O, %O, %O, %O, %O, %O).",    source, destination, behavior, overwrite, result, id);    Stat st = stat_file(destination, id);    if (st) {    // Destination exists. Check the overwrite header.    switch(overwrite) {    case DO_OVERWRITE:    // RFC 2518 8.8.4    // If a resource exists at the destination, and the Overwrite    // header is "T" then prior to performing the copy the server    // MUST perform a DELETE with "Depth: infinity" on the    // destination resource.    TRACE_ENTER("Destination exists and overwrite is on.", this); -  mapping res = recurse_delete_files(destination, result, id); +  mapping(string:mixed) res = recurse_delete_files(destination, result, id);    if (res && (res->error >= 300)) {    // Failed to delete something.    TRACE_LEAVE("Deletion failed.");    TRACE_LEAVE("Copy collection failed.");    return Roxen.http_status(Protocols.HTTP.HTTP_PRECOND_FAILED);    }    TRACE_LEAVE("Deletion ok.");    break;    case NEVER_OVERWRITE:    TRACE_LEAVE("Destination already exists.");
Roxen.git/server/base_server/module.pike:1301:    if (st->isdir) {    TRACE_LEAVE("Destination exists and is a directory.");    return copy_properties(source, destination, behavior, id);    }    TRACE_LEAVE("Destination exists and is not a directory.");    return Roxen.http_status(Protocols.HTTP.HTTP_PRECOND_FAILED);    }    }    // Create the new collection.    TRACE_LEAVE("Make a new collection."); -  mapping res = make_collection(destination, id); +  mapping(string:mixed) res = make_collection(destination, id);    if (res && res->error >= 300) return res;    return copy_properties(source, destination, behavior, id) || res;   }    - mapping copy_file(string path, string dest, PropertyBehavior behavior, + mapping(string:mixed) copy_file(string path, string dest, PropertyBehavior behavior,    Overwrite overwrite, RequestID id)   {    SIMPLE_TRACE_ENTER(this, "copy_file(%O, %O, %O, %O, %O)\n",    path, dest, behavior, overwrite, id);    TRACE_LEAVE("Not implemented yet.");    return Roxen.http_status (Protocols.HTTP.HTTP_NOT_IMPL);   }    - mapping recurse_copy_files(string source, string destination, int depth, + mapping(string:mixed) recurse_copy_files(string source, string destination, int depth,    mapping(string:PropertyBehavior) behavior,    Overwrite overwrite,    MultiStatus.Prefixed result, RequestID id)   {    SIMPLE_TRACE_ENTER(this, "recurse_copy_files(%O, %O, %O, %O, %O, %O)\n",    source, destination, depth, behavior, result, id);    string src_tmp = has_suffix(source, "/")?source:(source+"/");    string dst_tmp = has_suffix(destination, "/")?destination:(destination+"/");    if ((src_tmp == dst_tmp) ||    has_prefix(src_tmp, dst_tmp) ||
Roxen.git/server/base_server/module.pike:1337:    TRACE_LEAVE("Source and destination overlap.");    return Roxen.http_status(403, "Source and destination overlap.");    }    Stat st = stat_file(source, id);    if (!st) {    TRACE_LEAVE("Source not found.");    return 0; /* FIXME: 404? */    }    // FIXME: Check destination?    if (st->isdir) { -  mapping res = copy_collection(source, destination, -  behavior[query_location()+source] || -  behavior[0], +  mapping(string:mixed) res = +  copy_collection(source, destination, +  behavior[query_location()+source] || behavior[0],    overwrite, result, id);    if (res && (res->error != 204) && (res->error != 201)) {    if (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) { -  mapping sub_res = recurse_copy_files(combine_path(source, filename), +  mapping(string:mixed) sub_res = +  recurse_copy_files(combine_path(source, filename),    combine_path(destination, filename), -  depth, -  behavior, overwrite, result, id); +  depth, behavior, overwrite, result, id);    if (sub_res && (sub_res->error != 204) && (sub_res->error != 201)) {    result->add_status(combine_path(destination, filename),    sub_res->error, sub_res->rettext);    }    }    TRACE_LEAVE("Recursive copy done.");    return res;    } else {    return copy_file(source, destination,    behavior[query_location()+source] ||