ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
HTTP_WebDAV_Server Class Reference
+ Inheritance diagram for HTTP_WebDAV_Server:
+ Collaboration diagram for HTTP_WebDAV_Server:

Public Member Functions

 serveRequest ()
 Serve WebDAV HTTP request. More...
 
 http_OPTIONS ()
 GET implementation. More...
 
 http_PROPFIND ()
 PROPFIND method handler. More...
 
 http_PROPPATCH ()
 PROPPATCH method handler. More...
 
 http_MKCOL ()
 MKCOL method handler. More...
 
 http_GET ()
 GET method handler. More...
 
 _get_ranges (&$options)
 parse HTTP Range: header More...
 
 _multipart_byterange_header ($mimetype=false, $from=false, $to=false, $total=false)
 generate separator headers for multipart response More...
 
 http_HEAD ()
 HEAD method handler. More...
 
 http_PUT ()
 PUT method handler. More...
 
 http_DELETE ()
 DELETE method handler. More...
 
 http_COPY ()
 COPY method handler. More...
 
 http_MOVE ()
 MOVE method handler. More...
 
 http_LOCK ()
 LOCK method handler. More...
 
 http_UNLOCK ()
 UNLOCK method handler. More...
 
 _copymove ($what)
 
 _allow ()
 check for implemented HTTP methods More...
 
 mkprop ()
 helper for property element creation More...
 
 _check_auth ()
 check authentication if check is implemented More...
 
 _new_uuid ()
 generate Unique Universal IDentifier for lock token More...
 
 _new_locktoken ()
 create a new opaque lock token as defined in RFC2518 More...
 
 _if_header_lexer ($string, &$pos)
 
 _if_header_parser ($str)
 parse If: header More...
 
 _check_if_header_conditions ()
 check if conditions from "If:" headers are meat More...
 
 _check_uri_condition ($uri, $condition)
 Check a single URI condition parsed from an if-header. More...
 
 _check_lock_status ($path, $exclusive_only=false)
 
 lockdiscovery ($path)
 Generate lockdiscovery reply from checklock() result. More...
 
 http_status ($status)
 set HTTP return status and mirror it in a private header More...
 
 _urlencode ($url)
 private minimalistic version of PHP urlencode() More...
 
 _urldecode ($path)
 private version of PHP urldecode More...
 
 _prop_encode ($text)
 UTF-8 encode property values if not already done so. More...
 
 _slashify ($path)
 Slashify - make sure path ends in a slash. More...
 

Data Fields

 $uri
 
 $base_uri
 
 $path
 
 $http_auth_realm = "PHP WebDAV"
 
 $dav_powered_by = ""
 
 $_if_header_uris = array()
 
 $_http_status = "200 OK"
 
 $_prop_encoding = "utf-8"
 

Private Member Functions

 __construct ()
 Constructor. More...
 
 writelog ($message)
 Writes a message to the logfile.,. More...
 

Detailed Description

Definition at line 37 of file Server.php.

Constructor & Destructor Documentation

◆ __construct()

HTTP_WebDAV_Server::__construct ( )
private

Constructor.

Parameters
void

Definition at line 108 of file Server.php.

109  {
110  // PHP messages destroy XML output -> switch them off
111  //ini_set("display_errors", 0);
112  }

Member Function Documentation

◆ _allow()

HTTP_WebDAV_Server::_allow ( )

check for implemented HTTP methods

Parameters
void
Returns
array something

Definition at line 1511 of file Server.php.

References array.

Referenced by http_OPTIONS(), and serveRequest().

1512  {
1513  // OPTIONS is always there
1514  $allow = array("OPTIONS" =>"OPTIONS");
1515 
1516  // all other METHODS need both a http_method() wrapper
1517  // and a method() implementation
1518  // the base class supplies wrappers only
1519  foreach(get_class_methods($this) as $method) {
1520  if (!strncmp("http_", $method, 5)) {
1521  $method = strtoupper(substr($method, 5));
1522  if (method_exists($this, $method)) {
1523  $allow[$method] = $method;
1524  }
1525  }
1526  }
1527 
1528  // we can emulate a missing HEAD implemetation using GET
1529  if (isset($allow["GET"]))
1530  $allow["HEAD"] = "HEAD";
1531 
1532  // no LOCK without checklok()
1533  if (!method_exists($this, "checklock")) {
1534  unset($allow["LOCK"]);
1535  unset($allow["UNLOCK"]);
1536  }
1537 
1538  return $allow;
1539  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ _check_auth()

HTTP_WebDAV_Server::_check_auth ( )

check authentication if check is implemented

Parameters
void
Returns
bool true if authentication succeded or not necessary

Definition at line 1573 of file Server.php.

References $_SERVER.

Referenced by serveRequest().

1574  {
1575  if (method_exists($this, "checkAuth")) {
1576  // PEAR style method name
1577  return $this->checkAuth(@$_SERVER["AUTH_TYPE"],
1578  @$_SERVER["PHP_AUTH_USER"],
1579  @$_SERVER["PHP_AUTH_PW"]);
1580  } else if (method_exists($this, "check_auth")) {
1581  // old (pre 1.0) method name
1582  return $this->check_auth(@$_SERVER["AUTH_TYPE"],
1583  @$_SERVER["PHP_AUTH_USER"],
1584  @$_SERVER["PHP_AUTH_PW"]);
1585  } else {
1586  // no method found -> no authentication required
1587  return true;
1588  }
1589  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
+ Here is the caller graph for this function:

◆ _check_if_header_conditions()

HTTP_WebDAV_Server::_check_if_header_conditions ( )

check if conditions from "If:" headers are meat

the "If:" header is an extension to HTTP/1.1 defined in RFC 2518 section 9.4

Parameters
void
Returns
void

Definition at line 1786 of file Server.php.

References $_SERVER, $uri, _check_uri_condition(), and _if_header_parser().

Referenced by serveRequest().

1787  {
1788  if (isset($_SERVER["HTTP_IF"])) {
1789  $this->_if_header_uris =
1790  $this->_if_header_parser($_SERVER["HTTP_IF"]);
1791 
1792  foreach($this->_if_header_uris as $uri => $conditions) {
1793  if ($uri == "") {
1794  $uri = $this->uri;
1795  }
1796  // all must match
1797  $state = true;
1798  foreach($conditions as $condition) {
1799  // lock tokens may be free form (RFC2518 6.3)
1800  // but if opaquelocktokens are used (RFC2518 6.4)
1801  // we have to check the format (litmus tests this)
1802  if (!strncmp($condition, "<opaquelocktoken:", strlen("<opaquelocktoken"))) {
1803  if (!preg_match("/^<opaquelocktoken:[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}>$/", $condition)) {
1804  return false;
1805  }
1806  }
1807  if (!$this->_check_uri_condition($uri, $condition)) {
1808  $state = false;
1809  break;
1810  }
1811  }
1812 
1813  // any match is ok
1814  if ($state == true) {
1815  return true;
1816  }
1817  }
1818  return false;
1819  }
1820  return true;
1821  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
_if_header_parser($str)
parse If: header
Definition: Server.php:1701
_check_uri_condition($uri, $condition)
Check a single URI condition parsed from an if-header.
Definition: Server.php:1833
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _check_lock_status()

HTTP_WebDAV_Server::_check_lock_status (   $path,
  $exclusive_only = false 
)
Parameters
stringpath of resource to check
boolexclusive lock?

Definition at line 1847 of file Server.php.

References $_SERVER.

Referenced by _copymove(), http_DELETE(), http_LOCK(), http_MOVE(), http_PROPPATCH(), and http_PUT().

1848  {
1849  // FIXME depth -> ignored for now
1850  if (method_exists($this, "checkLock")) {
1851  // is locked?
1852  $lock = $this->checkLock($path);
1853 
1854  // ... and lock is not owned?
1855  if (is_array($lock) && count($lock)) {
1856  // FIXME doesn't check uri restrictions yet
1857  if (!strstr($_SERVER["HTTP_IF"], $lock["token"])) {
1858  if (!$exclusive_only || ($lock["scope"] !== "shared"))
1859  return false;
1860  }
1861  }
1862  }
1863  return true;
1864  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
+ Here is the caller graph for this function:

◆ _check_uri_condition()

HTTP_WebDAV_Server::_check_uri_condition (   $uri,
  $condition 
)

Check a single URI condition parsed from an if-header.

Check a single URI condition parsed from an if-header

Parameters
string$uriURI to check
string$conditionCondition to check for this URI
Returns
bool Condition check result

Definition at line 1833 of file Server.php.

Referenced by _check_if_header_conditions().

1834  {
1835  // not really implemented here,
1836  // implementations must override
1837  return true;
1838  }
+ Here is the caller graph for this function:

◆ _copymove()

HTTP_WebDAV_Server::_copymove (   $what)

Definition at line 1448 of file Server.php.

References $_SERVER, $options, $path, _check_lock_status(), _urldecode(), and http_status().

Referenced by http_COPY(), and http_MOVE().

1449  {
1450  //$this->writelog('_copymove('.$what.')');
1451  $options = Array();
1452  $options["path"] = $this->path;
1453 
1454  if (isset($_SERVER["HTTP_DEPTH"])) {
1455  $options["depth"] = $_SERVER["HTTP_DEPTH"];
1456  } else {
1457  $options["depth"] = "infinity";
1458  }
1459 //$this->writelog('_copymove dest='.$_SERVER["HTTP_DESTINATION"]);
1460  extract(parse_url($_SERVER["HTTP_DESTINATION"]));
1461  // BEGIN WebDAV: decode path (bereits in PEAR CVS gefixt)
1462  // We must decode the target path too.
1463  $path = $this->_urldecode($path);
1464  // END Patch WebDAV: decode path
1465  $http_host = $host;
1466  if (isset($port) && $port != 80)
1467  $http_host.= ":$port";
1468 
1469  list($http_header_host,$http_header_port) = explode(":",$_SERVER["HTTP_HOST"]);
1470  if (isset($http_header_port) && $http_header_port != 80) {
1471  $http_header_host .= ":".$http_header_port;
1472  }
1473 
1474  if ($http_host == $http_header_host &&
1475  !strncmp($_SERVER["SCRIPT_NAME"], $path,
1476  strlen($_SERVER["SCRIPT_NAME"]))) {
1477  $options["dest"] = substr($path, strlen($_SERVER["SCRIPT_NAME"]));
1478  //$this->writelog('_copymove() dest='.$options['dest']);
1479  if (!$this->_check_lock_status($options["dest"])) {
1480  //$this->writelog('_copymove():423 Locked');
1481  $this->http_status("423 Locked");
1482  return;
1483  }
1484  //$this->writelog('_copymove() ...');
1485 
1486  } else {
1487  $options["dest_url"] = $_SERVER["HTTP_DESTINATION"];
1488  }
1489 
1490  // see RFC 2518 Sections 9.6, 8.8.4 and 8.9.3
1491  if (isset($_SERVER["HTTP_OVERWRITE"])) {
1492  $options["overwrite"] = $_SERVER["HTTP_OVERWRITE"] == "T";
1493  } else {
1494  $options["overwrite"] = true;
1495  }
1496 
1497  $stat = $this->$what($options);
1498  $this->http_status($stat);
1499  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
_urldecode($path)
private version of PHP urldecode
Definition: Server.php:1966
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
if(!is_array($argv)) $options
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _get_ranges()

HTTP_WebDAV_Server::_get_ranges ( $options)

parse HTTP Range: header

Parameters
arrayoptions array to store result in
Returns
void

Definition at line 986 of file Server.php.

References $_SERVER, $options, $start, and array.

Referenced by http_GET().

987  {
988  // process Range: header if present
989  if (isset($_SERVER['HTTP_RANGE'])) {
990 
991  // we only support standard "bytes" range specifications for now
992  if (preg_match("/bytes[[:space:]]*=[[:space:]]*(.+)/", $_SERVER['HTTP_RANGE'], $matches)) {
993  $options["ranges"] = array();
994 
995  // ranges are comma separated
996  foreach (explode(",", $matches[1]) as $range) {
997  // ranges are either from-to pairs or just end positions
998  list($start, $end) = explode("-", $range);
999  $options["ranges"][] = ($start==="")
1000  ? array("last"=>$end)
1001  : array("start"=>$start, "end"=>$end);
1002  }
1003  }
1004  }
1005  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
if(!is_array($argv)) $options
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ _if_header_lexer()

HTTP_WebDAV_Server::_if_header_lexer (   $string,
$pos 
)
Parameters
stringheader string to parse
intcurrent parsing position
Returns
array next token (type and value)

Definition at line 1647 of file Server.php.

References array.

Referenced by _if_header_parser().

1648  {
1649  // skip whitespace
1650  while (ctype_space($string{$pos})) {
1651  ++$pos;
1652  }
1653 
1654  // already at end of string?
1655  if (strlen($string) <= $pos) {
1656  return false;
1657  }
1658 
1659  // get next character
1660  $c = $string{$pos++};
1661 
1662  // now it depends on what we found
1663  switch ($c) {
1664  case "<":
1665  // URIs are enclosed in <...>
1666  $pos2 = strpos($string, ">", $pos);
1667  $uri = substr($string, $pos, $pos2 - $pos);
1668  $pos = $pos2 + 1;
1669  return array("URI", $uri);
1670 
1671  case "[":
1672  //Etags are enclosed in [...]
1673  if ($string{$pos} == "W") {
1674  $type = "ETAG_WEAK";
1675  $pos += 2;
1676  } else {
1677  $type = "ETAG_STRONG";
1678  }
1679  $pos2 = strpos($string, "]", $pos);
1680  $etag = substr($string, $pos + 1, $pos2 - $pos - 2);
1681  $pos = $pos2 + 1;
1682  return array($type, $etag);
1683 
1684  case "N":
1685  // "N" indicates negation
1686  $pos += 2;
1687  return array("NOT", "Not");
1688 
1689  default:
1690  // anything else is passed verbatim char by char
1691  return array("CHAR", $c);
1692  }
1693  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ _if_header_parser()

HTTP_WebDAV_Server::_if_header_parser (   $str)

parse If: header

Parameters
stringheader string
Returns
array URIs and their conditions

Definition at line 1701 of file Server.php.

References $uri, _if_header_lexer(), and array.

Referenced by _check_if_header_conditions().

1702  {
1703  $pos = 0;
1704  $len = strlen($str);
1705 
1706  $uris = array();
1707 
1708  // parser loop
1709  while ($pos < $len) {
1710  // get next token
1711  $token = $this->_if_header_lexer($str, $pos);
1712 
1713  // check for URI
1714  if ($token[0] == "URI") {
1715  $uri = $token[1]; // remember URI
1716  $token = $this->_if_header_lexer($str, $pos); // get next token
1717  } else {
1718  $uri = "";
1719  }
1720 
1721  // sanity check
1722  if ($token[0] != "CHAR" || $token[1] != "(") {
1723  return false;
1724  }
1725 
1726  $list = array();
1727  $level = 1;
1728  $not = "";
1729  while ($level) {
1730  $token = $this->_if_header_lexer($str, $pos);
1731  if ($token[0] == "NOT") {
1732  $not = "!";
1733  continue;
1734  }
1735  switch ($token[0]) {
1736  case "CHAR":
1737  switch ($token[1]) {
1738  case "(":
1739  $level++;
1740  break;
1741  case ")":
1742  $level--;
1743  break;
1744  default:
1745  return false;
1746  }
1747  break;
1748 
1749  case "URI":
1750  $list[] = $not."<$token[1]>";
1751  break;
1752 
1753  case "ETAG_WEAK":
1754  $list[] = $not."[W/'$token[1]']>";
1755  break;
1756 
1757  case "ETAG_STRONG":
1758  $list[] = $not."['$token[1]']>";
1759  break;
1760 
1761  default:
1762  return false;
1763  }
1764  $not = "";
1765  }
1766 
1767  if (@is_array($uris[$uri])) {
1768  $uris[$uri] = array_merge($uris[$uri],$list);
1769  } else {
1770  $uris[$uri] = $list;
1771  }
1772  }
1773 
1774  return $uris;
1775  }
_if_header_lexer($string, &$pos)
Definition: Server.php:1647
Create styles array
The data for the language used.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ _multipart_byterange_header()

HTTP_WebDAV_Server::_multipart_byterange_header (   $mimetype = false,
  $from = false,
  $to = false,
  $total = false 
)

generate separator headers for multipart response

first and last call happen without parameters to generate the initial header and closing sequence, all calls inbetween require content mimetype, start and end byte position and optionaly the total byte length of the requested resource

Parameters
stringmimetype
intstart byte position
intend byte position
inttotal resource byte size

Definition at line 1020 of file Server.php.

References $total, and header.

Referenced by http_GET().

1021  {
1022  if ($mimetype === false) {
1023  if (!isset($this->multipart_separator)) {
1024  // initial
1025 
1026  // a little naive, this sequence *might* be part of the content
1027  // but it's really not likely and rather expensive to check
1028  $this->multipart_separator = "SEPARATOR_".md5(microtime());
1029 
1030  // generate HTTP header
1031  header("Content-type: multipart/byteranges; boundary=".$this->multipart_separator);
1032  } else {
1033  // final
1034 
1035  // generate closing multipart sequence
1036  echo "\n--{$this->multipart_separator}--";
1037  }
1038  } else {
1039  // generate separator and header for next part
1040  echo "\n--{$this->multipart_separator}\n";
1041  echo "Content-type: $mimetype\n";
1042  echo "Content-range: $from-$to/". ($total === false ? "*" : $total);
1043  echo "\n\n";
1044  }
1045  }
$total
Definition: Utf8Test.php:87
Add a drawing to the header
Definition: 04printing.php:69
+ Here is the caller graph for this function:

◆ _new_locktoken()

HTTP_WebDAV_Server::_new_locktoken ( )

create a new opaque lock token as defined in RFC2518

Parameters
void
Returns
string new RFC2518 opaque lock token

Definition at line 1631 of file Server.php.

Referenced by http_LOCK().

1632  {
1633  return "opaquelocktoken:".$this->_new_uuid();
1634  }
+ Here is the caller graph for this function:

◆ _new_uuid()

HTTP_WebDAV_Server::_new_uuid ( )

generate Unique Universal IDentifier for lock token

Parameters
void
Returns
string a new UUID

Definition at line 1601 of file Server.php.

References $n.

1602  {
1603  // use uuid extension from PECL if available
1604  if (function_exists("uuid_create")) {
1605  return uuid_create();
1606  }
1607 
1608  // fallback
1609  $uuid = md5(microtime().getmypid()); // this should be random enough for now
1610 
1611  // set variant and version fields for 'true' random uuid
1612  $uuid{12} = "4";
1613  $n = 8 + (ord($uuid{16}) & 3);
1614  $hex = "0123456789abcdef";
1615  $uuid{16} = $hex{$n};
1616 
1617  // return formated uuid
1618  return substr($uuid, 0, 8)."-"
1619  . substr($uuid, 8, 4)."-"
1620  . substr($uuid, 12, 4)."-"
1621  . substr($uuid, 16, 4)."-"
1622  . substr($uuid, 20);
1623  }
$n
Definition: RandomTest.php:80

◆ _prop_encode()

HTTP_WebDAV_Server::_prop_encode (   $text)

UTF-8 encode property values if not already done so.

Parameters
stringtext to encode
Returns
string utf-8 encoded text

Definition at line 1984 of file Server.php.

References $text.

Referenced by http_PROPFIND(), and http_PROPPATCH().

1985  {
1986  switch (strtolower($this->_prop_encoding)) {
1987  case "utf-8":
1988  return $text;
1989  case "iso-8859-1":
1990  case "iso-8859-15":
1991  case "latin-1":
1992  default:
1993  return utf8_encode($text);
1994  }
1995  }
$text
+ Here is the caller graph for this function:

◆ _slashify()

HTTP_WebDAV_Server::_slashify (   $path)

Slashify - make sure path ends in a slash.

Parameters
stringdirectory path
Returns
string directory path wiht trailing slash

Definition at line 2003 of file Server.php.

References $path.

2003  {
2004  if ($path[strlen($path)-1] != '/') {
2005  $path = $path."/";
2006  }
2007  return $path;
2008  }

◆ _urldecode()

HTTP_WebDAV_Server::_urldecode (   $path)

private version of PHP urldecode

not really needed but added for completenes

Parameters
stringURL to decode
Returns
string decoded URL

Definition at line 1966 of file Server.php.

References $result.

Referenced by _copymove(), and serveRequest().

1967  {
1968  // BEGIN WebDAV
1969  // urldecode wrongly replaces '+' characters by ' ' characters.
1970  // We replace '+' into '%2b' before passing the path through urldecode.
1971  //return urldecode($path);
1972  $result =& urldecode(str_replace('+','%2b',$path));
1973  //$this->writelog('_urldecode('.$path.'):'.$result);
1974  return $result;
1975  // END PATCH WebDAV
1976  }
$result
+ Here is the caller graph for this function:

◆ _urlencode()

HTTP_WebDAV_Server::_urlencode (   $url)

private minimalistic version of PHP urlencode()

only blanks and XML special chars must be encoded here full urlencode() encoding confuses some clients ...

Parameters
stringURL to encode
Returns
string encoded URL

Definition at line 1949 of file Server.php.

References $url, and array.

1950  {
1951  return strtr($url, array(" "=>"%20",
1952  "&"=>"%26",
1953  "<"=>"%3C",
1954  ">"=>"%3E",
1955  ));
1956  }
$url
Definition: shib_logout.php:72
Create styles array
The data for the language used.

◆ http_COPY()

HTTP_WebDAV_Server::http_COPY ( )

COPY method handler.

Parameters
void
Returns
void

Definition at line 1267 of file Server.php.

References _copymove().

1268  {
1269  // no need to check source lock status here
1270  // destination lock status is always checked by the helper method
1271  $this->_copymove("copy");
1272  }
+ Here is the call graph for this function:

◆ http_DELETE()

HTTP_WebDAV_Server::http_DELETE ( )

DELETE method handler.

Parameters
void
Returns
void

Definition at line 1232 of file Server.php.

References $_SERVER, $options, $path, _check_lock_status(), and http_status().

1233  {
1234  // check RFC 2518 Section 9.2, last paragraph
1235  if (isset($_SERVER["HTTP_DEPTH"])) {
1236  if ($_SERVER["HTTP_DEPTH"] != "infinity") {
1237  $this->http_status("400 Bad Request");
1238  return;
1239  }
1240  }
1241 
1242  // check lock status
1243  if ($this->_check_lock_status($this->path)) {
1244  // ok, proceed
1245  $options = Array();
1246  $options["path"] = $this->path;
1247 
1248  $stat = $this->delete($options);
1249 
1250  $this->http_status($stat);
1251  } else {
1252  // sorry, its locked
1253  $this->http_status("423 Locked");
1254  }
1255  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
if(!is_array($argv)) $options
+ Here is the call graph for this function:

◆ http_GET()

HTTP_WebDAV_Server::http_GET ( )

GET method handler.

Parameters
void
Returns
void

Definition at line 851 of file Server.php.

References $options, $path, $size, $start, $total, _get_ranges(), _multipart_byterange_header(), exit, header, and http_status().

852  {
853  // TODO check for invalid stream
854  $options = Array();
855  $options["path"] = $this->path;
856 
857  $this->_get_ranges($options);
858 
859  if (true === ($status = $this->get($options))) {
860  if (!headers_sent()) {
861  $status = "200 OK";
862 
863  if (!isset($options['mimetype'])) {
864  $options['mimetype'] = "application/octet-stream";
865  }
866  header("Content-type: $options[mimetype]");
867 
868  if (isset($options['mtime'])) {
869  header("Last-modified:".gmdate("D, d M Y H:i:s ", $options['mtime'])."GMT");
870  }
871 
872  if (isset($options['stream'])) {
873  // GET handler returned a stream
874  if (!empty($options['ranges']) && (0===fseek($options['stream'], 0, SEEK_SET))) {
875  // partial request and stream is seekable
876 
877  if (count($options['ranges']) === 1) {
878  $range = $options['ranges'][0];
879 
880  if (isset($range['start'])) {
881  fseek($options['stream'], $range['start'], SEEK_SET);
882  if (feof($options['stream'])) {
883  $this->http_status("416 Requested range not satisfiable");
884  exit;
885  }
886 
887  if (isset($range['end']) && $range['end'] != '') {
888  $size = $range['end']-$range['start']+1;
889  $this->http_status("206 partial");
890  header("Content-length: $size");
891  header("Content-range: $range[start]-$range[end]/"
892  . (isset($options['size']) ? $options['size'] : "*"));
893  while ($size && !feof($options['stream'])) {
894  $buffer = fread($options['stream'], 4096);
895  $size -= strlen($buffer);
896  echo $buffer;
897  }
898  } else {
899  $this->http_status("206 partial");
900  if (isset($options['size'])) {
901  header("Content-length: ".($options['size'] - $range['start']));
902  header("Content-range: $start-$end/"
903  . (isset($options['size']) ? $options['size'] : "*"));
904  }
905  fpassthru($options['stream']);
906  }
907  } else {
908  header("Content-length: ".$range['last']);
909  fseek($options['stream'], -$range['last'], SEEK_END);
910  fpassthru($options['stream']);
911  }
912  } else {
913  $this->_multipart_byterange_header(); // init multipart
914  foreach ($options['ranges'] as $range) {
915  // TODO what if size unknown? 500?
916  if (isset($range['start'])) {
917  $from = $range['start'];
918  $to = !empty($range['end']) ? $range['end'] : $options['size']-1;
919  } else {
920  $from = $options['size'] - $range['last']-1;
921  $to = $options['size'] -1;
922  }
923  $total = isset($options['size']) ? $options['size'] : "*";
924  $size = $to - $from + 1;
925  $this->_multipart_byterange_header($options['mimetype'], $from, $to, $total);
926 
927 
928  fseek($options['stream'], $start, SEEK_SET);
929  while ($size && !feof($options['stream'])) {
930  $buffer = fread($options['stream'], 4096);
931  $size -= strlen($buffer);
932  echo $buffer;
933  }
934  }
935  $this->_multipart_byterange_header(); // end multipart
936  }
937  } else {
938  // normal request or stream isn't seekable, return full content
939  if (isset($options['size'])) {
940  header("Content-length: ".$options['size']);
941  }
942 
943  // BEGIN WebDAV W. Randelshofer
944  // fpassthru apparently only delivers up to 2 million bytes.
945  // use fread instead
946  //fpassthru($options['stream']);
947  while (! feof($options['stream'])) {
948  $buffer = fread($options['stream'], 4096);
949  echo $buffer;
950  }
951  // END PATCH WebDAV W. Randelshofer
952 
953  return; // no more headers
954  }
955  } elseif (isset($options['data'])) {
956  if (is_array($options['data'])) {
957  // reply to partial request
958  } else {
959  header("Content-length: ".strlen($options['data']));
960  echo $options['data'];
961  }
962  }
963  }
964  }
965 
966  if (false === $status) {
967  // BEGIN WebDAV Randelshofer
968  $status = '404 Not Found';
969  //$this->http_status("404 not found");
970  // END PATCH WebDAV Randelshofer
971  }
972 
973  if (!headers_sent()) {
974  // TODO: check setting of headers in various code pathes above
975  $this->http_status("$status");
976  }
977  }
_get_ranges(&$options)
parse HTTP Range: header
Definition: Server.php:986
$size
Definition: RandomTest.php:79
_multipart_byterange_header($mimetype=false, $from=false, $to=false, $total=false)
generate separator headers for multipart response
Definition: Server.php:1020
$total
Definition: Utf8Test.php:87
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
if(!is_array($argv)) $options
Add a drawing to the header
Definition: 04printing.php:69
+ Here is the call graph for this function:

◆ http_HEAD()

HTTP_WebDAV_Server::http_HEAD ( )

HEAD method handler.

Parameters
void
Returns
void

Definition at line 1059 of file Server.php.

References $options, $path, and http_status().

1060  {
1061  $status = false;
1062  $options = Array();
1063  $options["path"] = $this->path;
1064 
1065  if (method_exists($this, "HEAD")) {
1066  $status = $this->head($options);
1067  } else if (method_exists($this, "GET")) {
1068  ob_start();
1069  $status = $this->GET($options);
1070  ob_end_clean();
1071  }
1072 
1073  if($status===true) $status = "200 OK";
1074  if($status===false) $status = "404 Not found";
1075 
1076  $this->http_status($status);
1077  }
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
if(!is_array($argv)) $options
+ Here is the call graph for this function:

◆ http_LOCK()

HTTP_WebDAV_Server::http_LOCK ( )

LOCK method handler.

Parameters
void
Returns
void

Definition at line 1307 of file Server.php.

References $_SERVER, $options, $path, _check_lock_status(), _new_locktoken(), header, http_status(), and time.

1308  {
1309  $options = Array();
1310  $options["path"] = $this->path;
1311 
1312  if (isset($_SERVER['HTTP_DEPTH'])) {
1313  $options["depth"] = $_SERVER["HTTP_DEPTH"];
1314  } else {
1315  $options["depth"] = "infinity";
1316  }
1317 
1318  if (isset($_SERVER["HTTP_TIMEOUT"])) {
1319  $options["timeout"] = explode(",", $_SERVER["HTTP_TIMEOUT"]);
1320  }
1321 
1322  if(empty($_SERVER['CONTENT_LENGTH']) && !empty($_SERVER['HTTP_IF'])) {
1323  // check if locking is possible
1324  if(!$this->_check_lock_status($this->path)) {
1325  $this->http_status("423 Locked");
1326  return;
1327  }
1328 
1329  // refresh lock
1330  $options["update"] = substr($_SERVER['HTTP_IF'], 2, -2);
1331  $stat = $this->lock($options);
1332  } else {
1333  // extract lock request information from request XML payload
1334  $lockinfo = new _parse_lockinfo("php://input");
1335  if (!$lockinfo->success) {
1336  $this->http_status("400 bad request");
1337  }
1338 
1339  // check if locking is possible
1340  if(!$this->_check_lock_status($this->path, $lockinfo->lockscope === "shared")) {
1341  $this->http_status("423 Locked");
1342  return;
1343  }
1344 
1345  // new lock
1346  $options["scope"] = $lockinfo->lockscope;
1347  $options["type"] = $lockinfo->locktype;
1348  $options["owner"] = $lockinfo->owner;
1349 
1350  $options["locktoken"] = $this->_new_locktoken();
1351 
1352  $stat = $this->lock($options);
1353  }
1354 
1355  if(is_bool($stat)) {
1356  $http_stat = $stat ? "200 OK" : "423 Locked";
1357  } else {
1358  $http_stat = $stat;
1359  }
1360 
1361  $this->http_status($http_stat);
1362 
1363  if ($http_stat{0} == 2) { // 2xx states are ok
1364  if($options["timeout"]) {
1365  // more than a million is considered an absolute timestamp
1366  // less is more likely a relative value
1367  if($options["timeout"]>1000000) {
1368  $timeout = "Second-".($options['timeout']-time());
1369  } else {
1370  $timeout = "Second-$options[timeout]";
1371  }
1372  } else {
1373  $timeout = "Infinite";
1374  }
1375  /*
1376  $this->writelog(
1377  'Content-Type: text/xml; charset="utf-8"'
1378  ."Lock-Token: <$options[locktoken]>"
1379  . "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
1380  . "<D:prop xmlns:D=\"DAV:\">\n"
1381  . " <D:lockdiscovery>\n"
1382  . " <D:activelock>\n"
1383  . " <D:lockscope><D:$options[scope]/></D:lockscope>\n"
1384  . " <D:locktype><D:$options[type]/></D:locktype>\n"
1385  . " <D:depth>$options[depth]</D:depth>\n"
1386  . " <D:owner>$options[owner]</D:owner>\n"
1387  . " <D:timeout>$timeout</D:timeout>\n"
1388  . " <D:locktoken><D:href>$options[locktoken]</D:href></D:locktoken>\n"
1389  . " </D:activelock>\n"
1390  . " </D:lockdiscovery>\n"
1391  . "</D:prop>\n\n"
1392  );*/
1393  header('Content-Type: text/xml; charset="utf-8"');
1394  header("Lock-Token: <$options[locktoken]>");
1395  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
1396  echo "<D:prop xmlns:D=\"DAV:\">\n";
1397  echo " <D:lockdiscovery>\n";
1398  echo " <D:activelock>\n";
1399  echo " <D:lockscope><D:$options[scope]/></D:lockscope>\n";
1400  echo " <D:locktype><D:$options[type]/></D:locktype>\n";
1401  echo " <D:depth>$options[depth]</D:depth>\n";
1402  echo " <D:owner>$options[owner]</D:owner>\n";
1403  echo " <D:timeout>$timeout</D:timeout>\n";
1404  echo " <D:locktoken><D:href>$options[locktoken]</D:href></D:locktoken>\n";
1405  echo " </D:activelock>\n";
1406  echo " </D:lockdiscovery>\n";
1407  echo "</D:prop>\n\n";
1408  }
1409  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_new_locktoken()
create a new opaque lock token as defined in RFC2518
Definition: Server.php:1631
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
if(!is_array($argv)) $options
Add a drawing to the header
Definition: 04printing.php:69
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the call graph for this function:

◆ http_MKCOL()

HTTP_WebDAV_Server::http_MKCOL ( )

MKCOL method handler.

Parameters
void
Returns
void

Definition at line 830 of file Server.php.

References $options, $path, and http_status().

831  {
832  $options = Array();
833  $options["path"] = $this->path;
834 
835  $stat = $this->mkcol($options);
836 
837  $this->http_status($stat);
838  }
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
if(!is_array($argv)) $options
+ Here is the call graph for this function:

◆ http_MOVE()

HTTP_WebDAV_Server::http_MOVE ( )

MOVE method handler.

Parameters
void
Returns
void

Definition at line 1284 of file Server.php.

References _check_lock_status(), _copymove(), and http_status().

1285  {
1286  //$this->writelog('MOVE()');
1287  if ($this->_check_lock_status($this->path)) {
1288  // destination lock status is always checked by the helper method
1289  $this->_copymove("move");
1290  } else {
1291  //$this->writelog('MOVE():423 Locked');
1292  $this->http_status("423 Locked");
1293  }
1294  }
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
+ Here is the call graph for this function:

◆ http_OPTIONS()

HTTP_WebDAV_Server::http_OPTIONS ( )

GET implementation.

overload this method to retrieve resources from your server

Parameters
array&$paramsArray of input and output parameters
input
  • path -

output
  • size -
Returns
int HTTP-Statuscode PUT implementation

PUT implementation

Parameters
array&$params
Returns
int HTTP-Statuscode COPY implementation

COPY implementation

Parameters
array&$params
Returns
int HTTP-Statuscode MOVE implementation

MOVE implementation

Parameters
array&$params
Returns
int HTTP-Statuscode DELETE implementation

DELETE implementation

Parameters
array&$params
Returns
int HTTP-Statuscode PROPFIND implementation

PROPFIND implementation

Parameters
array&$params
Returns
int HTTP-Statuscode PROPPATCH implementation

PROPPATCH implementation

Parameters
array&$params
Returns
int HTTP-Statuscode LOCK implementation

LOCK implementation

Parameters
array&$params
Returns
int HTTP-Statuscode UNLOCK implementation

UNLOCK implementation

Parameters
array&$params
Returns
int HTTP-Statuscode check authentication

overload this method to retrieve and confirm authentication information

Parameters
stringtype Authentication type, e.g. "basic" or "digest"
stringusername Transmitted username
stringpasswort Transmitted password
Returns
bool Authentication status check lock status for a resource

overload this method to return shared and exclusive locks active for this resource

Parameters
stringresource Resource path to check
Returns
array An array of lock entries each consisting of 'type' ('shared'/'exclusive'), 'token' and 'timeout' OPTIONS method handler

The OPTIONS method handler creates a valid OPTIONS reply including Dav: and Allowed: headers based on the implemented methods found in the actual instance

Parameters
void
Returns
void

Definition at line 478 of file Server.php.

References _allow(), array, header, http_status(), and writelog().

479  {
480  // Microsoft clients default to the Frontpage protocol
481  // unless we tell them to use WebDAV
482  header("MS-Author-Via: DAV");
483 
484  // get allowed methods
485  $allow = $this->_allow();
486 
487  // dav header
488  $dav = array(1); // assume we are always dav class 1 compliant
489  if (isset($allow['LOCK'])) {
490  $dav[] = 2; // dav class 2 requires that locking is supported
491  }
492 
493  // tell clients what we found
494  $this->http_status("200 OK");
495  header("DAV: " .join("," , $dav));
496  header("Allow: ".join(", ", $allow));
497  $this->writelog(__METHOD__.': dav='.var_export($dav,true).' allow='.var_export($allow,true));
498  header("Content-length: 0");
499  }
_allow()
check for implemented HTTP methods
Definition: Server.php:1511
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
Add a drawing to the header
Definition: 04printing.php:69
Create styles array
The data for the language used.
writelog($message)
Writes a message to the logfile.,.
Definition: Server.php:2016
+ Here is the call graph for this function:

◆ http_PROPFIND()

HTTP_WebDAV_Server::http_PROPFIND ( )

PROPFIND method handler.

Parameters
void
Returns
void

Definition at line 512 of file Server.php.

References $_SERVER, $file, $files, $options, $path, _prop_encode(), array, header, http_status(), lockdiscovery(), and mkprop().

513  {
514  $options = Array();
515  $options["path"] = $this->path;
516 
517  // search depth from header (default is "infinity)
518  if (isset($_SERVER['HTTP_DEPTH'])) {
519  $options["depth"] = $_SERVER["HTTP_DEPTH"];
520  } else {
521  $options["depth"] = "infinity";
522  }
523 
524  // analyze request payload
525  $propinfo = new _parse_propfind("php://input");
526  if (!$propinfo->success) {
527  $this->http_status("400 Error");
528  return;
529  }
530  $options['props'] = $propinfo->props;
531 
532  // call user handler
533  $files = array();
534  if (!$this->propfind($options, $files)) {
535  $this->http_status("404 Not Found");
536  return;
537  }
538 
539  // collect namespaces here
540  $ns_hash = array();
541 
542  // Microsoft Clients need this special namespace for date and time values
543  $ns_defs = "xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\"";
544 
545  // now we loop over all returned file entries
546  foreach($files["files"] as $filekey => $file) {
547 
548  // nothing to do if no properties were returend for a file
549  if (!isset($file["props"]) || !is_array($file["props"])) {
550  continue;
551  }
552 
553  // now loop over all returned properties
554  foreach($file["props"] as $key => $prop) {
555  // as a convenience feature we do not require that user handlers
556  // restrict returned properties to the requested ones
557  // here we strip all unrequested entries out of the response
558 
559  switch($options['props']) {
560  case "all":
561  // nothing to remove
562  break;
563 
564  case "names":
565  // only the names of all existing properties were requested
566  // so we remove all values
567  unset($files["files"][$filekey]["props"][$key]["val"]);
568  break;
569 
570  default:
571  $found = false;
572 
573  // search property name in requested properties
574  foreach((array)$options["props"] as $reqprop) {
575  if ( $reqprop["name"] == $prop["name"]
576  && $reqprop["xmlns"] == $prop["ns"]) {
577  $found = true;
578  break;
579  }
580  }
581 
582  // unset property and continue with next one if not found/requested
583  if (!$found) {
584  $files["files"][$filekey]["props"][$key]="";
585  continue(2);
586  }
587  break;
588  }
589 
590  // namespace handling
591  if (empty($prop["ns"])) continue; // no namespace
592  $ns = $prop["ns"];
593  if ($ns == "DAV:") continue; // default namespace
594  if (isset($ns_hash[$ns])) continue; // already known
595 
596  // register namespace
597  $ns_name = "ns".(count($ns_hash) + 1);
598  $ns_hash[$ns] = $ns_name;
599  $ns_defs .= " xmlns:$ns_name=\"$ns\"";
600  }
601 
602  // we also need to add empty entries for properties that were requested
603  // but for which no values where returned by the user handler
604  if (is_array($options['props'])) {
605  foreach($options["props"] as $reqprop) {
606  if($reqprop['name']=="") continue; // skip empty entries
607 
608  $found = false;
609 
610  // check if property exists in result
611  foreach($file["props"] as $prop) {
612  if ( $reqprop["name"] == $prop["name"]
613  && $reqprop["xmlns"] == $prop["ns"]) {
614  $found = true;
615  break;
616  }
617  }
618 
619  if (!$found) {
620  if($reqprop["xmlns"]==="DAV:" && $reqprop["name"]==="lockdiscovery") {
621  // lockdiscovery is handled by the base class
622  $files["files"][$filekey]["props"][]
623  = $this->mkprop("DAV:",
624  "lockdiscovery" ,
625  $this->lockdiscovery($files["files"][$filekey]['path']));
626  } else {
627  // add empty value for this property
628  $files["files"][$filekey]["noprops"][] =
629  $this->mkprop($reqprop["xmlns"], $reqprop["name"], "");
630 
631  // register property namespace if not known yet
632  if ($reqprop["xmlns"] != "DAV:" && !isset($ns_hash[$reqprop["xmlns"]])) {
633  $ns_name = "ns".(count($ns_hash) + 1);
634  $ns_hash[$reqprop["xmlns"]] = $ns_name;
635  $ns_defs .= " xmlns:$ns_name=\"$reqprop[xmlns]\"";
636  }
637  }
638  }
639  }
640  }
641  }
642 
643  // now we generate the reply header ...
644  $this->http_status("207 Multi-Status");
645  header('Content-Type: text/xml; charset="utf-8"');
646 
647  // ... and payload
648  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
649  echo "<D:multistatus xmlns:D=\"DAV:\">\n";
650 
651  foreach($files["files"] as $file) {
652  // ignore empty or incomplete entries
653  if(!is_array($file) || empty($file) || !isset($file["path"])) continue;
654  $path = $file['path'];
655  if(!is_string($path) || $path==="") continue;
656 
657  echo " <D:response $ns_defs>\n";
658 
659  // BEGIN WebDAV W. Randelshofer Don't slashify path because it confuses Mac OS X
660  //$href = $this->_slashify($_SERVER['SCRIPT_NAME'] . $path);
661  $href = $_SERVER['SCRIPT_NAME'] . $path;
662  //END PATCH WebDAV W. Randelshofer
663 
664  echo " <D:href>$href</D:href>\n";
665 
666  // report all found properties and their values (if any)
667  if (isset($file["props"]) && is_array($file["props"])) {
668  echo " <D:propstat>\n";
669  echo " <D:prop>\n";
670 
671  foreach($file["props"] as $key => $prop) {
672 
673  if (!is_array($prop)) continue;
674  if (!isset($prop["name"])) continue;
675  if (!isset($prop["val"]) || $prop["val"] === "" || $prop["val"] === false) {
676  // empty properties (cannot use empty() for check as "0" is a legal value here)
677  if($prop["ns"]=="DAV:") {
678  echo " <D:$prop[name]/>\n";
679  } else if(!empty($prop["ns"])) {
680  echo " <".$ns_hash[$prop["ns"]].":$prop[name]/>\n";
681  } else {
682  echo " <$prop[name] xmlns=\"\"/>";
683  }
684  } else if ($prop["ns"] == "DAV:") {
685  // some WebDAV properties need special treatment
686  switch ($prop["name"]) {
687  case "creationdate":
688  echo " <D:creationdate ns0:dt=\"dateTime.tz\">"
689  // BEGIN WebDAV W. Randelshofer
690  . gmdate("Y-m-d\\TH:i:s\\Z",$prop['val'])
691  // . gmdate("D, d M Y H:i:s ", $prop['val'])
692  // END PATCH WebDAV W. Randelshofer
693  . "</D:creationdate>\n";
694  break;
695  case "getlastmodified":
696  echo " <D:getlastmodified ns0:dt=\"dateTime.rfc1123\">"
697  . gmdate("D, d M Y H:i:s ", $prop['val'])
698  . "GMT</D:getlastmodified>\n";
699  break;
700  case "resourcetype":
701  echo " <D:resourcetype><D:$prop[val]/></D:resourcetype>\n";
702  break;
703  case "supportedlock":
704  echo " <D:supportedlock>$prop[val]</D:supportedlock>\n";
705  break;
706  case "lockdiscovery":
707  echo " <D:lockdiscovery>\n";
708  echo $prop["val"];
709  echo " </D:lockdiscovery>\n";
710  break;
711  default:
712  echo " <D:$prop[name]>"
713  . $this->_prop_encode(htmlspecialchars($prop['val']))
714  . "</D:$prop[name]>\n";
715  break;
716  }
717  } else {
718  // properties from namespaces != "DAV:" or without any namespace
719  if ($prop["ns"]) {
720  echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]>"
721  . $this->_prop_encode(htmlspecialchars($prop['val']))
722  . "</" . $ns_hash[$prop["ns"]] . ":$prop[name]>\n";
723  } else {
724  echo " <$prop[name] xmlns=\"\">"
725  . $this->_prop_encode(htmlspecialchars($prop['val']))
726  . "</$prop[name]>\n";
727  }
728  }
729  }
730 
731  echo " </D:prop>\n";
732  echo " <D:status>HTTP/1.1 200 OK</D:status>\n";
733  echo " </D:propstat>\n";
734  }
735 
736  // now report all properties requested but not found
737  if (isset($file["noprops"])) {
738  echo " <D:propstat>\n";
739  echo " <D:prop>\n";
740 
741  foreach($file["noprops"] as $key => $prop) {
742  if ($prop["ns"] == "DAV:") {
743  echo " <D:$prop[name]/>\n";
744  } else if ($prop["ns"] == "") {
745  echo " <$prop[name] xmlns=\"\"/>\n";
746  } else {
747  echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]/>\n";
748  }
749  }
750 
751  echo " </D:prop>\n";
752  echo " <D:status>HTTP/1.1 404 Not Found</D:status>\n";
753  echo " </D:propstat>\n";
754  }
755 
756  echo " </D:response>\n";
757  }
758 
759  echo "</D:multistatus>\n";
760  }
$files
Definition: add-vimline.php:18
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
if(!is_array($argv)) $options
mkprop()
helper for property element creation
Definition: Server.php:1551
Add a drawing to the header
Definition: 04printing.php:69
Create styles array
The data for the language used.
lockdiscovery($path)
Generate lockdiscovery reply from checklock() result.
Definition: Server.php:1876
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
_prop_encode($text)
UTF-8 encode property values if not already done so.
Definition: Server.php:1984
+ Here is the call graph for this function:

◆ http_PROPPATCH()

HTTP_WebDAV_Server::http_PROPPATCH ( )

PROPPATCH method handler.

Parameters
void
Returns
void

Definition at line 773 of file Server.php.

References $_SERVER, $options, $path, _check_lock_status(), _prop_encode(), header, and http_status().

774  {
775  if($this->_check_lock_status($this->path)) {
776  $options = Array();
777  $options["path"] = $this->path;
778 
779  $propinfo = new _parse_proppatch("php://input");
780 
781  if (!$propinfo->success) {
782  $this->http_status("400 Error");
783  return;
784  }
785 
786  $options['props'] = $propinfo->props;
787 
788  $responsedescr = $this->proppatch($options);
789 
790  $this->http_status("207 Multi-Status");
791  header('Content-Type: text/xml; charset="utf-8"');
792 
793  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
794 
795  echo "<D:multistatus xmlns:D=\"DAV:\">\n";
796  echo " <D:response>\n";
797  echo " <D:href>".$this->_urlencode($_SERVER["SCRIPT_NAME"].$this->path)."</D:href>\n";
798 
799  foreach($options["props"] as $prop) {
800  echo " <D:propstat>\n";
801  echo " <D:prop><$prop[name] xmlns=\"$prop[ns]\"/></D:prop>\n";
802  echo " <D:status>HTTP/1.1 $prop[status]</D:status>\n";
803  echo " </D:propstat>\n";
804  }
805 
806  if ($responsedescr) {
807  echo " <D:responsedescription>".
808  $this->_prop_encode(htmlspecialchars($responsedescr)).
809  "</D:responsedescription>\n";
810  }
811 
812  echo " </D:response>\n";
813  echo "</D:multistatus>\n";
814  } else {
815  $this->http_status("423 Locked");
816  }
817  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
if(!is_array($argv)) $options
Add a drawing to the header
Definition: 04printing.php:69
_prop_encode($text)
UTF-8 encode property values if not already done so.
Definition: Server.php:1984
+ Here is the call graph for this function:

◆ http_PUT()

HTTP_WebDAV_Server::http_PUT ( )

PUT method handler.

Parameters
void
Returns
void

Definition at line 1089 of file Server.php.

References $_SERVER, $options, $path, _check_lock_status(), array, and http_status().

1090  {
1091  if ($this->_check_lock_status($this->path)) {
1092  $options = Array();
1093  $options["path"] = $this->path;
1094  $options["content_length"] = $_SERVER["CONTENT_LENGTH"];
1095 
1096  // get the Content-type
1097  if (isset($_SERVER["CONTENT_TYPE"])) {
1098  // for now we do not support any sort of multipart requests
1099  if (!strncmp($_SERVER["CONTENT_TYPE"], "multipart/", 10)) {
1100  $this->http_status("501 not implemented");
1101  echo "The service does not support mulipart PUT requests";
1102  return;
1103  }
1104  $options["content_type"] = $_SERVER["CONTENT_TYPE"];
1105  } else {
1106  // default content type if none given
1107  $options["content_type"] = "application/octet-stream";
1108  }
1109 
1110  /* RFC 2616 2.6 says: "The recipient of the entity MUST NOT
1111  ignore any Content-* (e.g. Content-Range) headers that it
1112  does not understand or implement and MUST return a 501
1113  (Not Implemented) response in such cases."
1114  */
1115  foreach ($_SERVER as $key => $val) {
1116  if (strncmp($key, "HTTP_CONTENT", 11)) continue;
1117  switch ($key) {
1118  case 'HTTP_CONTENT_ENCODING': // RFC 2616 14.11
1119  // TODO support this if ext/zlib filters are available
1120  $this->http_status("501 not implemented");
1121  echo "The service does not support '$val' content encoding";
1122  return;
1123 
1124  case 'HTTP_CONTENT_LANGUAGE': // RFC 2616 14.12
1125  // we assume it is not critical if this one is ignored
1126  // in the actual PUT implementation ...
1127  $options["content_language"] = $value;
1128  break;
1129 
1130  case 'HTTP_CONTENT_LOCATION': // RFC 2616 14.14
1131  /* The meaning of the Content-Location header in PUT
1132  or POST requests is undefined; servers are free
1133  to ignore it in those cases. */
1134  break;
1135 
1136  case 'HTTP_CONTENT_RANGE': // RFC 2616 14.16
1137  // single byte range requests are supported
1138  // the header format is also specified in RFC 2616 14.16
1139  // TODO we have to ensure that implementations support this or send 501 instead
1140  if (!preg_match('@bytes\s+(\d+)-(\d+)/((\d+)|\*)@', $value, $matches)) {
1141  $this->http_status("400 bad request");
1142  echo "The service does only support single byte ranges";
1143  return;
1144  }
1145 
1146  $range = array("start"=>$matches[1], "end"=>$matches[2]);
1147  if (is_numeric($matches[3])) {
1148  $range["total_length"] = $matches[3];
1149  }
1150  $option["ranges"][] = $range;
1151 
1152  // TODO make sure the implementation supports partial PUT
1153  // this has to be done in advance to avoid data being overwritten
1154  // on implementations that do not support this ...
1155  break;
1156 
1157  case 'HTTP_CONTENT_MD5': // RFC 2616 14.15
1158  // TODO: maybe we can just pretend here?
1159  $this->http_status("501 not implemented");
1160  echo "The service does not support content MD5 checksum verification";
1161  return;
1162 
1163  case 'HTTP_CONTENT_LENGTH':
1164  // defined on IIS and has the same value as CONTENT_LENGTH
1165  break;
1166 
1167  default:
1168  // any other unknown Content-* headers
1169  $this->http_status("501 not implemented");
1170  echo "The service does not support '$key'";
1171  return;
1172  }
1173  }
1174 
1175  $options["stream"] = fopen("php://input", "r");
1176 
1177  $stat = $this->PUT($options);
1178 
1179  if ($stat == false) {
1180  $stat = "403 Forbidden";
1181  } else if (is_resource($stat) && get_resource_type($stat) == "stream") {
1182  $stream = $stat;
1183 
1184  $stat = $options["new"] ? "201 Created" : "204 No Content";
1185 
1186  if (!empty($options["ranges"])) {
1187  // TODO multipart support is missing (see also above)
1188  if (0 == fseek($stream, $range[0]["start"], SEEK_SET)) {
1189  $length = $range[0]["end"]-$range[0]["start"]+1;
1190  if (!fwrite($stream, fread($options["stream"], $length))) {
1191  $stat = "403 Forbidden";
1192  }
1193  } else {
1194  $stat = "403 Forbidden";
1195  }
1196  } else {
1197  while (!feof($options["stream"])) {
1198  // BEGIN WebDAV W. Randelshofer explicitly compare with false.
1199  if (false === ($written = fwrite($stream, fread($options["stream"], 4096)))) {
1200  // END WebDAV W. Randelshofer explicitly compare with false.
1201  $stat = "403 Forbidden";
1202  break;
1203  }
1204  $count += $written;
1205  }
1206  }
1207 
1208  fclose($stream);
1209  //$this->writelog('PUT wrote '.$written.' bytes');
1210  // BEGIN WebDAV W. Randelshofer finish the put-operation
1211  $this->PUTfinished($options);
1212  // END WebDAV W. Randelshofer finish the put-operation
1213  }
1214 
1215  $this->http_status($stat);
1216  } else {
1217  $this->http_status("423 Locked");
1218  }
1219  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
_check_lock_status($path, $exclusive_only=false)
Definition: Server.php:1847
if(!is_array($argv)) $options
Create styles array
The data for the language used.
+ Here is the call graph for this function:

◆ http_status()

HTTP_WebDAV_Server::http_status (   $status)

set HTTP return status and mirror it in a private header

Parameters
stringstatus code and message
Returns
void

Definition at line 1924 of file Server.php.

References header.

Referenced by _copymove(), http_DELETE(), http_GET(), http_HEAD(), http_LOCK(), http_MKCOL(), http_MOVE(), http_OPTIONS(), http_PROPFIND(), http_PROPPATCH(), http_PUT(), http_UNLOCK(), serveRequest(), and ilDAVServer\serveRequest().

1925  {
1926  // simplified success case
1927  if($status === true) {
1928  $status = "200 OK";
1929  }
1930  //$this->writelog('http_status('.$status.')');
1931 
1932  // remember status
1933  $this->_http_status = $status;
1934 
1935  // generate HTTP status response
1936  header("HTTP/1.1 $status");
1937  header("X-WebDAV-Status: $status", true);
1938  }
Add a drawing to the header
Definition: 04printing.php:69
+ Here is the caller graph for this function:

◆ http_UNLOCK()

HTTP_WebDAV_Server::http_UNLOCK ( )

UNLOCK method handler.

Parameters
void
Returns
void

Definition at line 1422 of file Server.php.

References $_SERVER, $options, $path, and http_status().

1423  {
1424  $options = Array();
1425  $options["path"] = $this->path;
1426 
1427  if (isset($_SERVER['HTTP_DEPTH'])) {
1428  $options["depth"] = $_SERVER["HTTP_DEPTH"];
1429  } else {
1430  $options["depth"] = "infinity";
1431  }
1432 
1433  // strip surrounding <>
1434  $options["token"] = substr(trim($_SERVER["HTTP_LOCK_TOKEN"]), 1, -1);
1435 //$this->writelog('http_UNLOCK HTTP_LOCK_TOKEN='.$_SERVER["HTTP_LOCK_TOKEN"]);
1436  // call user method
1437  $stat = $this->unlock($options);
1438 
1439  $this->http_status($stat);
1440  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
if(!is_array($argv)) $options
+ Here is the call graph for this function:

◆ lockdiscovery()

HTTP_WebDAV_Server::lockdiscovery (   $path)

Generate lockdiscovery reply from checklock() result.

Parameters
stringresource path to check
Returns
string lockdiscovery response

Definition at line 1876 of file Server.php.

References time.

Referenced by http_PROPFIND().

1877  {
1878  // no lock support without checklock() method
1879  if (!method_exists($this, "checklock")) {
1880  return "";
1881  }
1882 
1883  // collect response here
1884  $activelocks = "";
1885 
1886  // get checklock() reply
1887  $lock = $this->checklock($path);
1888 
1889  // generate <activelock> block for returned data
1890  if (is_array($lock) && count($lock)) {
1891  // check for 'timeout' or 'expires'
1892  if (!empty($lock["expires"])) {
1893  $timeout = "Second-".($lock["expires"] - time());
1894  } else if (!empty($lock["timeout"])) {
1895  $timeout = "Second-$lock[timeout]";
1896  } else {
1897  $timeout = "Infinite";
1898  }
1899 
1900  // genreate response block
1901  $activelocks.= "
1902  <D:activelock>
1903  <D:lockscope><D:$lock[scope]/></D:lockscope>
1904  <D:locktype><D:$lock[type]/></D:locktype>
1905  <D:depth>$lock[depth]</D:depth>
1906  <D:owner>$lock[owner]</D:owner>
1907  <D:timeout>$timeout</D:timeout>
1908  <D:locktoken><D:href>$lock[token]</D:href></D:locktoken>
1909  </D:activelock>
1910  ";
1911  }
1912  //$this->writelog('lockdiscovery('.$path.'):'.$activeclocks);
1913 
1914  // return generated response
1915  return $activelocks;
1916  }
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
+ Here is the caller graph for this function:

◆ mkprop()

HTTP_WebDAV_Server::mkprop ( )

helper for property element creation

Parameters
stringXML namespace (optional)
stringproperty name
stringproperty value
Returns
array property array

Definition at line 1551 of file Server.php.

References array.

Referenced by ilDAVServer\fileinfo(), and http_PROPFIND().

1552  {
1553  $args = func_get_args();
1554  if (count($args) == 3) {
1555  return array("ns" => $args[0],
1556  "name" => $args[1],
1557  "val" => $args[2]);
1558  } else {
1559  return array("ns" => "DAV:",
1560  "name" => $args[0],
1561  "val" => $args[1]);
1562  }
1563  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ serveRequest()

HTTP_WebDAV_Server::serveRequest ( )

Serve WebDAV HTTP request.

dispatch WebDAV HTTP request to the apropriate method handler

Parameters
void
Returns
void

Definition at line 125 of file Server.php.

References $_SERVER, $uri, _allow(), _check_auth(), _check_if_header_conditions(), _urldecode(), header, http_status(), and writelog().

126  {
127  // default uri is the complete request uri
128  // FIXME: use ilHTTPS::isDetected
129  $uri = (@$_SERVER["HTTPS"] === "on" ? "https:" : "http:");
130  $uri.= "//$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]";
131 
132  $this->base_uri = $uri;
133  $this->uri = $uri . $_SERVER[PATH_INFO];
134 
135  // identify ourselves
136  if (empty($this->dav_powered_by)) {
137  header("X-Dav-Powered-By: PHP class: ".get_class($this));
138  } else {
139  header("X-Dav-Powered-By: ".$this->dav_powered_by );
140  }
141 
142  $this->writelog(__METHOD__.': Using uri: '.$this->uri);
143 
144  // check authentication
145  if (!$this->_check_auth()) {
146  // RFC2518 says we must use Digest instead of Basic
147  // but Microsoft Clients do not support Digest
148  // and we don't support NTLM and Kerberos
149  // so we are stuck with Basic here
150  header('WWW-Authenticate: Basic realm="'.($this->http_auth_realm).'"');
151 
152  // Windows seems to require this being the last header sent
153  // (changed according to PECL bug #3138)
154  $this->http_status('401 Unauthorized');
155  $this->writelog('Check auth failed');
156 
157  return;
158  }
159 
160  // check
161  if(! $this->_check_if_header_conditions()) {
162  $this->writelog(__METHOD__.': Precondition failed.');
163  $this->http_status("412 Precondition failed");
164  return;
165  }
166 
167  // set path
168  $this->path = $this->_urldecode($_SERVER["PATH_INFO"]);
169  if (!strlen($this->path)) {
170  header("Location: ".$this->base_uri."/");
171  $this->writelog('HTTP_WebDAV_Server.ServeRequest() missing path info');
172  $this->path = '/';
173  //exit;
174  }
175  // BEGIN WebDAV: Don't strip backslashes. Backslashes are a valid part of a unix filename!
176  /*
177  if(ini_get("magic_quotes_gpc")) {
178  $this->path = stripslashes($this->path);
179  }*/
180  // END PATCH WebDAV: Don't strip backslashes. Backslashes are a valid part of a unix filename!
181 
182 
183  // detect requested method names
184  $method = strtolower($_SERVER["REQUEST_METHOD"]);
185  $wrapper = "http_".$method;
186 
187  $this->writelog(__METHOD__.': Using request method: '.$method);
188 
189  // activate HEAD emulation by GET if no HEAD method found
190  if ($method == "head" && !method_exists($this, "head"))
191  {
192  $method = "get";
193  $this->writelog(__METHOD__.': Using head emulation by get.');
194  }
195 
196  if (method_exists($this, $wrapper) && ($method == "options" || method_exists($this, $method)))
197  {
198  $this->writelog(__METHOD__.': Calling wrapper: '.$wrapper);
199  $this->$wrapper(); // call method by name
200  }
201  else
202  { // method not found/implemented
203  if ($_SERVER["REQUEST_METHOD"] == "LOCK")
204  {
205  $this->writelog(__METHOD__.': Method not found/implemented. Sending 412');
206  $this->http_status("412 Precondition failed");
207  }
208  else
209  {
210  $this->writelog(__METHOD__.': Method not found/implemented. Sending allowd methods');
211  $this->http_status("405 Method not allowed");
212  header("Allow: ".join(", ", $this->_allow())); // tell client what's allowed
213  }
214  }
215  }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
_allow()
check for implemented HTTP methods
Definition: Server.php:1511
_check_if_header_conditions()
check if conditions from "If:" headers are meat
Definition: Server.php:1786
_urldecode($path)
private version of PHP urldecode
Definition: Server.php:1966
http_status($status)
set HTTP return status and mirror it in a private header
Definition: Server.php:1924
Add a drawing to the header
Definition: 04printing.php:69
_check_auth()
check authentication if check is implemented
Definition: Server.php:1573
writelog($message)
Writes a message to the logfile.,.
Definition: Server.php:2016
+ Here is the call graph for this function:

◆ writelog()

HTTP_WebDAV_Server::writelog (   $message)
private

Writes a message to the logfile.,.

Parameters
messageString.
Returns
void.

Definition at line 2016 of file Server.php.

References $DIC, $ilUser, and $log.

Referenced by http_OPTIONS(), and serveRequest().

2017  {
2018  global $DIC;
2019  $log = $DIC['log'];
2020  $ilUser = $DIC['ilUser'];
2021 
2022  $log->write(
2023  $ilUser->getLogin()
2024  .' DAV Server.'.str_replace("\n",";",$message)
2025  );
2026  }
$ilUser
Definition: imgupload.php:18
global $DIC
+ Here is the caller graph for this function:

Field Documentation

◆ $_http_status

HTTP_WebDAV_Server::$_http_status = "200 OK"

Definition at line 90 of file Server.php.

◆ $_if_header_uris

HTTP_WebDAV_Server::$_if_header_uris = array()

Definition at line 83 of file Server.php.

◆ $_prop_encoding

HTTP_WebDAV_Server::$_prop_encoding = "utf-8"

Definition at line 97 of file Server.php.

◆ $base_uri

HTTP_WebDAV_Server::$base_uri

Definition at line 54 of file Server.php.

◆ $dav_powered_by

HTTP_WebDAV_Server::$dav_powered_by = ""

Definition at line 76 of file Server.php.

◆ $http_auth_realm

HTTP_WebDAV_Server::$http_auth_realm = "PHP WebDAV"

Definition at line 69 of file Server.php.

◆ $path

◆ $uri


The documentation for this class was generated from the following file: