# BetterFileUploader.pm
# Better File Uploader plugin for Movable Type
# by Dan Wolfgang
# http://www.danandsherree.com
# last modified 07/24/2006

package BetterFileUploader;

use strict;
use base 'MT::App';
use base 'MT::App::CMS';
use MT::Util qw( encode_url );



sub init {
	my $app = shift;
	$app->SUPER::init(@_) or return;
	$app->add_methods(
		'start_upload_entry' => \&start_upload_entry,
		'start_upload_extended_entry' => \&start_upload_extended_entry,
		'show_upload_html' => \&show_upload_html,
	);
	$app->{default_mode} = 'default';
	$app->{requires_login} = 1;
	$app;
}


sub default {
	print "Content-Type: text/html\n\n";
	print "You can't access Better File Uploader this way!\n";
}




sub show_upload_html {
    my $app = shift;
    defined(my $text = $app->process_upload) or return;
    $app->build_page('upload_show.tmpl', { upload_html => $text, blog_id => $app->param('blog_id') });
}

sub start_upload_entry {
    my $app = shift;
    my $q = $app->param;
    $q->param('_type', 'entry');
    defined(my $text = $app->process_upload) or return;
    $q->param('text', $text);
	$app->redirect( $app->mt_uri . '__mode=view&_type=entry&blog_id=1&text=test' );
#    $app->edit_object;
}

sub start_upload_extended_entry {
    my $app = shift;
    my $q = $app->param;
    $q->param('_type', 'entry');
    defined(my $text = $app->process_upload) or return;
    $q->param('text_more', $text);
    $app->edit_object;
}

# This is the rewritten version of the _process_post_upload subroutine.
sub process_upload {
    my $app = shift;
    my $q = $app->param;
    my($url, $width, $height) = map $q->param($_), qw( url width height );
    my ($base_url, $fname) = $url =~ m|(.*)/([^/]*)|;
    $url = $base_url . '/' . $fname; # no need to re-encode filename; url is already encoded
    my $blog_id = $q->param('blog_id');
    require MT::Blog;
    my $blog = MT::Blog->load($blog_id, {cached_ok=>1});
    my($thumb, $thumb_width, $thumb_height);
    if ($thumb = $q->param('thumb')) {
        require MT::Image;
        my $base_path = $q->param('site_path') ?
            $blog->site_path : $blog->archive_path;
        my $file = $q->param('fname');
        if ($file =~ m!\.\.|\0|\|!) {
            return $app->error($app->translate("Invalid filename '[_1]'", $file));
        }
        my $i_file = File::Spec->catfile($base_path, $file);
        ## Untaint. We checked $file for security holes above.
        ($i_file) = $i_file =~ /(.+)/s;
        my $fmgr = $blog->file_mgr;
        my $data = $fmgr->get_data($i_file, 'upload')
            or return $app->error($app->translate(
                "Reading '[_1]' failed: [_2]", $i_file, $fmgr->errstr));
        my $image_type = scalar $q->param('image_type');
        my $img = MT::Image->new( Data => $data,
                                  Type => $image_type )
            or return $app->error($app->translate(
                "Thumbnail failed: [_1]", MT::Image->errstr));
        my($w, $h) = map $q->param($_), qw( thumb_width thumb_height );
        (my($blob), $thumb_width, $thumb_height) =
            $img->scale( Width => $w, Height => $h )
            or return $app->error($app->translate("Thumbnail failed: [_1]",
                $img->errstr));
        require File::Basename;
        my($base, $path, $ext) = File::Basename::fileparse($i_file, '\.[^.]*');
        my $t_file = $path . $base . '-thumb' . $ext;
        $fmgr->put_data($blob, $t_file, 'upload')
            or return $app->error($app->translate(
                "Error writing to '[_1]': [_2]", $t_file, $fmgr->errstr));

        $file =~ s/\Q$base$ext\E$//;
        my $url = $q->param('site_path') ? $blog->site_url : $blog->archive_url;
        $url .= '/' unless $url =~ m!/$!;
        $url .= $file;
        $thumb = $url . encode_url($base . '-thumb' . $ext);
        MT->run_callbacks('CMSUploadFile',
                          File => $t_file, Url => $thumb, Size => length($blob),
                          Type => 'thumbnail',
                          Blog => $blog);
        MT->run_callbacks('CMSUploadImage',
                          File => $t_file, Url => $thumb,
                          Width => $thumb_width, Height => $thumb_height,
                          ImageType => $image_type,
                          Size => length($blob),
                          Type => 'thumbnail',
                          Blog => $blog);
    }
    if ($q->param('popup')) {
        require MT::Template;
        if (my $tmpl = MT::Template->load({ blog_id => $blog_id,
                                            type => 'popup_image' })) {
            (my $rel_path = $q->param('fname')) =~ s!\.[^.]*$!!;
            if ($rel_path =~ m!\.\.|\0|\|!) {
                return $app->error($app->translate(
                    "Invalid basename '[_1]'", $rel_path));
            }
            my $ext = $blog->file_extension || '';
            $ext = '.' . $ext if $ext ne '';
            require MT::Template::Context;
            my $ctx = MT::Template::Context->new;
            $ctx->stash('image_url', $url);
            $ctx->stash('image_width', $width);
            $ctx->stash('image_height', $height);
            my $popup = $tmpl->build($ctx);
            my $fmgr = $blog->file_mgr;
            my $root_path = $q->param('site_path') ?
                $blog->site_path : $blog->archive_path;
            my $abs_file_path = File::Spec->catfile($root_path, $rel_path . $ext);

            ## If the popup filename already exists, we don't want to overwrite
            ## it, because it could contain valuable data; so we'll just make
            ## sure to generate the name uniquely.
            my($i, $rel_path_ext) = (0, $rel_path . $ext);
            while ($fmgr->exists($abs_file_path)) {
                $rel_path_ext = $rel_path . ++$i . $ext;
                $abs_file_path = File::Spec->catfile($root_path, $rel_path_ext);
            }
            my ($vol, $dirs, $basename) = File::Spec->splitpath($rel_path_ext);
            my $rel_url_ext = File::Spec->catpath($vol, $dirs, encode_url($basename));

            ## Untaint. We have checked for security holes above, so we
            ## should be safe.
            ($abs_file_path) = $abs_file_path =~ /(.+)/s;
            $fmgr->put_data($popup, $abs_file_path, 'upload')
                or return $app->error($app->translate(
                   "Error writing to '[_1]': [_2]", $abs_file_path,
                                                     $fmgr->errstr));
            $url = $q->param('site_path') ?
                $blog->site_url : $blog->archive_url;
            $url .= '/' unless $url =~ m!/$!;
            $rel_url_ext =~ s!^/!!;
            $url .= $rel_url_ext;
            MT->run_callbacks('CMSUploadFile',
                          File => $abs_file_path, Url => $url,
                          Size => length($popup),
                          Type => 'popup',
                          Blog => $blog);
        }
        my $link = $thumb ? qq(<img src="$thumb" width="$thumb_width" height="$thumb_height" alt="$fname" />) : q{<MT_TRANS phrase="View image">};
        return $app->translate_templatized(<<"HTML");
<a href="$url" onclick="window.open('$url','popup','width=$width,height=$height,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false">$link</a>
HTML
    } elsif ($q->param('include')) {
        if ($thumb) {
            return qq(<a href="$url"><img alt="$fname" src="$thumb" width="$thumb_width" height="$thumb_height" /></a>);
        } else {
            return qq(<img alt="$fname" src="$url" width="$width" height="$height" />);
        }
    } elsif ($q->param('photogallery')) {
        (my $fname = $url) =~ s!^(.*)\.jpg!$1!i;
            return $fname;
    } elsif ($q->param('link')) {
        return $app->translate_templatized(<<"HTML");
<a href="$url"><MT_TRANS phrase="Download file"></a>
HTML
    }
}



1;
