#!perl
use lib '.';
use CGI::Carp qw(fatalsToBrowser);
use CGI;
use Jcode;
my $title = 'TinyTiny';
my $data_dir = './data';
my $top_page = 'トップページ';
my $new_page = '(新規ページ)';
&main;
sub main {
my $query = CGI->new;
my $mode = &initialize($query);
my $html = &$mode($query);
&output($query, $mode, $html) if (defined($html));
}
sub initialize {
my $query = shift;
my $mode = $query->param('mode');
my $page = $query->param('page');
if ($mode eq 'top') { ($mode, $page) = ('show', $top_page); }
elsif ($mode eq 'add') { ($mode, $page) = ('edit', $new_page); }
elsif ($mode eq 'list') { $page = ''; }
$mode = 'show' unless (grep { $_ eq $mode } qw(show list edit save));
$page = $top_page unless (defined($page));
$page = jcode($page)->euc;
$query->param(-name => 'mode', -value => $mode); # (2)
$query->param(-name => 'page', -value => $page); # (2')
return $mode;
}
sub output {
my ($query, $mode, $html) = @_;
my $url = $query->url;
my $page = $query->param('page');
my $page_url = &encodeURL($page);
my $style = 'padding: 3px; text-align: right; background-color: #dddddd;';
my $title = length($page) ? "$title - " . CGI::escapeHTML($page) : $title;
print $query->header('-charset' => 'EUC-JP'), $query->start_html(-title => $title), "\n";
print "
$title
\n";
my @modes = map { "[$_]" } ('top', 'list', 'add');
if ($mode eq 'show') {
push(@modes, "[edit]"); # (3)
} elsif ($mode eq 'edit' or $mode eq 'save') {
push(@modes, "[show]"); # (3')
}
print qq() . join(' ', @modes) . "
\n";
print $html;
print $query->end_html;
}
sub show {
my $query = shift;
my $text = CGI::escapeHTML(&page_read($query));
$text = jcode('(ページが未作成です)')->euc if (not defined($text));
$text =~ s/\r?\n/
\n/g;
$text =~ s/\t/ /g;
$text =~ s/( +)/sprintf('%s<\/span>', length($1) * 0.5, $1)/ge;
my $re_wiki = '\[\[.*?\]\]'; # (4)
my $re_bracket = '([A-Z][a-z]+){2,}';
my $re_url = 's?https?:\\/\\/[-_.!~*\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+';
$text =~ s/($re_wiki|$re_bracket|$re_url)/&conv_to_link($query, $1)/goe; # (4')
return $text;
}
sub conv_to_link {
my $query = shift;
my $link = shift;
if ($link =~ /^s?https?:/) {
$link = CGI::escapeHTML($link);
return "$link";
} else {
$link =~ s/^\[\[(.*)\]\]$/$1/;
return sprintf('%s', $query->url, &encodeURL($link), CGI::escapeHTML($link));
}
}
sub edit {
my $query = shift;
my $text = &page_read($query);
my $html = $query->start_form();
$html .= $query->textarea(-name=>'text', -default=>$text, -rows=>15, -columns=>60) . $query->br;
$html .= $query->textfield(-name=>'page'); # (5)
$html .= $query->submit(-name=>'mode', -value=>'save');
$html .= $query->end_form();
return $html;
}
sub save {
my $query = shift;
my $result = &page_write($query);
return CGI::escapeHTML($result);
}
sub list {
my $query = shift;
my $html = "\n";
my $url = $query->url;
foreach my $page (&get_page_list()) { # (6)
my ($page_html, $page_url) = (CGI::escapeHTML($page), &encodeURL($page));
$html .= qq(| $page_html | [show] | [edit] |
\n);
}
return "\n";
}
sub page_read {
my $query = shift;
my $file = &get_file_name($query->param('page')) or return undef; # (7)
my $text = undef;
if (-f $file and open(IN, $file)) {
local $/ = undef;
$text = ;
close(IN);
}
return $text;
}
sub page_write {
my $query = shift;
my $text = $query->param('text');
my $file = &get_file_name($query->param('page')) or return undef; # (7')
my $result = "ページを更新できませんでした。";
if (defined($text) and length($text)) {
if (open(OUT, ">$file")) {
$text =~ s/(:?\x0D\x0A|\x0D|\x0A)/\n/g;
print OUT jcode($text)->euc;
close(OUT);
$result = "ページが更新されました。";
}
} elsif (unlink($file)) {
$result = "ページが削除されました。";
}
return jcode($result)->euc;
}
sub encodeURL {
my $str = shift;
$str =~ s/(\W)/'%' . unpack('H2', $1)/eg;
return $str;
}
sub get_file_name {
my $page = shift;
$page = (defined($page) and length($page)) ? jcode($page)->euc : undef;
return undef if ($page eq undef or $page eq $new_page);
$page = &encodeURL($page);
return "$data_dir/$page";
}
sub get_page_name {
my $file = shift;
return undef unless (defined($file) and $file =~ s/^\Q$data_dir\/\E//);
$file =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
return $file;
}
sub get_page_list {
my @pages = grep {-f $_} glob("$data_dir/*");
@pages = grep { defined($_) } map { $_ = &get_page_name($_) } @pages;
@pages = sort { lc($a) cmp lc($b) or $a cmp $b } @pages;
return @pages;
}