Roxen.git / server / base_server / configuration.pike

version» Context lines:

Roxen.git/server/base_server/configuration.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 1996 - 2001, Roxen IS.   //      // @appears Configuration   //! A site's main configuration    - constant cvs_version = "$Id: configuration.pike,v 1.531 2003/01/21 13:08:14 mast Exp $"; + constant cvs_version = "$Id: configuration.pike,v 1.532 2003/06/02 12:10:29 grubba Exp $";   #include <module.h>   #include <module_constants.h>   #include <roxen.h>   #include <request_trace.h>   #include <timers.h>      #define CATCH(P,X) do{mixed e;if(e=catch{X;})report_error("While "+P+"\n"+describe_backtrace(e));}while(0)      // --- Locale defines ---   //<locale-token project="roxen_start"> LOC_S </locale-token>
Roxen.git/server/base_server/configuration.pike:477: Inside #if defined(THREADS)
   num_modules -= 17;    if (num_modules) modules_stopped->wait (lock);    lock = 0;   #else    if (num_modules != 17)    error ("num_modules shouldn't be nonzero here when running nonthreaded.\n");   #endif    }   }    - string type_from_filename( string file, int|void to, string|void myext ) + string|array(string) type_from_filename( string file, int|void to, +  string|void myext )   {    array(string)|string tmp;    if(!types_fun)    return to?({ "application/octet-stream", 0 }):"application/octet-stream";       string ext = lower_case(myext || Roxen.extension(file));       if(tmp = types_fun(ext))    {    mixed tmp2,nx;
Roxen.git/server/base_server/configuration.pike:1701:    return ([ "file":fid, ]);    }       if(!fid)    TRACE_LEAVE("Returned 'no such file'.");    else    TRACE_LEAVE("Returning data");    return fid;   }    + //! Implements PROPPATCH <DAV:set/>. + class PatchPropertySetCmd + { +  string property_name; +  static string|array(Parser.XML.Tree.Node) value; +  static void create(Parser.XML.Tree.Node prop_node) +  { +  property_name = prop_node->get_full_name(); +  value = prop_node->get_children(); +  +  if ((sizeof(value) == 1) && +  (value[0]->get_node_type() == Parser.XML.Tree.XML_TEXT)) { +  // Special case for a single text node. +  value = value[0]->get_text(); +  } +  } +  +  mapping(string:mixed) execute(string path, RoxenModule module, RequestID id) +  { +  return module->set_property(path, property_name, value, id); +  } + } +  + //! Implements PROPPATCH <DAV:remove/>. + class PatchPropertyRemoveCmd + { +  string property_name; +  static void create(string prop_name) +  { +  property_name = prop_name; +  } +  +  mapping(string:mixed) execute(string path, RoxenModule module, RequestID id) +  { +  return module->remove_property(path, property_name, id); +  } + } +  + //! Handle WEBDAV requests. + mapping|int(-1..0) handle_webdav(RequestID id) + { +  Parser.XML.Tree.Node xml_data; +  TRACE_ENTER("Handle WEBDAV request...", 0); +  if (catch { xml_data = id->get_xml_data(); }) { +  // RFC 2518 8: +  // If a server receives ill-formed XML in a request it MUST reject +  // the entire request with a 400 (Bad Request). +  TRACE_LEAVE("Malformed XML."); +  return Roxen.http_low_answer(400, "Malformed XML data."); +  } +  if (!(<"PROPFIND", "PROPPATCH">)[id->method]) { +  TRACE_LEAVE("Not implemented."); +  return Roxen.http_low_answer(501, "Not implemented."); +  } +  int depth = ([ "0":0, "1":1, "infinity":0x7fffffff, 0:0x7fffffff ]) +  [String.trim_whites(id->request_headers->depth)]; +  if (zero_type(depth)) { +  TRACE_LEAVE(sprintf("Bad depth header: %O.", +  id->request_headers->depth)); +  return Roxen.http_low_answer(400, "Unsupported depth."); +  } +  +  // Function to call for matching location modules. +  // +  // Arguments: +  // string path +  // int d +  // RoxenModule module +  // RequestID id +  // mixed ... extras +  function(string,int,RoxenModule,MultiStatus,RequestID,mixed ...:void) +  recur_func; +  array(mixed) extras = ({}); +  +  switch(id->method) { +  case "PROPFIND": // Get meta data. +  Parser.XML.Tree.Node propfind = +  xml_data->get_first_element("DAV:propfind", 1); +  if (!propfind) { +  return Roxen.http_low_answer(400, "Missing DAV:propfind."); +  } +  /* Valid children of <DAV:propfind> are +  * <DAV:propname /> +  * or +  * <DAV:allprop /> +  * or +  * <DAV:prop>{propertylist}*</DAV:prop> +  */ +  foreach(propfind->get_children(), Parser.XML.Tree.Node prop) { +  switch(prop->get_full_name()) { +  case "DAV:propname": +  if (recur_func) +  return Roxen.http_low_answer(400, "Bad DAV request (23.3.2.1)."); +  recur_func = lambda(string path, int d, RoxenModule module, +  MultiStatus stat, RequestID id) { +  module->recurse_find_properties(path, "DAV:propname", d, +  stat, id); +  }; +  break; +  case "DAV:allprop": +  if (recur_func) +  return Roxen.http_low_answer(400, "Bad DAV request (23.3.2.1)."); +  recur_func = lambda(string path, int d, RoxenModule module, +  MultiStatus stat, RequestID id) { +  module->recurse_find_properties(path, "DAV:allprop", d, +  stat, id); +  }; +  break; +  case "DAV:prop": +  if (recur_func) +  return Roxen.http_low_answer(400, "Bad DAV request (23.3.2.1)."); +  recur_func = lambda(string path, int d, RoxenModule module, +  MultiStatus stat, RequestID id, +  multiset(string) filt) { +  module->recurse_find_properties(path, "DAV:prop", d, +  stat, id, filt); +  }; +  extras = ({ (multiset)(prop->get_children()->get_full_name()) }); +  break; +  default: +  break; +  } +  } +  break; +  case "PROPPATCH": // Set/delete meta data. +  Parser.XML.Tree.Node propupdate = +  xml_data->get_first_element("DAV:propertyupdate", 1); +  if (!propupdate) { +  return Roxen.http_low_answer(400, "Missing DAV:propertyupdate."); +  } +  /* Valid children of <DAV:propertyupdate> are any combinations of +  * <DAV:set><DAV:prop>{propertylist}*</DAV:prop></DAV:set> +  * and +  * <DAV:remove><DAV:prop>{propertylist}*</DAV:prop></DAV:remove> +  * +  * RFC 2518 8.2: +  * Instruction processing MUST occur in the order instructions +  * are received (i.e., from top to bottom). +  */ +  array(PatchPropertyCommand) instructions = ({}); +  foreach(propupdate->get_children(), Parser.XML.Tree.Node cmd) { +  switch(cmd->get_full_name()) { +  case "DAV:set": +  case "DAV:remove": +  Parser.XML.Tree.Node prop = +  cmd->get_first_element("DAV:prop", 1); +  if (!prop) { +  TRACE_LEAVE("Bad DAV request."); +  return Roxen.http_low_answer(400, "Bad DAV request (no properties specified)."); +  } +  if (cmd->get_full_name() == "DAV:set") { +  instructions += map(prop->get_children(), PatchPropertySetCmd); +  } else { +  instructions += map(prop->get_children()->get_full_name(), +  PatchPropertyRemoveCmd); +  } +  break; +  default: +  // FIXME: Should we complain here? +  break; +  } +  } +  if (!sizeof(instructions)) { +  TRACE_LEAVE("Bad DAV request."); +  return Roxen.http_low_answer(400, "Bad DAV request (23.3.2.2)."); +  } +  recur_func = lambda(string path, int d, RoxenModule module, +  MultiStatus stat, RequestID id, +  array(PatchPropertyCommand) instructions) { +  module->recurse_patch_properties(path, d, instructions, +  stat, id); +  }; +  extras = ({ instructions }); +  break; +  default: +  break; +  } +  if (!recur_func) { +  TRACE_LEAVE("Bad DAV request."); +  return Roxen.http_low_answer(400, "Bad DAV request (23.3.2.2)."); +  } +  // FIXME: Security, DoS, etc... +  MultiStatus result = MultiStatus(); +  string href = id->not_query; +  string href_prefix = combine_path(href, "./"); +  foreach(location_modules(), [string loc, function fun]) { +  int d = depth; +  string path; +  TRACE_ENTER(sprintf("Trying module mounted at %O...", loc), +  function_object(fun)); +  if (has_prefix(href, loc)) { +  // href = loc + path. +  path = href[sizeof(loc)..]; +  } else if (d && has_prefix(loc, href_prefix) && +  ((d -= sizeof(loc[sizeof(href_prefix)..]/"/")) >= 0)) { +  // loc = href_path + ... +  // && recursion. +  path = ""; +  } else { +  TRACE_LEAVE("Miss"); +  continue; +  } + #ifdef MODULE_LEVEL_SECURITY +  if(check_security(fun, id)) { +  TRACE_LEAVE("Not allowed."); +  continue; +  } + #endif +  RoxenModule c = function_object(fun); +  TRACE_ENTER("Performing the work...", c); +  recur_func(path, d, c, result->prefix(loc), id, @extras); +  TRACE_LEAVE("Done."); +  TRACE_LEAVE("Done."); +  } +  TRACE_LEAVE("DAV request done."); +  return result->http_answer(); + } +    mixed handle_request( RequestID id )   {    function funp;    mixed file;    REQUEST_WERR("handle_request()");    TIMER_START(handle_request);    TIMER_START(first_modules);    foreach(first_module_cache||first_modules(), funp)    {    if(file = funp( id ))
Roxen.git/server/base_server/configuration.pike:1751:   //! wrapper for <ref>low_get_file()</ref>.   {    TIMER_START(get_file);    int orig_internal_get = id->misc->internal_get;    id->misc->internal_get = internal_get;    RequestID root_id = id->root_id || id;    root_id->misc->_request_depth++;    if(sub_req_limit && root_id->misc->_request_depth > sub_req_limit)    error("Subrequest limit reached. (Possibly an insertion loop.)");    +  if ((< "PROPFIND", "PROPPATCH" >)[id->method] +  /* && (id->request_headers->depth != "0") */) { +  // These need to be special cased, since they are recursive. +  return handle_webdav(id); +  } +     mapping|int res;    mapping res2;    function tmp;    res = low_get_file(id, no_magic);    TIMER_END(get_file);       // finally map all filter type modules.    // Filter modules are like TYPE_LAST modules, but they get called    // for _all_ files.    TIMER_START(filter_modules);