| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Mojolicious::Plugin::StaticShare::Controller; | 
| 2 | 1 |  |  | 1 |  | 14545 | use Mojo::Base 'Mojolicious::Controller'; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 8 |  | 
| 3 | 1 |  |  | 1 |  | 294 | use Mojo::File qw(path); | 
|  | 1 |  |  |  |  | 34 |  | 
|  | 1 |  |  |  |  | 76 |  | 
| 4 | 1 |  |  | 1 |  | 518 | use HTTP::AcceptLanguage; | 
|  | 1 |  |  |  |  | 2470 |  | 
|  | 1 |  |  |  |  | 32 |  | 
| 5 | 1 |  |  | 1 |  | 8 | use Mojo::Path; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 6 | 1 |  |  | 1 |  | 37 | use Mojo::Util qw ( decode encode url_unescape xml_escape);# | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 76 |  | 
| 7 | 1 |  |  | 1 |  | 525 | use Time::Piece;# module replaces the standard localtime and gmtime functions with implementations that return objects | 
|  | 1 |  |  |  |  | 7380 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 8 |  |  |  |  |  |  | #~ use Mojo::Asset::File; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | has plugin => sub {   shift->stash('plugin') }; | 
| 11 |  |  |  |  |  |  | has public_uploads => sub { shift->plugin->public_uploads }; | 
| 12 |  |  |  |  |  |  | has is_admin => sub { | 
| 13 |  |  |  |  |  |  | my $c = shift; | 
| 14 |  |  |  |  |  |  | $c->plugin->is_admin($c); | 
| 15 |  |  |  |  |  |  | }; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | sub get { | 
| 18 | 1 |  |  | 1 | 0 | 420 | my ($c) = @_; | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 1 |  |  |  |  | 15 | $c->_stash(); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | return $c->not_found | 
| 23 | 1 | 50 | 33 |  |  | 68 | if !$c->is_admin && grep {/^\./} @{$c->stash('url_path')->parts}; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 | 1 | 50 |  |  |  | 74 | if ($c->plugin->access) { | 
| 26 | 0 | 0 |  |  |  | 0 | my $access = ref $c->plugin->access eq 'CODE' ? $c->plugin->access->($c) : $c->plugin->access; | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 0 | 0 |  |  |  | 0 | return $c->not_found | 
| 29 |  |  |  |  |  |  | unless $access; | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 0 | 0 |  |  |  | 0 | return $c->render(%$access) | 
| 32 |  |  |  |  |  |  | if ref $access eq 'HASH'; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 1 | 50 | 33 |  |  | 8 | if ($c->is_admin && $c->param('admin')) { | 
| 36 |  |  |  |  |  |  | # Temporary Redirect | 
| 37 | 0 |  |  |  |  | 0 | $c->res->code(307); | 
| 38 | 0 |  |  |  |  | 0 | return $c->redirect_to($c->req->url->to_abs->path); | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 1 |  |  |  |  | 20 | my $file_path = $c->stash('file_path'); | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 1 | 50 |  |  |  | 25 | return $c->dir($file_path) | 
| 44 |  |  |  |  |  |  | if -d $file_path; | 
| 45 | 0 | 0 |  |  |  | 0 | return $c->file($file_path) | 
| 46 |  |  |  |  |  |  | if -f $file_path; | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 |  |  |  |  | 0 | $c->not_found; | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | sub post { | 
| 52 | 0 |  |  | 0 | 0 | 0 | my ($c) = @_; | 
| 53 | 0 |  |  |  |  | 0 | $c->_stash(); | 
| 54 |  |  |  |  |  |  |  | 
| 55 | 0 |  |  |  |  | 0 | my $file_path = $c->stash('file_path'); | 
| 56 | 0 |  |  |  |  | 0 | my $url_path = $c->stash('url_path'); | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 0 | 0 |  |  |  | 0 | $c->app->log->debug($file_path, $url_path->to_route, $c->dumper($c->req->params->to_hash)) | 
| 59 |  |  |  |  |  |  | if $c->plugin->debug; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 0 | 0 | 0 |  |  | 0 | if (my $dir = $c->param('dir')) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 62 | 0 | 0 |  |  |  | 0 | return $c->new_dir($file_path, $dir) | 
| 63 |  |  |  |  |  |  | if $c->is_admin; | 
| 64 | 0 |  |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('you cant create dir')}); | 
| 65 |  |  |  |  |  |  | } elsif (my $rename = $c->param('rename')) { | 
| 66 | 0 | 0 |  |  |  | 0 | return $c->rename($file_path, $rename) | 
| 67 |  |  |  |  |  |  | if $c->is_admin; | 
| 68 | 0 |  |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('you cant rename')}); | 
| 69 |  |  |  |  |  |  | } elsif (my $delete = $c->param('delete[]') && $c->every_param('delete[]')) { | 
| 70 | 0 | 0 |  |  |  | 0 | return $c->delete($file_path, $delete) | 
| 71 |  |  |  |  |  |  | if $c->is_admin; | 
| 72 | 0 |  |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('you cant delete')}); | 
| 73 |  |  |  |  |  |  | } elsif (defined (my $edit = $c->param('edit'))) { | 
| 74 | 0 | 0 |  |  |  | 0 | return $c->_edit($file_path, $edit) | 
| 75 |  |  |  |  |  |  | if $c->is_admin; | 
| 76 | 0 |  |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('you cant edit')}); | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | return $c->render(json=>{error=>$c->i18n('target directory not found')}) | 
| 80 | 0 | 0 | 0 |  |  | 0 | if !$c->is_admin && grep {/^\./} @{$c->stash('url_path')->parts}; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 0 | 0 | 0 |  |  | 0 | return $c->render(json=>{error=>$c->i18n('you cant upload')}) | 
| 83 |  |  |  |  |  |  | unless $c->is_admin || $c->public_uploads; | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 0 |  | 0 |  |  | 0 | my $name = url_unescape($c->param('name') || '');#$file->filename | 
| 86 | 0 |  |  |  |  | 0 | utf8::upgrade($name); | 
| 87 |  |  |  |  |  |  | #~ return $c->render(json=>{error=>$c->i18n('Provide the name of upload file')}) | 
| 88 |  |  |  |  |  |  | #~ unless $name =~ /\S/i; | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 0 | 0 | 0 |  |  | 0 | return $c->render(json=>{error=>$c->i18n('Cant open target directory')}) | 
| 91 |  |  |  |  |  |  | unless !$name || -w $file_path; | 
| 92 |  |  |  |  |  |  | #~ $c->req->max_message_size(0); | 
| 93 |  |  |  |  |  |  | # Check file size | 
| 94 | 0 | 0 |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('upload is too big')}, status=>417) | 
| 95 |  |  |  |  |  |  | if $c->req->is_limit_exceeded; | 
| 96 |  |  |  |  |  |  |  | 
| 97 | 0 | 0 |  |  |  | 0 | my $file = $c->req->upload('file') | 
| 98 |  |  |  |  |  |  | or return $c->render(json=>{error=>$c->i18n('Where is your upload file?')}); | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 0 | 0 |  |  |  | 0 | my $to = $name ? $file_path->child($name) : $file_path; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 0 | 0 | 0 |  |  | 0 | return $c->render(json=>{error=>$c->i18n('path is not a directory')}) | 
| 103 |  |  |  |  |  |  | unless !$name || -d $file_path; | 
| 104 | 0 | 0 | 0 |  |  | 0 | return $c->render(json=>{error=>$c->i18n('path is a directory')}) | 
| 105 |  |  |  |  |  |  | if !$name && -d $to; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 0 | 0 | 0 |  |  | 0 | return $c->render(json=>{error=>$c->i18n('file already exists')}) | 
| 108 |  |  |  |  |  |  | if !$c->param('replace') && -e $to; | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 0 | 0 |  |  |  | 0 | eval { $file->asset->move_to($to) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 111 |  |  |  |  |  |  | or return $c->render(json=>{error=>$@  =~ /(.+) at /}); | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 0 | 0 |  |  |  | 0 | $url_path->merge($name) | 
| 115 |  |  |  |  |  |  | if $name; | 
| 116 |  |  |  |  |  |  |  | 
| 117 | 0 |  |  |  |  | 0 | $c->render(json=>{ok=> $url_path->trailing_slash(0)->to_route}); | 
| 118 |  |  |  |  |  |  | } | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | # TODO DELETE request | 
| 121 |  |  |  |  |  |  | sub delete { | 
| 122 |  |  |  |  |  |  | my ($c) = @_; | 
| 123 |  |  |  |  |  |  | $c->_stash(); | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | my $file_path = $c->stash('file_path'); | 
| 126 |  |  |  |  |  |  | my $url_path = $c->stash('url_path'); | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | $c->app->log->debug($file_path, $url_path->to_route, $c->dumper($c->req->params->to_hash)) | 
| 129 |  |  |  |  |  |  | if $c->plugin->debug; | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | sub _stash { | 
| 134 | 1 |  |  | 1 |  | 4 | my ($c) = @_; | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 1 |  | 50 |  |  | 7 | my $lang = HTTP::AcceptLanguage->new($c->req->headers->accept_language || 'en;q=0.5'); | 
| 137 | 1 |  |  |  |  | 189 | $c->stash('language' => $lang); | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 1 |  |  |  |  | 27 | my $pth = Mojo::Path->new($c->stash('pth'))->leading_slash(0)->trailing_slash(0); | 
| 140 | 1 | 50 |  |  |  | 153 | $pth = $pth->trailing_slash(1)->merge('.'.$c->stash('format')) | 
| 141 |  |  |  |  |  |  | if $c->stash('format'); | 
| 142 | 1 |  |  |  |  | 15 | $c->stash('pth' => $pth); | 
| 143 | 1 |  |  |  |  | 30 | my $url_path = $c->plugin->root_url->clone->merge($pth)->trailing_slash(1); | 
| 144 | 1 |  |  |  |  | 303 | $c->stash('url_path' => $url_path); | 
| 145 |  |  |  |  |  |  | #~ $c->stash('file_path' => $c->plugin->root_dir->clone->merge($c->stash('pth'))); | 
| 146 | 1 |  |  |  |  | 21 | $c->stash('file_path' => path(decode('UTF-8', url_unescape($c->plugin->root_dir->clone->merge($pth))))); | 
| 147 | 1 |  |  |  |  | 769 | $c->stash('title' => $c->i18n('Share')." ".$url_path->to_route); | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | sub dir { | 
| 152 | 1 |  |  | 1 | 0 | 36 | my ($c, $path) = @_; | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 1 | 50 | 50 |  |  | 5 | return $c->not_found | 
| 155 |  |  |  |  |  |  | if ($c->plugin->render_dir // '') eq 0; | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 1 |  |  |  |  | 25 | my $ex = Mojo::Exception->new($c->i18n(qq{Cant open directory})); | 
| 158 | 1 | 50 | 0 |  |  | 24 | opendir(my $dir, $path) | 
| 159 |  |  |  |  |  |  | or return $c->render_maybe('Mojolicious-Plugin-StaticShare/exception', format=>'html', handler=>'ep', status=>500, exception=>$ex) | 
| 160 |  |  |  |  |  |  | || $c->reply->exception($ex); | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 1 |  |  |  |  | 51 | my $files = $c->stash('files' => [])->stash('files'); | 
| 163 | 1 |  |  |  |  | 40 | my $dirs = $c->stash('dirs' => [])->stash('dirs'); | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 1 |  |  |  |  | 55 | while (readdir $dir) { | 
| 166 |  |  |  |  |  |  | next | 
| 167 | 17 | 100 | 100 |  |  | 1621 | if $_ eq '.' || $_ eq '..'; | 
| 168 |  |  |  |  |  |  | next | 
| 169 | 15 | 50 | 33 |  |  | 54 | if !$c->is_admin && /^\./; | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 15 |  |  |  |  | 132 | my $child = $path->child(decode('UTF-8', $_)); | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 15 | 100 | 50 |  |  | 511 | push @$dirs, decode('UTF-8', $_) | 
|  |  |  | 66 |  |  |  |  | 
| 174 |  |  |  |  |  |  | and next | 
| 175 |  |  |  |  |  |  | if -d $child && -r _; | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | next | 
| 178 | 11 | 50 |  |  |  | 239 | unless -f _; | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 11 |  |  |  |  | 37 | my @stat = stat $child; | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 11 |  | 100 |  |  | 201 | push @$files, { | 
| 183 |  |  |  |  |  |  | name  => decode('UTF-8', $_), | 
| 184 |  |  |  |  |  |  | size  => $stat[7] || 0, | 
| 185 |  |  |  |  |  |  | #~ type  => $c->plugin->mime->type(  (/\.([0-9a-zA-Z]+)$/)[0] || 'txt' ) || 'application/octet-stream', | 
| 186 |  |  |  |  |  |  | mtime => decode('UTF-8', localtime( $stat[9] )->strftime), #->to_datetime, #to_string(), | 
| 187 |  |  |  |  |  |  | #~ mode=> $stat[2] & 07777, #-r _, | 
| 188 |  |  |  |  |  |  | }; | 
| 189 |  |  |  |  |  |  | } | 
| 190 | 1 |  |  |  |  | 144 | closedir $dir; | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 1 | 50 |  |  |  | 7 | for my $index ($c->plugin->dir_index ? @{$c->plugin->dir_index} : ()) { | 
|  | 1 |  |  |  |  | 19 |  | 
| 193 | 3 |  |  |  |  | 70 | my $file = $path->child($index); | 
| 194 |  |  |  |  |  |  | next | 
| 195 | 3 | 100 |  |  |  | 58 | unless -f $file; | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 1 | 50 | 0 |  |  | 21 | $c->_stash_markdown($file) | 
|  |  |  | 0 |  |  |  |  | 
| 198 |  |  |  |  |  |  | and $c->stash(index=>$index) | 
| 199 |  |  |  |  |  |  | and last | 
| 200 |  |  |  |  |  |  | if $index =~ $c->plugin->re_markdown; | 
| 201 |  |  |  |  |  |  |  | 
| 202 | 1 | 50 | 33 |  |  | 5 | $c->_stash_pod($file) | 
|  |  |  | 50 |  |  |  |  | 
| 203 |  |  |  |  |  |  | and $c->stash(index=>$index) | 
| 204 |  |  |  |  |  |  | and last | 
| 205 |  |  |  |  |  |  | if $index =~ $c->plugin->re_pod; | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 1 | 0 |  |  |  | 4382 | return $c->render(ref $c->plugin->render_dir ? %{$c->plugin->render_dir} : $c->plugin->render_dir,) | 
|  | 0 | 50 |  |  |  | 0 |  | 
| 210 |  |  |  |  |  |  | if $c->plugin->render_dir; | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | $c->render_maybe("Mojolicious-Plugin-StaticShare/$_/dir", format=>'html', handler=>'ep',) | 
| 213 |  |  |  |  |  |  | and return | 
| 214 | 1 |  | 50 |  |  | 20 | for $c->stash('language')->languages; | 
| 215 |  |  |  |  |  |  |  | 
| 216 | 1 |  |  |  |  | 4887 | return $c->render('Mojolicious-Plugin-StaticShare/dir', format=>'html', handler=>'ep',); | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | #~ $c->render_maybe('Mojolicious-Plugin-StaticShare/exception', format=>'html', handler=>'ep', status=>500,exception=>Mojo::Exception->new(qq{Template rendering for dir content not found})) | 
| 220 |  |  |  |  |  |  | #~ or $c->reply->exception(); | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | sub new_dir { | 
| 224 | 0 |  |  | 0 | 0 | 0 | my ($c, $path, $dir) = @_; | 
| 225 |  |  |  |  |  |  |  | 
| 226 | 0 |  |  |  |  | 0 | my $edir = url_unescape($dir); | 
| 227 | 0 |  |  |  |  | 0 | utf8::upgrade($edir); | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 0 | 0 |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('provide the name of new directory')}) | 
| 230 |  |  |  |  |  |  | unless $edir =~ /\S/; | 
| 231 |  |  |  |  |  |  |  | 
| 232 | 0 |  |  |  |  | 0 | my $to = $path->child($edir);# | 
| 233 |  |  |  |  |  |  |  | 
| 234 | 0 | 0 |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('dir or file exists')}) | 
| 235 |  |  |  |  |  |  | if -e $to; | 
| 236 |  |  |  |  |  |  |  | 
| 237 | 0 |  |  |  |  | 0 | $to->make_path; | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 0 |  |  |  |  | 0 | $c->render(json=>{ok=> $c->stash('url_path')->clone->merge($dir)->trailing_slash(1)->to_route}); | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | } | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  | sub rename { | 
| 244 | 0 |  |  | 0 | 0 | 0 | my ($c, $path, $rename) = @_; | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 0 |  |  |  |  | 0 | my $ename = url_unescape($rename); | 
| 247 | 0 |  |  |  |  | 0 | utf8::upgrade($ename); | 
| 248 |  |  |  |  |  |  |  | 
| 249 | 0 | 0 |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('provide new name')}) | 
| 250 |  |  |  |  |  |  | unless $ename =~ /\S/; | 
| 251 |  |  |  |  |  |  |  | 
| 252 | 0 |  |  |  |  | 0 | my $to = $path->sibling($ename); | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 0 | 0 |  |  |  | 0 | return $c->render(json=>{error=>$c->i18n('dir or file exists')}) | 
| 255 |  |  |  |  |  |  | if -e $to; | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 0 | 0 |  |  |  | 0 | my $move = eval { $path->move_to($to) } | 
|  | 0 |  |  |  |  | 0 |  | 
| 258 |  |  |  |  |  |  | or return $c->render(json=>{error=>$@ =~ /(.+) at /}); | 
| 259 |  |  |  |  |  |  |  | 
| 260 | 0 |  |  |  |  | 0 | $c->render(json=>{ok=> $c->stash('url_path')->trailing_slash(0)->to_dir->merge($rename)->to_route}); | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | sub delete { | 
| 265 | 0 |  |  | 0 | 0 | 0 | my ($c, $path, $delete) = @_; | 
| 266 | 0 |  |  |  |  | 0 | my @delete = (); | 
| 267 | 0 |  |  |  |  | 0 | for (@$delete) { | 
| 268 | 0 |  |  |  |  | 0 | my $del = url_unescape($_); | 
| 269 | 0 |  |  |  |  | 0 | utf8::upgrade($del); | 
| 270 | 0 | 0 | 0 |  |  | 0 | push @delete, $c->i18n('provide the name of deleted dir') | 
| 271 |  |  |  |  |  |  | and next | 
| 272 |  |  |  |  |  |  | unless $del =~ /\S/; | 
| 273 | 0 |  |  |  |  | 0 | my $d = $path->sibling($del); | 
| 274 | 0 | 0 | 0 |  |  | 0 | push @delete, $c->i18n('dir or file does not exists') | 
| 275 |  |  |  |  |  |  | and next | 
| 276 |  |  |  |  |  |  | unless -e $d; | 
| 277 | 0 | 0 |  |  |  | 0 | push @delete, eval {$d->remove_tree()} ? 1 : 0, | 
|  | 0 |  |  |  |  | 0 |  | 
| 278 |  |  |  |  |  |  | } | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 0 |  |  |  |  | 0 | $c->render(json=>{ok=>\@delete}); | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | sub file { | 
| 284 | 0 |  |  | 0 | 0 | 0 | my ($c, $path) = @_; | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 0 |  |  |  |  | 0 | my $ex = Mojo::Exception->new($c->i18n(qq{Permission denied})); | 
| 287 | 0 | 0 | 0 |  |  | 0 | return $c->render_maybe('Mojolicious-Plugin-StaticShare/exception', format=>'html', handler=>'ep', status=>500,exception=>$ex) | 
| 288 |  |  |  |  |  |  | || $c->reply->exception($ex) | 
| 289 |  |  |  |  |  |  | unless -r $path; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 0 | 0 | 0 |  |  | 0 | return $c->_edit($path) | 
| 292 |  |  |  |  |  |  | if $c->is_admin && $c->param('edit'); | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 0 |  |  |  |  | 0 | my $filename = $path->basename; | 
| 295 |  |  |  |  |  |  |  | 
| 296 | 0 | 0 | 0 |  |  | 0 | return $c->_markdown($path) | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 297 |  |  |  |  |  |  | unless ($c->plugin->render_markdown || '') eq 0 || $c->param('attachment') || $filename !~ $c->plugin->re_markdown; | 
| 298 |  |  |  |  |  |  |  | 
| 299 | 0 | 0 | 0 |  |  | 0 | return $c->_pod($path) | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 300 |  |  |  |  |  |  | unless ($c->plugin->render_pod || '') eq 0 || $c->param('attachment') || $filename !~ $c->plugin->re_pod; | 
| 301 |  |  |  |  |  |  |  | 
| 302 | 0 | 0 | 0 |  |  | 0 | my $asset = $c->_html($path) | 
| 303 |  |  |  |  |  |  | unless $c->param('attachment') || $filename !~ $c->plugin->re_html; | 
| 304 |  |  |  |  |  |  |  | 
| 305 | 0 | 0 |  |  |  | 0 | $c->res->headers->content_disposition($c->param('attachment') ? "attachment; filename=$filename;" : "inline"); | 
| 306 | 0 |  | 0 |  |  | 0 | my $type  =$c->plugin->mime->type(  ( $path =~ /\.([0-9a-zA-Z]+)$/)[0] || 'txt' ) || $c->plugin->mime->type('txt');#'application/octet-stream'; | 
| 307 | 0 |  |  |  |  | 0 | $c->res->headers->content_type($type); | 
| 308 | 0 |  | 0 |  |  | 0 | $c->reply->asset($asset || Mojo::Asset::File->new(path => $path)); | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | sub _html {# disable scripts inside html | 
| 312 | 0 |  |  | 0 |  | 0 | my ($c, $path) = @_; | 
| 313 | 0 |  |  |  |  | 0 | my $file = Mojo::Asset::File->new(path => $path); | 
| 314 | 0 |  |  |  |  | 0 | my $content = $file->slurp; | 
| 315 | 0 |  |  |  |  | 0 | my $dom = Mojo::DOM->new($content); | 
| 316 | 0 | 0 |  |  |  | 0 | $dom->find('script')->each(\&_sanitize_script)->size | 
| 317 |  |  |  |  |  |  | or return $file; | 
| 318 |  |  |  |  |  |  |  | 
| 319 | 0 |  |  |  |  | 0 | my $asset = Mojo::Asset::Memory->new; | 
| 320 | 0 |  |  |  |  | 0 | $asset->add_chunk($dom)->mtime($file->mtime); | 
| 321 | 0 |  |  |  |  | 0 | return $asset; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  |  | 
| 324 |  |  |  |  |  |  | sub _markdown {# file | 
| 325 | 0 |  |  | 0 |  | 0 | my ($c, $path) = @_; | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 0 |  |  |  |  | 0 | my $ex = Mojo::Exception->new($c->i18n(qq{Please install or verify markdown module (default to Text::Markdown::Hoedown) with markdown(\$str) sub or parse(\$str) method})); | 
| 328 |  |  |  |  |  |  |  | 
| 329 | 0 | 0 | 0 |  |  | 0 | $c->_stash_markdown($path) | 
| 330 |  |  |  |  |  |  | or return $c->render_maybe('Mojolicious-Plugin-StaticShare/exception', format=>'html', handler=>'ep', status=>500,exception=>$ex) | 
| 331 |  |  |  |  |  |  | || $c->reply->exception($ex); | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | return $c->plugin->render_markdown | 
| 334 | 0 | 0 |  |  |  | 0 | ? $c->render(ref $c->plugin->render_markdown ? %{$c->plugin->render_markdown} : $c->plugin->render_markdown,) | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 335 |  |  |  |  |  |  | : $c->render('Mojolicious-Plugin-StaticShare/markdown', format=>'html', handler=>'ep',); | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | my $layout_re = qr|^(?:\s*%+\s*layouts/(.+)[;\s]+)|; | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | sub _stash_markdown { | 
| 341 | 0 |  |  | 0 |  | 0 | my ($c, $path) = @_; | 
| 342 | 0 | 0 |  |  |  | 0 | my $md = $c->plugin->markdown | 
| 343 |  |  |  |  |  |  | or return; # not installed | 
| 344 | 0 |  |  |  |  | 0 | my $content = decode('UTF-8', $path->slurp); | 
| 345 | 0 |  |  |  |  | 0 | $content =~ s|$layout_re|$c->_layout_index($1)|e;#) {# || $content =~ s/(?:%\s*layout\s+"([^"]+)";?)//m | 
|  | 0 |  |  |  |  | 0 |  | 
| 346 | 0 |  |  |  |  | 0 | my $dom = Mojo::DOM->new($md->parse($content)); | 
| 347 | 0 |  |  |  |  | 0 | $dom->find('script')->each(\&_sanitize_script); | 
| 348 | 0 |  |  |  |  | 0 | $dom->find('*')->each(\&_dom_attrs); | 
| 349 | 0 |  | 0 |  |  | 0 | $c->stash(markdown => $dom->at('body') || $dom); | 
| 350 |  |  |  |  |  |  | #~ my $filename = $path->basename; | 
| 351 |  |  |  |  |  |  | #~ $c->stash('title'=>$filename); | 
| 352 |  |  |  |  |  |  | } | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | my $layout_ext_re = qr|\.([^/\.;\s]+)?\.?([^/\.;\s]+)?$|; # .html.ep | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | sub _layout_index {# from regexp execute | 
| 357 | 0 |  |  | 0 |  | 0 | my ($c, @match) = @_;# | 
| 358 | 0 |  |  |  |  | 0 | $match[0] =~ s|[;\s]+$||; | 
| 359 |  |  |  |  |  |  | #~ utf8::encode($match[0]); | 
| 360 | 0 | 0 |  |  |  | 0 | push @match, $1, $2 | 
| 361 |  |  |  |  |  |  | if $match[0] =~ s|$layout_ext_re||; | 
| 362 | 0 |  | 0 |  |  | 0 | my $found = $c->app->renderer->template_path({ | 
|  |  |  | 0 |  |  |  |  | 
| 363 |  |  |  |  |  |  | template => "layouts/$match[0]", | 
| 364 |  |  |  |  |  |  | format   => $match[1] || 'html', | 
| 365 |  |  |  |  |  |  | handler  => $match[2] || 'ep', | 
| 366 |  |  |  |  |  |  | }); | 
| 367 | 0 | 0 | 0 |  |  | 0 | $c->layout($match[0])#encode('UTF-8', $match[0])) | 
| 368 |  |  |  |  |  |  | and return '' | 
| 369 |  |  |  |  |  |  | if $found; | 
| 370 | 0 |  |  |  |  | 0 | my $err = "layout [$match[0]].$match[1].$match[2] not found"; | 
| 371 | 0 |  |  |  |  | 0 | $c->app->log->error("$err", "\t app->renderer->paths: ", @{$c->app->renderer->paths}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 372 | 0 |  |  |  |  | 0 | return " $err"; | 
| 373 |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | sub _sanitize_script {# for markdown | 
| 376 | 0 |  |  | 0 |  | 0 | my $el = shift; | 
| 377 | 0 |  |  |  |  | 0 | my $text = xml_escape $el->text; | 
| 378 | 0 |  |  |  |  | 0 | $el->replace(" $text"); | 
| 379 |  |  |  |  |  |  | } | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | sub _dom_attrs {# for markdown | 
| 382 |  |  |  |  |  |  | # translate ^{...} to id, style, class attributes | 
| 383 |  |  |  |  |  |  | # берем только первый child и он должен быть текстом | 
| 384 | 155 |  |  | 155 |  | 9811 | my $el = shift; | 
| 385 | 155 | 100 |  |  |  | 388 | my $text = $el->text | 
| 386 |  |  |  |  |  |  | or return; | 
| 387 | 138 |  |  |  |  | 4638 | my $child1 = $el->child_nodes->first; | 
| 388 | 138 |  |  |  |  | 11097 | my $parent = $child1->parent; | 
| 389 |  |  |  |  |  |  | return | 
| 390 | 138 | 100 | 33 |  |  | 6558 | unless $parent && $parent->type eq 'tag' && $child1->type eq 'text'; | 
|  |  |  | 66 |  |  |  |  | 
| 391 | 135 |  |  |  |  | 3293 | my $content = $child1->content; | 
| 392 | 135 | 50 |  |  |  | 3405 | if ($content =~ s|^(?:\s*\{([^\}]+)\}\s*)||) { | 
| 393 | 0 |  |  |  |  | 0 | my $attrs = $1; | 
| 394 | 0 |  |  |  |  | 0 | utf8::upgrade($attrs); | 
| 395 |  |  |  |  |  |  | # styles | 
| 396 | 0 |  |  |  |  | 0 | $parent->{style} .= " $1" | 
| 397 |  |  |  |  |  |  | while $attrs =~ s|(\S+\s*:\s*[^;]+;)||; | 
| 398 |  |  |  |  |  |  | # id | 
| 399 | 0 |  |  |  |  | 0 | $parent->{id}  = $1 | 
| 400 |  |  |  |  |  |  | while $attrs =~ s|#(\S+)||; | 
| 401 |  |  |  |  |  |  | # classes | 
| 402 | 0 |  |  |  |  | 0 | $parent->{class} .= " $1" | 
| 403 |  |  |  |  |  |  | while $attrs =~ s|\.?([^\.\s]+)||; | 
| 404 | 0 |  |  |  |  | 0 | $child1->content($content);# replace | 
| 405 |  |  |  |  |  |  | } | 
| 406 |  |  |  |  |  |  | } | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | sub _pod {# file | 
| 409 | 0 |  |  | 0 |  | 0 | my ($c, $path) = @_; | 
| 410 |  |  |  |  |  |  |  | 
| 411 | 0 | 0 |  |  |  | 0 | $c->_stash_pod($path) | 
| 412 |  |  |  |  |  |  | or return;# $c->render_maybe('Mojolicious-Plugin-StaticShare/exception', format=>'html', handler=>'ep', status=>500,exception=>$ex) | 
| 413 |  |  |  |  |  |  | #~ || $c->reply->exception($ex); | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | return $c->plugin->render_pod | 
| 416 | 0 | 0 |  |  |  | 0 | ? $c->render(ref $c->plugin->render_pod ? %{$c->plugin->render_pod} : $c->plugin->render_pod,) | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 417 |  |  |  |  |  |  | : $c->render('Mojolicious-Plugin-StaticShare/pod', format=>'html', handler=>'ep',); | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | sub _stash_pod { | 
| 422 | 1 |  |  | 1 |  | 4 | my ($c, $path) = @_; | 
| 423 |  |  |  |  |  |  | return | 
| 424 | 1 | 50 |  |  |  | 11 | unless $c->app->renderer->helpers->{'pod_to_html'}; | 
| 425 |  |  |  |  |  |  |  | 
| 426 | 1 |  |  |  |  | 28 | my $content = decode('UTF-8', $path->slurp); | 
| 427 | 1 |  |  |  |  | 380 | $content =~ s|$layout_re|$c->_layout_index($1)|e;#) {# || $content =~ s/(?:%\s*layout\s+"([^"]+)";?)//m | 
|  | 0 |  |  |  |  | 0 |  | 
| 428 | 1 |  |  |  |  | 14 | my $dom = Mojo::DOM->new($c->pod_to_html($content)); | 
| 429 | 1 |  |  |  |  | 22175 | $dom->find('script')->each(\&_sanitize_script); | 
| 430 | 1 |  |  |  |  | 4603 | $dom->find('*')->each(\&_dom_attrs); | 
| 431 | 1 |  | 33 |  |  | 52 | $c->stash(pod =>  $dom->at('body') || $dom); | 
| 432 |  |  |  |  |  |  | #~ my $filename = $path->basename; | 
| 433 |  |  |  |  |  |  | #~ $c->stash('title'=>$filename); | 
| 434 |  |  |  |  |  |  | } | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | sub not_found { | 
| 437 | 0 |  |  | 0 | 0 |  | my $c = shift; | 
| 438 | 0 | 0 |  |  |  |  | $c->render_maybe('Mojolicious-Plugin-StaticShare/not_found', format=>'html', handler=>'ep', status=>404,) | 
| 439 |  |  |  |  |  |  | or $c->reply->not_found; | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | }; | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | sub _edit { | 
| 444 | 0 |  |  | 0 |  |  | my ($c, $path, $edit) = @_; | 
| 445 | 0 | 0 |  |  |  |  | unless (defined $edit) {# get | 
| 446 | 0 |  |  |  |  |  | $c->stash('edit'=> decode('UTF-8', $path->slurp)); | 
| 447 | 0 |  |  |  |  |  | $c->stash('title' => $c->i18n('Edit')." ".$c->stash('url_path')->to_route); | 
| 448 | 0 |  |  |  |  |  | return $c->render('Mojolicious-Plugin-StaticShare/edit', format=>'html', handler=>'ep',); | 
| 449 |  |  |  |  |  |  | } | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | # save | 
| 452 | 0 |  |  |  |  |  | $path->spurt(encode('UTF-8', $edit)); | 
| 453 | 0 |  |  |  |  |  | $c->render(json=>{ok=>$path->to_string}); | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | 1; | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | =pod | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =encoding utf8 | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | Доброго всем | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =head1 Mojolicious::Plugin::StaticShare::Controller | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | ¡ ¡ ¡ ALL GLORY TO GLORIA ! ! ! | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | =head1 NAME | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | Mojolicious::Plugin::StaticShare::Controller - is an internal controller for L. | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | =cut |