ktwebdavserver.inc.php

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

PHP
1,547
字号
        $this->ktwebdavLog('REQUEST_URI is ' . $_SERVER['REQUEST_URI'], 'info', true);
        $this->ktwebdavLog('SCRIPT_NAME is ' . $_SERVER['SCRIPT_NAME'], 'info', true);
        $this->ktwebdavLog('PHP_SELF is ' . $_SERVER['PHP_SELF'], 'info', true);
        $this->ktwebdavLog('path set to ' . $this->path, 'info', true);

        // detect requested method names
        $method = strtolower($_SERVER['REQUEST_METHOD']);
        $wrapper = 'http_'.$method;

        $this->currentMethod = $method;
        // activate HEAD emulation by GET if no HEAD method found
        if ($method == 'head' && !method_exists($this, 'head')) {
            // rfc2068 Sec: 10.2.1
            //HEAD the entity-header fields corresponding to the requested resource
            //     are sent in the response without any message-body
            $method = 'get';
        }
        $this->ktwebdavLog("Entering $method request", 'info', true);

        if (method_exists($this, $wrapper) && ($method == 'options' || method_exists($this, $method))) {
            $this->$wrapper();  // call method by name
        } else { // method not found/implemented
            if ($_SERVER['REQUEST_METHOD'] == 'LOCK') {
                $this->http_status('412 Precondition failed');
            } else {
                $this->http_status('405 Method not allowed');
                header('Allow: '.join(', ', $this->_allow()));  // tell client what's allowed
            }
        }

        $this->ktwebdavLog("Exiting $method request", 'info', true);

    }


    /**
     * check authentication if check is implemented
     *
     * @param  void
     * @return bool  true if authentication succeded or not necessary
     */
    function _check_auth()
    {
        $this->ktwebdavLog('Entering _check_auth...', 'info', true);

        if (method_exists($this, 'checkAuth')) {
            // PEAR style method name
            return $this->checkAuth(@$_SERVER['AUTH_TYPE'],
                    @$_SERVER['PHP_AUTH_USER'],
                    @$_SERVER['PHP_AUTH_PW']);
        } else if (method_exists($this, 'check_auth')) {
            // old (pre 1.0) method name
            return $this->check_auth(@$_SERVER['AUTH_TYPE'],
                    @$_SERVER['PHP_AUTH_USER'],
                    @$_SERVER['PHP_AUTH_PW']);
        } else {
            // no method found -> no authentication required
            return true;
        }
    }

    /**
     * Authenticate user
     *
     * @access private
     * @param  string  HTTP Authentication type (Basic, Digest, ...)
     * @param  string  Username
     * @param  string  Password
     * @return bool    true on successful authentication
     */
    function checkAuth($sType, $sUser, $sPass) {

        $this->ktwebdavLog('Entering checkAuth params are: ', 'info', true);
        $this->ktwebdavLog('sType: ' . $sType, 'info', true);
        $this->ktwebdavLog('sUser: ' . $sUser, 'info', true);
        $this->ktwebdavLog('sPass: ' . $sPass, 'info', true);

        // Authenticate user

        require_once(KT_LIB_DIR . '/authentication/authenticationutil.inc.php');

        if ( empty($sUser) ) {
            $this->ktwebdavLog('sUser is empty, returning false.', 'info', true);
            return false;
        }

        if ( empty($sPass) ) {
            $this->ktwebdavLog('sPass is empty, returning false.', 'info', true);
            return false;
        }

        $sUser = iconv('ISO-8859-1', 'UTF-8', $sUser);
        $sPass = iconv('ISO-8859-1', 'UTF-8', $sPass);
        $oUser =& User::getByUsername($sUser);
        if (PEAR::isError($oUser) || ($oUser === false)) {
            $this->ktwebdavLog('User not found: ' . $sUser . '.', 'error');
            $this->lastMsg = 'User not found: ' . $sUser . '.';
            return false;
        }
        $authenticated = KTAuthenticationUtil::checkPassword($oUser, $sPass);

        if ($authenticated === false) {
            $this->ktwebdavLog('Password incorrect for ' . $sUser . '.', 'error');
            $this->lastMsg = 'Password incorrect for ' . $sUser . '.';
            return false;
        }

        if (PEAR::isError($authenticated)) {
            $this->ktwebdavLog('Password incorrect for ' . $sUser . '.', 'error');
            $this->lastMsg = 'Password incorrect for ' . $sUser . '.';
            return false;
        }

        $oUser->setLastLogin(date('Y-m-d H:i:s'));
        $oUser->update();

        $this->ktwebdavLog('Session ID is: '.$sessionID, 'info', true);
        $this->ktwebdavLog('UserID is: ' . $oUser->getId(), 'info', true );
        $this->_setUserID($oUser->getId());
        $_SESSION['userID'] = $this->_getUserID();
        $this->ktwebdavLog('SESSION UserID is: ' . $_SESSION['userID'], 'info', true );

        $this->ktwebdavLog("Authentication Success.", 'info', true);

        return true;
    }

    /**
     * PROPFIND method handler
     *
     * @param  array  options
     * @param  array  return array for file properties
     * @return bool   true on success
     */
    function PROPFIND(&$options, &$files) {

        $this->ktwebdavLog("Entering PROPFIND. options are " . print_r($options, true), 'info', true);

        global $default;

        $fspath = $default->documentRoot . "/" . $this->rootFolder . $options["path"];
        $this->ktwebdavLog("fspath is " . $fspath, 'info', true);

        $path = $options["path"];

        // Fix for the Mac Goliath Client
        // Mac adds DS_Store files when folders are added and ._filename files when files are added
        // The PUT function doesn't add these files to the dms but PROPFIND still looks for the .DS_Store file,
        // and returns an error if not found. We emulate its existence by returning a positive result.
        if($this->dav_client == 'MG'){
            // Remove filename from path
            $aPath = explode('/', $path);
            $fileName = $aPath[count($aPath)-1];

            if(strtolower($fileName) == '.ds_store'){
                $this->ktwebdavLog("Using a Mac client. Filename is .DS_Store so we emulate a positive result.", 'info', true);
                // ignore
                return true;
            }
            if($fileName[0] == '.' && $fileName[1] == '_'){
                $this->ktwebdavLog("Using a Mac client. Filename is ._Filename so we emulate a positive result.", 'info', true);
                // ignore
                return true;
            }
        }

        list($iFolderID, $iDocumentID) = $this->_folderOrDocument($path);
        $this->ktwebdavLog("Folder/Doc is " . print_r(array($iFolderID, $iDocumentID), true), 'info', true);

        // Folder does not exist
        if($iFolderID == '') return false;

        if (is_null($iDocumentID)) {
            return $this->_PROPFINDFolder($options, $files, $iFolderID);
        }
        return $this->_PROPFINDDocument($options, $files, $iDocumentID);

    }

    /**
     * PROPFIND helper for Folders
     *
     * @param array  options
     * @param array  Return array for file props
     * @param int  Folder ID
     * @return bool   true on success
     */
    function _PROPFINDFolder(&$options, &$files, $iFolderID) {

        global $default;

        $this->ktwebdavLog("Entering PROPFINDFolder. options are " . print_r($options, true), 'info', true);

        $folder_path = $options["path"];
        if (substr($folder_path, -1) != "/") {
            $folder_path .= "/";
        }
        $options["path"] = $folder_path;

        $files["files"] = array();
        $files["files"][] = $this->_fileinfoForFolderID($iFolderID, $folder_path);

        $oPerm =& KTPermission::getByName('ktcore.permissions.read');
        $oUser =& User::get($this->userID);

        if (!empty($options["depth"])) {
            $aChildren = Folder::getList(array('parent_id = ?', $iFolderID));
            // FIXME: Truncation Time Workaround
            //foreach (array_slice($aChildren, 0, 50) as $oChildFolder) {
            foreach ($aChildren as $oChildFolder) {
                // Check if the user has permissions to view this folder
                $oFolderDetailsPerm =& KTPermission::getByName('ktcore.permissions.folder_details');

                if(KTPermissionUtil::userHasPermissionOnItem($oUser, $oFolderDetailsPerm, $oChildFolder))
                {
                    $this->ktwebdavLog("Folder Details permissions GRANTED for user ". $_SESSION["userID"] ." on folder " . $oChildFolder->getName(), 'info', true);
                    $files["files"][] = $this->_fileinfoForFolder($oChildFolder, $folder_path . $oChildFolder->getName());
                }
                else
                {
                    $this->ktwebdavLog("Folder Details permissions DENIED for ". $_SESSION["userID"] ." on folder " . $oChildFolder->getName(), 'info', true);
                }
            }
            $aDocumentChildren = Document::getList(array('folder_id = ? AND status_id = 1', $iFolderID));
            // FIXME: Truncation Time Workaround
            //foreach (array_slice($aDocumentChildren, 0, 50) as $oChildDocument) {
            foreach ($aDocumentChildren as $oChildDocument) {
                // Check if the user has permissions to view this document
                if (KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oChildDocument)) {
                    $this->ktwebdavLog("Read permissions GRANTED for ". $_SESSION["userID"] ." on document " . $oChildDocument->getName(), 'info', true);
                    $files["files"][] = $this->_fileinfoForDocument($oChildDocument, $folder_path . $oChildDocument->getFileName());
                } else $this->ktwebdavLog("Read permissions DENIED for ". $_SESSION["userID"] ." on document " . $oChildDocument->getName(), 'info', true);
            }
        }
        return true;
        }

        /**
         * PROPFIND helper for Documents
         *
         * @param array  options
         * @param array  Return array for file props
         * @param int  Document ID
         * @return bool   true on success
         */
        function _PROPFINDDocument(&$options, &$files, $iDocumentID) {

            global $default;

            $this->ktwebdavLog("Entering PROPFINDDocument. files are " . print_r($files, true), 'info', true);

            $res = $this->_fileinfoForDocumentID($iDocumentID, $options["path"]);
            $this->ktwebdavLog("_fileinfoForDocumentID result is " . print_r($res, true), 'info', true);
            if ($res === false) {
                return false;
            }
            $files["files"] = array();
            $files["files"][] = $res;
            return true;
        }

        /**
         * PROPFIND helper for Document Info
         *
         * @param Document  Document Object
         * @param string    Path
         * @return array    Doc info array
         */
        function _fileinfoForDocument(&$oDocument, $path) {

            global $default;

            $this->ktwebdavLog("Entering _fileinfoForDocument. Document is " . print_r($oDocument, true), 'info', true);

            $fspath = $default->documentRoot . "/" . $this->rootFolder . $path;
            $this->ktwebdavLog("fspath is " . $fspath, 'info', true);

            // create result array
            // Modified - 25/10/07 - spaces prevent files displaying in finder
            if($this->dav_client == 'MC'){
                $path = str_replace('%2F', '/', urlencode($path));
            }
            $path = str_replace('&', '%26', $path);

            $info = array();
            $info["path"]  = $path;
            $info["props"] = array();

            // no special beautified displayname here ...
            $info["props"][] = $this->mkprop("displayname", $oDocument->getName());

            // creation and modification time
            $info["props"][] = $this->mkprop("creationdate", strtotime($oDocument->getCreatedDateTime()));
            $info["props"][] = $this->mkprop("getlastmodified", strtotime($oDocument->getVersionCreated()));

            // plain file (WebDAV resource)
            $info["props"][] = $this->mkprop("resourcetype", '');
            // FIXME: Direct database access
            $sQuery = array("SELECT mimetypes FROM $default->mimetypes_table WHERE id = ?", array($oDocument->getMimeTypeID()));
            $res = DBUtil::getOneResultKey($sQuery, 'mimetypes');
            $info["props"][] = $this->mkprop("getcontenttype", $res);

            $info["props"][] = $this->mkprop("getcontentlength", $oDocument->getFileSize());

            // explorer wants these?
            $info["props"][] = $this->mkprop("name", '');
            $info["props"][] = $this->mkprop("parentname", '');
            $info["props"][] = $this->mkprop("href", '');
            $info["props"][] = $this->mkprop("ishidden", '');
            $info["props"][] = $this->mkprop("iscollection", '');

⌨️ 快捷键说明

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