3 use Mojolicious::Lite -signatures;
4 use Mojo::File qw(curfile);
6 plugin NotYAMLConfig => { file => 'config.yml',
8 appname => 'Paste Bin',
11 my $datadir = curfile->sibling('data');
12 if (app->config->{datadir}) {
13 $datadir = Mojo::File->new(app->config->{datadir});
16 chdir curfile->dirname;
19 $c->render(template => 'forbidden', status => 403)
20 if !length app->config->{password};
23 post '/' => sub ($c) {
24 # print STDERR "pass=" . $c->param('password') . "\n";
25 return $c->render(template => 'forbidden', status => 403)
26 if !defined app->config->{password}
27 || !length $c->param('password')
28 || $c->param('password') ne app->config->{password};
30 my $file_content = $c->param('text');
31 my $filename = $c->param('filename');
32 my $upload = $c->param('file');
34 if (defined $upload && $upload->size) {
35 # print STDERR "FILENAME = " . $upload->filename . "\n";
36 $filename = $upload->filename;
37 $file_content = $upload->slurp;
40 if ($filename !~ /\A\w[\w\.]*\.\w+\z/) {
41 # print STDERR "FILENAME2 = " . $upload->filename . "\n";
42 return $c->render(template => 'forbidden', status => 403);
45 $datadir->child($filename)->spurt($file_content);
46 $c->redirect_to($c->req->url->base . "$filename");
49 get '/<filename>.<ext>'
50 => [ filename => qr/\w[\w\.]*/, ext => qr/\w+/ ]
52 my $fullname = $c->param('filename').'.'.$c->param('ext');
53 my $file = $datadir->child($fullname);
54 my $stat = $file->stat;
56 return $c->reply->not_found
59 $c->stash(mtime => POSIX::strftime('%Y-%m-%d %H:%M:%S',
60 localtime($stat->mtime)));
61 $c->stash(file_content => $file->slurp);
62 my $lang = $c->param('ext');
64 $c->stash(language => "language-$lang");
68 app->mode(app->config->{mode});
74 <h1><%= config->{appname} %></h1>
75 <form method="POST" enctype="multipart/form-data">
76 <label for="text">Enter some text or source code here:</label>
77 <textarea name="text" id="input_text">
79 <label for="file">Or select a file to upload:</label>
80 <input type="file" name="file"/>
81 <label for="filename">Name the file:</label>
82 <input type="text" name="filename"/>
83 <label for="password">Password:</label>
84 <input type="password" name="password" />
85 <input type="submit" value="Submit"/>
92 %= content_for header => begin
93 <base href="<%= config->{base} %>/">
94 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/qtcreator-dark.min.css">
95 <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
96 <script>hljs.highlightAll();</script>
99 <h1><tt><%= $filename%>.<%= $ext %></tt>
100 <span class="unimportant">— <%= config->{appname} %></span><br/>
101 <small class="unimportant">Created: <%= $mtime %></small></h1>
102 <pre><code class="<%= $language %>"><%= $file_content %></code></pre>
111 @@ layouts/default.html.ep
114 <meta charset="utf-8" />
115 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
116 <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
117 <meta name="viewport" content="width=device-width" />
119 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
120 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css">
121 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">
122 <link rel="icon" href="img/shebang-favicon.svg" />
123 <%= content 'header' %>
137 .button, input[type="submit"] {
138 background-color: #0030c0;
139 border-color: #202080;
146 font-family: monospace;
170 <title><%= config->{appname} %></title>
172 <body><div class="wrapper">
175 Created by <b>Yenya's Paste Bin</b>,
176 <a href="https://www.fi.muni.cz/~kas/git/paste.git/">www.fi.muni.cz/~kas/git/paste</a>