Luc Didry 995a38
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
Luc Didry 91e078
package Lufi::Controller::Files;
Luc Didry 91e078
use Mojo::Base 'Mojolicious::Controller';
Luc Didry d94c2b
use Mojo::JSON qw(encode_json decode_json to_json true false);
Luc Didry 1fbe93
use Mojo::Util qw(encode decode);
Luc Didry 1fbe93
use Mojo::File;
Luc Didry d909b8
use Lufi::DB::File;
Luc Didry d909b8
use Lufi::DB::Slice;
Luc Didry 91e078
use File::Spec::Functions;
Luc Didry 10a8dd
use Number::Bytes::Human qw(format_bytes);
Luc Didry 40deab
use Filesys::DfPortable;
Luc Didry 50b1f0
use Crypt::SaltedHash;
Luc Didry 91e078
Luc Didry 91e078
sub upload {
Luc Didry 91e078
    my $c = shift;
Luc Didry 91e078
Yann dbdaff
    if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) {
Luc Didry ac8d76
        $c->inactivity_timeout(30000000);
Luc Didry cd104c
Luc Didry ac8d76
        $c->app->log->debug('Client connected');
Luc Didry cd104c
Luc Didry ac8d76
        $c->on(
Luc Didry ac8d76
            message => sub {
Luc Didry ac8d76
                my ($ws, $text) = @_;
Luc Didry 91e078
Luc Didry ac8d76
                my $begin = time;
Luc Didry cd104c
Luc Didry ac8d76
                my ($json) = split('XXMOJOXX', $text, 2);
Luc Didry ac8d76
                $json = encode 'UTF-8', $json;
Luc Didry 6f3cf3
                $text =~ s/^.*?XXMOJOXX/${json}XXMOJOXX/;
Luc Didry ac8d76
                $json = decode_json $json;
Luc Didry 91e078
Luc Didry ac8d76
                $c->app->log->debug('Got message');
Luc Didry 91e078
Luc Didry ac8d76
                my $stop = 0;
Luc Didry 40deab
Luc Didry ac8d76
                # Check if stop_upload file is present
Luc Didry ac8d76
                if ($c->stop_upload) {
Luc Didry 40deab
                    $stop = 1;
Luc Didry d909b8
                    $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                        {
Luc Didry d94c2b
                            success    => false,
Luc Didry d94c2b
                            msg        => $c->l('Sorry, uploading is disabled.'),
Luc Didry d94c2b
                            sent_delay => $json->{delay},
Luc Didry d94c2b
                            i          => $json->{i}
Luc Didry d94c2b
                        }
Luc Didry d909b8
                    )));
Luc Didry ac8d76
                }
Luc Didry ac8d76
                # Check against max_size
Luc Didry ac8d76
                elsif (defined $c->config('max_file_size')) {
Luc Didry ac8d76
                    if ($json->{size} > $c->config('max_file_size')) {
Luc Didry ac8d76
                        $stop = 1;
Luc Didry d909b8
                        $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                            {
Luc Didry d94c2b
                                success    => false,
Luc Didry d94c2b
                                msg        => $c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))),
Luc Didry d94c2b
                                sent_delay => $json->{delay},
Luc Didry d94c2b
                                i          => $json->{i}
Luc Didry d94c2b
                            }
Luc Didry d909b8
                        )));
Luc Didry ac8d76
                    }
Luc Didry ac8d76
                }
Luc Didry ac8d76
                # Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file)
Luc Didry ac8d76
                elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
Luc Didry ac8d76
                    $stop = 1;
Luc Didry d909b8
                    $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                        {
Luc Didry d94c2b
                            success    => false,
Luc Didry d94c2b
                            msg        => $c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})),
Luc Didry d94c2b
                            sent_delay => $json->{delay},
Luc Didry d94c2b
                            i          => $json->{i}
Luc Didry d94c2b
                        }
Luc Didry d909b8
                    )));
Luc Didry 10a8dd
                }
Luc Didry 10a8dd
Luc Didry ac8d76
                unless ($stop) {
Luc Didry ac8d76
                    my $f;
Luc Didry ac8d76
                    if (defined($json->{id})) {
Luc Didry d909b8
                        $f = Lufi::DB::File->new(app => $c->app)->from_short($json->{id});
Luc Didry ac8d76
                    } else {
Luc Didry ac8d76
                        my $delay;
Luc Didry bd0c26
                        unless (defined $json->{delay}) {
Luc Didry bd0c26
                            $json->{delay} = $c->max_delay;
Luc Didry bd0c26
                        }
Luc Didry ac8d76
Luc Didry ac8d76
                        if (defined $c->config('delay_for_size')) {
Luc Didry ac8d76
                            # Choose delay according to config
Luc Didry ac8d76
                            my $delays   = $c->config('delay_for_size');
Luc Didry ac8d76
                            my @keys     = sort {$b <=> $a} keys %{$delays};
Luc Didry ac8d76
                            for my $key (@keys) {
Luc Didry ac8d76
                                if ($json->{size} >= $key) {
Luc Didry ac8d76
                                    $delay = ($json->{delay} < $delays->{$key}) ? $json->{delay} : $delays->{$key};
Luc Didry ac8d76
                                    last;
Luc Didry ac8d76
                                }
Luc Didry 10a8dd
                            }
Luc Didry be8c84
                        }
Luc Didry ac8d76
                        # If the file size is lower than the lowest configured size or if there is no delay_for_size setting, we choose the configured max delay
Luc Didry ac8d76
                        unless (defined $delay) {
Luc Didry b21906
                            $delay = (($json->{delay} > 0 && $json->{delay} <= $c->max_delay) || $c->max_delay == 0) ? $json->{delay} : $c->max_delay;
Luc Didry ac8d76
                        }
Luc Didry 50b1f0
                        # If we have a password
Luc Didry 50b1f0
                        my $salted_pwd;
Luc Didry 50b1f0
                        if ($c->config('allow_pwd_on_files') && defined($json->{file_pwd}) && $json->{file_pwd} ne '') {
Luc Didry 50b1f0
                            my $csh = Crypt::SaltedHash->new(algorithm => 'SHA-256', salt_len => 8);
Luc Didry 50b1f0
                            $csh->add($json->{file_pwd});
Luc Didry 50b1f0
Luc Didry 50b1f0
                            $salted_pwd = $csh->generate();
Luc Didry 50b1f0
                        }
Luc Didry be8c84
Luc Didry 3bbe80
                        my $creator = $c->ip;
Yann dbdaff
                        if (defined($c->config('ldap')) || defined($c->config('htpasswd'))) {
Luc Didry 3bbe80
                            $creator = 'User: '.$c->current_user.', IP: '.$creator;
Luc Didry 3bbe80
                        }
Luc Didry d909b8
                        $f = Lufi::DB::File->new(app => $c->app)->get_empty()
Luc Didry d909b8
                                ->created_by($creator)
Luc Didry d909b8
                                ->delete_at_first_view(($json->{del_at_first_view}) ? 1 : 0)
Luc Didry d909b8
                                ->delete_at_day($delay)
Luc Didry d909b8
                                ->mediatype($json->{type})
Luc Didry d909b8
                                ->filename($json->{name})
Luc Didry d909b8
                                ->filesize($json->{size})
Luc Didry d909b8
                                ->nbslices($json->{total})
Luc Didry d909b8
                                ->mod_token($c->shortener($c->config('token_length')))
Luc Didry d909b8
                                ->passwd($salted_pwd)
Luc Didry d909b8
                                ->write;
Luc Didry ac8d76
                    }
Luc Didry cd104c
Luc Didry ac8d76
                    # This check is just in case we didn't succeed to find a corresponding record
Luc Didry ac8d76
                    # It normally can't happen
Luc Didry ac8d76
                    if (defined $f) {
Luc Didry ac8d76
                        # If we already have a part, it's a resend because the websocket has been broken
Luc Didry ac8d76
                        # In this case, we don't need to rewrite the file
Luc Didry ac8d76
                        unless ($f->slices->grep(sub { $_->j == $json->{part} })->size) {
Luc Didry ac8d76
                            # Create directory
Luc Didry ac8d76
                            my $dir = catdir($c->config('upload_dir'), $f->short);
Luc Didry ac8d76
                            mkdir($dir, 0700) unless (-d $dir);
Luc Didry ac8d76
Luc Didry ac8d76
                            # Create slice file
Luc Didry ac8d76
                            my $file = catfile($dir, $json->{part}.'.part');
Luc Didry d909b8
                            my $s    = Lufi::DB::Slice->new(
Luc Didry d909b8
                                app   => $c->app,
Luc Didry ac8d76
                                short => $f->short,
Luc Didry ac8d76
                                j     => $json->{part},
Luc Didry ac8d76
                                path  => $file
Luc Didry ac8d76
                            );
Luc Didry 1fbe93
                            Mojo::File->new($file)->spurt($text);
Luc Didry ac8d76
                            push @{$f->slices}, $s;
Luc Didry ac8d76
                            $s->write;
Luc Didry ac8d76
Luc Didry ac8d76
                            if (($json->{part} + 1) == $json->{total}) {
Luc Didry ac8d76
                                $f->complete(1);
Luc Didry ac8d76
                                $f->created_at(time);
Luc Didry ac8d76
                                $f->write;
Luc Didry ac8d76
                            }
Luc Didry cd104c
                        }
Luc Didry a594b9
Luc Didry ac8d76
                        $c->provisioning;
Luc Didry 10a8dd
Luc Didry d94c2b
                        $ws->send(to_json(
Luc Didry d94c2b
                            {
Luc Didry d94c2b
                                success           => true,
Luc Didry d94c2b
                                i                 => $json->{i},
Luc Didry d94c2b
                                j                 => $json->{part},
Luc Didry d94c2b
                                parts             => $json->{total},
Luc Didry d94c2b
                                short             => $f->short,
Luc Didry d94c2b
                                name              => $f->filename,
Luc Didry d94c2b
                                size              => $f->filesize,
Luc Didry d94c2b
                                del_at_first_view => (($f->delete_at_first_view) ? true : false),
Luc Didry d94c2b
                                created_at        => $f->created_at,
Luc Didry d94c2b
                                delay             => $f->delete_at_day,
Luc Didry d94c2b
                                token             => $f->mod_token,
Luc Didry d94c2b
                                sent_delay        => $json->{delay},
Luc Didry d94c2b
                                duration          => time - $begin
Luc Didry d94c2b
                            }
Luc Didry d94c2b
                        ));
Luc Didry ac8d76
                    } else {
Luc Didry d909b8
                        $ws->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                            {
Luc Didry d94c2b
                                success    => false,
Luc Didry d94c2b
                                msg        => $c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.'),
Luc Didry d94c2b
                                sent_delay => $json->{delay},
Luc Didry d94c2b
                                i          => $json->{i}
Luc Didry d94c2b
                            }
Luc Didry d909b8
                        )));
Luc Didry ac8d76
                    }
Luc Didry cd104c
                }
Luc Didry 10a8dd
            }
Luc Didry ac8d76
        );
Luc Didry ac8d76
        $c->on(
Luc Didry ac8d76
            finish => sub {
Luc Didry ac8d76
                $c->app->log->debug('Client disconnected');
Luc Didry ac8d76
            }
Luc Didry ac8d76
        );
Luc Didry ac8d76
    }
Luc Didry 91e078
}
Luc Didry 91e078
Luc Didry 91e078
sub download {
Luc Didry 91e078
    my $c     = shift;
Luc Didry 91e078
    my $short = $c->param('short');
Luc Didry 91e078
Luc Didry 91e078
    $c->inactivity_timeout(300000);
Luc Didry cd104c
    $c->app->log->debug('Client connected');
Luc Didry 91e078
Luc Didry d909b8
    my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short);
Luc Didry 91e078
Luc Didry 2863f0
    # Do we have a file?
Luc Didry d909b8
    if (defined $ldfile) {
Luc Didry 2863f0
        # Is the file fully uploaded?
Luc Didry d909b8
        if ($ldfile->deleted
Luc Didry 40deab
            || (
Luc Didry d909b8
                $ldfile->delete_at_day != 0
Luc Didry 40deab
                && (
Luc Didry d909b8
                    ($ldfile->created_at + $ldfile->delete_at_day * 86400) < time()
Luc Didry 40deab
                )
Luc Didry 40deab
            )
Luc Didry 40deab
        ) {
Luc Didry d909b8
            unless ($ldfile->deleted) {
Luc Didry d909b8
                $ldfile->delete;
Luc Didry 40deab
            }
Luc Didry 2863f0
            $c->on(
Luc Didry 2863f0
                message => sub {
Luc Didry 2863f0
                    my ($ws, $json) = @_;
Luc Didry d909b8
                    $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                        {
Luc Didry d94c2b
                            success => false,
Luc Didry d94c2b
                            msg     => $c->l('Error: the file existed but was deleted.')
Luc Didry d94c2b
                        }
Luc Didry d909b8
                    )));
Luc Didry 91e078
                }
Luc Didry 2863f0
            );
Luc Didry d909b8
        } elsif ($ldfile->complete) {
Luc Didry d909b8
            my $f = $ldfile;
Luc Didry 2863f0
Luc Didry 2863f0
            $c->on(
Luc Didry 2863f0
                message => sub {
Luc Didry 2863f0
                    my ($ws, $json) = @_;
Luc Didry 2863f0
                    $json = decode_json $json;
Luc Didry 50b1f0
Luc Didry 50b1f0
                    # Do we need a password?
Luc Didry 50b1f0
                    my $valid = 1;
Luc Didry 50b1f0
                    if ($c->config('allow_pwd_on_files') && defined($f->{passwd})) {
Luc Didry 50b1f0
                        my $pwd = $json->{file_pwd};
Luc Didry 50b1f0
                        $valid = Crypt::SaltedHash->validate($f->{passwd}, $json->{file_pwd}, 8);
Luc Didry 50b1f0
                    }
Luc Didry 50b1f0
Luc Didry 50b1f0
                    if ($valid) {
Luc Didry 50b1f0
                        if (defined($json->{part})) {
Luc Didry 50b1f0
                            # Make $num an integer instead of a string
Luc Didry 50b1f0
                            my $num = $json->{part} + 0;
Luc Didry 50b1f0
Luc Didry 50b1f0
                            # Get the slice
Luc Didry 50b1f0
                            my $e    = $f->slices->[$num];
Luc Didry 1fbe93
                            my $text = Mojo::File->new($e->path)->slurp;
Luc Didry 50b1f0
Luc Didry 50b1f0
                            my ($json2) = split('XXMOJOXX', $text, 2);
Luc Didry 50b1f0
                            $json2 = decode 'UTF-8', $json2;
Luc Didry 50b1f0
                            $text =~ s/^.*?XXMOJOXX/${json2}XXMOJOXX/;
Luc Didry 50b1f0
Luc Didry 50b1f0
                            # Send the slice
Luc Didry 50b1f0
                            $c->send($text);
Luc Didry 50b1f0
                        } elsif (defined($json->{ended}) && $json->{ended}) {
Luc Didry 50b1f0
                            $f->counter($f->counter + 1);
Luc Didry 50b1f0
                            $f->last_access_at(time);
Luc Didry 50b1f0
Luc Didry 50b1f0
                            if ($f->delete_at_first_view) {
Luc Didry 50b1f0
                                $f->delete;
Luc Didry 50b1f0
                            } else {
Luc Didry 50b1f0
                                $f->write;
Luc Didry 50b1f0
                            }
Luc Didry 2863f0
                        }
Luc Didry 50b1f0
                    } else {
Luc Didry d909b8
                        $c->send(decode('UTF-8', encode_json(
Luc Didry d909b8
                            {
Luc Didry d909b8
                                msg => $c->l('Your password is not valid. Please refresh the page to retry.')
Luc Didry d909b8
                            }
Luc Didry d909b8
                        )));
Luc Didry 2863f0
                    }
Luc Didry 2863f0
                }
Luc Didry 2863f0
            );
Luc Didry 2863f0
            $c->on(
Luc Didry 2863f0
                finish => sub {
Luc Didry cd104c
                    $c->app->log->debug('Client disconnected');
Luc Didry 2863f0
                }
Luc Didry 2863f0
            );
Luc Didry 2863f0
        } else {
Luc Didry 2863f0
            $c->on(
Luc Didry 2863f0
                message => sub {
Luc Didry 2863f0
                    my ($ws, $json) = @_;
Luc Didry d909b8
                    $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
                        {
Luc Didry d94c2b
                            success => false,
Luc Didry d94c2b
                            msg     => $c->l('Error: the file has not been sent entirely.')
Luc Didry d94c2b
                        }
Luc Didry d909b8
                    )));
Luc Didry 2863f0
                }
Luc Didry 2863f0
            );
Luc Didry 91e078
        }
Luc Didry 2863f0
    } else {
Luc Didry d909b8
        $c->send(decode('UTF-8', encode_json(
Luc Didry d94c2b
            {
Luc Didry d94c2b
                success => false,
Luc Didry d94c2b
                msg     => $c->l('Error: unable to find the file. Are you sure of your URL?')
Luc Didry d94c2b
            }
Luc Didry d909b8
        )));
Luc Didry 2863f0
    }
Luc Didry 91e078
}
Luc Didry 91e078
Luc Didry 91e078
sub r {
Luc Didry 91e078
    my $c     = shift;
Luc Didry 91e078
    my $short = $c->param('short');
Luc Didry 91e078
Luc Didry d909b8
    my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short);
Luc Didry d909b8
Luc Didry d909b8
    if (defined $ldfile) {
Luc Didry 91e078
        return $c->render(
Luc Didry 91e078
            template => 'render',
Luc Didry d909b8
            f        => $ldfile,
Luc Didry d909b8
            file_pwd => ($c->config('allow_pwd_on_files') && defined($ldfile->passwd))
Luc Didry 91e078
        );
Luc Didry 91e078
    } else {
Luc Didry 91e078
        return $c->render(
Luc Didry 91e078
            template => 'render',
Luc Didry 91e078
            msg      => $c->l('Could not find the file. Are you sure of the URL?')
Luc Didry 91e078
        );
Luc Didry 91e078
    }
Luc Didry 91e078
}
Luc Didry 91e078
Luc Didry 91e078
sub get_counter {
Luc Didry 91e078
    my $c     = shift;
Luc Didry 91e078
    my $short = $c->param('short');
Luc Didry 91e078
    my $token = $c->param('token');
Luc Didry 91e078
Yann dbdaff
    if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) {
Luc Didry d909b8
        my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short);
Luc Didry d909b8
Luc Didry d909b8
        if (defined $ldfile) {
Luc Didry d909b8
            if ($ldfile->mod_token eq $token) {
Luc Didry ac8d76
                return $c->render(
Luc Didry ac8d76
                    json => {
Luc Didry ac8d76
                        success => true,
Luc Didry ac8d76
                        short   => $short,
Luc Didry d909b8
                        counter => $ldfile->counter,
Luc Didry d909b8
                        deleted => ($ldfile->deleted) ? true : false
Luc Didry ac8d76
                    }
Luc Didry ac8d76
                );
Luc Didry ac8d76
            } else {
Luc Didry ac8d76
                return $c->render(
Luc Didry ac8d76
                    json => {
Luc Didry ac8d76
                        success => false,
Luc Didry ac8d76
                        missing => false,
Luc Didry ac8d76
                        short   => $short,
Luc Didry ac8d76
                        msg     => $c->l('Unable to get counter for %1. The token is invalid.', $short)
Luc Didry ac8d76
                    }
Luc Didry ac8d76
                );
Luc Didry ac8d76
            }
Luc Didry 60e157
        } else {
Luc Didry 60e157
            return $c->render(
Luc Didry 60e157
                json => {
Luc Didry 60e157
                    success => false,
Luc Didry ac8d76
                    missing => true,
Luc Didry 60e157
                    short   => $short,
Luc Didry ac8d76
                    msg     => $c->l('Unable to get counter for %1. The file does not exists. It will be removed from your localStorage.', $short)
Luc Didry 60e157
                }
Luc Didry 60e157
            );
Luc Didry 60e157
        }
Luc Didry 2863f0
    } else {
Luc Didry 2863f0
        return $c->render(
Luc Didry 2863f0
            json => {
Luc Didry 2863f0
                success => false,
Luc Didry ac8d76
                missing => false,
Luc Didry 60e157
                short   => $short,
Luc Didry ac8d76
                msg     => $c->l('Unable to get counter for %1. You are not authenticated.', $short)
Luc Didry 2863f0
            }
Luc Didry 2863f0
        );
Luc Didry 91e078
    }
Luc Didry 91e078
}
Luc Didry 91e078
Luc Didry 91e078
sub delete {
Luc Didry 91e078
    my $c     = shift;
Luc Didry 91e078
    my $short = $c->param('short');
Luc Didry 91e078
    my $token = $c->param('token');
Luc Didry 91e078
Yann dbdaff
    if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) {
Luc Didry d909b8
        my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short);
Luc Didry d909b8
Luc Didry d909b8
        $ldfile = undef unless (defined($ldfile) && $ldfile->mod_token eq $token);
Luc Didry d909b8
Luc Didry d909b8
        if (defined $ldfile) {
Luc Didry ac8d76
            my $msg;
Luc Didry d909b8
            if ($ldfile->deleted) {
Luc Didry ac8d76
                $msg = $c->l('The file has already been deleted');
Luc Didry ac8d76
            } else {
Luc Didry d909b8
                $ldfile->delete;
Luc Didry ac8d76
                $msg = $c->l('File deleted');
Luc Didry ac8d76
            }
Luc Didry ac8d76
            return $c->respond_to(
Luc Didry ac8d76
                json => {
Luc Didry abebf6
                    json => {
Luc Didry abebf6
                        success => true,
Luc Didry abebf6
                        msg     => $msg
Luc Didry abebf6
                    }
Luc Didry ac8d76
                },
Luc Didry ac8d76
                any => sub {
Luc Didry ac8d76
                    $c->render(
Luc Didry ac8d76
                        template => 'msg',
Luc Didry d909b8
                        f        => $ldfile,
Luc Didry ac8d76
                        msg      => $msg
Luc Didry ac8d76
                    );
Luc Didry ac8d76
                }
Luc Didry ac8d76
            );
Luc Didry 91e078
        } else {
Luc Didry ac8d76
            my $msg = $c->l('Could not find the file. Are you sure of the URL and the token?');
Luc Didry ac8d76
            return $c->respond_to(
Luc Didry ac8d76
                json => {
Luc Didry abebf6
                    json => {
Luc Didry abebf6
                        success => false,
Luc Didry abebf6
                        msg     => $msg
Luc Didry abebf6
                    }
Luc Didry ac8d76
                },
Luc Didry ac8d76
                any => sub {
Luc Didry ac8d76
                    $c->render(
Luc Didry ac8d76
                        template => 'msg',
Luc Didry ac8d76
                        f        => undef,
Luc Didry ac8d76
                        msg      => $msg
Luc Didry ac8d76
                    );
Luc Didry ac8d76
                }
Luc Didry ac8d76
            );
Luc Didry 91e078
        }
Luc Didry 91e078
    } else {
Luc Didry ac8d76
        my $msg = $c->l('Could not delete the file. You are not authenticated.');
Luc Didry 91e078
        return $c->respond_to(
Luc Didry 91e078
            json => {
Luc Didry abebf6
                json => {
Luc Didry abebf6
                    success => false,
Luc Didry abebf6
                    msg     => $msg
Luc Didry abebf6
                }
Luc Didry 91e078
            },
Luc Didry 91e078
            any => sub {
Luc Didry 91e078
                $c->render(
Luc Didry 91e078
                    template => 'msg',
Luc Didry 91e078
                    f        => undef,
Luc Didry 91e078
                    msg      => $msg
Luc Didry 91e078
                );
Luc Didry 91e078
            }
Luc Didry 91e078
        );
Luc Didry 91e078
    }
Luc Didry 91e078
}
Luc Didry 91e078
Luc Didry 91e078
1;