#!/usr/bin/perl -w
use strict;
use CGI::FastTemplate;
print "Content-Type:text/html\n\n";
my (@trs, @books, @langs);
my ($tr, $search, $searchInd, $day, $size, $lang);
my ($book, $begin, $end, @tmp);
my ($fileTr, $fileBk) = ("translations", "books");
my $homeDir = '/htdocs/bible/';
### TODO: sanitize unicode ###
chdir $homeDir;
open(FILE, $fileTr) or die "Could not open $fileTr\n";
@tmp = ;
foreach my $line (@tmp) {
if ($line =~ /^(\w+), (\w*), (.*)$/) {
push(@trs, { key => $1, lang => $2, name => $3 });
} else {
die "translations formatted improperly: $line";
}
}
### TODO: implement country locales ###
open(FILE, $fileBk) or die "Could not open $fileBk\n";
@tmp = ;
foreach my $line (@tmp) {
if ($line =~ /^(([-_\w]+), ([^,]+(, )?){66})\n$/) {
$line = $1;
} else {
die "books formatted improperly";
}
my @bookNames = split(/, /, $line);
my $key = $bookNames[0];
for (my $i=1; $i{$key} = $bookNames[$i];
}
}
### e.g.: t=KJV&q=1Co5:4-6:9 ###
### e.g.: translation=KJV&book=1Co&chapter=5 ###
### order of arguments irrelevant, all parameters optional ###
### TODO: case-insensitive ###
my $query = substr($ENV{'QUERY_STRING'} || "", 0, 100);
my $acceptLang = substr($ENV{'HTTP_ACCEPT_LANGUAGE'} || "", 0, 100);
### TODO: Handle cookies ###
if ($query =~ /(\btranslation|\bt)=(\w{1,15})/) {
$tr = $2;
foreach my $hash (@trs) {
if ($hash->{key} eq $tr) {
$lang = $hash->{lang};
}
}
} else {
### check cookies, then fall back to HTTP Accept Language,
### english is default ###
foreach my $langStr (split(/,/, $acceptLang)) {
if ($langStr =~ /^((\w{1,3})(-\w{1,3})?)(;q=(\d?\.?\d{0,2}))?/) {
push(@langs, { lang => $2, q => $5 || 1.0 });
}
}
push (@langs, { lang => "en", q => 0 }); # default
my $qMax = -1;
foreach my $hashLg (@langs) {
foreach my $hashTr (@trs) {
if ($hashLg->{q} > $qMax and
$hashLg->{lang} eq $hashTr->{lang}) {
$qMax = $hashLg->{q};
$lang = $hashLg->{lang};
$tr = $hashTr->{key};
last;
}
}
}
}
if ($query =~ /(\bquery|\bq)=(\w+)/) {
$search = $2;
if ($query =~ /(\bn)=(\d+)/) {
$searchInd = $2;
} else {
$searchInd = 0;
}
} elsif ($query =~ /(\bbook|\bb)=(\w{3,4})&(chapter|c)=(\d{1,3})/) {
($book, $begin) = validCh($2, $4);
$end = $begin;
} else {
### check cookies, then fall back to John 1 ###
($book, $begin, $end) = ("joh", 1, 1);
}
sub validCh {
my ($b, $c) = @_;
my $i;
my $total = scalar(@books);
for ($i=0; $i<$total; $i++) {
if ($b eq lc($books[$i]->{abb})) {
last;
}
}
if ($c <= 0) {
if ($i-1 < 0) {
return ($books[0]->{abb}, 1);
} else {
return ($books[$i-1]->{abb}, $books[$i-1]->{ind});
}
} elsif ($c > $books[$i]->{ind}) {
if ($i == $total-1) {
return ($books[$total-1]->{abb}, $books[$total-1]->{ind});
} else {
return ($books[$i+1]->{abb}, 1);
}
} else {
return ($b, $c);
}
}
### check cookies, then fall back 1 ###
$day = 1;
### check cookies, then fall back 10 ###
$size = 10;
### inputs: book abbreviation, lang
### return: book name in local language
sub getBook {
my ($bookAbb, $lang) = @_;
foreach my $hash (@books) {
if ($bookAbb eq $hash->{abb}) {
return $hash->{$lang} || $hash->{en};
}
}
return;
}
sub getBookAbbr {
my ($book, $lang) = @_;
foreach my $hash (@books) {
if ($book eq $hash->{$lang}) {
return $hash->{abb};
}
}
return;
}
my $selectTr;
foreach my $hash (@trs) {
if ($tr eq $hash->{key}) {
$selectTr .= "\r\n";
} else {
$selectTr .= "\r\n";
}
}
my $selectBk;
foreach my $hash (@books) {
if ($book eq $hash->{abb}) {
$selectBk .= "\r\n";
} else {
$selectBk .= "\r\n";
}
}
my $tpl = new CGI::FastTemplate();
$tpl->define(
main => "main.tpl",
);
### TODO: add
tags ###
### TODO: search is too slow!! ###
if ($search && $search =~ /^[\w\s]+$/) {
my $results = `diatheke -b $tr -s multiword -k $search`;
my $scripture;
if ($results =~ /^Verses containing "$search"-- (.*) -- .*$/) {
my @verses = split(/ ; /, $1);
for (my $i = $searchInd; $i < $searchInd+10; $i++){
if ($verses[$i] =~ /^([\w ]+?) (\d{1,3}):(\d{1,3})$/) {
$scripture .= "".`diatheke -b $tr -k $&`."
\n";
} else {
die "Malformed search result: $verses[$i]";
}
}
$scripture .= "Search Results:
\n";
for (my $i = 0; $i < scalar(@verses); $i += 10) {
if ($searchInd == $i) {
$scripture .= "- $i
\n";
} else {
$scripture .= "- $i
\n";
}
}
$scripture .= "
";
} else {
$scripture = "No results found
";
}
$tpl->assign({
THEME => $day ? "day" : "night",
FONT => "sans-serif",
PREVPARAMS => "",
NEXTPARAMS => "",
TRANSLATIONS => $selectTr,
PASSAGE => "Search: $search",
BOOKS => $selectBk,
CHAPTER => "",
SCRIPTURE => $scripture,
});
} else {
my $scripture = `diatheke -b $tr -m 1000 -k $book$begin-$end`;
$scripture =~ s/[\w ]+ \d+:(\d+): /\$1<\/span>/mg;
$scripture =~ s/[\w ]+ \d+:(\d+): /$1<\/span>/mg;
$scripture = "".$scripture;
my ($prevBk, $prevCh) = validCh($book, $begin-1);
my ($nextBk, $nextCh) = validCh($book, $begin+1);
$tpl->assign({
THEME => $day ? "day" : "night",
FONT => "sans-serif",
PREVPARAMS => "t=$tr&b=$prevBk&c=$prevCh",
NEXTPARAMS => "t=$tr&b=$nextBk&c=$nextCh",
TRANSLATIONS => $selectTr,
PASSAGE => getBook($book, $lang)." $begin",
AUDIO => "$tr/$book".sprintf("%03d", $begin).".mp3",
BOOKS => $selectBk,
CHAPTER => $end,
SCRIPTURE => $scripture,
});
}
$tpl->parse(MAIN => "main");
$tpl->print();
### TODO: Combine css/javascript into one massive html file
### TODO: datauri base64 encode images, fonts
### Maybe? Expires header
### TODO: Parallel Bible ###
### TODO: Strong's Numbers ###
### Tooltips on hover
### TODO: Words of Jesus in red ###
### TODO: Greek/Hebrew Interlinear ###
### TODO: Search ###
### Show context of each verse
### TODO: Audio Bible ###
### TODO: Offline Access ###
### TODO: Bible verse Tooltips on hover
### TODO: Support cross-references
### TODO: Dictionary
### TODO: Bookmarks
### TODO: Compare how many versions render one single verse
### Different methods for sharing
### Reading plan idea:
### Keep track of every book and chapter read
### Based on frequency, use green/yellow/red higlighting
### to tell user what books he should read
#if ($query =~ /day=([01])/) {
# $day = $1;
#} else {
# ### check cookies, then fall back 1 ###
# $day = 1;
#}
#if ($query =~ /size=(\d{1,2})/) {
# $size = $1;
#} else {
# ### check cookies, then fall back 1 ###
# $size = 10;
#}
# my $styles = "
# html {
# font-size: ".($size*100/16)."%;
# }
# ";
#