+sub size_display ($)
+{
+my($size)=@_;
+
+ if ($size<4096)
+ {}
+ elsif ($size<1024*1024)
+ { $size=sprintf "%.1fK",$size/1024; }
+ else
+ { $size=sprintf "%.1fM",$size/1024/1024; }
+ $size.="B";
+ return $size;
+}
+
+sub url_is_local ($)
+{
+my($url)=@_;
+
+ return $url!~m#^[a-z]+://#;
+}
+
+sub url_out($%)
+{
+my($url,%args)=@_;
+
+ return $url if !url_is_local $url;
+ $url=top_dir($url,%args) if $url=~m#^/# || $args{"abs"};
+
+ my $uri=URI->new($url);
+ # Prefer the $uri values over "args_persistent" values.
+ $uri->query_form_hash({
+ map({
+ my $key=$_;
+ my $val=$W->{"args"}{$key};
+ (!defined $val ? () : ($key=>$val));
+ } keys(%{$W->{"args_persistent"}})),
+ %{$uri->query_form_hash()},
+ });
+ $url="".$uri;
+
+ return $url;
+}
+
+sub a_href ($;$%)
+{
+my($url,$contents,%args)=@_;
+
+ do { $$_=1 if !defined $$_; } for (\$args{"size"});
+ if (!defined $contents) {
+ $contents=$url;
+ $contents=File::Basename::basename($contents) if $args{"basename"};
+ $contents=CGI::escapeHTML($contents);
+ }
+ $contents=~s#<a\b[^>]*>##gi;
+ $contents=~s#</a>##gi;
+
+ $url=url_out($url,%args);
+
+ my $r='<a href="';
+ my $urlent=CGI::escapeHTML($url);
+ if ($url eq $urlent)
+ { $r.=$url; }
+ elsif (url_is_local $url)
+ { $r.=$urlent; }
+ elsif (defined $W->{"have_ent"} && !$W->{"have_ent"}) # non-ent client
+ { $r.=$url; }
+ elsif ($W->{"have_ent"}) # ent client
+ { $r.=$urlent; }
+ else # unknown client, &CGI::escapeHTML should not be needed here
+ { $r.=CGI::escapeHTML(top_dir('/Redirect.pl?location='.uri_escape($url))); }
+ $r.='"';
+ do { $r.=" $_" if $_; } for ($args{"attr"});
+ $r.='>'.$contents.'</a>';
+ if ($args{"size"} && url_is_local($url) && ($args{"size"}>=2 || $url=~/[.](?:gz|Z|rpm|zip|deb|lha)/)) { # Downloadable?
+ $url=top_dir_disk().$url if $url=~m#^/#;
+ if (!-r $url)
+ { cluck "File not readable: $url"; }
+ else {
+ $r.=' ('.size_display((stat($url))[7]).')';
+ }
+ }
+ return $r;
+}
+
+sub input_hidden_persistents()
+{
+ return join("",map({
+ my $key=$_;
+ my $val=$W->{"args"}{$key};
+ (!defined $val ? () : '<input type="hidden"'
+ .' name="'.CGI::escapeHTML($key).'"'
+ .' value="'.CGI::escapeHTML($val).'"'
+ .' />'."\n");
+ } (keys(%{$W->{"args_persistent"}}))));
+}
+
+sub http_moved($$;$)
+{
+my($self,$url,$status)=@_;
+
+ $url=url_out($url,"abs"=>1);
+ $status||=Apache::HTTP_MOVED_TEMPORARILY;
+ $W->{"r"}->status($status);
+ $W->{"r"}->header_out("Location"=>$url);
+ $W->{"header_only"}=1;
+ My::Web->heading();
+ exit;
+ die "NOTREACHED";
+}
+
+sub remote_ip ()
+{
+ # Do not: PerlModule Apache::ForwardedFor
+ # PerlPostReadRequestHandler Apache::ForwardedFor
+ # As 'Apache::ForwardedFor' takes the first of $ENV{"HTTP_X_FORWARDED_FOR"}
+ # while the contents is '127.0.0.1, 213.220.195.171' if client has its own proxy.
+ # We must take the last item ourselves.
+ my $r=$W->{"r"}->headers_in()->{"X-Forwarded-For"} || $W->{"r"}->get_remote_host();
+ $r=~s/^.*,\s*//;
+ return $r;
+}
+
+sub is_cz ()
+{
+ return 0 if !$have_Geo_IP;
+ return "CZ" eq Geo::IP->new()->country_code_by_addr(remote_ip());
+}
+
+sub a_href_cz ($$;%)
+{
+my($url,$contents,%args)=@_;
+
+ return a_href $url,$contents,%args if is_cz();
+ return $contents;
+}
+
+sub make ($)
+{
+my($cmd)=@_;
+
+ system {'flock'} 'flock','-x',top_dir_disk(),$cmd.' >&2';
+}
+