App-phoebe

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

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`

README.md  view on Meta::CPAN

    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");
}

t/test.pl  view on Meta::CPAN


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 )