Browse Source

* initial

master
Alex 'AdUser' Z 7 years ago
commit
2c58868855
  1. 11
      bin/cmtd
  2. 1
      cmtd.conf
  3. 29
      lib/CMTD.pm
  4. 105
      lib/CMTD/Comments.pm
  5. 36
      lib/CMTD/Helpers.pm
  6. 47
      lib/CMTD/Main.pm
  7. 94
      lib/LDV.pm
  8. 9
      t/basic.t

11
bin/cmtd

@ -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');

1
cmtd.conf

@ -0,0 +1 @@
{}

29
lib/CMTD.pm

@ -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;

105
lib/CMTD/Comments.pm

@ -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;

36
lib/CMTD/Helpers.pm

@ -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;

47
lib/CMTD/Main.pm

@ -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;

94
lib/LDV.pm

@ -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;

9
t/basic.t

@ -0,0 +1,9 @@
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
my $t = Test::Mojo->new('CMTD');
$t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i);
done_testing();
Loading…
Cancel
Save