App-Phoebe
view release on metacpan or search on metacpan
lib/App/Phoebe/Oddmuse.pm view on Meta::CPAN
$stream->write("<link href=\"$link\"/>\n");
$stream->write("<id>$link</id>\n");
my $summary = quote_html(oddmuse_gemini_text($stream, $host, $space, $data->{description}, $id));
$stream->write(encode_utf8 "<content type=\"text\">$summary</content>\n") if $summary;
$stream->write("<updated>$data->{'last-modified'}</updated>\n");
$stream->write("</entry>\n");
};
$stream->write("</feed>\n");
}
sub oddmuse_comment {
my $stream = shift;
my $host = shift;
my $space = shift;
my $id = shift;
my $query = shift; # token or comment
my $port = port($stream);
if (not $id) {
$log->debug("The URL lacks a page name");
result($stream, "59", "The URL lacks a page name");
return;
}
my $name = oddmuse_fingerprint_name($stream, $host, $query);
return unless defined $name;
if (not $query) {
result($stream, "10", "Short comment");
return;
}
$id = "Comments_on_$id" unless $id =~ /^Comments_on_/;
my $token = $oddmuse_wiki_tokens{$host};
$token = $server->{wiki_token}->[0] if not $token and $server->{wiki_token};
my $ua = Mojo::UserAgent->new;
my $tx = $ua->post(
$oddmuse_wikis{$host}
=> {'X-Forwarded-For' => $stream->handle->peerhost}
=> form => {
title => $id,
ns => $space,
aftertext => $query,
username => $name,
answer => $token,
gemini => 1 });
$log->debug("Got " . $tx->result->code . " response");
if ($tx->result->code == 302) {
my $url = "gemini://$host:$port";
$url .= "/$space" if $space;
result($stream, "30", "$url/page/" . uri_escape_utf8($id) . "");
return;
}
$stream->write("59 Got HTTP code " . $tx->result->code . " " . $tx->result->message
. " (" . $tx->req->url->to_abs . " " . $tx->req->params . ")\r\n");
}
# If the fingerprint exists in our file, no need to ask for the $token; it
# expires after a day (24 * 60 * 60 seconds). If no fingerprint is found, ask
# for a cert.
sub oddmuse_fingerprint_name {
my $stream = shift;
my $host = shift;
my $token = shift;
# This requires SSL_verify_mode => SSL_VERIFY_PEER and SSL_verify_callback =>
# \&verify_fingerprint (which must not reject self-signed certificates).
my $fingerprint = $stream->handle->get_fingerprint();
if (not $fingerprint) {
result($stream, "60", "You need a client certificate with a common name to edit this wiki");
return;
}
my $dir = $server->{wiki_dir};
my @lines;
my $now = time();
# Read the known fingerprint from the file.
my %fingerprints;
my $file = "$dir/fingerprints";
%fingerprints = split(/\s+/, read_text($file)) if -e $file;
# Forget about fingerprints older than 10min.
for my $fp (keys %fingerprints) {
delete $fingerprints{$fp} if $fingerprints{$fp} > $now + 600;
}
my @tokens;
push(@tokens, $oddmuse_wiki_tokens{$host}) if $oddmuse_wiki_tokens{$host};
push(@tokens, @{$server->{wiki_token}}) unless @tokens;
if (not $fingerprints{$fingerprint}) {
if (not $token) {
result($stream, "10", "Token required to edit this wiki");
} elsif (not grep { $token eq $_ } @tokens) {
result($stream, "59", "Wrong token");
} else {
result($stream, "10", "Short comment");
$fingerprints{$fingerprint} = $now;
}
# Save new or updated fingerprint timestamp.
write_text($file, join("\n", map { "$_ $fingerprints{$_}" } keys %fingerprints));
# Return undefined so that the user needs to react to the message above.
return;
}
# Fingerprint found!
$fingerprints{$fingerprint} = $now;
# Save new or updated fingerprint timestamp.
write_text($file, join("\n", map { "$_ $fingerprints{$_}" } keys %fingerprints));
# User wants to provide no name: use "" so that we have a defined name.
return ($stream->handle->peer_certificate('cn') || "");
}
( run in 0.447 second using v1.01-cache-2.11-cpan-99c4e6809bf )