mirror of https://github.com/ropg/ezTime
parent
83c7fbfe0b
commit
570fe50fb2
@ -0,0 +1,17 @@
|
||||
# timezoned - The Timezone Daemon
|
||||
|
||||
This is a brutally ugly hack that serves timezone information via UDP port 2342. To use it, try the following on a unix machine with PHP installed:
|
||||
|
||||
* Create a user called 'timezoned'
|
||||
|
||||
* Copy the 'update' and 'server' scripts to this user's homedir, and change the #! line at the beginning of the server script to point to the PHP binary on the system
|
||||
|
||||
* Log in or su to the timezoned user, make the 'update' script executable and run it.
|
||||
|
||||
* Make the 'server' script executable and run it. (Make sure the server accepts packets on 2342 UDP.)
|
||||
|
||||
* Test by running `nc -u <ip or domain name> 2342` on some other system and then typing a zone (like "Europe/London") followed by Ctrl-D. You should get the POSIX information for that zone.
|
||||
|
||||
* If that works, you may (on a FreeBSD machine) use the 'timezoned' script by placing it in /usr/local/etc/rc.d to start the server automatically. On other systems, you'll have to figure out how to start it automatically when the server reboots.
|
||||
|
||||
* Run update script and then restart the server periodically to stay up on timezone updates.
|
||||
@ -0,0 +1,161 @@
|
||||
#!/usr/local/bin/php
|
||||
|
||||
<?php
|
||||
|
||||
//Reduce errors
|
||||
// error_reporting(0);
|
||||
|
||||
$tz = array();
|
||||
|
||||
// Read posixinfo
|
||||
if ($file = fopen("/home/timezoned/posixinfo", "r")) {
|
||||
while(!feof($file)) {
|
||||
$line = fgets($file);
|
||||
preg_match("/^(.*?) (.*?)$/", $line, $matches);
|
||||
if ($matches[1] != "" && $matches[2] != "") {
|
||||
array_push($tz, array("olsen" => trim($matches[1]), "posix" => trim($matches[2])));
|
||||
}
|
||||
}
|
||||
fclose($file);
|
||||
}
|
||||
|
||||
// Read zone1970.tab
|
||||
if ($file = fopen("/home/timezoneddownload/zone1970.tab", "r")) {
|
||||
while(!feof($file)) {
|
||||
$line = fgets($file);
|
||||
if ($line[0] != "#") {
|
||||
$columns = explode("\t", $line);
|
||||
if (count($columns) >= 3) {
|
||||
$countries = explode(",", $columns[0]);
|
||||
for ($n = 0; $n < count($countries); $n++) {
|
||||
$country = trim($countries[$n]);
|
||||
$insert_at = -1;
|
||||
$posix = "";
|
||||
for ($m = 0; $m < count($tz); $m++) {
|
||||
if (trim($tz[$m]["olsen"]) == trim($columns[2])) {
|
||||
$posix = $tz[$m]["posix"];
|
||||
if (!isset($tz[$m]["country"])) {
|
||||
$insert_at = $m;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($insert_at == -1) {
|
||||
$insert_at = count($tz);
|
||||
array_push($tz, array());
|
||||
}
|
||||
$tz[$insert_at]["country"] = $countries[$n];
|
||||
$tz[$insert_at]["coordinates"] = $columns[1];
|
||||
$tz[$insert_at]["olsen"] = trim($columns[2]);
|
||||
if ($posix != "") $tz[$insert_at]["posix"] = $posix;
|
||||
if (isset ($columns[3])) $tz[$insert_at]["comments"] = $columns[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Data read \n";
|
||||
|
||||
//Create a UDP socket
|
||||
|
||||
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0)))
|
||||
{
|
||||
$errorcode = socket_last_error();
|
||||
$errormsg = socket_strerror($errorcode);
|
||||
|
||||
die("Couldn't create socket: [$errorcode] $errormsg\n");
|
||||
}
|
||||
|
||||
echo "Socket created \n";
|
||||
|
||||
// Bind the source address
|
||||
if( !socket_bind($sock, "0.0.0.0" , 2342) )
|
||||
{
|
||||
$errorcode = socket_last_error();
|
||||
$errormsg = socket_strerror($errorcode);
|
||||
|
||||
die("Could not bind socket : [$errorcode] $errormsg\n");
|
||||
}
|
||||
|
||||
echo "Socket bind OK \n";
|
||||
|
||||
$last_ask = array();
|
||||
|
||||
//Process packets. This loop can handle multiple clients
|
||||
while(1)
|
||||
{
|
||||
//Receive packet
|
||||
$r = socket_recvfrom($sock, $packet, 512, 0, $remote_ip, $remote_port);
|
||||
|
||||
// dDoS/flood protection
|
||||
if (isset($last_ask[$remote_ip]) && $last_ask[$remote_ip] > time() - 3) continue;
|
||||
$last_ask[$remote_ip] = time();
|
||||
|
||||
$parts = explode("#", $packet, 2);
|
||||
$query = $parts[0];
|
||||
$version = $parts[1];
|
||||
$process = strtoupper(str_replace(" ", "_", $query));
|
||||
|
||||
$logstart = date("D, d M Y H:i:s") . "Z -- $remote_ip:$remote_port --";
|
||||
|
||||
// GeoIP ?
|
||||
if ($process == "GEOIP") {
|
||||
if (preg_match("/: ([A-Z][A-Z]),/", exec("geoiplookup " . $remote_ip), $matches)) {
|
||||
$process = $matches[1];
|
||||
} else {
|
||||
echo "$logstart ERR GeoIP Lookup Failed\n";
|
||||
socket_sendto($sock, "ERROR GeoIP Lookup Failed", 100 , 0 , $remote_ip , $remote_port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($process == "UK") $process = "GB";
|
||||
if ($process == "DE") $process = "EUROPE/BERLIN";
|
||||
|
||||
|
||||
// If a two-letter country-code was provided
|
||||
if (preg_match('/^[A-Z][A-Z]$/', $process)) {
|
||||
// Convert to name of timezone if the country happens to have only one timezone
|
||||
$num_matches = 0;
|
||||
for ($m = 0; $m < count($tz); $m++) {
|
||||
if ($tz[$m]["country"] == $process) {
|
||||
$num_matches++;
|
||||
$posix = $tz[$m]["posix"];
|
||||
$olsen = $tz[$m]["olsen"];
|
||||
}
|
||||
}
|
||||
switch ($num_matches) {
|
||||
case 0:
|
||||
echo "$logstart ERR COUNTRY NOT FOUND: $query\n";
|
||||
socket_sendto($sock, "ERROR Country Not Found", 100 , 0 , $remote_ip , $remote_port);
|
||||
break;
|
||||
case 1:
|
||||
echo "$logstart OK $query -> $olsen $posix\n";
|
||||
socket_sendto($sock, "OK " . $olsen . " " . $posix , 100 , 0 , $remote_ip , $remote_port);
|
||||
break;
|
||||
default:
|
||||
echo "$logstart ERR MULTIPLE TIMEZONES: $query\n";
|
||||
socket_sendto($sock, "ERROR Country Spans Multiple Timezones", 100 , 0 , $remote_ip , $remote_port);
|
||||
break;
|
||||
//
|
||||
}
|
||||
} else {
|
||||
$num_matches = 0;
|
||||
for ($m = 0; $m < count($tz); $m++) {
|
||||
if (strpos(strtoupper($tz[$m]["olsen"]), $process) !== false) {
|
||||
$num_matches++;
|
||||
$posix = $tz[$m]["posix"];
|
||||
$olsen = $tz[$m]["olsen"];
|
||||
echo "$logstart OK $query -> $olsen $posix\n";
|
||||
socket_sendto($sock, "OK " . $olsen . " " . $posix , 100 , 0 , $remote_ip , $remote_port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$num_matches) {
|
||||
echo "$logstart ERR TIMEZONE NOT FOUND: $query\n";
|
||||
socket_sendto($sock, "ERROR Timezone Not Found", 100 , 0 , $remote_ip , $remote_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket_close($sock);
|
||||
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
# PROVIDE: timezoned
|
||||
# REQUIRE: LOGIN cleanvar sshd
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name=timezoned
|
||||
rcvar=timezoned_enable
|
||||
|
||||
: ${timezoned_enable="NO"}
|
||||
: ${timezoned_pidfile="/var/run/timezoned/timezoned.pid"}
|
||||
: ${timezoned_user="timezoned"}
|
||||
: ${timezoned_group="timezoned"}
|
||||
|
||||
command="/usr/sbin/daemon"
|
||||
command_interpreter="/usr/local/bin/php"
|
||||
command_args="-c -f -r -P ${timezoned_pidfile} -r /home/timezoned/server"
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
run_rc_command "$1"
|
||||
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf ~timezoned/download
|
||||
mkdir ~timezoned/download
|
||||
|
||||
rm -rf ~timezoned/zoneinfo
|
||||
mkdir ~timezoned/zoneinfo
|
||||
|
||||
cd ~timezoned/download
|
||||
|
||||
wget ftp://ftp.iana.org/tz/tzdata-latest.tar.gz
|
||||
tar zxvf tzdata-latest.tar.gz
|
||||
rm tzdata-latest.tar.gz
|
||||
for i in `ls`; do zic -d ~timezoned/zoneinfo $i;done
|
||||
|
||||
rm ~timezoned/posixinfo
|
||||
|
||||
cd ~timezoned/zoneinfo
|
||||
for i in `find *|grep /`
|
||||
do
|
||||
if [ -f $i ]; then
|
||||
echo -n $i >> ~timezoned/posixinfo
|
||||
echo -n " " >> ~timezoned/posixinfo
|
||||
tail -1 $i >> ~timezoned/posixinfo
|
||||
fi
|
||||
done
|
||||
Loading…
Reference in new issue