Branch: Tag:

2018-03-20

2018-03-20 11:17:02 by Henrik Grubbström (Grubba) <grubba@grubba.org>

WebDAV: Fix several depth header handling issues.

COPY of collections with a depth of 0 now works.

Added some more validation of the depth header.

Fixes [WS-224].

1: - // Protocol support for RFC 2518 + // Protocol support for RFC 2518 and RFC 4918   // - // $Id: webdav.pike,v 1.39 2010/06/28 06:57:48 marty Exp $ + // $Id$   //   // 2003-09-17 Henrik Grubbström   
9:   #include <module.h>   #include <request_trace.h>    - constant cvs_version = "$Id: webdav.pike,v 1.39 2010/06/28 06:57:48 marty Exp $"; + constant cvs_version = "$Id$";   constant thread_safe = 1;   constant module_name = "WebDAV: Protocol support";   constant module_type = MODULE_FIRST;
171:    id->request_headers->depth));    return Roxen.http_status(400, "Unsupported depth.");    } +  switch(id->method) { +  case "DELETE": +  case "MOVE": +  // RFC 4918 9.6.1: +  // The DELETE method on a collection MUST act as if a "Depth: +  // infinity" header was used on it. A client MUST NOT submit a +  // Depth header with a DELETE on a collection with any value but +  // infinity. +  // +  // RFC 4918 9.9.2: +  // The MOVE method on a collection MUST act as if a "Depth: +  // infinity" header was used on it. A client MUST NOT submit a +  // Depth header on a MOVE on a collection with any value but +  // "infinity". +  +  if (depth != 0x7fffffff) { +  TRACE_LEAVE(sprintf("Bad depth header: %O.", +  id->request_headers->depth)); +  return Roxen.http_status(400, "Unsupported depth."); +  } +  break; +  +  case "COPY": +  // RFC 4918 9.8.3: +  // The COPY method on a collection without a Depth header MUST +  // act as if a Depth header with value "infinity" was +  // included. A client may submit a Depth header on a COPY on a +  // collection with a value of "0" or "infinity". Servers MUST +  // support the "0" and "infinity" Depth header behaviors on +  // WebDAV-compliant resources. +  +  if (depth == 1) { +  TRACE_LEAVE(sprintf("Bad depth header: %O.", +  id->request_headers->depth)); +  return Roxen.http_status(400, "Unsupported depth."); +  } +  break; +  }    } else if (id->request_headers->depth) {    // Depth header not supported in this case.    }
478:    }    // Convert destination to module location relative.    destination = destination[sizeof(loc)..]; -  mapping(string:mixed) res = -  ((id->method == "COPY")? -  module->recurse_copy_files: -  module->recurse_move_files) -  (source, destination, behavior, overwrite, id); +  mapping(string:mixed) res; +  if (id->method == "MOVE") { +  res = module->recurse_move_files(source, destination, +  behavior, overwrite, id); +  } else { +  res = module->recurse_copy_files(source, destination, +  behavior, overwrite, id, +  !d); +  }    if (res && ((res->error == 201) || (res->error == 204))) {    empty_result = res;    return 0;
667:    if (has_prefix(href, loc) || (loc == href+"/")) {    // href = loc + path.    path = href[sizeof(loc)..]; -  } else if (d && has_prefix(loc, href_prefix) && -  ((d -= sizeof((loc[sizeof(href_prefix)..])/"/")) >= 0)) { +  } else if (d && has_prefix(loc, href_prefix)) {    // loc = href_prefix + ... -  +  d -= sizeof((loc[sizeof(href_prefix)..])/"/"); +  if (d < 0) continue;    // && recursion.    path = "";    } else {