#!/usr/local/bin/perl
# KOI.pl - CGI-Script (v0.1.1) by Maksim Moshkow, converts TXT-documents
# to HTML 'on the fly'. Feel free to modify and use it.

#
# мАЛЕНЬКОЕ ПРЕДУПРЕЖДЕНИЕ. сКРИПТ РАСЧИТАН ДЛЯ РАБОТЫ С ТЕКСТОВЫМИ ФАЙЛАМИ
# ПОДГОТОВЛЕННЫМИ В РЕДАКТОРЕ рК НА РАБОЧЕЙ СТАНЦИИ бЕСТА-88.
# пОЭТОМУ БУКОВКИ С ЕГО ПОДАЧИ ВАМ ПОКАЖУТТСЯ ПЕРЕВЕРНУТЫМИ.
# нЕ ПОЛЕНИТЕСЬ ИСПРАВИТЬ ТАБЛИЧКИ ПЕРЕКОДИРОВКИ В ФУНКЦИИ KOI
#

$ALARM_TIME=2400;         # ЛИМИТ ВРЕМЕНИ 40 МИНУТ - ЗАТЕМ - САМОУНИЧТОЖЕНИЕ
$SIG{'ALRM'} = 'timeout';
alarm $ALARM_TIME;

if    ($0 =~ /-KOI/)        {$PEREKODER='-k';$KNAMKODER='-K';}
elsif ($0 =~ /-windows/)    {$PEREKODER='-w';$KNAMKODER='-W';}
elsif ($0 =~ /-alt/)        {$PEREKODER='-a';$KNAMKODER='-A';}
elsif ($0 =~ /-iso_8859_5/) {$PEREKODER='-i';$KNAMKODER='-I';}
elsif ($0 =~ /-volapuk/)    {$PEREKODER='-l';$KNAMKODER='-L';}
;

@kodirowki=('volapuk','windows','iso_8859_5','alt','KOI');

$ROOT_DIR = '/home/www/docs/book';
$ROOT_WWW = '/book';

# бУДЕМ ДАВАТЬ ФАЙЛЫ КУСОЧКАМИ ПО 80 КБ
  $piece_size=81920;


$what_s_new="<form \n action=What-s-new method=POST><input type=submit value=What_is_new></form>";

@mesq=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
@nedelq=('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); # НЕДЕЛЯ НАЧИНАЕТСЯ С ВОСКРЕСЕНЬЯ

# $|=1; # Try uncommenting this line if the script stays in memory

$filename = $ROOT_DIR . $ENV{PATH_INFO};

$filename =~ s/\.\.//g ; # there is a '..' - someone tries to break in?

if ($filename =~ /\/What-s-new$/)              { &Directory("What-s-new") ; }
if ($filename =~ /\/Contents$/)                { &Contents          ; }
if ($filename =~ /\/with-big-pictures\.html$/) { &With_big_pictures ; }
if ($filename =~ /\/with-icons\.html$/)        { &With_icons        ; }
if ($filename =~ /\/Piece[0-9]*\.[0-9]*$/)     { &Piece             ; }

if (-d $filename) {

 if ($filename =~ /\/$/) {}	# there is a '/' at the end - Ok.
 else {print "Location: http:$ENV{SCRIPT_NAME}$PATH_INFO/\n\n"; exit 0 ;}

   if(-f $filename.'index.html'){$filename.='index.html';}
elsif(-f $filename.      '.dir'){$filename.=      '.dir';}
elsif(-f $filename.   'mim.dir'){$filename.=   'mim.dir';}
elsif(-f $filename. 'index.htm'){$filename.= 'index.htm';}
else                            { &Directory            ;}
}

open(DOCUMENT, $filename) || &file_not_found("Can't open $filename");

if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

if     ($filename =~ /\.html?$/i) {
	print "Content-type: text/html\n$Additional_header\n";
        while (read(DOCUMENT,$bufer,100000)){print &KOI ($PEREKODER, $bufer) ;}
}elsif ($filename =~ /\.dir$/) {
       	print "Content-type: text/html\n$Additional_header\n";
        &rkdir2html () ;
}elsif ($filename =~ /\.txt$|\.doc$/) {
	print "Content-type: text/html\n$Additional_header\n<pre>\n";
        &txt2html();
}elsif ($filename =~ /\.lbl$|\.hlp$|\.[0-9]*$/) {
	print "Content-type: text/plain\n$Additional_header\n";
        while (read(DOCUMENT,$bufer,100000)) {print &KOI($PEREKODER, $bufer);}
}elsif ($filename =~ /\.game$/) {
      print "Location: http:/cgi-bin/moshkow/Game-KOI.sh$ENV{PATH_INFO}/1\n\n";
        exit 0 ;
}else { # ЕСЛИ НЕ НАШЕ РАСШИРЕНИЕ, ТО ОТДАТЬ ЕГО НА ОТКУП httpd
	print "Location: http:$ROOT_WWW$ENV{PATH_INFO}\n\n";
        exit 0 ;
}

close(DOCUMENT);
close(STDOUT);

exit(0);

sub file_not_found # ВЫРУГАТЬСЯ И exit
{
print "Content-type: text/html\n\n",
"<HEAD><TITLE>404 Not Found</TITLE></HEAD>",
"<BODY><H1>404 Not Found</H1>",
"The requested URL $ENV{PATH_INFO} was not found on this server.<P>",
"You can mail all problems about this library to <a href=mailto:moshkow\@ipsun.ras.ru>moshkow\@ipsun.ras.ru</a>",
"</BODY>";
die @_[0];
}

sub timeout {
$SIG{'ALRM'} = 'finaltimeout';
alarm 10; # пОДОЗРЕВАЮ, ЧТО НА printe МЫ ОПЯТЬ МОЖЕМ ПОВИСНУТЬ. дАЕМ ЕМУ 10 СЕК
print "\n</pre><blink><b>Timeout $ALARM_TIME while printing $filename </b></blink><pre>";
exit 1;
}

sub finaltimeout {
    exit 1;
    die "Final timeout. Aborting $filename";
}

sub txt2html { # пРЕВРАЩАЕТ рк-ШНУЮ РАСКРАСКУ В HTML-ТЕГИ

$_=<DOCUMENT>; # НЕТ ЛИ В ПЕРВОЙ СТРОКЕ ЗАГЛАВИЯ?
/^        \024(.*)\025/ && print &KOI($PEREKODER, "<title>$1</title>" );

open(DOCUMENT, $filename) ;

$zagolowok=0;
while (<DOCUMENT>){
/^        \024(.*)\025(.*)/ && do { $_="<ul><h2><a name=$zagolowok>$1</a>$2</h2></ul>\n" ; $zagolowok++;};
/^( *)(.*[^ ]) *╬ *([^ \n]*)/ && do { $_="$1<a href=$3>$2</a>\n" ;};
 s/\024/<b>/g;
 s/\025/<\/b>/g;
 s/\036D/<b><i>/g;
 s/\036E/<\/b><\/i>/g;
 s/^----*$/<hr>/g ;
 print &KOI($PEREKODER, $_ );
 };
}

sub KOI # а ТЫ ЗНАЕШЬ, ЧТО ОН КАЛЕЧИТ сами АРГУМЕНТЫ ????????
{
if    ( @_[0] eq '-K' ) { @_[1] =~ tr/АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩ\377ЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя╬/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/; }
elsif ( @_[0] eq '-k' ) { @_[1] =~ tr/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩ\377ЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя╬/; }
elsif ( @_[0] eq '-w' ) { @_[1] =~ tr/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧ\377╬/; }
elsif ( @_[0] eq '-i' ) { @_[1] =~ tr/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/°+╤Ё╜ч·ё?╓'???╖юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНО╬/; }
elsif ( @_[0] eq '-I' ) { @_[1] =~ tr/°+╤Ё╜ч·ё?╓'???╖юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНО╬/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/; }
elsif ( @_[0] eq '-W' ) { @_[1] =~ tr/юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧ\377╬/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/; }
elsif ( @_[0] eq '-a' ) { @_[1] =~ tr/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357Ё/;@_[1] =~ s/\015*\n/\015\n/g; }
elsif ( @_[0] eq '-A' ) { @_[1] =~ tr/\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357Ё/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/; @_[1] =~ s/\015*\n/\n/g; }
elsif ( @_[0] eq '-l' ) {@_[1] =~ tr/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/ABWGDEVZIJKLMNOPRSTUFHC+{}┐YX|~Qabwgdevzijklmnoprstufhc=\133\135Ryxe`q╬/; }
elsif ( @_[0] eq '-L' ) {@_[1] =~ tr/ABWGDEVZIJKLMNOPRSTUFHC+{}┐YX|~Qabwgdevzijklmnoprstufhc=\133\135Ryxe`q╬/абвгдежзийклмнопрстуфхцчшщ┐ыьэюяАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩRЫЬЭЮЯ╬/; }
    @_[1];
}

sub rkdir2html
{
 # НЕТ ЛИ В ПЕРВОЙ СТРОКЕ ЗАГЛАВИЯ?
$_=<DOCUMENT>; if ($_ =~ /^        (.*)/) {
$_="<title>$1</title>\n<pre><center><h2>$1</h2>$what_s_new$search_form</center>";

# @kodirowki=("volapuk","windows","iso_8859_5","alt","KOI"); form
for $i (@kodirowki)
      {$encoding.="[<a \n href=/cgi-bin/html-$i$ENV{PATH_INFO}   >$i</a>]";}
$_.="<li><b>Choose ".$encoding." encoding</b></ul>";

  print &KOI($PEREKODER, $_ );

} else {open(DOCUMENT, $filename) ;}

print  "<pre><font size=+1>\n";

while (<DOCUMENT>) {
 s/^----*$/<hr>/ ;
 s/(.*[^ ]) *╬ *([^ \n]*)/<li><A HREF=$2\/Contents>*<IMG ALIGN=absbottom BORDER=0 SRC=internal-gopher-unknown> <\/A><A HREF=$2><b><i>$1<\/i><\/b><\/A>/ ;
print &KOI($PEREKODER, $_ );
}
}

sub Last_Modified
{  # 1 АРГУМЕНТ - ИМЯ ФАЙЛ, ВОЗВРАЩАЕМ СИМВОЛЬНУЮ СТРОКУ ВРЕМЯ МОДИФИКАЦИИ
   # 2 АРГУМЕНТ "Full | Brief" - ЗАДАЕТ ФОРМАТ ТЕКСТОВОЙ СТРОКИ С ДАТОЙ
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=gmtime((stat(@_[0]))[9]);
if   (@_[1]=~'Brief'){sprintf("%2d-%s-%d",
            # 29-Dec-95
                     $mday,@mesq[$mon],$year);}
elsif(@_[1]=~'Full'){sprintf("%s, %2d-%s-%d %02d:%02d:%02d GMT",
            # Fri, 29-Dec-95 22:50:47 GMT
                     @nedelq[$wday], $mday,@mesq[$mon],$year,$hour,$min,$sec);}
else                {sprintf("%s, %2d-%s-%d %02d:%02d:%02d GMT",
                     @nedelq[$wday], $mday,@mesq[$mon],$year,$hour,$min,$sec);}
}

sub Contents
{
$filename  =~ s/\/Contents// ;
$ENV{PATH_INFO}  =~ s/\/Contents// ;
$name_link = $ENV{PATH_INFO} ;
$name_link =~ s/.*\/// ; # эТО БУДЕТ ПРОСТОЕ ИМЯ ФАЙЛА

if ( -d $filename )  # еСЛИ Contents ЖМУТ НА КАТАЛОГЕ, ТО ВОЙТИ В НЕГО
 { print "Location: http:$ENV{SCRIPT_NAME}$ENV{PATH_INFO}\n\n" ; exit 0 }

if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

# бУДЕМ ДАВАТЬ ФАЙЛЫ КУСОЧКАМИ ПО 80 КБ
#  $piece_size=81920; # СМ. ВЫШЕ

$filesize=(stat($filename) )[7];

if ( $filesize > $piece_size ) {
$pieces="</font></pre><hr><b><font size=+2>Size $filesize bytes. If you permanently fail getting whole file, download it in 80Kb pieces:\n";
for ($i=1; $i-1 <= ($filesize / $piece_size) ; $i++ )
 {$pieces.=sprintf ("<a href=../$name_link/Piece80.%02d>[%d]</a>\n",$i,$i);};
$pieces.="</font></b><hr>";
}

print "Content-type: text/html\n$Additional_header\n".
"<TITLE>$ENV{PATH_INFO}/Contents</TITLE>\n".
"<H1><a href=http:$ENV{SCRIPT_NAME}$ENV{PATH_INFO}>$ENV{PATH_INFO}</a>/Contents</H1>\n".
"<pre><font size=+1><b>\n";

$zagolowok=0;
open(DOCUMENT, $filename) || &file_not_found("Can't open $filename");
while (<DOCUMENT>){
/^        \024(.*)\025(.*)/ && do {
    if ($1 =~ /[*]/){
$_="\n<h2><ul><i><a href=../$name_link#$zagolowok>$1</a>$2</i></ul></h3>\n";
}else{
$_="<li><a href=../$name_link#$zagolowok>$1</a>$2\n" ;
}
$zagolowok++;print &KOI($PEREKODER,$_);
};
}
print "</b>";
print $pieces;
exit(0);

}

sub With_big_pictures
{
$filename  =~ s/\/with-big-pictures\.html// ;

if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

print "Content-type: text/html\n$Additional_header\n<pre>";

open(DOCUMENT, $filename) || &file_not_found("Can't open $filename");
while (<DOCUMENT>){
 s/\024/<b>/g;
 s/\025/<\/b>/g;
 s/\036D/<b><i>/g;
 s/\036E/<\/b><\/i>/g;
 s/^----*$/<hr>/g ;

/^( *)(.*[^ ]) *╬ *([^ \n]*)\.jpg portret/ && do { $url=$3.".jpg" ;
 $_="<a href=../$url><img width=280 height=420 src=../$url></a><br>$1$2\n" ;};
/^( *)(.*[^ ]) *╬ *([^ \n]*)\.jpg/ && do { $url=$3.".jpg" ;
 $_="<a href=../$url><img width=420 height=280 src=../$url></a><br>$1$2\n" ;};
/^( *)(.*[^ ]) *╬ *([^ \n]*)/ && do { $url=$3 ;
if    ($url=~ /^mailto:|^http:|^ftp:|^\//) {$_="$1<A HREF=$url>$2</A>\n" ;}
else  {$_="$1<a href=../$url>$2</a>\n" ;}
};

print &KOI($PEREKODER, $_ );
}
exit(0);

}
sub With_icons
{
$filename  =~ s/\/with-icons\.html// ;

if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

print "Content-type: text/html\n$Additional_header\n<pre>";

$zagolowok=0;

open(DOCUMENT, $filename) || &file_not_found("Can't open $filename");
while (<DOCUMENT>){
/^        \024(.*)\025(.*)/ && do { $_="<ul><h2><a name=$zagolowok>$1</a>$2</h2></ul>" ; $zagolowok++;};
 s/\024/<b>/g;
 s/\025/<\/b>/g;
 s/\036D/<b><i>/g;
 s/\036E/<\/b><\/i>/g;
 s/^----*$/<hr>/g ;

/^( *)(.*[^ ]) *╬ *([^ \n]*)\.jpg portret/ && do { $url=$3.".jpg" ;
 $_="<a href=../$url><img width=70  height=105 src=../$3.gif></a><br>$1$2\n";};
/^( *)(.*[^ ]) *╬ *([^ \n]*)\.jpg/ && do { $url=$3.".jpg" ;
 $_="<a href=../$url><img width=105 height=70  src=../$3.gif></a><br>$1$2\n";};
/^( *)(.*[^ ]) *╬ *([^ \n]*)/ && do { $url=$3 ;
if    ($url=~ /^mailto:|^http:|^ftp:|^\//) {$_="$1<A HREF=$url>$2</A>\n" ;}
else  {$_="$1<a href=../$url>$2</a>\n" ;}
};

print &KOI($PEREKODER, $_ );
}
exit(0);

}

sub Directory
{ # БЕЗ АРГУМЕНТОВ ДАДИМ ПОЛНЫЙ СПИСОК ФАЙЛОВ КАТАЛОГА

if (@_[0] eq 'What-s-new'){$Ne_Tolxko_new=0;}else{$Ne_Tolxko_new=1;}
  # 'What-s-new' - ТОГДА ДАЕМ ТОЛЬКО ФАЙЛЫ С МОДИФИКАЦИЕЙ < 31 ДНЕЙ

$filename  =~ s/\/What-s-new/\// ;

if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

print "Content-type: text/html\n$Additional_header\n".
"<TITLE>$ENV{PATH_INFO}</TITLE>\n<H1>$ENV{PATH_INFO}</H1>\n".
"<pre>".
" Name                              Size   Last modified\n<hr>";

opendir(dirhandle, $filename)|| &file_not_found("Can't open dir $filename");

while ($fname=readdir(dirhandle)){@dir = ( @dir, $fname );}

foreach $fname (sort @dir) { # ДИРЕКТОРИЮ ЗАЧИТАЛИ В МАССИВ И ОТСОРТИРОВАЛИ

 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
   $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename.$fname);

 if (-d _ ) {$fname.="/";$image="menu";}else{$image="unknown";}

 if (!($fname =~ /^\./ )  && ( $Ne_Tolxko_new || (time()-$mtime < 2678400)) ) {
printf (" <a href=%s><IMG ALIGN=absbottom BORDER=0 SRC=internal-gopher-%s>%-28.28s    %9d \t %s \n",$fname,$image,substr($fname,0,24)."</a>", $size, &Last_Modified($filename.$fname,'Brief') );
 }
}
exit(0);

}

sub Piece
{ # оТРЕЗАЕМ КУСОЧЕК ЗАПРОШЕННОГО ФАЙЛА/Piece80.02
$ENV{PATH_INFO}  =~ s/\/Piece.*// ;

$filename  =~ s/\/Piece([0-9]*).([0-9]*)// ;

$piece_size=80*1024;
$piece_number=$2;
$poziciq=$piece_size*($piece_number-1);
$filesize=(stat($filename) )[7];


if ($ENV{REMOTE_HOST} =~ /localhost/) { } else {
 $Additional_header="Last-modified: ". &Last_Modified($filename,'Full')."\n";}

#"<TITLE>$ENV{PATH_INFO}/Piece $piece_size beginning at $poziciq</TITLE><pre>\n";
print "Content-type: text/plain\n$Additional_header\n";

if ($filesize < $poziciq ) {
    print "You miss - file is shoter, than you request";
    exit 1;
}

open(DOCUMENT, $filename) || &file_not_found("Can't open $filename");

seek(DOCUMENT,$poziciq,0) || &file_not_found("Can't seek $pozition $filename");

read(DOCUMENT,$bufer,$piece_size) ;
  if ($filename =~ /\.html?$|\.txt$|\.doc$|\.lbl$|\.hlp$|\.[0-9]*$/ )
         { print &KOI ($PEREKODER, $bufer) }
    else { print $bufer; }

close (DOCUMENT);

exit (0);

}