server.php.svn-base

来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· SVN-BASE 代码 · 共 2,047 行 · 第 1/5 页

SVN-BASE
2,047
字号
     *     * @param  string  header string to parse     * @param  int     current parsing position     * @return array   next token (type and value)     */    function _if_header_lexer($string, &$pos)     {        // skip whitespace        while (ctype_space($string{$pos})) {            ++$pos;        }        // already at end of string?        if (strlen($string) <= $pos) {            return false;        }        // get next character        $c = $string{$pos++};        // now it depends on what we found        switch ($c) {        case "<":            // URIs are enclosed in <...>            $pos2 = strpos($string, ">", $pos);            $uri  = substr($string, $pos, $pos2 - $pos);            $pos  = $pos2 + 1;            return array("URI", $uri);        case "[":            //Etags are enclosed in [...]            if ($string{$pos} == "W") {                $type = "ETAG_WEAK";                $pos += 2;            } else {                $type = "ETAG_STRONG";            }            $pos2 = strpos($string, "]", $pos);            $etag = substr($string, $pos + 1, $pos2 - $pos - 2);            $pos  = $pos2 + 1;            return array($type, $etag);        case "N":            // "N" indicates negation            $pos += 2;            return array("NOT", "Not");        default:            // anything else is passed verbatim char by char            return array("CHAR", $c);        }    }    /**      * parse If: header     *     * @param  string  header string     * @return array   URIs and their conditions     */    function _if_header_parser($str)     {        $pos  = 0;        $len  = strlen($str);        $uris = array();        // parser loop        while ($pos < $len) {            // get next token            $token = $this->_if_header_lexer($str, $pos);            // check for URI            if ($token[0] == "URI") {                $uri   = $token[1]; // remember URI                $token = $this->_if_header_lexer($str, $pos); // get next token            } else {                $uri = "";            }            // sanity check            if ($token[0] != "CHAR" || $token[1] != "(") {                return false;            }            $list  = array();            $level = 1;            $not   = "";            while ($level) {                $token = $this->_if_header_lexer($str, $pos);                if ($token[0] == "NOT") {                    $not = "!";                    continue;                }                switch ($token[0]) {                case "CHAR":                    switch ($token[1]) {                    case "(":                        $level++;                        break;                    case ")":                        $level--;                        break;                    default:                        return false;                    }                    break;                case "URI":                    $list[] = $not."<$token[1]>";                    break;                case "ETAG_WEAK":                    $list[] = $not."[W/'$token[1]']>";                    break;                case "ETAG_STRONG":                    $list[] = $not."['$token[1]']>";                    break;                default:                    return false;                }                $not = "";            }            if (@is_array($uris[$uri])) {                $uris[$uri] = array_merge($uris[$uri], $list);            } else {                $uris[$uri] = $list;            }        }        return $uris;    }    /**     * 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     *     * @param  void     * @return void     */    function _check_if_header_conditions()     {        if (isset($this->_SERVER["HTTP_IF"])) {            $this->_if_header_uris =                $this->_if_header_parser($this->_SERVER["HTTP_IF"]);            foreach ($this->_if_header_uris as $uri => $conditions) {                if ($uri == "") {                    $uri = $this->uri;                }                // all must match                $state = true;                foreach ($conditions as $condition) {                    // lock tokens may be free form (RFC2518 6.3)                    // but if opaquelocktokens are used (RFC2518 6.4)                    // we have to check the format (litmus tests this)                    if (!strncmp($condition, "<opaquelocktoken:", strlen("<opaquelocktoken"))) {                        if (!preg_match('/^<opaquelocktoken:[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}>$/', $condition)) {                            $this->http_status("423 Locked");                            return false;                        }                    }                    if (!$this->_check_uri_condition($uri, $condition)) {                        $this->http_status("412 Precondition failed");                        $state = false;                        break;                    }                }                // any match is ok                if ($state == true) {                    return true;                }            }            return false;        }        return true;    }    /**     * Check a single URI condition parsed from an if-header     *     * Check a single URI condition parsed from an if-header     *     * @abstract      * @param string $uri URI to check     * @param string $condition Condition to check for this URI     * @returns bool Condition check result     */    function _check_uri_condition($uri, $condition)     {        // not really implemented here,         // implementations must override        // a lock token can never be from the DAV: scheme        // litmus uses DAV:no-lock in some tests        if (!strncmp("<DAV:", $condition, 5)) {            return false;        }        return true;    }    /**     *      *     * @param  string  path of resource to check     * @param  bool    exclusive lock?     */    function _check_lock_status($path, $exclusive_only = false)     {        // FIXME depth -> ignored for now        if (method_exists($this, "checkLock")) {            // is locked?            $lock = $this->checkLock($path);            // ... and lock is not owned?            if (is_array($lock) && count($lock)) {                // FIXME doesn't check uri restrictions yet                if (!isset($this->_SERVER["HTTP_IF"]) || !strstr($this->_SERVER["HTTP_IF"], $lock["token"])) {                    if (!$exclusive_only || ($lock["scope"] !== "shared"))                        return false;                }            }        }        return true;    }    // }}}    /**     * Generate lockdiscovery reply from checklock() result     *     * @param   string  resource path to check     * @return  string  lockdiscovery response     */    function lockdiscovery($path)     {        // no lock support without checklock() method        if (!method_exists($this, "checklock")) {            return "";        }        // collect response here        $activelocks = "";        // get checklock() reply        $lock = $this->checklock($path);        // generate <activelock> block for returned data        if (is_array($lock) && count($lock)) {            // check for 'timeout' or 'expires'            if (!empty($lock["expires"])) {                $timeout = "Second-".($lock["expires"] - time());            } else if (!empty($lock["timeout"])) {                $timeout = "Second-$lock[timeout]";            } else {                $timeout = "Infinite";            }            // genreate response block            $activelocks.= "              <D:activelock>               <D:lockscope><D:$lock[scope]/></D:lockscope>               <D:locktype><D:$lock[type]/></D:locktype>               <D:depth>$lock[depth]</D:depth>               <D:owner>$lock[owner]</D:owner>               <D:timeout>$timeout</D:timeout>               <D:locktoken><D:href>$lock[token]</D:href></D:locktoken>              </D:activelock>             ";        }        // return generated response        return $activelocks;    }    /**     * set HTTP return status and mirror it in a private header     *     * @param  string  status code and message     * @return void     */    function http_status($status)     {        // simplified success case        if ($status === true) {            $status = "200 OK";        }        // remember status        $this->_http_status = $status;        // generate HTTP status response        header("HTTP/1.1 $status");        header("X-WebDAV-Status: $status", true);    }    /**     * private minimalistic version of PHP urlencode()     *     * only blanks and XML special chars must be encoded here     * full urlencode() encoding confuses some clients ...     *     * @param  string  URL to encode     * @return string  encoded URL     */    function _urlencode($url)     {        return strtr($url, array(" "=>"%20",                                 "&"=>"%26",                                 "<"=>"%3C",                                 ">"=>"%3E",                                 ));    }    /**     * private version of PHP urldecode     *     * not really needed but added for completenes     *     * @param  string  URL to decode     * @return string  decoded URL     */    function _urldecode($path)     {        return urldecode($path);    }    /**     * UTF-8 encode property values if not already done so     *     * @param  string  text to encode     * @return string  utf-8 encoded text     */    function _prop_encode($text)     {        switch (strtolower($this->_prop_encoding)) {        case "utf-8":            return $text;        case "iso-8859-1":        case "iso-8859-15":        case "latin-1":        default:            return utf8_encode($text);        }    }    /**     * Slashify - make sure path ends in a slash     *     * @param   string directory path     * @returns string directory path wiht trailing slash     */    function _slashify($path)     {        if ($path[strlen($path)-1] != '/') {            $path = $path."/";        }        return $path;    }    /**     * Unslashify - make sure path doesn't in a slash     *     * @param   string directory path     * @returns string directory path wihtout trailing slash     */    function _unslashify($path)     {        if ($path[strlen($path)-1] == '/') {            $path = substr($path, 0, strlen($path) -1);        }        return $path;    }    /**     * Merge two pathes, make sure there is exactly one slash between them     *     * @param  string  parent path     * @param  string  child path     * @return string  merged path     */    function _mergePathes($parent, $child)     {        if ($child{0} == '/') {            return $this->_unslashify($parent).$child;        } else {            return $this->_slashify($parent).$child;        }    }} /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?