server.php
来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 1,998 行 · 第 1/5 页
PHP
1,998 行
/**
* UNLOCK implementation
*
* UNLOCK implementation
*
* @abstract
* @param array &$params
* @returns int HTTP-Statuscode
*/
/* abstract
function UNLOCK()
{
// dummy entry for PHPDoc
}
*/
// }}}
// }}}
// {{{ other abstract methods
// {{{ check_auth()
/**
* check authentication
*
* overload this method to retrieve and confirm authentication information
*
* @abstract
* @param string type Authentication type, e.g. "basic" or "digest"
* @param string username Transmitted username
* @param string passwort Transmitted password
* @returns bool Authentication status
*/
/* abstract
function checkAuth($type, $username, $password)
{
// dummy entry for PHPDoc
}
*/
// }}}
// {{{ checklock()
/**
* check lock status for a resource
*
* overload this method to return shared and exclusive locks
* active for this resource
*
* @abstract
* @param string resource Resource path to check
* @returns array An array of lock entries each consisting
* of 'type' ('shared'/'exclusive'), 'token' and 'timeout'
*/
/* abstract
function checklock($resource)
{
// dummy entry for PHPDoc
}
*/
// }}}
// }}}
// {{{ WebDAV HTTP method wrappers
// {{{ http_OPTIONS()
/**
* OPTIONS method handler
*
* The OPTIONS method handler creates a valid OPTIONS reply
* including Dav: and Allowed: heaers
* based on the implemented methods found in the actual instance
*
* @param void
* @return void
*/
function http_OPTIONS()
{
// Microsoft clients default to the Frontpage protocol
// unless we tell them to use WebDAV
header("MS-Author-Via: DAV");
// get allowed methods
$allow = $this->_allow();
// dav header
$dav = array(1); // assume we are always dav class 1 compliant
if (isset($allow['LOCK'])) {
$dav[] = 2; // dav class 2 requires that locking is supported
}
// tell clients what we found
$this->http_status("200 OK");
header("DAV: " .join(", ", $dav));
header("Allow: ".join(", ", $allow));
header("Content-length: 0");
}
// }}}
// {{{ http_PROPFIND()
/**
* PROPFIND method handler
*
* @param void
* @return void
*/
function http_PROPFIND()
{
$options = Array();
$files = Array();
$options["path"] = $this->path;
// search depth from header (default is "infinity)
if (isset($this->_SERVER['HTTP_DEPTH'])) {
$options["depth"] = $this->_SERVER["HTTP_DEPTH"];
} else {
$options["depth"] = "infinity";
}
// analyze request payload
$propinfo = new _parse_propfind("php://input");
if (!$propinfo->success) {
$this->http_status("400 Error");
return;
}
$options['props'] = $propinfo->props;
// call user handler
if (!$this->PROPFIND($options, $files)) {
$files = array("files" => array());
if (method_exists($this, "checkLock")) {
// is locked?
$lock = $this->checkLock($this->path);
if (is_array($lock) && count($lock)) {
$created = isset($lock['created']) ? $lock['created'] : time();
$modified = isset($lock['modified']) ? $lock['modified'] : time();
$files['files'][] = array("path" => $this->_slashify($this->path),
"props" => array($this->mkprop("displayname", $this->path),
$this->mkprop("creationdate", $created),
$this->mkprop("getlastmodified", $modified),
$this->mkprop("resourcetype", ""),
$this->mkprop("getcontenttype", ""),
$this->mkprop("getcontentlength", 0))
);
}
}
if (empty($files['files'])) {
$this->http_status("404 Not Found");
return;
}
}
// collect namespaces here
$ns_hash = array();
// Microsoft Clients need this special namespace for date and time values
$ns_defs = "xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\"";
// now we loop over all returned file entries
foreach ($files["files"] as $filekey => $file) {
// nothing to do if no properties were returend for a file
if (!isset($file["props"]) || !is_array($file["props"])) {
continue;
}
// now loop over all returned properties
foreach ($file["props"] as $key => $prop) {
// as a convenience feature we do not require that user handlers
// restrict returned properties to the requested ones
// here we strip all unrequested entries out of the response
switch($options['props']) {
case "all":
// nothing to remove
break;
case "names":
// only the names of all existing properties were requested
// so we remove all values
unset($files["files"][$filekey]["props"][$key]["val"]);
break;
default:
$found = false;
// search property name in requested properties
foreach ((array)$options["props"] as $reqprop) {
if ( $reqprop["name"] == $prop["name"]
&& @$reqprop["xmlns"] == $prop["ns"]) {
$found = true;
break;
}
}
// unset property and continue with next one if not found/requested
if (!$found) {
$files["files"][$filekey]["props"][$key]="";
continue(2);
}
break;
}
// namespace handling
if (empty($prop["ns"])) continue; // no namespace
$ns = $prop["ns"];
if ($ns == "DAV:") continue; // default namespace
if (isset($ns_hash[$ns])) continue; // already known
// register namespace
$ns_name = "ns".(count($ns_hash) + 1);
$ns_hash[$ns] = $ns_name;
$ns_defs .= " xmlns:$ns_name=\"$ns\"";
}
// we also need to add empty entries for properties that were requested
// but for which no values where returned by the user handler
if (is_array($options['props'])) {
foreach ($options["props"] as $reqprop) {
if ($reqprop['name']=="") continue; // skip empty entries
$found = false;
// check if property exists in result
foreach ($file["props"] as $prop) {
if ( $reqprop["name"] == $prop["name"]
&& @$reqprop["xmlns"] == $prop["ns"]) {
$found = true;
break;
}
}
if (!$found) {
if ($reqprop["xmlns"]==="DAV:" && $reqprop["name"]==="lockdiscovery") {
// lockdiscovery is handled by the base class
$files["files"][$filekey]["props"][]
= $this->mkprop("DAV:",
"lockdiscovery",
$this->lockdiscovery($files["files"][$filekey]['path']));
} else {
// add empty value for this property
$files["files"][$filekey]["noprops"][] =
$this->mkprop($reqprop["xmlns"], $reqprop["name"], "");
// register property namespace if not known yet
if ($reqprop["xmlns"] != "DAV:" && !isset($ns_hash[$reqprop["xmlns"]])) {
$ns_name = "ns".(count($ns_hash) + 1);
$ns_hash[$reqprop["xmlns"]] = $ns_name;
$ns_defs .= " xmlns:$ns_name=\"$reqprop[xmlns]\"";
}
}
}
}
}
}
// now we generate the reply header ...
$this->http_status("207 Multi-Status");
header('Content-Type: text/xml; charset="utf-8"');
// ... and payload
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
echo "<D:multistatus xmlns:D=\"DAV:\">\n";
foreach ($files["files"] as $file) {
// ignore empty or incomplete entries
if (!is_array($file) || empty($file) || !isset($file["path"])) continue;
$path = $file['path'];
if (!is_string($path) || $path==="") continue;
echo " <D:response $ns_defs>\n";
/* TODO right now the user implementation has to make sure
collections end in a slash, this should be done in here
by checking the resource attribute */
$href = $this->_mergePathes($this->_SERVER['SCRIPT_NAME'], $path);
echo " <D:href>$href</D:href>\n";
// report all found properties and their values (if any)
if (isset($file["props"]) && is_array($file["props"])) {
echo " <D:propstat>\n";
echo " <D:prop>\n";
foreach ($file["props"] as $key => $prop) {
if (!is_array($prop)) continue;
if (!isset($prop["name"])) continue;
if (!isset($prop["val"]) || $prop["val"] === "" || $prop["val"] === false) {
// empty properties (cannot use empty() for check as "0" is a legal value here)
if ($prop["ns"]=="DAV:") {
echo " <D:$prop[name]/>\n";
} else if (!empty($prop["ns"])) {
echo " <".$ns_hash[$prop["ns"]].":$prop[name]/>\n";
} else {
echo " <$prop[name] xmlns=\"\"/>";
}
} else if ($prop["ns"] == "DAV:") {
// some WebDAV properties need special treatment
switch ($prop["name"]) {
case "creationdate":
echo " <D:creationdate ns0:dt=\"dateTime.tz\">"
. gmdate("Y-m-d\\TH:i:s\\Z", $prop['val'])
. "</D:creationdate>\n";
break;
case "getlastmodified":
echo " <D:getlastmodified ns0:dt=\"dateTime.rfc1123\">"
. gmdate("D, d M Y H:i:s ", $prop['val'])
. "GMT</D:getlastmodified>\n";
break;
case "resourcetype":
echo " <D:resourcetype><D:$prop[val]/></D:resourcetype>\n";
break;
case "supportedlock":
echo " <D:supportedlock>$prop[val]</D:supportedlock>\n";
break;
case "lockdiscovery":
echo " <D:lockdiscovery>\n";
echo $prop["val"];
echo " </D:lockdiscovery>\n";
break;
default:
echo " <D:$prop[name]>"
. $this->_prop_encode(htmlspecialchars($prop['val']))
. "</D:$prop[name]>\n";
break;
}
} else {
// properties from namespaces != "DAV:" or without any namespace
if ($prop["ns"]) {
echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]>"
. $this->_prop_encode(htmlspecialchars($prop['val']))
. "</" . $ns_hash[$prop["ns"]] . ":$prop[name]>\n";
} else {
echo " <$prop[name] xmlns=\"\">"
. $this->_prop_encode(htmlspecialchars($prop['val']))
. "</$prop[name]>\n";
}
}
}
echo " </D:prop>\n";
echo " <D:status>HTTP/1.1 200 OK</D:status>\n";
echo " </D:propstat>\n";
}
// now report all properties requested but not found
if (isset($file["noprops"])) {
echo " <D:propstat>\n";
echo " <D:prop>\n";
foreach ($file["noprops"] as $key => $prop) {
if ($prop["ns"] == "DAV:") {
echo " <D:$prop[name]/>\n";
} else if ($prop["ns"] == "") {
echo " <$prop[name] xmlns=\"\"/>\n";
} else {
echo " <" . $ns_hash[$prop["ns"]] . ":$prop[name]/>\n";
}
}
echo " </D:prop>\n";
echo " <D:status>HTTP/1.1 404 Not Found</D:status>\n";
echo " </D:propstat>\n";
}
echo " </D:response>\n";
}
echo "</D:multistatus>\n";
}
// }}}
// {{{ http_PROPPATCH()
/**
* PROPPATCH method handler
*
* @param void
* @return void
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?