App-phoebe
view release on metacpan or search on metacpan
install the following dependencies:
- [Algorithm::Diff](https://metacpan.org/pod/Algorithm%3A%3ADiff), or `libalgorithm-diff-xs-perl`
- [File::ReadBackwards](https://metacpan.org/pod/File%3A%3AReadBackwards), or `libfile-readbackwards-perl`
- [File::Slurper](https://metacpan.org/pod/File%3A%3ASlurper), or `libfile-slurper-perl`
- [Mojolicious](https://metacpan.org/pod/Mojolicious), or `libmojolicious-perl`
- [IO::Socket::SSL](https://metacpan.org/pod/IO%3A%3ASocket%3A%3ASSL), or `libio-socket-ssl-perl`
- [Modern::Perl](https://metacpan.org/pod/Modern%3A%3APerl), or `libmodern-perl-perl`
- [URI::Escape](https://metacpan.org/pod/URI%3A%3AEscape), or `liburi-escape-xs-perl`
- [Net::IDN::Encode](https://metacpan.org/pod/Net%3A%3AIDN%3A%3AEncode), or `libnet-idn-encode-perl`
- [Encode::Locale](https://metacpan.org/pod/Encode%3A%3ALocale), or `libencode-locale-perl`
I'm going to be using `curl` and `openssl` in the ["Quickstart"](#quickstart) instructions,
so you'll need those tools as well. And finally, when people download their
data, the code calls `tar` (available from packages with the same name on
Debian derived systems).
The `update-readme.pl` script I use to generate `README.md` also requires some
libraries:
- [Pod::Markdown](https://metacpan.org/pod/Pod%3A%3AMarkdown), or `libpod-markdown-perl`
ijirait --cert=cert.pem --key=key.pem --stream \
--url=gemini://campaignwiki.org/play/ijirait/stream
Here are the Debian package names to satisfy the dependencies. Use `cpan` or
`cpanm` to install them.
- [Modern::Perl](https://metacpan.org/pod/Modern%3A%3APerl) from `libmodern-perl-perl`
- [Mojo::IOLoop](https://metacpan.org/pod/Mojo%3A%3AIOLoop) from `libmojolicious-perl`
- [Term::ReadLine::Gnu](https://metacpan.org/pod/Term%3A%3AReadLine%3A%3AGnu) from `libterm-readline-gnu-perl`
- [URI::Escape::XS](https://metacpan.org/pod/URI%3A%3AEscape%3A%3AXS) from `liburi-escape-xs-perl`
- [Encode::Locale](https://metacpan.org/pod/Encode%3A%3ALocale) from `libencode-locale-perl`
- [Text::Wrapper](https://metacpan.org/pod/Text%3A%3AWrapper) from `libtext-wrapper-perl`
# phoebe-ctl
This script helps you maintain your Phoebe installation.
- **--wiki\_dir=**_DIR_
This the wiki data directory to use; the default is either the value of the
`GEMINI_WIKI_DATA_DIR` environment variable, or the `./wiki` subdirectory. Use
script/ijirait view on Meta::CPAN
=over
=item L<Modern::Perl> from C<libmodern-perl-perl>
=item L<Mojo::IOLoop> from C<libmojolicious-perl>
=item L<Term::ReadLine::Gnu> from C<libterm-readline-gnu-perl>
=item L<URI::Escape> from C<liburi-escape-xs-perl>
=item L<Encode::Locale> from C<libencode-locale-perl>
=item L<Text::Wrapper> from C<libtext-wrapper-perl>
=back
=cut
use Modern::Perl '2018';
use Mojo::IOLoop;
use Pod::Text;
script/ijirait view on Meta::CPAN
tls => 1,
tls_cert => $cert,
tls_key => $key,
tls_options => { SSL_verify_mode => 0x00 }} => sub {
my ($loop, $err, $stream) = @_;
# 1h timeout (for chat)
$stream->timeout(3600);
$stream->on(read => sub {
my ($stream, $bytes) = @_;
my $text = to_text(decode_utf8($bytes));
print encode(locale => $text) });
$stream->on(close => sub {
say "Connection closed";
exit });
# Write request to the server
$stream->write("$url\r\n")});
# Start event loop if necessary
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
}
sub play {
script/ijirait view on Meta::CPAN
my @queue = qw(look);
# start read loop for saying stuff
my $term = Term::ReadLine->new("Ijirait");
my $prompt = "> ";
my $OUT = $term->OUT || \*STDOUT;
while (defined ($_ = shift(@queue) || $term->readline($prompt))) {
exit if $_ eq "quit";
# Handle <
my $command = decode(locale => $_);
if ($command =~ /^(.*?)\s*<\s*([^|<>]+?)\s*$/s) {
if (-f $2) {
$command = $1 . " " . decode_utf8(read_text($2));
} else {
say "Cannot read $2";
next;
}
}
# Handle | >
my $shell_command;
script/ijirait view on Meta::CPAN
return say $err unless $stream;
$stream->on(read => sub {
my ($stream, $bytes) = @_;
if ($shell_command) {
open(my $fh, $shell_command)
or die "Can't run $shell_command: $!";
$bytes =~ s/^2.*\n//; # skip header
print $fh $bytes;
} else {
my $text = to_text(decode_utf8($bytes));
print encode(locale => $text);
}
if ($bytes =~ m!^30 /play/ijirait(?:/([a-z]+))?(?:\?(.*))?!) {
my $command = ($1 || "look") . ($2 ? " " . decode_utf8 uri_unescape($2) : "");
$command =~ s/[[:cntrl:]]+//g;
push(@queue, $command);
}});
# Write request to the server
say "$talk_url?$command" if $debug;
$command =~ s/\\\\/\n/g;
my $bytes = uri_escape(encode_utf8($command));
script/phoebe view on Meta::CPAN
=item * L<Mojolicious>, or C<libmojolicious-perl>
=item * L<IO::Socket::SSL>, or C<libio-socket-ssl-perl>
=item * L<Modern::Perl>, or C<libmodern-perl-perl>
=item * L<URI::Escape>, or C<liburi-escape-xs-perl>
=item * L<Net::IDN::Encode>, or C<libnet-idn-encode-perl>
=item * L<Encode::Locale>, or C<libencode-locale-perl>
=back
I'm going to be using F<curl> and F<openssl> in the L</Quickstart> instructions,
so you'll need those tools as well. And finally, when people download their
data, the code calls C<tar> (available from packages with the same name on
Debian derived systems).
The F<update-readme.pl> script I use to generate F<README.md> also requires some
libraries:
script/phoebe view on Meta::CPAN
'port=i@', # same ports for all hosts!
'wiki_dir=s',
'wiki_space=s@' => \&utf8_list_item,
'wiki_token=s@' => \&utf8_list_item,
'wiki_page=s@' => \&utf8_list_item,
'wiki_main_page=s' => \&utf8_item,
'wiki_mime_type=s@',
'wiki_page_size_limit=i')
or die("Error in command line arguments\n");
sub utf8_list_item { my ($key, $value) = @_; push(@{$server->{$key}}, decode(locale => $value)) };
sub utf8_item { my ($key, $value) = @_; $server->{$key} = decode(locale => $value) };
{
# use a block so that these variables stay local
my ($cert_file, $key_file, @host);
sub host_setup {
my ($opt, $val) = @_;
if ($opt eq 'host') {
push @host, decode(locale => $val);
return;
};
die "$val does not exist\n" unless -f $val;
if ($opt eq 'cert_file') { $cert_file = $val }
elsif ($opt eq 'key_file') { $key_file = $val }
if ($cert_file and $key_file) {
if (not @host) {
$server->{host}->{'localhost'} = 1;
$server->{cert_file}->{'localhost'} = $cert_file;
$server->{key_file}->{'localhost'} = $key_file;
script/spartan view on Meta::CPAN
# create client
Mojo::IOLoop->client({address => $host, port => $port} => sub {
my ($loop, $err, $stream) = @_;
die $err if $err;
# 1h timeout (for chat)
$stream->timeout(3600);
my ($header, $mimetype, $encoding);
$stream->on(read => sub {
my ($stream, $bytes) = @_;
if ($header and $encoding) {
print encode(locale => decode($encoding, $bytes));
} elsif ($header) {
print encode(locale => $bytes);
} else {
($header) = $bytes =~ /^(.*?)\r\n/;
warn "$header\n";
if ($header =~ /^2\d* (?:text\/\S+)?(?:; *charset=(\S+))?$/g) {
# empty, or text without charset defaults to UTF-8
$encoding = $1 || 'UTF-8';
}
$bytes =~ s/^(.*?)\r\n//; # remove header
if ($encoding) {
say encode(locale => decode($encoding, $bytes));
} else {
print encode(locale => $bytes);
}
}});
# Write request
my $size = length($data);
warn "Requesting $host $path $size\n" if $verbose;
$stream->write("$host $path $size\r\n$data")});
# Start event loop if necessary
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
t/encoding.t view on Meta::CPAN
$page = query_gemini("$base/page/$encoded_name");
like($page, qr/^20 text\/gemini; charset=UTF-8\r\n# $name\n$text/, "Text saved");
my $punycode = domain_to_ascii($idn);
$base = encode_utf8 "gemini://$punycode:$port";
$titan = encode_utf8 "titan://$punycode:$port";
SKIP: {
skip "Locale cannot handle test data", 3 unless decode(locale => encode(locale => $name)) eq $name;
$page = query_gemini("$base/page/$encoded_name");
like($page, qr/# æ¥æ¬èª\nThis page does not yet exist/, "International Domain Name");
$page = query_gemini("$titan/raw/$encoded_name;size=$length;mime=text/plain;token=hello", $encoded_text);
like($page, qr/^30 $base\/page\/$encoded_name\r$/, "Titan Text");
$page = query_gemini("$base/page/$encoded_name");
like($page, qr/^20 text\/gemini; charset=UTF-8\r\n# $name\n$text/, "Text saved");
}
if (!defined $pid) {
die "Cannot fork: $!";
} elsif ($pid == 0) {
say "This is the Phoebe server listening on port $port...";
use Config;
my $secure_perl_path = $Config{perlpath};
my @args = ("blib/script/phoebe",
# The test files containing hostnames are UTF-8 encoded, thus
# $host and @host are unicode strings. Command line parsing
# expects them encoded in the current locale, however.
(map { "--host=" . encode(locale => $_) } @hosts),
"--port=$port",
"--log_level=warn", # set to debug if you are bug hunting?
"--cert_file=t/cert.pem",
"--key_file=t/key.pem",
"--wiki_dir=$dir",
"--wiki_mime_type=image/jpeg",
(map { "--wiki_page=" . encode(locale => $_) } @pages),
(map { "--wiki_space=" . encode(locale => $_) } @spaces));
exec($secure_perl_path, @args) or die "Cannot exec: $!";
}
sub query_gemini {
my $query = shift;
my $text = shift;
my $cert = shift // 1; # suppress use of client certificate in the test
my ($header, $mimetype, $encoding, $buffer);
# create client
( run in 0.997 second using v1.01-cache-2.11-cpan-ceb78f64989 )