?¡ë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";