File indexing completed on 2024-12-22 05:37:18

0001 <?php
0002 
0003 /**
0004  * Zend Framework
0005  *
0006  * LICENSE
0007  *
0008  * This source file is subject to the new BSD license that is bundled
0009  * with this package in the file LICENSE.txt.
0010  * It is also available through the world-wide-web at this URL:
0011  * http://framework.zend.com/license/new-bsd
0012  * If you did not receive a copy of the license and are unable to
0013  * obtain it through the world-wide-web, please send an email
0014  * to license@zend.com so we can send you a copy immediately.
0015  *
0016  * @category   Zend
0017  * @package    Zend_TimeSync
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @version    $Id$
0020  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0021  */
0022 
0023 /**
0024  * Zend_Date
0025  */
0026 // require_once 'Zend/Date.php';
0027 
0028 /**
0029  * @category   Zend
0030  * @package    Zend_TimeSync
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_TimeSync implements IteratorAggregate
0035 {
0036     /**
0037      * Set the default timeserver protocol to "Ntp". This will be called
0038      * when no protocol is specified
0039      */
0040     const DEFAULT_PROTOCOL = 'Ntp';
0041 
0042     /**
0043      * Contains array of timeserver objects
0044      *
0045      * @var array
0046      */
0047     protected $_timeservers = array();
0048 
0049     /**
0050      * Holds a reference to the timeserver that is currently being used
0051      *
0052      * @var object
0053      */
0054     protected $_current;
0055 
0056     /**
0057      * Allowed timeserver schemes
0058      *
0059      * @var array
0060      */
0061     protected $_allowedSchemes = array(
0062         'Ntp',
0063         'Sntp'
0064     );
0065 
0066     /**
0067      * Configuration array, set using the constructor or using
0068      * ::setOptions() or ::setOption()
0069      *
0070      * @var array
0071      */
0072     public static $options = array(
0073         'timeout' => 1
0074     );
0075 
0076     /**
0077      * Zend_TimeSync constructor
0078      *
0079      * @param  string|array $target - OPTIONAL single timeserver, or an array of timeservers.
0080      * @param  string       $alias  - OPTIONAL an alias for this timeserver
0081      * @return  object
0082      */
0083     public function __construct($target = null, $alias = null)
0084     {
0085         if ($target !== null) {
0086             $this->addServer($target, $alias);
0087         }
0088     }
0089 
0090     /**
0091      * getIterator() - return an iteratable object for use in foreach and the like,
0092      * this completes the IteratorAggregate interface
0093      *
0094      * @return ArrayObject
0095      */
0096     public function getIterator()
0097     {
0098         return new ArrayObject($this->_timeservers);
0099     }
0100 
0101     /**
0102      * Add a timeserver or multiple timeservers
0103      *
0104      * Server should be a single string representation of a timeserver,
0105      * or a structured array listing multiple timeservers.
0106      *
0107      * If you provide an array of timeservers in the $target variable,
0108      * $alias will be ignored. you can enter these as the array key
0109      * in the provided array, which should be structured as follows:
0110      *
0111      * <code>
0112      * $example = array(
0113      *   'server_a' => 'ntp://127.0.0.1',
0114      *   'server_b' => 'ntp://127.0.0.1:123',
0115      *   'server_c' => 'ntp://[2000:364:234::2.5]',
0116      *   'server_d' => 'ntp://[2000:364:234::2.5]:123'
0117      * );
0118      * </code>
0119      *
0120      * If no port number has been suplied, the default matching port
0121      * number will be used.
0122      *
0123      * Supported protocols are:
0124      * - ntp
0125      * - sntp
0126      *
0127      * @param  string|array $target - Single timeserver, or an array of timeservers.
0128      * @param  string       $alias  - OPTIONAL an alias for this timeserver
0129      * @throws Zend_TimeSync_Exception
0130      */
0131     public function addServer($target, $alias = null)
0132     {
0133         if (is_array($target)) {
0134             foreach ($target as $key => $server) {
0135                 $this->_addServer($server, $key);
0136             }
0137         } else {
0138             $this->_addServer($target, $alias);
0139         }
0140     }
0141 
0142     /**
0143      * Sets the value for the given options
0144      *
0145      * This will replace any currently defined options.
0146      *
0147      * @param   array $options - An array of options to be set
0148      */
0149     public static function setOptions(array $options)
0150     {
0151         foreach ($options as $key => $value) {
0152             Zend_TimeSync::$options[$key] = $value;
0153         }
0154     }
0155 
0156     /**
0157      * Marks a nameserver as current
0158      *
0159      * @param   string|integer $alias - The alias from the timeserver to set as current
0160      * @throws  Zend_TimeSync_Exception
0161      */
0162     public function setServer($alias)
0163     {
0164         if (isset($this->_timeservers[$alias]) === true) {
0165             $this->_current = $this->_timeservers[$alias];
0166         } else {
0167             // require_once 'Zend/TimeSync/Exception.php';
0168             throw new Zend_TimeSync_Exception("'$alias' does not point to valid timeserver");
0169         }
0170     }
0171 
0172     /**
0173      * Returns the value to the option
0174      *
0175      * @param   string $key - The option's identifier
0176      * @return  mixed
0177      * @throws  Zend_TimeSync_Exception
0178      */
0179     public static function getOptions($key = null)
0180     {
0181         if ($key == null) {
0182             return Zend_TimeSync::$options;
0183         }
0184 
0185         if (isset(Zend_TimeSync::$options[$key]) === true) {
0186             return Zend_TimeSync::$options[$key];
0187         } else {
0188             // require_once 'Zend/TimeSync/Exception.php';
0189             throw new Zend_TimeSync_Exception("'$key' does not point to valid option");
0190         }
0191     }
0192 
0193     /**
0194      * Return a specified timeserver by alias
0195      * If no alias is given it will return the current timeserver
0196      *
0197      * @param   string|integer $alias - The alias from the timeserver to return
0198      * @return  object
0199      * @throws  Zend_TimeSync_Exception
0200      */
0201     public function getServer($alias = null)
0202     {
0203         if ($alias === null) {
0204             if (isset($this->_current) && $this->_current !== false) {
0205                 return $this->_current;
0206             } else {
0207                 // require_once 'Zend/TimeSync/Exception.php';
0208                 throw new Zend_TimeSync_Exception('there is no timeserver set');
0209             }
0210         }
0211         if (isset($this->_timeservers[$alias]) === true) {
0212             return $this->_timeservers[$alias];
0213         } else {
0214             // require_once 'Zend/TimeSync/Exception.php';
0215             throw new Zend_TimeSync_Exception("'$alias' does not point to valid timeserver");
0216         }
0217     }
0218 
0219     /**
0220      * Returns information sent/returned from the current timeserver
0221      *
0222      * @return  array
0223      */
0224     public function getInfo()
0225     {
0226         return $this->getServer()->getInfo();
0227     }
0228 
0229     /**
0230      * Query the timeserver list using the fallback mechanism
0231      *
0232      * If there are multiple servers listed, this method will act as a
0233      * facade and will try to return the date from the first server that
0234      * returns a valid result.
0235      *
0236      * @param   Zend_Locale $locale - OPTIONAL locale
0237      * @return  object
0238      * @throws  Zend_TimeSync_Exception
0239      */
0240     public function getDate($locale = null)
0241     {
0242         // require_once 'Zend/TimeSync/Exception.php';
0243         foreach ($this->_timeservers as $alias => $server) {
0244             $this->_current = $server;
0245             try {
0246                 return $server->getDate($locale);
0247             } catch (Zend_TimeSync_Exception $e) {
0248                 if (!isset($masterException)) {
0249                     $masterException = new Zend_TimeSync_Exception('all timeservers are bogus');
0250                 }
0251                 $masterException->addException($e);
0252             }
0253         }
0254 
0255         throw $masterException;
0256     }
0257 
0258     /**
0259      * Adds a timeserver object to the timeserver list
0260      *
0261      * @param  string|array $target   - Single timeserver, or an array of timeservers.
0262      * @param  string       $alias    - An alias for this timeserver
0263      */
0264     protected function _addServer($target, $alias)
0265     {
0266         if ($pos = strpos($target, '://')) {
0267             $protocol = substr($target, 0, $pos);
0268             $adress = substr($target, $pos + 3);
0269         } else {
0270             $adress = $target;
0271             $protocol = self::DEFAULT_PROTOCOL;
0272         }
0273 
0274         if ($pos = strrpos($adress, ':')) {
0275             $posbr = strpos($adress, ']');
0276             if ($posbr and ($pos > $posbr)) {
0277                 $port = substr($adress, $pos + 1);
0278                 $adress = substr($adress, 0, $pos);
0279             } else if (!$posbr and $pos) {
0280                 $port = substr($adress, $pos + 1);
0281                 $adress = substr($adress, 0, $pos);
0282             } else {
0283                 $port = null;
0284             }
0285         } else {
0286             $port = null;
0287         }
0288 
0289         $protocol = ucfirst(strtolower($protocol));
0290         if (!in_array($protocol, $this->_allowedSchemes)) {
0291             // require_once 'Zend/TimeSync/Exception.php';
0292             throw new Zend_TimeSync_Exception("'$protocol' is not a supported protocol");
0293         }
0294 
0295         $className = 'Zend_TimeSync_' . $protocol;
0296         if (!class_exists($className)) {
0297             // require_once 'Zend/Loader.php';
0298             Zend_Loader::loadClass($className);
0299         }
0300         $timeServerObj = new $className($adress, $port);
0301 
0302         $this->_timeservers[$alias] = $timeServerObj;
0303     }
0304 }