| <?php |
| /** |
| * File containing the ezcWebdavTransport class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Webdav |
| * @version //autogentag// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| /** |
| * Transport layer mainclass that implements RFC compliant client communication. |
| * |
| * This basis transport class is able to interact with RFC 2518 compliant |
| * WebDAV clients. It can parse all request types defined in the RFC into the |
| * abstraction layer of the Webdav component, defined by the base classes |
| * mentioned below. An exception are LOCK related requests, which will be |
| * handled by a plugin. |
| * |
| * To adjust this base transport layer main class to the needs of |
| * RFC-2518-inconform client implementations, there is the powerful |
| * possibility of extending this class and overwriting certain necessary |
| * protected methods. The easier way to adjust smaller issues is to replace one |
| * of the helper components during construction of via property access. |
| * |
| * The {@link ezcWebdavServer->xmlTool} property will be used which is |
| * accessed for different XML related operations. Exchanging this one will |
| * allow you to manipulate the XML handling for the transport layer in |
| * general. |
| * |
| * The {@link ezcWebdavServer->propertyHandler} property, of type {@link |
| * ezcWebdavPropertyHandler} will be used in the accordingly named property and |
| * is responsible for extracting WebDAV properties from a {@link DOMElement} |
| * and to serialize them back to one. |
| * |
| * The {@link ezcWebdavServer->pathFactory} property must be an instance of |
| * {@link ezcWebdavPathFactory} and is used to convert between internal WebDAV |
| * paths (resource locations understood by the {@link ezcWebdavBackend}) and |
| * URIs that reference a resource on the web. |
| * |
| * An instance of this class is by default capable of parsing the follwoing |
| * HTTP request methods: |
| * <ul> |
| * <li>COPY</li> |
| * <li>DELETE</li> |
| * <li>GET</li> |
| * <li>HEAD</li> |
| * <li>MKCOL</li> |
| * <li>MOVE</li> |
| * <li>OPTIONS</li> |
| * <li>PROPFIND</li> |
| * <li>PROPPATCH'</li> |
| * <li>PUT</li> |
| * </ul> |
| * |
| * The transport implementation is capable of handling the following response |
| * classes and output the to the client: |
| * <ul> |
| * <li>{@link ezcWebdavCopyResponse}</li> |
| * <li>{@link ezcWebdavDeleteResponse}</li> |
| * <li>{@link ezcWebdavErrorResponse}</li> |
| * <li>{@link ezcWebdavGetCollectionResponse}</li> |
| * <li>{@link ezcWebdavGetResourceResponse}</li> |
| * <li>{@link ezcWebdavHeadResponse}</li> |
| * <li>{@link ezcWebdavMakeCollectionResponse}</li> |
| * <li>{@link ezcWebdavMoveResponse}</li> |
| * <li>{@link ezcWebdavMultiStatusResponse}</li> |
| * <li>{@link ezcWebdavOptionsResponse}</li> |
| * <li>{@link ezcWebdavPropFindResponse}</li> |
| * <li>{@link ezcWebdavPropPatchResponse}</li> |
| * <li>{@link ezcWebdavPutResponse}</li> |
| * </ul> |
| * |
| * @see ezcWebdavRequest |
| * @see ezcWebdavResponse |
| * @see ezcWebdavProperty |
| * @link http://tools.ietf.org/html/rfc2518 RFC 2518 |
| * |
| * @version //autogentag// |
| * @package Webdav |
| */ |
| class ezcWebdavTransport |
| { |
| /** |
| * Used for server software string in Server header. |
| */ |
| const VERSION = '//autogentag//'; |
| |
| /** |
| * Map of HTTP methods to object method names for parsing. |
| * |
| * Need public access here to retrieve this in {@link |
| * ezcWebdavPluginRegistry}. |
| * |
| * @var array(string=>string) |
| * @access private |
| */ |
| static public $parsingMap = array( |
| 'COPY' => 'parseCopyRequest', |
| 'DELETE' => 'parseDeleteRequest', |
| 'GET' => 'parseGetRequest', |
| 'HEAD' => 'parseHeadRequest', |
| 'MKCOL' => 'parseMakeCollectionRequest', |
| 'MOVE' => 'parseMoveRequest', |
| 'OPTIONS' => 'parseOptionsRequest', |
| 'PROPFIND' => 'parsePropFindRequest', |
| 'PROPPATCH' => 'parsePropPatchRequest', |
| 'PUT' => 'parsePutRequest', |
| ); |
| |
| /** |
| * Map of response objects to handling methods. |
| * |
| * Need public access here to retrieve this in {@link |
| * ezcWebdavPluginRegistry}. |
| * |
| * @var array(string=>string) |
| * @access private |
| */ |
| static public $handlingMap = array( |
| 'ezcWebdavCopyResponse' => 'processCopyResponse', |
| 'ezcWebdavDeleteResponse' => 'processDeleteResponse', |
| 'ezcWebdavErrorResponse' => 'processErrorResponse', |
| 'ezcWebdavGetCollectionResponse' => 'processGetCollectionResponse', |
| 'ezcWebdavGetResourceResponse' => 'processGetResourceResponse', |
| 'ezcWebdavHeadResponse' => 'processHeadResponse', |
| 'ezcWebdavMakeCollectionResponse' => 'processMakeCollectionResponse', |
| 'ezcWebdavMoveResponse' => 'processMoveResponse', |
| 'ezcWebdavMultistatusResponse' => 'processMultiStatusResponse', |
| 'ezcWebdavOptionsResponse' => 'processOptionsResponse', |
| 'ezcWebdavPropFindResponse' => 'processPropFindResponse', |
| 'ezcWebdavPropPatchResponse' => 'processPropPatchResponse', |
| 'ezcWebdavPutResponse' => 'processPutResponse', |
| ); |
| |
| /** |
| * Properties. |
| * |
| * @var array(string=>mixed) |
| */ |
| protected $properties = array(); |
| |
| /** |
| * Parses the incoming request into a fitting request abstraction object. |
| * |
| * This method is the main entry point of {@link ezcWebdavServer} and is |
| * utilized by it to parse the incoming request into an instance of {@link |
| * ezcWebdavRequest}. |
| * |
| * The submitted $uri must be formatted in a way, that the {@link |
| * ezcWebdavPathFactory} (by default this is {@link |
| * ezcWebdavAutomaticPathFactory}) can convert it into a path absolute to |
| * the base of the WebDAV repository. |
| * |
| * The retrieval of the request body is performed by the {@link |
| * retrieveBody()} method, the request method from {@link |
| * $_SERVER['REQUEST_METHOD']}. The latter one is mapped through the |
| * {@link self::$parsingMap} attribute to a local object method. |
| * |
| * This method is marked final and may not be overwritten, because it |
| * belongs to the essential communication API with {@link ezcWebdavServer} |
| * and is responsible to dispatch the {@link ezcWebdavPluginRegistry} hooks |
| * of the transport layer. NOTE: The plugin API is not public, yet, and |
| * will be part of a next release. |
| * |
| * If an error occurs during request parsing, an instance of {@link |
| * ezcWebdavResponse} may be returned instead of an instance of {@link |
| * ezcWebdavRequest}. {@link ezcWebdavServer} will handle this correctly. |
| * |
| * @param string $uri |
| * @return ezcWebdavRequest|ezcWebdavResponse |
| */ |
| public final function parseRequest( $uri ) |
| { |
| $body = $this->retrieveBody(); |
| $path = $this->retrievePath( $uri ); |
| |
| if ( isset( self::$parsingMap[$_SERVER['REQUEST_METHOD']] ) ) |
| { |
| try |
| { |
| // Plugin hook beforeParseRequest |
| ezcWebdavServer::getInstance()->pluginRegistry->announceHook( |
| __CLASS__, |
| 'beforeParseRequest', |
| new ezcWebdavPluginParameters( |
| array( |
| 'path' => &$path, |
| 'body' => &$body, |
| ) |
| ) |
| ); |
| |
| $request = call_user_func( array( $this, self::$parsingMap[$_SERVER['REQUEST_METHOD']] ), $path, $body ); |
| } |
| catch ( Exception $e ) |
| { |
| return $this->handleException( $e, $uri ); |
| } |
| } |
| else |
| { |
| // Plugin hook parseUnknownRequest |
| $request = ezcWebdavServer::getInstance()->pluginRegistry->announceHook( |
| __CLASS__, |
| 'parseUnknownRequest', |
| new ezcWebdavPluginParameters( |
| array( |
| 'path' => &$path, |
| 'body' => &$body, |
| 'requestMethod' => &$_SERVER['REQUEST_METHOD'], |
| ) |
| ) |
| ); |
| |
| // If hooks did not return a valid request object, generate error |
| if ( !( $request instanceof ezcWebdavRequest ) && !( $request instanceof ezcWebdavResponse ) ) |
| { |
| // Error code 501: Not implemented |
| return new ezcWebdavErrorResponse( |
| ezcWebdavResponse::STATUS_501, |
| $uri |
| ); |
| } |
| } |
| $request->validateHeaders(); |
| |
| return $request; |
| } |
| |
| /** |
| * Handle a response and send it to the WebDAV client. |
| * |
| * This method is part of the integral communication API between the WebDAV |
| * client and the {@link ezcWebdavServer}. It is declared final to ensure a |
| * minimal compatibile API between the extended classes and it is |
| * responsible to dispatch the {@link ezcWebdavPluginRegistry} hooks. NOTE: |
| * The plugin API is not public, yet, and will be part of a next release. |
| * |
| * It currently just maps internally to {@link processResponse()} and |
| * passes the result to {@ $this->sendResponse()}. It is not recommended |
| * that the {@link $this->processResponse()} method is overwritten, because |
| * this one takes care about the dispatching. The {@link |
| * $this->sendResponse()} may be overwritten, mainly for debugging, testing |
| * and logging purposes. |
| * |
| * @param ezcWebdavResponse $response |
| * @return void |
| */ |
| public final function handleResponse( ezcWebdavResponse $response ) |
| { |
| // Set the Server header with information about eZ Components version |
| // and transport implementation. |
| $headers = ezcWebdavServer::getInstance()->headerHandler->parseHeaders( array( 'Server' ) ); |
| |
| $response->setHeader( |
| 'Server', |
| ( isset( $headers['Server'] ) && strlen( $headers['Server'] ) > 0 ? $headers['Server'] . '/' : '' ) |
| . 'eZComponents/' |
| . ( self::VERSION === '//auto'. 'gentag//' ? 'dev' : self::VERSION ) |
| . '/' |
| . get_class( $this ) |
| ); |
| |
| try |
| { |
| $response->validateHeaders(); |
| $this->sendResponse( $this->flattenResponse( $this->processResponse( $response ) ) ); |
| } |
| catch ( Exception $e ) |
| { |
| if ( $response instanceof ezcWebdavErrorResponse ) |
| { |
| // Attention: Recursion detected! |
| throw $e; |
| } |
| $this->handleResponse( $this->handleException( $e ) ); |
| throw $e; |
| } |
| } |
| |
| /** |
| * Handle a thrown exception and generate an error response from it. |
| * |
| * Takes the given exception $e and generates a response object from it. |
| * The $uri parameter will be given to {@link |
| * ezcWebdavErrorResponse::__construct()}. |
| * |
| * For special exceptions, special responses will be generated: |
| * <ul> |
| * <li>ezcWebdavBadRequestException: 400 Bad Request</li> |
| * <li>ezcWebdavInvalidRequestMethodException: 501 Not Implemented</li> |
| * </ul> |
| * |
| * Per default, a 500 Internal Server Error response will be generated. |
| * |
| * Depending on where this is called, the generatedResponse hook will be |
| * issued (if during request parsing), but the processErrorResponse hooks |
| * will allways be called. NOTE: The plugin API is not public, yet, and |
| * will be part of a next release. |
| * |
| * @param Exception $e |
| * @param string $uri |
| * @return ezcWebdavErrorResponse |
| */ |
| protected function handleException( Exception $e, $uri = null ) |
| { |
| $message = ( php_sapi_name() !== 'cli' ? htmlspecialchars_decode( $e->getMessage() ) : $e->getMessage() ); |
| |
| switch ( true ) |
| { |
| case ( $e instanceof ezcWebdavBadRequestException ): |
| case ( $e instanceof ezcWebdavInvalidRequestBodyException ): |
| $code = ezcWebdavResponse::STATUS_400; |
| break; |
| |
| case ( $e instanceof ezcWebdavInvalidRequestMethodException ): |
| $code = ezcWebdavResponse::STATUS_501; |
| break; |
| |
| default: |
| $code = ezcWebdavResponse::STATUS_500; |
| break; |
| } |
| return new ezcWebdavErrorResponse( $code, $uri, $message ); |
| } |
| |
| /** |
| * Returns the body content of the request. |
| * |
| * This method is only kept for BC reasons. Please refer to {@link |
| * retrieveBody()}. |
| * |
| * @return string The request body. |
| * |
| * @apichange This method will be removed in the next major version. Please |
| * use {@link retrieveBody()} instead. |
| */ |
| protected function retreiveBody() |
| { |
| return $this->retrieveBody(); |
| } |
| |
| /** |
| * Returns the body content of the request. |
| * |
| * This method mainly exists for unit testing purpose. It reads the request |
| * body and returns the contents as a string. This method can also be |
| * usefull to be overriden during inheritence to filter the body of |
| * missbehaving WebDAV clients. |
| * |
| * @return string The request body. |
| */ |
| protected function retrieveBody() |
| { |
| $body = ''; |
| $in = fopen( 'php://input', 'r' ); |
| |
| while ( $data = fread( $in, 1024 ) ) |
| { |
| // This line is untestable, since it reads from STDIN and during |
| // testing there is no input to read. |
| // @codeCoverageIgnoreStart |
| $body .= $data; |
| } |
| // @codeCoverageIgnoreEnd |
| return $body; |
| } |
| |
| /** |
| * Returns the translated request path. |
| * |
| * This method calls the configured path factory to translate the |
| * submitted $uri into a local path. It can be overwritten to perform client |
| * specific path adjustments. |
| * |
| * @param string $uri |
| * @return string |
| */ |
| protected function retrievePath( $uri ) |
| { |
| return ezcWebdavServer::getInstance()->pathFactory->parseUriToPath( $uri ); |
| } |
| |
| /** |
| * Serializes a response object to XML. |
| * |
| * This method performs the internal dispatching of a given $response |
| * object. It determines the method to handle the response by {@link |
| * self::$handlingMap} and throws an Exception if the given class could not |
| * be dispatched. |
| * |
| * The method internally calls one of the handle*Response() methods to get |
| * the repsonse object processed and returns an instance of {@link |
| * ezcWebdavDisplayInformation} to be displayed. |
| * |
| * @param ezcWebdavResponse $response |
| * @return ezcWebdavDisplayInformation |
| * |
| * @throws ezcWebdavMissingHeaderException |
| * if the generated result is an {@link |
| * ezcWebdavStringDisplayInformation} struct and the contained |
| * {@link ezcWebdavResponse} object has no Content-Type header set. |
| * @throws ezcWebdavInvalidHeaderException |
| * if the generated result is an {@link |
| * ezcWebdavEmptyDisplayInformation} and the contained {@link |
| * ezcWebdavResponse} object has a Content-Type or a Content-Length |
| * header set. |
| */ |
| private function processResponse( ezcWebdavResponse $response ) |
| { |
| // Check if response can be processed by default |
| if ( !isset( self::$handlingMap[( $responseClass = get_class( $response ) )] ) ) |
| { |
| // Plugin hook processUnknownResponse |
| $result = ezcWebdavServer::getInstance()->pluginRegistry->announceHook( |
| __CLASS__, |
| 'processUnknownResponse', |
| new ezcWebdavPluginParameters( |
| array( |
| 'response' => $response, |
| ) |
| ) |
| ); |
| |
| if ( $result === null ) |
| { |
| // No plugin could process the response: 500 Internal Server Error |
| return $this->processResponse( new ezcWebdavErrorResponse( ezcWebdavResponse::STATUS_500 ) ); |
| } |
| else |
| { |
| return $result; |
| } |
| } |
| |
| $result = call_user_func( array( $this, self::$handlingMap[( $responseClass = get_class( $response ) )] ), $response ); |
| |
| // Plugin hook afterProcessResponse |
| ezcWebdavServer::getInstance()->pluginRegistry->announceHook( |
| __CLASS__, |
| 'afterProcessResponse', |
| new ezcWebdavPluginParameters( |
| array( |
| 'result' => $result, |
| ) |
| ) |
| ); |
| return $result; |
| } |
| |
| /** |
| * Flattens a processed response object to headers and body. |
| * |
| * Takes a given {@link ezcWebdavDisplayInformation} object and returns an |
| * array containg the headers and body it represents. |
| * |
| * The returned information can be processed (send out to the client) by |
| * {@link ezcWebdavTransport::sendResponse()}. |
| * |
| * @param ezcWebdavDisplayInformation $info |
| * @return ezcWebdavOutputResult |
| * |
| * @throws ezcWebdavMissingHeaderException |
| * if the generated result is an {@link |
| * ezcWebdavStringDisplayInformation} struct and the contained |
| * {@link ezcWebdavResponse} object has no Content-Type header set. |
| * @throws ezcWebdavInvalidHeaderException |
| * if the generated result is an {@link |
| * ezcWebdavEmptyDisplayInformation} and the contained {@link |
| * ezcWebdavResponse} object has a Content-Type or a Content-Length |
| * header set. |
| */ |
| protected function flattenResponse( ezcWebdavDisplayInformation $info ) |
| { |
| $output = new ezcWebdavOutputResult(); |
| $output->status = (string) $info->response; |
| $output->headers = $info->response->getHeaders(); |
| $output->body = ''; |
| |
| switch ( true ) |
| { |
| case ( $info instanceof ezcWebdavXmlDisplayInformation ): |
| $output->headers['Content-Type'] = ( isset( $output->headers['Content-Type'] ) ? $output->headers['Content-Type'] : 'text/xml; charset="utf-8"' ); |
| $info->body->formatOutput = true; |
| $output->body = $info->body->saveXML( $info->body ); |
| break; |
| case ( $info instanceof ezcWebdavStringDisplayInformation ): |
| if ( $info->response->getHeader( 'Content-Type' ) === null ) |
| { |
| throw new ezcWebdavMissingHeaderException( 'Content-Type' ); |
| } |
| $output->body = $info->body; |
| break; |
| case ( $info instanceof ezcWebdavEmptyDisplayInformation ): |
| default: |
| // Ensure a content length header is set |
| if ( ( $header = $info->response->getHeader( 'Content-Length' ) ) === null ) |
| { |
| $output->headers['Content-Length'] = 0; |
| } |
| break; |
| } |
| |
| return $output; |
| } |
| |
| /** |
| * Finally sends out the response. |
| * |
| * This method is called to finally send the response to the client. It |
| * can be overwritten in test cases to change the behaviour of printing out |
| * the result and sending the headers. |
| * |
| * @param ezcWebdavOutputResult $output |
| * @return void |
| */ |
| protected function sendResponse( ezcWebdavOutputResult $output ) |
| { |
| // Sends HTTP headers |
| foreach ( $output->headers as $name => $content ) |
| { |
| $content = is_array( $content ) ? $content : array( $content ); |
| $overwrite = true; |
| foreach ( $content as $contentLine ) |
| { |
| header( "{$name}: {$contentLine}", $overwrite ); |
| // Append additional values |
| $overwrite = false; |
| } |
| } |
| |
| // Send HTTP status code |
| header( $output->status ); |
| |
| // Content-Length header automatically send |
| echo $output->body; |
| } |
| |
| /* |
| *************************** |
| * Request handling follows. |
| *************************** |
| */ |
| |
| // GET |
| |
| /** |
| * Parses the GET request and returns a request object. |
| * |
| * This method is responsible for parsing the GET request. It retrieves the |
| * current request URI in $path and the request body as $body. The return |
| * value, if no exception is thrown, is a valid {@link |
| * ezcWebdavGetResourceResponse} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavGetRequest |
| */ |
| protected function parseGetRequest( $path, $body ) |
| { |
| $req = new ezcWebdavGetRequest( $path ); |
| $req->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| return $req; |
| } |
| |
| // PUT |
| |
| /** |
| * Parses the PUT request and returns a request object. |
| * |
| * This method is responsible for parsing the PUT request. It retrieves the |
| * current request URI in $path and the request body as $body. The return |
| * value, if no exception is thrown, is a valid {@link ezcWebdavPutRequest} |
| * object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavPutRequest |
| */ |
| protected function parsePutRequest( $path, $body ) |
| { |
| $req = new ezcWebdavPutRequest( $path, $body ); |
| $req->setHeaders( |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders( |
| array( |
| 'Content-Length', 'Content-Type' |
| ) |
| ) |
| ); |
| return $req; |
| } |
| |
| // HEAD |
| |
| /** |
| * Parses the HEAD request and returns a request object. |
| * |
| * This method is responsible for parsing the HEAD request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavHeadRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavHeadRequest |
| */ |
| protected function parseHeadRequest( $path, $body ) |
| { |
| $req = new ezcWebdavHeadRequest( $path ); |
| $req->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| return $req; |
| } |
| |
| // COPY |
| |
| /** |
| * Parses the COPY request and returns a request object. |
| * |
| * This method is responsible for parsing the COPY request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavCopyRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavCopyRequest |
| * |
| * @throws ezcWebdavInvalidRequestBodyException |
| * if the body of the copy request is invalid (XML wise or RFC |
| * wise). |
| */ |
| protected function parseCopyRequest( $path, $body ) |
| { |
| $headers = ezcWebdavServer::getInstance()->headerHandler->parseHeaders( |
| array( 'Destination', 'Depth', 'Overwrite' ) |
| ); |
| |
| if ( !isset( $headers['Destination'] ) ) |
| { |
| throw new ezcWebdavMissingHeaderException( 'Destination' ); |
| } |
| |
| $request = new ezcWebdavCopyRequest( $path, $headers['Destination'] ); |
| |
| $request->setHeaders( $headers ); |
| |
| if ( trim( $body ) === '' ) |
| { |
| // No body present |
| return $request; |
| } |
| |
| try |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom( $body ); |
| } |
| catch ( ezcWebdavInvalidXmlException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'COPY', |
| $e->getMessage() |
| ); |
| } |
| |
| if ( $dom->documentElement->localName !== 'propertybehavior' ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'COPY', |
| "Expected XML element <propertybehavior />, received <{$dom->documentElement->localName} />." |
| ); |
| } |
| |
| return $this->parsePropertyBehaviourContent( $dom, $request ); |
| } |
| |
| // MOVE |
| |
| /** |
| * Parses the MOVE request and returns a request object. |
| * |
| * This method is responsible for parsing the MOVE request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavMoveRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavMoveRequest |
| */ |
| protected function parseMoveRequest( $path, $body ) |
| { |
| $headers = ezcWebdavServer::getInstance()->headerHandler->parseHeaders( |
| array( 'Destination', 'Depth', 'Overwrite' ) |
| ); |
| |
| if ( !isset( $headers['Destination'] ) ) |
| { |
| throw new ezcWebdavMissingHeaderException( 'Destination' ); |
| } |
| |
| $request = new ezcWebdavMoveRequest( $path, $headers['Destination'] ); |
| |
| $request->setHeaders( $headers ); |
| |
| if ( trim( $body ) === '' ) |
| { |
| // No body present |
| return $request; |
| } |
| |
| try |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom( $body ); |
| } |
| catch ( ezcWebdavInvalidXmlException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'MOVE', |
| $e->getMessage() |
| ); |
| } |
| |
| if ( $dom->documentElement->localName !== 'propertybehavior' ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'MOVE', |
| "Expected XML element <propertybehavior />, received <{$dom->documentElement->localName} />." |
| ); |
| } |
| |
| return $this->parsePropertyBehaviourContent( $dom, $request ); |
| } |
| |
| /** |
| * Parses the <propertybehavior /> XML element. |
| * |
| * This element is part of the COPY and MOVE requests, which are handled by |
| * {@link $this->parseCopyRequest()} respectivly {@link |
| * $this->parseMoveRequest()}. |
| * |
| * The $dom parameter is the DOMDocument where the <propertybehavior /> |
| * content should be parsed from. The $request object submitted will get |
| * the resulting {@link ezcWebdavRequestPropertyBehaviourContent} set into |
| * its $propertyBehavior property. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * If you overwrite the {@link $this->processCopyResponse()} or {@link |
| * $this->parseMoveRequest()} methods, you might disable this method |
| * accedentally. You should explicitly use it there and overwrite it, if |
| * necessary. This makes extending your extended transport easier. |
| * |
| * @param DOMDocument $dom |
| * @param ezcWebdavRequest $request ezcWebdavCopyRequest or ezcWebdavMoveRequest |
| * @return ezcWebdavCopyRequest|ezcWebdavMoveRequest As submitted. |
| */ |
| protected function parsePropertyBehaviourContent( DOMDocument $dom, ezcWebdavRequest $request ) |
| { |
| $propertyBehaviourNode = $dom->documentElement; |
| |
| $request->propertyBehaviour = new ezcWebdavRequestPropertyBehaviourContent(); |
| switch ( $propertyBehaviourNode->firstChild->localName ) |
| { |
| case 'omit': |
| $request->propertyBehaviour->omit = true; |
| break; |
| case 'keepalive': |
| if ( $propertyBehaviourNode->firstChild->nodeValue === '*' ) |
| { |
| $request->propertyBehaviour->keepAlive = ezcWebdavRequestPropertyBehaviourContent::ALL; |
| } |
| else |
| { |
| $keepAliveContent = array(); |
| $hrefNodes = $propertyBehaviourNode->firstChild->getElementsByTagName( 'href' ); |
| |
| for ( $i = 0; $i < $hrefNodes->length; ++$i ) |
| { |
| $keepAliveContent[] = $hrefNodes->item( $i )->nodeValue; |
| } |
| |
| $request->propertyBehaviour->keepAlive = $keepAliveContent; |
| } |
| } |
| return $request; |
| } |
| |
| // DELETE |
| |
| /** |
| * Parses the DELETE request and returns a request object. |
| * |
| * This method is responsible for parsing the DELETE request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavDeleteRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavDeleteRequest |
| */ |
| protected function parseDeleteRequest( $path, $body ) |
| { |
| $req = new ezcWebdavDeleteRequest( $path ); |
| $req->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| return $req; |
| } |
| |
| // MKCOL |
| |
| /** |
| * Parses the MKCOL request and returns a request object. |
| * |
| * This method is responsible for parsing the MKCOL request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavMakeCollectionRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavMakeCollectionRequest |
| */ |
| protected function parseMakeCollectionRequest( $path, $body ) |
| { |
| $req = new ezcWebdavMakeCollectionRequest( $path, ( trim( $body ) === '' ? null : $body ) ); |
| $req->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| return $req; |
| } |
| |
| // OPTIONS |
| |
| /** |
| * Parses the OPTIONS request and returns a request object. |
| * |
| * This method is responsible for parsing the OPTIONS request. It retrieves |
| * the current request URI in $path and the request body as $body. The |
| * return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavOptionsRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavOptionsRequest |
| */ |
| protected function parseOptionsRequest( $path, $body ) |
| { |
| $req = new ezcWebdavOptionsRequest( $path, ( trim( $body ) === '' ? null : $body ) ); |
| $req->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| return $req; |
| } |
| |
| // PROPFIND |
| |
| /** |
| * Parses the PROPFIND request and returns a request object. |
| * |
| * This method is responsible for parsing the PROPFIND request. It |
| * retrieves the current request URI in $path and the request body as |
| * $body. The return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavPropFindRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavPropFindRequest |
| */ |
| protected function parsePropFindRequest( $path, $body ) |
| { |
| $request = new ezcWebdavPropFindRequest( $path ); |
| |
| $request->setHeaders( |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders( |
| array( 'Depth' ) |
| ) |
| ); |
| |
| if ( empty( $body ) ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| "Could not open XML as DOMDocument: '{$body}'." |
| ); |
| } |
| try |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom( $body ); |
| } |
| catch ( ezcWebdavInvalidXmlException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| $e->getMessage() |
| ); |
| } |
| |
| if ( $dom->documentElement->localName !== 'propfind' ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| "Expected XML element <propfind />, received <{$dom->documentElement->localName} />." |
| ); |
| } |
| if ( $dom->documentElement->firstChild === null ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| "Element <propfind /> does not have a child element." |
| ); |
| } |
| |
| switch ( $dom->documentElement->firstChild->localName ) |
| { |
| case 'allprop': |
| $request->allProp = true; |
| break; |
| case 'propname': |
| $request->propName = true; |
| break; |
| case 'prop': |
| $request->prop = new ezcWebdavBasicPropertyStorage(); |
| try |
| { |
| ezcWebdavServer::getInstance()->propertyHandler->extractProperties( |
| $dom->documentElement->firstChild->childNodes, |
| $request->prop |
| ); |
| } |
| catch ( ezcBaseValueException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| "Property extraction produced value exception: '{$e->getMessage()}'." |
| ); |
| } |
| break; |
| default: |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPFIND', |
| "XML element <{$dom->documentElement->firstChild->nodeName} /> is not a valid child element for <propfind />." |
| ); |
| } |
| return $request; |
| } |
| |
| // PROPPATCH |
| |
| /** |
| * Parses the PROPPATCH request and returns a request object. |
| * |
| * This method is responsible for parsing the PROPPATCH request. It |
| * retrieves the current request URI in $path and the request body as |
| * $body. The return value, if no exception is thrown, is a valid {@link |
| * ezcWebdavPropPatchRequest} object. |
| * |
| * This method may be overwritten to adjust it to special client behaviour. |
| * |
| * @param string $path |
| * @param string $body |
| * @return ezcWebdavPropPatchRequest |
| */ |
| protected function parsePropPatchRequest( $path, $body ) |
| { |
| $request = new ezcWebdavPropPatchRequest( $path ); |
| |
| try |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom( $body ); |
| } |
| catch ( ezcWebdavInvalidXmlException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPPATCH', |
| $e->getMessage() |
| ); |
| } |
| |
| if ( $dom->documentElement->localName !== 'propertyupdate' ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPPATCH', |
| "Expected XML element <propertyupdate />, received <{$dom->documentElement->localName} />." |
| ); |
| } |
| |
| $propElements = $dom->documentElement->getElementsByTagNameNS( ezcWebdavXmlTool::XML_DEFAULT_NAMESPACE, 'prop' ); |
| |
| try |
| { |
| foreach ( $propElements as $propElement ) |
| { |
| if ( $propElement->hasChildNodes() ) |
| { |
| ezcWebdavServer::getInstance()->propertyHandler->extractProperties( |
| $propElement->childNodes, |
| $request->updates, |
| $propElement->parentNode->localName === 'remove' |
| ? ezcWebdavPropPatchRequest::REMOVE |
| : ezcWebdavPropPatchRequest::SET |
| ); |
| } |
| } |
| } |
| catch ( ezcBaseValueException $e ) |
| { |
| throw new ezcWebdavInvalidRequestBodyException( |
| 'PROPPATCH', |
| "Property extraction produced value exception: '{$e->getMessage()}'." |
| ); |
| } |
| |
| $request->setHeaders( |
| // Parse default headers |
| ezcWebdavServer::getInstance()->headerHandler->parseHeaders() |
| ); |
| |
| return $request; |
| } |
| |
| /* |
| **************************** |
| * Response handling follows. |
| **************************** |
| */ |
| |
| /** |
| * Returns display information for a multistatus response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavMultiStatusResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information generated by this response contains the post |
| * processed $response and a {@link DOMDocument} representing the XML |
| * response body. |
| * |
| * This method utilizes {@link ezcWebdavServer->xmlTool} to |
| * perform basic XML operations, so this is the place to perform such |
| * changeds. You should overwrite this method, if your client has problems |
| * specifically with the {@link ezcWebdavMultiStatusResponse} response. |
| * |
| * @param ezcWebdavMultistatusResponse $response |
| * @return ezcWebdavXmlDisplayInformation |
| */ |
| protected function processMultiStatusResponse( ezcWebdavMultistatusResponse $response ) |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom(); |
| |
| $multistatusElement = $dom->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'multistatus' ) |
| ); |
| |
| foreach ( $response->responses as $subResponse ) |
| { |
| $multistatusElement->appendChild( |
| ( $subResponse instanceof ezcWebdavErrorResponse |
| ? $dom->importNode( $this->processErrorResponse( $subResponse, true )->body->documentElement, true ) |
| : $dom->importNode( $this->processResponse( $subResponse )->body->documentElement, true ) |
| ) |
| ); |
| } |
| |
| return new ezcWebdavXmlDisplayInformation( $response, $dom ); |
| } |
| |
| /** |
| * Returns display information for a prop find response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavPropFindResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information generated by this response contains the post |
| * processed $response and a {@link DOMDocument} representing the XML |
| * response body. |
| * |
| * This method utilizes {@link ezcWebdavServer->xmlTool} to |
| * perform basic XML operations, so this is the place to perform such |
| * changeds. You should overwrite this method, if your client has problems |
| * specifically with the {@link ezcWebdavPropFindResponse} response. |
| * |
| * @param ezcWebdavPropFindResponse $response |
| * @return ezcWebdavXmlDisplayInformation |
| */ |
| protected function processPropFindResponse( ezcWebdavPropFindResponse $response ) |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom(); |
| |
| $responseElement = $dom->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'response' ) |
| ); |
| |
| $responseElement->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'href' ) |
| )->nodeValue = ezcWebdavServer::getInstance()->pathFactory->generateUriFromPath( $response->node->path ); |
| |
| foreach ( $response->responses as $propStat ) |
| { |
| if ( count( $propStat->storage ) > 0 ) |
| { |
| $responseElement->appendChild( |
| $dom->importNode( $this->processPropStatResponse( $propStat )->body->documentElement, true ) |
| ); |
| } |
| } |
| return new ezcWebdavXmlDisplayInformation( $response, $dom ); |
| } |
| |
| /** |
| * Returns display information for a prop patch response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavPropPatchResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavPropPatchResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processPropPatchResponse( ezcWebdavPropPatchResponse $response ) |
| { |
| if ( count( $response->responses ) === 0 ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| return $this->processPropFindResponse( $response ); |
| } |
| |
| /** |
| * Returns display information for a copy response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavCopyResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavCopyResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processCopyResponse( ezcWebdavCopyResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a move response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavMoveResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavMoveResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processMoveResponse( ezcWebdavMoveResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a delete response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavDeleteResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavDeleteResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processDeleteResponse( ezcWebdavDeleteResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a error response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavErrorResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The $xml parameter defines, if an XML representation should be |
| * generated, too (for use in {@link $this->processMultiStatusResponse()}), |
| * or if only the headers should be manipulated and an empty response body |
| * should be used. |
| * |
| * The display information generated by this response contains the post |
| * processed $response and a {@link DOMDocument} representing the XML |
| * response body. If the $xml parameter is set to false, an empty display |
| * information is generated, to indicate that only headers should be send. |
| * |
| * This method utilizes {@link ezcWebdavServer->xmlTool} to |
| * perform basic XML operations, so this is the place to perform such |
| * changeds. You should overwrite this method, if your client has problems |
| * specifically with the {@link ezcWebdavErrorResponse} response. |
| * |
| * @param ezcWebdavErrorResponse $response |
| * @param bool $xml DOMDocument in result only generated of true. |
| * @return ezcWebdavXmlDisplayInformation|ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processErrorResponse( ezcWebdavErrorResponse $response, $xml = false ) |
| { |
| $res = new ezcWebdavEmptyDisplayInformation( $response ); |
| if ( $xml === true ) |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom(); |
| $responseElement = $dom->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'response' ) |
| ); |
| |
| $responseElement->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'href' ) |
| )->nodeValue = ezcWebdavServer::getInstance()->pathFactory->generateUriFromPath( $response->requestUri ); |
| |
| $responseElement->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'status' ) |
| )->nodeValue = (string) $response; |
| |
| if ( !empty( $response->responseDescription ) ) |
| { |
| $responseElement->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'responsedescription' ) |
| )->nodeValue = $response->responseDescription; |
| } |
| $res = new ezcWebdavXmlDisplayInformation( $response, $dom ); |
| } |
| elseif ( $response->responseDescription !== null ) |
| { |
| // User $responseDescription as body |
| $response->setHeader( 'Content-Type', 'text/plain; charset="utf-8"' ); |
| $response->setHeader( 'Content-Length', (string) strlen( $response->responseDescription ) ); |
| $res = new ezcWebdavStringDisplayInformation( $response, $response->responseDescription ); |
| } |
| return $res; |
| } |
| |
| /** |
| * Returns display information for a get response for a collection. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavGetCollectionResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavGetCollectionResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| * |
| * @todo We should possibly offer an ezcWebdavTemplateTiein, which brings |
| * an extension that adds a directory listing body here (possibly in |
| * selectable formats like XHTML, HTML, Apache style, ...). |
| */ |
| protected function processGetCollectionResponse( ezcWebdavGetCollectionResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a get response on a non-collection. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavGetResourceResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * This response returns a very seldom (for this component) string |
| * response, since it returns the raw content of the requested resource. |
| * |
| * @param ezcWebdavGetResourceResponse $response |
| * @return ezcWebdavStringDisplayInformation |
| */ |
| protected function processGetResourceResponse( ezcWebdavGetResourceResponse $response ) |
| { |
| // Generate Content-Type header if necessary |
| if ( $response->getHeader( 'Content-Type' ) === null ) |
| { |
| $contentTypeProperty = $response->resource->liveProperties->get( 'getcontenttype' ); |
| $contentTypeHeader = ( $contentTypeProperty->mime !== null ? $contentTypeProperty->mime : 'application/octet-stream' ) . |
| '; charset="' . ( $contentTypeProperty->charset !== null ? $contentTypeProperty->charset : 'utf-8' ) . '"'; |
| $response->setHeader( 'Content-Type', $contentTypeHeader ); |
| } |
| // Content-Length automatically send by web server |
| return new ezcWebdavStringDisplayInformation( $response, $response->resource->content ); |
| } |
| |
| /** |
| * Returns display information for a put response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavPutResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavPutResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processPutResponse( ezcWebdavPutResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a head response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavHeadResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * This method always must be structured quite similar to {@link |
| * $this->processGetCollectionResponse} or {@link |
| * $this->processGetResourceResponse()}, since HEAD is more or less GET |
| * without a body. |
| * |
| * @param ezcWebdavHeadResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processHeadResponse( ezcWebdavHeadResponse $response ) |
| { |
| if ( $response->resource instanceof ezcWebdavResource ) |
| { |
| return $this->processHeadResourceResponse( $response ); |
| } |
| return $this->processHeadCollectionResponse( $response ); |
| } |
| |
| /** |
| * Creates display information for a HEAD response of a non-collection resource. |
| * |
| * Generates default Content-Type and Content-Length header, if not set in |
| * the $response (generated from the backend). Content-Type is determined |
| * by the 'getcontenttype' property, if set, otherwise |
| * 'application/octet-stream' is used. Same applies to the charset |
| * parameter, where 'utf-8' is the default. The Content-Length is determined |
| * by strlen() on the resource content. |
| * |
| * @param ezcWebdavHeadResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| private function processHeadResourceResponse( ezcWebdavHeadResponse $response ) |
| { |
| // Generate default Content-Type header if necessary |
| if ( $response->getHeader( 'Content-Type' ) === null ) |
| { |
| $contentTypeProperty = $response->resource->liveProperties->get( 'getcontenttype' ); |
| |
| $contentTypeHeader = ( $contentTypeProperty->mime !== null ? $contentTypeProperty->mime : 'application/octet-stream' ) |
| . '; charset="' . ( $contentTypeProperty->charset !== null ? $contentTypeProperty->charset : 'utf-8' ) . '"'; |
| |
| $response->setHeader( 'Content-Type', $contentTypeHeader ); |
| } |
| |
| // Generate default Content-Length header if necessary |
| if ( $response->getHeader( 'Content-Length' ) === null ) |
| { |
| $response->setHeader( 'Content-Length', strlen( $response->resource->content ) ); |
| } |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Creates display information for a HEAD response of a collection resource. |
| * |
| * Generates default Content-Type and Content-Length header, if not set in |
| * the $response (generated from the backend). Content-Type is set to . |
| * |
| * @param ezcWebdavHeadResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| private function processHeadCollectionResponse( ezcWebdavHeadResponse $response ) |
| { |
| // Generate default Content-Type header if necessary |
| if ( $response->getHeader( 'Content-Type' ) === null ) |
| { |
| $response->setHeader( 'Content-Type', 'httpd/unix-directory' ); |
| } |
| |
| // Generate default Content-Length header if necessary |
| if ( $response->getHeader( 'Content-Length' ) === null ) |
| { |
| $response->setHeader( 'Content-Length', ezcWebdavGetContentLengthProperty::COLLECTION ); |
| } |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| // ezcWebdavMakeCollectionResponse |
| |
| /** |
| * Returns display information for a make collection response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavMakeCollectionResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavMakeCollectionResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processMakeCollectionResponse( ezcWebdavMakeCollectionResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a options response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavOptionsResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information returned by this method indicates, that only |
| * headers, but no response body, should be send. |
| * |
| * @param ezcWebdavOptionsResponse $response |
| * @return ezcWebdavEmptyDisplayInformation |
| */ |
| protected function processOptionsResponse( ezcWebdavOptionsResponse $response ) |
| { |
| return new ezcWebdavEmptyDisplayInformation( $response ); |
| } |
| |
| /** |
| * Returns display information for a prop stat response object. |
| * |
| * This method returns the display information generated for a $response |
| * object of type {@link ezcWebdavPropStatResponse}. It returns an |
| * instance of {@link ezcWebdavDisplayInformation} containing the |
| * post-processed response object and the appropriate body. |
| * |
| * The display information generated by this response contains the post |
| * processed $response and a {@link DOMDocument} representing the XML |
| * response body. |
| * |
| * This method utilizes {@link ezcWebdavServer->xmlTool} to |
| * perform basic XML operations, so this is the place to perform such |
| * changeds. You should overwrite this method, if your client has problems |
| * specifically with the {@link ezcWebdavPropStatResponse} response. |
| * |
| * @param ezcWebdavPropStatResponse $response |
| * @return ezcWebdavXmlDisplayInformation |
| */ |
| protected function processPropStatResponse( ezcWebdavPropStatResponse $response ) |
| { |
| $dom = ezcWebdavServer::getInstance()->xmlTool->createDom(); |
| |
| $propstatElement = $dom->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'propstat' ) |
| ); |
| |
| ezcWebdavServer::getInstance()->propertyHandler->serializeProperties( |
| $response->storage, |
| $propstatElement->appendChild( ezcWebdavServer::getInstance()->xmlTool->createDomElement( $dom, 'prop' ) ) |
| ); |
| |
| $propstatElement->appendChild( |
| ezcWebdavServer::getInstance()->xmlTool->createDomElement( |
| $dom, |
| 'status' |
| ) |
| )->nodeValue = (string) $response; |
| |
| return new ezcWebdavXmlDisplayInformation( $response, $dom ); |
| } |
| } |
| |
| ?> |