]> bicyclesonthemoon.info Git - ott/backup/mscha/commitdiff
continue rework: frame - OK, viewer - ongoing main
authorb <rowerynaksiezycu@gmail.com>
Tue, 26 Mar 2024 19:27:38 +0000 (19:27 +0000)
committerb <rowerynaksiezycu@gmail.com>
Tue, 26 Mar 2024 19:27:38 +0000 (19:27 +0000)
.gitmodules
botm-common [new submodule]
frame.1.pl
frameaftertime.1.pl
makefile
makefile.1.mak
mscha_lib.1.pm
settings-debug.txt
settings.txt
viewer.1.pl
www-data/botmlogo2.png [new file with mode: 0644]

index b6a056721452fa294b51fefd488324554cdc825d..12d6f3822e319e1863c0fb789041a80b79ea6dc0 100644 (file)
@@ -4,3 +4,6 @@
 [submodule "exec"]
        path = exec
        url = ../../../botm/exec
+[submodule "botm-common"]
+       path = botm-common
+       url = ../../../botm/common-perl
diff --git a/botm-common b/botm-common
new file mode 160000 (submodule)
index 0000000..111fb5f
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 111fb5f38624401ac7f332dd8bf7fa65e7bf5b23
index a01891cbb6690bd955f6a42d97743a1c86bd473b..de6d63182675eddee3cc332813019a35c485cf18 100644 (file)
@@ -1,73 +1,84 @@
-#!/usr/bin/perl
-#
+###RUN_PERL: #!/usr/bin/perl
+
 # /mscha/frame
-# 04.03.2020
 # mscha time frame
 #
-#    Copyright (C) 2020  Balthasar Szczepański
+# Copyright (C) 2020, 2024  Balthasar Szczepański
 #
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
 #
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
 #
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 use strict;
+use utf8;
+# use Encode::Locale ('decode_argv');
+use Encode ('encode', 'decode');
+
+###PERL_LIB: use lib /botm/lib/mscha
+use botm_common (
+       'HTTP_STATUS',
+       'fail_method', 'fail_content_type',
+       'read_header_env',
+       'url_query_decode',
+       'merge_settings'
+);
+use mscha_lib (
+       'redirect',
+       'get_time_frame'
+);
 
-#use warnings;
-use lib '/eizm/lib/ottbackup/mscha/';
-use mscha_lib qw(failpage gethttpheader getcgi gettimeframe redirect);
+binmode STDIN,  ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+binmode STDERR, ':encoding(UTF-8)';
+# decode_argv();
 
 my $time = time();
 srand ($time+$$);
 
 my %http;
 my %cgi;
-my %cgipost;
-my %frameinfo;
+my %cgi_post;
+my %frame_info;
 
 my $method;
 my $frame;
 my $mode;
-# my $embed;
-my $embedUrl;
+my $embed_URL;
 
 my $header;
 my $title;
 my $message;
 
 if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
-       $method=$1;
+       $method = $1;
 }
 else{
-       exit failpage("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The interface does not support the $ENV{'REQUEST_METHOD'} method.",$method);
+       exit fail_method($ENV{'REQUEST_METHOD'}, ['GET', 'POST', 'HEAD']);
 }
 
-%http = gethttpheader (\%ENV);
-%cgi = getcgi($ENV{'QUERY_STRING'});
+%http = read_header_env(\%ENV);
+%cgi = url_query_decode($ENV{'QUERY_STRING'});
 
 if ($method eq 'POST') {
        if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
-               my %cgipost=getcgi( <STDIN> );
-               foreach my $ind (keys %cgipost) {
-                       $cgi{$ind}=$cgipost{$ind};
-               }
+               my %cgi_post = url_query_decode( <STDIN> );
+               %cgi = merge_settings(\%cgi, \%cgi_post);
        }
        # multipart not supported
        else{
-               exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
+               exit fail_content_type($method, $http{'content-type'});
        }
 }
 
-# $embed=lc($cgi{'embed'});
-
 if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = $1;
        $mode = lc($3);
@@ -75,37 +86,40 @@ if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = '1';
        $mode = '';
 }
-if ($cgi{'period'} ne '') {
-       $frame=$cgi{'period'};
+
+if ($cgi{'frameNo'} ne '') {
+       $frame = $cgi{'frameNo'};
 }
-if ($cgi{'frame'} ne '') {
-       $frame=$cgi{'frame'};
+elsif ($cgi{'frame'} ne '') {
+       $frame = $cgi{'frame'};
 }
-if ($cgi{'frameNo'} ne '') {
-       $frame=$cgi{'frameNo'};
+elsif ($cgi{'period'} ne '') {
+       $frame = $cgi{'period'};
 }
+
 if ($cgi{'mode'} ne '') {
-       $mode=lc($cgi{'mode'});
+       $mode = lc($cgi{'mode'});
 }
 if ($mode !~ /^(orig|diff)$/) {
        $mode = '';
 }
 
-%frameinfo = gettimeframe($frame,$time);
+%frame_info = get_time_frame($frame, $time);
 
-if (($mode eq 'diff') && ($frameinfo{'diffUrl'} eq '')) {
+if (($mode eq 'diff') && ($frame_info{'diffUrl'} eq '')) {
        $mode = '';
 }
 
 if ($mode eq 'orig') {
-       $embedUrl = $frameinfo{'downloadedUrl'};
-} elsif ($mode eq 'diff') {
-       $embedUrl = $frameinfo{'diffUrl'};
-} else {
-       $embedUrl = ($frameinfo{'xkcdUrl'} ne '')?$frameinfo{'xkcdUrl'}:$frameinfo{'downloadedUrl'};
+       $embed_URL = $frame_info{'downloadedUrl'};
+}
+elsif ($mode eq 'diff') {
+       $embed_URL = $frame_info{'diffUrl'};
+}
+else {
+       $embed_URL = ($frame_info{'xkcdUrl'} ne '') ?
+               $frame_info{'xkcdUrl'} :
+               $frame_info{'downloadedUrl'};
 }
-# if ($embedUrl !~ /^http/) {
-       # $embedUrl = 'http://1190.bicyclesonthemoon.info'.$embedUrl;
-# }
 
-redirect($embedUrl, !!%cgi, $method);
+redirect($method, $embed_URL, HTTP_STATUS->{'see_other'});
index b9054de8f82551a2c400f86ac8ec54b6cabd2f32..2a5aa5a724e8160f57b3d3b9e7cedd82593d2e06 100644 (file)
@@ -1,70 +1,80 @@
-#!/usr/bin/perl
+###RUN_PERL: #!/usr/bin/perl
 #
 # /mscha/frameaftertime
-# 04.03.2020
 # mscha TaT frame
 #
-#    Copyright (C) 2020  Balthasar Szczepański
+# Copyright (C) 2020, 2024  Balthasar Szczepański
 #
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
 #
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
 #
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 use strict;
-
-#use warnings;
-use lib '/eizm/lib/ottbackup/mscha/';
-use mscha_lib qw(failpage gethttpheader getcgi gettatframe redirect);
+use utf8;
+# use Encode::Locale ('decode_argv');
+use Encode ('encode', 'decode');
+
+###PERL_LIB: use lib /botm/lib/mscha
+use botm_common (
+       'HTTP_STATUS',
+       'fail_method', 'fail_content_type',
+       'read_header_env',
+       'url_query_decode',
+       'merge_settings'
+);
+use mscha_lib (
+       'redirect',
+       'get_tat_frame'
+);
+
+binmode STDIN,  ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+binmode STDERR, ':encoding(UTF-8)';
+# decode_argv();
 
 my $time = time();
 srand ($time+$$);
 
 my %http;
 my %cgi;
-my %cgipost;
-my %frameinfo;
+my %cgi_post;
+my %frame_info;
 
 my $method;
 my $frame;
 my $mode;
-# my $embed;
-my $embedUrl;
-# my $tatName;
+my $embed_URL;
 
 if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
-       $method=$1;
+       $method = $1;
 }
 else{
-       exit failpage("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The interface does not support the $ENV{'REQUEST_METHOD'} method.",$method);
+       exit fail_method($ENV{'REQUEST_METHOD'}, ['GET', 'POST', 'HEAD']);
 }
 
-%http = gethttpheader (\%ENV);
-%cgi = getcgi($ENV{'QUERY_STRING'});
+%http = read_header_env(\%ENV);
+%cgi = url_query_decode($ENV{'QUERY_STRING'});
 
 if ($method eq 'POST') {
        if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
-               my %cgipost=getcgi( <STDIN> );
-               foreach my $ind (keys %cgipost) {
-                       $cgi{$ind}=$cgipost{$ind};
-               }
+               my %cgi_post = url_query_decode( <STDIN> );
+               %cgi = merge_settings(\%cgi, \%cgi_post);
        }
        # multipart not supported
        else{
-               exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
+               exit fail_content_type($method, $http{'content-type'});
        }
 }
 
-# $embed=lc($cgi{'embed'});
-
 if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = $1;
        $mode = lc($3);
@@ -72,42 +82,39 @@ if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = '1';
        $mode = '';
 }
-if ($cgi{'frame'} ne '') {
-       $frame=$cgi{'frame'};
-}
+
 if ($cgi{'frameNo'} ne '') {
-       $frame=$cgi{'frameNo'};
+       $frame = $cgi{'frameNo'};
+}
+elsif ($cgi{'frame'} ne '') {
+       $frame = $cgi{'frame'};
 }
+
 if ($cgi{'mode'} ne '') {
-       $mode=lc($cgi{'mode'});
+       $mode = lc($cgi{'mode'});
 }
 if ($mode !~ /^(orig|diff)$/) {
        $mode = '';
 }
 
-%frameinfo = gettatframe($frame,$time);
+%frame_info = get_tat_frame($frame, $time);
 
-if (($mode eq 'diff') && ($frameinfo{'diffUrl'} eq '')) {
+if (($mode eq 'diff') && ($frame_info{'diffUrl'} eq '')) {
        $mode = '';
 }
 
-# if ($frameinfo{'match'} !~ /^(frameNo|downloadedUrl|tatUrl)$/) {
-       # $frame = $frameinfo{'frameNo'};
-# }
-
-if (($mode eq '') && ($frameinfo{'match'} eq 'downloadedUrl')) {
+if (($mode eq '') && ($frame_info{'match'} eq 'downloadedUrl')) {
        $mode = 'orig';
 }
 
 if ($mode eq 'orig') {
-       $embedUrl = $frameinfo{'downloadedUrl'};
-} elsif ($mode eq 'diff') {
-       $embedUrl = $frameinfo{'diffUrl'};
-} else {
-       $embedUrl = $frameinfo{'tatUrl'};
+       $embed_URL = $frame_info{'downloadedUrl'};
+}
+elsif ($mode eq 'diff') {
+       $embed_URL = $frame_info{'diffUrl'};
+}
+else {
+       $embed_URL = $frame_info{'tatUrl'};
 }
-# if ($embedUrl !~ /^http/) {
-       # $embedUrl = 'http://1190.bicyclesonthemoon.info'.$embedUrl;
-# }
 
-redirect($embedUrl, !!%cgi, $method);
+redirect($method, $embed_URL, HTTP_STATUS->{'see_other'});
index b9e629c848abd42eab5931562fe9b92beca7c8df..7abf1d78befa8d24b110973390de3b177d2072ae 100644 (file)
--- a/makefile
+++ b/makefile
@@ -89,6 +89,7 @@ $(PERL_WRAP_EXEC)
 
 
 LIB=\
+botm-common/botm_common.pm\
 mscha_lib.pm
 
 DIR=\
index 7d13bae3e3c97643f5b5b72ac591e491370c3d11..f8064c556f1943b10a82087f35d425eef24940ca 100644 (file)
@@ -89,6 +89,7 @@ $(PERL_WRAP_EXEC)
 
 
 LIB=\
+botm-common/botm_common.pm\
 mscha_lib.pm
 
 DIR=\
index 29348903aee52ae3fae6bdfeaeb8fae798e0290e..6066ca6f681f8a623fa97f087a551750fea896db 100644 (file)
@@ -1,7 +1,5 @@
 # Library of functions
 #
-# Library of functions
-#
 # Copyright (C) 2020, 2024  Balthasar Szczepański
 #
 # This program is free software: you can redistribute it and/or modify
@@ -31,429 +29,37 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
 @ISA         = qw(Exporter);
 @EXPORT      = ();
 @EXPORT_OK   = (
-       'failpage',
-       'entityencode',
-       'gethttpheader',
-       'getcgi',
-       'urldecode',
-       'gettimeframe',
-       'urlencode'
-       'printframeselection',
-       'gettatframe',
-       'redirect'
+       'get_time_frame', 'get_tat-frame',
+       'print_frame_selection'
 );
 
 ###PERL_LIB: use lib /botm/lib/ottbackub/mscha
+use botm_common (
+       'http_status', 'http_header_line', 'http_header_location',
+       'html_entity_encode_dec',
+       'open_encoded'
+)
 
-use constant entitycode => {
-       'amp' => '&',
-       'gt' => '>',
-       'lt' => '<',
-       'quot' => '"',
-       'acute' => '´',
-       'cedil' => '¸',
-       'circ' => 'ˆ',
-       'macr' => '¯',
-       'middot' => '·',
-       'tilde' => '˜',
-       'uml' => '¨',
-       'Aacute' => 'Á',
-       'aacute' => 'á',
-       'Acirc' => 'Â',
-       'acirc' => 'â',
-       'AElig' => 'Æ',
-       'aelig' => 'æ',
-       'Agrave' => 'À',
-       'agrave' => 'à',
-       'Aring' => 'Å',
-       'aring' => 'å',
-       'Atilde' => 'Ã',
-       'atilde' => 'ã',
-       'Auml' => 'Ä',
-       'auml' => 'ä',
-       'Ccedil' => 'Ç',
-       'ccedil' => 'ç',
-       'Eacute' => 'É',
-       'eacute' => 'é',
-       'Ecirc' => 'Ê',
-       'ecirc' => 'ê',
-       'Egrave' => 'È',
-       'egrave' => 'è',
-       'ETH' => 'Ð',
-       'eth' => 'ð',
-       'Euml' => 'Ë',
-       'euml' => 'ë',
-       'Iacute' => 'Í',
-       'iacute' => 'í',
-       'Icirc' => 'Î',
-       'icirc' => 'î',
-       'Igrave' => 'Ì',
-       'igrave' => 'ì',
-       'Iuml' => 'Ï',
-       'iuml' => 'ï',
-       'Ntilde' => 'Ñ',
-       'ntilde' => 'ñ',
-       'Oacute' => 'Ó',
-       'oacute' => 'ó',
-       'Ocirc' => 'Ô',
-       'ocirc' => 'ô',
-       'OElig' => 'Œ',
-       'oelig' => 'œ',
-       'Ograve' => 'Ò',
-       'ograve' => 'ò',
-       'Oslash' => 'Ø',
-       'oslash' => 'ø',
-       'Otilde' => 'Õ',
-       'otilde' => 'õ',
-       'Ouml' => 'Ö',
-       'ouml' => 'ö',
-       'Scaron' => 'Š',
-       'scaron' => 'š',
-       'szlig' => 'ß',
-       'THORN' => 'Þ',
-       'thorn' => 'þ',
-       'Uacute' => 'Ú',
-       'uacute' => 'ú',
-       'Ucirc' => 'Û',
-       'ucirc' => 'û',
-       'Ugrave' => 'Ù',
-       'ugrave' => 'ù',
-       'Uuml' => 'Ü',
-       'uuml' => 'ü',
-       'Yacute' => 'Ý',
-       'yacute' => 'ý',
-       'yuml' => 'ÿ',
-       'Yuml' => 'Ÿ',
-       'cent' => '¢',
-       'curren' => '¤',
-       'euro' => '€',
-       'pound' => '£',
-       'yen' => '¥',
-       'brvbar' => '¦',
-       'bull' => '•',
-       'copy' => '©',
-       'dagger' => '†',
-       'Dagger' => '‡',
-       'frasl' => '⁄',
-       'hellip' => '…',
-       'iexcl' => '¡',
-       'image' => 'ℑ',
-       'iquest' => '¿',
-       'lrm' => '‎',
-       'mdash' => '—',
-       'ndash' => '–',
-       'not' => '¬',
-       'oline' => '‾',
-       'ordf' => 'ª',
-       'ordm' => 'º',
-       'para' => '¶',
-       'permil' => '‰',
-       'prime' => '′',
-       'Prime' => '″',
-       'real' => 'ℜ',
-       'reg' => '®',
-       'rlm' => '‏',
-       'sect' => '§',
-       'shy' => '­',
-       'sup1' => '¹',
-       'trade' => '™',
-       'weierp' => '℘',
-       'bdquo' => '„',
-       'laquo' => '«',
-       'ldquo' => '“',
-       'lsaquo' => '‹',
-       'lsquo' => '‘',
-       'raquo' => '»',
-       'rdquo' => '”',
-       'rsaquo' => '›',
-       'rsquo' => '’',
-       'sbquo' => '‚',
-       'emsp' => ' ',
-       'ensp' => ' ',
-       'nbsp' => ' ',
-       'thinsp' => ' ',
-       'zwj' => '‍',
-       'zwnj' => '‌',
-       'deg' => '°',
-       'divide' => '÷',
-       'frac12' => '½',
-       'frac14' => '¼',
-       'frac34' => '¾',
-       'ge' => '≥',
-       'le' => '≤',
-       'minus' => '−',
-       'sup2' => '²',
-       'sup3' => '³',
-       'times' => '×',
-       'alefsym' => 'ℵ',
-       'and' => '∧',
-       'ang' => '∠',
-       'asymp' => '≈',
-       'cap' => '∩',
-       'cong' => '≅',
-       'cup' => '∪',
-       'empty' => '∅',
-       'equiv' => '≡',
-       'exist' => '∃',
-       'fnof' => 'ƒ',
-       'forall' => '∀',
-       'infin' => '∞',
-       'int' => '∫',
-       'isin' => '∈',
-       'lang' => '⟨',
-       'lceil' => '⌈',
-       'lfloor' => '⌊',
-       'lowast' => '∗',
-       'micro' => 'µ',
-       'nabla' => '∇',
-       'ne' => '≠',
-       'ni' => '∋',
-       'notin' => '∉',
-       'nsub' => '⊄',
-       'oplus' => '⊕',
-       'or' => '∨',
-       'otimes' => '⊗',
-       'part' => '∂',
-       'perp' => '⊥',
-       'plusmn' => '±',
-       'prod' => '∏',
-       'prop' => '∝',
-       'radic' => '√',
-       'rang' => '⟩',
-       'rceil' => '⌉',
-       'rfloor' => '⌋',
-       'sdot' => '⋅',
-       'sim' => '∼',
-       'sub' => '⊂',
-       'sube' => '⊆',
-       'sum' => '∑',
-       'sup' => '⊃',
-       'supe' => '⊇',
-       'there4' => '∴',
-       'Alpha' => 'Α',
-       'alpha' => 'α',
-       'Beta' => 'Β',
-       'beta' => 'β',
-       'Chi' => 'Χ',
-       'chi' => 'χ',
-       'Delta' => 'Δ',
-       'delta' => 'δ',
-       'Epsilon' => 'Ε',
-       'epsilon' => 'ε',
-       'Eta' => 'Η',
-       'eta' => 'η',
-       'Gamma' => 'Γ',
-       'gamma' => 'γ',
-       'Iota' => 'Ι',
-       'iota' => 'ι',
-       'Kappa' => 'Κ',
-       'kappa' => 'κ',
-       'Lambda' => 'Λ',
-       'lambda' => 'λ',
-       'Mu' => 'Μ',
-       'mu' => 'μ',
-       'Nu' => 'Ν',
-       'nu' => 'ν',
-       'Omega' => 'Ω',
-       'omega' => 'ω',
-       'Omicron' => 'Ο',
-       'omicron' => 'ο',
-       'Phi' => 'Φ',
-       'phi' => 'φ',
-       'Pi' => 'Π',
-       'pi' => 'π',
-       'piv' => 'ϖ',
-       'Psi' => 'Ψ',
-       'psi' => 'ψ',
-       'Rho' => 'Ρ',
-       'rho' => 'ρ',
-       'Sigma' => 'Σ',
-       'sigma' => 'σ',
-       'sigmaf' => 'ς',
-       'Tau' => 'Τ',
-       'tau' => 'τ',
-       'Theta' => 'Θ',
-       'theta' => 'θ',
-       'thetasym' => 'ϑ',
-       'upsih' => 'ϒ',
-       'Upsilon' => 'Υ',
-       'upsilon' => 'υ',
-       'Xi' => 'Ξ',
-       'xi' => 'ξ',
-       'Zeta' => 'Ζ',
-       'zeta' => 'ζ',
-       'crarr' => '↵',
-       'darr' => '↓',
-       'dArr' => '⇓',
-       'harr' => '↔',
-       'hArr' => '⇔',
-       'larr' => '←',
-       'lArr' => '⇐',
-       'rarr' => '→',
-       'rArr' => '⇒',
-       'uarr' => '↑',
-       'uArr' => '⇑',
-       'clubs' => '♣',
-       'diams' => '♦',
-       'hearts' => '♥',
-       'spades' => '♠',
-       'loz' => '◊',
-};
-
-use constant time_data => '/eizm/www/time/mscha/time-data';
-use constant time_data_period => '/eizm/www/time/mscha/time-data-period';
-use constant tat_data => '/eizm/www/time/mscha/tat-data';
-
-
-# Function to show an error page
-# arguments: 1 - header fields, 2 - page title, 3 - error message, 4 method
-sub failpage {
-       (my $header, my $title, my $message, my $method)=@_;
-       if($header ne ''){
-               print $header;
-       }
-       if($method eq 'HEAD') {
-               print "\n";
-               return;
-       }
-       print "Content-type: text/html\n\n";
-       print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
-       print '<html lang="en"><head>'."\n";
-       if($title ne ''){
-               print '<title>'.entityencode($title).'</title>'."\n";
-       }
-       print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
-       print '</head><body>'."\n";
-       if($title ne ''){
-               print '<h1>'.entityencode($title).'</h1>'."\n";
-       }
-       if($message ne ''){
-               print '<p>'.entityencode($message).'</p>'."\n";
-       }
-       print '</body></html>'."\n";
-}
-
-# HTTP redirection
-sub redirect {
-       (my $url, my $temporary, my $method)=@_;
-       $url =~ s/\n//g;
-       my $status = $temporary?'302 Found':'301 Moved Permanently';
-       my $en_url = entityencode($url);
-       
-       print 'Status: '.$status."\n";
-       print 'Location: '.$url."\n";
-       if($method eq 'HEAD') {
-               print "\n";
-               return;
-       }
-       print "Content-type: text/html\n\n";
-       print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
-       print '<html lang="en"><head>'."\n";
-       print '<title>'.$status.'</title>'."\n";
-       print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
-       print '</head><body>'."\n";
-       print '<h1>'.$status.'</h1>'."\n";
-       print '<p><a href="'.$en_url.'">'.$en_url.'</a></p>'."\n";
-       print '</body></html>'."\n";
-}
-
-# function to encode entities, decimal, 
-sub entityencode {
-       (my $t, my $all) = @_;
-       if ($all) {
-               $t =~ s/(.)/sprintf('\&#%02hu;',ord($1))/eg;
-       }
-       else {
-               $t =~ s/([\"=><\&])/sprintf('&#%02hu;',ord($1))/eg;
-       }
-       return $t;
-}
-
-# function to get values of http header fields. Returns a hash. names of header
-# fields are lowercase
-sub gethttpheader {
-       (my $env) = @_;
-       
-       my %http;
-       
-       foreach my $ind (keys %$env) {
-               my $name = '';
-               my $value= '';
-               
-               if ($ind =~ /^HTTP_([A-Z0-9_]+)$/) {
-                       $name=$1;
-               }
-               elsif ($ind =~ /^(CONTENT_[A-Z0-9_]+)$/) {
-                       $name=$1;
-               }
-               else{
-                       next;
-               }
-               $name =~ s/_/-/g;
-               $name = lc($name);
-               if ($$env{$ind} =~ /^([\x20-\x7e]*)$/) {
-                       $value=$1;
-               }
-               else {
-                       next;
-               }
-               $http{$name}=$value;
-       }
-       return %http;
-}
-
-# The function to get CGI parameters from string.
-# Format is: name=url_encoded_value&name=url_encoded_value& ... &name=url_encoded_value
-sub getcgi {
-       my $arg;
-       my $val;
-       my %cgi;
-       my $i = $_[0];
-       $i =~ s/[\r\n]//g;
-       my @s = split('&',$i);
-       foreach my $l ( @s) {
-               ($arg,$val)=split('=',$l);
-               $cgi{$arg}=urldecode($val);
-       }
-       return %cgi;
-}
-
-# Function for decoding URL-encoded text
-sub urldecode {
-       my $t = $_[0];
-       $t =~ s/\+/ /g;
-       $t =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/eg;
-       return $t;
-}
-
-# Function for URL-encoding
-sub urlencode {
-       (my $t, my $all) = @_;
-       if ($all) {
-               $t =~ s/(.)/sprintf('%%%02hX',ord($1))/eg;
-       }
-       else {
-               $t =~ s/([^0-9A-Za-z.~\-_])/sprintf('%%%02hX',ord($1))/eg;
-       }
-       return $t;
-}
+###PERL_WWW_TAT_DATA_PATH:         WWW_TAT_DATA_PATH         = /botm/www/1190/mscha/tat-data
+###PERL_WWW_TIME_DATA_PATH:        WWW_TIME_DATA_PATH        = /botm/www/1190/mscha/time-data
+###PERL_WWW_TIME_DATA_PERIOD_PATH: WWW_TIME_DATA_PERIOD_PATH = /botm/www/1190/mscha/time-data-period
 
 # Function to find a frame and get its options
-sub gettimeframe {
+sub get_time_frame {
        (my $id, my $time) = @_;
        
-       my %frameinfo;
+       my %frame_info;
        my %fallback;
-       my $datafile;
+       my $fh;
        
-       my $mschaID;
-       my $aubronwoodID;
+       my $mscha_ID;
+       my $aubronwood_ID;
        my $geekwagonID;
        my $hash;
        my $timetext;
        my $filename;
        
-       my $firstline=1;
+       my $firstline = 1;
        my $found = '';
        my @tab;
        
@@ -463,48 +69,51 @@ sub gettimeframe {
                $id = lc($id);
        }
        
-       if ($id =~ /^([0-9]+[a-z]?)$/) {
-               $mschaID = $1;
+       if ($id =~ /^[0-9]+[a-z]?$/) {
+               $mscha_ID = $&;
        }
        
-       if ($id =~ /^ba([0-9]+?)$/) {
-               $aubronwoodID = $1;
+       if ($id =~ /^ba([0-9]+)$/) {
+               $aubronwood_ID = $1;
        }
        
-       if ($id =~ /^gw([0-9]+?)$/) {
+       if ($id =~ /^gw([0-9]+)$/) {
                $geekwagonID = $1;
        }
        
-       if ($id =~ /^([0-9a-f]+)$/) {
-               $hash = $1;
+       if ($id =~ /^[0-9a-f]+$/) {
+               $hash = $&;
        }
        
-       if ($id =~ /^([0-9]{8}_[0-9]{4})$/) {
-               $timetext = $1;
+       if ($id =~ /^[0-9]{8}_[0-9]{4}$/) {
+               $timetext = $&;
        }
        
        if ($id eq 'ung') {
-               my @timetab=gmtime($time);
-               $timetext=sprintf('2013%02d%02d_%02d%02d',$timetab[4]+1,$timetab[3],$timetab[2],$timetab[1]);
+               my @timetab = gmtime($time);
+               $timetext = sprintf(
+                       '2013%02d%02d_%02d%02d',
+                       $timetab[4]+1, $timetab[3], $timetab[2], $timetab[1]
+               );
        }
        
        if ($id eq 'random') {
-               $aubronwoodID = int(rand(3102))+1; #aubronwood has best numbering for this purpose 
+               $aubronwood_ID = int(rand(3102))+1; #aubronwood has best numbering for this purpose 
        }
        
-       unless (open ($datafile, '<', time_data)) {
-               return %frameinfo;
+       unless (open_encoded ($fh, '<:encoding(utf8)', WWW_TIME_DATA_PATH())) {
+               return %frame_info;
        }
        
        if ($id eq 'randomsound') {
                my $soundcount = 0;
                my @soundtab;
                
-               while (defined(my $line = <$datafile>)) {
-                       $line =~ s/(\r)?\n$//g;
+               while (defined(my $line = <$fh>)) {
+                       $line =~ s/(\r)?\n$//gs;
                        if ($firstline) {
                                $firstline = '';
-                               $frameinfo{'match'} = '';
+                               $frame_info{'match'} = '';
                                next;
                        }
                        
@@ -516,32 +125,32 @@ sub gettimeframe {
                        }
                }
                if ($soundcount > 0) {
-                       $mschaID = $soundtab[int(rand($soundcount))];
+                       $mscha_ID = $soundtab[int(rand($soundcount))];
                } else {
-                       $mschaID = '1';
+                       $mscha_ID = '1';
                }
-               seek($datafile, 0, 0);
+               seek($fh, 0, 0);
                $firstline=1;
        }
        
-       while (defined(my $line = <$datafile>)) {
+       while (defined(my $line = <$fh>)) {
                $line =~ s/(\r)?\n$//g;
                if ($firstline) {
                        $firstline = '';
-                       $frameinfo{'match'} = '';
+                       $frame_info{'match'} = '';
                        next;
                }
                
                @tab = split (/\t/, $line);
                
                if ($found) {
-                       $frameinfo{'next'} = $tab[0];
+                       $frame_info{'next'} = $tab[0];
                        last;
                }
                
                if ($timetext ne '') {
-                       if ($frameinfo{'match'} ne 'dateTime') {
-                               $frameinfo{'match'} = 'dateTime';
+                       if ($frame_info{'match'} ne 'dateTime') {
+                               $frame_info{'match'} = 'dateTime';
                        } else {
                                my $toolate = '';
                                my $LYear   = int(substr($tab[2], 0,4));
@@ -586,97 +195,97 @@ sub gettimeframe {
                                }
                                
                                if ($toolate) {
-                                       $found=1;
+                                       $found = 1;
                                        next;
                                }
                        }
                }
                
-               $frameinfo{'prev'} = $frameinfo{'frameNo'};
-               $frameinfo{'frameNo'} = $tab[0];
-               $frameinfo{'apocryphal'} = $tab[1];
-               $frameinfo{'dateTime'} = $tab[2];
-               $frameinfo{'epoch'} = $tab[3];
-               $frameinfo{'hash'} = $tab[4];
-               $frameinfo{'downloadedUrl'} = $tab[5];
-               $frameinfo{'xkcdUrl'} = $tab[6];
-               $frameinfo{'diffUrl'} = $tab[7];
-               $frameinfo{'gwFrameNo'} = $tab[8];
-               $frameinfo{'baFrameNo'} = $tab[9];
-               $frameinfo{'botmEnhance'} = $tab[10];
-               $frameinfo{'alt'} = $tab[11];
-               $frameinfo{'soundUrl'} = $tab[12];
+               $frame_info{'prev'         } = $frame_info{'frameNo'};
+               $frame_info{'frameNo'      } = $tab[0];
+               $frame_info{'apocryphal'   } = $tab[1];
+               $frame_info{'dateTime'     } = $tab[2];
+               $frame_info{'epoch'        } = $tab[3];
+               $frame_info{'hash'         } = $tab[4];
+               $frame_info{'downloadedUrl'} = $tab[5];
+               $frame_info{'xkcdUrl'      } = $tab[6];
+               $frame_info{'diffUrl'      } = $tab[7];
+               $frame_info{'gwFrameNo'    } = $tab[8];
+               $frame_info{'baFrameNo'    } = $tab[9];
+               $frame_info{'botmEnhance'  } = $tab[10];
+               $frame_info{'alt'          } = $tab[11];
+               $frame_info{'soundUrl'     } = $tab[12];
                
-               if($fallback{'match'} eq ''){
-                       %fallback = %frameinfo;
-                       $fallback{'match'}='fallback';
-               } elsif ($fallback{'next'} eq ''){
-                       $fallback{'next'} = $frameinfo{'frameNo'};
+               if ($fallback{'match'} eq '') {
+                       %fallback = %frame_info;
+                       $fallback{'match'} = 'fallback';
+               } elsif ($fallback{'next'} eq '') {
+                       $fallback{'next'} = $frame_info{'frameNo'};
                }
                
-               if ($mschaID ne '') {
-                       if ($mschaID eq lc($frameinfo{'frameNo'})) {
-                               $frameinfo{'match'}='frameNo';
-                               $found=1;
+               if ($mscha_ID ne '') {
+                       if ($mscha_ID eq lc($frame_info{'frameNo'})) {
+                               $frame_info{'match'} = 'frameNo';
+                               $found = 1;
                                next;
                        }
                }
                
-               if ($aubronwoodID ne '') {
-                       if ($aubronwoodID eq $frameinfo{'baFrameNo'}) {
+               if ($aubronwood_ID ne '') {
+                       if ($aubronwood_ID eq $frame_info{'baFrameNo'}) {
                                if($id eq 'random') {
-                                       $frameinfo{'match'}='random';
+                                       $frame_info{'match'} ='random';
                                } else {
-                                       $frameinfo{'match'}='baFrameNo';
+                                       $frame_info{'match'} ='baFrameNo';
                                }
-                               $found=1;
+                               $found = 1;
                                next;
                        }
                }
                
                if ($geekwagonID ne '') {
-                       if ($geekwagonID eq $frameinfo{'gwFrameNo'}) {
-                               $frameinfo{'match'}='gwFrameNo';
-                               $found=1;
+                       if ($geekwagonID eq $frame_info{'gwFrameNo'}) {
+                               $frame_info{'match'} = 'gwFrameNo';
+                               $found = 1;
                                next;
                        }
                }
                
                if ($hash ne '') {
-                       if ($hash eq lc($frameinfo{'hash'})) {
-                               $frameinfo{'match'}='hash';
-                               $found=1;
+                       if ($hash eq lc($frame_info{'hash'})) {
+                               $frame_info{'match'} ='hash';
+                               $found = 1;
                                next;
                        }
                }
                
-               if ($frameinfo{'downloadedUrl'} =~ /\/([^\/\.]+)\./) {
+               if ($frame_info{'downloadedUrl'} =~ /\/([^\/\.]+)\./) {
                        $filename = lc($1);
                        if ($id eq $filename) {
-                               $frameinfo{'match'}='downloadedUrl';
-                               $found=1;
+                               $frame_info{'match'} = 'downloadedUrl';
+                               $found = 1;
                                next;
                        }
                }
        }
-       close ($datafile);
+       close ($fh);
        
-       if ($frameinfo{'match'} ne '') {
-               return %frameinfo;
+       if ($frame_info{'match'} ne '') {
+               return %frame_info;
        } else {
                return %fallback;
        }
 }
 
 # Function to find a TaT frame and get its options
-sub gettatframe {
+sub get_tat_frame {
        (my $id) = @_;
        
-       my %frameinfo;
+       my %frame_info;
        my %fallback;
-       my $datafile;
+       my $fh;
        
-       my $mschaID;
+       my $mscha_ID;
        my $randomID;
        my $hash;
        my $timetext;
@@ -694,46 +303,46 @@ sub gettatframe {
                $id = lc($id);
        }
        
-       if ($id =~ /^([0-9]+([a-z]|½)?)$/) {
-               $mschaID = $1;
+       if ($id =~ /^[0-9]+([a-z]|½)?$/) {
+               $mscha_ID = $&;
        }
        
-       if ($hash =~ /^([0-9a-zA-Z\-\+]+)$/) {
-               $hash = $1;
+       if ($hash =~ /^[0-9a-zA-Z\-\+]+$/) {
+               $hash = $&;
        } else {
                $hash = '';
        }
        
-       if ($id =~ /^([0-9]{8}_[0-9]{4})$/) {
-               $timetext = $1;
+       if ($id =~ /^[0-9]{8}_[0-9]{4}$/) {
+               $timetext = $&;
        }
        
        if ($id eq 'random') {
                $randomID = int(rand(2561)); 
        }
        
-       unless (open ($datafile, '<', tat_data)) {
-               return %frameinfo;
+       unless (open_encoded ($fh, '<:encoding(utf8)', WWW_TAT_DATA_PATH())) {
+               return %frame_info;
        }
        
-       while (defined(my $line = <$datafile>)) {
+       while (defined(my $line = <$fh>)) {
                $line =~ s/(\r)?\n$//g;
                if ($firstline) {
                        $firstline = '';
-                       $frameinfo{'match'} = '';
+                       $frame_info{'match'} = '';
                        next;
                }
                
                @tab = split (/\t/, $line);
                
                if ($found) {
-                       $frameinfo{'next'} = $tab[0];
+                       $frame_info{'next'} = $tab[0];
                        last;
                }
                
                if ($timetext ne '') {
-                       if ($frameinfo{'match'} ne 'dateTime') {
-                               $frameinfo{'match'} = 'dateTime';
+                       if ($frame_info{'match'} ne 'dateTime') {
+                               $frame_info{'match'} = 'dateTime';
                        } else {
                                my $toolate = '';
                                my $LYear   = int(substr($tab[1], 0,4));
@@ -778,103 +387,106 @@ sub gettatframe {
                                }
                                
                                if ($toolate) {
-                                       $found=1;
+                                       $found = 1;
                                        next;
                                }
                        }
                }
                
-               $frameinfo{'prev'} = $frameinfo{'frameNo'};
-               $frameinfo{'frameNo'} = $tab[0];
-               $frameinfo{'dateTime'} = $tab[1];
-               $frameinfo{'epoch'} = $tab[2];
-               $frameinfo{'downloadedUrl'} = $tab[3];
-               $frameinfo{'tatUrl'} = $tab[4];
-               $frameinfo{'diffUrl'} = $tab[5];
-               $frameinfo{'origName'} = $tab[6];
-               $frameinfo{'botmName'} = $tab[7];
-               $frameinfo{'botmFrameNo'} = $tab[8];
-               $frameinfo{'botmEnhance'} = $tab[9];
-               $frameinfo{'random'} = $tab[10];
-               $frameinfo{'alt'} = $tab[11];
+               $frame_info{'prev'         } = $frame_info{'frameNo'};
+               $frame_info{'frameNo'      } = $tab[0];
+               $frame_info{'dateTime'     } = $tab[1];
+               $frame_info{'epoch'        } = $tab[2];
+               $frame_info{'downloadedUrl'} = $tab[3];
+               $frame_info{'tatUrl'       } = $tab[4];
+               $frame_info{'diffUrl'      } = $tab[5];
+               $frame_info{'origName '    } = $tab[6];
+               $frame_info{'botmName'     } = $tab[7];
+               $frame_info{'botmFrameNo'  } = $tab[8];
+               $frame_info{'botmEnhance'  } = $tab[9];
+               $frame_info{'random'       } = $tab[10];
+               $frame_info{'alt'          } = $tab[11];
                
-               if($fallback{'match'} eq ''){
-                       %fallback = %frameinfo;
-                       $fallback{'match'}='fallback';
-               } elsif ($fallback{'next'} eq ''){
-                       $fallback{'next'} = $frameinfo{'frameNo'};
+               if ($fallback{'match'} eq '') {
+                       %fallback = %frame_info;
+                       $fallback{'match'} ='fallback';
+               } elsif ($fallback{'next'} eq '') {
+                       $fallback{'next'} = $frame_info{'frameNo'};
                }
                
-               if ($mschaID ne '') {
-                       if ($mschaID eq lc($frameinfo{'frameNo'})) {
-                               $frameinfo{'match'}='frameNo';
-                               $found=1;
+               if ($mscha_ID ne '') {
+                       if ($mscha_ID eq lc($frame_info{'frameNo'})) {
+                               $frame_info{'match'} = 'frameNo';
+                               $found = 1;
                                next;
                        }
                }
                
                if ($randomID ne '') {
-                       if ($randomID eq lc($frameinfo{'random'})) {
-                               $frameinfo{'match'}='random';
-                               $found=1;
+                       if ($randomID eq lc($frame_info{'random'})) {
+                               $frame_info{'match'} = 'random';
+                               $found = 1;
                                next;
                        }
                }
                
-               if ($frameinfo{'origName'} =~ /^([^\.]*)\./) {
+               if ($frame_info{'origName'} =~ /^([^\.]*)\./) {
                        $filename = $1;
                        if ($hash eq $filename) {
-                               $frameinfo{'match'}='origName';
-                               $found=1;
+                               $frame_info{'match'} = 'origName';
+                               $found = 1;
                                next;
                        }
                }
                
-               if ($frameinfo{'downloadedUrl'} =~ /\/([^\/\.]+)\./) {
+               if ($frame_info{'downloadedUrl'} =~ /\/([^\/\.]+)\./) {
                        $filename = lc($1);
                        if ($id eq $filename) {
-                               $frameinfo{'match'}='downloadedUrl';
-                               $found=1;
+                               $frame_info{'match'} = 'downloadedUrl';
+                               $found = 1;
                                next;
                        }
                }
                
-               if ($frameinfo{'tatUrl'} =~ /\/([^\/\.]+)\./) {
+               if ($frame_info{'tatUrl'} =~ /\/([^\/\.]+)\./) {
                        $filename = lc($1);
                        if ($id eq $filename) {
-                               $frameinfo{'match'}='tatUrl';
-                               $found=1;
+                               $frame_info{'match'} = 'tatUrl';
+                               $found = 1;
                                next;
                        }
                }
        }
-       close ($datafile);
+       close ($fh);
        
-       if ($frameinfo{'match'} ne '') {
-               return %frameinfo;
+       if ($frame_info{'match'} ne '') {
+               return %frame_info;
        } else {
                return %fallback;
        }
 }
 
-sub printframeselection {
+sub print_frame_selection {
        (my $id) = @_;
        
-       my $datafile;
-       my $firstline=1;
+       my $fh;
+       my $firstline = 1;
        my @tab;
-       my $class='';
-       my $value='';
-       my $name='';
-       my $found='';
+       my $class = '';
+       my $value = '';
+       my $name = '';
+       my $_class;
+       my $_value;
+       my $_name;
+       my $found = '';
        
        $id = int($id);
        
-       unless (open ($datafile, '<', time_data_period)) {
+       unless (open_encoded ($fh, '<:encoding(uft8)', WWW_TIME_DATA_PERIOD_PATH)) {
                return;
        }
        
-       while (defined(my $line = <$datafile>)) {
+       while (defined(my $line = <$fh>)) {
                $line =~ s/(\r)?\n$//g;
                if ($firstline) {
                        $firstline = '';
@@ -883,24 +495,27 @@ sub printframeselection {
                
                @tab = split (/\t/, $line);
                if ($value ne '') {
-                       print '<option class="'.entityencode($class).'"';
+                       print '<option class="'.$_class.'"';
                        if (!$found && (int($tab[1]) > $id)) {
                                $found = 1;
                                print ' selected';
                        }
-                       print ' value="'.entityencode($value).'">'.entityencode($name).'</option>';
+                       print ' value="'.$_value.'">'.$_name.'</option>';
                }
                $class = $tab[0];
                $value = $tab[1];
                $name = $tab[2];
+               $_class = html_entity_encode_dec($class);
+               $_value = html_entity_encode_dec($value);
+               $_name = html_entity_encode_dec($name);
        }
-       close ($datafile);
+       close ($fh);
        if ($value ne '') {
-               print '<option class="'.entityencode($class);
+               print '<option class="'.$_class;
                if (!$found) {
                        print ' selected';
                }
-               print ' value="'.entityencode($value).'">'.entityencode($name).'</option>';
+               print ' value="'.$_value.'">'.$_name.'</option>';
        }
 }
 
index d812ad91d491f98700fb07a3a05436623cf5421c..fb159620e0941bae772c8b159c7442dd31085480 100644 (file)
@@ -29,3 +29,11 @@ log_size_limit: 65536
 logs_uncompressed: 2
 logs_total: 10
 oldlogs_schedule: #0 3 * * *
+
+scheme  : http
+website : 1190.bicyclesonthemoon.info
+
+tat_viewer : /aftertime/viewer
+aubronwood : http://xkcd.aubronwood.com
+geekwagon  : http://geekwagon.net/projects/xkcd1190
+
index a76ebf170677ca5090ad92c1896e2c8f99f05ca0..fd3fae3c4a4819aaad81fb2b8228fa7070b7c1a4 100644 (file)
@@ -40,11 +40,15 @@ _cgi_tat_view_2_path = @_PATH($cgi_path, viewaftertime.fcgi)
 _cgi_view_path       = @_PATH($cgi_path, viewer            )
 _cgi_view_2_path     = @_PATH($cgi_path, view.fcgi         )
 
+_www_path                  = @_PATH($www_path,                 )
+_www_tat_data_data_path    = @_PATH($www_path, tat_data        )
+_www_time_data_path        = @_PATH($www_path, time_data       )
+_www_time_data_period_path = @_PATH($www_path, time_data_period)
+
 _conf_path = @_PATH($conf_path, $name\.conf)
 
 _lib_path = @_PATH($lib_path,)
 _log_path = @_PATH($log_path,)
-_www_path = @_PATH($www_path,)
 
 
 CONF_BIN           = $_bin_path
@@ -85,4 +89,11 @@ PERL_SET_PATH = \$ENV{'PATH'} = @_PERL_STR($path);
 
 PERL_EXPORT_VERSION    = @_PERL_OUR_STR( VERSION, $_version)
 
-# PERL_PATH_SEPARATOR     = @_PERL_CONSTANT_STR( PATH_SEPARATOR, $_PATH_SEPARATOR)
\ No newline at end of file
+# PERL_PATH_SEPARATOR     = @_PERL_CONSTANT_STR( PATH_SEPARATOR, $_PATH_SEPARATOR)
+
+PERL_WWW_TAT_DATA_PATH         = @_PERL_CONSTANT_STR( WWW_TAT_DATA_PATH,         $_www_tat_data_path        )
+PERL_WWW_TIME_DATA_PATH        = @_PERL_CONSTANT_STR( WWW_TIME_DATA_PATH,        $_www_time_data_path       )
+PERL_WWW_TIME_DATA_PERIOD_PATH = @_PERL_CONSTANT_STR( WWW_TIME_DATA_PERIOD_PATH, $_www_time_data_period_path)
+
+PERL_SCHEME  = @_PERL_CONSTANT_STR( SCHEME , $scheme )
+PERL_WEBSITE = @_PERL_CONSTANT_STR( WEBSITE, $website)
index 800fdc8e4421ad77ffb71bded496e56b4b8d9584..5c09bf575774cce411a87d3a110fd6f0b4960231 100644 (file)
@@ -1,68 +1,88 @@
-#!/usr/bin/perl
+###RUN_PERL: #!/usr/bin/perl
 #
 # /mscha/viewer
-# 07.04.2021
 # mscha time viewer
 #
-#    Copyright (C) 2020-2021  Balthasar Szczepański
+# Copyright (C) 2020, 2021, 2024  Balthasar Szczepański
 #
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
 #
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
 #
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 use strict;
+use utf8;
+# use Encode::Locale ('decode_argv');
+use Encode ('encode', 'decode');
 
-#use warnings;
-use lib '/eizm/lib/ottbackup/mscha/';
-use mscha_lib qw(failpage gethttpheader getcgi gettimeframe urlencode entityencode printframeselection);
+###PERL_LIB: use lib /botm/lib/mscha
+use botm_common (
+       'HTTP_STATUS',
+       'fail_method', 'fail_content_type',
+       'read_header_env',
+       'url_encode',
+       'url_query_decode',
+       'http_entity_encode_dec',
+       'merge_settings',
+       'merge_url'
+);
+use mscha_lib (
+       'redirect',
+       'get_time_frame',
+       'print_frame_selection'
+);
+
+###PERL_SCHEME:  SCHEME  = http
+###PERL_WEBSITE: WEBSITE = 1190.bicyclesonthemoon.info
+
+binmode STDIN,  ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+binmode STDERR, ':encoding(UTF-8)';
+# decode_argv();
 
 my $time = time();
 srand ($time+$$);
 
 my %http;
 my %cgi;
-my %cgipost;
-my %frameinfo;
+my %cgi_post;
+my %frame_info;
 
 my $method;
 my $frame;
 my $mode;
 my $embed;
-my $embedUrl;
 
 if ($ENV{'REQUEST_METHOD'} =~ /^(HEAD|GET|POST)$/) {
-       $method=$1;
+       $method = $1;
 }
 else{
-       exit failpage("Status: 405 Method Not Allowed\nAllow: GET, POST, HEAD\n","405 Method Not Allowed","The interface does not support the $ENV{'REQUEST_METHOD'} method.",$method);
+       exit fail_method($ENV{'REQUEST_METHOD'}, ['GET', 'POST', 'HEAD']);
 }
 
-%http = gethttpheader (\%ENV);
-%cgi = getcgi($ENV{'QUERY_STRING'});
+%http = read_header_env(\%ENV);
+%cgi = url_query_decode($ENV{'QUERY_STRING'});
 
 if ($method eq 'POST') {
        if ($http{'content-type'} eq 'application/x-www-form-urlencoded') {
-               my %cgipost=getcgi( <STDIN> );
-               foreach my $ind (keys %cgipost) {
-                       $cgi{$ind}=$cgipost{$ind};
-               }
+               my %cgi_post = url_query_decode( <STDIN> );
+               %cgi = merge_settings(\%cgi, \%cgi_post);
        }
        # multipart not supported
        else{
-               exit failpage("Status: 415 Unsupported Media Type\n","415 Unsupported Media Type","Unsupported Content-type: $http{'content-type'}.");
+               exit fail_content_type($method, $http{'content-type'});
        }
 }
 
-$embed=lc($cgi{'embed'});
+$embed = lc($cgi{'embed'});
 
 if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = $1;
@@ -71,15 +91,17 @@ if ($ENV{'PATH_INFO'} =~ /^\/([^\/]+)(\/(.+))?$/) {
        $frame = '1';
        $mode = '';
 }
-if ($cgi{'period'} ne '') {
-       $frame=$cgi{'period'};
+
+if ($cgi{'frameNo'} ne '') {
+       $frame = $cgi{'frameNo'};
 }
-if ($cgi{'frame'} ne '') {
-       $frame=$cgi{'frame'};
+elsif ($cgi{'frame'} ne '') {
+       $frame = $cgi{'frame'};
 }
-if ($cgi{'frameNo'} ne '') {
-       $frame=$cgi{'frameNo'};
+elsif ($cgi{'period'} ne '') {
+       $frame = $cgi{'period'};
 }
+
 if ($cgi{'mode'} ne '') {
        $mode=lc($cgi{'mode'});
 }
@@ -87,51 +109,226 @@ if ($mode !~ /^(orig|diff)$/) {
        $mode = '';
 }
 
-%frameinfo = gettimeframe($frame,$time);
+%frame_info = get_time_frame($frame, $time);
 
-if (($mode eq 'diff') && ($frameinfo{'diffUrl'} eq '')) {
+if (($mode eq 'diff') && ($frame_info{'diffUrl'} eq '')) {
        $mode = '';
 }
 
+my $website_full_url = merge_url(
+       {
+               'scheme' => SCHEME(),
+               'host'   => WEBSITE()
+       }
+);
+my $embedUrl;
+
 if ($mode eq 'orig') {
-       $embedUrl = $frameinfo{'downloadedUrl'};
-} elsif ($mode eq 'diff') {
-       $embedUrl = $frameinfo{'diffUrl'};
-} else {
-       $embedUrl = ($frameinfo{'xkcdUrl'} ne '')?$frameinfo{'xkcdUrl'}:$frameinfo{'downloadedUrl'};
+       $embedUrl = $frame_info{'downloadedUrl'};
+}
+elsif ($mode eq 'diff') {
+       $embedUrl = $frame_info{'diffUrl'};
+}
+else {
+       $embedUrl = ($frame_info{'xkcdUrl'} ne '')?$frame_info{'xkcdUrl'}:$frame_info{'downloadedUrl'};
 }
 if ($embedUrl !~ /^http/) {
-       $embedUrl = 'http://1190.bicyclesonthemoon.info'.$embedUrl;
-}
-
-if ($frameinfo{'match'} !~ /^(frameNo|gwFrameNo|baFrameNo)$/) {
-       $frame = $frameinfo{'frameNo'};
-}
-
-my $url_frame       = urlencode($frame);
-my $url_amp_mode    = ($mode ne '')?('&amp;mode='.urlencode($mode)):'';
-my $url_botmEnhance = urlencode($frameinfo{'botmEnhance'});
-my $url_frameNo     = urlencode($frameinfo{'FrameNo'});
-my $url_gwFrameNo   = urlencode($frameinfo{'gwFrameNo'});
-my $url_baFrameNo   = urlencode($frameinfo{'baFrameNo'});
-
-my $en_frame         = entityencode($frame);
-my $en_mode          = entityencode($mode);
-my $en_frameNo       = entityencode($frameinfo{'frameNo'});
-my $en_gwFrameNo     = entityencode($frameinfo{'gwFrameNo'});
-my $en_baFrameNo     = entityencode($frameinfo{'baFrameNo'});
-my $en_next          = entityencode($frameinfo{'next'});
-my $en_prev          = entityencode($frameinfo{'prev'});
-my $en_diffUrl       = entityencode($frameinfo{'diffUrl'});
-my $en_xkcdUrl       = entityencode($frameinfo{'xkcdUrl'});
-my $en_downloadedUrl = entityencode($frameinfo{'downloadedUrl'});
-my $en_soundUrl      = entityencode($frameinfo{'soundUrl'});
+       $embedUrl = merge_url(
+               $website_full_url,
+               {'path' => $embedUrl}
+       );
+}
+
+if ($frame_info{'match'} !~ /^(frameNo|gwFrameNo|baFrameNo)$/) {
+       $frame = $frame_info{'frameNo'};
+}
+
+my %base_url_query = (
+       'frame' => $frame,
+       'uri'   => CGI_VIEW_PATH()
+);
+my $viewer_first_url = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => '1'}
+);
+my $viewer_prev_url = ($frame_info{'prev'} ne '') ?
+       merge_url(
+               {'path' => CGI_VIEW_PATH()},
+               {'path' => $frame_info{'prev'}}
+       );
+my $viewer_next_url = ($frame_info{'prev'} ne '') ?
+       merge_url(
+               {'path' => CGI_VIEW_PATH()},
+               {'path' => $frame_info{'prev'}}
+       );
+my $viewer_last_url = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => '3094'}
+);
+my $viewer_random_url = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => 'random'}
+);
+my $viewer_rsound_url = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => 'randomsound'}
+);
+if ($mode ne '') {
+       $base_url_query{'mode'} = $mode;
+       $viewer_first_url = merge_url(
+               {'path' => $viewer_first_url},
+               {'path' => $mode}
+       );
+       if ($viewer_prev_url ne '') {
+               $viewer_prev_url = merge_url(
+                       {'path' => $viewer_prev_url},
+                       {'path' => $mode}
+               );
+       }
+       if ($viewer_next_url ne '') {
+               $viewer_next_url = merge_url(
+                       {'path' => $viewer_next_url},
+                       {'path' => $mode}
+               );
+       }
+       $viewer_last_url = merge_url(
+               {'path' => $viewer_last_url},
+               {'path' => $mode}
+       );
+}
+my $base_url = merge_url(
+       {
+               'path' => CGI_VIEW_2_PATH(),
+               'query' => \%base_url_query
+       }
+);
+
+my $viewer_xkcd_url = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => $frame_info{'frameNo'}}
+);
+my $viewer_orig_url = merge_url(
+       {'path' => $viewer_xkcd_url},
+       {'path' => 'orig'}
+);
+my $viewer_diff_url = merge_url(
+       {'path' => $viewer_xkcd_url},
+       {'path' => 'diff'}
+);
+my $geekwagon_url = ($frame_info{'gwFrameNo'} ne '') ?
+       merge_url(
+               GEEKWAGON_URL(),
+               {'query' => {'frame' => $frame_info{'gwFrameNo'}}}
+       ) : '';
+my $aubronwood_url = ($frame_info{'baFrameNo'} ne '') ?
+       merge_url(
+               AUBRONWOOD_URL(),
+               {'query' => {
+                       'i' => $frame_info{'baFrameNo'},
+                       'playing' => '0'
+               }}
+       ) : '';
+my $moon_url = merge_url(
+       TAT_VIEWER_URL(),
+       {'query' => {
+               'story' => 'time',
+               'f' => $frame_info{'frameNo'}
+       }}
+);
+my $moon_enhance_url = ($frame_info{'botmEnhance'} ne '') ?
+       merge_url(
+               $moon_url,
+               {
+                       'query' => {'e' => $frame_info{'botmEnhance'}},
+                       'append_query' => 1
+               }
+       ) : '';
+my $frame_url = 
+       ($mode eq 'diff') ?
+               $frame_info{'diffUrl'} : (
+                       (($mode ne 'orig') && ($frame_info{'xkcdUrl'} ne '')) ?
+                               $frame_info{'xkcdUrl'} :
+                               $frame_info{'downloadedUrl'}
+               );
+my $jumpUrl = merge_url(
+       {'path' => CGI_VIEW_PATH()},
+       {'path' => '_FRAMENO_'}
+);
+if ($mode ne '') {
+       $jumpUrl = merge_url(
+               {'path' => $jumpUrl},
+               {'path' => $mode}
+       );
+}
+
+
+my $title2 =
+       (($frame_info{'match'} eq 'baFrameNo') ? (' (Book of Aubron: '.$frame_info{'baFrameNo'}.')') : '').
+       (($frame_info{'match'} eq 'gwFrameNo') ? (' (Geekwagon: '.$frame_info{'gwFrameNo'}.')'):'');
+my $title = 'xkcd Timeframe '.$frame_info{'frameNo'}.$title2
+
+my $_website_full_url = html_entity_encode_dec($website_full_url);
+my $_base_url         = html_entity_encode_dec($base_url);
+my $_viewer_first_url = html_entity_encode_dec($viewer_first_url);
+my $_viewer_next_url  = html_entity_encode_dec($viewer_next_url);
+my $_viewer_last_url  = html_entity_encode_dec($viewer_last_url);
+my $_viewer_random_url= html_entity_encode_dec($viewer_random_url);
+my $_viewer_rsound_url= html_entity_encode_dec($viewer_rsound_url);
+my $_viewer_xkcd_url  = html_entity_encode_dec($viewer_xkcd_url);
+my $_viewer_orig_url  = html_entity_encode_dec($viewer_orig_url);
+my $_viewer_diff_url  = html_entity_encode_dec($viewer_diff_url);
+my $_geekwagon_url    = html_entity_encode_dec($geekwagon_url);
+my $_aubronwood_url   = html_entity_encode_dec($aubronwood_url);
+my $_moon_url         = html_entity_encode_dec($moon_url);
+my $_moon_enhance_url = html_entity_encode_dec($moon_enhance_url);
+my $_frame_url        = html_entity_encode_dec($frame_url);
+my $_css_url          = html_ebtity_encode_dec(CGI_CSS_PATH()); #/mscha/view1.css
+my $_logo_url         = html_ebtity_encode_dec(CGI_LOGO_PATH()); #/mscha/botmlogo2.spng
+my $_icon_url         = html_ebtity_encode_dec(CGI_ICON_PATH()); #/mscha/cuegan32.png
+my $_jquery_url       = html_ebtity_encode_dec(CGI_JQUERY_PATH()); #/mscha/js/1.11.0.jquery.min.js
+my $_jquery_ui_url    = html_ebtity_encode_dec(CGI_JQUERY_UI_PATH()); #/mscha/js/1.10.4.jquery-ui.min.js
+my $_jquery_cook_url  = html_ebtity_encode_dec(CGI_JQUERY_COOK_PATH()); #/mscha/js/jquery.cookie.js
+my $_js_url           = html_ebtity_encode_dec(CGI_VIEW_JS_PATH()); #/mscha/js/jquery.cookie.js
+my $_title            = html_ebtity_encode_dec($title);
+my $_title2           = html_ebtity_encode_dec($title2);
+my $_website          = html_ebtity_encode_dec($WEBSITE());
+my $_jumpUrl          = html_ebtity_encode_dec($jumpUrl);
+my $_frameNo          = html_entity_encode_dec($frame_info{'frameNo'});
+my $_alt              = html_entity_encode_dec($frame_info{'alt'});
+my $_next             = html_entity_encode_dec($frame_info{'next'});
+my $_prev             = html_entity_encode_dec($frame_info{'prev'});
+
+#my $_baFrameNo = html_entity_encode_dec($frame_info{'baFrameNo'});
+#my $_gwFrameNo = html_entity_encode_dec($frame_info{'gwFrameNo'});
+
+
+my $url_frame       = url_encode($frame);
+my $url_amp_mode    = ($mode ne '')?('&amp;mode='.url_encode($mode)):'';
+my $url_botmEnhance = url_encode($frame_info{'botmEnhance'});
+my $url_frameNo     = url_encode($frame_info{'FrameNo'});
+my $url_gwFrameNo   = url_encode($frame_info{'gwFrameNo'});
+my $url_baFrameNo   = url_encode($frame_info{'baFrameNo'});
+
+my $en_frame         = html_entity_encode_dec($frame);
+my $en_mode          = html_entity_encode_dec($mode);
+
+
+my $en_diffUrl       = html_entity_encode_dec($frame_info{'diffUrl'});
+my $en_xkcdUrl       = html_entity_encode_dec($frame_info{'xkcdUrl'});
+my $en_downloadedUrl = html_entity_encode_dec($frame_info{'downloadedUrl'});
+my $en_soundUrl      = html_entity_encode_dec($frame_info{'soundUrl'});
 my $en_embedUrl      = $embedUrl;
-my $en_alt           = entityencode($frameinfo{'alt'});
-my $en_sl_mode       = ($mode ne '')?('/'.entityencode($mode)):'';
-my $en_dateTime      = entityencode(substr($frameinfo{'dateTime'},0,4).'-'.substr($frameinfo{'dateTime'},5,2).'-'.substr($frameinfo{'dateTime'},8,2).' '.substr($frameinfo{'dateTime'},11,2).':'.substr($frameinfo{'dateTime'},14,2));
-my $en_epoch         = entityencode($frameinfo{'epoch'});
-my $en_hash          = entityencode($frameinfo{'hash'});
+
+my $en_sl_mode       = ($mode ne '')?('/'.html_entity_encode_dec($mode)):'';
+my $en_dateTime      = html_entity_encode_dec(
+       substr($frame_info{'dateTime'}, 0, 4).'-'.
+       substr($frame_info{'dateTime'}, 5, 2).'-'.
+       substr($frame_info{'dateTime'}, 8, 2).' '.
+       substr($frame_info{'dateTime'},11, 2).':'.
+       substr($frame_info{'dateTime'},14, 2)
+);
+my $en_epoch         = html_entity_encode_dec($frame_info{'epoch'});
+my $en_hash          = html_entity_encode_dec($frame_info{'hash'});
 
 print "Content-type: text/html\n";
 print "\n";
@@ -141,90 +338,85 @@ if($method eq 'HEAD') {
 
 print '<!DOCTYPE html>'."\n";
 print '<html>'."\n";
-print '<head>'."\n";
-print '<base href="/mscha/view.fcgi?frame='.$url_frame.$url_amp_mode.'&amp;uri=%2Fmscha%2Fviewer">'."\n";
-print '<meta charset="utf-8">'."\n";
-print '<meta name="viewport" content="width=device-width">'."\n";
-print '<title>xkcd Timeframe '.$en_frameNo.(($frameinfo{'match'} eq 'baFrameNo')?(' (Book of Aubron: '.$en_baFrameNo.')'):'').(($frameinfo{'match'} eq 'gwFrameNo')?(' (Geekwagon: '.$en_gwFrameNo.')'):'').'</title>'."\n";
-print '<link type="text/css" rel="stylesheet" href="/mscha/view1.css">'."\n";
-print '<link rel="icon" type="image/png" href="/mscha/cuegan32.png">'."\n";
-if ($frameinfo{'next'} ne '') {
-       print '<link rel="prefetch" href="/mscha/viewer/'.$en_next.$en_sl_mode.'">'."\n";
-}
-print '<script src="/mscha/js/1.11.0.jquery.min.js"></script>'."\n";
-print '<script src="/mscha/js/1.10.4.jquery-ui.min.js"></script>'."\n";
-print '<script src="/mscha/js/jquery.cookie.js"></script>'."\n";
-print '<script>//<![CDATA['."\n";
-print "\n";
-print 'var jumpUrl = \'/mscha/viewer/_FRAMENO_'.$en_sl_mode.'\';'."\n";
-print "\n";
-print '//]]></script><script src="/mscha/view.js"></script>'."\n";
-print '</head>'."\n";
-print '<body>'."\n";
-print '<span id="top"><a href="http://1190.bicyclesonthemoon.info"><img src="/img/botmlogo2.png" alt="1190.bicyclesonthemoon.info" border="0"></a><br>Redundant copy of <a href="http://xkcd.mscha.org">xkcd.mscha.org</a>.</span>'."\n";
-print '<h1>xkcd <a href="http://xkcd.com/1190/" target="_blank">Time</a>frame '.$en_frameNo.'</h1>'."\n";
-if ($frameinfo{'match'} eq 'baFrameNo') {
-       print '<h2> (Book of Aubron: '.$en_baFrameNo.')</h2>'."\n";
+print ' <head>'."\n";
+print ' <meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
+print ' <base href="'.$_base_url;.'">'."\n";
+print ' <meta name="viewport" content="width=device-width">'."\n";
+print '  <title>xkcd Timeframe '.$_title.'</title>'."\n";
+print '  <link type="text/css" rel="stylesheet" href="'.$_css_url.'">'."\n";
+print '  <link rel="icon" type="image/png" href=".'$_icon_url.'">'."\n";
+if ($viewer_prev_url ne '') {
+       print '  <link rel="next" href="'.$_viewer_prev_url.'">'."\n";
+       print '  <link rel="prefetch" href="'.$_viewer_prev_url.'">'."\n";
 }
-if ($frameinfo{'match'} eq 'gwFrameNo') {
-       print '<h2> (Geekwagon: '.$en_gwFrameNo.')</h2>'."\n";
+if ($viewer_next_url ne '') {
+       print '  <link rel="next" href="'.$_viewer_next_url.'">'."\n";
+       print '  <link rel="prefetch" href="'.$_viewer_next_url.'">'."\n";
 }
-print ''."\n";
-print '<span class="comic"><img src="';
-if ($mode eq 'diff') {
-       print $en_diffUrl."\n";
-} elsif (($mode ne 'orig')&&($frameinfo{'xkcdUrl'} ne '')) {
-       print $en_xkcdUrl."\n";
-} else {
-       print $en_downloadedUrl."\n";
+print '  <script src="'.$_jquery_url.'"></script>'."\n";
+print '  <script src="'.$_jquery_ui_url.'"></script>'."\n";
+print '  <script src="'.$_jquery_cook_url.'"></script>'."\n";
+print '  <script>//<![CDATA['."\n";
+print "   \n";
+print '   var jumpUrl = \''.$_jumpUrl.'\';'."\n";
+print "   \n";
+print '  //]]></script>'."\n";
+print '  <script src="'.$_js_url.'"></script>'."\n";
+print ' </head>'."\n";
+print ' <body>'."\n";
+print '  <span id="top"><a href="'.$_website_full_url.'"><img src="'.$_logo_url.'" alt="'.$_website.'" border="0"></a><br>Redundant copy of <a href="http://xkcd.mscha.org">xkcd.mscha.org</a>.</span>'."\n";
+print '  <h1>xkcd <a href="http://xkcd.com/1190/" target="_blank">Time</a>frame '.$_frameNo.'</h1>'."\n";
+if ($title2 ne '') {
+       print '  <h2>'.$_title2.'</h2>'."\n";
 }
-print '" class="comic" alt="Time" title="'.$en_alt.'"></span>'."\n";
-print ''."\n";
-print '<div class="type">'."\n";
+print "  \n";
+print ' <span class="comic"><img src="'.$_frame_url.'" class="comic" alt="Time" title="'.$_alt.'"></span>'."\n";
+print "  \n";
+print '  <div class="type">'."\n";
 if ($mode ne '') {
-       print '<a href="/mscha/viewer/'.$en_frameNo.'"  title="Current frame at xkcd servers">xkcd</a>'."\n";
+       print '   <a href="'.$_viewer_xkcd_url.'"  title="Current frame at xkcd servers">xkcd</a>'."\n";
 } else {
-       print '<strong title="Current frame at xkcd servers">xkcd</strong>'."\n";
+       print '   <strong title="Current frame at xkcd servers">xkcd</strong>'."\n";
 }
-print '&bull;'."\n";
+print '   &bull;'."\n";
 if ($mode ne 'orig') {
-       print '<a href="/mscha/viewer/'.$en_frameNo.'/orig" title="Frame as originally downloaded">original</a>'."\n";
+       print '   <a href="'.$_viewer_orig_url.'" title="Frame as originally downloaded">original</a>'."\n";
 } else {
-       print '<strong title="Frame as originally downloaded">original</strong>'."\n";
+       print '   <strong title="Frame as originally downloaded">original</strong>'."\n";
 }
-if ($frameinfo{'diffUrl'} ne '') {
-       print '&bull;'."\n";
+if ($frame_info{'diffUrl'} ne '') {
+       print '   &bull;'."\n";
        if ($mode ne 'diff') {
-               print '<a href="/mscha/viewer/'.$en_frameNo.'/diff" title="Difference between original and current frame">difference</a>'."\n";
+               print '   <a href="'.$viewer_diff_url.'" title="Difference between original and current frame">difference</a>'."\n";
        } else {
-               print '<strong title="Difference between original and current frame">difference</strong>'."\n";
+               print '   <strong title="Difference between original and current frame">difference</strong>'."\n";
        }
 }
-if ($frameinfo{'botmEnhance'} ne '') {
-       print '<br>'."\n";
-       print '<a href="http://1190.bicyclesonthemoon.info/aftertime/viewer/?story=time&amp;f='.$url_frameNo.'&amp;e='.$url_botmEnhance.'" target="_blank" style="font-size: 85%;">ENHANCE</a>'."\n";
+if ($moon_enhance_url ne '') {
+       print '   <br>'."\n";
+       print '   <a href="'.$_moon_enhance_url.'" target="_blank" style="font-size: 85%;">ENHANCE</a>'."\n";
 }
-print '</div>'."\n";
-print "\n";
-print '<div class="nav">'."\n";
-print '<a id="linkFirst" title="First frame (press &lt;Home&gt;)" href="/mscha/viewer/1'.$en_sl_mode.'">&lt;&lt;1&lt;&lt;</a>'."\n";
-if($frameinfo{'prev'} ne '') {
-       print '<a id="linkPrev" title="Previous frame (press &lt;&larr;&gt; or &lt;PgUp&gt;)" href="/mscha/viewer/'.$en_prev.$en_sl_mode.'">&lt;'.$en_prev.'&lt;</a>'."\n";
+print '  </div>'."\n";
+print "  \n";
+print '  <div class="nav">'."\n";
+print '   <a id="linkFirst" title="First frame (press &lt;Home&gt;)" href="'.$_viewer_first_url.'">&lt;&lt;1&lt;&lt;</a>'."\n";
+if ($viewer_prev_url ne '') {
+       print '   <a id="linkPrev" title="Previous frame (press &lt;&larr;&gt; or &lt;PgUp&gt;)" href="'.$_viewer_prev_url.'">&lt;'.$_prev.'&lt;</a>'."\n";
 } else {
-       print '<span class="placeholder"></span>'."\n";
+       print '   <span class="placeholder"></span>'."\n";
 }
-if($frameinfo{'next'} ne '') {
-       print '<a id="linkNext" title="Next frame (press &lt;&rarr;&gt; or &lt;PgDn&gt;)" href="/mscha/viewer/'.$en_next.$en_sl_mode.'">&gt;'.$en_next.'&gt;</a>'."\n";
+if($viewer_next_url{'next'} ne '') {
+       print '   <a id="linkNext" title="Next frame (press &lt;&rarr;&gt; or &lt;PgDn&gt;)" href="'.$_viewer_next_url.'">&gt;'.$_next.'&gt;</a>'."\n";
 } else {
-       print '<span class="placeholder"></span>'."\n";
+       print '   <span class="placeholder"></span>'."\n";
 }
-print '<a id="linkLast" title="Last frame (press &lt;End&gt;)" href="/mscha/viewer/3094'.$en_sl_mode.'">&gt;&gt;3094&gt;&gt;</a>'."\n";
-print '<br>'."\n";
-print '<a id="linkRandom" class="center2" title="Random frame (press &lt;?&gt;)" href="/mscha/viewer/random'.$en_sl_mode.'">Random</a>'."\n";
-print '<a id="linkRandomSound" title="Random frame with sound" href="/mscha/viewer/randomsound'.$en_sl_mode.'">with sound</a>'."\n";
-print '</div>'."\n";
-print "\n";
-if ($frameinfo{'soundUrl'} ne '') {
+print '   <a id="linkLast" title="Last frame (press &lt;End&gt;)" href="'.$_viewer_last_url.'">&gt;&gt;3094&gt;&gt;</a>'."\n";
+print '   <br>'."\n";
+print '   <a id="linkRandom" class="center2" title="Random frame (press &lt;?&gt;)" href="'.$_viewer_random_url.'">Random</a>'."\n";
+print '   <a id="linkRandomSound" title="Random frame with sound" href="'.$_viewer_rsound_url.'">with sound</a>'."\n";
+print '  </div>'."\n";
+print "  \n";
+if ($frame_info{'soundUrl'} ne '') {
        print '<div class="dialogue">'."\n";
        print '<audio controls title="Play dialogue">'."\n";
        print '<source src="'.$en_soundUrl.'" type="audio/mpeg">'."\n";
@@ -235,13 +427,13 @@ if ($frameinfo{'soundUrl'} ne '') {
 print "\n";
 print '<div class="metadata">'."\n";
 print '<strong>Date/time:</strong> '.$en_dateTime.' UTC <span id="localtime" data-epoch="'.$en_epoch.'"></span><br>'."\n";
-print '<strong>Hash:</strong> '.(($frameinfo{'hash'} ne '')?$en_hash:'<i>unknown</i>')."\n";
+print '<strong>Hash:</strong> '.(($frame_info{'hash'} ne '')?$en_hash:'<i>unknown</i>')."\n";
 print '</div>'."\n";
 print "\n";
 print '<div class="jump"><form method="get" action="/mscha/viewer">'."\n";
 print '<b>Jump to:</b>&nbsp;'."\n";
 print '<select id="period" name="period">';
-printframeselection ($frameinfo{'frameNo'});
+print_frame_selection ($frame_info{'frameNo'});
 print '</select>'."\n";
 print '<br>'."\n";
 print '<b>Or go to frame:</b>'."\n";
@@ -289,19 +481,19 @@ print '</div>'."\n";
 print ''."\n";
 print '<div class="external">'."\n";
 print '<strong>This frame on other sites:</strong><br>'."\n";
-if ($frameinfo{'gwFrameNo'} ne '') {
+if ($frame_info{'gwFrameNo'} ne '') {
        print 'Geekwagon:'."\n";
        print '<a href="http://geekwagon.net/projects/xkcd1190/?frame='.$url_gwFrameNo.'" target="_blank">frame '.$en_gwFrameNo.'</a>'."\n";
        print '<br>'."\n";
 }
-if ($frameinfo{'baFrameNo'} ne '') {
+if ($frame_info{'baFrameNo'} ne '') {
        print 'Book of Aubron:'."\n";
        print '<a href="http://xkcd.aubronwood.com/?i='.$url_baFrameNo.'&amp;playing=0" target="_blank">frame '.$en_baFrameNo.'</a>'."\n";
        print '<br>'."\n";
 }
 print 'The moon:'."\n";
 print '<a href="http://1190.bicyclesonthemoon.info/aftertime/viewer?story=time&amp;f='.$url_frameNo.'" target="_blank">Time/'.$en_frameNo.'</a>'."\n";
-if ($frameinfo{'botmEnhance'} ne '') {
+if ($frame_info{'botmEnhance'} ne '') {
        print '(<a href="http://1190.bicyclesonthemoon.info/aftertime/viewer?story=time&amp;e='.$url_botmEnhance.'&amp;f='.$url_frameNo.'" target="_blank" style="font-size: 85%;">ENHANCE</a>)'."\n";
 }
 print '<br>'."\n";
diff --git a/www-data/botmlogo2.png b/www-data/botmlogo2.png
new file mode 100644 (file)
index 0000000..8ffddc7
Binary files /dev/null and b/www-data/botmlogo2.png differ