App-phoebe
view release on metacpan or search on metacpan
lib/App/Phoebe/WebComments.pm view on Meta::CPAN
use App::Phoebe::WebComments;
=cut
package App::Phoebe::WebComments;
use App::Phoebe qw(@footer @extensions @request_handlers $server $log port space
host_regex space_regex quote_html wiki_dir with_lock
bogus_hash to_url);
use App::Phoebe::Web qw(handle_http_header http_error);
use Modern::Perl;
use URI::Escape;
use File::Slurper qw(write_text);
use Encode qw(decode_utf8 encode_utf8);
use File::Slurper qw(read_text);
use utf8;
push(@footer, \&add_comment_web_link_to_footer);
sub add_comment_web_link_to_footer {
my ($self, $host, $space, $id, $revision, $scheme) = @_;
# only leave comments on current comment pages
return "" if $revision;
$space = "/" . uri_escape_utf8($space) if $space;
$space //= "";
return "=> $space/page/" . uri_escape_utf8("Comments on $id") . " Comments"
if $id !~ /^Comments on / and not grep { $_ eq \&add_comment_link_to_footer } @footer;
return "=> $space/do/comment/" . uri_escape_utf8($id) . " Leave a short comment" if $scheme eq "html";
}
unshift(@request_handlers, '^POST .* HTTP/1\.[01]$' => \&handle_http_header);
push(@extensions, \&process_comment_requests_via_http);
sub process_comment_requests_via_http {
my ($stream, $url, $headers, $buffer) = @_;
my $hosts = host_regex();
my $spaces = space_regex();
my $port = port($stream);
my ($host, $space, $id, $token, $query);
if (($space, $id) = $url =~ m!^GET (?:/($spaces))?/do/comment/([^/#?]+) HTTP/1\.[01]$!
and ($host) = $headers->{host} =~ m!^($hosts)(?::$port)$!) {
serve_comment_via_http($stream, $host, space($stream, $host, $space), decode_utf8(uri_unescape($id)));
return 1;
} elsif (($space, $id) = $url =~ m!^POST (?:/($spaces))?/do/comment/([^/#?]+) HTTP/1\.[01]$!
and ($host) = $headers->{host} =~ m!^($hosts)(?::$port)$!) {
append_comment_via_http($stream, $host, space($stream, $host, $space), decode_utf8(uri_unescape($id)), $buffer);
return 1;
}
return 0;
}
sub serve_comment_via_http {
my ($stream, $host, $space, $id) = @_;
$log->info("Serve comments for $id via HTTP");
$stream->write("HTTP/1.1 200 OK\r\n");
$stream->write("Content-Type: text/html\r\n");
$stream->write("\r\n");
$stream->write("<!DOCTYPE html>\r\n");
$stream->write("<html>\r\n");
$stream->write("<head>\r\n");
$stream->write("<meta charset=\"utf-8\">\r\n");
$stream->write(encode_utf8 "<title>" . quote_html($id) . "</title>\r\n");
$stream->write("<link type=\"text/css\" rel=\"stylesheet\" href=\"/default.css\"/>\r\n");
$stream->write("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n");
$stream->write("</head>\r\n");
$stream->write("<body>\r\n");
$stream->write(encode_utf8 "<h1>" . quote_html($id) . "</h1>\r\n");
$stream->write("<form method=\"POST\">\r\n");
$stream->write("<p><label for=\"token\">Token:</label>\r\n");
$stream->write("<br><input type=\"text\" id=\"token\" name=\"token\" required>\r\n");
$stream->write("<p><label for=\"comment\">Comment:</label>\r\n");
$stream->write("<br><textarea style=\"width: 100%; height: 10em;\" id=\"comment\" name=\"comment\" required></textarea>\r\n");
$stream->write("<p><input type=\"submit\" value=\"Save\">\r\n");
$stream->write("</form>\r\n");
$stream->write("</body>\r\n");
$stream->write("</html>\r\n");
}
sub append_comment_via_http {
my ($stream, $host, $space, $id, $buffer) = @_;
$log->info("Save comments for $id via HTTP");
my %params;
for (split(/&/, $buffer)) {
my ($key, $value) = map { s/\+/ /g; decode_utf8(uri_unescape($_)) } split(/=/, $_, 2);
$params{$key} = $value;
}
$log->debug("Parameters: " . join(", ", map { "$_ => '$params{$_}'" } keys %params));
my $token = quotemeta($params{token}||"");
my @tokens = @{$server->{wiki_token}};
push(@tokens, @{$server->{wiki_space_token}->{$space}})
if $space and $server->{wiki_space_token}->{$space};
return http_error($stream, "Token required") if not $token and @tokens;
return http_error($stream, "Wrong token") if not grep(/^$token$/, @tokens);
my $comment = $params{comment};
return http_error($stream, "Comment required") if not $comment;
my $dir = wiki_dir($host, $space);
my $file = "$dir/page/$id.gmi";
my $text;
if (-e $file) {
$text = read_text($file) . "\n\nð¨ " . $comment;
} else {
$text = $comment;
}
with_lock($stream, $host, $space, sub { write_page_for_http($stream, $host, $space, $id, $text) } );
}
sub write_page_for_http {
my $stream = shift;
my $host = shift;
my $space = shift;
my $id = shift;
my $text = shift;
$log->info("Writing page $id");
my $dir = wiki_dir($host, $space);
my $file = "$dir/page/$id.gmi";
my $revision = 0;
if (-e $file) {
my $old = read_text($file);
if ($old eq $text) {
$log->info("$id is unchanged");
my $message = to_url($stream, $host, $space, "page/$id", "https");
( run in 1.699 second using v1.01-cache-2.11-cpan-39bf76dae61 )