$file.=".pm";
my $who=$W->{"__PACKAGE__"};
$who||="__My::Web" if $W->{"__My::Web_init"};
- my $aref=($W->{"packages_used"}{$who}||=[]);
- push @$aref,$class
- if !{ map(($_=>1),@$aref) }->{$class}; # Prevent duplicated entries.
+ if ($who) {
+ my $aref=($W->{"packages_used"}{$who}||=[]);
+ push @$aref,$class
+ if !{ map(($_=>1),@$aref) }->{$class}; # Prevent duplicated entries.
+ }
CORE::require $file;
1; # Otherwise 'require' would already file above.
}
#our $W;
# $W->{"title"}
# $W->{"head"}
- # $W->{"head_css"}
# $W->{"force_charset"}
# $W->{"heading_done"}
# $W->{"footer_passed"}
do { $W->{$_}=1 if !defined $W->{$_}; } for ("footer_ids");
do { $W->{$_}=1 if !defined $W->{$_}; } for ("indexme");
do { $W->{$_}="" if !defined $W->{$_}; } for ("head");
- do { $W->{$_}="" if !defined $W->{$_}; } for ("head_css");
+ do { $W->{$_}="" if !defined $W->{$_}; } for ("body_attr");
+ do { $W->{$_}="en-US" if !defined $W->{$_}; } for ("language");
my $footer_any=0;
for (qw(footer_mailme footer_ids)) {
$W->{"r"}=Apache->request();
$W->{"QUERY_STRING"}=$W->{"r"}->args() || "";
- if ($W->{"QUERY_STRING"}=~/[&]amp;have_ent/)
- { $W->{"have_ent"}=0; }
- elsif ($W->{"QUERY_STRING"}=~ /[&]have_ent/)
- { $W->{"have_ent"}=1; }
- else
- { delete $W->{"have_ent"}; }
- if ($W->{"detect_ent"} && !defined $W->{"have_ent"} && $W->{"r"}->method() eq "GET") {
- $W->{"head"}.='<meta http-equiv="Refresh" content="0; URL='
- .CGI::escapeHTML("http://".&{$W->{"web_hostname_sub"}}()."/".($W->{"r"}->uri()=~m#^/*(.*)$#)[0]
- ."?".($W->{"QUERY_STRING"} || "detect_ent_glue=1").'&have_ent=detect')
- .'" />'."\n";
+ if ($W->{"detect_ent"}) {
+ if ($W->{"QUERY_STRING"}=~/[&]amp;have_ent/)
+ { $W->{"have_ent"}=0; }
+ elsif ($W->{"QUERY_STRING"}=~ /[&]have_ent/)
+ { $W->{"have_ent"}=1; }
+ else
+ { delete $W->{"have_ent"}; }
+ if (!defined $W->{"have_ent"} && $W->{"r"}->method() eq "GET") {
+ $W->{"head"}.='<meta http-equiv="Refresh" content="0; URL='
+ .CGI::escapeHTML("http://".&{$W->{"web_hostname_sub"}}()."/".($W->{"r"}->uri()=~m#^/*(.*)$#)[0]
+ ."?".($W->{"QUERY_STRING"} || "detect_ent_glue=1").'&have_ent=detect')
+ .'" />'."\n";
+ }
}
$W->{"QUERY_STRING"}=~s/([&])amp;/$1/g;
$W->{"r"}->args($W->{"QUERY_STRING"});
+ # Workaround: &CGI::Vars behaves weird if strings passed both as POST data and in: $QUERY_STRING
+ do { $W->{"r"}->args(""); delete $ENV{"QUERY_STRING"}; } if $W->{"r"}->method() eq "POST";
# Do not: $W->{"r"}->args()
# as it parses only QUERY_STRING (not POST data).
$W->{"args"}={ CGI->new($W->{"r"})->Vars() };
- for (keys(%{$W->{"args"}})) {
- my @vals=split /\x00/,$W->{"args"}{$_};
+ for my $name (keys(%{$W->{"args"}})) {
+ my @vals=split /\x00/,$W->{"args"}{$name};
next if @vals<=1;
- $W->{"args"}{$_}=[@vals];
+ $W->{"args"}{$name}=[@vals];
}
do { $W->{$_}=$W->{"r"}->headers_in()->{"Accept"} if !defined $W->{$_}; } for ("accept");
my($msg)=@_;
$msg="UNKNOWN" if !$msg;
+ cluck "FATAL: $msg";
$W->{"indexme"}=0; # For the case no heading was sent yet.
+ $W->{"heading_done"}=0; # for the case of already sent {"header_only"}==1
+ $W->{"header_only"}=0; # assurance for &heading
My::Web->heading();
Wprint "\n".vskip("3ex")."<hr /><h1 class=\"error\">FATAL ERROR: $msg!</h1>\n"
."<p>You can report this problem's details to"
{
my($url,%args)=@_;
- return if !url_is_local $url;
+ return $url if !url_is_local $url;
$url=top_dir($url,%args) if $url=~m#^/# || $args{"abs"};
my $uri=URI->new($url);
- for my $key (keys(%{$W->{"args_persistent"}})) {
- my $val=$W->{"args"}{$key};
- next if !defined $val;
- $uri->query_param_append($key=>$val);
- }
+ # 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;
$contents=~s#<a\b[^>]*>##gi;
$contents=~s#</a>##gi;
- $url=url_out($url);
+ $url=url_out($url,%args);
my $r='<a href="';
my $urlent=CGI::escapeHTML($url);
return [ map(($args{$_}),@fields) ];
}
+# Input: $self is required!
+# Input: Put the fallback variant as the first one.
+# Returns: always only scalar!
+sub Negotiate_choose($$)
+{
+my($self,$variants)=@_;
+
+ my $best=HTTP::Negotiate::choose($variants,
+ # Do not: $W->{"r"}
+ # to prevent: Can't locate object method "scan" via package "Apache::RequestRec" at HTTP/Negotiate.pm line 84.
+ # Do not: $W->{"r"}->headers_in()
+ # to prevent: Can't locate object method "scan" via package "APR::Table" at HTTP/Negotiate.pm line 84.
+ # Do not: HTTP::Headers->new($W->{"r"}->headers_in());
+ # to prevent empty result or even: Odd number of elements in anonymous hash
+ HTTP::Headers->new(%{$W->{"r"}->headers_in()}));
+ $best||=$variants->[0]{"id"}; # &HTTP::Negotiate::choose failed?
+ return $best;
+}
+
my @img_variants=(
- { "id"=>"png","qs"=>1.0,"content-type"=>"image/png" },
- { "id"=>"gif","qs"=>0.9,"content-type"=>"image/gif" },
+ { "id"=>"png","qs"=>0.9,"content-type"=>"image/png" },
+ { "id"=>"gif","qs"=>0.7,"content-type"=>"image/gif" },
);
my $img_variants_re='[.](?:'.join('|',"jpeg",map(($_->{"id"}),@img_variants)).')$';
"size"=>(stat $file)[7],
);
}
- # Do not: ,$W->{"r"});
- # but should we provide somehow either 'HTTP::Headers' or 'HTTP::Request' ?
- my $ext=HTTP::Negotiate::choose(\@nego_variants);
- $ext||=$img_variants[0]->{"id"}; # &HTTP::Negotiate::choose failed?
+ my $ext=__PACKAGE__->Negotiate_choose(\@nego_variants);
return $file_base_uri.".".$ext if !wantarray();
return ($file_base_uri.".".$ext,$file_base_disk.".".$ext);
{
my($class)=@_;
- return if $W->{"heading_passed"}++;
-
# $ENV{"CLIENT_CHARSET"} ignored (mod_czech support dropped!)
my $client_charset=$W->{"force_charset"} || "us-ascii";
header("Content-Style-Type"=>"text/css");
header("Content-Script-Type"=>"text/javascript");
+ do { header("Content-Language"=>$_) if $_; } for $W->{"language"};
$class->no_cache() if $W->{"no_cache"};
while (my($key,$val)=each(%{$W->{"headers"}})) {
$W->{"r"}->header_out($key,$val);
}
- if (!$W->{"header_only"}) {
- $W->{"r"}->send_http_header("text/html; charset=$client_charset"); # "Content-type"; do not use header()
- }
-
- return if $W->{"heading_done"}++;
exit if $W->{"r"}->header_only();
return if $W->{"header_only"};
+ # We still can append headers before we put out some text.
+ # FIXME: It is not clean to still append them without overwriting.
+ return if $W->{"heading_done"}++;
+ my $lang=($W->{"language"}||"en-US");
+ # Workaround bug
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=120556
+ # of at least
+ # Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8b) Gecko/20050217
+ my $mime=$class->Negotiate_choose([
+ # Put the fallback variant as the first one.
+ negotiate_variant(
+ "id"=>"text/html",
+ "content-type"=>"text/html",
+ "qs"=>0.5,
+ "charset"=>$client_charset,
+ "lang"=>$lang,
+ ),
+ negotiate_variant(
+ "id"=>"application/xhtml+xml",
+ "content-type"=>"application/xhtml+xml",
+ "qs"=>0.9,
+ "charset"=>$client_charset,
+ "lang"=>$lang,
+ ),
+ # application/xml ?
+ # text/xml ?
+ ]);
+ $W->{"r"}->send_http_header("$mime; charset=$client_charset"); # "Content-type"; do not use header()
if (1) { # || !$msie_major || $msie_major>=4) # TODO:dyn
Wprint '<?xml version="1.0" encoding="'.$client_charset.'"?>'."\n";
}
Wprint '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\n";
- Wprint '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">'."\n";
+ Wprint '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$lang.'">'."\n";
my $title=$W->{"title_prefix"}.join("",map({ ': '.$_; } ($W->{"title"} || ())));
$title=~s#<[^>]*>##g;
Wprint "<head>";
Wprint "<title>$title</title>\n";
-
if ($W->{"have_css"}) {
- Wprint <<'HERE';
-<style type="text/css"><!--
-.cvs-id { font-family: monospace; }
-.error { color: red; background-color: transparent; }
-.quote { font-family: monospace; }
-.nowrap { white-space: nowrap; }
-.centered { text-align: center; }
-.tab-bold { font-weight: bold; }
-.tab-head { font-weight: bold; }
-/*
-.tab-head { font-weight: bold; color: yellow; background-color: transparent; }
-body {
- background-color: black;
- color: white;
- }
-:link { color: aqua; background-color: transparent; }
-:visited { color: teal; background-color: transparent; }
-h1,h2 { color: yellow; background-color: transparent; }
-*/
-td { padding: 2px; }
-caption { caption-side: bottom; }
-.footer img { vertical-align: middle; }
+ # Everything can get overriden later.
+ Wprint <<"HERE";
+<link rel="stylesheet" type="text/css" href="@{[ url_out("/My/Web.css") ]}" />
HERE
- Wprint $W->{"head_css"}."\n";
- Wprint "--></style>\n";
}
-
Wprint '<meta name="robots" content="'.($W->{"indexme"} ? "" : "no" ).'index,follow" />'."\n";
Wprint $W->{"head"};
for my $type (qw(prev next index contents start up)) {
Wprint "</head><body";
# Wprint ' bgcolor="black" text="white" link="aqua" vlink="teal"'
# if $W->{"browser"}->netscape() && (!$W->{"browser"}->major() || $W->{"browser"}->major()<=4);
- do { &{$_}($W) if $_; } for $W->{"body_attr_sub"};
+ Wprint $W->{"body_attr"};
Wprint ">\n";
do { &{$_}() if $_; } for ($W->{"heading"});