jak wdrożyć ustawę hazardową 2017 w sieci ISP (Mikrotik, Bind, Dnsmasq, PowerDNS) 26-04-2017 18:00:00 19-05-2024 00:00:00
Aktualizacja [2024-03-01] - skrypt z przeznaczeniem dla PowerDNS od Marka z amelek.net Aktualizacja [2022-02-18] - naprawienie problemu w skrypcie dla BIND`a z domenami, które mają w nazwie '_' [podkreślenie] Aktualizacja [2018-11-01] - wyeliminowanie problemu z DNS-em powodowanym przez występowanie w domenach znaków specyficznych dla krajów - IDN Aktualizacja [2017-07-04] - w strefie było zbyt długie TTL (7 dni) zmieniono na 2 godziny w hazardBind Aktualizacja [2017-06-29] - błędna kolejność IP oraz Domeny w hazardDNSMasq, - brak nowej linii w $zoneNew po IP MF w hazardBind Aktualizacja [2017-06-28] - dodano Lp (hazardMikrotik, hazardBind oraz hazardDNSMasq), - dodano generowanie kodu inne dla Mikrotik RouterOS v5 oraz v6 (hazardMikrotik) Dz.U. 2017 poz. 88 (Ustawa z dnia 15 grudnia 2016 r. o zmianie ustawy o grach hazardowych oraz niektórych innych ustaw) Z dniem 1 lipca 2017r. przedsiębiorca telekomunikacyjny świadczący usługi dostępu do sieci Internet jest obowiązany do:
Polecam obejrzeć relacje z iNET Meeting 2017, rozmowa chyba z prawnikiem: https://www.facebook.com/inetgroup/videos/1407249126009025/ Rejestr Domen Służących do Oferowania Gier Hazardowych Niezgodnie z Ustawą: https://hazard.mf.gov.pl Adres na który należy kierować połączenia: 145.237.235.240 Skrypty pisane są pod Debiana 8, ale nie znaczy to że nie będą działać na innych systemach. Do uruchomiena jest wymagany perl oraz moduły perlowe: XML::Simple, LWP::UserAgent, IO::Socket::SSL, POSIX, Net::IDN::Encode. Instalacja Debian: apt-get install libxml-simple-perl libnet-idn-encode-perl Wykorzystując skrypt dla Mikrotika dodatkowo jest potrzebny serwer WWW, poprzez który Mikrotik pobierze plik z liniami kodu. Konfiguracja dla RouterOS by Mikrotik: Stwórz pliki: touch /opt/hazardMikrotik.pl touch /etc/cron.d/hazardMikrotik touch /var/www/mikrotik5.rsc touch /var/www/mikrotik6.rsc touch /var/www/date.txt
#!/usr/bin/perl
use XML::Simple;
use LWP::UserAgent;
use IO::Socket::SSL;
use POSIX qw(strftime);
use Net::IDN::Encode ':all';
## www.kazuko.pl
## hazardMikrotik v0.4 [2018-11-30]
## START ## USTAWIENIA
my $urlHazardXML = "https://hazard.mf.gov.pl/api/Register"; # baza stron hazardowych
my $addressIP = "145.237.235.240"; # adres IP na który mają być kierowane zapytania
my $pathFile5 = "/var/www/mikrotik5.rsc"; # ścieżka do pliku z transkodem dla mikrotika v5.xx
my $pathFile6 = "/var/www/mikrotik6.rsc"; # ścieżka do pliku z transkodem dla mikrotika v6.xx
my $pathFileDate = "/var/www/date.txt"; # ścieżka do pliku, w którym jest data ostatniej aktualizacji
my $runCommend = ""; # komenda która będzie uruchamiana, jeśli zostanie coś zmodyfikowane w bazie stron
## KONIEC ## USTAWIENIA
my $ua = LWP::UserAgent->new;
$ua->default_header('Accept-Language' => "pl");
$ua->ssl_opts(%{{'verify_hostname' => 0, 'SSL_verify_mode' => SSL_VERIFY_NONE}});
my $response = $ua->get($urlHazardXML);
if($response->is_success) {
my $xml = new XML::Simple;
$data = $xml->XMLin($response->content);
my $dataNew5 = "/ip dns static remove [find comment~\"# hazard\"]\n";
$dataNew5 .= "/ip dns static\n";
my $dataNew6 = "/ip dns static remove [find comment~\"# hazard\"]\n";
$dataNew6 .= "/ip dns static\n";
my %isAdd;
foreach my $domain (@{$data->{'PozycjaRejestru'}}) {
my $domena = domain_to_ascii($domain->{'AdresDomeny'});
if(!$isAdd{$domena}) {
if($domain->{'DataWykreslenia'}) {
$dataNew5 .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\n";
$dataNew5 .= "add name=\"$domena\" address=\"$addressIP\" disabled=yes comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\";\n\n";
$dataNew6 .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\n";
$dataNew6 .= ":do { add name=\"$domena\" address=\"$addressIP\" disabled=yes comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\"; } on-error={ set [find name=\"$domena\"] address=\"$addressIP\" disabled=yes comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\"; }\n\n";
} else {
$dataNew5 .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\n";
$dataNew5 .= "add name=\"$domena\" address=\"$addressIP\" disabled=no comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\";\n\n";
$dataNew6 .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\n";
$dataNew6 .= ":do { add name=\"$domena\" address=\"$addressIP\" disabled=no comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\"; } on-error={ set [find name=\"$domena\"] address=\"$addressIP\" disabled=no comment=\"# hazard # Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\"; }\n\n";
}
$isAdd{$domena} = $domena;
}
}
$dataNew5 =~ s/^\s+//;
$dataNew5 =~ s/\s+$//;
$dataNew6 =~ s/^\s+//;
$dataNew6 =~ s/\s+$//;
my $dataOld5 = "";
if(-e $pathFile5) {
open(UCHWYT, $pathFile5);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $dataOld5 .= $row; } }
close (UCHWYT);
$dataOld5 =~ s/^\s+//;
$dataOld5 =~ s/\s+$//;
}
my $dataOld6 = "";
if(-e $pathFile6) {
open(UCHWYT, $pathFile6);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $dataOld6 .= $row; } }
close (UCHWYT);
$dataOld6 =~ s/^\s+//;
$dataOld6 =~ s/\s+$//;
}
if($dataOld5 ne $dataNew5 or $dataOld6 ne $dataNew6) {
my $date = strftime('%d-%m-%Y %H:%M:%S',localtime(time));
open(UCHWYT, '>', $pathFile5) or die "Nie można otworzyć $pathFile5: $!";
print UCHWYT "## Ostatnia aktualizacja: $date\n\n".$dataNew5;
close UCHWYT;
#system("chown root:root $pathFile5 1> /dev/null 2> /dev/null");
my $date = strftime('%d-%m-%Y %H:%M:%S',localtime(time));
open(UCHWYT, '>', $pathFile6) or die "Nie można otworzyć $pathFile6: $!";
print UCHWYT "## Ostatnia aktualizacja: $date\n\n".$dataNew6;
close UCHWYT;
#system("chown root:root $pathFile6 1> /dev/null 2> /dev/null");
if($pathFileDate) {
open(UCHWYT, '>', $pathFileDate) or die "Nie można otworzyć $pathFileDate: $!";
print UCHWYT $date;
close UCHWYT;
#system("chown root:root $pathFileDate 1> /dev/null 2> /dev/null");
}
if($runCommend) { system($runCommend); }
}
} else {
print STDERR "Error: ".$response->status_line."\n";
}
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 0 */2 * * * root perl /opt/hazardMikrotik.pl perl /opt/hazardMikrotik.pl http://hazard.domena.pl - zmień na swoją
## Włącz cache DNS na mikrotiku:
/ip dns set allow-remote-requests=yes
## Zablokuj możliwość korzystania z cache DNS dla hostów nie będących w Twojej sieci
## Jeśli nie będzie blokady, Mikrotik może zostać wykorzystany do ataków DDoS
## Zmień na własny: INTERFEJS_WANOWY
/ip firewall filter
add action=drop chain=input dst-port=53 protocol=udp in-interface=INTERFEJS_WANOWY
## Skrypt aktualizujący wpisy w cache DNS`ie dla Mikrotika RouterOS v5.xx
/system script
add name=ustawa-hazardowa policy=read,write,policy,test source=":global hazardUpdateOld\r\
\n/tool fetch url=\"http://hazard.domena.pl/date.txt\" mode=http dst-path=\"/hazardUpdate.txt\"\r\
\n:delay 2\r\
\n:local hazardUpdateNew [/file get hazardUpdate.txt contents];\r\
\n/file remove hazardUpdate.txt\r\
\n\r\
\n :if (\"\$hazardUpdateNew\" != \"\$hazardUpdateOld\" and \"\$hazardUpdateNew\" != \"\") do={\r\
\r\
\n\t/tool fetch url=\"http://hazard.domena.pl/mikrotik5.rsc\" mode=http dst-path=\"/hazardUpdate.rs\
c\"\r\
\n\t/import hazardUpdate.rsc\r\
\n\t:delay 2\r\
\n\t/file remove hazardUpdate.rsc\r\
\n\t:set hazardUpdateOld \$hazardUpdateNew\r\
\n }\r\
\n"
## Skrypt aktualizujący wpisy w cache DNS`ie dla Mikrotika RouterOS v6.xx
/system script
add name=ustawa-hazardowa policy=read,write,policy,test source=":global hazardUpdateOld\r\
\n/tool fetch url=\"http://hazard.domena.pl/date.txt\" mode=http dst-path=\"/hazardUpdate.txt\"\r\
\n:delay 2\r\
\n:local hazardUpdateNew [/file get hazardUpdate.txt contents];\r\
\n/file remove hazardUpdate.txt\r\
\n\r\
\n :if (\"\$hazardUpdateNew\" != \"\$hazardUpdateOld\" and \"\$hazardUpdateNew\" != \"\") do={\r\
\r\
\n\t/tool fetch url=\"http://hazard.domena.pl/mikrotik6.rsc\" mode=http dst-path=\"/hazardUpdate.rs\
c\"\r\
\n\t/import hazardUpdate.rsc\r\
\n\t:delay 2\r\
\n\t/file remove hazardUpdate.rsc\r\
\n\t:set hazardUpdateOld \$hazardUpdateNew\r\
\n }\r\
\n"
## Uruchamianie skryptu aktualizującego wpisy w cache DNS`ie co 12 godzin:
/system scheduler
add interval=12h name=ustawa-hazardowa on-event="/system script run ustawa-hazardowa\r\
\n" policy=read,write,policy,test start-date=apr/01/2017 start-time=22:10:00
/system script environment remove hazardUpdateOld Konfiguracja dla BIND`a: Do pliku /etc/bind/named.conf dodaj: include "/etc/bind/named.conf.hazard-redirect"; touch /opt/hazardBind.pl touch /etc/cron.d/hazardBind touch /etc/bind/named.conf.hazard-redirect touch /etc/bind/db.hazard-redirect
#!/usr/bin/perl
use XML::Simple;
use LWP::UserAgent;
use IO::Socket::SSL;
use POSIX qw(strftime);
use Net::IDN::Encode ':all';
## www.kazuko.pl
## hazardBind v0.7 [2022-02-18]
## START ## USTAWIENIA
my $urlHazardXML = "https://hazard.mf.gov.pl/api/Register"; # baza stron hazardowych
my $addressIP = "145.237.235.240"; # adres IP na który mają być kierowane zapytania
my $pathFile = "/etc/bind/named.conf.hazard-redirect"; # ścieżka do pliku, w której będą domeny hazardowe
my $pathFileZone = "/etc/bind/db.hazard-redirect"; # ścieżka do pliku ze strefą dla domen hazardowych
my $runCommend = "/etc/init.d/bind9 reload 1> /dev/null 2> /dev/null"; # komenda która będzie uruchamiana, jeśli zostanie coś zmodyfikowane w bazie stron
## KONIEC ## USTAWIENIA
my $ua = LWP::UserAgent->new;
$ua->default_header('Accept-Language' => "pl");
$ua->ssl_opts(%{{'verify_hostname' => 0, 'SSL_verify_mode' => SSL_VERIFY_NONE}});
my $response = $ua->get($urlHazardXML);
if($response->is_success) {
my $xml = new XML::Simple;
$data = $xml->XMLin($response->content);
my $dataNew = "";
my %isAdd;
foreach my $domain (@{$data->{'PozycjaRejestru'}}) {
my $domena = domain_to_ascii($domain->{'AdresDomeny'});
if(!$isAdd{$domena}) {
if($domain->{'DataWykreslenia'}) {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\n";
$dataNew .= "# zone \"$domena\" { type master; file \"$pathFileZone\"; ".($domena =~ /\_/ ? "check-names ignore; " : "")."};\n\n";
} else {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\n";
$dataNew .= "zone \"$domena\" { type master; file \"$pathFileZone\"; ".($domena =~ /\_/ ? "check-names ignore; " : "")."};\n\n";
}
$isAdd{$domena} = $domena;
}
}
$dataNew =~ s/^\s+//;
$dataNew =~ s/\s+$//;
my $dataOld = "";
if(-e $pathFile) {
open(UCHWYT, $pathFile);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $dataOld .= $row; } }
close (UCHWYT);
$dataOld =~ s/^\s+//;
$dataOld =~ s/\s+$//;
}
if($dataOld ne $dataNew) {
open(UCHWYT, '>', $pathFile) or die "Nie można otworzyć $pathFile: $!";
print UCHWYT "## Ostatnia aktualizacja: ".strftime('%d-%m-%Y %H:%M:%S',localtime(time))."\n\n".$dataNew;
close UCHWYT;
#system("chown root:root $pathFile 1> /dev/null 2> /dev/null");
if($runCommend) { system($runCommend); }
}
if($pathFileZone) {
my $zoneNew = "\$TTL 7200\n";
$zoneNew .= "@ IN SOA localhost. root.localhost. (\n";
$zoneNew .= " 1 ; Serial\n";
$zoneNew .= " 604800 ; Refresh\n";
$zoneNew .= " 86400 ; Retry\n";
$zoneNew .= " 2419200 ; Expire\n";
$zoneNew .= " 604800 ) ; Negative Cache TTL\n";
$zoneNew .= "@ IN NS localhost.\n";
$zoneNew .= "@ IN A $addressIP\n";
my $zoneOld = "";
if(-e $pathFileZone) {
open(UCHWYT, $pathFileZone);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $zoneOld .= $row; } }
close (UCHWYT);
$zoneOld =~ s/^\s+//;
$zoneOld =~ s/\s+$//;
}
if($zoneOld ne $zoneNew) {
open(UCHWYT, '>', $pathFileZone) or die "Nie można otworzyć $pathFileZone: $!";
print UCHWYT $zoneNew;
close UCHWYT;
#system("chown root:root $pathFileZone 1> /dev/null 2> /dev/null");
}
}
} else {
print STDERR "Error: ".$response->status_line."\n";
}
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 0 */2 * * * root perl /opt/hazardBind.pl perl /opt/hazardBind.pl Konfiguracja dla Dnsmasq`a: Do pliku /etc/dnsmasq.conf dodaj (lub z edytuj): addn-hosts=/etc/dnsmasq_hosts_hazard-redirect touch /opt/hazardDNSMasq.pl touch /etc/cron.d/hazardDNSMasq touch /etc/dnsmasq_hosts_hazard-redirect
#!/usr/bin/perl
use XML::Simple;
use LWP::UserAgent;
use IO::Socket::SSL;
use POSIX qw(strftime);
use Net::IDN::Encode ':all';
## www.kazuko.pl
## hazardDNSMasq v0.5 [2018-11-30]
## START ## USTAWIENIA
my $urlHazardXML = "https://hazard.mf.gov.pl/api/Register"; # baza stron hazardowych
my $addressIP = "145.237.235.240"; # adres IP na który mają być kierowane zapytania
my $pathFile = "/etc/dnsmasq_hosts_hazard-redirect"; # ścieżka do pliku, w której będą domeny hazardowe
my $runCommend = "/etc/init.d/dnsmasq restart 1> /dev/null 2> /dev/null"; # komenda która będzie uruchamiana, jeśli zostanie coś zmodyfikowane w bazie stron
## KONIEC ## USTAWIENIA
my $ua = LWP::UserAgent->new;
$ua->default_header('Accept-Language' => "pl");
$ua->ssl_opts(%{{'verify_hostname' => 0, 'SSL_verify_mode' => SSL_VERIFY_NONE}});
my $response = $ua->get($urlHazardXML);
if($response->is_success) {
my $xml = new XML::Simple;
$data = $xml->XMLin($response->content);
my $dataNew = "";
my %isAdd;
foreach my $domain (@{$data->{'PozycjaRejestru'}}) {
my $domena = domain_to_ascii($domain->{'AdresDomeny'});
if(!$isAdd{$domena}) {
if($domain->{'DataWykreslenia'}) {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\n";
$dataNew .= "# $addressIP $domena\n\n";
} else {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\n";
$dataNew .= "$addressIP $domena\n\n";
}
$isAdd{$domena} = $domena;
}
}
$dataNew =~ s/^\s+//;
$dataNew =~ s/\s+$//;
my $dataOld = "";
if(-e $pathFile) {
open(UCHWYT, $pathFile);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $dataOld .= $row; } }
close (UCHWYT);
$dataOld =~ s/^\s+//;
$dataOld =~ s/\s+$//;
}
if($dataOld ne $dataNew) {
open(UCHWYT, '>', $pathFile) or die "Nie można otworzyć $pathFile: $!";
print UCHWYT "## Ostatnia aktualizacja: ".strftime('%d-%m-%Y %H:%M:%S',localtime(time))."\n\n".$dataNew;
close UCHWYT;
#system("chown root:root $pathFile 1> /dev/null 2> /dev/null");
if($runCommend) { system($runCommend); }
}
} else {
print STDERR "Error: ".$response->status_line."\n";
}
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 0 */2 * * * root perl /opt/hazardDNSMasq.pl perl /opt/hazardDNSMasq.pl Konfiguracja dla PowerDNS`a by Markek z amelek.net: Obecnie jako cache DNS dla klientów używam PowerDNS (pdns-recursor 4.8.6-1, Debian 12.5 jako VM pod xcp-ng). Mam 2 takie serwery, tak samo skonfigurowane, w 2 różnych lokalizacjach dla redundancji. Skrypt jest zmodyfikowaną wersją dla dnsmasq (ten sam format pliku zgodny z /etc/hosts). W /etc/powerdns/recursor.conf zmieniamy ustawienia: allow-from-file=/etc/powerdns/allow-from etc-hosts-file=/var/cache/pdns/hosts.hazard-redirect export-etc-hosts=on local-address=0.0.0.0 socket-mode=0664 W /etc/powerdns/allow-from umieszczamy listę kto może korzystać z DNS, na końcu przykładowe moje prefiksy: 127.0.0.0/8 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 100.64.0.0/10 ::1/128 fe80::/10 91.224.224.0/23 185.38.220.0/22 2a04:7840::/29 Zwykłego użytkownika dodajemy do grupy "pdns" by pozwolić na przeładowanie bez uprawnień root-a (socket-mode 0664 pozwala tej grupie). Tworzymy katalog /var/cache/pdns z uprawnieniami 0775 zapisywalny dla grupy "pdns" gdzie skrypt będzie zapisywał pliki. W crontab użytkownika (mój przykładowy "marekm", edycja poleceniem "crontab -e") wpisujemy uruchomienie skryptu: # m h dom mon dow command 59 */2 * * * /home/marekm/bin/hazard-update.pl
#!/usr/bin/perl
use XML::Simple;
use LWP::UserAgent;
use IO::Socket::SSL;
use POSIX qw(strftime);
use Net::IDN::Encode ':all';
## www.kazuko.pl
## hazardPowerDNS v0.1 [2024-03-01] by Markek z amelek.net
## START ## USTAWIENIA
my $urlHazardXML = "https://hazard.mf.gov.pl/api/Register"; # baza stron hazardowych
my $addressIP = "145.237.235.240"; # adres IP na który mają być kierowane zapytania
my $pathFile = "/var/cache/pdns/hosts.hazard-redirect"; # ścieżka do pliku, w której będą domeny hazardowe
my $pathFileTmp = $pathFile . ".new";
my $pathFileOld = $pathFile . ".old";
my $runCommend = "rec_control reload-zones"; # komenda która będzie uruchamiana, jeśli zostanie coś zmodyfikowane w bazie stron
## KONIEC ## USTAWIENIA
my $ua = LWP::UserAgent->new;
$ua->default_header('Accept-Language' => "pl");
$ua->ssl_opts(%{{'verify_hostname' => 0, 'SSL_verify_mode' => SSL_VERIFY_NONE}});
my $response = $ua->get($urlHazardXML);
if($response->is_success) {
my $xml = new XML::Simple;
$data = $xml->XMLin($response->content);
my $dataNew = "";
my %isAdd;
foreach my $domain (@{$data->{'PozycjaRejestru'}}) {
my $domena = domain_to_ascii($domain->{'AdresDomeny'});
if(!$isAdd{$domena}) {
if($domain->{'DataWykreslenia'}) {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}." # wykreslono: ".$domain->{'DataWykreslenia'}."\n";
$dataNew .= "# $addressIP $domena\n\n";
} else {
$dataNew .= "# Lp: ".$domain->{'Lp'}." # dodano: ".$domain->{'DataWpisu'}."\n";
$dataNew .= "$addressIP $domena\n\n";
}
$isAdd{$domena} = $domena;
}
}
$dataNew =~ s/^\s+//;
$dataNew =~ s/\s+$//;
my $dataOld = "";
if(-e $pathFile) {
open(UCHWYT, $pathFile);
while (my $row = <UCHWYT>) { if(!($row =~ /^##\sOstatnia\saktualizacja/)) { $dataOld .= $row; } }
close (UCHWYT);
$dataOld =~ s/^\s+//;
$dataOld =~ s/\s+$//;
}
if($dataOld ne $dataNew) {
open(UCHWYT, '>', $pathFileTmp) or die "Nie można otworzyć $pathFileTmp: $!";
print UCHWYT "## Ostatnia aktualizacja: ".strftime('%FT%T',localtime(time))."\n\n".$dataNew;
close UCHWYT;
unlink($pathFileOld);
link($pathFile, $pathFileOld);
rename($pathFileTmp, $pathFile) or die "rename $pathFileTmp $pathFile: $!";
if($runCommend) { system($runCommend); }
}
} else {
print STDERR "Error: ".$response->status_line."\n";
}
|






26-04-2017 18:00:00
19-05-2024 00:00:00