Alex 'AdUser' Z
7 years ago
commit
2c58868855
8 changed files with 332 additions and 0 deletions
@ -0,0 +1,11 @@ |
|||||||
|
#!/usr/bin/env perl |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use FindBin; |
||||||
|
BEGIN { unshift @INC, "$FindBin::Bin/../lib" } |
||||||
|
|
||||||
|
# Start command line interface for application |
||||||
|
require Mojolicious::Commands; |
||||||
|
Mojolicious::Commands->start_app('CMTD'); |
@ -0,0 +1,29 @@ |
|||||||
|
package CMTD; |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious'; |
||||||
|
|
||||||
|
sub startup { |
||||||
|
my $self = shift; |
||||||
|
|
||||||
|
$self->plugin('CMTD::Helpers'); |
||||||
|
$self->plugin(Config => {file => 'cmtd.conf'}); |
||||||
|
|
||||||
|
my $r = $self->routes; |
||||||
|
|
||||||
|
$r->get('/') |
||||||
|
-> to('main#index'); |
||||||
|
|
||||||
|
$r->get('/captcha') |
||||||
|
-> to('main#captcha'); |
||||||
|
|
||||||
|
$r->get('/comments/list') |
||||||
|
-> to('main#c_list'); |
||||||
|
|
||||||
|
$r->get('/comments/add') |
||||||
|
-> to('main#c_add'); |
||||||
|
} |
||||||
|
|
||||||
|
1; |
@ -0,0 +1,105 @@ |
|||||||
|
package LDV::Comments; |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
use utf8; |
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious::Controller'; |
||||||
|
|
||||||
|
use File::Slurp qw(read_file write_file); |
||||||
|
use Mojo::URL; |
||||||
|
|
||||||
|
sub add { |
||||||
|
my ($self) = @_; |
||||||
|
|
||||||
|
eval { |
||||||
|
my $sectoken = $self->session('c_sectoken') |
||||||
|
or die("missing security token\n"); |
||||||
|
my ($ip, $upto) = ($sectoken =~ m{^([0-9a-f\.:]+)-(\d+)$}io) |
||||||
|
or die("malformed security token\n"); |
||||||
|
($upto > time()) |
||||||
|
or die("expired security token\n"); |
||||||
|
($ip eq $self->tx->remote_address) |
||||||
|
or die("remote address mismatch\n"); |
||||||
|
my $text = $self->req->param('text') |
||||||
|
or die("empty comment\n"); |
||||||
|
my $pageid = $self->_gen_pageid() |
||||||
|
or die("can't get pageid\n"); |
||||||
|
|
||||||
|
my %opts = (binmode => ':bytes'); |
||||||
|
my $comments = []; |
||||||
|
my $path = $self->app->home->rel_file("data/comments/$pageid.json"); |
||||||
|
if (-f $path) { |
||||||
|
my $json = read_file($path, %opts); |
||||||
|
$comments = $self->app->json->decode($json); |
||||||
|
} |
||||||
|
push @{ $comments }, { |
||||||
|
text => $text, time => time(), |
||||||
|
user => $self->session('username') || 'anonymous', |
||||||
|
}; |
||||||
|
write_file($path, \%opts, $self->app->json->encode($comments)); |
||||||
|
|
||||||
|
$path = $self->app->home->rel_file("data/comments/$pageid.html"); |
||||||
|
$self->stash({comments => $comments}); |
||||||
|
write_file($path, {binmode => ':utf8'}, $self->render_to_string(template => 'comments/list')); |
||||||
|
|
||||||
|
$self->render(text => 'OK'); |
||||||
|
} or do { |
||||||
|
chomp $@; |
||||||
|
$self->app->log->error($@); |
||||||
|
$@ = 'internal error' if $@ =~ m{line \d+}o; |
||||||
|
$self->res->code(400); |
||||||
|
$self->render(text => $@); |
||||||
|
}; |
||||||
|
|
||||||
|
$self->rendered(); |
||||||
|
} |
||||||
|
|
||||||
|
sub get { |
||||||
|
my ($self) = @_; |
||||||
|
|
||||||
|
eval { |
||||||
|
my $pageid = $self->_gen_pageid() |
||||||
|
or die("can't get id\n"); |
||||||
|
my $path = $self->app->home->rel_file("data/comments/$pageid.html"); |
||||||
|
if (-f $path) { |
||||||
|
my $comments = read_file($path, binmode => ':utf8'); |
||||||
|
$self->render(text => $comments); |
||||||
|
} else { |
||||||
|
$self->render(template => 'comments/none'); |
||||||
|
} 1; |
||||||
|
} or do { |
||||||
|
chomp $@; |
||||||
|
$self->app->log->error($@); |
||||||
|
$@ = 'internal error' if $@ =~ m{line \d+}o; |
||||||
|
$self->res->code(400); |
||||||
|
$self->render(text => $@); |
||||||
|
}; |
||||||
|
|
||||||
|
$self->rendered(); |
||||||
|
} |
||||||
|
|
||||||
|
sub create { |
||||||
|
my ($self) = @_; |
||||||
|
|
||||||
|
eval { |
||||||
|
die("request error\n") |
||||||
|
unless $self->req->is_xhr; |
||||||
|
my $ip = $self->tx->remote_address |
||||||
|
or die("can't find remote ip\n"); |
||||||
|
my $sectoken = sprintf "%s-%d", $ip, time() + 60 * 7; |
||||||
|
$self->session(c_sectoken => $sectoken); |
||||||
|
my $pageid = $self->_gen_pageid() |
||||||
|
or die("can't get pageid\n"); |
||||||
|
$self->stash({pageid => $pageid}); |
||||||
|
$self->render(template => 'comments/new'); |
||||||
|
} or do { |
||||||
|
chomp $@; |
||||||
|
$self->app->log->error($@); |
||||||
|
$@ = 'internal error' if $@ =~ m{line \d+}o; |
||||||
|
$self->res->code(400); |
||||||
|
$self->render(text => $@); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
1; |
@ -0,0 +1,36 @@ |
|||||||
|
package CMTD::Helpers; |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
use utf8; |
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious::Plugin'; |
||||||
|
|
||||||
|
sub register { |
||||||
|
my ($self, $app) = @_; |
||||||
|
|
||||||
|
$app->helper(referrer => sub { |
||||||
|
my ($c, $url) = @_; |
||||||
|
my $url = $c->req->headers->referrer || |
||||||
|
$c->req->param('url'); |
||||||
|
return $url; |
||||||
|
}); |
||||||
|
|
||||||
|
$app->helper(pageid => sub { |
||||||
|
my ($c, $url) = @_; |
||||||
|
return unless $url; |
||||||
|
|
||||||
|
my $u = Mojo::URL->new($url); |
||||||
|
my $site = $u->host; |
||||||
|
my $path = $u->path; |
||||||
|
$path =~ s{^/+}{}o; |
||||||
|
$path =~ s{/+$}{}o; |
||||||
|
$path =~ y{/.}{-}s; |
||||||
|
$path =~ s<\.[a-z0-9]{2,4}$><>io; |
||||||
|
my $md5 = md5_sum($path); |
||||||
|
|
||||||
|
return {site => $site, pid => $md5, path => $path}; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
1; |
@ -0,0 +1,47 @@ |
|||||||
|
package CMTD::Main; |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
use utf8; |
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious::Controller'; |
||||||
|
|
||||||
|
sub index { |
||||||
|
my $self = shift; |
||||||
|
|
||||||
|
$self->render(text => 'Go away!'); |
||||||
|
} |
||||||
|
|
||||||
|
sub captcha { |
||||||
|
} |
||||||
|
|
||||||
|
sub c_list { |
||||||
|
} |
||||||
|
|
||||||
|
sub c_add { |
||||||
|
my ($self) = @_; |
||||||
|
|
||||||
|
unless (my $ref = $self->referrer and ref $ref eq 'HASH') { |
||||||
|
$self->res->code(400); |
||||||
|
$self->render(text => "Can't detect referred page"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
unless (my $site = $self->app->sites->{ $ref->{site} }) { |
||||||
|
$self->res->code(400); |
||||||
|
$self->render(text => "No such site"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
eval { |
||||||
|
} or do { |
||||||
|
chomp $@; |
||||||
|
my $msg = sprintf "Error when listing comments for %s/%s: %s", |
||||||
|
$ref->{site}, $ref->{pid}, $@; |
||||||
|
$self->app->log->error($msg); |
||||||
|
$self->res->code(500); |
||||||
|
$self->render(text => 'Internal error'); |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
1; |
@ -0,0 +1,94 @@ |
|||||||
|
package LDV; |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
use utf8; |
||||||
|
|
||||||
|
use Mojo::Base 'Mojolicious'; |
||||||
|
|
||||||
|
sub startup { |
||||||
|
my ($self) = @_; |
||||||
|
|
||||||
|
my $config = $self->app->home->rel_file('conf/ldv.conf'); |
||||||
|
$self->plugin(Config => {file => $config}); |
||||||
|
$self->plugin(I18N => {default => 'ru'}); |
||||||
|
$self->plugin('LDV::Helpers'); |
||||||
|
|
||||||
|
$self->app->mode('production'); |
||||||
|
$self->app->secrets([ $self->app->config->{secret} ]); |
||||||
|
|
||||||
|
$self->app->attr(json => sub { |
||||||
|
require JSON; |
||||||
|
my $json = JSON->new->utf8; |
||||||
|
return $json; |
||||||
|
}); |
||||||
|
|
||||||
|
$self->app->attr(email => sub { |
||||||
|
require LDV::Email; |
||||||
|
my $email = LDV::Email->new($self->app->config->{email} // {}); |
||||||
|
return $email; |
||||||
|
}); |
||||||
|
|
||||||
|
$self->app->attr(ldap => sub { |
||||||
|
require LDV::LDAP; |
||||||
|
my $ldap = LDV::LDAP->new($self->app->config->{ldap}); |
||||||
|
return $ldap; |
||||||
|
}); |
||||||
|
|
||||||
|
my $r = $self->routes; |
||||||
|
|
||||||
|
{ # /comments |
||||||
|
my $comm = $r->route('/comments') -> to(controller => 'comments'); |
||||||
|
$comm->post('/add') ->to(action => 'add'); |
||||||
|
$comm->get ('/get') ->to(action => 'get'); |
||||||
|
$comm->get ('/new') ->to(action => 'create'); |
||||||
|
|
||||||
|
mkdir $self->app->home->rel_dir('data/comments'); |
||||||
|
} |
||||||
|
|
||||||
|
{ # /user |
||||||
|
my $user = $r->route('/user') -> to(controller => 'user'); |
||||||
|
$user->get('/') ->to(cb => sub { shift->redirect_to('/user/login'); }); |
||||||
|
$user->get('/login') ->to(action => 'login'); |
||||||
|
$user->get('/register') ->to(action => 'register'); |
||||||
|
$user->get('/profile') ->to(action => 'profile'); |
||||||
|
|
||||||
|
$user->post('/auth') ->to(action => 'auth'); |
||||||
|
$user->get ('/logout') ->to(action => 'logout'); |
||||||
|
$user->post('/create') ->to(action => 'create'); |
||||||
|
$user->post('/update') ->to(action => 'update'); |
||||||
|
} |
||||||
|
|
||||||
|
{ # /zerobin |
||||||
|
my $zb = $r->route('/zerobin2') -> to(controller => 'zerobin'); |
||||||
|
$zb->post('/') -> to(action => 'save'); |
||||||
|
$zb->get ('/') -> to(action => 'create'); |
||||||
|
$zb->route('/:time', time => qr/\d+/) |
||||||
|
->via('GET') -> to(action => 'view'); |
||||||
|
$zb->get('/prune') -> to(action => 'prune'); |
||||||
|
|
||||||
|
my $conf = $self->app->config->{zerobin}; |
||||||
|
mkdir $self->app->home->rel_dir($conf->{root}); |
||||||
|
} |
||||||
|
|
||||||
|
{ # /imgbin |
||||||
|
my $conf = $self->app->config->{imgbin}; |
||||||
|
my $ib = $r->route('/imgbin') -> to(controller => 'imgbin'); |
||||||
|
$ib->post('/') -> to(action => 'save'); |
||||||
|
$ib->get ('/') -> to(action => 'create'); |
||||||
|
$ib->route('/:time', time => qr/\d+/) |
||||||
|
->via('GET') -> to(action => 'view'); |
||||||
|
$ib->get ('/prune') -> to(action => 'prune'); |
||||||
|
$ib->get ('/latest') -> to(action => 'latest') |
||||||
|
if ($conf->{show_latest}); |
||||||
|
|
||||||
|
mkdir $self->app->home->rel_dir($conf->{root}); |
||||||
|
mkdir $self->app->home->rel_file('public/images'); |
||||||
|
mkdir $self->app->home->rel_file('public/images/full'); |
||||||
|
mkdir $self->app->home->rel_file('public/images/small'); |
||||||
|
|
||||||
|
$ENV{MOJO_MAX_MESSAGE_SIZE} = $conf->{maxsize} + 2 * 1024 * 1024; # +2Mb |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
1; |
Loading…
Reference in new issue