blob: 894f934225da51eebf20dfa4f75a72cce86cd27d [file] [log] [blame]
<?php
/**
* File containing the ezcWebdavServerConfigurationManager 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//
* @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
/**
* Manages and dispatches server configurations.
*
* An instance of this class is kept in the singleton instance of {@link
* ezcWebdavServer} and keeps track of different server configurations to be
* used with different clients.
*
* Several special configurations exist per default:
* - MS InternetExplorer compatible
* - GNOME Nautilus compatible
*
* In addtion, a default configuration that behaves RFC compliant is included
* as fallback for any other client.
*
* Configurations can be accessed by the ArrayAccess and Iterator interfaces.
* To insert new configurations, the method {@link insertBefore()} should be
* used.
*
* @package Webdav
* @version //autogen//
*/
class ezcWebdavServerConfigurationManager implements ArrayAccess, Iterator
{
/**
* Transport configurations to dispatch.
*
* @var array(int=>ezcWebdavServerConfiguration)
*/
protected $configurations = array();
/**
* Creates a new dispatcher.
*
* This creates a new manager object and registers the default {@link
* ezcWebdavServerConfiguration} instances automatically. The last added
* configuration is the RFC compliant one, which matches for every client
* if no other configurations matched before. That means, all following
* should be added by {@link insertBefore()} to ensure, this
* catchall will not break the transfer layer.
*
* @return void
*/
public function __construct()
{
// Add MS compatible configuration
$this[] = new ezcWebdavServerConfiguration(
'(Microsoft\s+Data\s+Access|MSIE|MiniRedir)i',
'ezcWebdavMicrosoftCompatibleTransport'
);
// Add Nautilus configuration
$this[] = new ezcWebdavServerConfiguration(
'(gnome-vfs/[0-9.]+ neon/[0-9.]*|gvfs/[0-9.]+)i',
'ezcWebdavNautilusCompatibleTransport',
'ezcWebdavXmlTool',
'ezcWebdavNautilusPropertyHandler'
);
// Add Konqueror configuration
$this[] = new ezcWebdavServerConfiguration(
'(Konqueror)i',
'ezcWebdavKonquerorCompatibleTransport'
);
// Add default RFC compliant transport as final catchall
$this[] = new ezcWebdavServerConfiguration();
}
/**
* Inserts a configuration right before a certain offset.
*
* This method inserts a given $config right before the given $offset. The
* $offset must be of type integer and between 0 and the number of elements
* in {@link $this->configurations} minus 1.
*
* If these preconditions do not match for the given $offset, an
* {@link ezcBaseValueException} is thrown.
*
* @param ezcWebdavServerConfiguration $config
* @param int $offset
* @return void
*
* @throws ezcBaseValueException
* if the given $offset is not an integer that is larger or equal
* to 0 and smaller than the number of elements in {@link
* $this->configurations}.
*/
public function insertBefore( ezcWebdavServerConfiguration $config, $offset = 0 )
{
if ( !is_int( $offset ) || $offset < 0 || $offset > ( count( $this->configurations ) - 1 ) )
{
throw new ezcBaseValueException( 'index', $offset, 'int >= 0, < number of transport configurations' );
}
array_splice( $this->configurations, $offset, 0, array( $config ) );
}
/**
* Configures the server for handling a request by the given User-Agent.
*
* This method is used by {@link ezcWebdavServer} to determine the correct
* {@link ezcWebdavTransport} for the current request. It returns the
* {@link ezcWebdavTransport} created by the {@link
* ezcWebdavServerConfiguration} which matched the submitted User-Agent
* header first.
*
* Per default, the RFC compliant default implementation {@link
* ezcWebdavTransport} is configured to catch all User-Agent headers for
* which no specific implementation could be found. If this configuration
* has been removed or manipulated incorrectly, an {@link
* ezcWebdavMissingTransportConfigurationException} might be thrown.
*
* @param ezcWebdavServer $server
* @param mixed $userAgent
* @return void
*
* @throws ezcWebdavMissingTransportConfigurationException
* if no {@link ezcWebdavServerConfiguration} could be found
* that matches the given $userAgent.
*/
public function configure( $server, $userAgent )
{
foreach ( $this as $transportConfiguration )
{
if ( preg_match( $transportConfiguration->userAgentRegex, $userAgent ) > 0 )
{
$transportConfiguration->configure( $server );
return;
}
}
throw new ezcWebdavMissingTransportConfigurationException( $userAgent );
}
/**
* Checks the given $offset for validity.
*
* This method checks if the given $offset is either of type int, then
* larger 0 and not larger as the number of elements in {@link
* $this->configurations}, or null.
*
* The method is primarily used in the {@link ArrayAccess} methods.
*
* @param int|null $offset
* @return void
*
* @throws ezcBaseValueException
* if the given $offset is not an an int with the given criteria
* and not null.
*/
protected function checkOffset( $offset )
{
if ( ( !is_int( $offset ) || $offset < 0 || $offset > count( $this->configurations ) ) && $offset !== null )
{
throw new ezcBaseValueException( 'offset', $offset, 'int >= 0, <= number of transport configurations' );
}
}
/**
* Checks the given $value for validity.
*
* This method checks if the given $value is either an instance of {@link
* ezcWebdavServerConfiguration} or null.
*
* The method is primarily used in the {@link ArrayAccess} methods.
*
* @param ezcWebdavServerConfiguration|null $value
* @return void
*
* @throws ezcBaseValueException
* if the given $value is not an instance of
* ezcWebdavServerConfiguration or null.
*/
protected function checkValue( $value )
{
if ( !( $value instanceof ezcWebdavServerConfiguration ) && $value !== null )
{
throw new ezcBaseValueException( 'value', $value, 'ezcWebdavServerConfiguration' );
}
}
// ArrayAccess
/**
* Array set access.
*
* @param string $offset
* @param string $value
* @return void
*/
public function offsetSet( $offset, $value )
{
$this->checkOffset( $offset );
$this->checkValue( $value );
if ( $value === null )
{
return $this->offsetUnset( $offset );
}
if ( $offset === null )
{
$offset = count( $this->configurations );
}
$this->configurations[$offset] = $value;
}
/**
* Array get access.
*
* @param string $offset
* @return string
* @ignore
*/
public function offsetGet( $offset )
{
$this->checkOffset( $offset );
if ( !isset( $this->configurations[$offset] ) )
{
return null;
}
return $this->configurations[$offset];
}
/**
* Array unset() access.
*
* @param string $offset
* @return void
* @ignore
*/
public function offsetUnset( $offset )
{
$this->checkOffset( $offset );
if ( $offset === null || $offset === count( $this->configurations ) )
{
return;
}
array_splice( $this->configurations, $offset, 1 );
}
/**
* Array isset() access.
*
* @param string $offset
* @return bool
* @ignore
*/
public function offsetExists( $offset )
{
return isset( $this->configurations[$offset] );
}
// Iterator
/**
* Implements current() for Iterator
*
* @return mixed
*/
public function current()
{
return current( $this->configurations );
}
/**
* Implements key() for Iterator
*
* @return int
*/
public function key()
{
return key( $this->configurations );
}
/**
* Implements next() for Iterator
*
* @return mixed
*/
public function next()
{
return next( $this->configurations );
}
/**
* Implements rewind() for Iterator
*
* @return void
*/
public function rewind()
{
return reset( $this->configurations );
}
/**
* Implements valid() for Iterator
*
* @return boolean
*/
public function valid()
{
return ( current( $this->configurations ) !== false );
}
}
?>