680 lines
24 KiB
Plaintext
680 lines
24 KiB
Plaintext
|
<?page
|
||
|
title=>File Manager
|
||
|
body<=
|
||
|
<?_code
|
||
|
{
|
||
|
use strict;
|
||
|
use vars qw(%GET %POST);
|
||
|
|
||
|
LJ::set_active_crumb('filemanager');
|
||
|
|
||
|
my $remote = LJ::get_remote();
|
||
|
return LJ::bad_input($ML{'error.noremote'})
|
||
|
unless $remote;
|
||
|
|
||
|
my $authas = $GET{'authas'} || $remote->{'user'};
|
||
|
my $u = LJ::get_authas_user($authas);
|
||
|
return LJ::bad_input($ML{'error.invalidauth'})
|
||
|
unless $u;
|
||
|
|
||
|
# KiB vs MiB byte conversions / printing
|
||
|
my %shift = ( MiB => 1 << 20, KiB => 1 << 10 );
|
||
|
my $size = sub {
|
||
|
my $bytes = shift;
|
||
|
# Display in Mb or Kb?
|
||
|
return sprintf("%.2f MiB", $bytes / $shift{MiB}) if $bytes >= $shift{MiB};
|
||
|
return sprintf("%.2f KiB", $bytes / $shift{KiB});
|
||
|
};
|
||
|
|
||
|
# for reporting error
|
||
|
my $err = sub { return "<?h1 $ML{'Error'} h1?><?p $_[0] p?>" };
|
||
|
|
||
|
# what type of blob to show
|
||
|
my $showtype = $GET{'showtype'};
|
||
|
|
||
|
# extra arguments for get requests
|
||
|
# how to make links back to this page
|
||
|
my $self_link = sub {
|
||
|
my $page = shift || $GET{'page'};
|
||
|
my $sort = shift || $GET{'sort'};
|
||
|
|
||
|
my $uri = "files.bml?";
|
||
|
$uri .= "authas=$authas&" if $authas ne $remote->{'user'};
|
||
|
$uri .= "showtype=$showtype&" if $showtype;
|
||
|
$uri .= "page=$page&" if $page > 1;
|
||
|
$uri .= "sort=$sort&" if $sort;
|
||
|
chop $uri;
|
||
|
|
||
|
return $uri;
|
||
|
};
|
||
|
|
||
|
# how to make a sort link back to this page,
|
||
|
# given a sort type and name
|
||
|
my $sort_link = sub {
|
||
|
my ($sort, $name) = @_;
|
||
|
return $name unless $sort;
|
||
|
|
||
|
my $type = $GET{'sort'} eq "${sort}_asc"
|
||
|
? "${sort}_desc" : "${sort}_asc";
|
||
|
return "<a href='" . $self_link->(undef, $type) . "'>$name</a>";
|
||
|
};
|
||
|
|
||
|
# declare these up here so closures below can use them
|
||
|
my %blobs = (); # { 'blobid' => blob object }, references into @blobs
|
||
|
my @blobs = (); # [ { blob object }, { ... }, ... ]
|
||
|
my ($domain, $domainid); # blob domain/id
|
||
|
my ($dbh, $dbcm);
|
||
|
|
||
|
my %btype = ();
|
||
|
|
||
|
###
|
||
|
### Userpic handler functions
|
||
|
###
|
||
|
$btype{'userpic'} = {
|
||
|
'name' => "Userpics",
|
||
|
|
||
|
# how to sort various columns
|
||
|
'sort' => sub {
|
||
|
my $sort = $GET{'sort'};
|
||
|
my $cmp = sub { $b->{'length'} <=> $a->{'length'} };
|
||
|
|
||
|
# numeric <=> comparison
|
||
|
if ($sort =~ /^(kw_ct|width|height|length)_(asc|desc)$/) {
|
||
|
my ($meth, $dir) = ($1, $2);
|
||
|
|
||
|
if ($dir eq 'desc') {
|
||
|
$cmp = sub { $b->{$meth} <=> $a->{$meth} };
|
||
|
} elsif ($dir eq 'asc') {
|
||
|
$cmp = sub { $a->{$meth} <=> $b->{$meth} };
|
||
|
}
|
||
|
|
||
|
# string 'cmp' comparison
|
||
|
} elsif ($sort =~ /^(picdate|ext)_(asc|desc)$/) {
|
||
|
my ($meth, $dir) = ($1, $2);
|
||
|
|
||
|
if ($dir eq 'desc') {
|
||
|
$cmp = sub { $b->{$meth} cmp $a->{$meth} };
|
||
|
} elsif ($dir eq 'asc') {
|
||
|
$cmp = sub { $a->{$meth} cmp $b->{$meth} };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sort $cmp @blobs;
|
||
|
},
|
||
|
|
||
|
# how to fetch userpic objects from the database
|
||
|
'fetch' => sub {
|
||
|
my @ids = map { $_->{'blobid'} } @blobs;
|
||
|
my $bind = join(",", map { "?" } @ids);
|
||
|
my $sth;
|
||
|
if ($u->{'dversion'} > 6) {
|
||
|
my $dbcr = LJ::get_cluster_def_reader($u);
|
||
|
$sth = $dbcr->prepare("SELECT picid, fmt, width, height, " .
|
||
|
"state, picdate FROM userpic2 " .
|
||
|
"WHERE userid=$u->{'userid'} AND picid IN ($bind)");
|
||
|
} else {
|
||
|
$sth = $dbh->prepare("SELECT picid, contenttype, width, height, " .
|
||
|
"state, picdate FROM userpic " .
|
||
|
"WHERE picid IN ($bind)");
|
||
|
}
|
||
|
$sth->execute(@ids);
|
||
|
while (my $row = $sth->fetchrow_hashref) {
|
||
|
my $picid = $row->{'picid'};
|
||
|
$row->{'length'} = $blobs{$picid}->{'length'};
|
||
|
$blobs{$picid} = $row;
|
||
|
}
|
||
|
@blobs = values %blobs;
|
||
|
|
||
|
# add in keywords
|
||
|
my $upicinf = LJ::get_userpic_info($u);
|
||
|
while (my ($k, $v) = each %{$upicinf->{'kw'}}) {
|
||
|
push @{$blobs{$v->{'picid'}}->{'kw'}}, $k;
|
||
|
}
|
||
|
|
||
|
# don't need keyword array though,
|
||
|
# 'kw_str' => comma separated keywords
|
||
|
# 'kw_ct' => count of keywords, for sorting
|
||
|
foreach my $bl (@blobs) {
|
||
|
$bl->{'kw_str'} = join(", ", @{$bl->{'kw'}||[]});
|
||
|
$bl->{'kw_ct'} = scalar(@{$bl->{'kw'}||[]});
|
||
|
delete $bl->{'kw'};
|
||
|
|
||
|
# convert mime type to filetype (ext)
|
||
|
if ($u->{'dversion'} > 6) {
|
||
|
$bl->{'ext'} = {
|
||
|
'G' => 'gif',
|
||
|
'J' => 'jpg',
|
||
|
'P' => 'png',
|
||
|
}->{$bl->{'contenttype'}};
|
||
|
} else {
|
||
|
$bl->{'ext'} = {
|
||
|
'image/gif' => 'gif',
|
||
|
'image/jpeg' => 'jpg',
|
||
|
'image/png' => 'png',
|
||
|
}->{$bl->{'contenttype'}};
|
||
|
}
|
||
|
delete $bl->{'contenttype'};
|
||
|
}
|
||
|
},
|
||
|
|
||
|
# deletes blobs which need to be deleted based on %POST
|
||
|
'delete' => sub {
|
||
|
|
||
|
# find picids to delete
|
||
|
my @del = ();
|
||
|
foreach my $id (map { $_->{'picid'} } @blobs) {
|
||
|
push @del, $id if $POST{"del_${id}"};
|
||
|
}
|
||
|
return 0 unless @del;
|
||
|
|
||
|
# try and delete from either the blob server or database,
|
||
|
my $deleted = 0;
|
||
|
my $bind = join(",", map { "?" } @del);
|
||
|
if ($LJ::USERPIC_BLOBSERVER) {
|
||
|
|
||
|
# delete blobs from blobserver
|
||
|
foreach my $picid (@del) {
|
||
|
LJ::Blob::delete($u, $domain, $blobs{$picid}->{'ext'}, $picid);
|
||
|
}
|
||
|
$deleted = 1;
|
||
|
|
||
|
} elsif ($u->do("DELETE FROM userpicblob2 WHERE ".
|
||
|
"userid=? AND picid IN ($bind)", undef,
|
||
|
$u->{userid}, @del) > 0) {
|
||
|
$deleted = 1;
|
||
|
}
|
||
|
if ($deleted) {
|
||
|
if ($u->{'dversion'} > 6) {
|
||
|
$u->do("DELETE FROM userpic2 WHERE userid=? IN ($bind)",
|
||
|
undef, $u->{'userid'}, @del);
|
||
|
} else {
|
||
|
$dbh->do("DELETE FROM userpic WHERE picid IN ($bind)",
|
||
|
undef, @del);
|
||
|
}
|
||
|
$u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " .
|
||
|
"AND blobid IN ($bind)", undef, $u->{'userid'},
|
||
|
$domain, @del);
|
||
|
|
||
|
# userpics changed, need to reactivate
|
||
|
LJ::activate_userpics($u);
|
||
|
}
|
||
|
|
||
|
return scalar(@del);
|
||
|
},
|
||
|
|
||
|
# renders userpic rows in the table (including column headings)
|
||
|
'render' => sub {
|
||
|
my $ret;
|
||
|
|
||
|
$ret .= "<tr><td class='tablehead'> </td>";
|
||
|
|
||
|
my $eff_sort =
|
||
|
$GET{'sort'} =~ /^(kw_ct|picdate|width|height|length|ext)_(asc|desc)$/
|
||
|
? $GET{'sort'} : "length_desc";
|
||
|
|
||
|
# display column headings
|
||
|
foreach ([undef, "Image"], ['kw_ct', "Keywords"], ['picdate', "Date Uploaded"],
|
||
|
['width', "Width"], ['height', "Height"], ['length', "Filesize"],
|
||
|
['ext', "Type"]) {
|
||
|
|
||
|
$ret .= "<td class='tablehead'";
|
||
|
$ret .= " width='40%'" if $_->[0] eq 'subject';
|
||
|
$ret .= ">" . $sort_link->(@$_);
|
||
|
|
||
|
if ($eff_sort =~ /^$_->[0]_(asc|desc)$/) {
|
||
|
my $pref = $1 eq 'asc' ? "down" : "up";
|
||
|
$ret .= "<img src='$LJ::IMGPREFIX/${pref}arrow.gif' width='16' ";
|
||
|
$ret .= "height='15' alt='' border='0' />";
|
||
|
}
|
||
|
|
||
|
$ret .= "</td>";
|
||
|
}
|
||
|
|
||
|
$ret .= "<td class='tablehead'> </td></tr>";
|
||
|
|
||
|
# fill in rows
|
||
|
foreach my $bl (@blobs) {
|
||
|
my $picid = $bl->{'picid'};
|
||
|
|
||
|
# delete checkbox
|
||
|
$ret .= "<tr><td class='tablecontent'>";
|
||
|
$ret .= LJ::html_check({ 'type' => 'check', 'name' => "del_${picid}",
|
||
|
'id' => "del_${picid}", 'value' => 1 }) . "</td>";
|
||
|
|
||
|
# display userpic
|
||
|
$ret .= "<td class='tablecontent'><label for='del_${picid}'>";
|
||
|
$ret .= "<img src='$LJ::USERPIC_ROOT/$bl->{'picid'}/$u->{'userid'}'";
|
||
|
$ret .= " width='$bl->{'width'}' height='$bl->{'height'}' alt='$bl->{'kw_str'}'";
|
||
|
$ret .= " title='$bl->{'kw_str'}'></label></td>";
|
||
|
|
||
|
# keywords, date/time
|
||
|
$bl->{'kw_str'} ||= "<i>none</i>";
|
||
|
foreach (qw(kw_str picdate)) {
|
||
|
$ret .= "<td class='tablecontent'>$bl->{$_}</td>";
|
||
|
}
|
||
|
|
||
|
# width/height
|
||
|
foreach (qw(width height)) {
|
||
|
$ret .= "<td class='tablecontent'>$bl->{$_}px</td>";
|
||
|
}
|
||
|
|
||
|
# file size
|
||
|
my $len = sprintf("%.1fk", $bl->{'length'} / 1000);
|
||
|
$ret .= "<td class='tablecontent' align='center'>$len</td>";
|
||
|
|
||
|
# typs
|
||
|
$ret .= "<td class='tablecontent' align='center'>";
|
||
|
$ret .= uc($bl->{'ext'}) . "</td></tr>";
|
||
|
}
|
||
|
|
||
|
# delete button
|
||
|
$ret .= "<tr><td colspan='4' align='left'>";
|
||
|
$ret .= LJ::html_submit('action:delete', "Delete Selected") . "</td>";
|
||
|
$ret .= "<td colspan='4' align='right'>[<a href='$LJ::SITEROOT/editpics.bml#upload'>";
|
||
|
$ret .= "Upload new userpics</a>]";
|
||
|
|
||
|
return $ret;
|
||
|
},
|
||
|
};
|
||
|
|
||
|
###
|
||
|
### PhonePost handler functions
|
||
|
###
|
||
|
$btype{'phonepost'} = {
|
||
|
'name' => "Phone Posts",
|
||
|
|
||
|
# how to sort phonepost rows, for each column type
|
||
|
'sort' => sub {
|
||
|
my $sort = $GET{'sort'};
|
||
|
my $cmp = sub { $b->{'length'} <=> $a->{'length'} };
|
||
|
|
||
|
# numeric <=> comparison
|
||
|
if ($sort =~ /^(length|lengthsecs|posttime)_(asc|desc)$/) {
|
||
|
my ($meth, $dir) = ($1, $2);
|
||
|
|
||
|
if ($dir eq 'desc') {
|
||
|
$cmp = sub { $b->{$meth} <=> $a->{$meth} };
|
||
|
} elsif ($dir eq 'asc') {
|
||
|
$cmp = sub { $a->{$meth} <=> $b->{$meth} };
|
||
|
}
|
||
|
|
||
|
# string 'cmp' comparison
|
||
|
} elsif ($sort =~ /^subject_(asc|desc)$/) {
|
||
|
if ($1 eq 'desc') {
|
||
|
$cmp = sub { $b->{'subject'} cmp $a->{'subject'} };
|
||
|
} else {
|
||
|
$cmp = sub { $a->{'subject'} cmp $b->{'subject'} };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sort $cmp @blobs;
|
||
|
},
|
||
|
|
||
|
# populates @/%blobs from database
|
||
|
'fetch' => sub {
|
||
|
|
||
|
# get data from phonepostentry
|
||
|
my $bind = join(",", map { "?" } @blobs);
|
||
|
my $sth = $dbcm->prepare("SELECT blobid, jitemid, anum AS pp_anum, " .
|
||
|
"lengthsecs, posttime, filetype FROM phonepostentry " .
|
||
|
"WHERE userid=? AND blobid IN ($bind)");
|
||
|
$sth->execute($u->{'userid'}, map { $_->{'blobid'} } @blobs);
|
||
|
while (my $row = $sth->fetchrow_hashref) {
|
||
|
my $bid = $row->{'blobid'};
|
||
|
$row->{'length'} = $blobs{$bid}->{'length'};
|
||
|
|
||
|
# convert filetype to extension
|
||
|
$row->{'ext'} = $row->{'filetype'} == 1 ? "ogg" : "mp3";
|
||
|
delete $row->{'filetype'};
|
||
|
|
||
|
$blobs{$bid} = $row;
|
||
|
}
|
||
|
@blobs = values %blobs;
|
||
|
|
||
|
# now get subject from logtext2
|
||
|
my $logtext = LJ::get_logtext2($u, map { $_->{'jitemid'} } @blobs);
|
||
|
foreach my $bl (@blobs) {
|
||
|
my $jitemid = $bl->{'jitemid'};
|
||
|
next unless ref $logtext->{$jitemid} eq 'ARRAY';
|
||
|
|
||
|
# subject and has_entry keys
|
||
|
$bl->{'subject'} = $logtext->{$jitemid}->[0];
|
||
|
$bl->{'has_entry'} = 1;
|
||
|
|
||
|
# also get log2 row so we can see security
|
||
|
my $log = LJ::get_log2_row($u, $jitemid);
|
||
|
if (ref $log eq 'HASH') {
|
||
|
$bl->{'security'} = $log->{'security'};
|
||
|
$bl->{'l_anum'} = $log->{'anum'};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
},
|
||
|
|
||
|
# deletes blobs which need to be deleted based on %POST
|
||
|
'delete' => sub {
|
||
|
|
||
|
# find picids to delete
|
||
|
my @del = ();
|
||
|
foreach my $id (map { $_->{'blobid'} } @blobs) {
|
||
|
push @del, $id if $POST{"del_${id}"};
|
||
|
}
|
||
|
return 0 unless @del;
|
||
|
|
||
|
return 0 unless $u->writer;
|
||
|
|
||
|
# delete from userblob (journalid, domain, blobid)
|
||
|
my $bind = join(",", map { "?" } @del);
|
||
|
$u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " .
|
||
|
"AND blobid IN ($bind)", undef, $u->{'userid'},
|
||
|
$domainid, @del);
|
||
|
|
||
|
# delete blobs from blobserver
|
||
|
foreach my $bid (@del) {
|
||
|
my $ppe = LJ::PhonePost::get_phonepost_entry($u, $bid);
|
||
|
if ($ppe->{location} eq 'mogile') {
|
||
|
LJ::mogclient()->delete("pp:$u->{userid}:$bid");
|
||
|
} else {
|
||
|
LJ::Blob::delete($u, $domain, $blobs{$bid}->{'ext'}, $bid);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# update phonepost entry locations to be 'none'
|
||
|
$u->do("UPDATE phonepostentry SET location='none' WHERE userid=? AND blobid IN ($bind)",
|
||
|
undef, $u->{userid}, @del);
|
||
|
|
||
|
return scalar(@del);
|
||
|
},
|
||
|
|
||
|
# generate phonepost table rows
|
||
|
'render' => sub {
|
||
|
my $ret;
|
||
|
|
||
|
$ret .= "<tr><td class='tablehead'> </td>";
|
||
|
|
||
|
my $eff_sort =
|
||
|
$GET{'sort'} =~ /^(subject|length|lengthsecs|posttime)_(asc|desc)$/
|
||
|
? $GET{'sort'} : "length_desc";
|
||
|
|
||
|
# table heading
|
||
|
foreach ([undef, "Audio"], ['subject', "Subject"], ['posttime', "Date/Time"],
|
||
|
['lengthsecs', "Duration"], ['length', "Filesize"]) {
|
||
|
|
||
|
$ret .= "<td class='tablehead'";
|
||
|
$ret .= " width='40%'" if $_->[0] eq 'subject';
|
||
|
$ret .= ">" . $sort_link->(@$_);
|
||
|
|
||
|
if ($eff_sort =~ /^$_->[0]_(asc|desc)$/) {
|
||
|
my $pref = $1 eq 'asc' ? "down" : "up";
|
||
|
$ret .= "<img src='$LJ::IMGPREFIX/${pref}arrow.gif' width='16' ";
|
||
|
$ret .= "height='15' alt='' border='0' />";
|
||
|
}
|
||
|
|
||
|
$ret .= "</td>";
|
||
|
}
|
||
|
|
||
|
$ret .= "<td class='tablehead'> </td></tr>";
|
||
|
|
||
|
# table rows
|
||
|
foreach my $bl (@blobs) {
|
||
|
my $blobid = $bl->{'blobid'};
|
||
|
|
||
|
# delete checkbox
|
||
|
$ret .= "<tr><td class='tablecontent'>";
|
||
|
$ret .= LJ::html_check({ 'type' => 'check', 'name' => "del_${blobid}",
|
||
|
'value' => 1, 'selected' => 0 }) . "</td>";
|
||
|
|
||
|
# link to phonepost
|
||
|
{
|
||
|
$ret .= "<td class='tablecontent'>";
|
||
|
$ret .= LJ::PhonePost::make_link($remote, $u, $bl->{'blobid'}, 'bare');
|
||
|
}
|
||
|
|
||
|
# link to original entry
|
||
|
my $subject = "<i>No associated journal entry</i>";
|
||
|
if ($bl->{'has_entry'}) {
|
||
|
$subject = "<a href='" . LJ::item_link($u, $bl->{'jitemid'}, $bl->{'l_anum'});
|
||
|
$subject .= "'>" . ($bl->{'subject'} || "<i>no subject</i>") . "</a>";
|
||
|
}
|
||
|
$ret .= "<td class='tablecontent'>$subject</td>";
|
||
|
|
||
|
# date/time
|
||
|
my $datetime = LJ::mysql_time($bl->{'posttime'});
|
||
|
$ret .= "<td class='tablecontent'>$datetime</td>";
|
||
|
|
||
|
# length
|
||
|
my $secs = int($bl->{'lengthsecs'} / 60) . ":";
|
||
|
$secs .= sprintf("%02ds", $bl->{'lengthsecs'} % 60);
|
||
|
$ret .= "<td class='tablecontent' align='center'>$secs</td>";
|
||
|
|
||
|
# file size
|
||
|
my $len = sprintf("%.1fk", $bl->{'length'} / 1000);
|
||
|
$ret .= "<td class='tablecontent' align='center'>$len</td>";
|
||
|
|
||
|
# security
|
||
|
$ret .= "<td class='tablecontent' align='center'>";
|
||
|
if ($bl->{'security'} && $bl->{'security'} ne 'public') {
|
||
|
$ret .= "<img src='$LJ::IMGPREFIX/icon_protected.gif' width='14' ";
|
||
|
$ret .= "height='15' border='0'alt='Protected' />";
|
||
|
}
|
||
|
$ret .= "</td></tr>";
|
||
|
}
|
||
|
|
||
|
# delete button
|
||
|
$ret .= "<tr><td colspan='6' align='left'>";
|
||
|
$ret .= LJ::html_submit('action:delete', "Delete Selected") . "</td>";
|
||
|
|
||
|
return $ret;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
# All of this is managed on the FotoBilder side of things, so just give total
|
||
|
# usage info, and a link to where they can manage it.
|
||
|
if (LJ::get_cap($u, 'fb_account')) {
|
||
|
$btype{'fotobilder'} = {
|
||
|
'name' => "Photo Hosting",
|
||
|
'sort' => sub {},
|
||
|
'delete' => sub {},
|
||
|
'fetch' => sub {},
|
||
|
'render' => sub
|
||
|
{
|
||
|
my $ret;
|
||
|
|
||
|
my $pp_bytes = LJ::Blob::get_disk_usage($u, 'fotobilder');
|
||
|
my $pp_display = $size->($pp_bytes);
|
||
|
|
||
|
my $max_size = LJ::get_cap($u, "disk_quota") * $shift{MiB};
|
||
|
my $ret;
|
||
|
|
||
|
$ret .= '<tr>';
|
||
|
foreach (' ', 'Images', 'Filesize Totals') {
|
||
|
$ret .= "<td class='tablehead'>$_</td>";
|
||
|
}
|
||
|
$ret .= '</tr>';
|
||
|
|
||
|
$ret .= "<tr><td class='tablecontent'> </td>";
|
||
|
$ret .= "<td class='tablecontent' valign='top'>";
|
||
|
$ret .= "<img src='$LJ::IMGPREFIX/imageplaceholder2.png' width='35' ";
|
||
|
$ret .= "height='35' alt='' border='0' /></td>";
|
||
|
|
||
|
$ret .= "<td class='tablecontent' valign='top'>";
|
||
|
$ret .= "$pp_display (";
|
||
|
$ret .= sprintf("%.2f%%", ($pp_bytes / $max_size) * 100);
|
||
|
$ret .= " of your total) <br />";
|
||
|
|
||
|
$ret .= "Please visit <a href='$LJ::FB_SITEROOT'>$LJ::FB_DOMAIN</a> to manage your images.";
|
||
|
$ret .= '</td></tr>';
|
||
|
return $ret;
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
###
|
||
|
### START OF OUTPUT
|
||
|
###
|
||
|
my $ret;
|
||
|
|
||
|
# authas switcher form
|
||
|
$ret .= "<form method='get' action='files.bml'>\n";
|
||
|
$ret .= LJ::html_hidden('showtype' => $showtype) if $showtype;
|
||
|
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||
|
$ret .= "</form>\n\n";
|
||
|
|
||
|
# domain type selector
|
||
|
$ret .= "<form method='get' action='files.bml'>File Type: ";
|
||
|
$ret .= LJ::html_hidden('authas' => $authas) if $authas ne $remote->{'user'};
|
||
|
$ret .= LJ::html_select({ 'name' => 'showtype', 'selected' => $showtype },
|
||
|
'' => '---',
|
||
|
map { $_ => $btype{$_}->{'name'} } sort keys %btype) . " ";
|
||
|
$ret .= LJ::html_submit("Show") . "</form>";
|
||
|
|
||
|
# show quota info
|
||
|
my $used_size = LJ::Blob::get_disk_usage($u);
|
||
|
my $max_size = LJ::get_cap($u, "disk_quota") * $shift{MiB};
|
||
|
|
||
|
if ($max_size) {
|
||
|
|
||
|
$ret .= "<?h2 Quota Usage h2?>";
|
||
|
$ret .= "<p>You are currently using " . $size->($used_size) . " (";
|
||
|
$ret .= sprintf("%.2f%%", ($used_size / $max_size) * 100);
|
||
|
$ret .= ") of your " . $size->($max_size) . " quota.</p>";
|
||
|
}
|
||
|
|
||
|
return $ret unless defined $btype{$showtype};
|
||
|
|
||
|
###
|
||
|
### LOAD DATA
|
||
|
###
|
||
|
|
||
|
# now we have a showtype
|
||
|
$domain = $showtype;
|
||
|
$domainid = LJ::get_blob_domainid($domain);
|
||
|
my $bobj = $btype{$showtype};
|
||
|
|
||
|
# get db handle now
|
||
|
$dbh = LJ::get_db_writer();
|
||
|
$dbcm = LJ::get_cluster_master($u);
|
||
|
return $err->($ML{'error.nodb'}) unless $dbh && $dbcm;
|
||
|
|
||
|
# fetch data from userblob
|
||
|
my $sth = $dbcm->prepare("SELECT blobid, length FROM userblob " .
|
||
|
"WHERE journalid=? AND domain=?");
|
||
|
$sth->execute($u->{'userid'}, $domainid);
|
||
|
while (my $row = $sth->fetchrow_hashref) {
|
||
|
push @blobs, $row;
|
||
|
}
|
||
|
|
||
|
# no blobs?
|
||
|
unless (@blobs) {
|
||
|
$ret .= "<?h1 No Files h1?>";
|
||
|
$ret .= "<?p You do not have any files of the specified type. Please select a ";
|
||
|
$ret .= "different type from the list above and try again. p?>";
|
||
|
return $ret;
|
||
|
}
|
||
|
|
||
|
# generate paging object and make a navbar
|
||
|
my $page_size = 25;
|
||
|
my %items = BML::paging(\@blobs, $GET{'page'}, $page_size);
|
||
|
my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'},
|
||
|
{ 'self_link' => $self_link });
|
||
|
@blobs = @{$items{'items'}};
|
||
|
|
||
|
# get only this page of blobids
|
||
|
$blobs{$_->{'blobid'}} = $_ foreach @blobs;
|
||
|
|
||
|
# call data-getter to fill in the rest of blob data
|
||
|
$bobj->{'fetch'}->();
|
||
|
|
||
|
# sort blobs into specified order
|
||
|
@blobs = $bobj->{'sort'}->();
|
||
|
|
||
|
|
||
|
# if a blob's id is in the blobid list, but we got nothing from the
|
||
|
# database, then we'll remove its entry from userblob because we
|
||
|
# forgot to remove the row in editpics.bml
|
||
|
if ($showtype eq 'userpic') {
|
||
|
my @del;
|
||
|
foreach my $bl (@blobs) {
|
||
|
|
||
|
# see if required 'picdate' column was added in
|
||
|
push @del, $bl->{'blobid'} unless
|
||
|
$bl->{'picdate'};
|
||
|
}
|
||
|
if (@del) {
|
||
|
return $err->($ML{'error.nodb'}) unless $u->writer;
|
||
|
|
||
|
my $bind = join(",", map { "?" } @del);
|
||
|
$u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " .
|
||
|
"AND blobid IN ($bind)", undef, $u->{'userid'}, $domainid, @del);
|
||
|
|
||
|
return BML::redirect($self_link->());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
###
|
||
|
### Perform actions
|
||
|
###
|
||
|
if (LJ::did_post() && $POST{'action:delete'}) {
|
||
|
|
||
|
my $res = $bobj->{'delete'}->();
|
||
|
if ($res) {
|
||
|
# now the database has been modified and deleted, but our current
|
||
|
# memory state isn't accurate, so we'll have to redirect and start
|
||
|
# over before displaying anything below
|
||
|
return BML::redirect($self_link->());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
###
|
||
|
### Generate page
|
||
|
###
|
||
|
|
||
|
# output table
|
||
|
$ret .= $navbar;
|
||
|
$ret .= "<form method='post' action='" . $self_link->() . "'>";
|
||
|
|
||
|
$ret .= "<table border='0' width='100%' cellspacing='1' cellpadding='4'>";
|
||
|
$ret .= $bobj->{'render'}->();
|
||
|
$ret .= "</table></form>";
|
||
|
|
||
|
$ret .= $navbar;
|
||
|
|
||
|
return $ret;
|
||
|
}
|
||
|
_code?>
|
||
|
<=body
|
||
|
head<=
|
||
|
<style type='text/css'>
|
||
|
dt { font-weight: bold }
|
||
|
.tablecontent {
|
||
|
border-top: 1px solid #dfdfdf;
|
||
|
border-bottom: 1px solid #dfdfdf;
|
||
|
padding-top: 10px;
|
||
|
padding-bottom: 10px;
|
||
|
}
|
||
|
|
||
|
.tablehead {
|
||
|
border-bottom: 1px solid #dfdfdf;
|
||
|
padding-top: 10px;
|
||
|
padding-bottom: 10px;
|
||
|
font-weight: bold;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
|
||
|
.tablehead A {
|
||
|
color: #000;
|
||
|
text-decoration: none;
|
||
|
vertical-align: bottom;
|
||
|
}
|
||
|
|
||
|
.tablebottom {
|
||
|
border-top: 1px solid #dfdfdf;
|
||
|
padding-top: 10px;
|
||
|
padding-bottom: 10px;
|
||
|
}
|
||
|
</style>
|
||
|
<=head
|
||
|
page?>
|