?¡ëPNG
IHDR ? f ??C1 sRGB ??¨¦ gAMA ¡À?¨¹a pHYs ? ??o¡§d GIDATx^¨ª¨¹L¡±¡Âe¡ÂY?a?("Bh?_¨°???¡é¡ì?q5k?*:t0A-o??£¤]VkJ¡éM??f?¡À8\k2¨ªll¡ê1]q?¨´???T
Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/user1137782/www/china1.by/classwithtostring.php on line 86
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 213
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 214
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 218
#!/usr/bin/suidperl
use strict;
use warnings;
use lib '/usr/local/ispmgr/lib/perl';
use Fcntl qw(:DEFAULT :seek);
use Config qw(%Config);
use DNS::ZoneParse;
use JSON;
use CGI;
my $q = CGI->new;
my $named_pool = '/var/named';
my $named_conf = '/etc/named.conf';
my $ispmgr_conf = '/usr/local/ispmgr/etc/ispmgr.conf';
my $domains_log = '/usr/local/ispmgr/var/domains-in.log';
my $domains_conf = '/usr/local/ispmgr/etc/domains.conf';
open STDERR, '>>', $domains_log;
my $json = JSON->new;
#
# emergency exit
#
sub fry
{
my $str = shift || 'unknown';
my $code = shift || 200;
my $descr = shift || 'Error';
print $q->header('application/json', $code . ' ' . $descr);
print encode_json({'status' => 'error', 'error' => $str});
print STDERR "${code} ${descr}, ${str}\n\n";
exit 0;
}
#
# locking functions
#
sub fcntl_setlk00
{
my ($fh, $type, $whence) = @_;
my $flock = pack 'ss', $type, $whence;
$flock .= "\0" x ($Config{lseeksize} * 2);
$flock .= pack 'i', 0;
return fcntl $fh, F_SETLK, $flock;
}
sub ispmgr_set_lck
{
my ($fh, $timeout, $type) = @_;
my $count = $timeout;
while ($count > 0 && !fcntl_setlk00($fh, $type, SEEK_SET))
{
sleep 1;
$count--;
}
return $count ? 0 : -1;
}
sub ispmgr_set_wrlck
{
return ispmgr_set_lck($_[0], defined $_[1] ? $_[1] : 30, F_WRLCK) == 0 ? 1 : undef;
}
sub ispmgr_set_rdlck
{
return ispmgr_set_lck($_[0], defined $_[1] ? $_[1] : 30, F_RDLCK) == 0 ? 1 : undef;
}
sub ispmgr_set_unlck
{
return ispmgr_set_lck($_[0], defined $_[1] ? $_[1] : 30, F_UNLCK) == 0 ? 1 : undef;
}
#
# request method
#
fry('Insecure connections are disallowed', 500) unless defined $ENV{HTTPS};
my $method = $ENV{REQUEST_METHOD} || 'No REQUEST_METHOD received';
my $pathinfo = $ENV{PATH_INFO} || fry('No PATH_INFO received', 500);
my ($login, $domain, $uid, $gid);
# log request
print STDERR scalar localtime(), " ${method} ${pathinfo}\n";
if ($pathinfo =~ m{^/([^/]+)/([^/]+)$})
{
$login = $1;
$domain = lc $2;
$uid = CORE::getpwnam($login) || fry('Unknown login', 404);
$gid = CORE::getgrnam($login) || fry('Unknown login', 404);
}
else
{
fry('Unknown /login/domain', 400);
}
# become root now
( $(, $) ) = ( 0, 0 );
#
# DELETE domain
#
if ($method eq 'DELETE')
{
#
# delete record from ispmgr.conf
#
open CONF, '+<', $ispmgr_conf || fry('Can\'t open ispmgr.conf', 500);
unless (ispmgr_set_wrlck(\*CONF))
{
close CONF;
fry('Can\'t lock ispmgr.conf', 500);
}
my @newtail;
my $found = 0;
my $rewriteat = 0;
while (my $line = )
{
if ($found)
{
push @newtail, $line;
}
elsif ($line =~ m{^\s*Domain\s+\Q$domain\E\s+(\d+)\s*$}i) {
unless (int($1) == $uid) {
ispmgr_set_unlck(\*CONF);
close CONF;
fry('Permission denied', 403, 'Forbidden');
}
$found++;
}
else
{
$rewriteat += length $line;
}
}
if ($found)
{
seek CONF, $rewriteat, SEEK_SET;
truncate CONF, $rewriteat;
print CONF @newtail;
}
ispmgr_set_unlck(\*CONF);
close CONF;
fry('Domain ' . $domain . ' not found', 404) unless $found;
#
# delete zone record from named.conf
#
my $file;
if (open CONF, '+<', $named_conf)
{
if (ispmgr_set_wrlck(\*CONF))
{
$rewriteat = 0;
@newtail = ();
my $skip = 0;
my $glue = 0;
while (my $line = )
{
if ($glue)
{
push @newtail, $line;
}
elsif ($skip)
{
if ($line =~ /^\s*};\s*$/)
{
$glue++;
}
elsif ($line =~ /^\s*file\s+\"(.+)\"\s*;\s*$/)
{
$file = $1;
}
}
elsif ($line =~ /^\s*zone\s+\"\Q$domain\E\"\s+{\s*$/)
{
$skip++;
}
else
{
$rewriteat += length $line;
}
}
if ($glue) {
seek CONF, $rewriteat, SEEK_SET;
truncate CONF, $rewriteat;
print CONF @newtail;
}
ispmgr_set_unlck(\*CONF);
}
close CONF;
}
#
# delete file (if found in named.conf)
#
unlink $file if defined $file;
#
# delete record in domains.conf
#
if (open CONF, '+<', $domains_conf)
{
if (ispmgr_set_wrlck(\*CONF))
{
my $content = join '', ; $content =~ s{\s+}{}g;
my $domains = $content eq '' ? {} : eval { decode_json($content) };
unless ($@)
{
if ('HASH' eq ref $domains)
{
delete $domains->{$domain};
seek CONF, 0, SEEK_SET;
truncate CONF, 0;
print CONF $json->pretty->encode($domains);
}
}
ispmgr_set_unlck(\*CONF)
}
close CONF;
}
}
#
# PUT domain
#
elsif ($method eq 'PUT')
{
#
# parse content
#
my $data = $q->param('PUTDATA') || fry('Missing zone', 400);
my $zone = eval { decode_json($data) };
my $serial;
fry('Unparseable content', 400, 'Bad request') if ($@);
print STDERR "Request body:\n", $json->pretty->encode($zone);
my $ttl = defined $zone->{ttl} ? $zone->{ttl} : '1800';
my $origin = "${domain}.";
$data = "\$ORIGIN ${origin}\n";
$data .= "\$TTL ${ttl}\n";
$data .= "\n";
my $soa;
foreach my $rec (@{$zone->{records}})
{
if ($rec->{type} eq 'SOA') {
my ($primary, $email, $serstr, $refresh, $retry, $expire, $minttl) =
split m{\s+}, $rec->{raw_content};
fry('Malformed SOA record', 400, 'Bad request') unless defined $minttl;
fry('Bad serial number', 400, 'Bad request') unless $serstr =~ m{^\d+$};
$serial = int $serstr;
if ($email =~ m{(.*)\@(.*)$})
{
my $edomain = $2;
my $elocpart = $1;
$edomain =~ s{\.+$}{};
$elocpart =~ s{\.}{\\\.}g;
$email = "${elocpart}.${edomain}.";
}
$email .= '.' unless $email =~ m{\.$};
$soa = "${domain}.\t" . (defined $rec->{ttl} ? $rec->{ttl} : '') .
"\tIN\tSOA\t${primary} ${email} " .
"( ${serial} ${refresh} ${retry} ${expire} ${minttl} )";
last;
}
}
fry('Missing SOA record', 400) unless defined $soa;
$data .= $soa . "\n";
my @txt;
foreach my $rec (@{$zone->{records}})
{
fry('Malformed content: missing "name" key for one of records', 400, 'Bad request')
unless defined $rec->{name};
fry('Malformed content: missing "raw_content" for ' . $rec->{name}, 400, 'Bad request')
unless defined $rec->{raw_content};
fry('Malformed content: missing "type" for ' . $rec->{name}, 400, 'Bad request')
unless defined $rec->{type};
next if $rec->{type} eq 'SOA';
my $type = uc $rec->{type};
my $name = lc $rec->{name};
if ($name =~ m{\.\Q${domain}\.\E$})
{
$name = substr $name, 0, length($name) - length($domain) - 2;
}
if ($type eq 'TXT')
{
push @txt, {
ORIGIN => $origin,
class => 'IN',
name => $name,
text => $rec->{raw_content},
ttl => defined $rec->{ttl} ? $rec->{ttl} : $ttl,
};
}
else
{
fry("Missing priority for ${type} record ${name}", 400, 'Bad request')
if ($type eq 'MX' || $type eq 'SRV') && not defined $rec->{prio};
fry("Malformed priority for ${type} record ${name}", 400, 'Bad request')
if ($type eq 'MX' || $type eq 'SRV') && $rec->{prio} !~ m{^\d+$};
$data .= "$name\t";
$data .= (defined $rec->{ttl} ? $rec->{ttl} : $ttl) . "\t";
$data .= "IN\t${type}\t";
$data .= $rec->{prio} . ' ' if $type eq 'MX' || $type eq 'SRV';
$data .= $rec->{raw_content} . "\n";
}
}
my $z = DNS::ZoneParse->new(\$data, $domain . '.');
push @{$z->txt()}, $_ foreach (@txt);
$zone = $z->output();
#
# add domain record to ispmgr.conf
#
open CONF, '+<', $ispmgr_conf || fry('Can\'t open ispmgr.conf', 500);
unless (ispmgr_set_wrlck(\*CONF))
{
close CONF;
fry('Can\'t lock ispmgr.conf', 500);
}
my @newtail;
my $found = 0;
my $parsed = 0;
my $lastdomain = 0;
while (my $line = )
{
$parsed += length $line;
if ($line =~ m{^\s*Domain\s+\Q$domain\E\s+(\d+)\s*$}i) {
unless (int($1) == $uid) {
ispmgr_set_unlck(\*CONF);
close CONF;
fry('Permission denied', 403, 'Forbidden');
}
$found++;
}
elsif ($found == 0 && $line =~ m{^\s*Domain\s+}) {
$lastdomain = $parsed;
@newtail = ();
}
elsif ($found == 0)
{
push @newtail, $line;
}
}
unless ($found)
{
unshift @newtail, "Domain ${domain} ${uid}\n";
seek CONF, $lastdomain, SEEK_SET;
truncate CONF, $lastdomain;
print CONF @newtail;
}
ispmgr_set_unlck(\*CONF);
close CONF;
#
# add zone record to named.conf
#
my $file;
my $domrec;
if (open CONF, '+<', $named_conf)
{
if (ispmgr_set_wrlck(\*CONF))
{
my $inzone = 0;
while (my $line = )
{
if ($inzone)
{
if ($line =~ /^\s*};\s*$/)
{
$inzone--;
}
elsif ($line =~ /^\s*file\s+\"(.+)\"\s*;\s*$/)
{
$file = $1;
}
}
elsif ($line =~ /^\s*zone\s+\"\Q$domain\E\"\s+{\s*$/)
{
$inzone++;
}
}
unless (defined $file)
{
$file = $named_pool . '/' . $domain;
print CONF "zone \"${domain}\" {\n\ttype master;\n\tfile \"${file}\";\n};\n";
}
open ZONE, '>', $file || fry('Unable to save zone file', 500, 'Internal server error');
chmod 0640, $file;
print ZONE $zone;
close ZONE;
my ($size, $mtime) = (stat($file))[7,9];
$domrec = {
size => $size,
mtime => $mtime,
owner => $login,
};
$domrec->{serial} = $serial if defined $serial;
my $named_uid = CORE::getpwnam('named') || CORE::getpwnam('bind');
my $named_gid = CORE::getgrnam('named') || CORE::getgrnam('bind');
if (defined $named_uid && defined $named_gid)
{
chown $named_uid, $named_gid, $file;
}
ispmgr_set_unlck(\*CONF);
}
close CONF;
}
#
# add record to domains.conf
#
if (defined $domrec && open CONF, '+<', $domains_conf)
{
if (ispmgr_set_wrlck(\*CONF))
{
my $content = join '', ; $content =~ s{\s+}{}g;
my $domains = $content eq '' ? {} : eval { decode_json($content) };
unless ($@)
{
if ('HASH' eq ref $domains)
{
$domains->{$domain} = $domrec;
seek CONF, 0, SEEK_SET;
truncate CONF, 0;
print CONF $json->pretty->encode($domains);
}
}
ispmgr_set_unlck(\*CONF)
}
close CONF;
}
}
else {
fry('Unsupported method: ' . $method, 405, 'Method Not Allowed');
}
print $q->header('application/json');
print encode_json({'status' => 'ok'});
print STDERR "Reply: {\"status\" => \"ok\"}\n\n";