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 >> /usr/libexec/webmin/virtual-server/ |
files >> //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`