site/cgi-bin/modules/Apache/Session/DBIreal.pm
site/cgi-bin/modules/Apache/Session/Store/DBIreal.pm
site/cgi-bin/modules/Article.pm
-site/cgi-bin/modules/ArticleFile.pm
-site/cgi-bin/modules/ArticleFiles.pm
site/cgi-bin/modules/Articles.pm
site/cgi-bin/modules/BSE/API.pm
site/cgi-bin/modules/BSE/Admin/StepParents.pm
site/cgi-bin/modules/BSE/EmailBlacklist.pm
site/cgi-bin/modules/BSE/EmailRequest.pm
site/cgi-bin/modules/BSE/EmailRequests.pm
+site/cgi-bin/modules/BSE/FileHandler/Base.pm
+site/cgi-bin/modules/BSE/FileHandler/Default.pm
+site/cgi-bin/modules/BSE/FileHandler/FLV.pm
site/cgi-bin/modules/BSE/Formatter.pm
site/cgi-bin/modules/BSE/Formatter/Article.pm
site/cgi-bin/modules/BSE/Formatter/Subscription.pm
site/cgi-bin/modules/BSE/TB/AdminPerms.pm
site/cgi-bin/modules/BSE/TB/AdminUser.pm
site/cgi-bin/modules/BSE/TB/AdminUsers.pm
+site/cgi-bin/modules/BSE/TB/ArticleFile.pm
+site/cgi-bin/modules/BSE/TB/ArticleFileMeta.pm
+site/cgi-bin/modules/BSE/TB/ArticleFileMetas.pm
+site/cgi-bin/modules/BSE/TB/ArticleFiles.pm
site/cgi-bin/modules/BSE/TB/BackgroundTask.pm
site/cgi-bin/modules/BSE/TB/BackgroundTasks.pm
site/cgi-bin/modules/BSE/TB/FileAccessLog.pm
site/htdocs/css/admin.css_natural
site/htdocs/css/style-main.css
site/htdocs/favicon.ico
+site/htdocs/images/50.png
site/htdocs/images/admin/busy.gif
site/htdocs/images/admin/checked.gif
site/htdocs/images/admin/error.gif
site/htdocs/images/titles/the_shop.gif
site/htdocs/images/titles/your_site.gif
site/htdocs/images/trans_pixel.gif
+site/htdocs/images/videoclose.png
# site/htdocs/js/admin_dragdrop.js
site/htdocs/js/admin_prodopts.js
+site/htdocs/js/bse.js
site/htdocs/js/builder.js
site/htdocs/js/controls.js
site/htdocs/js/date.js
site/htdocs/js/scriptoverride.js
site/htdocs/js/slider.js
site/htdocs/js/sound.js
+site/htdocs/js/swfobject.js
+site/htdocs/swf/flvplayer.swf
# site/htdocs/shop created by the Makefile
site/templates/1/shop_multicat.tmpl
site/templates/1/sitemap.tmpl
site/templates/include/usermenu.tmpl
site/templates/index.tmpl
site/templates/index2.tmpl
+site/templates/inline/flv.tmpl
+site/templates/inline/flv_small.tmpl
site/templates/interest/askagain_base.tmpl
site/templates/interest/confirm_base.tmpl
site/templates/interest/error_base.tmpl
storage varchar(20) not null default 'local',
src varchar(255) not null default '',
+ category varchar(20) not null default '',
+ file_handler varchar(20) not null default '',
primary key (id)
);
+drop table if exists bse_article_file_meta;
+create table bse_article_file_meta (
+ id integer not null auto_increment primary key,
+
+ -- refers to article_files
+ file_id integer not null,
+
+ -- name of this metadata
+ name varchar(20) not null,
+
+ content_type varchar(80) not null default 'text/plain',
+ value longblob not null,
+
+ unique file_name(file_id, name)
+);
+
-- these are mailing list subscriptions
drop table if exists subscription_types;
create table subscription_types (
#!/usr/bin/perl -w
# -d:ptkdb
-BEGIN { $ENV{DISPLAY} = '192.168.32.51:0.0' }
+BEGIN { $ENV{DISPLAY} = '192.168.32.54:0.0' }
use strict;
use FindBin;
use CGI::Carp 'fatalsToBrowser';
[basic]
randomdata = /dev/urandom
access_control=0
+file_handlers=flv
[paths]
; the following needs to be set to a path writable by the BSE processes
[thumb geometries]
editor=scale(200x200)
+
+[file handlers]
+flv=BSE::FileHandler::FLV
sub files {
my ($self) = @_;
- require ArticleFiles;
- return ArticleFiles->getBy(articleId=>$self->{id});
+ require BSE::TB::ArticleFiles;
+ return BSE::TB::ArticleFiles->getBy(articleId=>$self->{id});
}
sub parent {
+++ /dev/null
-package ArticleFile;
-use strict;
-# represents a file associated with an article from the database
-use Squirrel::Row;
-use vars qw/@ISA/;
-@ISA = qw/Squirrel::Row/;
-use Carp 'confess';
-
-sub columns {
- return qw/id articleId displayName filename sizeInBytes description
- contentType displayOrder forSale download whenUploaded
- requireUser notes name hide_from_list storage src/;
-}
-
-sub remove {
- my ($self, $cfg) = @_;
-
- $cfg or confess "No \$cfg supplied to ",ref $self,"->remove()";
-
- my $downloadPath = $cfg->entryErr('paths', 'downloads');
- my $filename = $downloadPath . "/" . $self->{filename};
- my $debug_del = $cfg->entryBool('debug', 'file_unlink', 0);
- if ($debug_del) {
- unlink $filename
- or print STDERR "Error deleting $filename: $!\n";
- }
- else {
- unlink $filename;
- }
-
- $self->SUPER::remove();
-}
-
-sub article {
- my $self = shift;
- require Articles;
-
- return Articles->getByPkey($self->{articleId});
-}
-
-1;
+++ /dev/null
-package ArticleFiles;
-use strict;
-use Squirrel::Table;
-use vars qw(@ISA $VERSION);
-@ISA = qw(Squirrel::Table);
-use ArticleFile;
-
-sub rowClass {
- return 'ArticleFile';
-}
-
-sub file_storages {
- my $self = shift;
- return map [ $_->{filename}, $_->{storage}, $_ ], $self->all;
-}
-
-1;
sub global_files {
my ($self) = @_;
- require ArticleFiles;
- return ArticleFiles->getBy(articleId => -1);
+ require BSE::TB::ArticleFiles;
+ return BSE::TB::ArticleFiles->getBy(articleId => -1);
}
1;
ArticleFiles => 'select * from article_files',
addArticleFile =>
- 'insert into article_files values (null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ 'insert into article_files values (null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
replaceArticleFile =>
- 'replace article_files values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ 'replace article_files values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
deleteArticleFile => 'delete from article_files where id = ?',
getArticleFileByArticleId =>
'select * from article_files where articleId = ? order by displayOrder desc',
$parent = $articles->getByPkey($article->{id});
}
- my $shopid = $self->{cfg}->entryErr('articles', 'shop');
+ my $shopid = $self->cfg->entryErr('articles', 'shop');
return $article->{parentid} && $parent &&
($article->{parentid} == $shopid ||
my %labels;
my @values;
- my $shopid = $self->{cfg}->entryErr('articles', 'shop');
+ my $shopid = $self->cfg->entryErr('articles', 'shop');
my @parents = $articles->getBy('level', $article->{level}-1);
@parents = grep { $_->{generator} eq 'Generate::Article'
&& $_->{id} != $shopid } @parents;
my ($self, $article) = @_;
my @title_images;
- my $imagedir = cfg_image_dir($self->{cfg});
+ my $imagedir = cfg_image_dir($self->cfg);
if (opendir TITLE_IMAGES, "$imagedir/titles") {
@title_images = sort
grep -f "$imagedir/titles/$_" && /\.(gif|jpeg|jpg|png)$/i,
my @dirs = $self->base_template_dirs;
if (my $parentid = $article->{parentid}) {
my $section = "children of $parentid";
- if (my $dirs = $self->{cfg}->entry($section, 'template_dirs')) {
+ if (my $dirs = $self->cfg->entry($section, 'template_dirs')) {
push @dirs, split /,/, $dirs;
}
}
my $imagedir = $cfg->entry('paths', 'images', $Constants::IMAGEDIR);
my $error;
- ($data, $type) = $thumb_obj->
- thumb_data("$imagedir/$image->{image}", $geometry, \$error)
+ ($data, $type) = $thumb_obj->thumb_data
+ (
+ filename => "$imagedir/$image->{image}",
+ geometry => $geometry,
+ error => \$error
+ )
or return
{
type => 'text/plain',
description => 'Identifier',
maxlength => 80,
},
+ category =>
+ {
+ description => "Category",
+ maxlength => 20,
+ },
);
sub fileadd {
my %file;
my $cgi = $req->cgi;
- require ArticleFile;
- my @cols = ArticleFile->columns;
+ require BSE::TB::ArticleFiles;
+ my @cols = BSE::TB::ArticleFile->columns;
shift @cols;
for my $col (@cols) {
if (defined $cgi->param($col)) {
$file{download} = 0 + exists $file{download};
$file{requireUser} = 0 + exists $file{requireUser};
$file{hide_from_list} = 0 + exists $file{hide_from_list};
+ $file{category} ||= '';
my $downloadPath = $self->{cfg}->entryVar('paths', 'downloads');
$file{whenUploaded} = now_datetime();
$file{storage} = 'local';
$file{src} = '';
+ $file{file_handler} = "";
- require ArticleFiles;
- my $fileobj = ArticleFiles->add(@file{@cols});
+ require BSE::TB::ArticleFiles;
+ my $fileobj = BSE::TB::ArticleFiles->add(@file{@cols});
$req->flash("New file added");
my $src;
$storage = $self->_select_filestore($req, $file_manager, $storage, $fileobj);
$src = $file_manager->store($filename, $storage, $fileobj);
-
+
if ($src) {
$fileobj->{src} = $src;
$fileobj->{storage} = $storage;
$req->flash($@);
}
+ $fileobj->set_handler($req->cfg);
+ $fileobj->save;
+
use Util 'generate_article';
generate_article($articles, $article) if $Constants::AUTO_GENERATE;
"You don't have access to save file information for this article");
my @files = $self->get_files($article);
- my $download_path = $self->{cfg}->entryVar('paths', 'downloads');
+ my $download_path = BSE::TB::ArticleFiles->download_path($self->{cfg});
my $cgi = $req->cgi;
my %names;
my @old_files;
my @new_files;
my %store_anyway;
+ my @content_changed;
for my $file (@files) {
my $id = $file->{id};
my $desc = $cgi->param("description_$id");
}
my $notes = $cgi->param("notes_$id");
defined $notes and $file->{notes} = $notes;
+ my $category = $cgi->param("category_$id");
+ defined $category and $file->{category} = $category;
my $name = $cgi->param("name_$id");
if (defined $name) {
$file->{name} = $name;
$file->{sizeInBytes} = -s $full_name;
$file->{whenUploaded} = now_datetime();
$file->{displayName} = $display_name;
+ push @content_changed, $file;
}
else {
$errors{"file_$id"} = $msg;
unlink "$download_path/$filename";
}
+ # update file type metadatas
+ for my $file (@content_changed) {
+ $file->set_handler($self->{cfg});
+ $file->save;
+ }
+
use Util 'generate_article';
generate_article($articles, $article) if $Constants::AUTO_GENERATE;
"You don't have access to save file information for this article");
my @other_files = grep $_->{id} != $id, @files;
- my $download_path = $self->{cfg}->entryVar('paths', 'downloads');
+ my $download_path = BSE::TB::ArticleFiles->download_path($self->{cfg});
my %errors;
use strict;
use BSE::Util::Tags;
use Constants qw($TMPLDIR $IMAGES_URI);
-use ArticleFiles;
+use BSE::TB::ArticleFiles;
use Util qw/refresh_to/;
=head1 NAME
- BSE::FileEditor - maintains a list of images associated with an article
+ BSE::FileEditor - maintains a list of files associated with an article
=head1 SYNOPSIS
my %file;
- my @cols = ArticleFile->columns;
+ my @cols = BSE::TB::ArticleFile->columns;
shift @cols;
for my $col (@cols) {
if (defined $self->{cgi}->param($col)) {
$file{displayOrder} = time;
$file{whenUploaded} = now_datetime();
- my $fileobj = ArticleFiles->add(@file{@cols});
+ my $fileobj = BSE::TB::ArticleFiles->add(@file{@cols});
$self->_refresh_list($article);
}
my ($self, $article) = @_;
return sort { $b->{displayOrder} <=> $a->{displayOrder} }
- ArticleFiles->getBy(articleId=>$article->{id});
+ BSE::TB::ArticleFiles->getBy(articleId=>$article->{id});
}
1;
--- /dev/null
+package BSE::FileHandler::Base;
+use strict;
+use Carp qw(confess);
+
+sub new {
+ my ($class, $cfg) = @_;
+
+ $cfg
+ or confess "Missing cfg option";
+
+ return bless
+ {
+ cfg => $cfg,
+ }, $class;
+}
+
+sub cfg {
+ $_[0]{cfg};
+}
+
+sub cfg_entry {
+ my ($self, $key, $def) = @_;
+
+ return $self->cfg->entry($self->section, $key, $def);
+}
+
+sub process_file {
+ my ($self, $file) = @_;
+
+ my $class = ref $self;
+ confess "$class hasn't implemented process-file";
+}
+
+1;
--- /dev/null
+package BSE::FileHandler::Default;
+use strict;
+use base "BSE::FileHandler::Base";
+use DevHelp::HTML;
+
+sub process_file {
+ my ($self, $file) = @_;
+
+ # accept the file, but do nothing
+
+ 1;
+}
+
+sub inline {
+ my ($self, $file) = @_;
+
+ my $url = $file->url;
+ my $eurl = escape_html($url);
+ my $class = $file->{download} ? "file_download" : "file_inline";
+ my $html = qq!<a class="$class" href="$eurl">! . escape_html($file->{displayName}) . '</a>';
+ return $html;
+}
+
+1;
--- /dev/null
+package BSE::FileHandler::FLV;
+use strict;
+use base "BSE::FileHandler::Base";
+use BSE::Util::Tags qw(tag_hash);
+use DevHelp::HTML;
+
+sub process_file {
+ my ($self, $file) = @_;
+
+ my %info;
+ unless
+ (eval {
+ local $SIG{__DIE__};
+ require FLV::Info;
+ my $reader = FLV::Info->new;
+ $reader->parse($file->full_filename($self->cfg));
+ %info = $reader->get_info;
+ 1;
+ }) {
+ die "Cannot parse as FLV: $@\n";
+ }
+
+ $info{video_width} && $info{video_height} && $info{duration}
+ or die "Missing required metadata\n";
+
+ $file->add_meta(name => 'width', value => $info{video_width});
+ $file->add_meta(name => 'height', value => $info{video_height});
+ my $dur_secs = sprintf("%.0f", $info{duration}/1000);
+ $file->add_meta(name => 'duration', value => $dur_secs);
+ my $fmt_dur = sprintf("%02d:%02d:%02d", $dur_secs / 3600, ($dur_secs / 60) % 60,
+ $dur_secs % 60);
+ $file->add_meta(name => "duration_formatted", value => $fmt_dur);
+ $file->add_meta(name => 'audio_type', value => $info{audio_type});
+
+ my $section = "flv handler";
+ if ($self->cfg_entry("ffmpeg", 1)) {
+ my $raw_frame = $self->cfg_entry("raw_frame", 1);
+ my $fmt = $self->cfg_entry("frame_fmt", "jpeg");
+ my $content_type = $self->cfg_entry("frame_content_type", "image/$fmt");
+ my $bin = $self->cfg_entry("ffmpeg_bin", "ffmpeg");
+ my $debug = $self->cfg_entry("debug", 0);
+ my @geo_names = split /,/, $self->cfg_entry("frame_thumbs");
+ my @cvt_options = split /,/, $self->cfg_entry("ffmpeg_options");
+ my $cmd = "$bin -i " . $file->full_filename($self->cfg) . " -vcodec ppm -ss 5 -vframes 1 @cvt_options -f image2 -";
+ my $redir = $debug ? "" : "2>/dev/null";
+ my $ppm_data = `$cmd $redir`;
+
+ $?
+ and die "Cannot extract placeholder image\n";
+
+ if ($raw_frame) {
+ my $image_data = '';
+ require Imager;
+ my $im = Imager->new;
+ $im->read(data => $ppm_data, type => "pnm")
+ or die "Cannot load placeholder image: ", $im->errstr, "\n";
+
+ $im->write(data => \$image_data, type => $fmt, @cvt_options)
+ or die "Cannot produce final placeholder data: ", $im->errstr, "\n";
+ $file->add_meta(name => "ph_data",
+ value => $image_data,
+ content_type => $content_type);
+ }
+
+ if (@geo_names) {
+ my $thumbs = $self->_get_thumbs_class;
+ for my $geo_name (@geo_names) {
+ my $geometry = $self->cfg->entry('thumb geometries', $geo_name)
+ or die "Cannot find thumb geometry $geo_name\n";
+ my $thumb_data = '';
+ my $error;
+ my ($twidth, $theight, $type, $original) =
+ $thumbs->thumb_dimensions_sized
+ (
+ $geometry,
+ $info{video_width},
+ $info{video_height},
+ undef
+ );
+ ($thumb_data, $content_type) = $thumbs->thumb_data
+ (
+ data => $ppm_data,
+ geometry => $geometry,
+ error => \$error
+ )
+ or die "Cannot thumb captured frame; $error\n";
+ $file->add_meta(name => "ph_${geo_name}_width",
+ value => $twidth);
+ $file->add_meta(name => "ph_${geo_name}_height",
+ value => $theight);
+ $file->add_meta(name => "ph_${geo_name}_data",
+ value => $thumb_data,
+ content_type => $content_type);
+ }
+ }
+
+ }
+
+ return 1;
+}
+
+sub section {
+ return "flv handler";
+}
+
+sub _get_thumbs_class {
+ my ($self) = @_;
+
+ my $class = $self->cfg->entry('editor', 'thumbs_class')
+ or return;
+
+ (my $filename = "$class.pm") =~ s!::!/!g;
+ eval { require $filename; };
+ if ($@) {
+ print STDERR "** Error loading thumbs_class $class ($filename): $@\n";
+ return;
+ }
+ my $obj;
+ eval { $obj = $class->new($self->{cfg}) };
+ if ($@) {
+ print STDERR "** Error creating thumbs objects $class: $@\n";
+ return;
+ }
+
+ return $obj;
+}
+
+sub inline {
+ my ($self, $file, $parms) = @_;
+
+ defined $parms or $parms = '';
+
+ require BSE::Template;
+ my %meta = map { $_->name => $_->value }
+ grep $_->content_type eq "text/plain", $file->metadata;
+
+ my $base_template = "inline/flv";
+ my $template = $base_template;
+ if ($parms =~ s/\btemplate=(\w+)//
+ || $parms =~ /^(\w+)$/) {
+ $template .= "_$1";
+ }
+
+ my %acts =
+ (
+ BSE::Util::Tags->static(undef, $self->cfg),
+ meta => [ \&tag_hash, \%meta ],
+ file => [ \&tag_hash, $file ],
+ src => scalar(escape_html($file->url)),
+ );
+
+ return BSE::Template->get_page($template, $self->cfg, \%acts, );
+}
+
+1;
+
+=item NAME
+
+BSE::FileHandler::FLV - file metadata generator for FLV files
+
+=item Configuration
+
+ [flv handler]
+ ffmpeg=1
+ raw_frame=1
+ frame_fmt=jpeg
+ ; following defaults to image/(frame_fmt)
+ frame_content_type=image/jpeg
+ ffmpeg_bin=ffmpeg
+ frame_thumbs=geoname1,geoname2
+
+=over
+
+=item *
+
+ffmpeg - if non-zero, which is the default, ffmpeg is used to extract
+a single frame for use as a placeholder image.
+
+=item *
+
+raw_frame - if non-zero, which is the default, the frame extracted
+with ffmpeg is added as metadata with name C<ph_data>.
+
+=item *
+
+frame_fmt - the image format of the C<ph_data> image. Default: jpeg.
+
+=item *
+
+frame_content_type - the MIME content type of the C<ph_data> image,
+defaults to "image/" followed by the value of frame_fmt.
+
+=item *
+
+ffmpeg_bin - the name of the ffmpeg binary. If ffmpeg is in the PATH
+this can be left as just C<ffmpeg>, otherwise set this to the full
+path to ffmpeg.
+
+=item *
+
+frame_thumbs - geometry names separated by commas for extra
+thumbnailed placeholder images, attached as C<ph_>I<geometry>C<_data>
+metadata to the file, with the width and height in
+C<ph_>I<geometry>C<_width> and C<ph_>I<geometry>C<_height>.
+
+=back
+
+=cut
return $self->_file($file, $text, $type);
}
+sub file {
+ my ($self, $fileid, $field, $type) = @_;
+
+ my ($file) = grep $_->{name} eq $fileid, @{$self->{files}}
+ or return "* unknown file $fileid *";
+
+ return $file->inline
+ (
+ field => $field,
+ cfg => $self->{gen}->cfg,
+ );
+}
+
sub thumbimage {
my ($self, $geo_id, $image_id) = @_;
and return 1;
$$rpart =~ s#filelink\[\s*(\w+)\s*\]# $self->filelink($1, undef, 'filelink') #ige
and return 1;
+ $$rpart =~ s#file\[(\w+)(?:\|([\w.]*))?\]# $self->file($1, $2, 'file') #ige
+ and return 1;
$$rpart =~ s#gpopimage\[([^\[\]]+)\]# $self->gpopimage($1) #ige
and return 1;
$$rpart =~ s#popimage\[([^\[\]]+)\]# $self->popimage($1) #ige
sub thumb {
my ($self, %opts) = @_;
- $DB::single=1;
-
my $geo_id = delete $opts{geo};
defined $geo_id
or confess "Missing geo parameter";
my $user = get_siteuser($session, $cfg, $cgi);
if (!$user && $reg_if_files) {
- require ArticleFiles;
+ require BSE::TB::ArticleFiles;
# scan to see if any of the products have files
# requires a subscription or subscribes
for my $prod (@$cart_prods) {
- my @files = ArticleFiles->getBy(articleId=>$prod->{id});
+ my @files = BSE::TB::ArticleFiles->getBy(articleId=>$prod->{id});
if (grep $_->{forSale}, @files) {
return ("register before checkout", "shop/fileitems");
}
}
sub files {
- require ArticleFiles;
- return ArticleFiles->file_storages;
+ require BSE::TB::ArticleFiles;
+ return BSE::TB::ArticleFiles->file_storages;
}
sub metadata {
--- /dev/null
+package BSE::TB::ArticleFile;
+use strict;
+# represents a file associated with an article from the database
+use Squirrel::Row;
+use vars qw/@ISA/;
+@ISA = qw/Squirrel::Row/;
+use Carp 'confess';
+
+sub columns {
+ return qw/id articleId displayName filename sizeInBytes description
+ contentType displayOrder forSale download whenUploaded
+ requireUser notes name hide_from_list storage src category
+ file_handler/;
+}
+
+sub full_filename {
+ my ($self, $cfg) = @_;
+
+ my $downloadPath = BSE::TB::ArticleFiles->download_path($cfg);
+ return $downloadPath . "/" . $self->{filename};
+}
+
+sub remove {
+ my ($self, $cfg) = @_;
+
+ $self->clear_metadata;
+
+ $cfg or confess "No \$cfg supplied to ",ref $self,"->remove()";
+
+ my $filename = $self->full_filename($cfg);
+ my $debug_del = $cfg->entryBool('debug', 'file_unlink', 0);
+ if ($debug_del) {
+ unlink $filename
+ or print STDERR "Error deleting $filename: $!\n";
+ }
+ else {
+ unlink $filename;
+ }
+
+ $self->SUPER::remove();
+}
+
+sub article {
+ my $self = shift;
+ require Articles;
+
+ return Articles->getByPkey($self->{articleId});
+}
+
+sub url {
+ my ($file) = @_;
+
+ return "/cgi-bin/user.pl/download_file/$file->{id}";
+}
+
+sub handler {
+ my ($self, $cfg) = @_;
+
+ return BSE::TB::ArticleFiles->handler($self->file_handler, $cfg);
+}
+
+sub clear_metadata {
+ my ($self) = @_;
+
+ BSE::DB->run(bseClearArticleFileMetadata => $self->{id});
+}
+
+sub set_handler {
+ my ($self, $cfg) = @_;
+
+ my %errors; # save for later setting into the metadata
+
+ for my $handler_entry (BSE::TB::ArticleFiles->file_handlers($cfg)) {
+ my ($key, $handler) = @$handler_entry;
+ my $success = eval {
+ $self->clear_metadata;
+ $handler->process_file($self);
+ 1;
+ };
+ if ($success) {
+ # set errors from handlers that failed
+ for my $key (keys %errors) {
+ $self->add_meta(name => "${key}_error", value => $errors{$key});
+ }
+ $self->set_file_handler($key);
+
+ return;
+ }
+ else {
+ $errors{$key} = $@;
+ chomp $errors{$key};
+ }
+ }
+
+ # we should never get here
+ $self->set_file_handler("");
+ print STDERR "** Ran off the end of ArticleFile->set_handler()\n";
+ return;
+}
+
+sub add_meta {
+ my ($self, %opts) = @_;
+
+ require BSE::TB::ArticleFileMetas;
+ return BSE::TB::ArticleFileMetas->make
+ (
+ file_id => $self->{id},
+ %opts,
+ );
+}
+
+sub metadata {
+ my ($self) = @_;
+
+ require BSE::TB::ArticleFileMetas;
+ return BSE::TB::ArticleFileMetas->getBy
+ (
+ file_id => $self->id
+ );
+}
+
+sub meta_by_name {
+ my ($self, $name) = @_;
+
+ require BSE::TB::ArticleFileMetas;
+ my ($result) = BSE::TB::ArticleFileMetas->getBy
+ (
+ file_id => $self->id,
+ name => $name
+ )
+ or return;
+
+ return $result;
+}
+
+sub inline {
+ my ($file, %opts) = @_;
+
+ my $cfg = delete $opts{cfg}
+ or confess "Missing cfg parameter";
+
+ my $field = delete $opts{field};
+ defined $field or $field = "";
+
+ if ($field && exists $file->{$field}) {
+ return escape_html($file->{$field});
+ }
+ elsif ($field =~ /^meta\.(\w+)$/) {
+ my $name = $1;
+ my $meta = $file->meta_by_name($name)
+ or return "";
+ $meta->content_type eq "text/plain"
+ or return "* metadata $name isn't text *";
+
+ return escape_html($meta->value);
+ }
+ elsif ($field eq "link") {
+ my $url = "/cgi-bin/user.pl?download_file=1&file=$file->{id}";
+ my $eurl = escape_html($url);
+ if ($field eq 'url') {
+ return $eurl;
+ }
+ my $class = $file->{download} ? "file_download" : "file_inline";
+ my $html = qq!<a class="$class" href="$eurl">! . escape_html($file->{displayName}) . '</a>';
+ return $html;
+ }
+ else {
+ my $handler = $file->handler($cfg);
+ return $handler->inline($file, $field);
+ }
+
+}
+
+1;
--- /dev/null
+package BSE::TB::ArticleFileMeta;
+use strict;
+use base 'Squirrel::Row';
+
+sub table {
+ "bse_article_file_meta";
+}
+
+sub columns {
+ qw/id file_id name content_type value/;
+}
+
+sub defaults {
+ content_type => "text/plain",
+}
+
+1;
--- /dev/null
+package BSE::TB::ArticleFileMetas;
+use strict;
+use base 'Squirrel::Table';
+use BSE::TB::ArticleFileMeta;
+
+sub rowClass { "BSE::TB::ArticleFileMeta" }
+
+1;
--- /dev/null
+package BSE::TB::ArticleFiles;
+use strict;
+use Squirrel::Table;
+use vars qw(@ISA $VERSION);
+@ISA = qw(Squirrel::Table);
+use BSE::TB::ArticleFile;
+use Carp qw(confess);
+
+sub rowClass {
+ return 'BSE::TB::ArticleFile';
+}
+
+sub file_storages {
+ my $self = shift;
+ return map [ $_->{filename}, $_->{storage}, $_ ], $self->all;
+}
+
+sub categories {
+ my ($class, $cfg) = @_;
+
+ my @cat_ids = split /,/, $cfg->entry("article file categories", "ids", "");
+ grep $_ eq "", @cat_ids
+ or unshift @cat_ids, "";
+
+ my @cats;
+ for my $id (@cat_ids) {
+ my $section = length $id ? "file category $id" : "file category empty";
+ my $def_name = length $id ? ucfirst $id : "(None)";
+ my $name = $cfg->entry($section, "name", $def_name);
+ push @cats, +{ id => $id, name => $name };
+ }
+
+ return @cats;
+}
+
+sub file_handlers {
+ my ($self, $cfg) = @_;
+
+ $cfg or confess "Missing cfg option";
+
+ my @handlers = split /[;,]/, $cfg->entry('basic', 'file_handlers');
+ push @handlers, "";
+
+ return map [ $_, $self->handler($_, $cfg) ], @handlers;
+}
+
+sub handler {
+ my ($self, $id, $cfg) = @_;
+
+ my $key = $id || "default";
+ my $class = $id ? $cfg->entry("file handlers", $id) : "BSE::FileHandler::Default";
+
+ (my $file = $class . ".pm") =~ s(::)(/)g;
+ require $file;
+ return $class->new($cfg);
+}
+
+sub download_path {
+ my ($class, $cfg) = @_;
+
+ return $cfg->entryVar('paths', 'downloads');
+}
+
+1;
defined $field or $field = '';
- if ($field && exists $file->{$field}) {
- return escape_html($file->{$field});
- }
- else {
- my $url = "/cgi-bin/user.pl?download_file=1&file=$file->{id}";
- my $eurl = escape_html($url);
- if ($field eq 'url') {
- return $eurl;
- }
- my $class = $file->{download} ? "file_download" : "file_inline";
- my $html = qq!<a class="$class" href="$eurl">! . escape_html($file->{displayName}) . '</a>';
- return $html;
- }
+ return $file->inline
+ (
+ cfg => $self->cfg,
+ field => $field
+ );
}
1;
}
sub thumb_data {
- my ($self, $filename, $geometry, $error) = @_;
+ my ($self, %opts) = @_;
+
+ #$filename, $geometry, $error) = @_;
+
+ my $filename = delete $opts{filename};
+ my $geometry = delete $opts{geometry};
+ my $data = delete $opts{data};
+ my $error = delete $opts{error};
my $geolist = $self->_parse_geometry($geometry, $error)
or return;
}
require Imager;
my $src = Imager->new;
- unless ($src->read(file => $filename)) {
- $$error = "Cannot read image $filename: ".$src->errstr;
+ if ($filename) {
+ unless ($src->read(file => $filename)) {
+ $$error = "Cannot read image $filename: ".$src->errstr;
+ return;
+ }
+ }
+ elsif ($data) {
+ unless ($src->read(data => $data)) {
+ $$error = "Cannot read image (by data): ".$src->errstr;
+ return;
+ }
+ }
+ else {
+ $$error = "No image filename or data supplied";
return;
}
translate => 'errdiff',
gifquant => 'gen',
);
+ $write_opts{type} = $src->tags(name => 'i_format');
+ my @allowed_types = split /,/, $self->{cfg}->entry(CFG_SECTION, 'types', "jpeg,png,gif");
+ unless (grep $_ eq $write_opts{type}, @allowed_types) {
+ $write_opts{type} = $allowed_types[0];
+ }
my $work = $src;
for my $geo (@$geolist) {
if ($work->getchannels == 4 || $work->getchannels == 2) {
$write_opts{type} ||= 'png';
}
- $write_opts{type} ||= $src->tags(name => 'i_format');
my $type = $write_opts{type};
$work = $tmp;
}
- my $data;
+ my $outdata;
$work = $work->to_rgb8;
- unless ($work->write(data => \$data, %write_opts)) {
+ unless ($work->write(data => \$outdata, %write_opts)) {
$$error = "cannot write image ".$work->errstr;
return;
}
- return ( $data, "image/$type" );
+ return ( $outdata, "image/$type" );
}
sub _incs {
include=path1:path2:path3
blib=/path/to/imager/src
jpegquality=90
+ allowed_types=jpeg,png,gif
[thumb geometries]
geometryname1=operator1(arguments),operator2(arguments)
}
my @files;
if ($product->{id}) {
- require 'ArticleFiles.pm';
- @files = ArticleFiles->getBy(articleId=>$product->{id});
+ require BSE::TB::ArticleFiles;
+ @files = BSE::TB::ArticleFiles->getBy(articleId=>$product->{id});
}
my $file_index;
unless ($action) {
($action, @extras) = $self->other_action($cgi);
}
+ if (!$action && $ENV{PATH_INFO}) {
+ my @components = split '/', $ENV{PATH_INFO};
+ @components && !$components[0] and shift @components;
+ if (@components && $actions->{$components[0]}) {
+ ($action, @extras) = @components;
+ }
+ }
$action ||= $self->default_action;
$self->check_action($req, $action, \$result)
-e $filename
or return $class->error($req, "image file missing");
- (my $data, $type) = $thumbs->thumb_data($filename, $geometry, \$error)
+ (my $data, $type) = $thumbs->thumb_data
+ (
+ filename => $filename,
+ geometry => $geometry,
+ error => \$error
+ )
or return $class->error($req, $error);
return
sub {
require 'ArticleFiles.pm';
@files = sort { $b->{displayOrder} <=> $a->{displayOrder} }
- ArticleFiles->getBy(articleId=>$items[$item_index]{productId});
+ BSE::TB::ArticleFiles->getBy(articleId=>$items[$item_index]{productId});
},
'prodfile', 'prodfiles', \$file_index),
ifFileAvail =>
orderdetail => 'req_orderdetail',
wishlist => 'req_wishlist',
downufile => 'req_downufile',
+ file_metadata => "req_file_metadata",
);
sub actions { \%actions }
make_multidependent_iterator
([ \$item_index, \$order_index],
sub {
- require 'ArticleFiles.pm';
+ require BSE::TB::ArticleFiles;
@files = sort { $b->{displayOrder} <=> $a->{displayOrder} }
- ArticleFiles->getBy(articleId=>$items[$item_index]{productId});
+ BSE::TB::ArticleFiles->getBy(articleId=>$items[$item_index]{productId});
},
'prodfile', 'prodfiles', \$file_index),
ifFileAvail =>
my ($item) = grep $_->{id} == $itemid,
BSE::TB::OrderItems->getBy(orderId=>$order->{id})
or return _refresh_userpage($cfg, $msgs->(notinorder=>"Not part of that order"));
- require 'ArticleFiles.pm';
- my @files = ArticleFiles->getBy(articleId=>$item->{productId})
+ require BSE::TB::ArticleFiles;
+ my @files = BSE::TB::ArticleFiles->getBy(articleId=>$item->{productId})
or return _refresh_userpage($cfg, $msgs->(nofilesonline=>"No files in this line"));
my $fileid = $cgi->param('file')
or return _refresh_userpage($cfg, $msgs->(nofileid=>"No file id supplied"));
}
sub req_download_file {
- my ($self, $req) = @_;
+ my ($self, $req, $fileid) = @_;
my $cfg = $req->cfg;
my $cgi = $req->cgi;
if ($userid) {
$user = SiteUsers->getBy(userId=>$userid);
}
- my $fileid = $cgi->param('file')
+ $fileid ||= $cgi->param('file')
or return $self->req_show_logon($req,
$msgs->('nofileid', "No file id supplied"));
- require ArticleFiles;
+ require BSE::TB::ArticleFiles;
my $file;
my $article;
my $article_id = $cgi->param('page');
($file) = grep $_->{name} eq $fileid, $article->files;
}
else {
- $file = ArticleFiles->getByPkey($fileid);
+ $file = BSE::TB::ArticleFiles->getByPkey($fileid);
}
$file
or return $self->req_show_logon($req,
close FILE;
}
+sub req_file_metadata {
+ my ($self, $req, $fileid, $metaname) = @_;
+
+ my $user = $req->siteuser;
+ my $cgi = $req->cgi;
+ $fileid ||= $cgi->param('file')
+ or return $self->req_show_logon($req, $req->text(nofileid => "No file id supplied"));
+ $metaname ||= $cgi->param('name')
+ or return $self->req_show_logon($req, $req->text(nometaname => "No metaname supplied"));
+ require BSE::TB::ArticleFiles;
+ my $file = BSE::TB::ArticleFiles->getByPkey($fileid)
+ or return $self->req_show_logon($req, $req->text(nosuchfile => "No such file"));
+
+ if ($file->articleId != -1) {
+ # check the user has access
+ my $article = $file->article
+ or return $self->req_show_logon($req, $req->text(nofilearticle => "No article found for this file"));
+ if ($article->is_dynamic && !$req->siteuser_has_access($article)) {
+ if ($req->siteuser) {
+ return $self->req_userpage($req, $req->text(downloadnoacces => "You do not have access to this article"));
+ }
+ else {
+ return $self->req_show_logon($req, $req->text(needlogon => "You need to logon to download this file"));
+ }
+ }
+ }
+ my $meta = $file->meta_by_name($metaname)
+ or return $self->req_show_logon($req, $req->text(nosuchmeta => "There is no metadata by that name for this file"));
+
+ my %result =
+ (
+ type => $meta->content_type,
+ content => $meta->value,
+ );
+
+ require BSE::Template;
+ BSE::Template->output_result($req, \%result);
+}
+
sub req_show_lost_password {
my ($self, $req, $message) = @_;
my $error;
(my $data, $type) =
- $thumbs->thumb_data($image_filename, $geometry, \$error)
+ $thumbs->thumb_data
+ (
+ filename => $image_filename,
+ geometry => $geometry,
+ error => \$error
+ )
or return;
if (open IMAGE, ">$cache_name") {
use Generate;
use Util qw(generate_button);
use BSE::Util::Tags qw(tag_article);
-use ArticleFiles;
+use BSE::TB::ArticleFiles;
@ISA = qw/Generate/;
use DevHelp::HTML;
use BSE::Arrows;
my $image_index = -1;
my $had_image_tags = 0;
my @all_files = sort { $b->{displayOrder} <=> $a->{displayOrder} }
- ArticleFiles->getBy(articleId=>$article->{id});
+ BSE::TB::ArticleFiles->getBy(articleId=>$article->{id});
my @files = grep !$_->{hide_from_list}, @all_files;
my $blank = qq!<img src="$IMAGES_URI/trans_pixel.gif" width="17" height="13" border="0" align="absbottom" alt="" />!;
#!/usr/bin/perl -w
# -d:ptkdb
-BEGIN { $ENV{DISPLAY} = '192.168.32.51:0.0'; }
+BEGIN { $ENV{DISPLAY} = '192.168.32.54:0.0'; }
use strict;
use FindBin;
use lib "$FindBin::Bin/modules";
name: BackgroundTasks
sql_statement: select * from bse_background_tasks
+
+name: bseClearArticleFileMetadata
+sql_statement: <<SQL
+delete from bse_article_file_meta
+where file_id = ?
+SQL
float: left;
}
+#bse_video_stage {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ background-image: url(/images/50.png);
+ display: none;
+}
+
+#bse_video_frame {
+ position: absolute;
+ border: 1px solid #000;
+ left: 50%;
+ top: 20%;
+}
+
+#bse_video_close {
+ display: block;
+ position: absolute;
+ right: 50%;
+ top: 20%;
+ margin-top: -20px;
+}
+
+#bse_video_close img {
+ border: 0px;
+}
+
+.bse_video_popup img {
+ border: 1px solid #CCC;
+}
\ No newline at end of file
--- /dev/null
+var bse_image_popup;
+function bse_popup_image (article_id, image_id, width, height, tag_id, image_url) {
+ var url = "/cgi-bin/image.pl?id=" + article_id + "&imid=" + image_id
+ + '&comment=jspopup';
+ var work_width = width;
+ var work_height = height;
+ var features = 'width=' + work_width + ',height=' + work_height
+ + ',resizable=yes';
+
+ // lose the old one if it exists
+ if (bse_image_popup != null && !bse_image_popup.closed) {
+ bse_image_popup.close();
+ }
+ var left = window.screenX + (window.outerWidth - work_width) / 2;
+ var top = window.screenY + (window.outerHeight - work_height) / 2;
+ features = features + ",top=" + top + ",left=" + left;
+
+ bse_image_popup = window.open(url, 'bse_image', features, 0);
+
+ return 0;
+}
+
+var bse_video_stage;
+var bse_video_frame;
+var bse_video_running = 0;
+
+function bse_show_video (fileid, width, height, src) {
+ if (bse_video_running) {
+ bse_close_video();
+ return false;
+ }
+ // check for our staging area
+ if (!bse_video_stage) {
+ bse_video_stage = document.getElementById("bse_video_stage");
+ bse_video_frame = document.getElementById("bse_video_frame");
+ bse_video_close = document.getElementById("bse_video_close");
+ }
+ if (!bse_video_stage) {
+ bse_video_stage = document.createElement("div");
+ bse_video_stage.id = "bse_video_stage";
+ bse_video_frame = document.createElement("div");
+ bse_video_frame.id = "bse_video_frame";
+ bse_video_close = document.createElement("a");
+ bse_video_close.href="#";
+ bse_video_close.onclick = bse_close_video;
+ bse_video_close.id = "bse_video_close";
+ bse_video_stage.appendChild(bse_video_frame);
+ bse_video_stage.appendChild(bse_video_close);
+ var img = document.createElement("img");
+ img.src = "/images/videoclose.png";
+ bse_video_close.appendChild(img);
+ document.body.appendChild(bse_video_stage);
+ }
+ bse_video_frame.style.width = width + "px";
+ bse_video_frame.style.height = height + "px";
+ var margin = (-width / 2);
+ bse_video_frame.style.marginLeft = margin + "px";
+ bse_video_close.style.marginRight = (margin - 20) + "px";
+
+
+ var so = new SWFObject("/swf/flvplayer.swf", "flvplayer", width, height, "8", "#000000");
+ so.addParam('allowFullScreen',true);
+ so.addVariable('aspect_ratio', width/height);
+ //so.addVariable('placeholder','/cgi-bin/user.pl/file_metadata/'+fileid+'/ph_data');
+ so.addVariable('video_path',src);
+ so.addVariable('autoplay');
+ so.write("bse_video_frame");
+
+ bse_video_stage.style.display="block";
+
+ bse_video_stage.onmousedown = "bse_close_video(); return false;";
+ bse_video_running = 1;
+
+ return false;
+}
+
+function bse_close_video() {
+ bse_video_frame.innerHTML = '';
+ bse_video_stage.style.display = "none";
+ bse_video_running = 0;
+ return false;
+}
\ No newline at end of file
--- /dev/null
+/**
+ * SWFObject v1.5.1: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+if(typeof deconcept=="undefined"){var deconcept={};}if(typeof deconcept.util=="undefined"){deconcept.util={};}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil={};}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params={};this.variables={};this.attributes=[];if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10]||"";},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15]||"";},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=[];var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+(this.getAttribute("style")||"")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+(this.getAttribute("style")||"")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
\ No newline at end of file
<input type="hidden" name="file_id" value="<:efile id:>" />
<input type="hidden" name="_t" value="file" />
<input type="hidden" name="save_file_flags" value="1" />
- <table cellpadding="6" border="0" cellspacing="1">
+ <table class="editform editformsmall">
<tr>
<th align="left">Replacement file:</th>
<td>
<meta http-equiv="Expires" content="Thu, 01 Jan 1970 00:00:00 GMT">
<link rel="stylesheet" href="/css/style-main.css">
<:ajax includes:>
+<script src="/js/bse.js"></script>
+<script src="/js/swfobject.js"></script>
</head>
-<script>
-var bse_image_popup;
-function bse_popup_image (article_id, image_id, width, height, tag_id, image_url) {
- var url = "/cgi-bin/image.pl?id=" + article_id + "&imid=" + image_id
- + '&comment=jspopup';
- var work_width = width + <:cfg popimage extrawidth 0:>;
- var work_height = height + <:cfg popimage extraheight 0:>;
- var features = 'width=' + work_width + ',height=' + work_height
- + ',resizable=yes';
-
- // lose the old one if it exists
- if (<:cfg popimage popmiddle 0:>) {
- if (bse_image_popup != null && !bse_image_popup.closed) {
- bse_image_popup.close();
- }
- var left = window.screenX + (window.outerWidth - work_width) / 2;
- var top = window.screenY + (window.outerHeight - work_height) / 2;
- features = features + ",top=" + top + ",left=" + left;
- }
- else if (bse_image_popup != null && !bse_image_popup.closed) {
- var left = bse_image_popup.screenX;
- var top = bse_image_popup.screenY;
- features = features + ",top=" + top + ",left=" + left;
- bse_image_popup.close();
- }
-
- bse_image_popup = window.open(url, 'bse_image', features, 0);
-
- return 0;
-}
-</script>
<body bgcolor="#FFFFFF" text="#000000" link="#666666" vlink="#666666" alink="#FF7F00" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FF7F00">
<tr>
--- /dev/null
+<script type="text/javascript" src="/js/swfobject.js"></script><div id="flashcontent"> This text is replaced by the Flash movie.</div><script type="text/javascript"> var so = new SWFObject("/swf/flvplayer.swf", "flvplayer", "<:meta width:>", "<:meta height:>", "8", "#000000"); so.addParam('allowFullScreen',true); so.addVariable('aspect_ratio', <:meta width:>/<:meta height:>); so.addVariable('placeholder','/cgi-bin/user.pl/file_metadata/<:file id:>/ph_data'); so.addVariable('video_path','<:src:>'); so.addVariable("wmode", "opaque"); so.write("flashcontent");</script>
+<!--
+so.addVariable('placeholder','placeholder.jpg');
+-->
+
+<!-- object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" type="application/x-shockwave-flash" height="<:meta height:>" width="<:meta width:>"><param name="movie" value="/swf/flvplayer.swf"><param name="video_path" value="/notarealvideo"><param name="quality" value="high"><param name="wmode" value="opaque"><embed src="/swf/flvplayer.swf" video_path="/notarealvideo" quality="high" wmode="opaque" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="<:meta height:>" width="<:meta width:>"></object -->
+
+<!-- div id="flv<:file id:>"><a href="#" onclick="return false;"><img src="/cgi-bin/user.pl?file_metadata=1&file=<:file id:>&name=ph_data" width="<:meta width:>" height="<:meta height:>" /></a></div -->
\ No newline at end of file
--- /dev/null
+<div><a class="bse_video_popup" href="#" onclick="return bse_show_video(<:file id:>, <:meta width:>, <:meta height:>, '<:src:>');"><img src="/cgi-bin/user.pl/file_metadata/<:file id:>/ph_editor_data" width="<:meta ph_editor_width:>" height="<:meta ph_editor_height:>" /></a></div>
\ No newline at end of file
Column hide_from_list;int(11);NO;0;
Column storage;varchar(20);NO;local;
Column src;varchar(255);NO;;
+Column category;varchar(20);NO;;
+Column file_handler;varchar(20);NO;;
Index PRIMARY;1;[id]
+Table bse_article_file_meta
+Column id;int(11);NO;NULL;auto_increment
+Column file_id;int(11);NO;NULL;
+Column name;varchar(20);NO;NULL;
+Column content_type;varchar(80);NO;text/plain;
+Column value;longblob;NO;NULL;
+Index PRIMARY;1;[id]
+Index file_name;1;[file_id;name]
Table bse_article_groups
Column article_id;int(11);NO;NULL;
Column group_id;int(11);NO;NULL;