App-Phoebe

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

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 section of
`phoebe`, 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).

## Installing Perl

If you are on GNU/Linx or macOS, I recommend installing from
[Perlbrew](https://perlbrew.pl/). Each Perl installation comes with its own

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 $verbose;
	$command =~ s/\\\\/\n/g;
	my $bytes = uri_escape(encode_utf8($command));

script/phoebe  view on Meta::CPAN

  'port=i@' => \&host_setup,
  '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, @port);

  sub host_setup {
    my ($opt, $val) = @_;
    if ($opt eq 'host') {
      push @host, map { decode(locale => $_) } $val;
      return;
    } elsif ($opt eq 'port') {
      push @port, $val;
      return;
    } elsif ($opt eq 'no_cert') {
      push @port, 1965 unless @port;
      if (not @host and not $server->{host}->{'localhost'}) {
	$server->{host}->{'localhost'} = 1;
	$server->{port}->{'localhost'} = [@port];
      }

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 $cert_file = [undef, "t/cert.pem", "t/cert2.pem"]->[$cert];
  my $key_file = [undef, "t/key.pem", "t/key2.pem"]->[$cert];
  my ($header, $mimetype, $encoding, $buffer);



( run in 1.193 second using v1.01-cache-2.11-cpan-ceb78f64989 )