diff options
Diffstat (limited to 'server.cgi')
-rwxr-xr-x | server.cgi | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/server.cgi b/server.cgi new file mode 100755 index 0000000..f52f3d9 --- /dev/null +++ b/server.cgi @@ -0,0 +1,128 @@ +#!/usr/bin/perl +# +# Copyright (c) 2013 Michel Ketterle, Steven Schubiger +# +# This file is part of distdns. +# +# distdns 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 3 of the License, or +# (at your option) any later version. +# +# distdns is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with distdns. If not, see <http://www.gnu.org/licenses/>. + +use strict; +use warnings; + +use CGI (); +use Fcntl ':flock'; +use JSON qw(decode_json encode_json); + +my $VERSION = '0.04'; + +#----------------------- +# Start of configuration +#----------------------- + +my $json_file = 'data.json'; +my $session_file = 'session.dat'; + +#--------------------- +# End of configuration +#--------------------- + +my $query = CGI->new; + +my @params = qw(netz pc name debug init session); +my %params; + +foreach my $param (@params) { + $params{$param} = $query->param($param); +} +$params{ip} = $query->remote_addr; + +if ($params{debug}) { + $SIG{__DIE__} = sub + { + print $query->header('application/json'); + print encode_json({ entries => [], error => $_[0] }); + exit; + }; +} + +if ($params{init}) { + die "Delete server-side $session_file first\n" if -e $session_file; + + open(my $fh, '>', $session_file) or die "Cannot open server-side $session_file for writing: $!\n"; + print {$fh} "$params{session}\n"; + close($fh); +} +else { + open(my $fh, '<', $session_file) or die "Cannot open server-side $session_file for reading: $!\nPerhaps try running --init\n"; + my $session = do { local $/; <$fh> }; + chomp $session; + close($fh); + + die "Session ID mismatch\n" unless $params{session} eq $session; +} + +my @missing_params = grep { not defined $params{$_} && length $params{$_} } @params; +if (@missing_params) { + my $missing_params = join ', ', map "'$_'", @missing_params; + die "Incomplete query: param(s) $missing_params missing or not defined\n"; +} + +my %access; +my $access_file = "$params{netz}.conf"; + +if (-e $access_file) { + open(my $fh, '<', $access_file) or die "Cannot open $access_file for reading: $!\n"; + while (my $line = <$fh>) { + chomp $line; + my ($name, $pc) = split /\s*,\s*/, $line; + push @{$access{$name}}, $pc; + } + close($fh); +} +else { + die "Access file $access_file does not exist\n"; +} + +if (exists $access{$params{name}} && grep /^$params{pc}$/i, @{$access{$params{name}}}) { + open(my $fh, '+<', $json_file) or die "Cannot open $json_file for read/write: $!\n"; + flock($fh, LOCK_EX) or die "Cannot lock $json_file: $!\n"; + + my $json = do { local $/; <$fh> }; + + my $data = defined $json && length $json ? decode_json($json) : []; + + for (my $i = 0; $i < @$data; $i++) { + if ($params{netz} eq $data->[$i]->{netz} + && $params{pc} eq $data->[$i]->{pc} + && $params{name} eq $data->[$i]->{name}) { + splice @$data, $i--, 1; + } + } + push @$data, { map { $_ => $params{$_} } qw(netz pc name ip) }; + + seek($fh, 0, 0) or die "Cannot seek to start of $json_file: $!\n"; + truncate($fh, 0) or die "Cannot truncate $json_file: $!\n"; + + print {$fh} encode_json($data); + + close($fh); + + my @data = grep $_->{netz} eq $params{netz}, @$data; + + print $query->header('application/json'); + print encode_json({ entries => \@data, error => undef }); +} +else { + die "Access not permitted\n"; +} |