File Coverage

script/docsiscious
Criterion Covered Total %
statement 25 25 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 34 34 100.0


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2 1     1   1452 use Mojolicious::Lite;
  1         113249  
  1         8  
3 1     1   18281 use Mojo::Util 'steady_time';
  1         3  
  1         64  
4 1     1   1151 use DOCSIS::ConfigFile qw( decode_docsis encode_docsis );
  1         63593  
  1         95  
5 1     1   10 use File::Basename;
  1         2  
  1         72  
6 1     1   5 use File::Spec::Functions qw( catdir catfile );
  1         2  
  1         49  
7 1     1   5 use FindBin;
  1         2  
  1         41  
8 1     1   757 use YAML::XS;
  1         2837  
  1         81  
9 1     1   24 BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
10 1     1   562 use App::docsisicious;
  1         3  
  1         8  
11              
12             my $STORAGE = $ENV{DOCSIS_STORAGE} || ($ENV{HOME} ? catdir $ENV{HOME}, '.docsisicious' : '');
13             die "DOCSIS_STORAGE=/path/to/docsis/files need to be set" unless $STORAGE;
14             mkdir $STORAGE or die "mkdir $STORAGE: $!" unless -d $STORAGE;
15             app->log->info("Will store DOCSIS config files in $STORAGE");
16              
17             get '/' => {layout => 'default'} => 'editor';
18             get '/css/docsis/:version' => [format => ['css']] => {template => 'css/docsis'};
19             get '/js/docsis/:version' => [format => ['js']] => {template => 'js/docsis'};
20              
21             my $download = sub {
22             my $c = shift;
23              
24             eval {
25             my $config = YAML::XS::Load($c->param('config'));
26             delete $config->{$_} for qw( CmMic CmtsMic );
27             my $binary = encode_docsis $config, {shared_secret => $c->param('shared_secret')};
28             my $filename = $c->param('filename') || $config->{filename} || sprintf '%s.bin', $c->paste_id;
29             $filename =~ s![^\w\.-]!-!g;
30             $c->res->headers->content_disposition("attachment; filename=$filename");
31             $c->render(data => $binary, format => 'binary');
32             } or do {
33             my $err = $@;
34             chomp $err;
35             $c->app->log->warn("Could not encode_docsis: $err");
36             $err =~ s! at \S+.*$!!s;
37             $c->render(error => "Cannot encode config file: $err", status => 400);
38             };
39             };
40              
41             my $save = sub {
42             my $c = shift;
43             my $id = $c->paste_id;
44             my $config = $c->param('config');
45             my %data;
46              
47             eval {
48             die 'Empty config' unless length $config;
49             $data{filename} = $c->param('filename');
50             $data{shared_secret} = $c->param('shared_secret');
51             $data{ts} = Mojo::Date->new->to_datetime;
52             $data{config} = YAML::XS::Load($config);
53             Mojo::Util::spurt(YAML::XS::Dump(\%data), catfile $STORAGE, "$id.yaml");
54             $c->redirect_to('edit' => id => $id);
55             } or do {
56             my $err = $@;
57             chomp $err;
58             $err =~ s! at \S+.*$!!s;
59             $c->render(error => "Cannot encode config file: $err", status => 400);
60             };
61             };
62              
63             my $upload = sub {
64             my $c = shift;
65             my $binary = $c->req->upload('binary');
66              
67             eval {
68             my $config = decode_docsis $binary->slurp;
69             $c->param(config => YAML::XS::Dump($config));
70             $c->param(filename => basename $binary->filename);
71             } or do {
72             my $err = $@;
73             chomp $err;
74             $err =~ s! at \S+.*$!!s;
75             $c->render(error => "Cannot decode config file: $err", status => 400);
76             };
77             };
78              
79             get(
80             '/edit/example' => {layout => 'default', template => 'editor'} => sub {
81             my $c = shift;
82             $c->param(config => Mojo::Loader::data_section(__PACKAGE__, 'example.yaml'));
83             $c->param(filename => 'example.bin');
84             },
85             'example',
86             );
87              
88             get(
89             '/edit/:id' => {layout => 'default', template => 'editor'} => sub {
90             my $c = shift;
91             my $id = $c->paste_id;
92             my $data = YAML::XS::Load(Mojo::Util::slurp(catfile $STORAGE, "$id.yaml"));
93             $c->param(config => YAML::XS::Dump($data->{config}));
94             $c->param(filename => $data->{filename});
95             $c->param(shared_secret => $data->{shared_secret});
96             },
97             'edit'
98             );
99              
100             post(
101             '/' => {layout => 'default', template => 'editor'} => sub {
102             my $c = shift;
103             return $c->$save if $c->param('save');
104             return $c->$download if $c->param('download');
105             return $c->$upload if $c->req->upload('binary');
106             return $c->render(text => "Either download, binary or save need to be present.\n", status => 400);
107             },
108             'save'
109             );
110              
111             helper paste_id => sub {
112             my $c = shift;
113             my $id = $c->param('id') || Mojo::Util::md5_sum($^T . $$ . steady_time);
114             die "Invalid id: $id" unless $id =~ /^\w+$/;
115             die "Invalid id: $id" if $id eq 'example';
116             return $id;
117             };
118              
119             app->home->parse(App::docsisicious->HOME);
120             app->static->paths([app->home->rel_dir('public')]);
121             app->defaults(error => '', VERSION => App::docsisicious->VERSION);
122             app->defaults->{VERSION} =~ s!\W+!-!g;
123             app->start;
124              
125             __DATA__