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