mirror of
https://github.com/webmin/webmin.git
synced 2025-07-23 00:30:33 +00:00
416 lines
13 KiB
Perl
Executable File
416 lines
13 KiB
Perl
Executable File
#!/usr/local/bin/perl
|
|
# view_table.cgi
|
|
# Display all data in some table
|
|
|
|
require './postgresql-lib.pl';
|
|
if ($config{'charset'}) {
|
|
$force_charset = $config{'charset'};
|
|
}
|
|
if ($ENV{'CONTENT_TYPE'} !~ /boundary=/) {
|
|
&ReadParse();
|
|
}
|
|
else {
|
|
&ReadParseMime();
|
|
}
|
|
&can_edit_db($in{'db'}) || &error($text{'dbase_ecannot'});
|
|
@str = &table_structure($in{'db'}, $in{'table'});
|
|
$qt = "e_table($in{'table'});
|
|
if ($in{'field'}) {
|
|
$in{'field'} =~ s/\0.*$//;
|
|
$search = "where "."estr($in{'field'})." ".
|
|
&make_like($in{'match'}, $in{'for'}, $in{'field'});
|
|
$searchargs = "&field=".&urlize($in{'field'}).
|
|
"&for=".&urlize($in{'for'}).
|
|
"&match=".&urlize($in{'match'});
|
|
$searchhids = &ui_hidden("field", $in{'field'})."\n".
|
|
&ui_hidden("for", $in{'for'})."\n".
|
|
&ui_hidden("match", $in{'match'})."\n";
|
|
}
|
|
elsif ($in{'advanced'}) {
|
|
# An advanced search
|
|
for($i=0; defined($in{"field_$i"}); $i++) {
|
|
if ($in{"field_$i"}) {
|
|
push(@adv, "estr($in{"field_$i"})." ".
|
|
&make_like($in{"match_$i"}, $in{"for_$i"},
|
|
$in{"field_$i"}));
|
|
$searchargs .= "&field_$i=".&urlize($in{"field_$i"}).
|
|
"&for_$i=".&urlize($in{"for_$i"}).
|
|
"&match_$i=".&urlize($in{"match_$i"});
|
|
$searchhids .= &ui_hidden("field_$i", $in{"field_$i"})."\n".
|
|
&ui_hidden("for_$i", $in{"for_$i"})."\n".
|
|
&ui_hidden("match_$i", $in{"match_$i"})."\n";
|
|
}
|
|
}
|
|
if (@adv) {
|
|
$search = "where (".join($in{'and'} ? " and " : " or ",
|
|
@adv).")";
|
|
$searchhids .= &ui_hidden("and", $in{'and'})."\n".
|
|
&ui_hidden("advanced", 1)."\n";
|
|
$searchargs .= "&and=".$in{'and'}.
|
|
"&advanced=1";
|
|
}
|
|
}
|
|
|
|
if ($in{'delete'}) {
|
|
# Deleting selected rows
|
|
$count = 0;
|
|
foreach $r (split(/\0/, $in{'row'})) {
|
|
&execute_sql_logged($in{'db'},
|
|
"delete from $qt where oid = ?", $r);
|
|
$count++;
|
|
}
|
|
&webmin_log("delete", "data", $count, \%in);
|
|
&redirect("view_table.cgi?db=$in{'db'}&".
|
|
"table=$in{'table'}&start=$in{'start'}&field=$in{'field'}".
|
|
$searchargs);
|
|
}
|
|
elsif ($in{'save'}) {
|
|
# Update edited rows
|
|
$count = 0;
|
|
foreach $r (split(/\0/, $in{'row'})) {
|
|
local @set;
|
|
local @params;
|
|
foreach $t (@str) {
|
|
local $ij = $in{"${r}_$t->{'field'}"};
|
|
local $ijdef = $in{"${r}_$t->{'field'}_def"};
|
|
next if ($ijdef || !defined($ij));
|
|
if (!$config{'blob_mode'} || !&is_blob($str[$i])) {
|
|
$ij =~ s/\r//g;
|
|
}
|
|
push(@set, "$t->{'field'} = ?");
|
|
push(@params, $ij eq "" ? undef : $ij);
|
|
}
|
|
&execute_sql_logged($in{'db'}, "update $qt set ".
|
|
join(" , ", @set)." where oid = ?",
|
|
@params, $r);
|
|
$count++;
|
|
}
|
|
&webmin_log("modify", "data", $count, \%in);
|
|
&redirect("view_table.cgi?db=$in{'db'}&".
|
|
"table=$in{'table'}&start=$in{'start'}&field=$in{'field'}".
|
|
$searchargs);
|
|
}
|
|
elsif ($in{'savenew'}) {
|
|
# Adding a new row
|
|
for($j=0; defined($in{$j}); $j++) {
|
|
if (!$config{'blob_mode'} || !&is_blob($str[$i])) {
|
|
$in{$j} =~ s/\r//g;
|
|
}
|
|
push(@set, $in{$j} eq "" ? undef : $in{$j});
|
|
}
|
|
&execute_sql_logged($in{'db'}, "insert into $qt values (".
|
|
join(" , ", map { "?" } @set).")", @set);
|
|
&redirect("view_table.cgi?db=$in{'db'}&".
|
|
"table=$in{'table'}&start=$in{'start'}&field=$in{'field'}".
|
|
$searchargs);
|
|
&webmin_log("create", "data", undef, \%in);
|
|
}
|
|
elsif ($in{'cancel'} || $in{'new'}) {
|
|
undef($in{'row'});
|
|
}
|
|
|
|
$desc = &text('table_header', "<tt>$in{'table'}</tt>", "<tt>$in{'db'}</tt>");
|
|
&ui_print_header($desc, $text{'view_title'}, "", "view_table");
|
|
|
|
foreach $t (@str) {
|
|
$has_blob++ if (&is_blob($t));
|
|
}
|
|
if (!$driver_handle && $config{'blob_mode'} && $has_blob) {
|
|
print "<center><b>",&text('view_warn', "<tt>DBI</tt>",
|
|
"<tt>DBD::Pg</tt>"),"</b></center><p>\n";
|
|
}
|
|
|
|
$d = &execute_sql_safe($in{'db'}, "select count(*) from $qt $search");
|
|
$total = $d->{'data'}->[0]->[0];
|
|
if ($in{'jump'} > 0) {
|
|
$in{'start'} = int($in{'jump'} / $config{'perpage'}) *
|
|
$config{'perpage'};
|
|
if ($in{'start'} >= $total) {
|
|
$in{'start'} = $total - $config{'perpage'};
|
|
$in{'start'} = int(($in{'start'} / $config{'perpage'}) + 1) *
|
|
$config{'perpage'};
|
|
}
|
|
}
|
|
else {
|
|
$in{'start'} = int($in{'start'});
|
|
}
|
|
if ($in{'new'} && $total > $config{'perpage'}) {
|
|
# go to the last screen for adding a row
|
|
$in{'start'} = $total - $config{'perpage'};
|
|
$in{'start'} = int(($in{'start'} / $config{'perpage'}) + 1) *
|
|
$config{'perpage'};
|
|
}
|
|
if ($in{'start'} || $total > $config{'perpage'}) {
|
|
print "<center>\n";
|
|
if ($in{'start'}) {
|
|
printf "<a href='view_table.cgi?db=%s&table=%s&start=%s%s'>".
|
|
"<img src=/images/left.gif border=0 align=middle></a>\n",
|
|
$in{'db'}, $in{'table'},
|
|
$in{'start'} - $config{'perpage'},
|
|
$searchargs;
|
|
}
|
|
print "<font size=+1>",&text('view_pos', $in{'start'}+1,
|
|
$in{'start'}+$config{'perpage'} > $total ? $total :
|
|
$in{'start'}+$config{'perpage'}, $total),"</font>\n";
|
|
if ($in{'start'}+$config{'perpage'} < $total) {
|
|
printf "<a href='view_table.cgi?db=%s&table=%s&start=%s%s'>".
|
|
"<img src=/images/right.gif border=0 align=middle></a>\n",
|
|
$in{'db'}, $in{'table'},
|
|
$in{'start'} + $config{'perpage'},
|
|
$searchargs;
|
|
}
|
|
print "</center>\n";
|
|
}
|
|
|
|
if ($in{'field'}) {
|
|
# Show details of simple search
|
|
print "<table width=100% cellspacing=0 cellpadding=0><tr>\n";
|
|
print "<td><b>",&text('view_searchhead', "<tt>$in{'for'}</tt>",
|
|
"<tt>$in{'field'}</tt>"),"</b></td>\n";
|
|
print "<td align=right><a href='view_table.cgi?db=$in{'db'}&",
|
|
"table=$in{'table'}'>$text{'view_searchreset'}</a></td>\n";
|
|
print "</tr></table>\n";
|
|
}
|
|
elsif ($in{'advanced'}) {
|
|
# Show details of advanced search
|
|
print "<table width=100% cellspacing=0 cellpadding=0><tr>\n";
|
|
print "<td><b>",&text('view_searchhead2', scalar(@adv)),"</b></td>\n";
|
|
print "<td align=right><a href='view_table.cgi?db=$in{'db'}&",
|
|
"table=$in{'table'}'>$text{'view_searchreset'}</a></td>\n";
|
|
print "</tr></table>\n";
|
|
}
|
|
|
|
if ($config{'blob_mode'}) {
|
|
print &ui_form_start("view_table.cgi", "form-data"),"\n";
|
|
}
|
|
else {
|
|
print &ui_form_start("view_table.cgi", "post"),"\n";
|
|
}
|
|
print &ui_hidden("db", $in{'db'}),"\n";
|
|
print &ui_hidden("table", $in{'table'}),"\n";
|
|
print &ui_hidden("start", $in{'start'}),"\n";
|
|
print $searchhids;
|
|
$check = !defined($in{'row'}) && !$in{'new'};
|
|
if ($total || $in{'new'}) {
|
|
# Get the rows of data, and show the table header
|
|
$d = &execute_sql_safe($in{'db'},
|
|
"select oid,* from $qt $search limit ".
|
|
"$config{'perpage'} offset $in{'start'}");
|
|
@data = @{$d->{'data'}};
|
|
@titles = @{$d->{'titles'}}; shift(@titles);
|
|
print &select_all_link("row"),"\n";
|
|
print &select_invert_link("row"),"<br>\n";
|
|
print &ui_columns_start([
|
|
$check ? ( "" ) : ( ),
|
|
map { $_->{'field'} } @str
|
|
], 100);
|
|
@tds = $check ? ( "width=5" ) : ( );
|
|
($has_blob) = grep { &is_blob($_) } @str;
|
|
|
|
# Add an empty row for inserting
|
|
$realrows = scalar(@data);
|
|
if ($in{'new'}) {
|
|
push(@data, [ "*", map { undef } @str ]);
|
|
$row{"*"} = 1;
|
|
}
|
|
|
|
# Show the rows, some of which may be editable
|
|
map { $row{$_}++ } split(/\0/, $in{'row'});
|
|
$w = int(100 / scalar(@str));
|
|
$w = 10 if ($w < 10);
|
|
for($i=0; $i<@data; $i++) {
|
|
local @d = @{$data[$i]};
|
|
local $oid = shift(@d);
|
|
if ($row{$oid} && ($config{'add_mode'} || $has_blob)) {
|
|
# Show multi-line row editor
|
|
$et = "<table border>\n";
|
|
$et .= "<tr $tb> <td><b>$text{'view_field'}</b></td> ".
|
|
"<td><b>$text{'view_data'}</b></td> </tr>\n";
|
|
for($j=0; $j<@d; $j++) {
|
|
local $nm = $i == $realrows ? $j :
|
|
"${oid}_$titles[$j]";
|
|
$et .= "<tr $cb> <td><b>$titles[$j]</b></td> <td>";
|
|
if ($config{'blob_mode'} &&
|
|
&is_blob($str[$j]) && $d[$j]) {
|
|
# Show as keep/upload inputs
|
|
$et .= &ui_radio($nm."_def", 1,
|
|
[ [ 1, $text{'view_keep'} ],
|
|
[ 0, $text{'view_set'} ] ])." ".
|
|
&ui_upload($nm);
|
|
}
|
|
elsif ($config{'blob_mode'} &&
|
|
&is_blob($str[$j])) {
|
|
# Show upload input
|
|
$et .= &ui_upload($nm);
|
|
}
|
|
elsif ($str[$j]->{'type'} =~ /\((\d+)\)/) {
|
|
# Show as known-size text
|
|
local $nw = $1 > 70 ? 70 : $1;
|
|
$et .= &ui_textbox($nm, $d[$j], $nw);
|
|
}
|
|
elsif (&is_blob($str[$j])) {
|
|
# Show as multiline text
|
|
$et .= &ui_textarea($nm, $d[$j], 5, 70);
|
|
}
|
|
else {
|
|
# Show as fixed-size text
|
|
$et .= &ui_textbox($nm, $d[$j], 30);
|
|
}
|
|
$et .= "</td></tr>\n";
|
|
}
|
|
print &ui_hidden("row", $oid),"\n";
|
|
$et .= "</table>";
|
|
print &ui_columns_row([ $check ? ( "" ) : ( ), $et ],
|
|
[ @tds, "colspan=".scalar(@d) ] );
|
|
}
|
|
elsif ($row{$oid}) {
|
|
# Show one-line row-editor
|
|
local @cols;
|
|
for($j=0; $j<@d; $j++) {
|
|
local $l = $d[$j] =~ tr/\n/\n/;
|
|
local $nm = $i == $realrows ? $j :
|
|
"${oid}_$titles[$j]";
|
|
if ($config{'blob_mode'} &&
|
|
&is_blob($str[$j])) {
|
|
# Cannot edit this blob
|
|
push(@cols, undef);
|
|
}
|
|
elsif ($str[$j]->{'type'} =~ /\((\d+)\)/) {
|
|
# Show as known-size text
|
|
local $nw = $1 > 70 ? 70 : $1;
|
|
push(@cols,
|
|
&ui_textbox($nm, $d[$j], $nw));
|
|
}
|
|
elsif ($l) {
|
|
# Show as multiline text
|
|
$l++;
|
|
push(@cols,
|
|
&ui_textarea($nm, $d[$j], $l, $w));
|
|
}
|
|
else {
|
|
# Show as known size text
|
|
push(@cols,
|
|
&ui_textbox($nm, $d[$j], $w));
|
|
}
|
|
}
|
|
print &ui_hidden("row", $oid),"\n";
|
|
print &ui_columns_row([ $check ? ( "" ) : ( ), @cols ],
|
|
\@tds);
|
|
}
|
|
else {
|
|
# Show contents of row
|
|
local @cols;
|
|
local $j = 0;
|
|
foreach $c (@d) {
|
|
if ($config{'blob_mode'} &&
|
|
&is_blob($str[$j]) && $c ne '') {
|
|
# Show download link for blob
|
|
push(@cols, "<a href='download.cgi?db=$in{'db'}&table=$in{'table'}&row=$oid&field=".&urlize($str[$j]->{'field'})."'>$text{'view_download'}</a>");
|
|
}
|
|
else {
|
|
# Just show text (up to limit)
|
|
if ($config{'max_text'} &&
|
|
length($c) > $config{'max_text'}) {
|
|
$c = substr($c, 0,
|
|
$config{'max_text'})." ...";
|
|
}
|
|
push(@cols, &html_escape($c));
|
|
}
|
|
$j++;
|
|
}
|
|
if ($check) {
|
|
print &ui_checked_columns_row(\@cols, \@tds,
|
|
"row", $oid);
|
|
}
|
|
else {
|
|
print &ui_columns_row(\@cols, \@tds);
|
|
}
|
|
}
|
|
print "</tr>\n";
|
|
}
|
|
print &ui_columns_end();
|
|
if ($check) {
|
|
print &select_all_link("row"),"\n";
|
|
print &select_invert_link("row"),"<br>\n";
|
|
}
|
|
}
|
|
else {
|
|
print "<b>$text{'view_none'}</b> <p>\n";
|
|
}
|
|
|
|
# Show buttons to edit / delete rows
|
|
if (!$check) {
|
|
if ($in{'new'}) {
|
|
print &ui_form_end([ [ "savenew", $text{'save'} ],
|
|
[ "cancel", $text{'cancel'} ] ]);
|
|
}
|
|
else {
|
|
print &ui_form_end([ [ "save", $text{'save'} ],
|
|
[ "cancel", $text{'cancel'} ] ]);
|
|
}
|
|
}
|
|
elsif ($total) {
|
|
print &ui_form_end([ [ "edit", $text{'view_edit'} ],
|
|
[ "new", $text{'view_new'} ],
|
|
[ "delete", $text{'view_delete'} ] ]);
|
|
}
|
|
else {
|
|
print &ui_form_end([ [ "new", $text{'view_new'} ] ]);
|
|
}
|
|
|
|
if (!$in{'field'} && $total > $config{'perpage'} || 1) {
|
|
print "<hr>\n";
|
|
print "<table width=100%><tr>\n";
|
|
print "<form action=view_table.cgi>\n";
|
|
print "<input type=hidden name=search value=1>\n";
|
|
print &ui_hidden("db", $in{'db'});
|
|
print &ui_hidden("table", $in{'table'});
|
|
$sel = &ui_select("field", undef,
|
|
[ map { [ $_->{'field'}, $_->{'field'} ] } @str ]);
|
|
$match = &ui_select("match", 0,
|
|
[ map { [ $_, $text{'view_match'.$_} ] } (0.. 3) ]);
|
|
print "<td>",&text('view_search2', "<input name=for size=20>", $sel,
|
|
$match);
|
|
print " ",
|
|
"<input type=submit value='$text{'view_searchok'}'></td>\n";
|
|
print "</form>\n";
|
|
|
|
print "<form action=view_table.cgi>\n";
|
|
print &ui_hidden("db", $in{'db'});
|
|
print &ui_hidden("table", $in{'table'});
|
|
print "<td align=right><input type=submit value='$text{'view_jump'}'> ";
|
|
print "<input name=jump size=6></td></form>\n";
|
|
|
|
print "</tr><tr>\n";
|
|
|
|
print "<form action=search_form.cgi>\n";
|
|
print &ui_hidden("db", $in{'db'});
|
|
print &ui_hidden("table", $in{'table'});
|
|
print "<td><input type=submit value='$text{'view_adv'}'></td>\n";
|
|
print "</form>\n";
|
|
|
|
print "</tr> </table>\n";
|
|
}
|
|
|
|
&ui_print_footer("edit_table.cgi?db=$in{'db'}&table=$in{'table'}",$text{'table_return'},
|
|
"edit_dbase.cgi?db=$in{'db'}", $text{'dbase_return'},
|
|
"", $text{'index_return'});
|
|
|
|
# make_like(mode, for, field)
|
|
sub make_like
|
|
{
|
|
local ($match, $for, $field) = @_;
|
|
local ($finfo) = grep { $_->{'field'} eq $field } @str;
|
|
local $bool = $finfo->{'type'} eq 'bool';
|
|
local $bit = $finfo->{'type'} =~ /^bit/;
|
|
return $bool && $match <= 1 ? "= $for" :
|
|
$bool && $match > 1 ? "!= $for" :
|
|
$bit && $match <= 1 ? "= b'$for'" :
|
|
$bit && $match > 1 ? "!= b'$for'" :
|
|
$match == 0 ? "like '%$for%'" :
|
|
$match == 1 ? "like '$for'" :
|
|
$match == 2 ? "not like '%$for%'" :
|
|
$match == 3 ? "not like '$for'" : " = ''";
|
|
}
|
|
|