Commit e2a21b8c authored by amnesia's avatar amnesia

Added custom, hacked htpdate script.

Copied from commit 151b1a83392e.
parent 3397f102
#!/usr/bin/perl
#
# htpdate time poller version 0.9.3
# Copyright (C) 2005 Eddy Vervest
# Copyright (C) 2010 T(A)ILS dev team <amnesia@boum.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# http://www.gnu.org/copyleft/gpl.html
# Proxy setting are read from environment
# e.g. in bash for setting environment variables:
#
# export HTTP_PROXY='http://wwwproxy.xs4all.nl:8080'
#
# or set the proxy value here
#
# $ENV{HTTP_PROXY} = 'http://wwwproxy.xs4all.nl:8080';
#
# If proxy authentication is required, specify your userid and password below.
use strict;
use warnings;
use version; our $VERSION = qv('0.9.3');
use Carp;
use Cwd;
use DateTime;
use DateTime::Format::DateParse;
use Fatal qw( open close );
use File::Temp qw/tempdir/;
use Getopt::Std;
use open qw{:utf8 :std};
use POSIX qw( WIFEXITED );
my $datecommand = '/bin/date'; # "date" command to set time
my $dateparam = '-s'; # "date" parameter to set time
my $debug = 0;
my $fullrequest = 0;
my $maxadjust = 1800; # maximum time step in seconds
my $minadjust = 1; # minimum time step in seconds
my $password = ''; # password for proxy server
my $quiet = 0;
my $set_date = 1;
my $ssl_protocol = 'TLSv1'; # will be passed to wget's --secure-protocol
my $useragent = "htpdate/$VERSION";
my $userid = ''; # userid for proxy servers
our ($opt_d, $opt_h, $opt_q, $opt_x, $opt_u, $opt_a, $opt_f);
sub parseCommandLine () {
# specify valid switches
getopts('dhqxfu:a:') || usage();
usage() if $opt_h;
usage() unless $ARGV[0];
$> = getpwnam($opt_u) if $opt_u;
$useragent = $opt_a if $opt_a;
$debug = 1 if $opt_d;
$fullrequest = 1 if $opt_f;
$quiet = 1 if $opt_q;
$set_date = 0 if $opt_x;
my @urls;
foreach my $url (@ARGV) {
unless ( $url =~ /^http/i ) {
$url = 'https://'.$url;
}
push @urls, $url;
}
return @urls;
}
sub usage () {
print STDERR <<USAGE;
htpdate version $VERSION
Usage: $0 [-dhqxf] [-u userid] [-a useragent] <URL> [<URL> ...]
-d debug
-h show this help
-q quiet
-u userid to run as
-x do not set the time (only show)
-a http user agent to use
-f request the full page and referenced resources rather than only its header
e.g. $0 -x http://www.microsoft.com/ https://check.torproject.org/
USAGE
exit;
}
sub newestDateHeader {
my ($dir) = @_;
my $origdir = getcwd;
chdir $dir;
my @files = glob('.* *');
@files or croak "No downloaded files can be found";
my $newestdt;
foreach my $file (@files) {
next if -l $file || -d _;
my $date;
open(my $file_h, '<', $file);
while (my $line = <$file_h>) {
chomp $line;
# empty line == we leave the headers to go into the content
last if $line eq '';
last if ($date) = ($line =~ m/^Date:\s+(.*)$/m);
}
close $file_h;
if (defined $date) {
# RFC 2616 (3.3.1) says Date headers MUST be represented in GMT
my $dt = DateTime::Format::DateParse->parse_datetime( $date, 'GMT' );
if (! defined $newestdt || DateTime->compare($dt, $newestdt) > 0) {
$newestdt = $dt;
}
}
}
chdir $origdir;
return $newestdt;
}
sub getRemoteDateDiff {
my ($url, $fullrequest) = @_;
defined $url or croak "getRemoteDateDiff must be passed an URL";
$fullrequest = defined $fullrequest ? $fullrequest : 0;
my $origdir = getcwd;
my @wget_options = ( '-U', $useragent, '--quiet', '--no-cache',
'-e', 'robots=off', '--save-headers',
'--no-directories',
'--secure-protocol', $ssl_protocol,
);
if ($fullrequest) {
push @wget_options, ('--page-requisites', '--span-hosts');
}
my @cmdline = ('wget', @wget_options, $url);
my $tmpdir = tempdir("XXXXXXXXXX", TMPDIR => 1);
chdir $tmpdir;
# fetch (the page and) referenced resources:
# images, stylesheets, scripts, etc.
WIFEXITED(system(@cmdline)) or croak "Failed to fetch content from $url: $!";
my $localdt = DateTime->now;
my $newestdt = newestDateHeader($tmpdir);
defined $newestdt or croak "Could not get any Date header";
my $diffdt = $newestdt - $localdt;
my $diff = $diffdt->in_units('seconds');
print "$url => $diff second(s)\n" if $debug;
chdir $origdir;
return $diffdt;
}
sub adjustDate {
my ($diffdt) = @_;
defined $diffdt or croak "adjustDate was passed an undefined diff";
my $localdt = DateTime->now;
my $absdiffdt = $diffdt->is_positive() ? $diffdt : $diffdt->inverse();
my $diff = $diffdt->in_units('seconds');
print "Median diff: $diff second(s)\n" if $debug;
if ( DateTime::Duration->compare( $absdiffdt,
DateTime::Duration->new(seconds => $maxadjust),
$localdt )
> 0 ) {
print STDERR "Not setting clock as diff ($diff seconds) is too large.\n" unless $quiet;
}
elsif ( DateTime::Duration->compare($absdiffdt,
DateTime::Duration->new(seconds => $minadjust),
$localdt, )
<= 0 ) {
print STDERR "Not setting clock as diff ($diff seconds) is too small.\n" unless $quiet;
}
else {
my $newtimedt = DateTime->now + $diffdt;
my $newtime = scalar localtime($newtimedt->epoch);
print "Setting time to $newtime...\n" unless $quiet;
if ($set_date) {
$> = 0 if $opt_u;
open(my $fd, "-|", $datecommand, $dateparam, $newtime);
if ( $? != 0 ) {
print STDERR "An error occured setting the time\n";
while (<$fd>) {
print STDERR $_;
}
}
close($fd);
$> = getpwnam($opt_u) if $opt_u;
}
}
}
my @urls = parseCommandLine();
my @diffdts;
foreach my $url (@urls) {
# TODO: use try/catch, return a zero diff on failure
my $diffdt = getRemoteDateDiff($url, $fullrequest);
push @diffdts, $diffdt;
}
my @sorted_diffdts = sort {
$a->in_units('seconds') <=> $b->in_units('seconds')
} @diffdts;
adjustDate($sorted_diffdts[int(@sorted_diffdts / 2)]);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment