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