App-Phoebe

 view release on metacpan or  search on metacpan

lib/App/Phoebe/WebEdit.pm  view on Meta::CPAN

# -*- mode: perl -*-
# Copyright (C) 2017–2021  Alex Schroeder <alex@gnu.org>

# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.

=head1 NAME

App::Phoebe::WebEdit - allow edits of a Phoebe wiki via the web

=head1 DESCRIPTION

This package allows visitors on the web to edit your pages.

There is no configuration. Simply add it to your F<config> file:

    use App::Phoebe::WebEdit;

=cut

package App::Phoebe::WebEdit;
use App::Phoebe::Web qw(handle_http_header http_error);
use App::Phoebe qw(@footer @extensions @request_handlers @main_menu $server $log
		   port space host_regex space_regex text with_lock wiki_dir
		   bogus_hash to_url quote_html);
use Encode qw(decode_utf8 encode_utf8);
use File::Slurper qw(read_text write_text read_dir);
use Modern::Perl;
use URI::Escape;

unshift(@request_handlers, '^POST .* HTTP/1\.[01]$' => \&handle_http_header);

# edit from the web

push(@footer, \&add_edit_link_to_footer);

sub is_editable {
  my ($space) = @_;
  my $editable = { return test => 1, gemini => 1 };
  return $editable->{$space};
}

sub add_edit_link_to_footer {
  my ($stream, $host, $space, $id, $revision, $format) = @_;
  # only add the edit links to the web UI of the test space
  # return if not $space or not is_editable($space);
  return "" if $revision or not $id or $format ne "html";
  $id = uri_escape_utf8($id);
  if ($space) {
    $space = uri_escape_utf8($space);
    return "=> /$space/do/edit/$id Edit";
  } else {
    return "=> /do/edit/$id Edit";
  }
}

# note that the requests handled here must be protected in
# App::Phoebe::RegisteredEditorsOnly!
push(@extensions, \&process_edit_requests);

sub process_edit_requests {
  my ($stream, $request, $headers, $buffer) = @_;
  my $host_regex = host_regex();
  my $spaces = space_regex();
  my $port = port($stream);
  my ($host, $space, $id, $token, $query);
  if (($space, $id) = $request =~ m!^GET (?:/($spaces))?/do/edit/([^/#?]+) HTTP/1\.[01]$!
      and is_editable($space)
      and ($host) = $headers->{host} =~ m!^($host_regex)(?::$port)$!) {
    serve_edit_via_http($stream, $host, space($stream, $host, $space), decode_utf8(uri_unescape($id)));
  } elsif (($space, $id) = $request =~ m!^POST (?:/($spaces))?/do/edit/([^/#?]+) HTTP/1\.[01]$!
	   and is_editable($space)
	   and ($host) = $headers->{host} =~ m!^($host_regex)(?::$port)$!) {
    save_edit_via_http($stream, $host, space($stream, $host, $space), decode_utf8(uri_unescape($id)), $headers, $buffer);
  } else {
    return 0;
  }
  return 1;
}

sub serve_edit_via_http {
  my ($stream, $host, $space, $id) = @_;
  $log->info("Serve edit page 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>\n");
  $stream->write("<html>\n");



( run in 0.316 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )