# -*- cperl -*- package POE::Component::IRC::Plugin::NoPaste::Httpd::Index; use strict; use warnings; use POE; use POE::Component::IRC::Plugin::NoPaste::Httpd; use POE::Component::IRC::Plugin::NoPaste::StaticFile; use POE::Component::IRC::Plugin::NoPaste::Pager; use URI::QueryParam; use Locale::TextDomain qw(pci-nopaste); use HTTP::Status; use Socket; use Time::Format qw(%time); use Encode qw(from_to); use constant NICK_LIMIT => 20; use constant TITLE_LIMIT => 100; use constant BODY_LIMIT => 500 * 1024; sub handler { my ($this, $req, $resp) = @_; if ($req->uri->path =~ m!^/nopaste/(.+?)/?$! and $this->{nopaste}{id_to_channel}{$1}) { return index_handler( $this, $req, $resp, $this->{nopaste}{id_to_channel}{$1}); } elsif ($req->uri->path =~ m!^/post/(.+?)/?$! and $this->{nopaste}{id_to_channel}{$1}) { return post_handler( $this, $req, $resp, $this->{nopaste}{id_to_channel}{$1}); } else { return notfound_handler(@_); } } sub index_handler { my ($this, $req, $resp, $ch, $error) = @_; local $ENV{LANGUAGE} = $ch->{locale}; my $t = POE::Component::IRC::Plugin::NoPaste::Template->new( -data => static_file('tmpl/index.html')); $t->expand( lang => $ch->{locale}, title => "NoPaste :: $ch->{name}", ); my ($ptr) = gethostbyaddr( inet_aton($req->{connection}->remote_ip), AF_INET); my @writable = $this->{nopaste}->pickup_writable($ch->{id}, $ptr); my @readable = $this->{nopaste}->pickup_readable($ch->{id}, $ptr); if (@writable or $ch->{restriction}{write} eq 'any') { if ($error) { $_ = $error; s!\n!
!g; $t->writable->error->add(error => $_); } $t->writable->expand( channel_id => $ch->{id}, l18n_name => __"Name", ); if ($ch->{restriction}{write} ne 'any') { if (@writable ==1) { $t->writable->restricted->only_one->add( nick => $writable[0], ); } else { foreach my $nick (@writable) { $t->writable->restricted->multiple->entry->add( nick => $nick, ); } $t->writable->restricted->multiple->add; } $t->writable->restricted->add; } else { $t->writable->not_restricted->add; } $t->writable->add( l18n_title => __"Title", l18n_body => __( # body of the post "Body", ), l18n_paste => __"Paste", ); # set the default values my $q = $req->uri->clone; if (not $q->query_param('nick') and @writable == 1) { $q->query_param(nick => $writable[0]); } $t->setform($q => 'post'); } else { my $msg = $this->{nopaste}->gen_unwritable_error($ch); $msg =~ s!\n!
!g; $t->not_writable->add( error => $msg, ); } if (@readable or $ch->{restriction}{read} eq 'any') { my $pager = POE::Component::IRC::Plugin::NoPaste::Pager->new( fetch => { sql => q{ SELECT * FROM post WHERE channel_id = ? ORDER BY posted_time DESC }, placeholder => [$ch->{id}], dbh => $this->{nopaste}{db}->dbh, }, page_to_show => scalar $req->uri->query_param('page'), pagenums_limit => 20, items_per_page => 20, show_meta => sub { my %meta = @_; if ($meta{page} == 1) { $t->readable->prev->nolink->add; } else { $t->readable->prev->link->add( page => $meta{page} - 1, ); } $t->readable->prev->add; foreach my $i ($meta{pagelink_begin} .. $meta{pagelink_end}) { if ($i == $meta{page}) { $t->readable->pages->page->nolink->add( page => $i, ); } else { $t->readable->pages->page->link->add( page => $i, ); } $t->readable->pages->page->add; } $t->readable->pages->add; if ($meta{page} == $meta{last_page}) { $t->readable->next->nolink->add; } else { $t->readable->next->link->add( page => $meta{page} + 1, ); } $t->readable->next->add; }, show_content => sub { my $row = shift; $t->readable->list_data->add( id => $row->{post_id}, title => $row->{title}, name => $row->{nick}, body => $row->{body}, timestamp => $time{'yyyy-mm-dd hh:mm:ss', $row->{posted_time}}, ); }, no_content => sub { $t->readable->list_nodata->add( l18n_nodata => __"There are no entries currently.", ); }, ); $pager->execute; $t->readable->add( l18n_title => __"Title", l18n_name => __"Name", l18n_timestamp => __"Time Stamp", ); } else { my $msg = $this->{nopaste}->gen_unreadable_error($ch); $msg =~ s!\n!
!g; $t->not_readable->add( error => $msg, ); } $resp->content($t->str); return RC_OK; } sub post_handler { my ($this, $req, $resp, $ch) = @_; my $nick = $req->uri->query_param('nick'); my $title = $req->uri->query_param('title'); my $body = $req->uri->query_param('body'); local $ENV{LANGUAGE} = $ch->{locale}; my @error; if (not defined $nick or not length $nick) { push @error, __"Please don't omit your name."; } elsif (length($nick) > NICK_LIMIT) { push @error, __x("Please shorten your name up to {n} bytes.", n => NICK_LIMIT); } if (not defined $title or not length $title) { push @error, __"Please don't omit the title."; } elsif (length($title) > TITLE_LIMIT) { push @error, __x("Please shorten the title up to {n} bytes.", n => TITLE_LIMIT); } if (not defined $body or not length $body) { push @error, __"Please don't omit the body."; } elsif (length($body) > BODY_LIMIT) { push @error, __x("Please shorten the body up to {n} bytes.", n => BODY_LIMIT); } if (@error) { return index_handler($this, $req, $resp, $ch, join("\n", map {"* $_"} @error)); } my ($ptr) = gethostbyaddr( inet_aton($req->{connection}->remote_ip), AF_INET); my @writable = $this->{nopaste}->pickup_writable($ch->{id}, $ptr); if ($ch->{restriction}{write} eq 'any' or grep {$_ eq $nick} @writable) { my $db = $this->{nopaste}{db}; # check for duplication if ($db->dbh->selectrow_hashref(q{ SELECT * FROM post WHERE channel_id = ? AND nick = ? AND title = ? AND body = ? }, undef, $ch->{id}, $nick, $title, $body)) { return index_handler( $this, $req, $resp, $ch, __"A duplicated entry is being pasted."); } # insert it $db->dbh->do(q{ INSERT INTO post (channel_id, posted_time, nick, title, body) VALUES (? , ? , ? , ? , ? ) }, undef, $ch->{id}, time, $nick, $title, $body); # get the post id my ($post_id) = $db->dbh->selectrow_array(q{ SELECT LAST_INSERT_ROWID()}); # announce it in the channel my $name = $ch->{name}; from_to $name, 'UTF-8' => $ch->{charset}; my @msg = ( __x("{nick} pasted an entry: {title}", nick => $nick, title => $title), do { my $uri = $req->uri->clone; $uri->path("/pasted/$post_id"); $uri->query(undef); $uri->fragment(undef); $uri->as_string; }, ); foreach (@msg) { my $line = $_; from_to $line, 'UTF-8' => $ch->{charset}; $this->{nopaste}{irc}->yield( notice => $name => $line); } # redirect to the index return redirect_handler( $this, $req, $resp, "/nopaste/$ch->{id}/"); } else { return index_handler($this, $req, $resp, $ch); } } 1;