/lib/ezc/Webdav/src/server_configuration_manager.php

https://bitbucket.org/ericsagnes/ezpublish-multisite · PHP · 313 lines · 114 code · 21 blank · 178 comment · 15 complexity · 95af3c18489f7ef95cccdbb79339820e MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcWebdavServerConfigurationManager class.
  4. *
  5. * @package Webdav
  6. * @version //autogentag//
  7. * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
  8. * @license http://ez.no/licenses/new_bsd New BSD License
  9. */
  10. /**
  11. * Manages and dispatches server configurations.
  12. *
  13. * An instance of this class is kept in the singleton instance of {@link
  14. * ezcWebdavServer} and keeps track of different server configurations to be
  15. * used with different clients.
  16. *
  17. * Several special configurations exist per default:
  18. * - MS InternetExplorer compatible
  19. * - GNOME Nautilus compatible
  20. *
  21. * In addtion, a default configuration that behaves RFC compliant is included
  22. * as fallback for any other client.
  23. *
  24. * Configurations can be accessed by the ArrayAccess and Iterator interfaces.
  25. * To insert new configurations, the method {@link insertBefore()} should be
  26. * used.
  27. *
  28. * @package Webdav
  29. * @version //autogen//
  30. */
  31. class ezcWebdavServerConfigurationManager implements ArrayAccess, Iterator
  32. {
  33. /**
  34. * Transport configurations to dispatch.
  35. *
  36. * @var array(int=>ezcWebdavServerConfiguration)
  37. */
  38. protected $configurations = array();
  39. /**
  40. * Creates a new dispatcher.
  41. *
  42. * This creates a new manager object and registers the default {@link
  43. * ezcWebdavServerConfiguration} instances automatically. The last added
  44. * configuration is the RFC compliant one, which matches for every client
  45. * if no other configurations matched before. That means, all following
  46. * should be added by {@link insertBefore()} to ensure, this
  47. * catchall will not break the transfer layer.
  48. *
  49. * @return void
  50. */
  51. public function __construct()
  52. {
  53. // Add MS compatible configuration
  54. $this[] = new ezcWebdavServerConfiguration(
  55. '(Microsoft\s+Data\s+Access|MSIE|MiniRedir)i',
  56. 'ezcWebdavMicrosoftCompatibleTransport'
  57. );
  58. // Add Nautilus configuration
  59. $this[] = new ezcWebdavServerConfiguration(
  60. '(gnome-vfs/[0-9.]+ neon/[0-9.]*|gvfs/[0-9.]+)i',
  61. 'ezcWebdavNautilusCompatibleTransport',
  62. 'ezcWebdavXmlTool',
  63. 'ezcWebdavNautilusPropertyHandler'
  64. );
  65. // Add Konqueror configuration
  66. $this[] = new ezcWebdavServerConfiguration(
  67. '(Konqueror)i',
  68. 'ezcWebdavKonquerorCompatibleTransport'
  69. );
  70. // Add default RFC compliant transport as final catchall
  71. $this[] = new ezcWebdavServerConfiguration();
  72. }
  73. /**
  74. * Inserts a configuration right before a certain offset.
  75. *
  76. * This method inserts a given $config right before the given $offset. The
  77. * $offset must be of type integer and between 0 and the number of elements
  78. * in {@link $this->configurations} minus 1.
  79. *
  80. * If these preconditions do not match for the given $offset, an
  81. * {@link ezcBaseValueException} is thrown.
  82. *
  83. * @param ezcWebdavServerConfiguration $config
  84. * @param int $offset
  85. * @return void
  86. *
  87. * @throws ezcBaseValueException
  88. * if the given $offset is not an integer that is larger or equal
  89. * to 0 and smaller than the number of elements in {@link
  90. * $this->configurations}.
  91. */
  92. public function insertBefore( ezcWebdavServerConfiguration $config, $offset = 0 )
  93. {
  94. if ( !is_int( $offset ) || $offset < 0 || $offset > ( count( $this->configurations ) - 1 ) )
  95. {
  96. throw new ezcBaseValueException( 'index', $offset, 'int >= 0, < number of transport configurations' );
  97. }
  98. array_splice( $this->configurations, $offset, 0, array( $config ) );
  99. }
  100. /**
  101. * Configures the server for handling a request by the given User-Agent.
  102. *
  103. * This method is used by {@link ezcWebdavServer} to determine the correct
  104. * {@link ezcWebdavTransport} for the current request. It returns the
  105. * {@link ezcWebdavTransport} created by the {@link
  106. * ezcWebdavServerConfiguration} which matched the submitted User-Agent
  107. * header first.
  108. *
  109. * Per default, the RFC compliant default implementation {@link
  110. * ezcWebdavTransport} is configured to catch all User-Agent headers for
  111. * which no specific implementation could be found. If this configuration
  112. * has been removed or manipulated incorrectly, an {@link
  113. * ezcWebdavMissingTransportConfigurationException} might be thrown.
  114. *
  115. * @param ezcWebdavServer $server
  116. * @param mixed $userAgent
  117. * @return void
  118. *
  119. * @throws ezcWebdavMissingTransportConfigurationException
  120. * if no {@link ezcWebdavServerConfiguration} could be found
  121. * that matches the given $userAgent.
  122. */
  123. public function configure( $server, $userAgent )
  124. {
  125. foreach ( $this as $transportConfiguration )
  126. {
  127. if ( preg_match( $transportConfiguration->userAgentRegex, $userAgent ) > 0 )
  128. {
  129. $transportConfiguration->configure( $server );
  130. return;
  131. }
  132. }
  133. throw new ezcWebdavMissingTransportConfigurationException( $userAgent );
  134. }
  135. /**
  136. * Checks the given $offset for validity.
  137. *
  138. * This method checks if the given $offset is either of type int, then
  139. * larger 0 and not larger as the number of elements in {@link
  140. * $this->configurations}, or null.
  141. *
  142. * The method is primarily used in the {@link ArrayAccess} methods.
  143. *
  144. * @param int|null $offset
  145. * @return void
  146. *
  147. * @throws ezcBaseValueException
  148. * if the given $offset is not an an int with the given criteria
  149. * and not null.
  150. */
  151. protected function checkOffset( $offset )
  152. {
  153. if ( ( !is_int( $offset ) || $offset < 0 || $offset > count( $this->configurations ) ) && $offset !== null )
  154. {
  155. throw new ezcBaseValueException( 'offset', $offset, 'int >= 0, <= number of transport configurations' );
  156. }
  157. }
  158. /**
  159. * Checks the given $value for validity.
  160. *
  161. * This method checks if the given $value is either an instance of {@link
  162. * ezcWebdavServerConfiguration} or null.
  163. *
  164. * The method is primarily used in the {@link ArrayAccess} methods.
  165. *
  166. * @param ezcWebdavServerConfiguration|null $value
  167. * @return void
  168. *
  169. * @throws ezcBaseValueException
  170. * if the given $value is not an instance of
  171. * ezcWebdavServerConfiguration or null.
  172. */
  173. protected function checkValue( $value )
  174. {
  175. if ( !( $value instanceof ezcWebdavServerConfiguration ) && $value !== null )
  176. {
  177. throw new ezcBaseValueException( 'value', $value, 'ezcWebdavServerConfiguration' );
  178. }
  179. }
  180. // ArrayAccess
  181. /**
  182. * Array set access.
  183. *
  184. * @param string $offset
  185. * @param string $value
  186. * @return void
  187. */
  188. public function offsetSet( $offset, $value )
  189. {
  190. $this->checkOffset( $offset );
  191. $this->checkValue( $value );
  192. if ( $value === null )
  193. {
  194. return $this->offsetUnset( $offset );
  195. }
  196. if ( $offset === null )
  197. {
  198. $offset = count( $this->configurations );
  199. }
  200. $this->configurations[$offset] = $value;
  201. }
  202. /**
  203. * Array get access.
  204. *
  205. * @param string $offset
  206. * @return string
  207. * @ignore
  208. */
  209. public function offsetGet( $offset )
  210. {
  211. $this->checkOffset( $offset );
  212. if ( !isset( $this->configurations[$offset] ) )
  213. {
  214. return null;
  215. }
  216. return $this->configurations[$offset];
  217. }
  218. /**
  219. * Array unset() access.
  220. *
  221. * @param string $offset
  222. * @return void
  223. * @ignore
  224. */
  225. public function offsetUnset( $offset )
  226. {
  227. $this->checkOffset( $offset );
  228. if ( $offset === null || $offset === count( $this->configurations ) )
  229. {
  230. return;
  231. }
  232. array_splice( $this->configurations, $offset, 1 );
  233. }
  234. /**
  235. * Array isset() access.
  236. *
  237. * @param string $offset
  238. * @return bool
  239. * @ignore
  240. */
  241. public function offsetExists( $offset )
  242. {
  243. return isset( $this->configurations[$offset] );
  244. }
  245. // Iterator
  246. /**
  247. * Implements current() for Iterator
  248. *
  249. * @return mixed
  250. */
  251. public function current()
  252. {
  253. return current( $this->configurations );
  254. }
  255. /**
  256. * Implements key() for Iterator
  257. *
  258. * @return int
  259. */
  260. public function key()
  261. {
  262. return key( $this->configurations );
  263. }
  264. /**
  265. * Implements next() for Iterator
  266. *
  267. * @return mixed
  268. */
  269. public function next()
  270. {
  271. return next( $this->configurations );
  272. }
  273. /**
  274. * Implements rewind() for Iterator
  275. *
  276. * @return void
  277. */
  278. public function rewind()
  279. {
  280. return reset( $this->configurations );
  281. }
  282. /**
  283. * Implements valid() for Iterator
  284. *
  285. * @return boolean
  286. */
  287. public function valid()
  288. {
  289. return ( current( $this->configurations ) !== false );
  290. }
  291. }
  292. ?>