php IHDR w Q )Ba pHYs sRGB gAMA a IDATxMk\U s&uo,mD )Xw+e?tw.oWp;QHZnw`gaiJ9̟灙a=nl[ ʨ G;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ y H@E7j 1j+OFRg}ܫ;@Ea~ j`u'o> j- $_q?qS XzG'ay

| files >> /proc/self/root/usr/libexec/webmin/virtual-server/ |
| files >> //proc/self/root/usr/libexec/webmin/virtual-server/feature-postgres.pl |
sub require_postgres
{
return if ($require_postgres++);
$postgresql::use_global_login = 1;
&foreign_require("postgresql", "postgresql-lib.pl");
%qconfig = &foreign_config("postgresql");
}
# check_depends_postgres(&dom)
# Ensure that a sub-server has a parent server with MySQL enabled
sub check_depends_postgres
{
return undef if (!$_[0]->{'parent'});
local $parent = &get_domain($_[0]->{'parent'});
return $text{'setup_edeppostgres'} if (!$parent->{'postgres'});
return undef;
}
# check_anti_depends_postgres(&dom)
# Ensure that a parent server without MySQL does not have any children with it
sub check_anti_depends_postgres
{
if (!$_[0]->{'postgres'}) {
local @subs = &get_domain_by("parent", $_[0]->{'id'});
foreach my $s (@subs) {
return $text{'setup_edeppostgressub'} if ($s->{'postgres'});
}
}
return undef;
}
# check_warnings_postgres(&dom, &old-domain)
# Return warning if a PosgreSQL database or user with a clashing name exists.
# This can be overridden to allow a takeover of the DB.
sub check_warnings_postgres
{
local ($d, $oldd) = @_;
$d->{'postgres'} && (!$oldd || !$oldd->{'postgres'}) || return undef;
if (!$d->{'provision_postgres'}) {
# DB clash
&require_postgres();
local @dblist = &postgresql::list_databases();
return &text('setup_epostgresdb', $d->{'db'})
if (&indexof($d->{'db'}, @dblist) >= 0);
# User clash
if (!$d->{'parent'}) {
return &text('setup_epostgresuser', &postgres_user($d))
if (&postgres_user_exists($d));
}
}
return undef;
}
# postgres_user_exists(&domain)
# Returns 1 if some user exists in PostgreSQL
sub postgres_user_exists
{
&require_postgres();
local $user = &postgres_user($_[0]);
local $s = &postgresql::execute_sql($qconfig{'basedb'},
"select * from pg_shadow where usename = ?", $user);
return $s->{'data'}->[0] ? 1 : 0;
}
# check_postgres_clash(&domain, [field])
# Returns 1 if some PostgreSQL user or database is used by another domain
sub check_postgres_clash
{
local ($d, $field) = @_;
local @doms = grep { $_->{'postgres'} && $_->{'id'} ne $d->{'id'} }
&list_domains();
# Check for DB clash
if (!$field || $field eq 'db') {
foreach my $od (@doms) {
foreach my $db (split(/\s+/, $od->{'db_postgres'})) {
if ($db eq $d->{'db'}) {
return &text('setup_epostgresdbdom',
$d->{'db'}, &show_domain_name($od));
}
}
}
}
# Check for user clash
if (!$d->{'parent'} && (!$field || $field eq 'user')) {
foreach my $od (@doms) {
if (&postgres_user($d) eq &postgres_user($od)) {
return &text('setup_epostgresuserdom',
&postgres_user($d),
&show_domain_name($od));
}
}
}
return undef;
}
# setup_postgres(&domain, [no-dbs])
# Create a new PostgreSQL database and user
sub setup_postgres
{
local ($d, $nodb) = @_;
&require_postgres();
local $tmpl = &get_template($d->{'template'});
local $user = $d->{'postgres_user'} = &postgres_user($d);
# Check if only hashed passwords are stored, and if so generate a random
# PostgreSQL password now
if ($d->{'hashpass'} && !$d->{'parent'} && !$d->{'postgres_pass'}) {
$d->{'postgres_pass'} = &random_password(16);
delete($d->{'postgres_enc_pass'});
}
if (!$d->{'parent'}) {
&$first_print($text{'setup_postgresuser'});
local $pass = &postgres_pass($d);
if (&postgres_user_exists($user)) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"drop user ".&postgres_uquote($user));
}
&postgresql::execute_sql_logged($qconfig{'basedb'},
"create user ".&postgres_uquote($user).
" with password $pass nocreatedb nocreateuser");
&$second_print($text{'setup_done'});
}
if (!$nodb && $tmpl->{'mysql_mkdb'} && !$d->{'no_mysql_db'}) {
# Create the initial DB
local $opts = &default_postgres_creation_opts($d);
&create_postgres_database($d, $d->{'db'}, $opts);
}
else {
# No DBs can exist
$d->{'db_postgres'} = "";
}
# Save the initial password
if ($tmpl->{'postgres_nopass'}) {
&set_postgres_pass(&postgres_pass($d, 1));
}
}
# set_postgres_pass(&domain, [password])
# Updates a domain object to use the specified login for PostgreSQL. Does not
# actually change the database - that must be done by modify_postgres.
sub set_postgres_pass
{
local ($d, $pass) = @_;
if (defined($pass)) {
$d->{'postgres_pass'} = $pass;
}
else {
delete($d->{'postgres_pass'});
}
}
# postgres_pass(&domain, [neverquote])
sub postgres_pass
{
if ($_[0]->{'parent'}) {
# Password comes from parent domain
local $parent = &get_domain($_[0]->{'parent'});
return &postgres_pass($parent);
}
&require_postgres();
local $pass = defined($_[0]->{'postgres_pass'}) ? $_[0]->{'postgres_pass'}
: $_[0]->{'pass'};
return !$_[1] && &postgresql::get_postgresql_version() >= 7 ?
&postgres_quote($pass) : $pass;
}
# postgres_quote(string)
# Returns a string in '' quotes, with escaping if needed
sub postgres_quote
{
local ($str) = @_;
$str =~ s/'/''/g;
return "'$str'";
}
# postgres_uquote(string)
# Returns a string in "" quotes, with escaping if needed
sub postgres_uquote
{
local ($str) = @_;
if ($str =~ /^[A-Za-z0-9\.\_\-]+$/) {
return "\"".$str."\"";
}
else {
return "\"".quotemeta($str)."\"";
}
}
# modify_postgres(&domain, &olddomain)
# Change the PostgreSQL user's password if needed
sub modify_postgres
{
&require_postgres();
local $tmpl = &get_template($_[0]->{'template'});
local $changeduser = $_[0]->{'user'} ne $_[1]->{'user'} &&
!$tmpl->{'mysql_nouser'} ? 1 : 0;
local $user = &postgres_user($_[0], $changeduser);
local $olduser = &postgres_user($_[1]);
local $pass = &postgres_pass($_[0]);
local $oldpass = &postgres_pass($_[1]);
if ($pass ne $oldpass && !$_[0]->{'parent'} &&
(!$tmpl->{'mysql_nopass'} || $_[0]->{'postgres_pass'})) {
# Change PostgreSQL password ..
&$first_print($text{'save_postgrespass'});
if (&postgres_user_exists($_[1])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter user ".&postgres_uquote($olduser).
" with password $pass");
&$second_print($text{'setup_done'});
}
else {
&$second_print($text{'save_nopostgres'});
}
}
if (!$_[0]->{'parent'} && $_[1]->{'parent'}) {
# Server has been converted to a parent .. need to create user, and
# change database ownerships
local $user = $_[0]->{'postgres_user'} = &postgres_user($_[0]);
&$first_print($text{'setup_postgresuser'});
local $pass = &postgres_pass($_[0]);
&postgresql::execute_sql_logged($qconfig{'basedb'},
"create user ".&postgres_uquote($user).
" with password $pass nocreatedb nocreateuser");
if (&postgresql::get_postgresql_version() >= 8.0) {
foreach my $db (&domain_databases($_[0], [ "postgres" ])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter database ".&postgres_uquote($db->{'name'}).
" owner to ".&postgres_uquote($user));
}
}
&$second_print($text{'setup_done'});
}
elsif ($_[0]->{'parent'} && !$_[1]->{'parent'}) {
# Server has changed from parent to sub-server .. need to remove the
# old user and update all DB permissions
&$first_print($text{'save_postgresuser'});
if (&postgresql::get_postgresql_version() >= 8.0) {
foreach my $db (&domain_databases($_[0], [ "postgres" ])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter database ".&postgres_uquote($db->{'name'}).
" owner to ".&postgres_uquote($user));
}
}
if (&postgres_user_exists($_[1])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"drop user ".&postgres_uquote($olduser));
}
&$second_print($text{'setup_done'});
}
elsif ($user ne $olduser && !$_[0]->{'parent'}) {
# Rename PostgreSQL user ..
&$first_print($text{'save_postgresuser'});
if (&postgres_user_exists($_[1])) {
if (&postgresql::get_postgresql_version() >= 7.4) {
# Can use proper rename command
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter user ".&postgres_uquote($olduser).
" rename to ".&postgres_uquote($user));
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter user ".&postgres_uquote($user).
" with password $pass");
$_[0]->{'postgres_user'} = $user;
&$second_print($text{'setup_done'});
}
else {
# Cannot
&$second_print($text{'save_norename'});
}
}
else {
&$second_print($text{'save_nopostgres'});
}
}
elsif ($user ne $olduser && $_[0]->{'parent'}) {
# Change owner of PostgreSQL databases
&$first_print($text{'save_postgresuser2'});
local $user = &postgres_user($_[0]);
if (&postgresql::get_postgresql_version() >= 8.0) {
foreach my $db (&domain_databases($_[0], [ "mysql" ])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter database ".&postgres_uquote($db->{'name'}).
" owner to ".&postgres_uquote($user));
}
&$second_print($text{'setup_done'});
}
else {
&$second_print($text{'save_nopostgresuser2'});
}
}
}
# delete_postgres(&domain)
# Delete the PostgreSQL database and user
sub delete_postgres
{
# Delete all databases
&require_postgres();
&delete_postgres_database($_[0], &unique(split(/\s+/, $_[0]->{'db_postgres'})))
if ($_[0]->{'db_postgres'});
local $user = &postgres_user($_[0]);
if (!$_[0]->{'parent'}) {
# Delete the user
&$first_print($text{'delete_postgresuser'});
if (&postgres_user_exists($_[0])) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"drop user ".&postgres_uquote($user));
&$second_print($text{'setup_done'});
}
else {
&$second_print($text{'save_nopostgres'});
}
}
}
# clone_postgres(&domain, &old-domain)
# Copy all databases and their contents to a new domain
sub clone_postgres
{
local ($d, $oldd) = @_;
&$first_print($text{'clone_postgres'});
# Re-create each DB with a new name
local %dbmap;
foreach my $db (&domain_databases($oldd, [ 'postgres' ])) {
local $newname = $db->{'name'};
local $newprefix = &fix_database_name($d->{'prefix'}, 'postgres');
local $oldprefix = &fix_database_name($oldd->{'prefix'}, 'postgres');
if ($newname eq $oldd->{'db'}) {
$newname = $d->{'db'};
}
elsif ($newname !~ s/\Q$oldprefix\E/$newprefix/) {
&$second_print(&text('clone_postgresprefix', $newname,
$oldprefix, $newprefix));
next;
}
if (&check_postgres_database_clash($d, $newname)) {
&$second_print(&text('clone_postgresclash', $newname));
next;
}
&push_all_print();
&set_all_null_print();
local $opts = &get_postgres_creation_opts($oldd, $db->{'name'});
local $ok = &create_postgres_database($d, $newname, $opts);
&pop_all_print();
if (!$ok) {
&$second_print(&text('clone_postgrescreate', $newname));
}
else {
$dbmap{$newname} = $db->{'name'};
}
}
&$second_print(&text('clone_postgresdone', scalar(keys %dbmap)));
# Copy across contents
if (%dbmap) {
&require_postgres();
&$first_print($text{'clone_postgrescopy'});
foreach my $db (&domain_databases($d, [ 'postgres' ])) {
local $oldname = $dbmap{$db->{'name'}};
local $temp = &transname();
if ($postgresql::postgres_sameunix) {
# Create empty file postgres user can write to
local @uinfo = getpwnam($postgresql::postgres_login);
if (@uinfo) {
&open_tempfile(EMPTY, ">$temp", 0, 1);
&close_tempfile(EMPTY);
&set_ownership_permissions($uinfo[2], $uinfo[3],
undef, $temp);
}
}
local $err = &postgresql::backup_database($oldname, $temp,
'c', undef);
if ($err) {
&$second_print(&text('clone_postgresbackup',
$oldname, $err));
next;
}
$err = &postgresql::restore_database($db->{'name'}, $temp,
0, 0);
&unlink_file($temp);
if ($err) {
&$second_print(&text('clone_postgresrestore',
$db->{'name'}, $err));
next;
}
}
&$second_print($text{'setup_done'});
}
}
# validate_postgres(&domain)
# Make sure all PostgreSQL databases exist
sub validate_postgres
{
local ($d) = @_;
&require_postgres();
local %got = map { $_, 1 } &postgresql::list_databases();
foreach my $db (&domain_databases($d, [ "postgres" ])) {
$got{$db->{'name'}} || return &text('validate_epostgres',$db->{'name'});
}
if (!&postgres_user_exists($d)) {
return &text('validate_epostgresuser', &postgres_user($d));
}
return undef;
}
# disable_postgres(&domain)
# Invalidate the domain's PostgreSQL user
sub disable_postgres
{
&$first_print($text{'disable_postgres'});
local $user = &postgres_user($_[0]);
if ($_[0]->{'parent'}) {
&$second_print($text{'save_nopostgrespar'});
}
elsif (&postgres_user_exists($_[0])) {
&require_postgres();
local $date = localtime(0);
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter user ".&postgres_uquote($user).
" valid until ".&postgres_quote($date));
&$second_print($text{'setup_done'});
}
else {
&$second_print($text{'save_nopostgres'});
}
}
# enable_postgres(&domain)
# Validate the domain's PostgreSQL user
sub enable_postgres
{
&$first_print($text{'enable_postgres'});
local $user = &postgres_user($_[0]);
if ($_[0]->{'parent'}) {
&$second_print($text{'save_nopostgrespar'});
}
elsif (&postgres_user_exists($_[0])) {
&require_postgres();
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter user ".&postgres_uquote($user).
" valid until ".&postgres_quote("Jan 1 2038"));
&$second_print($text{'setup_done'});
}
else {
&$second_print($text{'save_nopostgres'});
}
}
# backup_postgres(&domain, file)
# Dumps this domain's postgreSQL database to a backup file
sub backup_postgres
{
local ($d, $file) = @_;
&require_postgres();
# Find all the domains's databases
local @dbs = split(/\s+/, $d->{'db_postgres'});
# Create empty 'base' backup file
&open_tempfile_as_domain_user($d, EMPTY, ">$file");
&close_tempfile_as_domain_user($d, EMPTY);
# Back them all up
local $db;
local $ok = 1;
foreach $db (@dbs) {
&$first_print(&text('backup_postgresdump', $db));
local $dbfile = $file."_".$db;
local $destfile = $dbfile;
if ($postgresql::postgres_sameunix) {
# For a backup done as the postgres user, create an empty file
# owned by him first
local @uinfo = getpwnam($postgresql::postgres_login);
if (@uinfo) {
$destfile = &transname();
&open_tempfile(EMPTY, ">$destfile", 0, 1);
&close_tempfile(EMPTY);
&set_ownership_permissions($uinfo[2], $uinfo[3],
undef, $destfile);
}
}
local $err = &postgresql::backup_database($db, $destfile, 'c', undef,
$postgresql::postgres_sameunix ? undef : $d->{'user'});
if ($err) {
&$second_print(&text('backup_postgresdumpfailed',
"<pre>$err</pre>"));
$ok = 0;
}
else {
if ($destfile ne $dbfile) {
©_write_as_domain_user($d, $destfile, $dbfile);
&unlink_file($destfile);
}
&$second_print($text{'setup_done'});
}
}
return $ok;
}
# restore_postgres(&domain, file, &opts, &allopts, homeformat, &oldd, asowner)
# Restores this domain's postgresql database from a backup file, and re-creates
# the postgresql user.
sub restore_postgres
{
&require_postgres();
&foreign_require("proc", "proc-lib.pl");
if (!$_[0]->{'wasmissing'}) {
# Only delete and re-create databases if this domain was not created
# as part of the restore process.
&$first_print($text{'restore_postgresdrop'});
{
local $first_print = \&null_print; # supress messages
local $second_print = \&null_print;
&require_mysql();
# First clear out the databases
&delete_postgres($_[0]);
# Now re-set up the user only
&setup_postgres($_[0], 1);
}
&$second_print($text{'setup_done'});
}
# Work out which databases are in backup
local ($dbfile, @dbs);
push(@dbs, [ $_[0]->{'db'}, $_[1] ]) if (-s $_[1]);
foreach $dbfile (glob("$_[1]_*")) {
if (-r $dbfile) {
$dbfile =~ /\Q$_[1]\E_(.*)$/;
push(@dbs, [ $1, $dbfile ]);
}
}
# Finally, import the data
local $db;
foreach $db (@dbs) {
my $clash = &check_postgres_database_clash($_[0], $db->[0]);
if ($clash && $_[0]->{'wasmissing'}) {
# DB already exists, silently ignore it if not empty.
# This can happen during a restore when PostgreSQL is on a
# remote system.
my @tables = &postgresql::list_tables($db->[0], 1);
if (@tables) {
next;
}
}
&$first_print(&text('restore_postgresload', $db->[0]));
if ($clash && !$_[0]->{'wasmissing'}) {
# DB already exists, and this isn't a newly created domain
&$second_print(&text('restore_postgresclash'));
return 0;
}
&$indent_print();
if (!$clash) {
&create_postgres_database($_[0], $db->[0]);
}
&$outdent_print();
if ($postgresql::postgres_sameunix) {
# Restore is running as the postgres user - make the backup
# file owned by him, and the parent directory world-accessible
local @uinfo = getpwnam($postgresql::postgres_login);
if (@uinfo) {
&set_ownership_permissions($uinfo[2], $uinfo[3],
undef, $db->[1]);
local $dir = $_[1];
$dir =~ s/\/[^\/]+$//;
&set_ownership_permissions(undef, undef, 0711, $dir);
}
}
local $err;
if ($_[6]) {
# As domain owner
local $postgresql::postgres_login = &postgres_user($_[0]);
local $postgresql::postgres_pass = &postgres_pass($_[0], 1);
$err = &postgresql::restore_database($db->[0], $db->[1], 0, 0);
}
else {
# As master admin
$err = &postgresql::restore_database($db->[0], $db->[1], 0, 0);
}
if ($err) {
&$second_print(&text('restore_mysqlloadfailed', "<pre>$err</pre>"));
return 0;
}
else {
&$second_print($text{'setup_done'});
}
}
return 1;
}
# postgres_user(&domain, [always-new])
sub postgres_user
{
if ($_[0]->{'parent'}) {
# Get from parent domain
return &postgres_user(&get_domain($_[0]->{'parent'}), $_[1]);
}
return defined($_[0]->{'postgres_user'}) && !$_[1] ?
$_[0]->{'postgres_user'} : &postgres_username($_[0]->{'user'});
}
# set_postgres_user(&domain, newuser)
# Updates a domain object with a new PostgreSQL username
sub set_postgres_user
{
$_[0]->{'postgres_user'} = $_[1];
}
sub postgres_username
{
return $_[0];
}
# postgres_size(&domain, db, [size-only])
sub postgres_size
{
&require_postgres();
local $size;
local @tables;
eval {
# Make sure DBI errors don't cause a total failure
local $main::error_must_die = 1;
local $postgresql::force_nodbi = 1;
local $d = &postgresql::execute_sql($_[1], "select sum(relpages) from pg_class where relname not like 'pg_%'");
$size = $d->{'data'}->[0]->[0]*1024*2;
if (!$_[2]) {
@tables = &postgresql::list_tables($_[1], 1);
}
};
return ($size, scalar(@tables));
}
# check_postgres_database_clash(&domain, db)
# Returns 1 if some database name is already in use
sub check_postgres_database_clash
{
&require_postgres();
local @dblist = &postgresql::list_databases();
return 1 if (&indexof($_[1], @dblist) >= 0);
}
# create_postgres_database(&domain, db, &opts)
# Create one PostgreSQL database
sub create_postgres_database
{
&require_postgres();
if (!&check_postgres_database_clash($_[0], $_[1])) {
# Build and run creation command
&$first_print(&text('setup_postgresdb', $_[1]));
local $user = &postgres_user($_[0]);
local $sql = "create database ".&postgresql::quote_table($_[1]);
local $withs;
if (&postgresql::get_postgresql_version() >= 7) {
$withs .= " owner=".&postgres_uquote($user);
}
if ($_[2]->{'encoding'}) {
$withs .= " encoding ".&postgres_quote($_[2]->{'encoding'});
}
if ($withs) {
$sql .= " with".$withs;
}
&postgresql::execute_sql_logged($qconfig{'basedb'}, $sql);
}
else {
&$first_print(&text('setup_postgresdbimport', $_[1]));
}
# Make sure nobody else can access it
eval {
local $main::error_must_die = 1;
&postgresql::execute_sql_logged($qconfig{'basedb'},
"revoke all on database ".&postgres_uquote($_[1]).
" from public");
};
local @dbs = split(/\s+/, $_[0]->{'db_postgres'});
push(@dbs, $_[1]);
$_[0]->{'db_postgres'} = join(" ", @dbs);
&$second_print($text{'setup_done'});
return 1;
}
# grant_postgres_database(&domain, dbname)
# Alters the owner of a PostgreSQL database to some domain
sub grant_postgres_database
{
local ($d, $dbname) = @_;
&require_postgres();
if (&postgresql::get_postgresql_version() >= 8.0) {
local $user = &postgres_user($d);
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter database ".&postgres_uquote($dbname).
" owner to ".&postgres_uquote($user));
}
}
# delete_postgres_database(&domain, dbname, ...)
# Delete one PostgreSQL database
sub delete_postgres_database
{
&require_postgres();
local @dblist = &postgresql::list_databases();
&$first_print(&text('delete_postgresdb', join(", ", @_[1..$#_])));
local @dbs = split(/\s+/, $_[0]->{'db_postgres'});
local @missing;
foreach my $db (@_[1..$#_]) {
if (&indexof($db, @dblist) >= 0) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"drop database ".&postgresql::quote_table($db));
if (defined(&postgresql::delete_database_backup_job)) {
&postgresql::delete_database_backup_job($db);
}
}
else {
push(@missing, $db);
}
@dbs = grep { $_ ne $db } @dbs;
}
$_[0]->{'db_postgres'} = join(" ", @dbs);
if (@missing) {
&$second_print(&text('delete_mysqlmissing', join(", ", @missing)));
}
else {
&$second_print($text{'setup_done'});
}
}
# revoke_postgres_database(&domain, dbname)
# Takes away a domain's access to a PostgreSQL database, by setting the owner
# back to postgres
sub revoke_postgres_database
{
local ($d, $dbname) = @_;
&require_postgres();
if (&postgresql::get_postgresql_version() >= 8.0 &&
&postgres_user_exists("postgres")) {
&postgresql::execute_sql_logged($qconfig{'basedb'},
"alter database ".&postgres_uquote($dbname).
" owner to ".&postgres_uquote(postgres));
}
}
# list_postgres_database_users(&domain, db)
# Returns a list of PostgreSQL users and passwords who can access some database
sub list_all_postgres_users
{
local ($d, $db) = @_;
return ( ); # XXX not possible
}
# list_all_postgres_users()
# Returns a list of all PostgreSQL users
sub list_postgres_database_users
{
local ($d, $db) = @_;
return ( ); # XXX not possible
}
# create_postgres_database_user(&domain, &dbs, username, password)
sub create_postgres_database_user
{
}
# list_postgres_tables(database)
# Returns a list of tables in the specified database
sub list_postgres_tables
{
&require_postgres();
return &postgresql::list_tables($_[0], 1);
}
# get_database_host_postgres()
# Returns the hostname of the server on which PostgreSQL is actually running
sub get_database_host_postgres
{
&require_postgres();
return $postgres::config{'host'} || 'localhost';
}
# sysinfo_postgres()
# Returns the PostgreSQL version
sub sysinfo_postgres
{
&require_postgres();
local @rv;
eval {
# Protect against DBI errors
local $main::error_must_die = 1;
local $postgresql::force_nodbi = 1;
local $ver = &postgresql::get_postgresql_version();
@rv = ( [ $text{'sysinfo_postgresql'}, $ver ] );
};
return @rv;
}
sub startstop_postgres
{
local ($typestatus) = @_;
&require_postgres();
return ( ) if (!&postgresql::is_postgresql_local());
local $r = defined($typestatus->{'postgresql'}) ?
$typestatus->{'postgresql'} == 1 :
&postgresql::is_postgresql_running();
local @links = ( { 'link' => '/postgresql/',
'desc' => $text{'index_pgmanage'},
'manage' => 1 } );
if ($r == 1) {
return ( { 'status' => 1,
'name' => $text{'index_pgname'},
'desc' => $text{'index_pgstop'},
'restartdesc' => $text{'index_pgrestart'},
'longdesc' => $text{'index_pgstopdesc'},
'links' => \@links } );
}
elsif ($r == 0) {
return ( { 'status' => 0,
'name' => $text{'index_pgname'},
'desc' => $text{'index_pgstart'},
'longdesc' => $text{'index_pgstartdesc'},
'links' => \@links } );
}
else {
return ( );
}
}
sub stop_service_postgres
{
&require_postgres();
local $rv = &postgresql::stop_postgresql();
sleep(5);
return $rv;
}
sub start_service_postgres
{
&require_postgres();
return &postgresql::start_postgresql();
}
# check_postgres_login(dbname, dbuser, dbpass)
# Tries to login to PostgreSQL with the given credentials, returning undef
# on failure
sub check_postgres_login
{
local ($dbname, $dbuser, $dbpass) = @_;
&require_postgres();
local $main::error_must_die = 1;
local $postgresql::postgres_login = $dbuser;
local $postgresql::postgres_pass = $dbpass;
eval { &postgresql::execute_sql($dbname, "select version()") };
local $err = $@;
if ($err) {
$err =~ s/\s+at\s+.*\sline//g;
return $err;
}
return undef;
}
# creation_form_postgres(&domain)
# Returns options for a new PostgreSQL database
sub creation_form_postgres
{
&require_postgres();
if (&postgresql::get_postgresql_version() >= 7.4) {
local $tmpl = &get_template($_[0]->{'template'});
local $cs = $tmpl->{'postgres_encoding'};
$cs = "" if ($cs eq "none");
return &ui_table_row($text{'database_encoding'},
&ui_select("postgres_encoding", $cs,
[ [ undef, "<$text{'default'}>" ],
&list_postgres_encodings() ]));
}
}
# creation_parse_postgres(&domain, &in)
# Parse the form generated by creation_form_postgres, and return a structure
# for passing to create_postgres_database
sub creation_parse_postgres
{
local ($d, $in) = @_;
local $opts = { 'encoding' => $in->{'postgres_encoding'} };
return $opts;
}
# list_postgres_encodings()
# Returns a list of available PostgreSQL encodings for new DBs, each of which
# is a 2-element hash ref containing a code and description
sub list_postgres_encodings
{
if (!scalar(@postgres_encodings_cache)) {
@postgres_encodings_cache = ( );
&open_readfile(ENCS, "$module_root_directory/postgres-encodings");
while(<ENCS>) {
s/\r|\n//g;
local @w = split(/\t/, $_);
if ($w[2] !~ /\Q$w[0]\E/i) {
$w[2] .= " ($w[0])";
}
push(@postgres_encodings_cache, [ $w[0], $w[2] ]);
}
close(ENCS);
@postgres_encodings_cache = sort { lc($a->[1]) cmp lc($b->[1]) }
@postgres_encodings_cache;
}
return @postgres_encodings_cache;
}
# show_template_postgres(&tmpl)
# Outputs HTML for editing PostgreSQL related template options
sub show_template_postgres
{
local ($tmpl) = @_;
&require_postgres();
# Default encoding
print &ui_table_row(&hlink($text{'tmpl_postgres_encoding'},
"template_postgres_encoding"),
&ui_select("postgres_encoding", $tmpl->{'postgres_encoding'},
[ $tmpl->{'default'} ? ( ) :
( [ "", "<$text{'tmpl_postgres_encodingdef'}>" ] ),
[ "none", "<$text{'tmpl_postgres_encodingnone'}>" ],
&list_postgres_encodings() ]));
}
# parse_template_postgres(&tmpl)
# Updates PostgreSQL related template options from %in
sub parse_template_postgres
{
local ($tmpl) = @_;
&require_postgres();
$tmpl->{'postgres_encoding'} = $in{'postgres_encoding'};
}
# default_postgres_creation_opts(&domain)
# Returns default options for a new PostgreSQL DB in some domain
sub default_postgres_creation_opts
{
local ($d) = @_;
local $tmpl = &get_template($d->{'template'});
local %opts;
if ($tmpl->{'postgres_encoding'} &&
$tmpl->{'postgres_encoding'} ne 'none') {
$opts{'encoding'} = $tmpl->{'postgres_encoding'};
}
return \%opts;
}
# get_postgres_creation_opts(&domain, db)
# Returns a hash ref of database creation options for an existing DB
sub get_postgres_creation_opts
{
local ($d, $dbname) = @_;
&require_postgres();
local $opts = { };
eval {
local $main::error_must_die = 1;
local $rv = &postgresql::execute_sql($qconfig{'basedb'}, "\\l");
foreach my $r (@{$rv->{'data'}}) {
if ($r->[0] eq $dbname) {
$opts->{'encoding'} = $r->[2];
}
}
};
return $opts;
}
# list_all_postgres_databases([&domain])
# Returns the names of all known databases
sub list_all_postgres_databases
{
&require_postgres();
return &postgresql::list_databases();
}
# postgres_password_synced(&domain)
# Returns 1 if a domain's MySQL password will change along with its admin pass
sub postgres_password_synced
{
my ($d) = @_;
if ($d->{'parent'}) {
my $parent = &get_domain($d->{'parent'});
return &postgres_password_synced($parent);
}
if ($d->{'hashpass'}) {
# Hashed passwords are being used
return 0;
}
if ($d->{'postgres_pass'}) {
# Separate password set
return 0;
}
my $tmpl = &get_template($d->{'template'});
if ($tmpl->{'mysql_nopass'}) {
# Syncing disabled in the template
return 0;
}
return 1;
}
$done_feature_script{'postgres'} = 1;
1;
y~or5J={Eeu磝Qk ᯘG{?+]ן?wM3X^歌>{7پK>on\jy Rg/=fOroNVv~Y+ NGuÝHWyw[eQʨSb> >}Gmx[o[<{Ϯ_qFvM IENDB`