TimeSync.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_TimeSync
  17. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @version $Id$
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * Zend_Date
  23. */
  24. #require_once 'Zend/Date.php';
  25. /**
  26. * @category Zend
  27. * @package Zend_TimeSync
  28. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_TimeSync implements IteratorAggregate
  32. {
  33. /**
  34. * Set the default timeserver protocol to "Ntp". This will be called
  35. * when no protocol is specified
  36. */
  37. const DEFAULT_PROTOCOL = 'Ntp';
  38. /**
  39. * Contains array of timeserver objects
  40. *
  41. * @var array
  42. */
  43. protected $_timeservers = array();
  44. /**
  45. * Holds a reference to the timeserver that is currently being used
  46. *
  47. * @var object
  48. */
  49. protected $_current;
  50. /**
  51. * Allowed timeserver schemes
  52. *
  53. * @var array
  54. */
  55. protected $_allowedSchemes = array(
  56. 'Ntp',
  57. 'Sntp'
  58. );
  59. /**
  60. * Configuration array, set using the constructor or using
  61. * ::setOptions() or ::setOption()
  62. *
  63. * @var array
  64. */
  65. public static $options = array(
  66. 'timeout' => 1
  67. );
  68. /**
  69. * Zend_TimeSync constructor
  70. *
  71. * @param string|array $target - OPTIONAL single timeserver, or an array of timeservers.
  72. * @param string $alias - OPTIONAL an alias for this timeserver
  73. * @return object
  74. */
  75. public function __construct($target = null, $alias = null)
  76. {
  77. if ($target !== null) {
  78. $this->addServer($target, $alias);
  79. }
  80. }
  81. /**
  82. * getIterator() - return an iteratable object for use in foreach and the like,
  83. * this completes the IteratorAggregate interface
  84. *
  85. * @return ArrayObject
  86. */
  87. public function getIterator()
  88. {
  89. return new ArrayObject($this->_timeservers);
  90. }
  91. /**
  92. * Add a timeserver or multiple timeservers
  93. *
  94. * Server should be a single string representation of a timeserver,
  95. * or a structured array listing multiple timeservers.
  96. *
  97. * If you provide an array of timeservers in the $target variable,
  98. * $alias will be ignored. you can enter these as the array key
  99. * in the provided array, which should be structured as follows:
  100. *
  101. * <code>
  102. * $example = array(
  103. * 'server_a' => 'ntp://127.0.0.1',
  104. * 'server_b' => 'ntp://127.0.0.1:123',
  105. * 'server_c' => 'ntp://[2000:364:234::2.5]',
  106. * 'server_d' => 'ntp://[2000:364:234::2.5]:123'
  107. * );
  108. * </code>
  109. *
  110. * If no port number has been suplied, the default matching port
  111. * number will be used.
  112. *
  113. * Supported protocols are:
  114. * - ntp
  115. * - sntp
  116. *
  117. * @param string|array $target - Single timeserver, or an array of timeservers.
  118. * @param string $alias - OPTIONAL an alias for this timeserver
  119. * @throws Zend_TimeSync_Exception
  120. */
  121. public function addServer($target, $alias = null)
  122. {
  123. if (is_array($target)) {
  124. foreach ($target as $key => $server) {
  125. $this->_addServer($server, $key);
  126. }
  127. } else {
  128. $this->_addServer($target, $alias);
  129. }
  130. }
  131. /**
  132. * Sets the value for the given options
  133. *
  134. * This will replace any currently defined options.
  135. *
  136. * @param array $options - An array of options to be set
  137. */
  138. public static function setOptions(array $options)
  139. {
  140. foreach ($options as $key => $value) {
  141. Zend_TimeSync::$options[$key] = $value;
  142. }
  143. }
  144. /**
  145. * Marks a nameserver as current
  146. *
  147. * @param string|integer $alias - The alias from the timeserver to set as current
  148. * @throws Zend_TimeSync_Exception
  149. */
  150. public function setServer($alias)
  151. {
  152. if (isset($this->_timeservers[$alias]) === true) {
  153. $this->_current = $this->_timeservers[$alias];
  154. } else {
  155. #require_once 'Zend/TimeSync/Exception.php';
  156. throw new Zend_TimeSync_Exception("'$alias' does not point to valid timeserver");
  157. }
  158. }
  159. /**
  160. * Returns the value to the option
  161. *
  162. * @param string $key - The option's identifier
  163. * @return mixed
  164. * @throws Zend_TimeSync_Exception
  165. */
  166. public static function getOptions($key = null)
  167. {
  168. if ($key == null) {
  169. return Zend_TimeSync::$options;
  170. }
  171. if (isset(Zend_TimeSync::$options[$key]) === true) {
  172. return Zend_TimeSync::$options[$key];
  173. } else {
  174. #require_once 'Zend/TimeSync/Exception.php';
  175. throw new Zend_TimeSync_Exception("'$key' does not point to valid option");
  176. }
  177. }
  178. /**
  179. * Return a specified timeserver by alias
  180. * If no alias is given it will return the current timeserver
  181. *
  182. * @param string|integer $alias - The alias from the timeserver to return
  183. * @return object
  184. * @throws Zend_TimeSync_Exception
  185. */
  186. public function getServer($alias = null)
  187. {
  188. if ($alias === null) {
  189. if (isset($this->_current) && $this->_current !== false) {
  190. return $this->_current;
  191. } else {
  192. #require_once 'Zend/TimeSync/Exception.php';
  193. throw new Zend_TimeSync_Exception('there is no timeserver set');
  194. }
  195. }
  196. if (isset($this->_timeservers[$alias]) === true) {
  197. return $this->_timeservers[$alias];
  198. } else {
  199. #require_once 'Zend/TimeSync/Exception.php';
  200. throw new Zend_TimeSync_Exception("'$alias' does not point to valid timeserver");
  201. }
  202. }
  203. /**
  204. * Returns information sent/returned from the current timeserver
  205. *
  206. * @return array
  207. */
  208. public function getInfo()
  209. {
  210. return $this->getServer()->getInfo();
  211. }
  212. /**
  213. * Query the timeserver list using the fallback mechanism
  214. *
  215. * If there are multiple servers listed, this method will act as a
  216. * facade and will try to return the date from the first server that
  217. * returns a valid result.
  218. *
  219. * @param Zend_Locale $locale - OPTIONAL locale
  220. * @return object
  221. * @throws Zend_TimeSync_Exception
  222. */
  223. public function getDate($locale = null)
  224. {
  225. #require_once 'Zend/TimeSync/Exception.php';
  226. foreach ($this->_timeservers as $alias => $server) {
  227. $this->_current = $server;
  228. try {
  229. return $server->getDate($locale);
  230. } catch (Zend_TimeSync_Exception $e) {
  231. if (!isset($masterException)) {
  232. $masterException = new Zend_TimeSync_Exception('all timeservers are bogus');
  233. }
  234. $masterException->addException($e);
  235. }
  236. }
  237. throw $masterException;
  238. }
  239. /**
  240. * Adds a timeserver object to the timeserver list
  241. *
  242. * @param string|array $target - Single timeserver, or an array of timeservers.
  243. * @param string $alias - An alias for this timeserver
  244. */
  245. protected function _addServer($target, $alias)
  246. {
  247. if ($pos = strpos($target, '://')) {
  248. $protocol = substr($target, 0, $pos);
  249. $adress = substr($target, $pos + 3);
  250. } else {
  251. $adress = $target;
  252. $protocol = self::DEFAULT_PROTOCOL;
  253. }
  254. if ($pos = strrpos($adress, ':')) {
  255. $posbr = strpos($adress, ']');
  256. if ($posbr and ($pos > $posbr)) {
  257. $port = substr($adress, $pos + 1);
  258. $adress = substr($adress, 0, $pos);
  259. } else if (!$posbr and $pos) {
  260. $port = substr($adress, $pos + 1);
  261. $adress = substr($adress, 0, $pos);
  262. } else {
  263. $port = null;
  264. }
  265. } else {
  266. $port = null;
  267. }
  268. $protocol = ucfirst(strtolower($protocol));
  269. if (!in_array($protocol, $this->_allowedSchemes)) {
  270. #require_once 'Zend/TimeSync/Exception.php';
  271. throw new Zend_TimeSync_Exception("'$protocol' is not a supported protocol");
  272. }
  273. $className = 'Zend_TimeSync_' . $protocol;
  274. if (!class_exists($className)) {
  275. #require_once 'Zend/Loader.php';
  276. Zend_Loader::loadClass($className);
  277. }
  278. $timeServerObj = new $className($adress, $port);
  279. $this->_timeservers[$alias] = $timeServerObj;
  280. }
  281. }