#!/usr/local/bin/perl
# view_table.cgi
# Display all data in some table

require './postgresql-lib.pl';
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 = &quote_table($in{'table'});
if ($in{'field'}) {
	($finfo) = grep { $_->{'field'} eq $in{'field'} } @str;
        $search = "where \"$in{'field'}\" ".
                ($finfo->{'type'} eq 'bool' &&
		   $in{'match'} <= 1 ? "= $in{'for'}" :
                 $finfo->{'type'} eq 'bool' &&
		   $in{'match'} > 1 ? "!= $in{'for'}" :
		 $in{'match'} == 0 ? "like '%$in{'for'}%'" :
                 $in{'match'} == 1 ? "like '$in{'for'}'" :
                 $in{'match'} == 2 ? "not like '%$in{'for'}%'" :
                 $in{'match'} == 3 ? "not like '$in{'for'}'" : " = ''");
        }

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'}&".
		  "for=".&urlize($in{'for'})."&match=$in{'match'}");
	}
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'}&".
		  "for=".&urlize($in{'for'})."&match=$in{'match'}");
	}
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'}&".
		  "for=".&urlize($in{'for'})."&match=$in{'match'}");
	&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($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&".
		       "field=%s&for=%s&match=%s'>".
		       "<img src=/images/left.gif border=0 align=middle></a>\n",
			$in{'db'}, $in{'table'},
			$in{'start'} - $config{'perpage'},
			$in{'field'}, &urlize($in{'for'}), $in{'match'};
		}
	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&".
		       "field=%s&for=%s&match=%s'>".
		      "<img src=/images/right.gif border=0 align=middle></a>\n",
			$in{'db'}, $in{'table'},
			$in{'start'} + $config{'perpage'},
			$in{'field'}, &urlize($in{'for'}), $in{'match'};
		}
	print "</center>\n";
	}

if ($in{'field'}) {
        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";
        }

if ($config{'blob_mode'}) {
	print "<form action=view_table.cgi method=post enctype=multipart/form-data>\n";
	}
else {
	print "<form action=view_table.cgi method=post>\n";
	}
print "<input type=hidden name=db value='$in{'db'}'>\n";
print "<input type=hidden name=table value='$in{'table'}'>\n";
print "<input type=hidden name=start value='$in{'start'}'>\n";
if ($in{'field'}) {
        print "<input type=hidden name=field value='$in{'field'}'>\n";
        print "<input type=hidden name=for value='$in{'for'}'>\n";
        print "<input type=hidden name=match value='$in{'match'}'>\n";
        }
$check = !defined($in{'row'}) && !$in{'new'};
if ($total || $in{'new'}) {
	$d = &execute_sql($in{'db'},
			  "select oid,* from $qt $search limit ".
			  "$config{'perpage'} offset $in{'start'}");
	@data = @{$d->{'data'}};
	@titles = @{$d->{'titles'}}; shift(@titles);

	print "<table border width=100%>\n";
	print "<tr $tb>\n";
	print "<td>&nbsp;</td>\n" if ($check);
	foreach $t (@str) {
		print "<td><b>$t->{'field'}</b></td>\n";
		}
	print "</tr>\n";

	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);
		print "<tr $cb>\n";
		if ($row{$oid} && ($config{'add_mode'} || $has_blob)) {
			# Show multi-line row editor
			printf "<td colspan=%d>\n", scalar(@d);
			print "<table border>\n";
			print "<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 = "${oid}_$titles[$j]";
				print "<tr $cb> <td><b>$titles[$j]</b></td>\n";
				$d[$j] = &html_escape($d[$j]);
				if ($config{'blob_mode'} &&
				    &is_blob($str[$j])) {
					# Show as keep/upload inputs
					print "<td><input type=radio name=${nm}_def value=1 checked> $text{'view_keep'}\n";
					print "<input type=radio name=${nm}_def value=0> $text{'view_set'}\n";
					print "<input type=file name=$nm></td>\n";
					}
				elsif ($str[$j]->{'type'} =~ /\((\d+)\)/) {
					local $nw = $1 > 70 ? 70 : $1;
					print "<td><input name=$nm size=$nw value=\"$d[$j]\"></td>\n";
					}
				elsif (&is_blob($str[$j])) {
					print "<td><textarea name=$nm rows=5 cols=70>$d[$j]",
					      "</textarea></td>\n";
					}
				else {
					print "<td><input name=$nm size=30 value=\"$d[$j]\"></td>\n";
					}
				print "</tr>\n";
				}
			print "</table></td>\n";
			print "<input type=hidden name=row value='$oid'>\n";
			}
		elsif ($row{$oid}) {
			# Show simple row editor
			for($j=0; $j<@d; $j++) {
				$d[$j] = &html_escape($d[$j]);
				local $l = $d[$j] =~ tr/\n/\n/;
				local $nm = "${oid}_$titles[$j]";
				if ($config{'blob_mode'} &&
				    &is_blob($str[$j])) {
					# Cannot edit this blob
					print "<td width=$w%%><br></td>\n";
					}
				elsif ($l) {
					$l++;
					print "<td width=$w%%><textarea name=$nm cols=$w rows=$l>$d[$j]</textarea></td>\n";
					}
				else {
					print "<td width=$w%%><input name=$nm size=$w value=\"$d[$j]\"></td>\n";
					}
				}
			print "<input type=hidden name=row value='$oid'>\n";
			}
		else {
			# Show contents of row
			print "<td><input type=checkbox name=row ",
			      "value=$oid></td>\n" if ($check);
			local $j = 0;
			foreach $c (@d) {
				if ($config{'blob_mode'} &&
                                    &is_blob($str[$j]) && $c ne '') {
                                        print "<td width=$w%><a href='download.cgi?db=$in{'db'}&table=$in{'table'}&row=$oid&field=",&urlize($str[$j]->{'field'}),"'>$text{'view_download'}</a></td>\n";
                                        }
                                else {
					printf "<td width=$w%%>%s</td>\n",
					    $c =~ /\S/ ? &html_escape($c) : "<br>";
					}
				$j++;
				}
			}
		print "</tr>\n";
		}
	if ($in{'new'} && ($config{'add_mode'} || $has_blob)) {
		# Show new fields in longer format
		print "</table> <br> <table border>\n";
		print "<tr $tb> <td><b>$text{'view_field'}</b></td> ",
		      "<td><b>$text{'view_data'}</b></td> </tr>\n";
		for($j=0; $j<@str; $j++) {
			print "<tr $cb> <td><b>$str[$j]->{'field'}</b></td>\n";
			if ($config{'blob_mode'} && &is_blob($str[$j])) {
				print "<td><input name=$j type=file></td>\n";
				}
			elsif ($str[$j]->{'type'} =~ /\((\d+)\)/) {
				local $nw = $1 > 70 ? 70 : $1;
				print "<td><input name=$j size=$nw></td>\n";
				}
			elsif (&is_blob($str[$j])) {
				print "<td><textarea name=$j rows=5 cols=70>",
				      "</textarea></td>\n";
				}
			else {
				print "<td><input name=$j size=30></td>\n";
				}
			print "</tr>\n";
			}
		}
	elsif ($in{'new'}) {
		# Show new field row at end of table
		print "<tr $cb>\n";
		for($j=0; $j<@str; $j++) {
			print "<td width=$w%><input name=$j size=$w></td>\n";
			}
		print "</tr>\n";
		}
	print "</table>\n";
	if ($check) {
		print &select_all_link("row", 0, $text{'view_all'}),"&nbsp;\n";
		print &select_invert_link("row", 0, $text{'view_invert'}),"<br>\n";
		}
	}
else {
	print "<b>$text{'view_none'}</b> <p>\n";
	}

print "<table width=100%><tr>\n";
if (!$check) {
	if ($in{'new'}) {
		print "<td><input type=submit name=savenew ",
		      "value='$text{'save'}'></td>\n";
		}
	else {
		print "<td><input type=submit name=save ",
		      "value='$text{'save'}'></td>\n";
		}
	print "<td align=right><input type=submit name=cancel ",
	      "value='$text{'cancel'}'></td>\n";
	}
else {
	print "<td><input type=submit name=edit ",
	      "value='$text{'view_edit'}'></td>\n";
	print "<td align=middle><input type=submit name=new ",
	      "value='$text{'view_new'}'></td>\n";
	print "<td align=right><input type=submit name=delete ",
	      "value='$text{'view_delete'}'></td>\n";
	}
print "</tr></table></form>\n";

if (!$in{'field'} && $total > $config{'perpage'}) {
	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 "<input type=hidden name=db value='$in{'db'}'>\n";
	print "<input type=hidden name=table value='$in{'table'}'>\n";
	$sel = "<select name=field>\n";
	foreach $f (@str) {
		$sel .= "<option>$f->{'field'}\n";
		}
	$sel .= "</select>";
	$match = "<select name=match>\n";
	$match .= "<option value=0 selected>$text{'view_match0'}\n";
	$match .= "<option value=1>$text{'view_match1'}\n";
	$match .= "<option value=2>$text{'view_match2'}\n";
	$match .= "<option value=3>$text{'view_match3'}\n";
	$match .= "</select>";
	print "<td>",&text('view_search2', "<input name=for size=20>", $sel,
			   $match);
	print "&nbsp;&nbsp;",
	      "<input type=submit value='$text{'view_searchok'}'></td>\n";
	print "</form>\n";

	print "<form action=view_table.cgi>\n";
	print "<input type=hidden name=db value='$in{'db'}'>\n";
	print "<input type=hidden name=table value='$in{'table'}'>\n";
	print "<td align=right><input type=submit value='$text{'view_jump'}'> ";
	print "<input name=jump size=6></td></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'});

